[FFmpeg-devel] [PATCH] libavformat/matroska: Write stream durations in metadata, in the format of mkvmerge.
Michael Niedermayer
michael at niedermayer.cc
Wed Aug 5 03:54:33 CEST 2015
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.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20150805/c7bec041/attachment.sig>
More information about the ffmpeg-devel
mailing list