[FFmpeg-devel] [PATCH] libavformat/matroska: Write stream durations in metadata, in the format of mkvmerge.

Sasi Inguva isasi at google.com
Wed Aug 5 07:12:28 CEST 2015


Changed the patch to initialize those variables in mkv_write_header. Also
checking if stream_duration_offset > 0 before writing them as tags in
write_trailer, so it won't be written for webm.

On Tue, Aug 4, 2015 at 6:54 PM, Michael Niedermayer <michael at niedermayer.cc>
wrote:

> On Tue, Aug 04, 2015 at 05:32:51PM -0700, Sasi Inguva wrote:
> > Compute individual stream durations in matroska muxer.
> > Write them as string tags in the same format as mkvmerge tool does.
> >
> > Signed-off-by: Sasi Inguva <isasi at google.com>
> > ---
> >  libavformat/matroskaenc.c    | 75
> +++++++++++++++++++++++++++++++++++++++++---
> >  tests/fate/wavpack.mak       |  4 +--
> >  tests/ref/acodec/tta         |  4 +--
> >  tests/ref/fate/binsub-mksenc |  2 +-
> >  tests/ref/lavf/mkv           |  8 ++---
> >  tests/ref/seek/lavf-mkv      | 44 +++++++++++++-------------
> >  6 files changed, 101 insertions(+), 36 deletions(-)
> >
> > diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
> > index 2d0d5f6..0d3ae37 100644
> > --- a/libavformat/matroskaenc.c
> > +++ b/libavformat/matroskaenc.c
> > @@ -44,6 +44,7 @@
> >  #include "libavutil/mathematics.h"
> >  #include "libavutil/opt.h"
> >  #include "libavutil/random_seed.h"
> > +#include "libavutil/rational.h"
> >  #include "libavutil/samplefmt.h"
> >  #include "libavutil/sha.h"
> >  #include "libavutil/stereo3d.h"
> > @@ -131,6 +132,9 @@ typedef struct MatroskaMuxContext {
> >
> >      int64_t last_track_timestamp[MAX_TRACKS];
> >
> > +    int64_t* stream_durations;
> > +    int64_t* stream_duration_offsets;
> > +
> >      int allow_raw_vfw;
> >  } MatroskaMuxContext;
> >
> > @@ -1151,12 +1155,12 @@ static int mkv_write_simpletag(AVIOContext *pb,
> AVDictionaryEntry *t)
> >      return 0;
> >  }
> >
> > -static int mkv_write_tag(AVFormatContext *s, AVDictionary *m, unsigned
> int elementid,
> > -                         unsigned int uid, ebml_master *tags)
> > +static int mkv_write_tag_targets(AVFormatContext *s,
> > +                                 unsigned int elementid, unsigned int
> uid,
> > +                                 ebml_master *tags, ebml_master* tag)
> >  {
> >      MatroskaMuxContext *mkv = s->priv_data;
> > -    ebml_master tag, targets;
> > -    AVDictionaryEntry *t = NULL;
> > +    ebml_master targets;
> >      int ret;
> >
> >      if (!tags->pos) {
> > @@ -1166,11 +1170,24 @@ static int mkv_write_tag(AVFormatContext *s,
> AVDictionary *m, unsigned int eleme
> >          *tags = start_ebml_master(s->pb, MATROSKA_ID_TAGS, 0);
> >      }
> >
> > -    tag     = start_ebml_master(s->pb, MATROSKA_ID_TAG,        0);
> > +    *tag     = start_ebml_master(s->pb, MATROSKA_ID_TAG,        0);
> >      targets = start_ebml_master(s->pb, MATROSKA_ID_TAGTARGETS, 0);
> >      if (elementid)
> >          put_ebml_uint(s->pb, elementid, uid);
> >      end_ebml_master(s->pb, targets);
> > +    return 0;
> > +}
> > +
> > +static int mkv_write_tag(AVFormatContext *s, AVDictionary *m, unsigned
> int elementid,
> > +                         unsigned int uid, ebml_master *tags)
> > +{
> > +    ebml_master tag;
> > +    int ret;
> > +    AVDictionaryEntry *t = NULL;
> > +
> > +    ret = mkv_write_tag_targets(s, elementid, uid, tags, &tag);
> > +    if (ret < 0)
> > +        return ret;
> >
> >      while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) {
> >          if (av_strcasecmp(t->key, "title") &&
> > @@ -1220,6 +1237,29 @@ static int mkv_write_tags(AVFormatContext *s)
> >          if (ret < 0) return ret;
> >      }
> >
> > +
> > +    mkv->stream_durations = av_mallocz(s->nb_streams * sizeof(int64_t));
> > +    mkv->stream_duration_offsets = av_mallocz(s->nb_streams *
> sizeof(int64_t));
>
> this is not called in all cases, for example its not called for
> webm
>
>
> > +
> > +    if (!mkv->is_live) {
> > +      for (i = 0; i < s->nb_streams; i++) {
> > +        ebml_master tag_target;
> > +        ebml_master tag;
> > +
> > +        mkv_write_tag_targets(s, MATROSKA_ID_TAGTARGETS_TRACKUID, i +
> 1, &tags, &tag_target);
> > +
> > +        tag = start_ebml_master(s->pb, MATROSKA_ID_SIMPLETAG, 0);
> > +        put_ebml_string(s->pb, MATROSKA_ID_TAGNAME, "DURATION");
> > +        mkv->stream_duration_offsets[i] = avio_tell(s->pb);
> > +
> > +        // Reserve space to write duration as a 20-byte string.
> > +        // 2 (ebml id) + 1 (data size) + 20 (data)
> > +        put_ebml_void(s->pb, 23);
> > +        end_ebml_master(s->pb, tag);
> > +        end_ebml_master(s->pb, tag_target);
> > +      }
> > +    }
> > +
> >      for (i = 0; i < s->nb_chapters; i++) {
> >          AVChapter *ch = s->chapters[i];
> >
> > @@ -1801,6 +1841,9 @@ static int
> mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_
> >      }
> >
> >      mkv->duration = FFMAX(mkv->duration, ts + duration);
> > +    mkv->stream_durations[pkt->stream_index] =
> > +        FFMAX(mkv->stream_durations[pkt->stream_index], ts + duration);
> > +
>
> this is called for webm too though
>
> [...]
> --
> Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> Old school: Use the lowest level language in which you can solve the
> problem
>             conveniently.
> New school: Use the highest level language in which the latest
> supercomputer
>             can solve the problem without the user falling asleep waiting.
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
>


More information about the ffmpeg-devel mailing list