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