1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-08-10 06:10:52 +02:00

avformat/fifo: Check for keyframe video type before stop dropping

The current behavior when using restart_with_keyframe is that it will
recover if it also encounters any audio packet, as they are flagged as a
keyframe.

The expectation is that packets are dropped until the next _video_
keyframe.

To fix that, check if exists a video stream, if it exists check the
packet stream codec type, only letting it recover when it is a video
one. If there is no video stream, resume to the original behavior, not
checking the codec type.

Fixes ticket: #11467

Signed-off-by: Arthur Grillo <arthurgrillo@riseup.net>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
Arthur Grillo
2025-04-10 19:59:15 -03:00
committed by Michael Niedermayer
parent 50910c32c5
commit 2fedb29780

View File

@@ -106,6 +106,9 @@ typedef struct FifoThreadContext {
uint8_t header_written;
int64_t last_received_dts;
/* If > 0 at least one of the streams is a video stream */
uint8_t has_video_stream;
} FifoThreadContext;
typedef enum FifoMessageType {
@@ -185,14 +188,26 @@ static int fifo_thread_write_packet(FifoThreadContext *ctx, AVPacket *pkt)
AVRational src_tb, dst_tb;
int ret, s_idx;
int64_t orig_pts, orig_dts, orig_duration;
enum AVMediaType stream_codec_type = avf->streams[pkt->stream_index]->codecpar->codec_type;
if (fifo->timeshift && pkt->dts != AV_NOPTS_VALUE)
atomic_fetch_sub_explicit(&fifo->queue_duration, next_duration(avf, pkt, &ctx->last_received_dts), memory_order_relaxed);
if (ctx->drop_until_keyframe) {
if (pkt->flags & AV_PKT_FLAG_KEY) {
ctx->drop_until_keyframe = 0;
av_log(avf, AV_LOG_VERBOSE, "Keyframe received, recovering...\n");
if (!ctx->has_video_stream) {
ctx->drop_until_keyframe = 0;
av_log(avf, AV_LOG_VERBOSE, "Keyframe received, recovering...\n");
} else {
if (stream_codec_type == AVMEDIA_TYPE_VIDEO) {
ctx->drop_until_keyframe = 0;
av_log(avf, AV_LOG_VERBOSE, "Video keyframe received, recovering...\n");
} else {
av_log(avf, AV_LOG_VERBOSE, "Dropping non-video keyframe\n");
av_packet_unref(pkt);
return 0;
}
}
} else {
av_log(avf, AV_LOG_VERBOSE, "Dropping non-keyframe packet\n");
av_packet_unref(pkt);
@@ -425,7 +440,7 @@ static void *fifo_consumer_thread(void *data)
FifoContext *fifo = avf->priv_data;
AVThreadMessageQueue *queue = fifo->queue;
FifoMessage msg = {fifo->timeshift ? FIFO_NOOP : FIFO_WRITE_HEADER, {0}};
int ret;
int ret, i;
FifoThreadContext fifo_thread_ctx;
memset(&fifo_thread_ctx, 0, sizeof(FifoThreadContext));
@@ -434,6 +449,13 @@ static void *fifo_consumer_thread(void *data)
ff_thread_setname("fifo-consumer");
for (i = 0; i < avf->nb_streams; i++) {
if (avf->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
fifo_thread_ctx.has_video_stream = 1;
break;
}
}
while (1) {
uint8_t just_flushed = 0;