[FFmpeg-devel] [PATCH] lavf/segment: add support to concat segment list

Stefano Sabatini stefasab at gmail.com
Thu Mar 7 01:49:02 CET 2013


On date Tuesday 2013-03-05 16:05:42 +0100, Nicolas George encoded:
> Le quartidi 14 ventôse, an CCXXI, Stefano Sabatini a écrit :
> > Seems to work fine after your fix, patch updated.
> 
> Adding the durations in the concat file may be a good thing, but that can
> come later.

Pushed in order to avoid to delay too much the patch (feel free to
propose such a patch yourself). What's the benefit of such approach?

> 
> > >From fbe4f6fb86490a76715f9ac0b43b49e6692780fb Mon Sep 17 00:00:00 2001
> > From: Stefano Sabatini <stefasab at gmail.com>
> > Date: Thu, 21 Feb 2013 19:33:26 +0100
> > Subject: [PATCH] lavf/segment: add support to concat segment list
> > 
> > TODO: update docs, bump micro
> > ---
> >  doc/demuxers.texi     |    1 +
> >  doc/muxers.texi       |    7 +++++++
> >  libavformat/segment.c |   24 +++++++++++++++++++++---
> >  3 files changed, 29 insertions(+), 3 deletions(-)
> > 
> > diff --git a/doc/demuxers.texi b/doc/demuxers.texi
> > index c8eec21..899729a 100644
> > --- a/doc/demuxers.texi
> > +++ b/doc/demuxers.texi
> > @@ -29,6 +29,7 @@ the caller can decide which variant streams to actually receive.
> >  The total bitrate of the variant that the stream belongs to is
> >  available in a metadata key named "variant_bitrate".
> >  
> > + at anchor{concat}
> >  @section concat
> >  
> >  Virtual concatenation script demuxer.
> > diff --git a/doc/muxers.texi b/doc/muxers.texi
> > index 6aae871..52b88ca 100644
> > --- a/doc/muxers.texi
> > +++ b/doc/muxers.texi
> > @@ -560,6 +560,13 @@ The following values are recognized:
> >  @item flat
> >  Generate a flat list for the created segments, one segment per line.
> >  
> > + at item concat
> > +Generate a ffconcat file for the created segments. The resulting file
> > +can be read using the @ref{concat} demuxer.
> > +
> > +A list file with the suffix @code{".ffcat"} or @code{".ffconcat"} will
> > +auto-select this format.
> > +
> >  @item csv, ext
> >  Generate a list for the created segments, one segment per line,
> >  each line matching the format (comma-separated values):
> > diff --git a/libavformat/segment.c b/libavformat/segment.c
> > index 13d8c43..6b7d5b0 100644
> > --- a/libavformat/segment.c
> > +++ b/libavformat/segment.c
> > @@ -53,6 +53,7 @@ typedef enum {
> >      LIST_TYPE_CSV,
> >      LIST_TYPE_M3U8,
> >      LIST_TYPE_EXT, ///< deprecated
> > +    LIST_TYPE_CONCAT,
> >      LIST_TYPE_NB,
> >  } ListType;
> >  
> > @@ -225,6 +226,8 @@ static int segment_list_open(AVFormatContext *s)
> >          for (entry = seg->segment_list_entries; entry; entry = entry->next)
> >              max_duration = FFMAX(max_duration, entry->end_time - entry->start_time);
> >          avio_printf(seg->list_pb, "#EXT-X-TARGETDURATION:%"PRId64"\n", (int64_t)ceil(max_duration));
> > +    } else if (seg->list_type == LIST_TYPE_CONCAT) {
> > +        avio_printf(seg->list_pb, "ffconcat version 1.0\n");
> >      }
> >  
> >      return ret;
> > @@ -232,7 +235,8 @@ static int segment_list_open(AVFormatContext *s)
> >  
> >  static void segment_list_print_entry(AVIOContext      *list_ioctx,
> >                                       ListType          list_type,
> > -                                     const SegmentListEntry *list_entry)
> > +                                     const SegmentListEntry *list_entry,
> > +                                     void *log_ctx)
> >  {
> >      switch (list_type) {
> >      case LIST_TYPE_FLAT:
> > @@ -247,6 +251,18 @@ static void segment_list_print_entry(AVIOContext      *list_ioctx,
> >          avio_printf(list_ioctx, "#EXTINF:%f,\n%s\n",
> >                      list_entry->end_time - list_entry->start_time, list_entry->filename);
> >          break;
> > +    case LIST_TYPE_CONCAT:
> > +    {
> > +        char *buf;
> 
> > +        if (av_escape(&buf, list_entry->filename, NULL, AV_ESCAPE_MODE_QUOTE, 0) < 0) {
> 
> MODE_DEFAULT, maybe? I have no strong opinion about it.

Changed.
 
> > +            av_log(log_ctx, AV_LOG_WARNING,
> > +                   "Error writing list entry '%s' in list file\n", list_entry->filename);
> > +            return;
> > +        }
> 
> The error is not reported to the application, this is not good. OTOH, the
> same already happens for all errors on avio, so...

Indeed...

> 
> > +        avio_printf(list_ioctx, "file %s\n", buf);
> > +        av_free(buf);
> > +        break;
> > +    }
> >      default:
> >          av_assert0(!"Invalid list type");
> >      }
> > @@ -293,11 +309,11 @@ static int segment_end(AVFormatContext *s, int write_trailer, int is_last)
> >              if ((ret = segment_list_open(s)) < 0)
> >                  goto end;
> >              for (entry = seg->segment_list_entries; entry; entry = entry->next)
> > -                segment_list_print_entry(seg->list_pb, seg->list_type, entry);
> > +                segment_list_print_entry(seg->list_pb, seg->list_type, entry, s);
> >              if (seg->list_type == LIST_TYPE_M3U8 && is_last)
> >                  avio_printf(seg->list_pb, "#EXT-X-ENDLIST\n");
> >          } else {
> > -            segment_list_print_entry(seg->list_pb, seg->list_type, &seg->cur_entry);
> > +            segment_list_print_entry(seg->list_pb, seg->list_type, &seg->cur_entry, s);
> >          }
> >          avio_flush(seg->list_pb);
> >      }
> > @@ -551,6 +567,7 @@ static int seg_write_header(AVFormatContext *s)
> >              if      (av_match_ext(seg->list, "csv" )) seg->list_type = LIST_TYPE_CSV;
> >              else if (av_match_ext(seg->list, "ext" )) seg->list_type = LIST_TYPE_EXT;
> >              else if (av_match_ext(seg->list, "m3u8")) seg->list_type = LIST_TYPE_M3U8;
> > +            else if (av_match_ext(seg->list, "ffcat,ffconcat")) seg->list_type = LIST_TYPE_CONCAT;
> >              else                                      seg->list_type = LIST_TYPE_FLAT;
> >          }
> >          if ((ret = segment_list_open(s)) < 0)
> > @@ -759,6 +776,7 @@ static const AVOption options[] = {
> >  
> >      { "segment_list_type", "set the segment list type",                  OFFSET(list_type), AV_OPT_TYPE_INT,  {.i64 = LIST_TYPE_UNDEFINED}, -1, LIST_TYPE_NB-1, E, "list_type" },
> >      { "flat", "flat format",     0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_FLAT }, INT_MIN, INT_MAX, E, "list_type" },
> > +    { "concat", "ffconcat format", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_CONCAT }, INT_MIN, INT_MAX, E, "list_type" },
> >      { "csv",  "csv format",      0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_CSV  }, INT_MIN, INT_MAX, E, "list_type" },
> >      { "ext",  "extended format", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_EXT  }, INT_MIN, INT_MAX, E, "list_type" },
> >      { "m3u8", "M3U8 format",     0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_M3U8 }, INT_MIN, INT_MAX, E, "list_type" },
> 
> LGTM, thanks.

Pushed, thanks.
-- 
FFmpeg = Fundamental & Fierce Minimalistic Pitiful Earthshaking Guru


More information about the ffmpeg-devel mailing list