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

Sasi Inguva isasi at google.com
Wed Aug 5 19:00:45 CEST 2015


yes. it does .
http://stackoverflow.com/questions/18688971/c-char-array-initialization
 and from an example in Initialization from strings in
http://en.cppreference.com/w/c/language/array_initialization .

On Wed, Aug 5, 2015 at 9:48 AM, wm4 <nfxjfg at googlemail.com> wrote:

> On Tue,  4 Aug 2015 22:09:57 -0700
> Sasi Inguva <isasi at google.com> 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    | 79
> +++++++++++++++++++++++++++++++++++++++++---
> >  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, 105 insertions(+), 36 deletions(-)
> >
> > diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
> > index 2d0d5f6..703abc3 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,25 @@ static int mkv_write_tags(AVFormatContext *s)
> >          if (ret < 0) return ret;
> >      }
> >
> > +    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];
> >
> > @@ -1430,6 +1466,10 @@ static int mkv_write_header(AVFormatContext *s)
> >      }
> >      end_ebml_master(pb, segment_info);
> >
> > +    // initialize stream_duration fields
> > +    mkv->stream_durations = av_mallocz(s->nb_streams * sizeof(int64_t));
> > +    mkv->stream_duration_offsets = av_mallocz(s->nb_streams *
> sizeof(int64_t));
> > +
> >      ret = mkv_write_tracks(s);
> >      if (ret < 0)
> >          return ret;
> > @@ -1801,6 +1841,11 @@ static int
> mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_
> >      }
> >
> >      mkv->duration = FFMAX(mkv->duration, ts + duration);
> > +
> > +    if (mkv->stream_durations)
> > +        mkv->stream_durations[pkt->stream_index] =
> > +            FFMAX(mkv->stream_durations[pkt->stream_index], ts +
> duration);
> > +
> >      return 0;
> >  }
> >
> > @@ -1978,6 +2023,28 @@ static int mkv_write_trailer(AVFormatContext *s)
> >          avio_seek(pb, mkv->duration_offset, SEEK_SET);
> >          put_ebml_float(pb, MATROSKA_ID_DURATION, mkv->duration);
> >
> > +        // update stream durations
> > +        if (mkv->stream_durations) {
> > +            for (int i = 0; i < s->nb_streams; ++i) {
> > +                AVStream *st = s->streams[i];
> > +                double duration_sec = mkv->stream_durations[i] *
> av_q2d(st->time_base);
> > +                char duration_string[20] = "";
>
> The whole char array is written to the file. Does C guarantee that this
> initialization actually sets all items to 0? (Most likely does, I don't
> remember. I just want to be sure it gets padded with zeros, instead of
> writing stack data to the file.)
>
> > +
> > +                av_log(s, AV_LOG_DEBUG, "stream %d end duration = %"
> PRIu64 "\n", i,
> > +                       mkv->stream_durations[i]);
> > +
> > +                if (!mkv->is_live && mkv->stream_duration_offsets[i] >
> 0) {
> > +                    avio_seek(pb, mkv->stream_duration_offsets[i],
> SEEK_SET);
> > +
> > +                    snprintf(duration_string, 20, "%02d:%02d:%012.9f",
> > +                             (int) duration_sec / 3600, ((int)
> duration_sec / 60) % 60,
> > +                             fmod(duration_sec, 60));
> > +
> > +                    put_ebml_binary(pb, MATROSKA_ID_TAGSTRING,
> duration_string, 20);
> > +                }
> > +            }
> > +        }
> > +
> >          avio_seek(pb, currentpos, SEEK_SET);
> >      }
> >
> > @@ -1987,6 +2054,8 @@ static int mkv_write_trailer(AVFormatContext *s)
> >      av_freep(&mkv->tracks);
> >      av_freep(&mkv->cues->entries);
> >      av_freep(&mkv->cues);
> > +    av_freep(&mkv->stream_durations);
> > +    av_freep(&mkv->stream_duration_offsets);
> >
> >      return 0;
> >  }
> > diff --git a/tests/fate/wavpack.mak b/tests/fate/wavpack.mak
> > index 240f5ea..a825a02 100644
> > --- a/tests/fate/wavpack.mak
> > +++ b/tests/fate/wavpack.mak
> > @@ -91,12 +91,12 @@ fate-wavpack-matroskamode: CMD = md5 -i
> $(TARGET_SAMPLES)/wavpack/special/matros
> >  FATE_WAVPACK-$(call DEMMUX, WV, MATROSKA) +=
> fate-wavpack-matroska_mux-mono
> >  fate-wavpack-matroska_mux-mono: CMD = md5 -i
> $(TARGET_SAMPLES)/wavpack/num_channels/mono_16bit_int.wv -c copy -fflags
> +bitexact -f matroska
> >  fate-wavpack-matroska_mux-mono: CMP = oneline
> > -fate-wavpack-matroska_mux-mono: REF = a2987e2e51e01a35e47e7da13eb47a35
> > +fate-wavpack-matroska_mux-mono: REF = 4befcc41dab6c690a15d0c396c324468
> >
> >  FATE_WAVPACK-$(call DEMMUX, WV, MATROSKA) +=
> fate-wavpack-matroska_mux-61
> >  fate-wavpack-matroska_mux-61: CMD = md5 -i
> $(TARGET_SAMPLES)/wavpack/num_channels/eva_2.22_6.1_16bit-partial.wv -c
> copy -fflags +bitexact -f matroska
> >  fate-wavpack-matroska_mux-61: CMP = oneline
> > -fate-wavpack-matroska_mux-61: REF = ffba4ddea1ba71f7a5901d9ed1a267be
> > +fate-wavpack-matroska_mux-61: REF = 7fedbfc3b9ea7348761db664626c29f4
> >
> >  FATE_SAMPLES_AVCONV += $(FATE_WAVPACK-yes)
> >  fate-wavpack: $(FATE_WAVPACK-yes)
> > diff --git a/tests/ref/acodec/tta b/tests/ref/acodec/tta
> > index b4b9611..0f60345 100644
> > --- a/tests/ref/acodec/tta
> > +++ b/tests/ref/acodec/tta
> > @@ -1,4 +1,4 @@
> > -aeeb0f2e75d044dbe2f89b7e70a54c82 *tests/data/fate/acodec-tta.matroska
> > -331080 tests/data/fate/acodec-tta.matroska
> > +6c260836d7a32e4bd714453a3546c0d5 *tests/data/fate/acodec-tta.matroska
> > +331148 tests/data/fate/acodec-tta.matroska
> >  95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-tta.out.wav
> >  stddev:    0.00 PSNR:999.99 MAXDIFF:    0 bytes:  1058400/  1058400
> > diff --git a/tests/ref/fate/binsub-mksenc b/tests/ref/fate/binsub-mksenc
> > index c473497..128ca31 100644
> > --- a/tests/ref/fate/binsub-mksenc
> > +++ b/tests/ref/fate/binsub-mksenc
> > @@ -1 +1 @@
> > -2dad5f63688ec613a04e94c8d4d167db
> > +37a212f8d56ad71e7466d5129f88e756
> > diff --git a/tests/ref/lavf/mkv b/tests/ref/lavf/mkv
> > index edbfe60..39a48d8 100644
> > --- a/tests/ref/lavf/mkv
> > +++ b/tests/ref/lavf/mkv
> > @@ -1,6 +1,6 @@
> > -bab98f5a04a9f7991fb960041c996478 *./tests/data/lavf/lavf.mkv
> > -472668 ./tests/data/lavf/lavf.mkv
> > +7c6509f597fb57bab002cbceec960011 *./tests/data/lavf/lavf.mkv
> > +472872 ./tests/data/lavf/lavf.mkv
> >  ./tests/data/lavf/lavf.mkv CRC=0xec6c3c68
> > -c93950920d4ee57eb3ff5ba0cf0c8b19 *./tests/data/lavf/lavf.mkv
> > -320412 ./tests/data/lavf/lavf.mkv
> > +5f8cb4b7e98610347dd8d0d58a828a0f *./tests/data/lavf/lavf.mkv
> > +320548 ./tests/data/lavf/lavf.mkv
> >  ./tests/data/lavf/lavf.mkv CRC=0xec6c3c68
> > diff --git a/tests/ref/seek/lavf-mkv b/tests/ref/seek/lavf-mkv
> > index 11275d6..af13ddb 100644
> > --- a/tests/ref/seek/lavf-mkv
> > +++ b/tests/ref/seek/lavf-mkv
> > @@ -1,48 +1,48 @@
> > -ret: 0         st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos:    661
> size:   208
> > +ret: 0         st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos:    797
> size:   208
> >  ret: 0         st:-1 flags:0  ts:-1.000000
> > -ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    877
> size: 27837
> > +ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1013
> size: 27837
> >  ret: 0         st:-1 flags:1  ts: 1.894167
> > -ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292291
> size: 27834
> > +ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292427
> size: 27834
> >  ret: 0         st: 0 flags:0  ts: 0.788000
> > -ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292291
> size: 27834
> > +ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292427
> size: 27834
> >  ret: 0         st: 0 flags:1  ts:-0.317000
> > -ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    877
> size: 27837
> > +ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1013
> size: 27837
> >  ret:-1         st: 1 flags:0  ts: 2.577000
> >  ret: 0         st: 1 flags:1  ts: 1.471000
> > -ret: 0         st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320132
> size:   209
> > +ret: 0         st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320268
> size:   209
> >  ret: 0         st:-1 flags:0  ts: 0.365002
> > -ret: 0         st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146844
> size: 27925
> > +ret: 0         st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146980
> size: 27925
> >  ret: 0         st:-1 flags:1  ts:-0.740831
> > -ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    877
> size: 27837
> > +ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1013
> size: 27837
> >  ret:-1         st: 0 flags:0  ts: 2.153000
> >  ret: 0         st: 0 flags:1  ts: 1.048000
> > -ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292291
> size: 27834
> > +ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292427
> size: 27834
> >  ret: 0         st: 1 flags:0  ts:-0.058000
> > -ret: 0         st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos:    661
> size:   208
> > +ret: 0         st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos:    797
> size:   208
> >  ret: 0         st: 1 flags:1  ts: 2.836000
> > -ret: 0         st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320132
> size:   209
> > +ret: 0         st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320268
> size:   209
> >  ret:-1         st:-1 flags:0  ts: 1.730004
> >  ret: 0         st:-1 flags:1  ts: 0.624171
> > -ret: 0         st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146844
> size: 27925
> > +ret: 0         st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146980
> size: 27925
> >  ret: 0         st: 0 flags:0  ts:-0.482000
> > -ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    877
> size: 27837
> > +ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1013
> size: 27837
> >  ret: 0         st: 0 flags:1  ts: 2.413000
> > -ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292291
> size: 27834
> > +ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292427
> size: 27834
> >  ret:-1         st: 1 flags:0  ts: 1.307000
> >  ret: 0         st: 1 flags:1  ts: 0.201000
> > -ret: 0         st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos:    661
> size:   208
> > +ret: 0         st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos:    797
> size:   208
> >  ret: 0         st:-1 flags:0  ts:-0.904994
> > -ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    877
> size: 27837
> > +ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1013
> size: 27837
> >  ret: 0         st:-1 flags:1  ts: 1.989173
> > -ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292291
> size: 27834
> > +ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292427
> size: 27834
> >  ret: 0         st: 0 flags:0  ts: 0.883000
> > -ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292291
> size: 27834
> > +ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292427
> size: 27834
> >  ret: 0         st: 0 flags:1  ts:-0.222000
> > -ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    877
> size: 27837
> > +ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1013
> size: 27837
> >  ret:-1         st: 1 flags:0  ts: 2.672000
> >  ret: 0         st: 1 flags:1  ts: 1.566000
> > -ret: 0         st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320132
> size:   209
> > +ret: 0         st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320268
> size:   209
> >  ret: 0         st:-1 flags:0  ts: 0.460008
> > -ret: 0         st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146844
> size: 27925
> > +ret: 0         st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146980
> size: 27925
> >  ret: 0         st:-1 flags:1  ts:-0.645825
> > -ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    877
> size: 27837
> > +ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1013
> size: 27837
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>


More information about the ffmpeg-devel mailing list