From bb461370e34b1fa1637f34ce7d37b934ddb472d5 Mon Sep 17 00:00:00 2001 From: Vladimir Pantelic Date: Thu, 19 Sep 2013 17:50:38 +0200 Subject: [PATCH] asfenc: mux chapters in ASF files using an ASF "marker" section ASF markers only have a start time, so we lose the chapter end times, but that is ASF for you Signed-off-by: Vladimir Pantelic Signed-off-by: Anton Khirnov --- Changelog | 1 + libavformat/asfenc.c | 66 ++++++++++++++++++++++++++++++++++++++++++- libavformat/version.h | 2 +- 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/Changelog b/Changelog index 10ad63bf21..b0ff897459 100644 --- a/Changelog +++ b/Changelog @@ -36,6 +36,7 @@ version 10: - WebP decoder - Error Resilient AAC syntax (ER AAC LC) decoding - Low Delay AAC (ER AAC LD) decoding +- mux chapters in ASF files version 9: diff --git a/libavformat/asfenc.c b/libavformat/asfenc.c index 7e1594bc1d..e1a718966d 100644 --- a/libavformat/asfenc.c +++ b/libavformat/asfenc.c @@ -20,6 +20,7 @@ */ #include "libavutil/dict.h" +#include "libavutil/mathematics.h" #include "avformat.h" #include "avio_internal.h" #include "internal.h" @@ -287,6 +288,64 @@ static int64_t unix_to_file_time(int ti) return t; } +static int32_t get_send_time(ASFContext *asf, int64_t pres_time, uint64_t *offset) +{ + int i; + int32_t send_time = 0; + *offset = asf->data_offset + DATA_HEADER_SIZE; + for (i = 0; i < asf->nb_index_count; i++) { + if (pres_time <= asf->index_ptr[i].send_time) + break; + send_time = asf->index_ptr[i].send_time; + *offset = asf->index_ptr[i].offset; + } + + return send_time / 10000; +} + +static int asf_write_markers(AVFormatContext *s) +{ + ASFContext *asf = s->priv_data; + AVIOContext *pb = s->pb; + int i; + AVRational scale = {1, 10000000}; + int64_t hpos = put_header(pb, &ff_asf_marker_header); + + put_guid(pb, &ff_asf_reserved_4); // ASF spec mandates this reserved value + avio_wl32(pb, s->nb_chapters); // markers count + avio_wl16(pb, 0); // ASF spec mandates 0 for this + avio_wl16(pb, 0); // name length 0, no name given + + for (i = 0; i < s->nb_chapters; i++) { + AVChapter *c = s->chapters[i]; + AVDictionaryEntry *t = av_dict_get(c->metadata, "title", NULL, 0); + int64_t pres_time = av_rescale_q(c->start, c->time_base, scale); + uint64_t offset; + int32_t send_time = get_send_time(asf, pres_time, &offset); + int len = 0; + uint8_t *buf; + AVIOContext *dyn_buf; + if (t) { + if (avio_open_dyn_buf(&dyn_buf) < 0) + return AVERROR(ENOMEM); + avio_put_str16le(dyn_buf, t->value); + len = avio_close_dyn_buf(dyn_buf, &buf); + } + avio_wl64(pb, offset); // offset of the packet with send_time + avio_wl64(pb, pres_time + PREROLL_TIME * 10000); // presentation time + avio_wl16(pb, 12 + len); // entry length + avio_wl32(pb, send_time); // send time + avio_wl32(pb, 0); // flags, should be 0 + avio_wl32(pb, len / 2); // marker desc length in WCHARS! + if (t) { + avio_write(pb, buf, len); // marker desc + av_freep(&buf); + } + } + end_header(pb, hpos); + return 0; +} + /* write the header (used two times if non streamed) */ static int asf_write_header1(AVFormatContext *s, int64_t file_size, int64_t data_chunk_size) @@ -388,7 +447,12 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, } end_header(pb, hpos); } - + /* chapters using ASF markers */ + if (!asf->is_streamed && s->nb_chapters) { + int ret; + if (ret = asf_write_markers(s)) + return ret; + } /* stream headers */ for (n = 0; n < s->nb_streams; n++) { int64_t es_pos; diff --git a/libavformat/version.h b/libavformat/version.h index 53ce0606d4..6d8bd52f62 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #define LIBAVFORMAT_VERSION_MAJOR 55 #define LIBAVFORMAT_VERSION_MINOR 5 -#define LIBAVFORMAT_VERSION_MICRO 0 +#define LIBAVFORMAT_VERSION_MICRO 1 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \