On Wed, 3 Dec 2014 17:58:57 +0530 anshul.ffm...@gmail.com wrote: > From: Nicolas George <geo...@nsup.org> > > --- > doc/indevs.texi | 9 ++++++ > libavdevice/lavfi.c | 80 > +++++++++++++++++++++++++++++++++++++++++++++++++---- > 2 files changed, 84 insertions(+), 5 deletions(-) > > diff --git a/doc/indevs.texi b/doc/indevs.texi > index 5d2a308..f31e2e3 100644 > --- a/doc/indevs.texi > +++ b/doc/indevs.texi > @@ -494,6 +494,9 @@ number starting from 0 corresponding to the mapped input > stream > generated by the device. > The first unlabelled output is automatically assigned to the "out0" > label, but all the others need to be specified explicitly. > +The suffix "+subcc" can be appended to the output label to create an extra > +stream with the closed captions packets attached to that output > +(experimental). > > If not specified defaults to the filename specified for the input > device. > @@ -541,6 +544,12 @@ Read an audio stream and a video stream and play it back > with > ffplay -f lavfi "movie=test.avi[out0];amovie=test.wav[out1]" > @end example > > +@item > +Dump decoded frames to images and closed captions to a file (experimental): > +@example > +ffmpeg -f lavfi -i "movie=test.ts[out0+subcc]" -map v frame%08d.png -map s > -c copy -f rawvideo subcc.bin > +@end example > + > @end itemize > > @section libcdio > diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c > index 1398ece..bc45117 100644 > --- a/libavdevice/lavfi.c > +++ b/libavdevice/lavfi.c > @@ -51,7 +51,10 @@ typedef struct { > int *sink_stream_map; > int *sink_eof; > int *stream_sink_map; > + int *sink_stream_subcc_map; > AVFrame *decoded_frame; > + int nb_sinks; > + AVPacket subcc_packet; > } LavfiContext; > > static int *create_all_formats(int n) > @@ -82,6 +85,7 @@ av_cold static int lavfi_read_close(AVFormatContext *avctx) > av_freep(&lavfi->sink_stream_map); > av_freep(&lavfi->sink_eof); > av_freep(&lavfi->stream_sink_map); > + av_freep(&lavfi->sink_stream_subcc_map); > av_freep(&lavfi->sinks); > avfilter_graph_free(&lavfi->graph); > av_frame_free(&lavfi->decoded_frame); > @@ -89,6 +93,27 @@ av_cold static int lavfi_read_close(AVFormatContext *avctx) > return 0; > } > > +static int create_subcc_streams(AVFormatContext *avctx) > +{ > + LavfiContext *lavfi = avctx->priv_data; > + AVStream *st; > + int stream_idx, sink_idx; > + > + for (stream_idx = 0; stream_idx < lavfi->nb_sinks; stream_idx++) { > + sink_idx = lavfi->stream_sink_map[stream_idx]; > + if (lavfi->sink_stream_subcc_map[sink_idx]) { > + lavfi->sink_stream_subcc_map[sink_idx] = avctx->nb_streams; > + if (!(st = avformat_new_stream(avctx, NULL))) > + return AVERROR(ENOMEM); > + st->codec->codec_id = AV_CODEC_ID_EIA_608; > + st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; > + } else { > + lavfi->sink_stream_subcc_map[sink_idx] = -1; > + } > + } > + return 0; > +} > + > av_cold static int lavfi_read_header(AVFormatContext *avctx) > { > LavfiContext *lavfi = avctx->priv_data; > @@ -153,6 +178,7 @@ av_cold static int lavfi_read_header(AVFormatContext > *avctx) > > /* count the outputs */ > for (n = 0, inout = output_links; inout; n++, inout = inout->next); > + lavfi->nb_sinks = n; > > if (!(lavfi->sink_stream_map = av_malloc(sizeof(int) * n))) > FAIL(AVERROR(ENOMEM)); > @@ -160,6 +186,8 @@ av_cold static int lavfi_read_header(AVFormatContext > *avctx) > FAIL(AVERROR(ENOMEM)); > if (!(lavfi->stream_sink_map = av_malloc(sizeof(int) * n))) > FAIL(AVERROR(ENOMEM)); > + if (!(lavfi->sink_stream_subcc_map = av_malloc(sizeof(int) * n))) > + FAIL(AVERROR(ENOMEM)); > > for (i = 0; i < n; i++) > lavfi->stream_sink_map[i] = -1; > @@ -167,10 +195,10 @@ av_cold static int lavfi_read_header(AVFormatContext > *avctx) > /* parse the output link names - they need to be of the form out0, out1, > ... > * create a mapping between them and the streams */ > for (i = 0, inout = output_links; inout; i++, inout = inout->next) { > - int stream_idx; > + int stream_idx, use_subcc = 0; > if (!strcmp(inout->name, "out")) > stream_idx = 0; > - else if (sscanf(inout->name, "out%d\n", &stream_idx) != 1) { > + else if (sscanf(inout->name, "out%d+subcc%n\n", &stream_idx, > &use_subcc) != 1) { > av_log(avctx, AV_LOG_ERROR, > "Invalid outpad name '%s'\n", inout->name); > FAIL(AVERROR(EINVAL)); > @@ -192,6 +220,7 @@ av_cold static int lavfi_read_header(AVFormatContext > *avctx) > } > lavfi->sink_stream_map[i] = stream_idx; > lavfi->stream_sink_map[stream_idx] = i; > + lavfi->sink_stream_subcc_map[stream_idx] = !!use_subcc; > } > > /* for each open output create a corresponding stream */ > @@ -203,7 +232,7 @@ av_cold static int lavfi_read_header(AVFormatContext > *avctx) > } > > /* create a sink for each output and connect them to the graph */ > - lavfi->sinks = av_malloc_array(avctx->nb_streams, sizeof(AVFilterContext > *)); > + lavfi->sinks = av_malloc_array(lavfi->nb_sinks, sizeof(AVFilterContext > *)); > if (!lavfi->sinks) > FAIL(AVERROR(ENOMEM)); > > @@ -267,7 +296,7 @@ av_cold static int lavfi_read_header(AVFormatContext > *avctx) > } > > /* fill each stream with the information in the corresponding sink */ > - for (i = 0; i < avctx->nb_streams; i++) { > + for (i = 0; i < lavfi->nb_sinks; i++) { > AVFilterLink *link = > lavfi->sinks[lavfi->stream_sink_map[i]]->inputs[0]; > AVStream *st = avctx->streams[i]; > st->codec->codec_type = link->type; > @@ -298,6 +327,9 @@ av_cold static int lavfi_read_header(AVFormatContext > *avctx) > } > } > > + if ((ret = create_subcc_streams(avctx)) < 0) > + FAIL(ret); > + > if (!(lavfi->decoded_frame = av_frame_alloc())) > FAIL(AVERROR(ENOMEM)); > > @@ -310,6 +342,30 @@ end: > return ret; > } > > +static int create_subcc_packet(AVFormatContext *avctx, AVFrame *frame, > + int sink_idx) > +{ > + LavfiContext *lavfi = avctx->priv_data; > + AVFrameSideData *sd; > + int stream_idx, i, ret; > + > + if ((stream_idx = lavfi->sink_stream_subcc_map[sink_idx]) < 0) > + return 0; > + for (i = 0; i < frame->nb_side_data; i++) > + if (frame->side_data[i]->type == AV_FRAME_DATA_A53_CC) > + break; > + if (i >= frame->nb_side_data) > + return 0; > + sd = frame->side_data[i]; > + if ((ret = av_new_packet(&lavfi->subcc_packet, sd->size)) < 0) > + return ret; > + memcpy(lavfi->subcc_packet.data, sd->data, sd->size); > + lavfi->subcc_packet.stream_index = stream_idx; > + lavfi->subcc_packet.pts = frame->pts; > + lavfi->subcc_packet.pos = av_frame_get_pkt_pos(frame); > + return 0; > +} > + > static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt) > { > LavfiContext *lavfi = avctx->priv_data; > @@ -321,9 +377,17 @@ static int lavfi_read_packet(AVFormatContext *avctx, > AVPacket *pkt) > int ret, i; > int size = 0; > > + if (lavfi->subcc_packet.size) { > + *pkt = lavfi->subcc_packet; > + av_init_packet(&lavfi->subcc_packet); > + lavfi->subcc_packet.size = 0; > + lavfi->subcc_packet.data = NULL; > + return pkt->size; > + } > + > /* iterate through all the graph sinks. Select the sink with the > * minimum PTS */ > - for (i = 0; i < avctx->nb_streams; i++) { > + for (i = 0; i < lavfi->nb_sinks; i++) { > AVRational tb = lavfi->sinks[i]->inputs[0]->time_base; > double d; > int ret; > @@ -397,6 +461,12 @@ static int lavfi_read_packet(AVFormatContext *avctx, > AVPacket *pkt) > av_bprint_finalize(&meta_buf, NULL); > } > > + if ((ret = create_subcc_packet(avctx, frame, min_pts_sink_idx)) < 0) { > + av_frame_unref(frame); > + av_packet_unref(pkt); > + return ret; > + } > + > pkt->stream_index = stream_idx; > pkt->pts = frame->pts; > pkt->pos = av_frame_get_pkt_pos(frame);
Why is this in libavdevice? _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel