aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat/asfenc.c
diff options
context:
space:
mode:
authorVladimir Pantelic <vladoman@gmail.com>2013-09-19 17:50:38 +0200
committerAnton Khirnov <anton@khirnov.net>2013-09-19 19:51:49 +0200
commitbb461370e34b1fa1637f34ce7d37b934ddb472d5 (patch)
tree315d642c3a3b27ccff52fa2ddd2ae02f6fe4755f /libavformat/asfenc.c
parent09f3c937ed6fd7c5bd64450d45f73b0f4975f4c9 (diff)
downloadffmpeg-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.c66
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;