* commit 'bb461370e34b1fa1637f34ce7d37b934ddb472d5':
asfenc: mux chapters in ASF files using an ASF "marker" section
Conflicts:
Changelog
libavformat/version.h
Merged-by: Michael Niedermayer <michaelni@gmx.at>
... | ... |
@@ -21,6 +21,7 @@ |
21 | 21 |
|
22 | 22 |
#include "libavutil/avassert.h" |
23 | 23 |
#include "libavutil/dict.h" |
24 |
+#include "libavutil/mathematics.h" |
|
24 | 25 |
#include "avformat.h" |
25 | 26 |
#include "avio_internal.h" |
26 | 27 |
#include "internal.h" |
... | ... |
@@ -291,6 +292,64 @@ static int64_t unix_to_file_time(int ti) |
291 | 291 |
return t; |
292 | 292 |
} |
293 | 293 |
|
294 |
+static int32_t get_send_time(ASFContext *asf, int64_t pres_time, uint64_t *offset) |
|
295 |
+{ |
|
296 |
+ int i; |
|
297 |
+ int32_t send_time = 0; |
|
298 |
+ *offset = asf->data_offset + DATA_HEADER_SIZE; |
|
299 |
+ for (i = 0; i < asf->next_start_sec; i++) { |
|
300 |
+ if (pres_time <= asf->index_ptr[i].send_time) |
|
301 |
+ break; |
|
302 |
+ send_time = asf->index_ptr[i].send_time; |
|
303 |
+ *offset = asf->index_ptr[i].offset; |
|
304 |
+ } |
|
305 |
+ |
|
306 |
+ return send_time / 10000; |
|
307 |
+} |
|
308 |
+ |
|
309 |
+static int asf_write_markers(AVFormatContext *s) |
|
310 |
+{ |
|
311 |
+ ASFContext *asf = s->priv_data; |
|
312 |
+ AVIOContext *pb = s->pb; |
|
313 |
+ int i; |
|
314 |
+ AVRational scale = {1, 10000000}; |
|
315 |
+ int64_t hpos = put_header(pb, &ff_asf_marker_header); |
|
316 |
+ |
|
317 |
+ ff_put_guid(pb, &ff_asf_reserved_4);// ASF spec mandates this reserved value |
|
318 |
+ avio_wl32(pb, s->nb_chapters); // markers count |
|
319 |
+ avio_wl16(pb, 0); // ASF spec mandates 0 for this |
|
320 |
+ avio_wl16(pb, 0); // name length 0, no name given |
|
321 |
+ |
|
322 |
+ for (i = 0; i < s->nb_chapters; i++) { |
|
323 |
+ AVChapter *c = s->chapters[i]; |
|
324 |
+ AVDictionaryEntry *t = av_dict_get(c->metadata, "title", NULL, 0); |
|
325 |
+ int64_t pres_time = av_rescale_q(c->start, c->time_base, scale); |
|
326 |
+ uint64_t offset; |
|
327 |
+ int32_t send_time = get_send_time(asf, pres_time, &offset); |
|
328 |
+ int len = 0; |
|
329 |
+ uint8_t *buf; |
|
330 |
+ AVIOContext *dyn_buf; |
|
331 |
+ if (t) { |
|
332 |
+ if (avio_open_dyn_buf(&dyn_buf) < 0) |
|
333 |
+ return AVERROR(ENOMEM); |
|
334 |
+ avio_put_str16le(dyn_buf, t->value); |
|
335 |
+ len = avio_close_dyn_buf(dyn_buf, &buf); |
|
336 |
+ } |
|
337 |
+ avio_wl64(pb, offset); // offset of the packet with send_time |
|
338 |
+ avio_wl64(pb, pres_time + PREROLL_TIME * 10000); // presentation time |
|
339 |
+ avio_wl16(pb, 12 + len); // entry length |
|
340 |
+ avio_wl32(pb, send_time); // send time |
|
341 |
+ avio_wl32(pb, 0); // flags, should be 0 |
|
342 |
+ avio_wl32(pb, len / 2); // marker desc length in WCHARS! |
|
343 |
+ if (t) { |
|
344 |
+ avio_write(pb, buf, len); // marker desc |
|
345 |
+ av_freep(&buf); |
|
346 |
+ } |
|
347 |
+ } |
|
348 |
+ end_header(pb, hpos); |
|
349 |
+ return 0; |
|
350 |
+} |
|
351 |
+ |
|
294 | 352 |
/* write the header (used two times if non streamed) */ |
295 | 353 |
static int asf_write_header1(AVFormatContext *s, int64_t file_size, |
296 | 354 |
int64_t data_chunk_size) |
... | ... |
@@ -392,7 +451,12 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, |
392 | 392 |
} |
393 | 393 |
end_header(pb, hpos); |
394 | 394 |
} |
395 |
- |
|
395 |
+ /* chapters using ASF markers */ |
|
396 |
+ if (!asf->is_streamed && s->nb_chapters) { |
|
397 |
+ int ret; |
|
398 |
+ if (ret = asf_write_markers(s)) |
|
399 |
+ return ret; |
|
400 |
+ } |
|
396 | 401 |
/* stream headers */ |
397 | 402 |
for (n = 0; n < s->nb_streams; n++) { |
398 | 403 |
int64_t es_pos; |
... | ... |
@@ -31,7 +31,7 @@ |
31 | 31 |
|
32 | 32 |
#define LIBAVFORMAT_VERSION_MAJOR 55 |
33 | 33 |
#define LIBAVFORMAT_VERSION_MINOR 18 |
34 |
-#define LIBAVFORMAT_VERSION_MICRO 100 |
|
34 |
+#define LIBAVFORMAT_VERSION_MICRO 101 |
|
35 | 35 |
|
36 | 36 |
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ |
37 | 37 |
LIBAVFORMAT_VERSION_MINOR, \ |