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