ffmpeg: delay processing of subtitles before filters are initialized
If a subtitle packet came before the first video frame could be fully decoded, the subtitle packet would get discarded. This puts the subtitle into a queue instead, and processes it once the attached filter graph is initialized.
This commit is contained in:
		
							parent
							
								
									736f4af4fe
								
							
						
					
					
						commit
						7dd44cde2a
					
				
							
								
								
									
										31
									
								
								ffmpeg.c
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								ffmpeg.c
									
									
									
									
									
								
							@ -226,7 +226,7 @@ static void sub2video_push_ref(InputStream *ist, int64_t pts)
 | 
			
		||||
                                     AV_BUFFERSRC_FLAG_PUSH);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sub2video_update(InputStream *ist, AVSubtitle *sub)
 | 
			
		||||
void sub2video_update(InputStream *ist, AVSubtitle *sub)
 | 
			
		||||
{
 | 
			
		||||
    AVFrame *frame = ist->sub2video.frame;
 | 
			
		||||
    int8_t *dst;
 | 
			
		||||
@ -480,6 +480,15 @@ static void ffmpeg_cleanup(int ret)
 | 
			
		||||
                av_frame_free(&frame);
 | 
			
		||||
            }
 | 
			
		||||
            av_fifo_free(fg->inputs[j]->frame_queue);
 | 
			
		||||
            if (fg->inputs[j]->ist->sub2video.sub_queue) {
 | 
			
		||||
                while (av_fifo_size(fg->inputs[j]->ist->sub2video.sub_queue)) {
 | 
			
		||||
                    AVSubtitle sub;
 | 
			
		||||
                    av_fifo_generic_read(fg->inputs[j]->ist->sub2video.sub_queue,
 | 
			
		||||
                                         &sub, sizeof(sub), NULL);
 | 
			
		||||
                    avsubtitle_free(&sub);
 | 
			
		||||
                }
 | 
			
		||||
                av_fifo_free(fg->inputs[j]->ist->sub2video.sub_queue);
 | 
			
		||||
            }
 | 
			
		||||
            av_buffer_unref(&fg->inputs[j]->hw_frames_ctx);
 | 
			
		||||
            av_freep(&fg->inputs[j]->name);
 | 
			
		||||
            av_freep(&fg->inputs[j]);
 | 
			
		||||
@ -2468,6 +2477,7 @@ fail:
 | 
			
		||||
static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
 | 
			
		||||
{
 | 
			
		||||
    AVSubtitle subtitle;
 | 
			
		||||
    int free_sub = 1;
 | 
			
		||||
    int i, ret = avcodec_decode_subtitle2(ist->dec_ctx,
 | 
			
		||||
                                          &subtitle, got_output, pkt);
 | 
			
		||||
 | 
			
		||||
@ -2502,7 +2512,21 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
 | 
			
		||||
    if (!*got_output)
 | 
			
		||||
        return ret;
 | 
			
		||||
 | 
			
		||||
    sub2video_update(ist, &subtitle);
 | 
			
		||||
    if (ist->sub2video.frame) {
 | 
			
		||||
        sub2video_update(ist, &subtitle);
 | 
			
		||||
    } else if (ist->nb_filters) {
 | 
			
		||||
        if (!ist->sub2video.sub_queue)
 | 
			
		||||
            ist->sub2video.sub_queue = av_fifo_alloc(8 * sizeof(AVSubtitle));
 | 
			
		||||
        if (!ist->sub2video.sub_queue)
 | 
			
		||||
            exit_program(1);
 | 
			
		||||
        if (!av_fifo_space(ist->sub2video.sub_queue)) {
 | 
			
		||||
            ret = av_fifo_realloc2(ist->sub2video.sub_queue, 2 * av_fifo_size(ist->sub2video.sub_queue));
 | 
			
		||||
            if (ret < 0)
 | 
			
		||||
                exit_program(1);
 | 
			
		||||
        }
 | 
			
		||||
        av_fifo_generic_write(ist->sub2video.sub_queue, &subtitle, sizeof(subtitle), NULL);
 | 
			
		||||
        free_sub = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!subtitle.num_rects)
 | 
			
		||||
        goto out;
 | 
			
		||||
@ -2520,7 +2544,8 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
    avsubtitle_free(&subtitle);
 | 
			
		||||
    if (free_sub)
 | 
			
		||||
        avsubtitle_free(&subtitle);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								ffmpeg.h
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								ffmpeg.h
									
									
									
									
									
								
							@ -337,6 +337,7 @@ typedef struct InputStream {
 | 
			
		||||
    struct sub2video {
 | 
			
		||||
        int64_t last_pts;
 | 
			
		||||
        int64_t end_pts;
 | 
			
		||||
        AVFifoBuffer *sub_queue;    ///< queue of AVSubtitle* before filter init
 | 
			
		||||
        AVFrame *frame;
 | 
			
		||||
        int w, h;
 | 
			
		||||
    } sub2video;
 | 
			
		||||
@ -636,6 +637,8 @@ int filtergraph_is_simple(FilterGraph *fg);
 | 
			
		||||
int init_simple_filtergraph(InputStream *ist, OutputStream *ost);
 | 
			
		||||
int init_complex_filtergraph(FilterGraph *fg);
 | 
			
		||||
 | 
			
		||||
void sub2video_update(InputStream *ist, AVSubtitle *sub);
 | 
			
		||||
 | 
			
		||||
int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame);
 | 
			
		||||
 | 
			
		||||
int ffmpeg_parse_options(int argc, char **argv);
 | 
			
		||||
 | 
			
		||||
@ -1137,6 +1137,19 @@ int configure_filtergraph(FilterGraph *fg)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* process queued up subtitle packets */
 | 
			
		||||
    for (i = 0; i < fg->nb_inputs; i++) {
 | 
			
		||||
        InputStream *ist = fg->inputs[i]->ist;
 | 
			
		||||
        if (ist->sub2video.sub_queue && ist->sub2video.frame) {
 | 
			
		||||
            while (av_fifo_size(ist->sub2video.sub_queue)) {
 | 
			
		||||
                AVSubtitle tmp;
 | 
			
		||||
                av_fifo_generic_read(ist->sub2video.sub_queue, &tmp, sizeof(tmp), NULL);
 | 
			
		||||
                sub2video_update(ist, &tmp);
 | 
			
		||||
                avsubtitle_free(&tmp);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user