[FFmpeg-devel] [PATCH 2/2] lavd/lavfi: allow to extract subcc.
anshul
anshul.ffmpeg at gmail.com
Thu Mar 13 11:22:24 CET 2014
On 03/13/2014 01:52 PM, anshul wrote:
> On 03/10/2014 04:26 PM, Nicolas George wrote:
>> Signed-off-by: Nicolas George <george at nsup.org>
>> ---
>> doc/indevs.texi | 9 ++++++
>> libavdevice/lavfi.c | 80
>> +++++++++++++++++++++++++++++++++++++++++++++++++----
>> 2 files changed, 84 insertions(+), 5 deletions(-)
>>
>>
>> With this patch, it becomes possible to dump the subcc data, just like
>> Anshul's program did, using the ffmpeg command-line tool.
>>
>> With a decoder, hopefully, it would be possible to use them like any
>> kind of
>> text subtitles.
>>
>> It requires using "-f lavfi -i movie=file" instead of just "-i file".
>> I am
>> not sure what the long term solution would be: implementing that
>> really at
>> the demuxer level, including frame reordering, or acknowledging that the
>> protocol/demuxer/decoder stack model is too limited for some features
>> (including, but not limited to, this one) and move to a more general
>> model,
>> possibly based on complex graphs.
>>
>>
>> diff --git a/doc/indevs.texi b/doc/indevs.texi
>> index 93fbbe8..cf948c6 100644
>> --- a/doc/indevs.texi
>> +++ b/doc/indevs.texi
>> @@ -324,6 +324,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.
>> @@ -371,6 +374,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
>> + at item
>> +Dump decoded frames to images and closed captions to a file
>> (experimental):
>> + at example
>> +ffmpeg -f lavfi -i "movie=test.ts[out0+subcc]" -map v frame%08d.png
>> -map s -c copy -f rawvideo subcc.bin
>> + at end example
>> +
>> @end itemize
>> @section libdc1394
>> diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c
>> index 1ea7ea7..83fe490 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_CEA_708;
>> + 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));
>> @@ -200,6 +228,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[i] = !!use_subcc;
>> }
>> /* for each open output create a corresponding stream */
>> @@ -211,7 +240,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(sizeof(AVFilterContext *) *
>> avctx->nb_streams);
>> + lavfi->sinks = av_malloc(sizeof(AVFilterContext *) *
>> lavfi->nb_sinks);
>> if (!lavfi->sinks)
>> FAIL(AVERROR(ENOMEM));
>> @@ -271,7 +300,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;
>> @@ -302,6 +331,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));
>> @@ -314,6 +346,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;
>> @@ -325,9 +381,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;
>> @@ -401,6 +465,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);
>
> Hi
> I was patched my git with both of this patch,
> I am unable to run the code using below command,
> ./ffmpeg_g f lavfi -i "movie=test.ts[out0+subcc]" -map v frame%08d.png
> -map s -c copy -f rawvideo subcc.bin
> I kept test.ts file in same folder as ffmpeg_g.
> ffmpeg gives me error
> movie=test.ts[out0+subcc]: No such file or directory
>
> I have never given the movie after i, but as per the texi file this is
> what i understood.
>
> Thanks
> Anshul
ignore it it was my typing mistake f instead of -f and I was looking
inside that patch.
Sorry
Anshul
More information about the ffmpeg-devel
mailing list