[FFmpeg-devel] [PATCH 1/2] allow to extract subcc

Anshul anshul.ffmpeg at gmail.com
Wed Dec 3 21:09:27 CET 2014


On 12/04/2014 12:36 AM, wm4 wrote:
> On Wed,  3 Dec 2014 17:58:57 +0530
> anshul.ffmpeg at gmail.com wrote:
>
>> From: Nicolas George <george at 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
>>  
>> + 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 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 at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Dont know why its here, but this  is most required part to extract cc
from h264 user data.

It may be because -f v4l2 is in device,  Here input parameter is not
considered in normal way.


More information about the ffmpeg-devel mailing list