diff options
author | Martin Storsjö <martin@martin.st> | 2017-02-07 00:25:19 +0200 |
---|---|---|
committer | Martin Storsjö <martin@martin.st> | 2017-02-08 11:50:57 +0200 |
commit | 57ec83e4246b21c2f0c068b9151d806737d4497f (patch) | |
tree | f73eb6664d337fa20167b65a6c04bf1be52d6cfb | |
parent | dad7a9c7c0ae8ebc56f2e3a24e6fa4da5c2cd491 (diff) | |
download | ffmpeg-57ec83e4246b21c2f0c068b9151d806737d4497f.tar.gz |
omx: Use the EOS flag to handle flushing at the end
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ö <martin@martin.st>
-rw-r--r-- | libavcodec/omx.c | 30 |
1 files 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 |