blob: f7000b0413525a6777e84a73e8677b436ba7ccd3
1 | /* |
2 | * Microsoft Advanced Streaming Format demuxer |
3 | * Copyright (c) 2014 Alexandra Hájková |
4 | * |
5 | * This file is part of FFmpeg. |
6 | * |
7 | * FFmpeg is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2.1 of the License, or (at your option) any later version. |
11 | * |
12 | * FFmpeg is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Lesser General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Lesser General Public |
18 | * License along with FFmpeg; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | */ |
21 | |
22 | #include "libavutil/attributes.h" |
23 | #include "libavutil/avstring.h" |
24 | #include "libavutil/bswap.h" |
25 | #include "libavutil/common.h" |
26 | #include "libavutil/dict.h" |
27 | #include "libavutil/internal.h" |
28 | #include "libavutil/mathematics.h" |
29 | #include "libavutil/opt.h" |
30 | #include "libavutil/time_internal.h" |
31 | |
32 | #include "avformat.h" |
33 | #include "avio_internal.h" |
34 | #include "avlanguage.h" |
35 | #include "id3v2.h" |
36 | #include "internal.h" |
37 | #include "riff.h" |
38 | #include "asf.h" |
39 | #include "asfcrypt.h" |
40 | |
41 | #define ASF_BOOL 0x2 |
42 | #define ASF_WORD 0x5 |
43 | #define ASF_GUID 0x6 |
44 | #define ASF_DWORD 0x3 |
45 | #define ASF_QWORD 0x4 |
46 | #define ASF_UNICODE 0x0 |
47 | #define ASF_FLAG_BROADCAST 0x1 |
48 | #define ASF_BYTE_ARRAY 0x1 |
49 | #define ASF_TYPE_AUDIO 0x2 |
50 | #define ASF_TYPE_VIDEO 0x1 |
51 | #define ASF_STREAM_NUM 0x7F |
52 | #define ASF_MAX_STREAMS 128 |
53 | #define BMP_HEADER_SIZE 40 |
54 | #define ASF_NUM_OF_PAYLOADS 0x3F |
55 | #define ASF_ERROR_CORRECTION_LENGTH_TYPE 0x60 |
56 | #define ASF_PACKET_ERROR_CORRECTION_DATA_SIZE 0x2 |
57 | |
58 | typedef struct GUIDParseTable { |
59 | const char *name; |
60 | ff_asf_guid guid; |
61 | int (*read_object)(AVFormatContext *, const struct GUIDParseTable *); |
62 | int is_subobject; |
63 | } GUIDParseTable; |
64 | |
65 | typedef struct ASFPacket { |
66 | AVPacket avpkt; |
67 | int64_t dts; |
68 | uint32_t frame_num; // ASF payloads with the same number are parts of the same frame |
69 | int flags; |
70 | int data_size; |
71 | int duration; |
72 | int size_left; |
73 | uint8_t stream_index; |
74 | } ASFPacket; |
75 | |
76 | typedef struct ASFStream { |
77 | uint8_t stream_index; // from packet header |
78 | int index; // stream index in AVFormatContext, set in asf_read_stream_properties |
79 | int type; |
80 | int indexed; // added index entries from the Simple Index Object or not |
81 | int8_t span; // for deinterleaving |
82 | uint16_t virtual_pkt_len; |
83 | uint16_t virtual_chunk_len; |
84 | int16_t lang_idx; |
85 | ASFPacket pkt; |
86 | } ASFStream; |
87 | |
88 | typedef struct ASFStreamData{ |
89 | char langs[32]; |
90 | AVDictionary *asf_met; // for storing per-stream metadata |
91 | AVRational aspect_ratio; |
92 | } ASFStreamData; |
93 | |
94 | typedef struct ASFContext { |
95 | int data_reached; |
96 | int is_simple_index; // is simple index present or not 1/0 |
97 | int is_header; |
98 | |
99 | uint64_t preroll; |
100 | uint64_t nb_packets; // ASF packets |
101 | uint32_t packet_size; |
102 | int64_t send_time; |
103 | int duration; |
104 | |
105 | uint32_t b_flags; // flags with broadcast flag |
106 | uint32_t prop_flags; // file properties object flags |
107 | |
108 | uint64_t data_size; // data object size |
109 | uint64_t unknown_size; // size of the unknown object |
110 | |
111 | int64_t offset; // offset of the current object |
112 | |
113 | int64_t data_offset; |
114 | int64_t first_packet_offset; // packet offset |
115 | int64_t unknown_offset; // for top level header objects or subobjects without specified behavior |
116 | |
117 | // ASF file must not contain more than 128 streams according to the specification |
118 | ASFStream *asf_st[ASF_MAX_STREAMS]; |
119 | ASFStreamData asf_sd[ASF_MAX_STREAMS]; |
120 | int nb_streams; |
121 | |
122 | int stream_index; // from packet header, for the subpayload case |
123 | |
124 | // packet parameters |
125 | uint64_t sub_header_offset; // offset of subpayload header |
126 | int64_t sub_dts; |
127 | uint8_t dts_delta; // for subpayloads |
128 | uint32_t packet_size_internal; // packet size stored inside ASFPacket, can be 0 |
129 | int64_t packet_offset; // offset of the current packet inside Data Object |
130 | uint32_t pad_len; // padding after payload |
131 | uint32_t rep_data_len; |
132 | |
133 | // packet state |
134 | uint64_t sub_left; // subpayloads left or not |
135 | unsigned int nb_sub; // number of subpayloads read so far from the current ASF packet |
136 | uint16_t mult_sub_len; // total length of subpayloads array inside multiple payload |
137 | uint64_t nb_mult_left; // multiple payloads left |
138 | int return_subpayload; |
139 | enum { |
140 | PARSE_PACKET_HEADER, |
141 | READ_SINGLE, |
142 | READ_MULTI, |
143 | READ_MULTI_SUB |
144 | } state; |
145 | } ASFContext; |
146 | |
147 | static int detect_unknown_subobject(AVFormatContext *s, int64_t offset, int64_t size); |
148 | static const GUIDParseTable *find_guid(ff_asf_guid guid); |
149 | |
150 | static int asf_probe(AVProbeData *pd) |
151 | { |
152 | /* check file header */ |
153 | if (!ff_guidcmp(pd->buf, &ff_asf_header)) |
154 | return AVPROBE_SCORE_MAX/2; |
155 | else |
156 | return 0; |
157 | } |
158 | |
159 | static void swap_guid(ff_asf_guid guid) |
160 | { |
161 | FFSWAP(unsigned char, guid[0], guid[3]); |
162 | FFSWAP(unsigned char, guid[1], guid[2]); |
163 | FFSWAP(unsigned char, guid[4], guid[5]); |
164 | FFSWAP(unsigned char, guid[6], guid[7]); |
165 | } |
166 | |
167 | static void align_position(AVIOContext *pb, int64_t offset, uint64_t size) |
168 | { |
169 | if (size < INT64_MAX - offset && avio_tell(pb) != offset + size) |
170 | avio_seek(pb, offset + size, SEEK_SET); |
171 | } |
172 | |
173 | static int asf_read_unknown(AVFormatContext *s, const GUIDParseTable *g) |
174 | { |
175 | ASFContext *asf = s->priv_data; |
176 | AVIOContext *pb = s->pb; |
177 | uint64_t size = avio_rl64(pb); |
178 | int ret; |
179 | |
180 | if (size > INT64_MAX) |
181 | return AVERROR_INVALIDDATA; |
182 | |
183 | if (asf->is_header) |
184 | asf->unknown_size = size; |
185 | asf->is_header = 0; |
186 | if (!g->is_subobject) { |
187 | if (!(ret = strcmp(g->name, "Header Extension"))) |
188 | avio_skip(pb, 22); // skip reserved fields and Data Size |
189 | if ((ret = detect_unknown_subobject(s, asf->unknown_offset, |
190 | asf->unknown_size)) < 0) |
191 | return ret; |
192 | } else { |
193 | if (size < 24) { |
194 | av_log(s, AV_LOG_ERROR, "Too small size %"PRIu64" (< 24).\n", size); |
195 | return AVERROR_INVALIDDATA; |
196 | } |
197 | avio_skip(pb, size - 24); |
198 | } |
199 | |
200 | return 0; |
201 | } |
202 | |
203 | static int get_asf_string(AVIOContext *pb, int maxlen, char *buf, int buflen) |
204 | { |
205 | char *q = buf; |
206 | int ret = 0; |
207 | if (buflen <= 0) |
208 | return AVERROR(EINVAL); |
209 | while (ret + 1 < maxlen) { |
210 | uint8_t tmp; |
211 | uint32_t ch; |
212 | GET_UTF16(ch, (ret += 2) <= maxlen ? avio_rl16(pb) : 0, break;); |
213 | PUT_UTF8(ch, tmp, if (q - buf < buflen - 1) *q++ = tmp;) |
214 | } |
215 | *q = 0; |
216 | |
217 | return ret; |
218 | } |
219 | |
220 | static int asf_read_marker(AVFormatContext *s, const GUIDParseTable *g) |
221 | { |
222 | ASFContext *asf = s->priv_data; |
223 | AVIOContext *pb = s->pb; |
224 | uint64_t size = avio_rl64(pb); |
225 | int i, nb_markers, ret; |
226 | size_t len; |
227 | char name[1024]; |
228 | |
229 | avio_skip(pb, 8); |
230 | avio_skip(pb, 8); // skip reserved GUID |
231 | nb_markers = avio_rl32(pb); |
232 | avio_skip(pb, 2); // skip reserved field |
233 | len = avio_rl16(pb); |
234 | for (i = 0; i < len; i++) |
235 | avio_skip(pb, 1); |
236 | |
237 | for (i = 0; i < nb_markers; i++) { |
238 | int64_t pts; |
239 | |
240 | avio_skip(pb, 8); |
241 | pts = avio_rl64(pb); |
242 | pts -= asf->preroll * 10000; |
243 | avio_skip(pb, 2); // entry length |
244 | avio_skip(pb, 4); // send time |
245 | avio_skip(pb, 4); // flags |
246 | len = avio_rl32(pb); |
247 | |
248 | if ((ret = avio_get_str16le(pb, len, name, |
249 | sizeof(name))) < len) |
250 | avio_skip(pb, len - ret); |
251 | avpriv_new_chapter(s, i, (AVRational) { 1, 10000000 }, pts, |
252 | AV_NOPTS_VALUE, name); |
253 | } |
254 | align_position(pb, asf->offset, size); |
255 | |
256 | return 0; |
257 | } |
258 | |
259 | static int asf_read_metadata(AVFormatContext *s, const char *title, uint16_t len, |
260 | unsigned char *ch, uint16_t buflen) |
261 | { |
262 | AVIOContext *pb = s->pb; |
263 | |
264 | avio_get_str16le(pb, len, ch, buflen); |
265 | if (ch[0]) { |
266 | if (av_dict_set(&s->metadata, title, ch, 0) < 0) |
267 | av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n"); |
268 | } |
269 | |
270 | return 0; |
271 | } |
272 | |
273 | static int asf_read_value(AVFormatContext *s, const uint8_t *name, |
274 | uint16_t val_len, int type, AVDictionary **met) |
275 | { |
276 | int ret; |
277 | uint8_t *value; |
278 | uint16_t buflen = 2 * val_len + 1; |
279 | AVIOContext *pb = s->pb; |
280 | |
281 | value = av_malloc(buflen); |
282 | if (!value) |
283 | return AVERROR(ENOMEM); |
284 | if (type == ASF_UNICODE) { |
285 | // get_asf_string reads UTF-16 and converts it to UTF-8 which needs longer buffer |
286 | if ((ret = get_asf_string(pb, val_len, value, buflen)) < 0) |
287 | goto failed; |
288 | if (av_dict_set(met, name, value, 0) < 0) |
289 | av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n"); |
290 | } else { |
291 | char buf[256]; |
292 | if (val_len > sizeof(buf)) { |
293 | ret = AVERROR_INVALIDDATA; |
294 | goto failed; |
295 | } |
296 | if ((ret = avio_read(pb, value, val_len)) < 0) |
297 | goto failed; |
298 | if (ret < 2 * val_len) |
299 | value[ret] = '\0'; |
300 | else |
301 | value[2 * val_len - 1] = '\0'; |
302 | snprintf(buf, sizeof(buf), "%s", value); |
303 | if (av_dict_set(met, name, buf, 0) < 0) |
304 | av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n"); |
305 | } |
306 | av_freep(&value); |
307 | |
308 | return 0; |
309 | |
310 | failed: |
311 | av_freep(&value); |
312 | return ret; |
313 | } |
314 | static int asf_read_generic_value(AVIOContext *pb, int type, uint64_t *value) |
315 | { |
316 | |
317 | switch (type) { |
318 | case ASF_BOOL: |
319 | *value = avio_rl16(pb); |
320 | break; |
321 | case ASF_DWORD: |
322 | *value = avio_rl32(pb); |
323 | break; |
324 | case ASF_QWORD: |
325 | *value = avio_rl64(pb); |
326 | break; |
327 | case ASF_WORD: |
328 | *value = avio_rl16(pb); |
329 | break; |
330 | default: |
331 | return AVERROR_INVALIDDATA; |
332 | } |
333 | |
334 | return 0; |
335 | } |
336 | |
337 | static int asf_set_metadata(AVFormatContext *s, const uint8_t *name, |
338 | int type, AVDictionary **met) |
339 | { |
340 | AVIOContext *pb = s->pb; |
341 | uint64_t value; |
342 | char buf[32]; |
343 | int ret; |
344 | |
345 | ret = asf_read_generic_value(pb, type, &value); |
346 | if (ret < 0) |
347 | return ret; |
348 | |
349 | snprintf(buf, sizeof(buf), "%"PRIu64, value); |
350 | if (av_dict_set(met, name, buf, 0) < 0) |
351 | av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n"); |
352 | |
353 | return 0; |
354 | } |
355 | |
356 | /* MSDN claims that this should be "compatible with the ID3 frame, APIC", |
357 | * but in reality this is only loosely similar */ |
358 | static int asf_read_picture(AVFormatContext *s, int len) |
359 | { |
360 | ASFContext *asf = s->priv_data; |
361 | AVPacket pkt = { 0 }; |
362 | const CodecMime *mime = ff_id3v2_mime_tags; |
363 | enum AVCodecID id = AV_CODEC_ID_NONE; |
364 | char mimetype[64]; |
365 | uint8_t *desc = NULL; |
366 | AVStream *st = NULL; |
367 | int ret, type, picsize, desc_len; |
368 | ASFStream *asf_st; |
369 | |
370 | /* type + picsize + mime + desc */ |
371 | if (len < 1 + 4 + 2 + 2) { |
372 | av_log(s, AV_LOG_ERROR, "Invalid attached picture size: %d.\n", len); |
373 | return AVERROR_INVALIDDATA; |
374 | } |
375 | |
376 | /* picture type */ |
377 | type = avio_r8(s->pb); |
378 | len--; |
379 | if (type >= FF_ARRAY_ELEMS(ff_id3v2_picture_types) || type < 0) { |
380 | av_log(s, AV_LOG_WARNING, "Unknown attached picture type: %d.\n", type); |
381 | type = 0; |
382 | } |
383 | |
384 | /* picture data size */ |
385 | picsize = avio_rl32(s->pb); |
386 | len -= 4; |
387 | |
388 | /* picture MIME type */ |
389 | len -= avio_get_str16le(s->pb, len, mimetype, sizeof(mimetype)); |
390 | while (mime->id != AV_CODEC_ID_NONE) { |
391 | if (!strncmp(mime->str, mimetype, sizeof(mimetype))) { |
392 | id = mime->id; |
393 | break; |
394 | } |
395 | mime++; |
396 | } |
397 | if (id == AV_CODEC_ID_NONE) { |
398 | av_log(s, AV_LOG_ERROR, "Unknown attached picture mimetype: %s.\n", |
399 | mimetype); |
400 | return 0; |
401 | } |
402 | |
403 | if (picsize >= len) { |
404 | av_log(s, AV_LOG_ERROR, "Invalid attached picture data size: %d >= %d.\n", |
405 | picsize, len); |
406 | return AVERROR_INVALIDDATA; |
407 | } |
408 | |
409 | /* picture description */ |
410 | desc_len = (len - picsize) * 2 + 1; |
411 | desc = av_malloc(desc_len); |
412 | if (!desc) |
413 | return AVERROR(ENOMEM); |
414 | len -= avio_get_str16le(s->pb, len - picsize, desc, desc_len); |
415 | |
416 | ret = av_get_packet(s->pb, &pkt, picsize); |
417 | if (ret < 0) |
418 | goto fail; |
419 | |
420 | st = avformat_new_stream(s, NULL); |
421 | if (!st) { |
422 | ret = AVERROR(ENOMEM); |
423 | goto fail; |
424 | } |
425 | asf->asf_st[asf->nb_streams] = av_mallocz(sizeof(*asf_st)); |
426 | asf_st = asf->asf_st[asf->nb_streams]; |
427 | if (!asf_st) { |
428 | ret = AVERROR(ENOMEM); |
429 | goto fail; |
430 | } |
431 | |
432 | st->disposition |= AV_DISPOSITION_ATTACHED_PIC; |
433 | st->codecpar->codec_type = asf_st->type = AVMEDIA_TYPE_VIDEO; |
434 | st->codecpar->codec_id = id; |
435 | st->attached_pic = pkt; |
436 | st->attached_pic.stream_index = asf_st->index = st->index; |
437 | st->attached_pic.flags |= AV_PKT_FLAG_KEY; |
438 | |
439 | asf->nb_streams++; |
440 | |
441 | if (*desc) { |
442 | if (av_dict_set(&st->metadata, "title", desc, AV_DICT_DONT_STRDUP_VAL) < 0) |
443 | av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n"); |
444 | } else |
445 | av_freep(&desc); |
446 | |
447 | if (av_dict_set(&st->metadata, "comment", ff_id3v2_picture_types[type], 0) < 0) |
448 | av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n"); |
449 | |
450 | return 0; |
451 | |
452 | fail: |
453 | av_freep(&desc); |
454 | av_packet_unref(&pkt); |
455 | return ret; |
456 | } |
457 | |
458 | static void get_id3_tag(AVFormatContext *s, int len) |
459 | { |
460 | ID3v2ExtraMeta *id3v2_extra_meta = NULL; |
461 | |
462 | ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, len); |
463 | if (id3v2_extra_meta) |
464 | ff_id3v2_parse_apic(s, &id3v2_extra_meta); |
465 | ff_id3v2_free_extra_meta(&id3v2_extra_meta); |
466 | } |
467 | |
468 | static int process_metadata(AVFormatContext *s, const uint8_t *name, uint16_t name_len, |
469 | uint16_t val_len, uint16_t type, AVDictionary **met) |
470 | { |
471 | int ret; |
472 | ff_asf_guid guid; |
473 | |
474 | if (val_len) { |
475 | switch (type) { |
476 | case ASF_UNICODE: |
477 | asf_read_value(s, name, val_len, type, met); |
478 | break; |
479 | case ASF_BYTE_ARRAY: |
480 | if (!strcmp(name, "WM/Picture")) // handle cover art |
481 | asf_read_picture(s, val_len); |
482 | else if (!strcmp(name, "ID3")) // handle ID3 tag |
483 | get_id3_tag(s, val_len); |
484 | else |
485 | asf_read_value(s, name, val_len, type, met); |
486 | break; |
487 | case ASF_GUID: |
488 | ff_get_guid(s->pb, &guid); |
489 | break; |
490 | default: |
491 | if ((ret = asf_set_metadata(s, name, type, met)) < 0) |
492 | return ret; |
493 | break; |
494 | } |
495 | } |
496 | |
497 | return 0; |
498 | } |
499 | |
500 | static int asf_read_ext_content(AVFormatContext *s, const GUIDParseTable *g) |
501 | { |
502 | ASFContext *asf = s->priv_data; |
503 | AVIOContext *pb = s->pb; |
504 | uint64_t size = avio_rl64(pb); |
505 | uint16_t nb_desc = avio_rl16(pb); |
506 | int i, ret; |
507 | |
508 | for (i = 0; i < nb_desc; i++) { |
509 | uint16_t name_len, type, val_len; |
510 | uint8_t *name = NULL; |
511 | |
512 | name_len = avio_rl16(pb); |
513 | if (!name_len) |
514 | return AVERROR_INVALIDDATA; |
515 | name = av_malloc(name_len); |
516 | if (!name) |
517 | return AVERROR(ENOMEM); |
518 | avio_get_str16le(pb, name_len, name, |
519 | name_len); |
520 | type = avio_rl16(pb); |
521 | // BOOL values are 16 bits long in the Metadata Object |
522 | // but 32 bits long in the Extended Content Description Object |
523 | if (type == ASF_BOOL) |
524 | type = ASF_DWORD; |
525 | val_len = avio_rl16(pb); |
526 | |
527 | ret = process_metadata(s, name, name_len, val_len, type, &s->metadata); |
528 | av_freep(&name); |
529 | if (ret < 0) |
530 | return ret; |
531 | } |
532 | |
533 | align_position(pb, asf->offset, size); |
534 | return 0; |
535 | } |
536 | |
537 | static AVStream *find_stream(AVFormatContext *s, uint16_t st_num) |
538 | { |
539 | AVStream *st = NULL; |
540 | ASFContext *asf = s->priv_data; |
541 | int i; |
542 | |
543 | for (i = 0; i < asf->nb_streams; i++) { |
544 | if (asf->asf_st[i]->stream_index == st_num) { |
545 | st = s->streams[asf->asf_st[i]->index]; |
546 | break; |
547 | } |
548 | } |
549 | |
550 | return st; |
551 | } |
552 | |
553 | static int asf_store_aspect_ratio(AVFormatContext *s, uint8_t st_num, uint8_t *name, int type) |
554 | { |
555 | ASFContext *asf = s->priv_data; |
556 | AVIOContext *pb = s->pb; |
557 | uint64_t value = 0; |
558 | int ret; |
559 | |
560 | ret = asf_read_generic_value(pb, type, &value); |
561 | if (ret < 0) |
562 | return ret; |
563 | |
564 | if (st_num < ASF_MAX_STREAMS) { |
565 | if (!strcmp(name, "AspectRatioX")) |
566 | asf->asf_sd[st_num].aspect_ratio.num = value; |
567 | else |
568 | asf->asf_sd[st_num].aspect_ratio.den = value; |
569 | } |
570 | return 0; |
571 | } |
572 | |
573 | static int asf_read_metadata_obj(AVFormatContext *s, const GUIDParseTable *g) |
574 | { |
575 | ASFContext *asf = s->priv_data; |
576 | AVIOContext *pb = s->pb; |
577 | uint64_t size = avio_rl64(pb); |
578 | uint16_t nb_recs = avio_rl16(pb); // number of records in the Description Records list |
579 | int i, ret; |
580 | |
581 | for (i = 0; i < nb_recs; i++) { |
582 | uint16_t name_len, buflen, type, val_len, st_num; |
583 | uint8_t *name = NULL; |
584 | |
585 | avio_skip(pb, 2); // skip reserved field |
586 | st_num = avio_rl16(pb); |
587 | name_len = avio_rl16(pb); |
588 | buflen = 2 * name_len + 1; |
589 | if (!name_len) |
590 | break; |
591 | type = avio_rl16(pb); |
592 | val_len = avio_rl32(pb); |
593 | name = av_malloc(buflen); |
594 | if (!name) |
595 | return AVERROR(ENOMEM); |
596 | avio_get_str16le(pb, name_len, name, |
597 | buflen); |
598 | if (!strcmp(name, "AspectRatioX") || !strcmp(name, "AspectRatioY")) { |
599 | ret = asf_store_aspect_ratio(s, st_num, name, type); |
600 | if (ret < 0) { |
601 | av_freep(&name); |
602 | break; |
603 | } |
604 | } else { |
605 | if (st_num < ASF_MAX_STREAMS) { |
606 | if ((ret = process_metadata(s, name, name_len, val_len, type, |
607 | &asf->asf_sd[st_num].asf_met)) < 0) { |
608 | av_freep(&name); |
609 | break; |
610 | } |
611 | } |
612 | } |
613 | av_freep(&name); |
614 | } |
615 | |
616 | align_position(pb, asf->offset, size); |
617 | return 0; |
618 | } |
619 | |
620 | static int asf_read_content_desc(AVFormatContext *s, const GUIDParseTable *g) |
621 | { |
622 | ASFContext *asf = s->priv_data; |
623 | AVIOContext *pb = s->pb; |
624 | int i; |
625 | static const char *const titles[] = |
626 | { "Title", "Author", "Copyright", "Description", "Rate" }; |
627 | uint16_t len[5], buflen[5] = { 0 }; |
628 | uint8_t *ch; |
629 | uint64_t size = avio_rl64(pb); |
630 | |
631 | for (i = 0; i < 5; i++) { |
632 | len[i] = avio_rl16(pb); |
633 | // utf8 string should be <= 2 * utf16 string, extra byte for the terminator |
634 | buflen[i] = 2 * len[i] + 1; |
635 | } |
636 | |
637 | for (i = 0; i < 5; i++) { |
638 | ch = av_malloc(buflen[i]); |
639 | if (!ch) |
640 | return(AVERROR(ENOMEM)); |
641 | asf_read_metadata(s, titles[i], len[i], ch, buflen[i]); |
642 | av_freep(&ch); |
643 | } |
644 | align_position(pb, asf->offset, size); |
645 | |
646 | return 0; |
647 | } |
648 | |
649 | static int asf_read_properties(AVFormatContext *s, const GUIDParseTable *g) |
650 | { |
651 | ASFContext *asf = s->priv_data; |
652 | AVIOContext *pb = s->pb; |
653 | time_t creation_time; |
654 | |
655 | avio_rl64(pb); // read object size |
656 | avio_skip(pb, 16); // skip File ID |
657 | avio_skip(pb, 8); // skip File size |
658 | creation_time = avio_rl64(pb); |
659 | if (!(asf->b_flags & ASF_FLAG_BROADCAST)) { |
660 | struct tm tmbuf; |
661 | struct tm *tm; |
662 | char buf[64]; |
663 | |
664 | // creation date is in 100 ns units from 1 Jan 1601, conversion to s |
665 | creation_time /= 10000000; |
666 | // there are 11644473600 seconds between 1 Jan 1601 and 1 Jan 1970 |
667 | creation_time -= 11644473600; |
668 | tm = gmtime_r(&creation_time, &tmbuf); |
669 | if (tm) { |
670 | if (!strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm)) |
671 | buf[0] = '\0'; |
672 | } else |
673 | buf[0] = '\0'; |
674 | if (buf[0]) { |
675 | if (av_dict_set(&s->metadata, "creation_time", buf, 0) < 0) |
676 | av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n"); |
677 | } |
678 | } |
679 | asf->nb_packets = avio_rl64(pb); |
680 | asf->duration = avio_rl64(pb) / 10000; // stream duration |
681 | avio_skip(pb, 8); // skip send duration |
682 | asf->preroll = avio_rl64(pb); |
683 | asf->duration -= asf->preroll; |
684 | asf->b_flags = avio_rl32(pb); |
685 | avio_skip(pb, 4); // skip minimal packet size |
686 | asf->packet_size = avio_rl32(pb); |
687 | avio_skip(pb, 4); // skip max_bitrate |
688 | |
689 | return 0; |
690 | } |
691 | |
692 | static int parse_video_info(AVIOContext *pb, AVStream *st) |
693 | { |
694 | uint16_t size; |
695 | unsigned int tag; |
696 | |
697 | st->codecpar->width = avio_rl32(pb); |
698 | st->codecpar->height = avio_rl32(pb); |
699 | avio_skip(pb, 1); // skip reserved flags |
700 | size = avio_rl16(pb); // size of the Format Data |
701 | tag = ff_get_bmp_header(pb, st, NULL); |
702 | st->codecpar->codec_tag = tag; |
703 | st->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag); |
704 | |
705 | if (size > BMP_HEADER_SIZE) { |
706 | int ret; |
707 | st->codecpar->extradata_size = size - BMP_HEADER_SIZE; |
708 | if (!(st->codecpar->extradata = av_malloc(st->codecpar->extradata_size + |
709 | AV_INPUT_BUFFER_PADDING_SIZE))) { |
710 | st->codecpar->extradata_size = 0; |
711 | return AVERROR(ENOMEM); |
712 | } |
713 | memset(st->codecpar->extradata + st->codecpar->extradata_size , 0, |
714 | AV_INPUT_BUFFER_PADDING_SIZE); |
715 | if ((ret = avio_read(pb, st->codecpar->extradata, |
716 | st->codecpar->extradata_size)) < 0) |
717 | return ret; |
718 | } |
719 | return 0; |
720 | } |
721 | |
722 | static int asf_read_stream_properties(AVFormatContext *s, const GUIDParseTable *g) |
723 | { |
724 | ASFContext *asf = s->priv_data; |
725 | AVIOContext *pb = s->pb; |
726 | uint64_t size; |
727 | uint32_t err_data_len, ts_data_len; // type specific data length |
728 | uint16_t flags; |
729 | ff_asf_guid stream_type; |
730 | enum AVMediaType type; |
731 | int i, ret; |
732 | uint8_t stream_index; |
733 | AVStream *st; |
734 | ASFStream *asf_st; |
735 | |
736 | // ASF file must not contain more than 128 streams according to the specification |
737 | if (asf->nb_streams >= ASF_MAX_STREAMS) |
738 | return AVERROR_INVALIDDATA; |
739 | |
740 | size = avio_rl64(pb); |
741 | ff_get_guid(pb, &stream_type); |
742 | if (!ff_guidcmp(&stream_type, &ff_asf_audio_stream)) |
743 | type = AVMEDIA_TYPE_AUDIO; |
744 | else if (!ff_guidcmp(&stream_type, &ff_asf_video_stream)) |
745 | type = AVMEDIA_TYPE_VIDEO; |
746 | else if (!ff_guidcmp(&stream_type, &ff_asf_jfif_media)) |
747 | type = AVMEDIA_TYPE_VIDEO; |
748 | else if (!ff_guidcmp(&stream_type, &ff_asf_command_stream)) |
749 | type = AVMEDIA_TYPE_DATA; |
750 | else if (!ff_guidcmp(&stream_type, |
751 | &ff_asf_ext_stream_embed_stream_header)) |
752 | type = AVMEDIA_TYPE_UNKNOWN; |
753 | else |
754 | return AVERROR_INVALIDDATA; |
755 | |
756 | ff_get_guid(pb, &stream_type); // error correction type |
757 | avio_skip(pb, 8); // skip the time offset |
758 | ts_data_len = avio_rl32(pb); |
759 | err_data_len = avio_rl32(pb); |
760 | flags = avio_rl16(pb); // bit 15 - Encrypted Content |
761 | |
762 | stream_index = flags & ASF_STREAM_NUM; |
763 | for (i = 0; i < asf->nb_streams; i++) |
764 | if (stream_index == asf->asf_st[i]->stream_index) { |
765 | av_log(s, AV_LOG_WARNING, |
766 | "Duplicate stream found, this stream will be ignored.\n"); |
767 | align_position(pb, asf->offset, size); |
768 | return 0; |
769 | } |
770 | |
771 | st = avformat_new_stream(s, NULL); |
772 | if (!st) |
773 | return AVERROR(ENOMEM); |
774 | avpriv_set_pts_info(st, 32, 1, 1000); // pts should be dword, in milliseconds |
775 | st->codecpar->codec_type = type; |
776 | asf->asf_st[asf->nb_streams] = av_mallocz(sizeof(*asf_st)); |
777 | if (!asf->asf_st[asf->nb_streams]) |
778 | return AVERROR(ENOMEM); |
779 | asf_st = asf->asf_st[asf->nb_streams]; |
780 | asf->nb_streams++; |
781 | asf_st->stream_index = stream_index; |
782 | asf_st->index = st->index; |
783 | asf_st->indexed = 0; |
784 | st->id = flags & ASF_STREAM_NUM; |
785 | av_init_packet(&asf_st->pkt.avpkt); |
786 | asf_st->pkt.data_size = 0; |
787 | avio_skip(pb, 4); // skip reserved field |
788 | |
789 | switch (type) { |
790 | case AVMEDIA_TYPE_AUDIO: |
791 | asf_st->type = AVMEDIA_TYPE_AUDIO; |
792 | if ((ret = ff_get_wav_header(s, pb, st->codecpar, ts_data_len, 0)) < 0) |
793 | return ret; |
794 | break; |
795 | case AVMEDIA_TYPE_VIDEO: |
796 | asf_st->type = AVMEDIA_TYPE_VIDEO; |
797 | if ((ret = parse_video_info(pb, st)) < 0) |
798 | return ret; |
799 | break; |
800 | default: |
801 | avio_skip(pb, ts_data_len); |
802 | break; |
803 | } |
804 | |
805 | if (err_data_len) { |
806 | if (type == AVMEDIA_TYPE_AUDIO) { |
807 | uint8_t span = avio_r8(pb); |
808 | if (span > 1) { |
809 | asf_st->span = span; |
810 | asf_st->virtual_pkt_len = avio_rl16(pb); |
811 | asf_st->virtual_chunk_len = avio_rl16(pb); |
812 | if (!asf_st->virtual_chunk_len || !asf_st->virtual_pkt_len) |
813 | return AVERROR_INVALIDDATA; |
814 | avio_skip(pb, err_data_len - 5); |
815 | } else |
816 | avio_skip(pb, err_data_len - 1); |
817 | } else |
818 | avio_skip(pb, err_data_len); |
819 | } |
820 | |
821 | align_position(pb, asf->offset, size); |
822 | |
823 | return 0; |
824 | } |
825 | |
826 | static void set_language(AVFormatContext *s, const char *rfc1766, AVDictionary **met) |
827 | { |
828 | // language abbr should contain at least 2 chars |
829 | if (rfc1766 && strlen(rfc1766) > 1) { |
830 | const char primary_tag[3] = { rfc1766[0], rfc1766[1], '\0' }; // ignore country code if any |
831 | const char *iso6392 = ff_convert_lang_to(primary_tag, |
832 | AV_LANG_ISO639_2_BIBL); |
833 | if (iso6392) |
834 | if (av_dict_set(met, "language", iso6392, 0) < 0) |
835 | av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n"); |
836 | } |
837 | } |
838 | |
839 | static int asf_read_ext_stream_properties(AVFormatContext *s, const GUIDParseTable *g) |
840 | { |
841 | ASFContext *asf = s->priv_data; |
842 | AVIOContext *pb = s->pb; |
843 | AVStream *st = NULL; |
844 | ff_asf_guid guid; |
845 | uint16_t nb_st_name, nb_pay_exts, st_num, lang_idx; |
846 | int i, ret; |
847 | uint32_t bitrate; |
848 | uint64_t start_time, end_time, time_per_frame; |
849 | uint64_t size = avio_rl64(pb); |
850 | |
851 | start_time = avio_rl64(pb); |
852 | end_time = avio_rl64(pb); |
853 | bitrate = avio_rl32(pb); |
854 | avio_skip(pb, 28); // skip some unused values |
855 | st_num = avio_rl16(pb); |
856 | st_num &= ASF_STREAM_NUM; |
857 | lang_idx = avio_rl16(pb); // Stream Language ID Index |
858 | for (i = 0; i < asf->nb_streams; i++) { |
859 | if (st_num == asf->asf_st[i]->stream_index) { |
860 | st = s->streams[asf->asf_st[i]->index]; |
861 | asf->asf_st[i]->lang_idx = lang_idx; |
862 | break; |
863 | } |
864 | } |
865 | time_per_frame = avio_rl64(pb); // average time per frame |
866 | if (st) { |
867 | st->start_time = start_time; |
868 | st->duration = end_time - start_time; |
869 | st->codecpar->bit_rate = bitrate; |
870 | st->avg_frame_rate.num = 10000000; |
871 | st->avg_frame_rate.den = time_per_frame; |
872 | } |
873 | nb_st_name = avio_rl16(pb); |
874 | nb_pay_exts = avio_rl16(pb); |
875 | for (i = 0; i < nb_st_name; i++) { |
876 | uint16_t len; |
877 | |
878 | avio_rl16(pb); // Language ID Index |
879 | len = avio_rl16(pb); |
880 | avio_skip(pb, len); |
881 | } |
882 | |
883 | for (i = 0; i < nb_pay_exts; i++) { |
884 | uint32_t len; |
885 | avio_skip(pb, 16); // Extension System ID |
886 | avio_skip(pb, 2); // Extension Data Size |
887 | len = avio_rl32(pb); |
888 | avio_skip(pb, len); |
889 | } |
890 | |
891 | if ((ret = ff_get_guid(pb, &guid)) < 0) { |
892 | align_position(pb, asf->offset, size); |
893 | |
894 | return 0; |
895 | } |
896 | |
897 | g = find_guid(guid); |
898 | if (g && !(strcmp(g->name, "Stream Properties"))) { |
899 | if ((ret = g->read_object(s, g)) < 0) |
900 | return ret; |
901 | } |
902 | |
903 | align_position(pb, asf->offset, size); |
904 | return 0; |
905 | } |
906 | |
907 | static int asf_read_language_list(AVFormatContext *s, const GUIDParseTable *g) |
908 | { |
909 | ASFContext *asf = s->priv_data; |
910 | AVIOContext *pb = s->pb; |
911 | int i, ret; |
912 | uint64_t size = avio_rl64(pb); |
913 | uint16_t nb_langs = avio_rl16(pb); |
914 | |
915 | if (nb_langs < ASF_MAX_STREAMS) { |
916 | for (i = 0; i < nb_langs; i++) { |
917 | size_t len; |
918 | len = avio_r8(pb); |
919 | if (!len) |
920 | len = 6; |
921 | if ((ret = get_asf_string(pb, len, asf->asf_sd[i].langs, |
922 | sizeof(asf->asf_sd[i].langs))) < 0) { |
923 | return ret; |
924 | } |
925 | } |
926 | } |
927 | |
928 | align_position(pb, asf->offset, size); |
929 | return 0; |
930 | } |
931 | |
932 | // returns data object offset when reading this object for the first time |
933 | static int asf_read_data(AVFormatContext *s, const GUIDParseTable *g) |
934 | { |
935 | ASFContext *asf = s->priv_data; |
936 | AVIOContext *pb = s->pb; |
937 | uint64_t size = asf->data_size = avio_rl64(pb); |
938 | int i; |
939 | |
940 | if (!asf->data_reached) { |
941 | asf->data_reached = 1; |
942 | asf->data_offset = asf->offset; |
943 | } |
944 | |
945 | for (i = 0; i < asf->nb_streams; i++) { |
946 | if (!(asf->b_flags & ASF_FLAG_BROADCAST)) |
947 | s->streams[i]->duration = asf->duration; |
948 | } |
949 | asf->nb_mult_left = 0; |
950 | asf->sub_left = 0; |
951 | asf->state = PARSE_PACKET_HEADER; |
952 | asf->return_subpayload = 0; |
953 | asf->packet_size_internal = 0; |
954 | avio_skip(pb, 16); // skip File ID |
955 | size = avio_rl64(pb); // Total Data Packets |
956 | if (size != asf->nb_packets) |
957 | av_log(s, AV_LOG_WARNING, |
958 | "Number of Packets from File Properties Object is not equal to Total" |
959 | "Datapackets value! num of packets %"PRIu64" total num %"PRIu64".\n", |
960 | size, asf->nb_packets); |
961 | avio_skip(pb, 2); // skip reserved field |
962 | asf->first_packet_offset = avio_tell(pb); |
963 | if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !(asf->b_flags & ASF_FLAG_BROADCAST)) |
964 | align_position(pb, asf->offset, asf->data_size); |
965 | |
966 | return 0; |
967 | } |
968 | |
969 | static int asf_read_simple_index(AVFormatContext *s, const GUIDParseTable *g) |
970 | { |
971 | ASFContext *asf = s->priv_data; |
972 | AVIOContext *pb = s->pb; |
973 | AVStream *st = NULL; |
974 | uint64_t interval; // index entry time interval in 100 ns units, usually it's 1s |
975 | uint32_t pkt_num, nb_entries; |
976 | int32_t prev_pkt_num = -1; |
977 | int i, ret; |
978 | uint64_t size = avio_rl64(pb); |
979 | |
980 | // simple index objects should be ordered by stream number, this loop tries to find |
981 | // the first not indexed video stream |
982 | for (i = 0; i < asf->nb_streams; i++) { |
983 | if ((asf->asf_st[i]->type == AVMEDIA_TYPE_VIDEO) && !asf->asf_st[i]->indexed) { |
984 | asf->asf_st[i]->indexed = 1; |
985 | st = s->streams[asf->asf_st[i]->index]; |
986 | break; |
987 | } |
988 | } |
989 | if (!st) { |
990 | avio_skip(pb, size - 24); // if there's no video stream, skip index object |
991 | return 0; |
992 | } |
993 | avio_skip(pb, 16); // skip File ID |
994 | interval = avio_rl64(pb); |
995 | avio_skip(pb, 4); |
996 | nb_entries = avio_rl32(pb); |
997 | for (i = 0; i < nb_entries; i++) { |
998 | pkt_num = avio_rl32(pb); |
999 | ret = avio_skip(pb, 2); |
1000 | if (ret < 0) { |
1001 | av_log(s, AV_LOG_ERROR, "Skipping failed in asf_read_simple_index.\n"); |
1002 | return ret; |
1003 | } |
1004 | if (prev_pkt_num != pkt_num) { |
1005 | av_add_index_entry(st, asf->first_packet_offset + asf->packet_size * |
1006 | pkt_num, av_rescale(interval, i, 10000), |
1007 | asf->packet_size, 0, AVINDEX_KEYFRAME); |
1008 | prev_pkt_num = pkt_num; |
1009 | } |
1010 | } |
1011 | asf->is_simple_index = 1; |
1012 | align_position(pb, asf->offset, size); |
1013 | |
1014 | return 0; |
1015 | } |
1016 | |
1017 | static const GUIDParseTable gdef[] = { |
1018 | { "Data", { 0x75, 0xB2, 0x26, 0x36, 0x66, 0x8E, 0x11, 0xCF, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C }, asf_read_data, 1 }, |
1019 | { "Simple Index", { 0x33, 0x00, 0x08, 0x90, 0xE5, 0xB1, 0x11, 0xCF, 0x89, 0xF4, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xCB }, asf_read_simple_index, 1 }, |
1020 | { "Content Description", { 0x75, 0xB2, 0x26, 0x33, 0x66 ,0x8E, 0x11, 0xCF, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C }, asf_read_content_desc, 1 }, |
1021 | { "Extended Content Description", { 0xD2, 0xD0, 0xA4, 0x40, 0xE3, 0x07, 0x11, 0xD2, 0x97, 0xF0, 0x00, 0xA0, 0xC9, 0x5e, 0xA8, 0x50 }, asf_read_ext_content, 1 }, |
1022 | { "Stream Bitrate Properties", { 0x7B, 0xF8, 0x75, 0xCE, 0x46, 0x8D, 0x11, 0xD1, 0x8D, 0x82, 0x00, 0x60, 0x97, 0xC9, 0xA2, 0xB2 }, asf_read_unknown, 1 }, |
1023 | { "File Properties", { 0x8C, 0xAB, 0xDC, 0xA1, 0xA9, 0x47, 0x11, 0xCF, 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_properties, 1 }, |
1024 | { "Header Extension", { 0x5F, 0xBF, 0x03, 0xB5, 0xA9, 0x2E, 0x11, 0xCF, 0x8E, 0xE3, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_unknown, 0 }, |
1025 | { "Stream Properties", { 0xB7, 0xDC, 0x07, 0x91, 0xA9, 0xB7, 0x11, 0xCF, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_stream_properties, 1 }, |
1026 | { "Codec List", { 0x86, 0xD1, 0x52, 0x40, 0x31, 0x1D, 0x11, 0xD0, 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 }, asf_read_unknown, 1 }, |
1027 | { "Marker", { 0xF4, 0x87, 0xCD, 0x01, 0xA9, 0x51, 0x11, 0xCF, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_marker, 1 }, |
1028 | { "Script Command", { 0x1E, 0xFB, 0x1A, 0x30, 0x0B, 0x62, 0x11, 0xD0, 0xA3, 0x9B, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 }, asf_read_unknown, 1 }, |
1029 | { "Language List", { 0x7C, 0x43, 0x46, 0xa9, 0xef, 0xe0, 0x4B, 0xFC, 0xB2, 0x29, 0x39, 0x3e, 0xde, 0x41, 0x5c, 0x85 }, asf_read_language_list, 1}, |
1030 | { "Padding", { 0x18, 0x06, 0xD4, 0x74, 0xCA, 0xDF, 0x45, 0x09, 0xA4, 0xBA, 0x9A, 0xAB, 0xCB, 0x96, 0xAA, 0xE8 }, asf_read_unknown, 1 }, |
1031 | { "DRMv1 Header", { 0x22, 0x11, 0xB3, 0xFB, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown, 1 }, |
1032 | { "DRMv2 Header", { 0x29, 0x8A, 0xE6, 0x14, 0x26, 0x22, 0x4C, 0x17, 0xB9, 0x35, 0xDA, 0xE0, 0x7E, 0xE9, 0x28, 0x9c }, asf_read_unknown, 1 }, |
1033 | { "Index", { 0xD6, 0xE2, 0x29, 0xD3, 0x35, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown, 1 }, |
1034 | { "Media Object Index", { 0xFE, 0xB1, 0x03, 0xF8, 0x12, 0xAD, 0x4C, 0x64, 0x84, 0x0F, 0x2A, 0x1D, 0x2F, 0x7A, 0xD4, 0x8C }, asf_read_unknown, 1 }, |
1035 | { "Timecode Index", { 0x3C, 0xB7, 0x3F, 0xD0, 0x0C, 0x4A, 0x48, 0x03, 0x95, 0x3D, 0xED, 0xF7, 0xB6, 0x22, 0x8F, 0x0C }, asf_read_unknown, 0 }, |
1036 | { "Bitrate_Mutual_Exclusion", { 0xD6, 0xE2, 0x29, 0xDC, 0x35, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown, 1 }, |
1037 | { "Error Correction", { 0x75, 0xB2, 0x26, 0x35, 0x66, 0x8E, 0x11, 0xCF, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C }, asf_read_unknown, 1 }, |
1038 | { "Content Branding", { 0x22, 0x11, 0xB3, 0xFA, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown, 1 }, |
1039 | { "Content Encryption", { 0x22, 0x11, 0xB3, 0xFB, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown, 1 }, |
1040 | { "Extended Content Encryption", { 0x29, 0x8A, 0xE6, 0x14, 0x26, 0x22, 0x4C, 0x17, 0xB9, 0x35, 0xDA, 0xE0, 0x7E, 0xE9, 0x28, 0x9C }, asf_read_unknown, 1 }, |
1041 | { "Digital Signature", { 0x22, 0x11, 0xB3, 0xFC, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown, 1 }, |
1042 | { "Extended Stream Properties", { 0x14, 0xE6, 0xA5, 0xCB, 0xC6, 0x72, 0x43, 0x32, 0x83, 0x99, 0xA9, 0x69, 0x52, 0x06, 0x5B, 0x5A }, asf_read_ext_stream_properties, 1 }, |
1043 | { "Advanced Mutual Exclusion", { 0xA0, 0x86, 0x49, 0xCF, 0x47, 0x75, 0x46, 0x70, 0x8A, 0x16, 0x6E, 0x35, 0x35, 0x75, 0x66, 0xCD }, asf_read_unknown, 1 }, |
1044 | { "Group Mutual Exclusion", { 0xD1, 0x46, 0x5A, 0x40, 0x5A, 0x79, 0x43, 0x38, 0xB7, 0x1B, 0xE3, 0x6B, 0x8F, 0xD6, 0xC2, 0x49 }, asf_read_unknown, 1}, |
1045 | { "Stream Prioritization", { 0xD4, 0xFE, 0xD1, 0x5B, 0x88, 0xD3, 0x45, 0x4F, 0x81, 0xF0, 0xED, 0x5C, 0x45, 0x99, 0x9E, 0x24 }, asf_read_unknown, 1 }, |
1046 | { "Bandwidth Sharing Object", { 0xA6, 0x96, 0x09, 0xE6, 0x51, 0x7B, 0x11, 0xD2, 0xB6, 0xAF, 0x00, 0xC0, 0x4F, 0xD9, 0x08, 0xE9 }, asf_read_unknown, 1 }, |
1047 | { "Metadata", { 0xC5, 0xF8, 0xCB, 0xEA, 0x5B, 0xAF, 0x48, 0x77, 0x84, 0x67, 0xAA, 0x8C, 0x44, 0xFA, 0x4C, 0xCA }, asf_read_metadata_obj, 1 }, |
1048 | { "Metadata Library", { 0x44, 0x23, 0x1C, 0x94, 0x94, 0x98, 0x49, 0xD1, 0xA1, 0x41, 0x1D, 0x13, 0x4E, 0x45, 0x70, 0x54 }, asf_read_metadata_obj, 1 }, |
1049 | { "Audio Spread", { 0xBF, 0xC3, 0xCD, 0x50, 0x61, 0x8F, 0x11, 0xCF, 0x8B, 0xB2, 0x00, 0xAA, 0x00, 0xB4, 0xE2, 0x20 }, asf_read_unknown, 1 }, |
1050 | { "Index Parameters", { 0xD6, 0xE2, 0x29, 0xDF, 0x35, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown, 1 }, |
1051 | { "Content Encryption System Windows Media DRM Network Devices", |
1052 | { 0x7A, 0x07, 0x9B, 0xB6, 0xDA, 0XA4, 0x4e, 0x12, 0xA5, 0xCA, 0x91, 0xD3, 0x8D, 0xC1, 0x1A, 0x8D }, asf_read_unknown, 1 }, |
1053 | { "Mutex Language", { 0xD6, 0xE2, 0x2A, 0x00, 0x25, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown, 1 }, |
1054 | { "Mutex Bitrate", { 0xD6, 0xE2, 0x2A, 0x01, 0x25, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown, 1 }, |
1055 | { "Mutex Unknown", { 0xD6, 0xE2, 0x2A, 0x02, 0x25, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown, 1 }, |
1056 | { "Bandwidth Sharing Exclusive", { 0xAF, 0x60, 0x60, 0xAA, 0x51, 0x97, 0x11, 0xD2, 0xB6, 0xAF, 0x00, 0xC0, 0x4F, 0xD9, 0x08, 0xE9 }, asf_read_unknown, 1 }, |
1057 | { "Bandwidth Sharing Partial", { 0xAF, 0x60, 0x60, 0xAB, 0x51, 0x97, 0x11, 0xD2, 0xB6, 0xAF, 0x00, 0xC0, 0x4F, 0xD9, 0x08, 0xE9 }, asf_read_unknown, 1 }, |
1058 | { "Payload Extension System Timecode", { 0x39, 0x95, 0x95, 0xEC, 0x86, 0x67, 0x4E, 0x2D, 0x8F, 0xDB, 0x98, 0x81, 0x4C, 0xE7, 0x6C, 0x1E }, asf_read_unknown, 1 }, |
1059 | { "Payload Extension System File Name", { 0xE1, 0x65, 0xEC, 0x0E, 0x19, 0xED, 0x45, 0xD7, 0xB4, 0xA7, 0x25, 0xCB, 0xD1, 0xE2, 0x8E, 0x9B }, asf_read_unknown, 1 }, |
1060 | { "Payload Extension System Content Type", { 0xD5, 0x90, 0xDC, 0x20, 0x07, 0xBC, 0x43, 0x6C, 0x9C, 0xF7, 0xF3, 0xBB, 0xFB, 0xF1, 0xA4, 0xDC }, asf_read_unknown, 1 }, |
1061 | { "Payload Extension System Pixel Aspect Ratio", { 0x1, 0x1E, 0xE5, 0x54, 0xF9, 0xEA, 0x4B, 0xC8, 0x82, 0x1A, 0x37, 0x6B, 0x74, 0xE4, 0xC4, 0xB8 }, asf_read_unknown, 1 }, |
1062 | { "Payload Extension System Sample Duration", { 0xC6, 0xBD, 0x94, 0x50, 0x86, 0x7F, 0x49, 0x07, 0x83, 0xA3, 0xC7, 0x79, 0x21, 0xB7, 0x33, 0xAD }, asf_read_unknown, 1 }, |
1063 | { "Payload Extension System Encryption Sample ID", { 0x66, 0x98, 0xB8, 0x4E, 0x0A, 0xFA, 0x43, 0x30, 0xAE, 0xB2, 0x1C, 0x0A, 0x98, 0xD7, 0xA4, 0x4D }, asf_read_unknown, 1 }, |
1064 | { "Payload Extension System Degradable JPEG", { 0x00, 0xE1, 0xAF, 0x06, 0x7B, 0xEC, 0x11, 0xD1, 0xA5, 0x82, 0x00, 0xC0, 0x4F, 0xC2, 0x9C, 0xFB }, asf_read_unknown, 1 }, |
1065 | }; |
1066 | |
1067 | #define READ_LEN(flag, name, len) \ |
1068 | do { \ |
1069 | if ((flag) == name ## IS_BYTE) \ |
1070 | len = avio_r8(pb); \ |
1071 | else if ((flag) == name ## IS_WORD) \ |
1072 | len = avio_rl16(pb); \ |
1073 | else if ((flag) == name ## IS_DWORD) \ |
1074 | len = avio_rl32(pb); \ |
1075 | else \ |
1076 | len = 0; \ |
1077 | } while(0) |
1078 | |
1079 | static int asf_read_subpayload(AVFormatContext *s, AVPacket *pkt, int is_header) |
1080 | { |
1081 | ASFContext *asf = s->priv_data; |
1082 | AVIOContext *pb = s->pb; |
1083 | uint8_t sub_len; |
1084 | int ret, i; |
1085 | |
1086 | if (is_header) { |
1087 | asf->dts_delta = avio_r8(pb); |
1088 | if (asf->nb_mult_left) { |
1089 | asf->mult_sub_len = avio_rl16(pb); // total |
1090 | } |
1091 | asf->sub_header_offset = avio_tell(pb); |
1092 | asf->nb_sub = 0; |
1093 | asf->sub_left = 1; |
1094 | } |
1095 | sub_len = avio_r8(pb); |
1096 | if ((ret = av_get_packet(pb, pkt, sub_len)) < 0) // each subpayload is entire frame |
1097 | return ret; |
1098 | for (i = 0; i < asf->nb_streams; i++) { |
1099 | if (asf->stream_index == asf->asf_st[i]->stream_index) { |
1100 | pkt->stream_index = asf->asf_st[i]->index; |
1101 | break; |
1102 | } |
1103 | } |
1104 | asf->return_subpayload = 1; |
1105 | if (!sub_len) |
1106 | asf->return_subpayload = 0; |
1107 | |
1108 | if (sub_len) |
1109 | asf->nb_sub++; |
1110 | pkt->dts = asf->sub_dts + (asf->nb_sub - 1) * asf->dts_delta - asf->preroll; |
1111 | if (asf->nb_mult_left && (avio_tell(pb) >= |
1112 | (asf->sub_header_offset + asf->mult_sub_len))) { |
1113 | asf->sub_left = 0; |
1114 | asf->nb_mult_left--; |
1115 | } |
1116 | if (avio_tell(pb) >= asf->packet_offset + asf->packet_size - asf->pad_len) { |
1117 | asf->sub_left = 0; |
1118 | if (!asf->nb_mult_left) { |
1119 | avio_skip(pb, asf->pad_len); |
1120 | if (avio_tell(pb) != asf->packet_offset + asf->packet_size) { |
1121 | if (!asf->packet_size) |
1122 | return AVERROR_INVALIDDATA; |
1123 | av_log(s, AV_LOG_WARNING, |
1124 | "Position %"PRId64" wrong, should be %"PRId64"\n", |
1125 | avio_tell(pb), asf->packet_offset + asf->packet_size); |
1126 | avio_seek(pb, asf->packet_offset + asf->packet_size, SEEK_SET); |
1127 | } |
1128 | } |
1129 | } |
1130 | |
1131 | return 0; |
1132 | } |
1133 | |
1134 | static void reset_packet(ASFPacket *asf_pkt) |
1135 | { |
1136 | asf_pkt->size_left = 0; |
1137 | asf_pkt->data_size = 0; |
1138 | asf_pkt->duration = 0; |
1139 | asf_pkt->flags = 0; |
1140 | asf_pkt->dts = 0; |
1141 | asf_pkt->duration = 0; |
1142 | av_packet_unref(&asf_pkt->avpkt); |
1143 | av_init_packet(&asf_pkt->avpkt); |
1144 | } |
1145 | |
1146 | static int asf_read_replicated_data(AVFormatContext *s, ASFPacket *asf_pkt) |
1147 | { |
1148 | ASFContext *asf = s->priv_data; |
1149 | AVIOContext *pb = s->pb; |
1150 | int ret, data_size; |
1151 | |
1152 | if (!asf_pkt->data_size) { |
1153 | data_size = avio_rl32(pb); // read media object size |
1154 | if (data_size <= 0) |
1155 | return AVERROR_INVALIDDATA; |
1156 | if ((ret = av_new_packet(&asf_pkt->avpkt, data_size)) < 0) |
1157 | return ret; |
1158 | asf_pkt->data_size = asf_pkt->size_left = data_size; |
1159 | } else |
1160 | avio_skip(pb, 4); // reading of media object size is already done |
1161 | asf_pkt->dts = avio_rl32(pb); // read presentation time |
1162 | if (asf->rep_data_len && (asf->rep_data_len >= 8)) |
1163 | avio_skip(pb, asf->rep_data_len - 8); // skip replicated data |
1164 | |
1165 | return 0; |
1166 | } |
1167 | |
1168 | static int asf_read_multiple_payload(AVFormatContext *s, AVPacket *pkt, |
1169 | ASFPacket *asf_pkt) |
1170 | { |
1171 | ASFContext *asf = s->priv_data; |
1172 | AVIOContext *pb = s->pb; |
1173 | uint16_t pay_len; |
1174 | unsigned char *p; |
1175 | int ret; |
1176 | int skip = 0; |
1177 | |
1178 | // if replicated length is 1, subpayloads are present |
1179 | if (asf->rep_data_len == 1) { |
1180 | asf->sub_left = 1; |
1181 | asf->state = READ_MULTI_SUB; |
1182 | pkt->flags = asf_pkt->flags; |
1183 | if ((ret = asf_read_subpayload(s, pkt, 1)) < 0) |
1184 | return ret; |
1185 | } else { |
1186 | if (asf->rep_data_len) |
1187 | if ((ret = asf_read_replicated_data(s, asf_pkt)) < 0) |
1188 | return ret; |
1189 | pay_len = avio_rl16(pb); // payload length should be WORD |
1190 | if (pay_len > asf->packet_size) { |
1191 | av_log(s, AV_LOG_ERROR, |
1192 | "Error: invalid data packet size, pay_len %"PRIu16", " |
1193 | "asf->packet_size %"PRIu32", offset %"PRId64".\n", |
1194 | pay_len, asf->packet_size, avio_tell(pb)); |
1195 | return AVERROR_INVALIDDATA; |
1196 | } |
1197 | p = asf_pkt->avpkt.data + asf_pkt->data_size - asf_pkt->size_left; |
1198 | if (pay_len > asf_pkt->size_left) { |
1199 | av_log(s, AV_LOG_ERROR, |
1200 | "Error: invalid buffer size, pay_len %d, data size left %d.\n", |
1201 | pay_len, asf_pkt->size_left); |
1202 | skip = pay_len - asf_pkt->size_left; |
1203 | pay_len = asf_pkt->size_left; |
1204 | } |
1205 | if (asf_pkt->size_left <= 0) |
1206 | return AVERROR_INVALIDDATA; |
1207 | if ((ret = avio_read(pb, p, pay_len)) < 0) |
1208 | return ret; |
1209 | if (s->key && s->keylen == 20) |
1210 | ff_asfcrypt_dec(s->key, p, ret); |
1211 | avio_skip(pb, skip); |
1212 | asf_pkt->size_left -= pay_len; |
1213 | asf->nb_mult_left--; |
1214 | } |
1215 | |
1216 | return 0; |
1217 | } |
1218 | |
1219 | static int asf_read_single_payload(AVFormatContext *s, ASFPacket *asf_pkt) |
1220 | { |
1221 | ASFContext *asf = s->priv_data; |
1222 | AVIOContext *pb = s->pb; |
1223 | int64_t offset; |
1224 | uint64_t size; |
1225 | unsigned char *p; |
1226 | int ret, data_size; |
1227 | |
1228 | if (!asf_pkt->data_size) { |
1229 | data_size = avio_rl32(pb); // read media object size |
1230 | if (data_size <= 0) |
1231 | return AVERROR_EOF; |
1232 | if ((ret = av_new_packet(&asf_pkt->avpkt, data_size)) < 0) |
1233 | return ret; |
1234 | asf_pkt->data_size = asf_pkt->size_left = data_size; |
1235 | } else |
1236 | avio_skip(pb, 4); // skip media object size |
1237 | asf_pkt->dts = avio_rl32(pb); // read presentation time |
1238 | if (asf->rep_data_len >= 8) |
1239 | avio_skip(pb, asf->rep_data_len - 8); // skip replicated data |
1240 | offset = avio_tell(pb); |
1241 | |
1242 | // size of the payload - size of the packet without header and padding |
1243 | if (asf->packet_size_internal) |
1244 | size = asf->packet_size_internal - offset + asf->packet_offset - asf->pad_len; |
1245 | else |
1246 | size = asf->packet_size - offset + asf->packet_offset - asf->pad_len; |
1247 | if (size > asf->packet_size) { |
1248 | av_log(s, AV_LOG_ERROR, |
1249 | "Error: invalid data packet size, offset %"PRId64".\n", |
1250 | avio_tell(pb)); |
1251 | return AVERROR_INVALIDDATA; |
1252 | } |
1253 | p = asf_pkt->avpkt.data + asf_pkt->data_size - asf_pkt->size_left; |
1254 | if (size > asf_pkt->size_left || asf_pkt->size_left <= 0) |
1255 | return AVERROR_INVALIDDATA; |
1256 | if (asf_pkt->size_left > size) |
1257 | asf_pkt->size_left -= size; |
1258 | else |
1259 | asf_pkt->size_left = 0; |
1260 | if ((ret = avio_read(pb, p, size)) < 0) |
1261 | return ret; |
1262 | if (s->key && s->keylen == 20) |
1263 | ff_asfcrypt_dec(s->key, p, ret); |
1264 | if (asf->packet_size_internal) |
1265 | avio_skip(pb, asf->packet_size - asf->packet_size_internal); |
1266 | avio_skip(pb, asf->pad_len); // skip padding |
1267 | |
1268 | return 0; |
1269 | } |
1270 | |
1271 | static int asf_read_payload(AVFormatContext *s, AVPacket *pkt) |
1272 | { |
1273 | ASFContext *asf = s->priv_data; |
1274 | AVIOContext *pb = s->pb; |
1275 | int ret, i; |
1276 | ASFPacket *asf_pkt = NULL; |
1277 | |
1278 | if (!asf->sub_left) { |
1279 | uint32_t off_len, media_len; |
1280 | uint8_t stream_num; |
1281 | |
1282 | stream_num = avio_r8(pb); |
1283 | asf->stream_index = stream_num & ASF_STREAM_NUM; |
1284 | for (i = 0; i < asf->nb_streams; i++) { |
1285 | if (asf->stream_index == asf->asf_st[i]->stream_index) { |
1286 | asf_pkt = &asf->asf_st[i]->pkt; |
1287 | asf_pkt->stream_index = asf->asf_st[i]->index; |
1288 | break; |
1289 | } |
1290 | } |
1291 | if (!asf_pkt) { |
1292 | if (asf->packet_offset + asf->packet_size <= asf->data_offset + asf->data_size) { |
1293 | if (!asf->packet_size) { |
1294 | av_log(s, AV_LOG_ERROR, "Invalid packet size 0.\n"); |
1295 | return AVERROR_INVALIDDATA; |
1296 | } |
1297 | avio_seek(pb, asf->packet_offset + asf->packet_size, SEEK_SET); |
1298 | av_log(s, AV_LOG_WARNING, "Skipping the stream with the invalid stream index %d.\n", |
1299 | asf->stream_index); |
1300 | return AVERROR(EAGAIN); |
1301 | } else |
1302 | return AVERROR_INVALIDDATA; |
1303 | } |
1304 | |
1305 | if (stream_num >> 7) |
1306 | asf_pkt->flags |= AV_PKT_FLAG_KEY; |
1307 | READ_LEN(asf->prop_flags & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE, |
1308 | ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_, media_len); |
1309 | READ_LEN(asf->prop_flags & ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE, |
1310 | ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_, off_len); |
1311 | READ_LEN(asf->prop_flags & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE, |
1312 | ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_, asf->rep_data_len); |
1313 | if (asf_pkt->size_left && (asf_pkt->frame_num != media_len)) { |
1314 | av_log(s, AV_LOG_WARNING, "Unfinished frame will be ignored\n"); |
1315 | reset_packet(asf_pkt); |
1316 | } |
1317 | asf_pkt->frame_num = media_len; |
1318 | asf->sub_dts = off_len; |
1319 | if (asf->nb_mult_left) { |
1320 | if ((ret = asf_read_multiple_payload(s, pkt, asf_pkt)) < 0) |
1321 | return ret; |
1322 | } else if (asf->rep_data_len == 1) { |
1323 | asf->sub_left = 1; |
1324 | asf->state = READ_SINGLE; |
1325 | pkt->flags = asf_pkt->flags; |
1326 | if ((ret = asf_read_subpayload(s, pkt, 1)) < 0) |
1327 | return ret; |
1328 | } else { |
1329 | if ((ret = asf_read_single_payload(s, asf_pkt)) < 0) |
1330 | return ret; |
1331 | } |
1332 | } else { |
1333 | for (i = 0; i <= asf->nb_streams; i++) { |
1334 | if (asf->stream_index == asf->asf_st[i]->stream_index) { |
1335 | asf_pkt = &asf->asf_st[i]->pkt; |
1336 | break; |
1337 | } |
1338 | } |
1339 | if (!asf_pkt) |
1340 | return AVERROR_INVALIDDATA; |
1341 | pkt->flags = asf_pkt->flags; |
1342 | pkt->dts = asf_pkt->dts; |
1343 | pkt->stream_index = asf->asf_st[i]->index; |
1344 | if ((ret = asf_read_subpayload(s, pkt, 0)) < 0) // read subpayload without its header |
1345 | return ret; |
1346 | } |
1347 | |
1348 | return 0; |
1349 | } |
1350 | |
1351 | static int asf_read_packet_header(AVFormatContext *s) |
1352 | { |
1353 | ASFContext *asf = s->priv_data; |
1354 | AVIOContext *pb = s->pb; |
1355 | uint64_t size; |
1356 | uint32_t av_unused seq; |
1357 | unsigned char error_flags, len_flags, pay_flags; |
1358 | |
1359 | asf->packet_offset = avio_tell(pb); |
1360 | error_flags = avio_r8(pb); // read Error Correction Flags |
1361 | if (error_flags & ASF_PACKET_FLAG_ERROR_CORRECTION_PRESENT) { |
1362 | if (!(error_flags & ASF_ERROR_CORRECTION_LENGTH_TYPE)) { |
1363 | size = error_flags & ASF_PACKET_ERROR_CORRECTION_DATA_SIZE; |
1364 | avio_skip(pb, size); |
1365 | } |
1366 | len_flags = avio_r8(pb); |
1367 | } else |
1368 | len_flags = error_flags; |
1369 | asf->prop_flags = avio_r8(pb); |
1370 | READ_LEN(len_flags & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE, |
1371 | ASF_PPI_FLAG_PACKET_LENGTH_FIELD_, asf->packet_size_internal); |
1372 | READ_LEN(len_flags & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE, |
1373 | ASF_PPI_FLAG_SEQUENCE_FIELD_, seq); |
1374 | READ_LEN(len_flags & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE, |
1375 | ASF_PPI_FLAG_PADDING_LENGTH_FIELD_, asf->pad_len ); |
1376 | asf->send_time = avio_rl32(pb); // send time |
1377 | avio_skip(pb, 2); // skip duration |
1378 | if (len_flags & ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT) { // Multiple Payloads present |
1379 | pay_flags = avio_r8(pb); |
1380 | asf->nb_mult_left = (pay_flags & ASF_NUM_OF_PAYLOADS); |
1381 | } |
1382 | |
1383 | return 0; |
1384 | } |
1385 | |
1386 | static int asf_deinterleave(AVFormatContext *s, ASFPacket *asf_pkt, int st_num) |
1387 | { |
1388 | ASFContext *asf = s->priv_data; |
1389 | ASFStream *asf_st = asf->asf_st[st_num]; |
1390 | unsigned char *p = asf_pkt->avpkt.data; |
1391 | uint16_t pkt_len = asf->asf_st[st_num]->virtual_pkt_len; |
1392 | uint16_t chunk_len = asf->asf_st[st_num]->virtual_chunk_len; |
1393 | int nchunks = pkt_len / chunk_len; |
1394 | AVPacket pkt; |
1395 | int pos = 0, j, l, ret; |
1396 | |
1397 | |
1398 | if ((ret = av_new_packet(&pkt, asf_pkt->data_size)) < 0) |
1399 | return ret; |
1400 | |
1401 | while (asf_pkt->data_size >= asf_st->span * pkt_len + pos) { |
1402 | if (pos >= asf_pkt->data_size) { |
1403 | break; |
1404 | } |
1405 | for (l = 0; l < pkt_len; l++) { |
1406 | if (pos >= asf_pkt->data_size) { |
1407 | break; |
1408 | } |
1409 | for (j = 0; j < asf_st->span; j++) { |
1410 | if ((pos + chunk_len) >= asf_pkt->data_size) |
1411 | break; |
1412 | memcpy(pkt.data + pos, |
1413 | p + (j * nchunks + l) * chunk_len, |
1414 | chunk_len); |
1415 | pos += chunk_len; |
1416 | } |
1417 | } |
1418 | p += asf_st->span * pkt_len; |
1419 | if (p > asf_pkt->avpkt.data + asf_pkt->data_size) |
1420 | break; |
1421 | } |
1422 | av_packet_unref(&asf_pkt->avpkt); |
1423 | asf_pkt->avpkt = pkt; |
1424 | |
1425 | return 0; |
1426 | } |
1427 | |
1428 | static int asf_read_packet(AVFormatContext *s, AVPacket *pkt) |
1429 | { |
1430 | ASFContext *asf = s->priv_data; |
1431 | AVIOContext *pb = s->pb; |
1432 | int ret, i; |
1433 | |
1434 | if ((avio_tell(pb) >= asf->data_offset + asf->data_size) && |
1435 | !(asf->b_flags & ASF_FLAG_BROADCAST)) |
1436 | return AVERROR_EOF; |
1437 | while (!pb->eof_reached) { |
1438 | if (asf->state == PARSE_PACKET_HEADER) { |
1439 | asf_read_packet_header(s); |
1440 | if (pb->eof_reached) |
1441 | break; |
1442 | if (!asf->nb_mult_left) |
1443 | asf->state = READ_SINGLE; |
1444 | else |
1445 | asf->state = READ_MULTI; |
1446 | } |
1447 | ret = asf_read_payload(s, pkt); |
1448 | if (ret == AVERROR(EAGAIN)) { |
1449 | asf->state = PARSE_PACKET_HEADER; |
1450 | continue; |
1451 | } |
1452 | else if (ret < 0) |
1453 | return ret; |
1454 | |
1455 | switch (asf->state) { |
1456 | case READ_SINGLE: |
1457 | if (!asf->sub_left) |
1458 | asf->state = PARSE_PACKET_HEADER; |
1459 | break; |
1460 | case READ_MULTI_SUB: |
1461 | if (!asf->sub_left && !asf->nb_mult_left) { |
1462 | asf->state = PARSE_PACKET_HEADER; |
1463 | if (!asf->return_subpayload && |
1464 | (avio_tell(pb) <= asf->packet_offset + |
1465 | asf->packet_size - asf->pad_len)) |
1466 | avio_skip(pb, asf->pad_len); // skip padding |
1467 | if (asf->packet_offset + asf->packet_size > avio_tell(pb)) |
1468 | avio_seek(pb, asf->packet_offset + asf->packet_size, SEEK_SET); |
1469 | } else if (!asf->sub_left) |
1470 | asf->state = READ_MULTI; |
1471 | break; |
1472 | case READ_MULTI: |
1473 | if (!asf->nb_mult_left) { |
1474 | asf->state = PARSE_PACKET_HEADER; |
1475 | if (!asf->return_subpayload && |
1476 | (avio_tell(pb) <= asf->packet_offset + |
1477 | asf->packet_size - asf->pad_len)) |
1478 | avio_skip(pb, asf->pad_len); // skip padding |
1479 | if (asf->packet_offset + asf->packet_size > avio_tell(pb)) |
1480 | avio_seek(pb, asf->packet_offset + asf->packet_size, SEEK_SET); |
1481 | } |
1482 | break; |
1483 | } |
1484 | if (asf->return_subpayload) { |
1485 | asf->return_subpayload = 0; |
1486 | return 0; |
1487 | } |
1488 | for (i = 0; i < s->nb_streams; i++) { |
1489 | ASFPacket *asf_pkt = &asf->asf_st[i]->pkt; |
1490 | if (asf_pkt && !asf_pkt->size_left && asf_pkt->data_size) { |
1491 | if (asf->asf_st[i]->span > 1 && |
1492 | asf->asf_st[i]->type == AVMEDIA_TYPE_AUDIO) |
1493 | if ((ret = asf_deinterleave(s, asf_pkt, i)) < 0) |
1494 | return ret; |
1495 | av_packet_move_ref(pkt, &asf_pkt->avpkt); |
1496 | pkt->stream_index = asf->asf_st[i]->index; |
1497 | pkt->flags = asf_pkt->flags; |
1498 | pkt->dts = asf_pkt->dts - asf->preroll; |
1499 | asf_pkt->data_size = 0; |
1500 | asf_pkt->frame_num = 0; |
1501 | return 0; |
1502 | } |
1503 | } |
1504 | } |
1505 | |
1506 | if (pb->eof_reached) |
1507 | return AVERROR_EOF; |
1508 | |
1509 | return 0; |
1510 | } |
1511 | |
1512 | static int asf_read_close(AVFormatContext *s) |
1513 | { |
1514 | ASFContext *asf = s->priv_data; |
1515 | int i; |
1516 | |
1517 | for (i = 0; i < ASF_MAX_STREAMS; i++) { |
1518 | av_dict_free(&asf->asf_sd[i].asf_met); |
1519 | if (i < asf->nb_streams) { |
1520 | av_packet_unref(&asf->asf_st[i]->pkt.avpkt); |
1521 | av_freep(&asf->asf_st[i]); |
1522 | } |
1523 | } |
1524 | |
1525 | asf->nb_streams = 0; |
1526 | return 0; |
1527 | } |
1528 | |
1529 | static void reset_packet_state(AVFormatContext *s) |
1530 | { |
1531 | ASFContext *asf = s->priv_data; |
1532 | int i; |
1533 | |
1534 | asf->state = PARSE_PACKET_HEADER; |
1535 | asf->offset = 0; |
1536 | asf->return_subpayload = 0; |
1537 | asf->sub_left = 0; |
1538 | asf->sub_header_offset = 0; |
1539 | asf->packet_offset = asf->first_packet_offset; |
1540 | asf->pad_len = 0; |
1541 | asf->rep_data_len = 0; |
1542 | asf->dts_delta = 0; |
1543 | asf->mult_sub_len = 0; |
1544 | asf->nb_mult_left = 0; |
1545 | asf->nb_sub = 0; |
1546 | asf->prop_flags = 0; |
1547 | asf->sub_dts = 0; |
1548 | for (i = 0; i < asf->nb_streams; i++) { |
1549 | ASFPacket *pkt = &asf->asf_st[i]->pkt; |
1550 | pkt->size_left = 0; |
1551 | pkt->data_size = 0; |
1552 | pkt->duration = 0; |
1553 | pkt->flags = 0; |
1554 | pkt->dts = 0; |
1555 | pkt->duration = 0; |
1556 | av_packet_unref(&pkt->avpkt); |
1557 | av_init_packet(&pkt->avpkt); |
1558 | } |
1559 | } |
1560 | |
1561 | /* |
1562 | * Find a timestamp for the requested position within the payload |
1563 | * where the pos (position) is the offset inside the Data Object. |
1564 | * When position is not on the packet boundary, asf_read_timestamp tries |
1565 | * to find the closest packet offset after this position. If this packet |
1566 | * is a key frame, this packet timestamp is read and an index entry is created |
1567 | * for the packet. If this packet belongs to the requested stream, |
1568 | * asf_read_timestamp upgrades pos to the packet beginning offset and |
1569 | * returns this packet's dts. So returned dts is the dts of the first key frame with |
1570 | * matching stream number after given position. |
1571 | */ |
1572 | static int64_t asf_read_timestamp(AVFormatContext *s, int stream_index, |
1573 | int64_t *pos, int64_t pos_limit) |
1574 | { |
1575 | ASFContext *asf = s->priv_data; |
1576 | int64_t pkt_pos = *pos, pkt_offset, dts = AV_NOPTS_VALUE, data_end; |
1577 | AVPacket pkt; |
1578 | int n; |
1579 | |
1580 | data_end = asf->data_offset + asf->data_size; |
1581 | |
1582 | n = (pkt_pos - asf->first_packet_offset + asf->packet_size - 1) / |
1583 | asf->packet_size; |
1584 | n = av_clip(n, 0, ((data_end - asf->first_packet_offset) / asf->packet_size - 1)); |
1585 | pkt_pos = asf->first_packet_offset + n * asf->packet_size; |
1586 | |
1587 | avio_seek(s->pb, pkt_pos, SEEK_SET); |
1588 | pkt_offset = pkt_pos; |
1589 | |
1590 | reset_packet_state(s); |
1591 | while (avio_tell(s->pb) < data_end) { |
1592 | |
1593 | int i, ret, st_found; |
1594 | |
1595 | av_init_packet(&pkt); |
1596 | pkt_offset = avio_tell(s->pb); |
1597 | if ((ret = asf_read_packet(s, &pkt)) < 0) { |
1598 | dts = AV_NOPTS_VALUE; |
1599 | return ret; |
1600 | } |
1601 | // ASFPacket may contain fragments of packets belonging to different streams, |
1602 | // pkt_offset is the offset of the first fragment within it. |
1603 | if ((pkt_offset >= (pkt_pos + asf->packet_size))) |
1604 | pkt_pos += asf->packet_size; |
1605 | for (i = 0; i < asf->nb_streams; i++) { |
1606 | ASFStream *st = asf->asf_st[i]; |
1607 | |
1608 | st_found = 0; |
1609 | if (pkt.flags & AV_PKT_FLAG_KEY) { |
1610 | dts = pkt.dts; |
1611 | if (dts) { |
1612 | av_add_index_entry(s->streams[pkt.stream_index], pkt_pos, |
1613 | dts, pkt.size, 0, AVINDEX_KEYFRAME); |
1614 | if (stream_index == st->index) { |
1615 | st_found = 1; |
1616 | break; |
1617 | } |
1618 | } |
1619 | } |
1620 | } |
1621 | if (st_found) |
1622 | break; |
1623 | av_packet_unref(&pkt); |
1624 | } |
1625 | *pos = pkt_pos; |
1626 | |
1627 | av_packet_unref(&pkt); |
1628 | return dts; |
1629 | } |
1630 | |
1631 | static int asf_read_seek(AVFormatContext *s, int stream_index, |
1632 | int64_t timestamp, int flags) |
1633 | { |
1634 | ASFContext *asf = s->priv_data; |
1635 | int idx, ret; |
1636 | |
1637 | if (s->streams[stream_index]->nb_index_entries && asf->is_simple_index) { |
1638 | idx = av_index_search_timestamp(s->streams[stream_index], timestamp, flags); |
1639 | if (idx < 0 || idx >= s->streams[stream_index]->nb_index_entries) |
1640 | return AVERROR_INVALIDDATA; |
1641 | avio_seek(s->pb, s->streams[stream_index]->index_entries[idx].pos, SEEK_SET); |
1642 | } else { |
1643 | if ((ret = ff_seek_frame_binary(s, stream_index, timestamp, flags)) < 0) |
1644 | return ret; |
1645 | } |
1646 | |
1647 | reset_packet_state(s); |
1648 | |
1649 | return 0; |
1650 | } |
1651 | |
1652 | static const GUIDParseTable *find_guid(ff_asf_guid guid) |
1653 | { |
1654 | int j, ret; |
1655 | const GUIDParseTable *g; |
1656 | |
1657 | swap_guid(guid); |
1658 | g = gdef; |
1659 | for (j = 0; j < FF_ARRAY_ELEMS(gdef); j++) { |
1660 | if (!(ret = memcmp(guid, g->guid, sizeof(g->guid)))) |
1661 | return g; |
1662 | g++; |
1663 | } |
1664 | |
1665 | return NULL; |
1666 | } |
1667 | |
1668 | static int detect_unknown_subobject(AVFormatContext *s, int64_t offset, int64_t size) |
1669 | { |
1670 | ASFContext *asf = s->priv_data; |
1671 | AVIOContext *pb = s->pb; |
1672 | const GUIDParseTable *g = NULL; |
1673 | ff_asf_guid guid; |
1674 | int ret; |
1675 | |
1676 | while (avio_tell(pb) <= offset + size) { |
1677 | if (avio_tell(pb) == asf->offset) |
1678 | break; |
1679 | asf->offset = avio_tell(pb); |
1680 | if ((ret = ff_get_guid(pb, &guid)) < 0) |
1681 | return ret; |
1682 | g = find_guid(guid); |
1683 | if (g) { |
1684 | if ((ret = g->read_object(s, g)) < 0) |
1685 | return ret; |
1686 | } else { |
1687 | GUIDParseTable g2; |
1688 | |
1689 | g2.name = "Unknown"; |
1690 | g2.is_subobject = 1; |
1691 | asf_read_unknown(s, &g2); |
1692 | } |
1693 | } |
1694 | |
1695 | return 0; |
1696 | } |
1697 | |
1698 | static int asf_read_header(AVFormatContext *s) |
1699 | { |
1700 | ASFContext *asf = s->priv_data; |
1701 | AVIOContext *pb = s->pb; |
1702 | const GUIDParseTable *g = NULL; |
1703 | ff_asf_guid guid; |
1704 | int i, ret; |
1705 | uint64_t size; |
1706 | |
1707 | asf->preroll = 0; |
1708 | asf->is_simple_index = 0; |
1709 | ff_get_guid(pb, &guid); |
1710 | if (ff_guidcmp(&guid, &ff_asf_header)) |
1711 | return AVERROR_INVALIDDATA; |
1712 | avio_skip(pb, 8); // skip header object size |
1713 | avio_skip(pb, 6); // skip number of header objects and 2 reserved bytes |
1714 | asf->data_reached = 0; |
1715 | |
1716 | /* 1 is here instead of pb->eof_reached because (when not streaming), Data are skipped |
1717 | * for the first time, |
1718 | * Index object is processed and got eof and then seeking back to the Data is performed. |
1719 | */ |
1720 | while (1) { |
1721 | // for the cases when object size is invalid |
1722 | if (avio_tell(pb) == asf->offset) |
1723 | break; |
1724 | asf->offset = avio_tell(pb); |
1725 | if ((ret = ff_get_guid(pb, &guid)) < 0) { |
1726 | if (ret == AVERROR_EOF && asf->data_reached) |
1727 | break; |
1728 | else |
1729 | goto failed; |
1730 | } |
1731 | g = find_guid(guid); |
1732 | if (g) { |
1733 | asf->unknown_offset = asf->offset; |
1734 | asf->is_header = 1; |
1735 | if ((ret = g->read_object(s, g)) < 0) |
1736 | goto failed; |
1737 | } else { |
1738 | size = avio_rl64(pb); |
1739 | align_position(pb, asf->offset, size); |
1740 | } |
1741 | if (asf->data_reached && |
1742 | (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || |
1743 | (asf->b_flags & ASF_FLAG_BROADCAST))) |
1744 | break; |
1745 | } |
1746 | |
1747 | if (!asf->data_reached) { |
1748 | av_log(s, AV_LOG_ERROR, "Data Object was not found.\n"); |
1749 | ret = AVERROR_INVALIDDATA; |
1750 | goto failed; |
1751 | } |
1752 | if (pb->seekable & AVIO_SEEKABLE_NORMAL) |
1753 | avio_seek(pb, asf->first_packet_offset, SEEK_SET); |
1754 | |
1755 | for (i = 0; i < asf->nb_streams; i++) { |
1756 | const char *rfc1766 = asf->asf_sd[asf->asf_st[i]->lang_idx].langs; |
1757 | AVStream *st = s->streams[asf->asf_st[i]->index]; |
1758 | set_language(s, rfc1766, &st->metadata); |
1759 | } |
1760 | |
1761 | for (i = 0; i < ASF_MAX_STREAMS; i++) { |
1762 | AVStream *st = NULL; |
1763 | |
1764 | st = find_stream(s, i); |
1765 | if (st) { |
1766 | av_dict_copy(&st->metadata, asf->asf_sd[i].asf_met, AV_DICT_IGNORE_SUFFIX); |
1767 | if (asf->asf_sd[i].aspect_ratio.num > 0 && asf->asf_sd[i].aspect_ratio.den > 0) { |
1768 | st->sample_aspect_ratio.num = asf->asf_sd[i].aspect_ratio.num; |
1769 | st->sample_aspect_ratio.den = asf->asf_sd[i].aspect_ratio.den; |
1770 | } |
1771 | } |
1772 | } |
1773 | |
1774 | return 0; |
1775 | |
1776 | failed: |
1777 | asf_read_close(s); |
1778 | return ret; |
1779 | } |
1780 | |
1781 | AVInputFormat ff_asf_o_demuxer = { |
1782 | .name = "asf_o", |
1783 | .long_name = NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"), |
1784 | .priv_data_size = sizeof(ASFContext), |
1785 | .read_probe = asf_probe, |
1786 | .read_header = asf_read_header, |
1787 | .read_packet = asf_read_packet, |
1788 | .read_close = asf_read_close, |
1789 | .read_timestamp = asf_read_timestamp, |
1790 | .read_seek = asf_read_seek, |
1791 | .flags = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH, |
1792 | }; |
1793 |