From f9b34b8bf967e8e80df9bcb4a16556a9d4526484 Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Sun, 10 Mar 2013 11:51:02 +0100 Subject: [PATCH] ffmpeg: port sub2video to AVFrame. And re-enable the FATE test. --- ffmpeg.c | 44 ++++++++++++++++++++++++++++--------------- ffmpeg.h | 2 +- ffmpeg_filter.c | 16 +++------------- tests/fate/ffmpeg.mak | 2 +- 4 files changed, 34 insertions(+), 30 deletions(-) diff --git a/ffmpeg.c b/ffmpeg.c index 33d57833b4..6012a5c1de 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -168,7 +168,20 @@ static int restore_tty; This is a temporary solution until libavfilter gets real subtitles support. */ +static int sub2video_get_blank_frame(InputStream *ist) +{ + int ret; + AVFrame *frame = ist->sub2video.frame; + av_frame_unref(frame); + ist->sub2video.frame->width = ist->sub2video.w; + ist->sub2video.frame->height = ist->sub2video.h; + ist->sub2video.frame->format = AV_PIX_FMT_RGB32; + if ((ret = av_frame_get_buffer(frame, 32)) < 0) + return ret; + memset(frame->data[0], 0, frame->height * frame->linesize[0]); + return 0; +} static void sub2video_copy_rect(uint8_t *dst, int dst_linesize, int w, int h, AVSubtitleRect *r) @@ -201,28 +214,25 @@ static void sub2video_copy_rect(uint8_t *dst, int dst_linesize, int w, int h, static void sub2video_push_ref(InputStream *ist, int64_t pts) { - AVFilterBufferRef *ref = ist->sub2video.ref; + AVFrame *frame = ist->sub2video.frame; int i; - ist->sub2video.last_pts = ref->pts = pts; + av_assert1(frame->data[0]); + ist->sub2video.last_pts = frame->pts = pts; for (i = 0; i < ist->nb_filters; i++) - av_buffersrc_add_ref(ist->filters[i]->filter, - avfilter_ref_buffer(ref, ~0), - AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT | - AV_BUFFERSRC_FLAG_NO_COPY | - AV_BUFFERSRC_FLAG_PUSH); + av_buffersrc_write_frame(ist->filters[i]->filter, frame); } static void sub2video_update(InputStream *ist, AVSubtitle *sub) { int w = ist->sub2video.w, h = ist->sub2video.h; - AVFilterBufferRef *ref = ist->sub2video.ref; + AVFrame *frame = ist->sub2video.frame; int8_t *dst; int dst_linesize; int num_rects, i; int64_t pts, end_pts; - if (!ref) + if (!frame) return; if (sub) { pts = av_rescale_q(sub->pts + sub->start_display_time * 1000, @@ -235,9 +245,13 @@ static void sub2video_update(InputStream *ist, AVSubtitle *sub) end_pts = INT64_MAX; num_rects = 0; } - dst = ref->data [0]; - dst_linesize = ref->linesize[0]; - memset(dst, 0, h * dst_linesize); + if (sub2video_get_blank_frame(ist) < 0) { + av_log(ist->st->codec, AV_LOG_ERROR, + "Impossible to get a blank canvas.\n"); + return; + } + dst = frame->data [0]; + dst_linesize = frame->linesize[0]; for (i = 0; i < num_rects; i++) sub2video_copy_rect(dst, dst_linesize, w, h, sub->rects[i]); sub2video_push_ref(ist, pts); @@ -256,7 +270,7 @@ static void sub2video_heartbeat(InputStream *ist, int64_t pts) (possibly overlay) is desperately waiting for a subtitle frame. */ for (i = 0; i < infile->nb_streams; i++) { InputStream *ist2 = input_streams[infile->ist_index + i]; - if (!ist2->sub2video.ref) + if (!ist2->sub2video.frame) continue; /* subtitles seem to be usually muxed ahead of other streams; if not, substracting a larger time here is necessary */ @@ -264,7 +278,7 @@ static void sub2video_heartbeat(InputStream *ist, int64_t pts) /* do not send the heartbeat frame if the subtitle is already ahead */ if (pts2 <= ist2->sub2video.last_pts) continue; - if (pts2 >= ist2->sub2video.end_pts) + if (pts2 >= ist2->sub2video.end_pts || !ist2->sub2video.frame->data[0]) sub2video_update(ist2, NULL); for (j = 0, nb_reqs = 0; j < ist2->nb_filters; j++) nb_reqs += av_buffersrc_get_nb_failed_requests(ist2->filters[j]->filter); @@ -466,7 +480,7 @@ static void exit_program(void) av_dict_free(&input_streams[i]->opts); free_buffer_pool(&input_streams[i]->buffer_pool); avsubtitle_free(&input_streams[i]->prev_sub.subtitle); - avfilter_unref_bufferp(&input_streams[i]->sub2video.ref); + avcodec_free_frame(&input_streams[i]->sub2video.frame); av_freep(&input_streams[i]->filters); av_freep(&input_streams[i]); } diff --git a/ffmpeg.h b/ffmpeg.h index d7046fd1e3..a04913e793 100644 --- a/ffmpeg.h +++ b/ffmpeg.h @@ -255,7 +255,7 @@ typedef struct InputStream { struct sub2video { int64_t last_pts; int64_t end_pts; - AVFilterBufferRef *ref; + AVFrame *frame; int w, h; } sub2video; diff --git a/ffmpeg_filter.c b/ffmpeg_filter.c index bdf43638ae..1c30961228 100644 --- a/ffmpeg_filter.c +++ b/ffmpeg_filter.c @@ -501,9 +501,7 @@ int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOu static int sub2video_prepare(InputStream *ist) { AVFormatContext *avf = input_files[ist->file_index]->ctx; - int i, ret, w, h; - uint8_t *image[4]; - int linesize[4]; + int i, w, h; /* Compute the size of the canvas for the subtitles stream. If the subtitles codec has set a size, use it. Otherwise use the @@ -530,17 +528,9 @@ static int sub2video_prepare(InputStream *ist) palettes for all rectangles are identical or compatible */ ist->resample_pix_fmt = ist->st->codec->pix_fmt = AV_PIX_FMT_RGB32; - ret = av_image_alloc(image, linesize, w, h, AV_PIX_FMT_RGB32, 32); - if (ret < 0) - return ret; - memset(image[0], 0, h * linesize[0]); - ist->sub2video.ref = avfilter_get_video_buffer_ref_from_arrays( - image, linesize, AV_PERM_READ | AV_PERM_PRESERVE, - w, h, AV_PIX_FMT_RGB32); - if (!ist->sub2video.ref) { - av_free(image[0]); + ist->sub2video.frame = av_frame_alloc(); + if (!ist->sub2video.frame) return AVERROR(ENOMEM); - } return 0; } diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index a39b0135a2..cc0e22add3 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -22,7 +22,7 @@ fate-force_key_frames: CMD = enc_dec \ avi "-c mpeg4 -g 240 -qscale 10 -force_key_frames 0.5,0:00:01.5" \ framecrc "" "" "-skip_frame nokey" -#FATE_SAMPLES_FFMPEG-$(call ALLYES, VOBSUB_DEMUXER DVDSUB_DECODER AVFILTER OVERLAY_FILTER DVDSUB_ENCODER) += fate-sub2video +FATE_SAMPLES_FFMPEG-$(call ALLYES, VOBSUB_DEMUXER DVDSUB_DECODER AVFILTER OVERLAY_FILTER DVDSUB_ENCODER) += fate-sub2video fate-sub2video: tests/data/vsynth2.yuv fate-sub2video: CMD = framecrc \ -f rawvideo -r 5 -s 352x288 -pix_fmt yuv420p -i tests/data/vsynth2.yuv \