mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-03 05:10:03 +02:00
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;
|
uint8_t *output_buf;
|
||||||
int output_buf_size;
|
int output_buf_size;
|
||||||
|
|
||||||
|
int input_zerocopy;
|
||||||
} OMXCodecContext;
|
} OMXCodecContext;
|
||||||
|
|
||||||
static void append_buffer(pthread_mutex_t *mutex, pthread_cond_t *cond,
|
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)
|
OMX_BUFFERHEADERTYPE *buffer)
|
||||||
{
|
{
|
||||||
OMXCodecContext *s = app_data;
|
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,
|
append_buffer(&s->input_mutex, &s->input_cond,
|
||||||
&s->num_free_in_buffers, s->free_in_buffers, buffer);
|
&s->num_free_in_buffers, s->free_in_buffers, buffer);
|
||||||
return OMX_ErrorNone;
|
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);
|
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)
|
if (!s->in_buffer_headers || !s->free_in_buffers || !s->out_buffer_headers || !s->done_out_buffers)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
for (i = 0; i < s->num_in_buffers && err == OMX_ErrorNone; i++)
|
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);
|
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);
|
CHECK(err);
|
||||||
s->num_in_buffers = i;
|
s->num_in_buffers = i;
|
||||||
for (i = 0; i < s->num_out_buffers && err == OMX_ErrorNone; 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++) {
|
for (i = 0; i < s->num_in_buffers; i++) {
|
||||||
OMX_BUFFERHEADERTYPE *buffer = get_buffer(&s->input_mutex, &s->input_cond,
|
OMX_BUFFERHEADERTYPE *buffer = get_buffer(&s->input_mutex, &s->input_cond,
|
||||||
&s->num_free_in_buffers, s->free_in_buffers, 1);
|
&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);
|
OMX_FreeBuffer(s->handle, s->in_port, buffer);
|
||||||
}
|
}
|
||||||
for (i = 0; i < s->num_out_buffers; i++) {
|
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_BUFFERHEADERTYPE *buffer;
|
||||||
OMX_ERRORTYPE err;
|
OMX_ERRORTYPE err;
|
||||||
|
|
||||||
|
#if CONFIG_OMX_RPI
|
||||||
|
s->input_zerocopy = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
s->omx_context = omx_init(avctx, s->libname, s->libprefix);
|
s->omx_context = omx_init(avctx, s->libname, s->libprefix);
|
||||||
if (!s->omx_context)
|
if (!s->omx_context)
|
||||||
return AVERROR_ENCODER_NOT_FOUND;
|
return AVERROR_ENCODER_NOT_FOUND;
|
||||||
@ -706,10 +729,56 @@ static int omx_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
|
|||||||
if (frame) {
|
if (frame) {
|
||||||
uint8_t *dst[4];
|
uint8_t *dst[4];
|
||||||
int linesize[4];
|
int linesize[4];
|
||||||
|
int need_copy;
|
||||||
buffer = get_buffer(&s->input_mutex, &s->input_cond,
|
buffer = get_buffer(&s->input_mutex, &s->input_cond,
|
||||||
&s->num_free_in_buffers, s->free_in_buffers, 1);
|
&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);
|
buffer->nFilledLen = av_image_fill_arrays(dst, linesize, buffer->pBuffer, avctx->pix_fmt, s->stride, s->plane_size, 1);
|
||||||
|
|
||||||
|
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);
|
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->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
|
||||||
buffer->nOffset = 0;
|
buffer->nOffset = 0;
|
||||||
@ -808,9 +877,11 @@ static av_cold int omx_encode_end(AVCodecContext *avctx)
|
|||||||
|
|
||||||
#define OFFSET(x) offsetof(OMXCodecContext, x)
|
#define OFFSET(x) offsetof(OMXCodecContext, x)
|
||||||
#define VDE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM
|
#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[] = {
|
static const AVOption options[] = {
|
||||||
{ "omx_libname", "OpenMAX library name", OFFSET(libname), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VDE },
|
{ "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 },
|
{ "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 }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
#define LIBAVCODEC_VERSION_MAJOR 57
|
#define LIBAVCODEC_VERSION_MAJOR 57
|
||||||
#define LIBAVCODEC_VERSION_MINOR 41
|
#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, \
|
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||||
LIBAVCODEC_VERSION_MINOR, \
|
LIBAVCODEC_VERSION_MINOR, \
|
||||||
|
Loading…
Reference in New Issue
Block a user