Merge commit '1bb56abb9b37bd208a66164339c92cad59b1087b'
* commit '1bb56abb9b37bd208a66164339c92cad59b1087b': omx: Add support for zerocopy input of frames Merged-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
This commit is contained in:
commit
ec1d8abfb9
@ -224,6 +224,8 @@ typedef struct OMXCodecContext {
|
||||
|
||||
uint8_t *output_buf;
|
||||
int output_buf_size;
|
||||
|
||||
int input_zerocopy;
|
||||
} OMXCodecContext;
|
||||
|
||||
static void append_buffer(pthread_mutex_t *mutex, pthread_cond_t *cond,
|
||||
@ -303,6 +305,15 @@ static OMX_ERRORTYPE empty_buffer_done(OMX_HANDLETYPE component, OMX_PTR app_dat
|
||||
OMX_BUFFERHEADERTYPE *buffer)
|
||||
{
|
||||
OMXCodecContext *s = app_data;
|
||||
if (s->input_zerocopy) {
|
||||
if (buffer->pAppPrivate) {
|
||||
if (buffer->pOutputPortPrivate)
|
||||
av_free(buffer->pAppPrivate);
|
||||
else
|
||||
av_frame_free((AVFrame**)&buffer->pAppPrivate);
|
||||
buffer->pAppPrivate = NULL;
|
||||
}
|
||||
}
|
||||
append_buffer(&s->input_mutex, &s->input_cond,
|
||||
&s->num_free_in_buffers, s->free_in_buffers, buffer);
|
||||
return OMX_ErrorNone;
|
||||
@ -525,8 +536,14 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role)
|
||||
s->done_out_buffers = av_mallocz(sizeof(OMX_BUFFERHEADERTYPE*) * s->num_out_buffers);
|
||||
if (!s->in_buffer_headers || !s->free_in_buffers || !s->out_buffer_headers || !s->done_out_buffers)
|
||||
return AVERROR(ENOMEM);
|
||||
for (i = 0; i < s->num_in_buffers && err == OMX_ErrorNone; i++)
|
||||
err = OMX_AllocateBuffer(s->handle, &s->in_buffer_headers[i], s->in_port, s, in_port_params.nBufferSize);
|
||||
for (i = 0; i < s->num_in_buffers && err == OMX_ErrorNone; i++) {
|
||||
if (s->input_zerocopy)
|
||||
err = OMX_UseBuffer(s->handle, &s->in_buffer_headers[i], s->in_port, s, in_port_params.nBufferSize, NULL);
|
||||
else
|
||||
err = OMX_AllocateBuffer(s->handle, &s->in_buffer_headers[i], s->in_port, s, in_port_params.nBufferSize);
|
||||
if (err == OMX_ErrorNone)
|
||||
s->in_buffer_headers[i]->pAppPrivate = s->in_buffer_headers[i]->pOutputPortPrivate = NULL;
|
||||
}
|
||||
CHECK(err);
|
||||
s->num_in_buffers = i;
|
||||
for (i = 0; i < s->num_out_buffers && err == OMX_ErrorNone; i++)
|
||||
@ -571,6 +588,8 @@ static av_cold void cleanup(OMXCodecContext *s)
|
||||
for (i = 0; i < s->num_in_buffers; i++) {
|
||||
OMX_BUFFERHEADERTYPE *buffer = get_buffer(&s->input_mutex, &s->input_cond,
|
||||
&s->num_free_in_buffers, s->free_in_buffers, 1);
|
||||
if (s->input_zerocopy)
|
||||
buffer->pBuffer = NULL;
|
||||
OMX_FreeBuffer(s->handle, s->in_port, buffer);
|
||||
}
|
||||
for (i = 0; i < s->num_out_buffers; i++) {
|
||||
@ -611,6 +630,10 @@ static av_cold int omx_encode_init(AVCodecContext *avctx)
|
||||
OMX_BUFFERHEADERTYPE *buffer;
|
||||
OMX_ERRORTYPE err;
|
||||
|
||||
#if CONFIG_OMX_RPI
|
||||
s->input_zerocopy = 1;
|
||||
#endif
|
||||
|
||||
s->omx_context = omx_init(avctx, s->libname, s->libprefix);
|
||||
if (!s->omx_context)
|
||||
return AVERROR_ENCODER_NOT_FOUND;
|
||||
@ -706,11 +729,57 @@ static int omx_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
|
||||
if (frame) {
|
||||
uint8_t *dst[4];
|
||||
int linesize[4];
|
||||
int need_copy;
|
||||
buffer = get_buffer(&s->input_mutex, &s->input_cond,
|
||||
&s->num_free_in_buffers, s->free_in_buffers, 1);
|
||||
|
||||
buffer->nFilledLen = av_image_fill_arrays(dst, linesize, buffer->pBuffer, avctx->pix_fmt, s->stride, s->plane_size, 1);
|
||||
av_image_copy(dst, linesize, (const uint8_t**) frame->data, frame->linesize, avctx->pix_fmt, avctx->width, avctx->height);
|
||||
|
||||
if (s->input_zerocopy) {
|
||||
uint8_t *src[4] = { NULL };
|
||||
int src_linesize[4];
|
||||
av_image_fill_arrays(src, src_linesize, frame->data[0], avctx->pix_fmt, s->stride, s->plane_size, 1);
|
||||
if (frame->linesize[0] == src_linesize[0] &&
|
||||
frame->linesize[1] == src_linesize[1] &&
|
||||
frame->linesize[2] == src_linesize[2] &&
|
||||
frame->data[1] == src[1] &&
|
||||
frame->data[2] == src[2]) {
|
||||
// If the input frame happens to have all planes stored contiguously,
|
||||
// with the right strides, just clone the frame and set the OMX
|
||||
// buffer header to point to it
|
||||
AVFrame *local = av_frame_clone(frame);
|
||||
if (!local) {
|
||||
// Return the buffer to the queue so it's not lost
|
||||
append_buffer(&s->input_mutex, &s->input_cond, &s->num_free_in_buffers, s->free_in_buffers, buffer);
|
||||
return AVERROR(ENOMEM);
|
||||
} else {
|
||||
buffer->pAppPrivate = local;
|
||||
buffer->pOutputPortPrivate = NULL;
|
||||
buffer->pBuffer = local->data[0];
|
||||
need_copy = 0;
|
||||
}
|
||||
} else {
|
||||
// If not, we need to allocate a new buffer with the right
|
||||
// size and copy the input frame into it.
|
||||
uint8_t *buf = av_malloc(av_image_get_buffer_size(avctx->pix_fmt, s->stride, s->plane_size, 1));
|
||||
if (!buf) {
|
||||
// Return the buffer to the queue so it's not lost
|
||||
append_buffer(&s->input_mutex, &s->input_cond, &s->num_free_in_buffers, s->free_in_buffers, buffer);
|
||||
return AVERROR(ENOMEM);
|
||||
} else {
|
||||
buffer->pAppPrivate = buf;
|
||||
// Mark that pAppPrivate is an av_malloc'ed buffer, not an AVFrame
|
||||
buffer->pOutputPortPrivate = (void*) 1;
|
||||
buffer->pBuffer = buf;
|
||||
need_copy = 1;
|
||||
buffer->nFilledLen = av_image_fill_arrays(dst, linesize, buffer->pBuffer, avctx->pix_fmt, s->stride, s->plane_size, 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
need_copy = 1;
|
||||
}
|
||||
if (need_copy)
|
||||
av_image_copy(dst, linesize, (const uint8_t**) frame->data, frame->linesize, avctx->pix_fmt, avctx->width, avctx->height);
|
||||
buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
|
||||
buffer->nOffset = 0;
|
||||
// Convert the timestamps to microseconds; some encoders can ignore
|
||||
@ -808,9 +877,11 @@ static av_cold int omx_encode_end(AVCodecContext *avctx)
|
||||
|
||||
#define OFFSET(x) offsetof(OMXCodecContext, x)
|
||||
#define VDE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM
|
||||
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
|
||||
static const AVOption options[] = {
|
||||
{ "omx_libname", "OpenMAX library name", OFFSET(libname), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VDE },
|
||||
{ "omx_libprefix", "OpenMAX library prefix", OFFSET(libprefix), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VDE },
|
||||
{ "zerocopy", "Try to avoid copying input frames if possible", OFFSET(input_zerocopy), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
#define LIBAVCODEC_VERSION_MAJOR 57
|
||||
#define LIBAVCODEC_VERSION_MINOR 41
|
||||
#define LIBAVCODEC_VERSION_MICRO 101
|
||||
#define LIBAVCODEC_VERSION_MICRO 102
|
||||
|
||||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||
LIBAVCODEC_VERSION_MINOR, \
|
||||
|
Loading…
Reference in New Issue
Block a user