From 57ec83e4246b21c2f0c068b9151d806737d4497f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 7 Feb 2017 00:25:19 +0200 Subject: [PATCH] omx: Use the EOS flag to handle flushing at the end MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids having to count the number of frames sent to the codec and the number of output packets received; instead just wait until the encoder returns a buffer with the EOS flag set. Signed-off-by: Martin Storsjö --- libavcodec/omx.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/libavcodec/omx.c b/libavcodec/omx.c index 05c874323c..f43e92ae88 100644 --- a/libavcodec/omx.c +++ b/libavcodec/omx.c @@ -220,7 +220,7 @@ typedef struct OMXCodecContext { int mutex_cond_inited; - int num_in_frames, num_out_frames; + int eos_sent, got_eos; uint8_t *output_buf; int output_buf_size; @@ -791,17 +791,35 @@ static int omx_encode_frame(AVCodecContext *avctx, AVPacket *pkt, av_log(avctx, AV_LOG_ERROR, "OMX_EmptyThisBuffer failed: %x\n", err); return AVERROR_UNKNOWN; } - s->num_in_frames++; + } else if (!s->eos_sent) { + buffer = get_buffer(&s->input_mutex, &s->input_cond, + &s->num_free_in_buffers, s->free_in_buffers, 1); + + buffer->nFilledLen = 0; + buffer->nFlags = OMX_BUFFERFLAG_EOS; + buffer->pAppPrivate = buffer->pOutputPortPrivate = NULL; + err = OMX_EmptyThisBuffer(s->handle, buffer); + if (err != OMX_ErrorNone) { + append_buffer(&s->input_mutex, &s->input_cond, &s->num_free_in_buffers, s->free_in_buffers, buffer); + av_log(avctx, AV_LOG_ERROR, "OMX_EmptyThisBuffer failed: %x\n", err); + return AVERROR_UNKNOWN; + } + s->eos_sent = 1; } - while (!*got_packet && ret == 0) { - // Only wait for output if flushing and not all frames have been output + while (!*got_packet && ret == 0 && !s->got_eos) { + // If not flushing, just poll the queue if there's finished packets. + // If flushing, do a blocking wait until we either get a completed + // packet, or get EOS. buffer = get_buffer(&s->output_mutex, &s->output_cond, &s->num_done_out_buffers, s->done_out_buffers, - !frame && s->num_out_frames < s->num_in_frames); + !frame); if (!buffer) break; + if (buffer->nFlags & OMX_BUFFERFLAG_EOS) + s->got_eos = 1; + if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG && avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { if ((ret = av_reallocp(&avctx->extradata, avctx->extradata_size + buffer->nFilledLen + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) { avctx->extradata_size = 0; @@ -811,8 +829,6 @@ static int omx_encode_frame(AVCodecContext *avctx, AVPacket *pkt, avctx->extradata_size += buffer->nFilledLen; memset(avctx->extradata + avctx->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); } else { - if (buffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME) - s->num_out_frames++; if (!(buffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME) || !pkt->data) { // If the output packet isn't preallocated, just concatenate everything in our // own buffer