diff options
author | Vladimir Pantelic <vladoman@gmail.com> | 2013-09-19 17:50:38 +0200 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2013-09-19 19:51:49 +0200 |
commit | bb461370e34b1fa1637f34ce7d37b934ddb472d5 (patch) | |
tree | 315d642c3a3b27ccff52fa2ddd2ae02f6fe4755f /libavformat/asfenc.c | |
parent | 09f3c937ed6fd7c5bd64450d45f73b0f4975f4c9 (diff) | |
download | ffmpeg-bb461370e34b1fa1637f34ce7d37b934ddb472d5.tar.gz |
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 <vladoman@gmail.com>
Signed-off-by: Anton Khirnov <anton@khirnov.net>
Diffstat (limited to 'libavformat/asfenc.c')
-rw-r--r-- | libavformat/asfenc.c | 66 |
1 files changed, 65 insertions, 1 deletions
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; |