mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
ffmpeg: port sub2video to AVFrame.
And re-enable the FATE test.
This commit is contained in:
parent
f185a040b0
commit
f9b34b8bf9
44
ffmpeg.c
44
ffmpeg.c
@ -168,7 +168,20 @@ static int restore_tty;
|
|||||||
This is a temporary solution until libavfilter gets real subtitles support.
|
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,
|
static void sub2video_copy_rect(uint8_t *dst, int dst_linesize, int w, int h,
|
||||||
AVSubtitleRect *r)
|
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)
|
static void sub2video_push_ref(InputStream *ist, int64_t pts)
|
||||||
{
|
{
|
||||||
AVFilterBufferRef *ref = ist->sub2video.ref;
|
AVFrame *frame = ist->sub2video.frame;
|
||||||
int i;
|
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++)
|
for (i = 0; i < ist->nb_filters; i++)
|
||||||
av_buffersrc_add_ref(ist->filters[i]->filter,
|
av_buffersrc_write_frame(ist->filters[i]->filter, frame);
|
||||||
avfilter_ref_buffer(ref, ~0),
|
|
||||||
AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT |
|
|
||||||
AV_BUFFERSRC_FLAG_NO_COPY |
|
|
||||||
AV_BUFFERSRC_FLAG_PUSH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sub2video_update(InputStream *ist, AVSubtitle *sub)
|
static void sub2video_update(InputStream *ist, AVSubtitle *sub)
|
||||||
{
|
{
|
||||||
int w = ist->sub2video.w, h = ist->sub2video.h;
|
int w = ist->sub2video.w, h = ist->sub2video.h;
|
||||||
AVFilterBufferRef *ref = ist->sub2video.ref;
|
AVFrame *frame = ist->sub2video.frame;
|
||||||
int8_t *dst;
|
int8_t *dst;
|
||||||
int dst_linesize;
|
int dst_linesize;
|
||||||
int num_rects, i;
|
int num_rects, i;
|
||||||
int64_t pts, end_pts;
|
int64_t pts, end_pts;
|
||||||
|
|
||||||
if (!ref)
|
if (!frame)
|
||||||
return;
|
return;
|
||||||
if (sub) {
|
if (sub) {
|
||||||
pts = av_rescale_q(sub->pts + sub->start_display_time * 1000,
|
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;
|
end_pts = INT64_MAX;
|
||||||
num_rects = 0;
|
num_rects = 0;
|
||||||
}
|
}
|
||||||
dst = ref->data [0];
|
if (sub2video_get_blank_frame(ist) < 0) {
|
||||||
dst_linesize = ref->linesize[0];
|
av_log(ist->st->codec, AV_LOG_ERROR,
|
||||||
memset(dst, 0, h * dst_linesize);
|
"Impossible to get a blank canvas.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dst = frame->data [0];
|
||||||
|
dst_linesize = frame->linesize[0];
|
||||||
for (i = 0; i < num_rects; i++)
|
for (i = 0; i < num_rects; i++)
|
||||||
sub2video_copy_rect(dst, dst_linesize, w, h, sub->rects[i]);
|
sub2video_copy_rect(dst, dst_linesize, w, h, sub->rects[i]);
|
||||||
sub2video_push_ref(ist, pts);
|
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. */
|
(possibly overlay) is desperately waiting for a subtitle frame. */
|
||||||
for (i = 0; i < infile->nb_streams; i++) {
|
for (i = 0; i < infile->nb_streams; i++) {
|
||||||
InputStream *ist2 = input_streams[infile->ist_index + i];
|
InputStream *ist2 = input_streams[infile->ist_index + i];
|
||||||
if (!ist2->sub2video.ref)
|
if (!ist2->sub2video.frame)
|
||||||
continue;
|
continue;
|
||||||
/* subtitles seem to be usually muxed ahead of other streams;
|
/* subtitles seem to be usually muxed ahead of other streams;
|
||||||
if not, substracting a larger time here is necessary */
|
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 */
|
/* do not send the heartbeat frame if the subtitle is already ahead */
|
||||||
if (pts2 <= ist2->sub2video.last_pts)
|
if (pts2 <= ist2->sub2video.last_pts)
|
||||||
continue;
|
continue;
|
||||||
if (pts2 >= ist2->sub2video.end_pts)
|
if (pts2 >= ist2->sub2video.end_pts || !ist2->sub2video.frame->data[0])
|
||||||
sub2video_update(ist2, NULL);
|
sub2video_update(ist2, NULL);
|
||||||
for (j = 0, nb_reqs = 0; j < ist2->nb_filters; j++)
|
for (j = 0, nb_reqs = 0; j < ist2->nb_filters; j++)
|
||||||
nb_reqs += av_buffersrc_get_nb_failed_requests(ist2->filters[j]->filter);
|
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);
|
av_dict_free(&input_streams[i]->opts);
|
||||||
free_buffer_pool(&input_streams[i]->buffer_pool);
|
free_buffer_pool(&input_streams[i]->buffer_pool);
|
||||||
avsubtitle_free(&input_streams[i]->prev_sub.subtitle);
|
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]->filters);
|
||||||
av_freep(&input_streams[i]);
|
av_freep(&input_streams[i]);
|
||||||
}
|
}
|
||||||
|
2
ffmpeg.h
2
ffmpeg.h
@ -255,7 +255,7 @@ typedef struct InputStream {
|
|||||||
struct sub2video {
|
struct sub2video {
|
||||||
int64_t last_pts;
|
int64_t last_pts;
|
||||||
int64_t end_pts;
|
int64_t end_pts;
|
||||||
AVFilterBufferRef *ref;
|
AVFrame *frame;
|
||||||
int w, h;
|
int w, h;
|
||||||
} sub2video;
|
} sub2video;
|
||||||
|
|
||||||
|
@ -501,9 +501,7 @@ int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOu
|
|||||||
static int sub2video_prepare(InputStream *ist)
|
static int sub2video_prepare(InputStream *ist)
|
||||||
{
|
{
|
||||||
AVFormatContext *avf = input_files[ist->file_index]->ctx;
|
AVFormatContext *avf = input_files[ist->file_index]->ctx;
|
||||||
int i, ret, w, h;
|
int i, w, h;
|
||||||
uint8_t *image[4];
|
|
||||||
int linesize[4];
|
|
||||||
|
|
||||||
/* Compute the size of the canvas for the subtitles stream.
|
/* Compute the size of the canvas for the subtitles stream.
|
||||||
If the subtitles codec has set a size, use it. Otherwise use the
|
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 */
|
palettes for all rectangles are identical or compatible */
|
||||||
ist->resample_pix_fmt = ist->st->codec->pix_fmt = AV_PIX_FMT_RGB32;
|
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);
|
ist->sub2video.frame = av_frame_alloc();
|
||||||
if (ret < 0)
|
if (!ist->sub2video.frame)
|
||||||
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]);
|
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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" \
|
avi "-c mpeg4 -g 240 -qscale 10 -force_key_frames 0.5,0:00:01.5" \
|
||||||
framecrc "" "" "-skip_frame nokey"
|
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: tests/data/vsynth2.yuv
|
||||||
fate-sub2video: CMD = framecrc \
|
fate-sub2video: CMD = framecrc \
|
||||||
-f rawvideo -r 5 -s 352x288 -pix_fmt yuv420p -i tests/data/vsynth2.yuv \
|
-f rawvideo -r 5 -s 352x288 -pix_fmt yuv420p -i tests/data/vsynth2.yuv \
|
||||||
|
Loading…
Reference in New Issue
Block a user