diff --git a/ffmpeg/decoder.c b/ffmpeg/decoder.c index 8fd0fa3dd3..c0de58cf54 100755 --- a/ffmpeg/decoder.c +++ b/ffmpeg/decoder.c @@ -22,12 +22,12 @@ static int lpms_receive_frame(struct input_ctx *ictx, AVCodecContext *dec, AVFra return ret; } -static int send_first_pkt(struct input_ctx *ictx) +static int send_flush_pkt(struct input_ctx *ictx) { if (ictx->flushed) return 0; - if (!ictx->first_pkt) return lpms_ERR_INPUT_NOKF; + if (!ictx->flush_pkt) return lpms_ERR_INPUT_NOKF; - int ret = avcodec_send_packet(ictx->vc, ictx->first_pkt); + int ret = avcodec_send_packet(ictx->vc, ictx->flush_pkt); ictx->sentinel_count++; if (ret < 0) { LPMS_ERR(packet_cleanup, "Error sending flush packet"); @@ -68,9 +68,14 @@ int decode_in(struct input_ctx *ictx, AVPacket *pkt, AVFrame *frame, int *stream return 0; } - if (!ictx->first_pkt && pkt->flags & AV_PKT_FLAG_KEY && decoder == ictx->vc) { - ictx->first_pkt = av_packet_clone(pkt); - ictx->first_pkt->pts = -1; + // Set up flush packet. Do this every keyframe in case the underlying frame changes + if (pkt->flags & AV_PKT_FLAG_KEY && decoder == ictx->vc) { + if (!ictx->flush_pkt) ictx->flush_pkt = av_packet_clone(pkt); + else { + av_packet_unref(ictx->flush_pkt); + av_packet_ref(ictx->flush_pkt, pkt); + } + ictx->flush_pkt->pts = -1; } ret = lpms_send_packet(ictx, decoder, pkt); @@ -104,7 +109,7 @@ int flush_in(struct input_ctx *ictx, AVFrame *frame, int *stream_index) // TODO this is unnecessary for SW decoding! SW process should match audio if (ictx->vc && !ictx->flushed && ictx->pkt_diff > 0) { ictx->flushing = 1; - ret = send_first_pkt(ictx); + ret = send_flush_pkt(ictx); if (ret < 0) { ictx->flushed = 1; return ret; diff --git a/ffmpeg/decoder.h b/ffmpeg/decoder.h index 5b28d4dbe3..2dd85a5f25 100755 --- a/ffmpeg/decoder.h +++ b/ffmpeg/decoder.h @@ -20,7 +20,7 @@ struct input_ctx { char *xcoderParams; // Decoder flush - AVPacket *first_pkt; + AVPacket *flush_pkt; int flushed; int flushing; // The diff of `packets sent - frames recv` serves as an estimate of diff --git a/ffmpeg/transcoder.c b/ffmpeg/transcoder.c index da7caf3492..ce667b35c3 100755 --- a/ffmpeg/transcoder.c +++ b/ffmpeg/transcoder.c @@ -43,7 +43,7 @@ const int lpms_ERR_UNRECOVERABLE = FFERRTAG('U', 'N', 'R', 'V'); // MOVED TO decoder.[ch] // Decoder: For audio, we pay the price of closing and re-opening the decoder. -// For video, we cache the first packet we read (input_ctx.first_pkt). +// For video, we cache the last keyframe read (input_ctx.flush_pkt). // The pts is set to a sentinel value and fed to the decoder. Once we // receive all frames from the decoder OR have sent too many sentinel // pkts without receiving anything, then we know the decoder has been @@ -133,7 +133,7 @@ int transcode_shutdown(struct transcode_thread *h, int ret) ictx->flushing = 0; ictx->pkt_diff = 0; ictx->sentinel_count = 0; - if (ictx->first_pkt) av_packet_free(&ictx->first_pkt); + if (ictx->flush_pkt) av_packet_free(&ictx->flush_pkt); if (ictx->ac) avcodec_free_context(&ictx->ac); if (ictx->vc && (AV_HWDEVICE_TYPE_NONE == ictx->hw_type)) avcodec_free_context(&ictx->vc); for (int i = 0; i < nb_outputs; i++) {