Mercurial > libavformat.hg
annotate asf.c @ 360:81e90b91f457 libavformat
no limits!, warning is enough
author | michael |
---|---|
date | Sat, 07 Feb 2004 00:03:11 +0000 |
parents | 46029c682234 |
children | 845f9de2c883 |
rev | line source |
---|---|
0 | 1 /* |
2 * ASF compatible encoder and decoder. | |
3 * Copyright (c) 2000, 2001 Fabrice Bellard. | |
4 * | |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2 of the License, or (at your option) any later version. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Lesser General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Lesser General Public | |
16 * License along with this library; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 */ | |
19 #include "avformat.h" | |
20 #include "avi.h" | |
21 #include "mpegaudio.h" | |
22 | |
348 | 23 #undef NDEBUG |
24 #include <assert.h> | |
25 | |
0 | 26 #define PACKET_SIZE 3200 |
27 #define PACKET_HEADER_SIZE 12 | |
28 #define FRAME_HEADER_SIZE 17 | |
29 | |
30 typedef struct { | |
31 int num; | |
32 int seq; | |
33 /* use for reading */ | |
34 AVPacket pkt; | |
35 int frag_offset; | |
36 int timestamp; | |
65 | 37 int64_t duration; |
0 | 38 |
39 int ds_span; /* descrambling */ | |
40 int ds_packet_size; | |
41 int ds_chunk_size; | |
42 int ds_data_size; | |
43 int ds_silence_data; | |
349 | 44 |
45 int packet_pos; | |
0 | 46 |
47 } ASFStream; | |
48 | |
49 typedef struct { | |
65 | 50 uint32_t v1; |
51 uint16_t v2; | |
52 uint16_t v3; | |
53 uint8_t v4[8]; | |
0 | 54 } GUID; |
55 | |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
136
diff
changeset
|
56 typedef struct { |
0 | 57 GUID guid; // generated by client computer |
58 uint64_t file_size; // in bytes | |
59 // invalid if broadcasting | |
60 uint64_t create_time; // time of creation, in 100-nanosecond units since 1.1.1601 | |
61 // invalid if broadcasting | |
62 uint64_t packets_count; // how many packets are there in the file | |
63 // invalid if broadcasting | |
64 uint64_t play_time; // play time, in 100-nanosecond units | |
65 // invalid if broadcasting | |
66 uint64_t send_time; // time to send file, in 100-nanosecond units | |
67 // invalid if broadcasting (could be ignored) | |
68 uint32_t preroll; // timestamp of the first packet, in milliseconds | |
69 // if nonzero - substract from time | |
70 uint32_t ignore; // preroll is 64bit - but let's just ignore it | |
71 uint32_t flags; // 0x01 - broadcast | |
72 // 0x02 - seekable | |
73 // rest is reserved should be 0 | |
74 uint32_t min_pktsize; // size of a data packet | |
75 // invalid if broadcasting | |
76 uint32_t max_pktsize; // shall be the same as for min_pktsize | |
77 // invalid if broadcasting | |
78 uint32_t max_bitrate; // bandwith of stream in bps | |
79 // should be the sum of bitrates of the | |
80 // individual media streams | |
81 } ASFMainHeader; | |
82 | |
83 | |
84 typedef struct { | |
85 int seqno; | |
86 int packet_size; | |
87 int is_streamed; | |
88 int asfid2avid[128]; /* conversion table from asf ID 2 AVStream ID */ | |
89 ASFStream streams[128]; /* it's max number and it's not that big */ | |
90 /* non streamed additonnal info */ | |
65 | 91 int64_t nb_packets; |
92 int64_t duration; /* in 100ns units */ | |
0 | 93 /* packet filling */ |
94 int packet_size_left; | |
95 int packet_timestamp_start; | |
96 int packet_timestamp_end; | |
97 int packet_nb_frames; | |
65 | 98 uint8_t packet_buf[PACKET_SIZE]; |
0 | 99 ByteIOContext pb; |
100 /* only for reading */ | |
101 uint64_t data_offset; /* begining of the first data packet */ | |
102 | |
103 ASFMainHeader hdr; | |
104 | |
105 int packet_flags; | |
106 int packet_property; | |
107 int packet_timestamp; | |
108 int packet_segsizetype; | |
109 int packet_segments; | |
110 int packet_seq; | |
111 int packet_replic_size; | |
112 int packet_key_frame; | |
113 int packet_padsize; | |
114 int packet_frag_offset; | |
115 int packet_frag_size; | |
116 int packet_frag_timestamp; | |
117 int packet_multi_size; | |
118 int packet_obj_size; | |
119 int packet_time_delta; | |
120 int packet_time_start; | |
349 | 121 int packet_pos; |
0 | 122 |
123 int stream_index; | |
124 ASFStream* asf_st; /* currently decoded stream */ | |
125 } ASFContext; | |
126 | |
127 static const GUID asf_header = { | |
128 0x75B22630, 0x668E, 0x11CF, { 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C }, | |
129 }; | |
130 | |
131 static const GUID file_header = { | |
132 0x8CABDCA1, 0xA947, 0x11CF, { 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, | |
133 }; | |
134 | |
135 static const GUID stream_header = { | |
136 0xB7DC0791, 0xA9B7, 0x11CF, { 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, | |
137 }; | |
138 | |
139 static const GUID audio_stream = { | |
140 0xF8699E40, 0x5B4D, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B }, | |
141 }; | |
142 | |
143 static const GUID audio_conceal_none = { | |
144 // 0x49f1a440, 0x4ece, 0x11d0, { 0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 }, | |
145 // New value lifted from avifile | |
146 0x20fb5700, 0x5b55, 0x11cf, { 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b }, | |
147 }; | |
148 | |
149 static const GUID video_stream = { | |
150 0xBC19EFC0, 0x5B4D, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B }, | |
151 }; | |
152 | |
153 static const GUID video_conceal_none = { | |
154 0x20FB5700, 0x5B55, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B }, | |
155 }; | |
156 | |
157 | |
158 static const GUID comment_header = { | |
159 0x75b22633, 0x668e, 0x11cf, { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c }, | |
160 }; | |
161 | |
162 static const GUID codec_comment_header = { | |
163 0x86D15240, 0x311D, 0x11D0, { 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 }, | |
164 }; | |
165 static const GUID codec_comment1_header = { | |
166 0x86d15241, 0x311d, 0x11d0, { 0xa3, 0xa4, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 }, | |
167 }; | |
168 | |
169 static const GUID data_header = { | |
170 0x75b22636, 0x668e, 0x11cf, { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c }, | |
171 }; | |
172 | |
173 static const GUID index_guid = { | |
174 0x33000890, 0xe5b1, 0x11cf, { 0x89, 0xf4, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb }, | |
175 }; | |
176 | |
177 static const GUID head1_guid = { | |
178 0x5fbf03b5, 0xa92e, 0x11cf, { 0x8e, 0xe3, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 }, | |
179 }; | |
180 | |
181 static const GUID head2_guid = { | |
182 0xabd3d211, 0xa9ba, 0x11cf, { 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 }, | |
183 }; | |
184 | |
341
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
185 static const GUID extended_content_header = { |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
186 0xD2D0A440, 0xE307, 0x11D2, { 0x97, 0xF0, 0x00, 0xA0, 0xC9, 0x5E, 0xA8, 0x50 }, |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
187 }; |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
188 |
0 | 189 /* I am not a number !!! This GUID is the one found on the PC used to |
190 generate the stream */ | |
191 static const GUID my_guid = { | |
192 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, | |
193 }; | |
194 | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
241
diff
changeset
|
195 #ifdef CONFIG_ENCODERS |
0 | 196 static void put_guid(ByteIOContext *s, const GUID *g) |
197 { | |
198 int i; | |
199 | |
200 put_le32(s, g->v1); | |
201 put_le16(s, g->v2); | |
202 put_le16(s, g->v3); | |
203 for(i=0;i<8;i++) | |
204 put_byte(s, g->v4[i]); | |
205 } | |
206 | |
207 static void put_str16(ByteIOContext *s, const char *tag) | |
208 { | |
209 int c; | |
210 | |
211 put_le16(s,strlen(tag) + 1); | |
212 for(;;) { | |
65 | 213 c = (uint8_t)*tag++; |
0 | 214 put_le16(s, c); |
215 if (c == '\0') | |
216 break; | |
217 } | |
218 } | |
219 | |
220 static void put_str16_nolen(ByteIOContext *s, const char *tag) | |
221 { | |
222 int c; | |
223 | |
224 for(;;) { | |
65 | 225 c = (uint8_t)*tag++; |
0 | 226 put_le16(s, c); |
227 if (c == '\0') | |
228 break; | |
229 } | |
230 } | |
231 | |
65 | 232 static int64_t put_header(ByteIOContext *pb, const GUID *g) |
0 | 233 { |
65 | 234 int64_t pos; |
0 | 235 |
236 pos = url_ftell(pb); | |
237 put_guid(pb, g); | |
238 put_le64(pb, 24); | |
239 return pos; | |
240 } | |
241 | |
242 /* update header size */ | |
65 | 243 static void end_header(ByteIOContext *pb, int64_t pos) |
0 | 244 { |
65 | 245 int64_t pos1; |
0 | 246 |
247 pos1 = url_ftell(pb); | |
248 url_fseek(pb, pos + 16, SEEK_SET); | |
249 put_le64(pb, pos1 - pos); | |
250 url_fseek(pb, pos1, SEEK_SET); | |
251 } | |
252 | |
253 /* write an asf chunk (only used in streaming case) */ | |
254 static void put_chunk(AVFormatContext *s, int type, int payload_length, int flags) | |
255 { | |
256 ASFContext *asf = s->priv_data; | |
257 ByteIOContext *pb = &s->pb; | |
258 int length; | |
259 | |
260 length = payload_length + 8; | |
261 put_le16(pb, type); | |
262 put_le16(pb, length); | |
263 put_le32(pb, asf->seqno); | |
264 put_le16(pb, flags); /* unknown bytes */ | |
265 put_le16(pb, length); | |
266 asf->seqno++; | |
267 } | |
268 | |
269 /* convert from unix to windows time */ | |
65 | 270 static int64_t unix_to_file_time(int ti) |
0 | 271 { |
65 | 272 int64_t t; |
0 | 273 |
65 | 274 t = ti * int64_t_C(10000000); |
275 t += int64_t_C(116444736000000000); | |
0 | 276 return t; |
277 } | |
278 | |
279 /* write the header (used two times if non streamed) */ | |
65 | 280 static int asf_write_header1(AVFormatContext *s, int64_t file_size, int64_t data_chunk_size) |
0 | 281 { |
282 ASFContext *asf = s->priv_data; | |
283 ByteIOContext *pb = &s->pb; | |
284 int header_size, n, extra_size, extra_size2, wav_extra_size, file_time; | |
285 int has_title; | |
286 AVCodecContext *enc; | |
65 | 287 int64_t header_offset, cur_pos, hpos; |
0 | 288 int bit_rate; |
289 | |
290 has_title = (s->title[0] || s->author[0] || s->copyright[0] || s->comment[0]); | |
291 | |
292 bit_rate = 0; | |
293 for(n=0;n<s->nb_streams;n++) { | |
294 enc = &s->streams[n]->codec; | |
295 | |
296 bit_rate += enc->bit_rate; | |
297 } | |
298 | |
299 if (asf->is_streamed) { | |
300 put_chunk(s, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */ | |
301 } | |
302 | |
303 put_guid(pb, &asf_header); | |
304 put_le64(pb, -1); /* header length, will be patched after */ | |
305 put_le32(pb, 3 + has_title + s->nb_streams); /* number of chunks in header */ | |
306 put_byte(pb, 1); /* ??? */ | |
307 put_byte(pb, 2); /* ??? */ | |
308 | |
309 /* file header */ | |
310 header_offset = url_ftell(pb); | |
311 hpos = put_header(pb, &file_header); | |
312 put_guid(pb, &my_guid); | |
313 put_le64(pb, file_size); | |
314 file_time = 0; | |
315 put_le64(pb, unix_to_file_time(file_time)); | |
316 put_le64(pb, asf->nb_packets); /* number of packets */ | |
317 put_le64(pb, asf->duration); /* end time stamp (in 100ns units) */ | |
318 put_le64(pb, asf->duration); /* duration (in 100ns units) */ | |
319 put_le32(pb, 0); /* start time stamp */ | |
320 put_le32(pb, 0); /* ??? */ | |
321 put_le32(pb, asf->is_streamed ? 1 : 0); /* ??? */ | |
322 put_le32(pb, asf->packet_size); /* packet size */ | |
323 put_le32(pb, asf->packet_size); /* packet size */ | |
324 put_le32(pb, bit_rate); /* Nominal data rate in bps */ | |
325 end_header(pb, hpos); | |
326 | |
327 /* unknown headers */ | |
328 hpos = put_header(pb, &head1_guid); | |
329 put_guid(pb, &head2_guid); | |
330 put_le32(pb, 6); | |
331 put_le16(pb, 0); | |
332 end_header(pb, hpos); | |
333 | |
334 /* title and other infos */ | |
335 if (has_title) { | |
336 hpos = put_header(pb, &comment_header); | |
337 put_le16(pb, 2 * (strlen(s->title) + 1)); | |
338 put_le16(pb, 2 * (strlen(s->author) + 1)); | |
339 put_le16(pb, 2 * (strlen(s->copyright) + 1)); | |
340 put_le16(pb, 2 * (strlen(s->comment) + 1)); | |
341 put_le16(pb, 0); | |
342 put_str16_nolen(pb, s->title); | |
343 put_str16_nolen(pb, s->author); | |
344 put_str16_nolen(pb, s->copyright); | |
345 put_str16_nolen(pb, s->comment); | |
346 end_header(pb, hpos); | |
347 } | |
348 | |
349 /* stream headers */ | |
350 for(n=0;n<s->nb_streams;n++) { | |
65 | 351 int64_t es_pos; |
0 | 352 // ASFStream *stream = &asf->streams[n]; |
353 | |
354 enc = &s->streams[n]->codec; | |
355 asf->streams[n].num = n + 1; | |
356 asf->streams[n].seq = 0; | |
357 | |
358 switch(enc->codec_type) { | |
359 case CODEC_TYPE_AUDIO: | |
360 wav_extra_size = 0; | |
361 extra_size = 18 + wav_extra_size; | |
362 extra_size2 = 0; | |
363 break; | |
364 default: | |
365 case CODEC_TYPE_VIDEO: | |
366 wav_extra_size = 0; | |
367 extra_size = 0x33; | |
368 extra_size2 = 0; | |
369 break; | |
370 } | |
371 | |
372 hpos = put_header(pb, &stream_header); | |
373 if (enc->codec_type == CODEC_TYPE_AUDIO) { | |
374 put_guid(pb, &audio_stream); | |
375 put_guid(pb, &audio_conceal_none); | |
376 } else { | |
377 put_guid(pb, &video_stream); | |
378 put_guid(pb, &video_conceal_none); | |
379 } | |
380 put_le64(pb, 0); /* ??? */ | |
381 es_pos = url_ftell(pb); | |
382 put_le32(pb, extra_size); /* wav header len */ | |
383 put_le32(pb, extra_size2); /* additional data len */ | |
384 put_le16(pb, n + 1); /* stream number */ | |
385 put_le32(pb, 0); /* ??? */ | |
386 | |
387 if (enc->codec_type == CODEC_TYPE_AUDIO) { | |
388 /* WAVEFORMATEX header */ | |
389 int wavsize = put_wav_header(pb, enc); | |
390 | |
391 if (wavsize < 0) | |
392 return -1; | |
393 if (wavsize != extra_size) { | |
394 cur_pos = url_ftell(pb); | |
395 url_fseek(pb, es_pos, SEEK_SET); | |
396 put_le32(pb, wavsize); /* wav header len */ | |
397 url_fseek(pb, cur_pos, SEEK_SET); | |
398 } | |
399 } else { | |
400 put_le32(pb, enc->width); | |
401 put_le32(pb, enc->height); | |
402 put_byte(pb, 2); /* ??? */ | |
403 put_le16(pb, 40); /* size */ | |
404 | |
405 /* BITMAPINFOHEADER header */ | |
406 put_bmp_header(pb, enc, codec_bmp_tags, 1); | |
407 } | |
408 end_header(pb, hpos); | |
409 } | |
410 | |
411 /* media comments */ | |
412 | |
413 hpos = put_header(pb, &codec_comment_header); | |
414 put_guid(pb, &codec_comment1_header); | |
415 put_le32(pb, s->nb_streams); | |
416 for(n=0;n<s->nb_streams;n++) { | |
417 AVCodec *p; | |
418 | |
419 enc = &s->streams[n]->codec; | |
420 p = avcodec_find_encoder(enc->codec_id); | |
421 | |
422 put_le16(pb, asf->streams[n].num); | |
423 put_str16(pb, p ? p->name : enc->codec_name); | |
424 put_le16(pb, 0); /* no parameters */ | |
196 | 425 |
426 | |
0 | 427 /* id */ |
428 if (enc->codec_type == CODEC_TYPE_AUDIO) { | |
429 put_le16(pb, 2); | |
196 | 430 if(!enc->codec_tag) |
431 enc->codec_tag = codec_get_tag(codec_wav_tags, enc->codec_id); | |
432 if(!enc->codec_tag) | |
433 return -1; | |
434 put_le16(pb, enc->codec_tag); | |
0 | 435 } else { |
436 put_le16(pb, 4); | |
196 | 437 if(!enc->codec_tag) |
438 enc->codec_tag = codec_get_tag(codec_bmp_tags, enc->codec_id); | |
439 if(!enc->codec_tag) | |
440 return -1; | |
441 put_le32(pb, enc->codec_tag); | |
0 | 442 } |
443 } | |
444 end_header(pb, hpos); | |
445 | |
446 /* patch the header size fields */ | |
447 | |
448 cur_pos = url_ftell(pb); | |
449 header_size = cur_pos - header_offset; | |
450 if (asf->is_streamed) { | |
451 header_size += 8 + 30 + 50; | |
452 | |
453 url_fseek(pb, header_offset - 10 - 30, SEEK_SET); | |
454 put_le16(pb, header_size); | |
455 url_fseek(pb, header_offset - 2 - 30, SEEK_SET); | |
456 put_le16(pb, header_size); | |
457 | |
458 header_size -= 8 + 30 + 50; | |
459 } | |
460 header_size += 24 + 6; | |
461 url_fseek(pb, header_offset - 14, SEEK_SET); | |
462 put_le64(pb, header_size); | |
463 url_fseek(pb, cur_pos, SEEK_SET); | |
464 | |
465 /* movie chunk, followed by packets of packet_size */ | |
466 asf->data_offset = cur_pos; | |
467 put_guid(pb, &data_header); | |
468 put_le64(pb, data_chunk_size); | |
469 put_guid(pb, &my_guid); | |
470 put_le64(pb, asf->nb_packets); /* nb packets */ | |
471 put_byte(pb, 1); /* ??? */ | |
472 put_byte(pb, 1); /* ??? */ | |
473 return 0; | |
474 } | |
475 | |
476 static int asf_write_header(AVFormatContext *s) | |
477 { | |
478 ASFContext *asf = s->priv_data; | |
479 | |
480 av_set_pts_info(s, 32, 1, 1000); /* 32 bit pts in ms */ | |
481 | |
482 asf->packet_size = PACKET_SIZE; | |
483 asf->nb_packets = 0; | |
484 | |
485 if (asf_write_header1(s, 0, 50) < 0) { | |
486 //av_free(asf); | |
487 return -1; | |
488 } | |
489 | |
490 put_flush_packet(&s->pb); | |
491 | |
492 asf->packet_nb_frames = 0; | |
493 asf->packet_timestamp_start = -1; | |
494 asf->packet_timestamp_end = -1; | |
495 asf->packet_size_left = asf->packet_size - PACKET_HEADER_SIZE; | |
496 init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size, 1, | |
497 NULL, NULL, NULL, NULL); | |
498 | |
499 return 0; | |
500 } | |
501 | |
502 static int asf_write_stream_header(AVFormatContext *s) | |
503 { | |
504 ASFContext *asf = s->priv_data; | |
505 | |
506 asf->is_streamed = 1; | |
507 | |
508 return asf_write_header(s); | |
509 } | |
510 | |
511 /* write a fixed size packet */ | |
512 static int put_packet(AVFormatContext *s, | |
513 unsigned int timestamp, unsigned int duration, | |
514 int nb_frames, int padsize) | |
515 { | |
516 ASFContext *asf = s->priv_data; | |
517 ByteIOContext *pb = &s->pb; | |
518 int flags; | |
519 | |
520 if (asf->is_streamed) { | |
521 put_chunk(s, 0x4424, asf->packet_size, 0); | |
522 } | |
523 | |
524 put_byte(pb, 0x82); | |
525 put_le16(pb, 0); | |
526 | |
527 flags = 0x01; /* nb segments present */ | |
528 if (padsize > 0) { | |
529 if (padsize < 256) | |
530 flags |= 0x08; | |
531 else | |
532 flags |= 0x10; | |
533 } | |
534 put_byte(pb, flags); /* flags */ | |
535 put_byte(pb, 0x5d); | |
536 if (flags & 0x10) | |
537 put_le16(pb, padsize - 2); | |
538 if (flags & 0x08) | |
539 put_byte(pb, padsize - 1); | |
540 put_le32(pb, timestamp); | |
541 put_le16(pb, duration); | |
542 put_byte(pb, nb_frames | 0x80); | |
543 | |
544 return PACKET_HEADER_SIZE + ((flags & 0x18) >> 3); | |
545 } | |
546 | |
547 static void flush_packet(AVFormatContext *s) | |
548 { | |
549 ASFContext *asf = s->priv_data; | |
550 int hdr_size, ptr; | |
551 | |
552 hdr_size = put_packet(s, asf->packet_timestamp_start, | |
553 asf->packet_timestamp_end - asf->packet_timestamp_start, | |
554 asf->packet_nb_frames, asf->packet_size_left); | |
555 | |
556 /* Clear out the padding bytes */ | |
557 ptr = asf->packet_size - hdr_size - asf->packet_size_left; | |
558 memset(asf->packet_buf + ptr, 0, asf->packet_size_left); | |
559 | |
560 put_buffer(&s->pb, asf->packet_buf, asf->packet_size - hdr_size); | |
561 | |
562 put_flush_packet(&s->pb); | |
563 asf->nb_packets++; | |
564 asf->packet_nb_frames = 0; | |
565 asf->packet_timestamp_start = -1; | |
566 asf->packet_timestamp_end = -1; | |
567 asf->packet_size_left = asf->packet_size - PACKET_HEADER_SIZE; | |
568 init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size, 1, | |
569 NULL, NULL, NULL, NULL); | |
570 } | |
571 | |
572 static void put_frame_header(AVFormatContext *s, ASFStream *stream, int timestamp, | |
573 int payload_size, int frag_offset, int frag_len) | |
574 { | |
575 ASFContext *asf = s->priv_data; | |
576 ByteIOContext *pb = &asf->pb; | |
577 int val; | |
578 | |
579 val = stream->num; | |
7 | 580 if (s->streams[val - 1]->codec.coded_frame->key_frame /* && frag_offset == 0 */) |
0 | 581 val |= 0x80; |
582 put_byte(pb, val); | |
583 put_byte(pb, stream->seq); | |
584 put_le32(pb, frag_offset); /* fragment offset */ | |
585 put_byte(pb, 0x08); /* flags */ | |
586 put_le32(pb, payload_size); | |
587 put_le32(pb, timestamp); | |
588 put_le16(pb, frag_len); | |
589 } | |
590 | |
591 | |
592 /* Output a frame. We suppose that payload_size <= PACKET_SIZE. | |
593 | |
594 It is there that you understand that the ASF format is really | |
595 crap. They have misread the MPEG Systems spec ! | |
596 */ | |
597 static void put_frame(AVFormatContext *s, ASFStream *stream, int timestamp, | |
241 | 598 const uint8_t *buf, int payload_size) |
0 | 599 { |
600 ASFContext *asf = s->priv_data; | |
601 int frag_pos, frag_len, frag_len1; | |
602 | |
603 frag_pos = 0; | |
604 while (frag_pos < payload_size) { | |
605 frag_len = payload_size - frag_pos; | |
606 frag_len1 = asf->packet_size_left - FRAME_HEADER_SIZE; | |
607 if (frag_len1 > 0) { | |
608 if (frag_len > frag_len1) | |
609 frag_len = frag_len1; | |
610 put_frame_header(s, stream, timestamp+1, payload_size, frag_pos, frag_len); | |
611 put_buffer(&asf->pb, buf, frag_len); | |
612 asf->packet_size_left -= (frag_len + FRAME_HEADER_SIZE); | |
613 asf->packet_timestamp_end = timestamp; | |
614 if (asf->packet_timestamp_start == -1) | |
615 asf->packet_timestamp_start = timestamp; | |
616 asf->packet_nb_frames++; | |
617 } else { | |
618 frag_len = 0; | |
619 } | |
620 frag_pos += frag_len; | |
621 buf += frag_len; | |
622 /* output the frame if filled */ | |
623 if (asf->packet_size_left <= FRAME_HEADER_SIZE) | |
624 flush_packet(s); | |
625 } | |
626 stream->seq++; | |
627 } | |
628 | |
629 | |
630 static int asf_write_packet(AVFormatContext *s, int stream_index, | |
241 | 631 const uint8_t *buf, int size, int64_t timestamp) |
0 | 632 { |
633 ASFContext *asf = s->priv_data; | |
634 ASFStream *stream; | |
65 | 635 int64_t duration; |
0 | 636 AVCodecContext *codec; |
637 | |
638 codec = &s->streams[stream_index]->codec; | |
639 stream = &asf->streams[stream_index]; | |
640 | |
641 if (codec->codec_type == CODEC_TYPE_AUDIO) { | |
65 | 642 duration = (codec->frame_number * codec->frame_size * int64_t_C(10000000)) / |
0 | 643 codec->sample_rate; |
644 } else { | |
85
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
84
diff
changeset
|
645 duration = av_rescale(codec->frame_number * codec->frame_rate_base, 10000000, codec->frame_rate); |
0 | 646 } |
647 if (duration > asf->duration) | |
648 asf->duration = duration; | |
649 | |
650 put_frame(s, stream, timestamp, buf, size); | |
651 return 0; | |
652 } | |
653 | |
654 static int asf_write_trailer(AVFormatContext *s) | |
655 { | |
656 ASFContext *asf = s->priv_data; | |
65 | 657 int64_t file_size; |
0 | 658 |
659 /* flush the current packet */ | |
660 if (asf->pb.buf_ptr > asf->pb.buffer) | |
661 flush_packet(s); | |
662 | |
663 if (asf->is_streamed) { | |
664 put_chunk(s, 0x4524, 0, 0); /* end of stream */ | |
665 } else { | |
666 /* rewrite an updated header */ | |
667 file_size = url_ftell(&s->pb); | |
668 url_fseek(&s->pb, 0, SEEK_SET); | |
669 asf_write_header1(s, file_size, file_size - asf->data_offset); | |
670 } | |
671 | |
672 put_flush_packet(&s->pb); | |
673 return 0; | |
674 } | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
241
diff
changeset
|
675 #endif //CONFIG_ENCODERS |
0 | 676 |
677 /**********************************/ | |
678 /* decoding */ | |
679 | |
680 //#define DEBUG | |
681 | |
682 #ifdef DEBUG | |
69 | 683 #define PRINT_IF_GUID(g,cmp) \ |
684 if (!memcmp(g, &cmp, sizeof(GUID))) \ | |
685 printf("(GUID: %s) ", #cmp) | |
686 | |
0 | 687 static void print_guid(const GUID *g) |
688 { | |
689 int i; | |
69 | 690 PRINT_IF_GUID(g, asf_header); |
691 else PRINT_IF_GUID(g, file_header); | |
692 else PRINT_IF_GUID(g, stream_header); | |
693 else PRINT_IF_GUID(g, audio_stream); | |
694 else PRINT_IF_GUID(g, audio_conceal_none); | |
695 else PRINT_IF_GUID(g, video_stream); | |
696 else PRINT_IF_GUID(g, video_conceal_none); | |
697 else PRINT_IF_GUID(g, comment_header); | |
698 else PRINT_IF_GUID(g, codec_comment_header); | |
699 else PRINT_IF_GUID(g, codec_comment1_header); | |
700 else PRINT_IF_GUID(g, data_header); | |
701 else PRINT_IF_GUID(g, index_guid); | |
702 else PRINT_IF_GUID(g, head1_guid); | |
703 else PRINT_IF_GUID(g, head2_guid); | |
704 else PRINT_IF_GUID(g, my_guid); | |
705 else | |
706 printf("(GUID: unknown) "); | |
0 | 707 printf("0x%08x, 0x%04x, 0x%04x, {", g->v1, g->v2, g->v3); |
708 for(i=0;i<8;i++) | |
709 printf(" 0x%02x,", g->v4[i]); | |
710 printf("}\n"); | |
711 } | |
69 | 712 #undef PRINT_IF_GUID(g,cmp) |
0 | 713 #endif |
714 | |
715 static void get_guid(ByteIOContext *s, GUID *g) | |
716 { | |
717 int i; | |
718 | |
719 g->v1 = get_le32(s); | |
720 g->v2 = get_le16(s); | |
721 g->v3 = get_le16(s); | |
722 for(i=0;i<8;i++) | |
723 g->v4[i] = get_byte(s); | |
724 } | |
725 | |
726 #if 0 | |
727 static void get_str16(ByteIOContext *pb, char *buf, int buf_size) | |
728 { | |
729 int len, c; | |
730 char *q; | |
731 | |
732 len = get_le16(pb); | |
733 q = buf; | |
734 while (len > 0) { | |
735 c = get_le16(pb); | |
736 if ((q - buf) < buf_size - 1) | |
737 *q++ = c; | |
738 len--; | |
739 } | |
740 *q = '\0'; | |
741 } | |
742 #endif | |
743 | |
744 static void get_str16_nolen(ByteIOContext *pb, int len, char *buf, int buf_size) | |
745 { | |
746 int c; | |
747 char *q; | |
748 | |
749 q = buf; | |
750 while (len > 0) { | |
751 c = get_le16(pb); | |
752 if ((q - buf) < buf_size - 1) | |
753 *q++ = c; | |
754 len-=2; | |
755 } | |
756 *q = '\0'; | |
757 } | |
758 | |
759 static int asf_probe(AVProbeData *pd) | |
760 { | |
761 GUID g; | |
762 const unsigned char *p; | |
763 int i; | |
764 | |
765 /* check file header */ | |
766 if (pd->buf_size <= 32) | |
767 return 0; | |
768 p = pd->buf; | |
769 g.v1 = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); | |
770 p += 4; | |
771 g.v2 = p[0] | (p[1] << 8); | |
772 p += 2; | |
773 g.v3 = p[0] | (p[1] << 8); | |
774 p += 2; | |
775 for(i=0;i<8;i++) | |
776 g.v4[i] = *p++; | |
777 | |
778 if (!memcmp(&g, &asf_header, sizeof(GUID))) | |
779 return AVPROBE_SCORE_MAX; | |
780 else | |
781 return 0; | |
782 } | |
783 | |
784 static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap) | |
785 { | |
786 ASFContext *asf = s->priv_data; | |
787 GUID g; | |
788 ByteIOContext *pb = &s->pb; | |
789 AVStream *st; | |
790 ASFStream *asf_st; | |
791 int size, i; | |
65 | 792 int64_t gsize; |
0 | 793 |
794 av_set_pts_info(s, 32, 1, 1000); /* 32 bit pts in ms */ | |
795 | |
796 get_guid(pb, &g); | |
797 if (memcmp(&g, &asf_header, sizeof(GUID))) | |
798 goto fail; | |
799 get_le64(pb); | |
800 get_le32(pb); | |
801 get_byte(pb); | |
802 get_byte(pb); | |
803 memset(&asf->asfid2avid, -1, sizeof(asf->asfid2avid)); | |
804 for(;;) { | |
805 get_guid(pb, &g); | |
806 gsize = get_le64(pb); | |
807 #ifdef DEBUG | |
808 printf("%08Lx: ", url_ftell(pb) - 24); | |
809 print_guid(&g); | |
810 printf(" size=0x%Lx\n", gsize); | |
811 #endif | |
812 if (gsize < 24) | |
813 goto fail; | |
814 if (!memcmp(&g, &file_header, sizeof(GUID))) { | |
815 get_guid(pb, &asf->hdr.guid); | |
816 asf->hdr.file_size = get_le64(pb); | |
817 asf->hdr.create_time = get_le64(pb); | |
818 asf->hdr.packets_count = get_le64(pb); | |
819 asf->hdr.play_time = get_le64(pb); | |
820 asf->hdr.send_time = get_le64(pb); | |
821 asf->hdr.preroll = get_le32(pb); | |
822 asf->hdr.ignore = get_le32(pb); | |
823 asf->hdr.flags = get_le32(pb); | |
824 asf->hdr.min_pktsize = get_le32(pb); | |
825 asf->hdr.max_pktsize = get_le32(pb); | |
826 asf->hdr.max_bitrate = get_le32(pb); | |
827 asf->packet_size = asf->hdr.max_pktsize; | |
828 asf->nb_packets = asf->hdr.packets_count; | |
829 } else if (!memcmp(&g, &stream_header, sizeof(GUID))) { | |
84
0068a6902911
correct AUDIO strf parsing patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
74
diff
changeset
|
830 int type, total_size, type_specific_size; |
0 | 831 unsigned int tag1; |
65 | 832 int64_t pos1, pos2; |
0 | 833 |
834 pos1 = url_ftell(pb); | |
835 | |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
136
diff
changeset
|
836 st = av_new_stream(s, 0); |
0 | 837 if (!st) |
838 goto fail; | |
839 asf_st = av_mallocz(sizeof(ASFStream)); | |
840 if (!asf_st) | |
841 goto fail; | |
842 st->priv_data = asf_st; | |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
136
diff
changeset
|
843 st->start_time = asf->hdr.preroll / (10000000 / AV_TIME_BASE); |
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
136
diff
changeset
|
844 st->duration = (asf->hdr.send_time - asf->hdr.preroll) / |
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
136
diff
changeset
|
845 (10000000 / AV_TIME_BASE); |
0 | 846 get_guid(pb, &g); |
847 if (!memcmp(&g, &audio_stream, sizeof(GUID))) { | |
848 type = CODEC_TYPE_AUDIO; | |
849 } else if (!memcmp(&g, &video_stream, sizeof(GUID))) { | |
850 type = CODEC_TYPE_VIDEO; | |
851 } else { | |
852 goto fail; | |
853 } | |
854 get_guid(pb, &g); | |
855 total_size = get_le64(pb); | |
84
0068a6902911
correct AUDIO strf parsing patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
74
diff
changeset
|
856 type_specific_size = get_le32(pb); |
0 | 857 get_le32(pb); |
858 st->id = get_le16(pb) & 0x7f; /* stream id */ | |
859 // mapping of asf ID to AV stream ID; | |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
136
diff
changeset
|
860 asf->asfid2avid[st->id] = s->nb_streams - 1; |
0 | 861 |
862 get_le32(pb); | |
863 st->codec.codec_type = type; | |
312
8a04d2e1be2f
frame rate should be completely disabled in asf (closer now) - disabled seek
bellard
parents:
300
diff
changeset
|
864 /* 1 fps default (XXX: put 0 fps instead) */ |
8a04d2e1be2f
frame rate should be completely disabled in asf (closer now) - disabled seek
bellard
parents:
300
diff
changeset
|
865 st->codec.frame_rate = 1; |
8a04d2e1be2f
frame rate should be completely disabled in asf (closer now) - disabled seek
bellard
parents:
300
diff
changeset
|
866 st->codec.frame_rate_base = 1; |
0 | 867 if (type == CODEC_TYPE_AUDIO) { |
84
0068a6902911
correct AUDIO strf parsing patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
74
diff
changeset
|
868 get_wav_header(pb, &st->codec, type_specific_size); |
312
8a04d2e1be2f
frame rate should be completely disabled in asf (closer now) - disabled seek
bellard
parents:
300
diff
changeset
|
869 st->need_parsing = 1; |
0 | 870 /* We have to init the frame size at some point .... */ |
871 pos2 = url_ftell(pb); | |
872 if (gsize > (pos2 + 8 - pos1 + 24)) { | |
873 asf_st->ds_span = get_byte(pb); | |
874 asf_st->ds_packet_size = get_le16(pb); | |
875 asf_st->ds_chunk_size = get_le16(pb); | |
876 asf_st->ds_data_size = get_le16(pb); | |
877 asf_st->ds_silence_data = get_byte(pb); | |
878 } | |
879 //printf("Descrambling: ps:%d cs:%d ds:%d s:%d sd:%d\n", | |
880 // asf_st->ds_packet_size, asf_st->ds_chunk_size, | |
881 // asf_st->ds_data_size, asf_st->ds_span, asf_st->ds_silence_data); | |
882 if (asf_st->ds_span > 1) { | |
883 if (!asf_st->ds_chunk_size | |
884 || (asf_st->ds_packet_size/asf_st->ds_chunk_size <= 1)) | |
885 asf_st->ds_span = 0; // disable descrambling | |
886 } | |
887 switch (st->codec.codec_id) { | |
232 | 888 case CODEC_ID_MP3: |
0 | 889 st->codec.frame_size = MPA_FRAME_SIZE; |
890 break; | |
891 case CODEC_ID_PCM_S16LE: | |
892 case CODEC_ID_PCM_S16BE: | |
893 case CODEC_ID_PCM_U16LE: | |
894 case CODEC_ID_PCM_U16BE: | |
895 case CODEC_ID_PCM_S8: | |
896 case CODEC_ID_PCM_U8: | |
897 case CODEC_ID_PCM_ALAW: | |
898 case CODEC_ID_PCM_MULAW: | |
899 st->codec.frame_size = 1; | |
900 break; | |
901 default: | |
902 /* This is probably wrong, but it prevents a crash later */ | |
903 st->codec.frame_size = 1; | |
904 break; | |
905 } | |
906 } else { | |
907 get_le32(pb); | |
908 get_le32(pb); | |
909 get_byte(pb); | |
910 size = get_le16(pb); /* size */ | |
911 get_le32(pb); /* size */ | |
912 st->codec.width = get_le32(pb); | |
913 st->codec.height = get_le32(pb); | |
914 /* not available for asf */ | |
915 get_le16(pb); /* panes */ | |
117 | 916 st->codec.bits_per_sample = get_le16(pb); /* depth */ |
0 | 917 tag1 = get_le32(pb); |
918 url_fskip(pb, 20); | |
919 if (size > 40) { | |
920 st->codec.extradata_size = size - 40; | |
921 st->codec.extradata = av_mallocz(st->codec.extradata_size); | |
922 get_buffer(pb, st->codec.extradata, st->codec.extradata_size); | |
923 } | |
297
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
277
diff
changeset
|
924 |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
277
diff
changeset
|
925 /* Extract palette from extradata if bpp <= 8 */ |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
277
diff
changeset
|
926 /* This code assumes that extradata contains only palette */ |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
277
diff
changeset
|
927 /* This is true for all paletted codecs implemented in ffmpeg */ |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
277
diff
changeset
|
928 if (st->codec.extradata_size && (st->codec.bits_per_sample <= 8)) { |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
277
diff
changeset
|
929 st->codec.palctrl = av_mallocz(sizeof(AVPaletteControl)); |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
277
diff
changeset
|
930 #ifdef WORDS_BIGENDIAN |
300
6ee1b02f9b2a
* fixes for broken builds on Solaris, OS2 and all bingendian
romansh
parents:
297
diff
changeset
|
931 for (i = 0; i < FFMIN(st->codec.extradata_size, AVPALETTE_SIZE)/4; i++) |
6ee1b02f9b2a
* fixes for broken builds on Solaris, OS2 and all bingendian
romansh
parents:
297
diff
changeset
|
932 st->codec.palctrl->palette[i] = bswap_32(((uint32_t*)st->codec.extradata)[i]); |
297
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
277
diff
changeset
|
933 #else |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
277
diff
changeset
|
934 memcpy(st->codec.palctrl->palette, st->codec.extradata, |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
277
diff
changeset
|
935 FFMIN(st->codec.extradata_size, AVPALETTE_SIZE)); |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
277
diff
changeset
|
936 #endif |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
277
diff
changeset
|
937 st->codec.palctrl->palette_changed = 1; |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
277
diff
changeset
|
938 } |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
277
diff
changeset
|
939 |
74 | 940 st->codec.codec_tag = tag1; |
0 | 941 st->codec.codec_id = codec_get_id(codec_bmp_tags, tag1); |
942 } | |
943 pos2 = url_ftell(pb); | |
944 url_fskip(pb, gsize - (pos2 - pos1 + 24)); | |
945 } else if (!memcmp(&g, &data_header, sizeof(GUID))) { | |
946 break; | |
947 } else if (!memcmp(&g, &comment_header, sizeof(GUID))) { | |
948 int len1, len2, len3, len4, len5; | |
949 | |
950 len1 = get_le16(pb); | |
951 len2 = get_le16(pb); | |
952 len3 = get_le16(pb); | |
953 len4 = get_le16(pb); | |
954 len5 = get_le16(pb); | |
955 get_str16_nolen(pb, len1, s->title, sizeof(s->title)); | |
956 get_str16_nolen(pb, len2, s->author, sizeof(s->author)); | |
957 get_str16_nolen(pb, len3, s->copyright, sizeof(s->copyright)); | |
958 get_str16_nolen(pb, len4, s->comment, sizeof(s->comment)); | |
959 url_fskip(pb, len5); | |
341
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
960 } else if (!memcmp(&g, &extended_content_header, sizeof(GUID))) { |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
961 int desc_count, i; |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
962 |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
963 desc_count = get_le16(pb); |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
964 for(i=0;i<desc_count;i++) |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
965 { |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
966 int name_len,value_type,value_len,value_num = 0; |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
967 char *name, *value; |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
968 |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
969 name_len = get_le16(pb); |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
970 name = (char *)av_mallocz(name_len); |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
971 get_str16_nolen(pb, name_len, name, name_len); |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
972 value_type = get_le16(pb); |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
973 value_len = get_le16(pb); |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
974 if ((value_type == 0) || (value_type == 1)) // unicode or byte |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
975 { |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
976 value = (char *)av_mallocz(value_len); |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
977 get_str16_nolen(pb, value_len, value, value_len); |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
978 if (strcmp(name,"WM/AlbumTitle")==0) { strcpy(s->album, value); } |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
979 av_free(value); |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
980 } |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
981 if ((value_type >= 2) || (value_type <= 5)) // boolean or DWORD or QWORD or WORD |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
982 { |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
983 if (value_type==2) value_num = get_le32(pb); |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
984 if (value_type==3) value_num = get_le32(pb); |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
985 if (value_type==4) value_num = get_le64(pb); |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
986 if (value_type==5) value_num = get_le16(pb); |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
987 if (strcmp(name,"WM/Track")==0) s->track = value_num + 1; |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
988 if (strcmp(name,"WM/TrackNumber")==0) s->track = value_num; |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
989 } |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
990 av_free(name); |
ad2a57c5467a
ASF extended header parsing patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
312
diff
changeset
|
991 } |
0 | 992 #if 0 |
993 } else if (!memcmp(&g, &head1_guid, sizeof(GUID))) { | |
994 int v1, v2; | |
995 get_guid(pb, &g); | |
996 v1 = get_le32(pb); | |
997 v2 = get_le16(pb); | |
998 } else if (!memcmp(&g, &codec_comment_header, sizeof(GUID))) { | |
999 int len, v1, n, num; | |
1000 char str[256], *q; | |
1001 char tag[16]; | |
1002 | |
1003 get_guid(pb, &g); | |
1004 print_guid(&g); | |
1005 | |
1006 n = get_le32(pb); | |
1007 for(i=0;i<n;i++) { | |
1008 num = get_le16(pb); /* stream number */ | |
1009 get_str16(pb, str, sizeof(str)); | |
1010 get_str16(pb, str, sizeof(str)); | |
1011 len = get_le16(pb); | |
1012 q = tag; | |
1013 while (len > 0) { | |
1014 v1 = get_byte(pb); | |
1015 if ((q - tag) < sizeof(tag) - 1) | |
1016 *q++ = v1; | |
1017 len--; | |
1018 } | |
1019 *q = '\0'; | |
1020 } | |
1021 #endif | |
1022 } else if (url_feof(pb)) { | |
1023 goto fail; | |
1024 } else { | |
1025 url_fseek(pb, gsize - 24, SEEK_CUR); | |
1026 } | |
1027 } | |
1028 get_guid(pb, &g); | |
1029 get_le64(pb); | |
1030 get_byte(pb); | |
1031 get_byte(pb); | |
1032 if (url_feof(pb)) | |
1033 goto fail; | |
1034 asf->data_offset = url_ftell(pb); | |
1035 asf->packet_size_left = 0; | |
1036 | |
1037 return 0; | |
1038 | |
1039 fail: | |
1040 for(i=0;i<s->nb_streams;i++) { | |
1041 AVStream *st = s->streams[i]; | |
1042 if (st) { | |
1043 av_free(st->priv_data); | |
1044 av_free(st->codec.extradata); | |
1045 } | |
1046 av_free(st); | |
1047 } | |
1048 return -1; | |
1049 } | |
1050 | |
1051 #define DO_2BITS(bits, var, defval) \ | |
1052 switch (bits & 3) \ | |
1053 { \ | |
1054 case 3: var = get_le32(pb); rsize += 4; break; \ | |
1055 case 2: var = get_le16(pb); rsize += 2; break; \ | |
1056 case 1: var = get_byte(pb); rsize++; break; \ | |
1057 default: var = defval; break; \ | |
1058 } | |
1059 | |
1060 static int asf_get_packet(AVFormatContext *s) | |
1061 { | |
1062 ASFContext *asf = s->priv_data; | |
1063 ByteIOContext *pb = &s->pb; | |
1064 uint32_t packet_length, padsize; | |
353 | 1065 int rsize = 9; |
1066 int c; | |
1067 | |
1068 assert((url_ftell(&s->pb) - s->data_offset) % asf->packet_size == 0); | |
1069 | |
1070 c = get_byte(pb); | |
0 | 1071 if (c != 0x82) { |
1072 if (!url_feof(pb)) | |
136 | 1073 printf("ff asf bad header %x at:%lld\n", c, url_ftell(pb)); |
0 | 1074 } |
1075 if ((c & 0x0f) == 2) { // always true for now | |
1076 if (get_le16(pb) != 0) { | |
1077 if (!url_feof(pb)) | |
1078 printf("ff asf bad non zero\n"); | |
1079 return -EIO; | |
1080 } | |
353 | 1081 rsize+=2; |
1082 /* }else{ | |
1083 if (!url_feof(pb)) | |
1084 printf("ff asf bad header %x at:%lld\n", c, url_ftell(pb)); | |
1085 return -EIO;*/ | |
0 | 1086 } |
1087 | |
1088 asf->packet_flags = get_byte(pb); | |
1089 asf->packet_property = get_byte(pb); | |
1090 | |
1091 DO_2BITS(asf->packet_flags >> 5, packet_length, asf->packet_size); | |
1092 DO_2BITS(asf->packet_flags >> 1, padsize, 0); // sequence ignored | |
1093 DO_2BITS(asf->packet_flags >> 3, padsize, 0); // padding length | |
1094 | |
1095 asf->packet_timestamp = get_le32(pb); | |
1096 get_le16(pb); /* duration */ | |
1097 // rsize has at least 11 bytes which have to be present | |
1098 | |
1099 if (asf->packet_flags & 0x01) { | |
1100 asf->packet_segsizetype = get_byte(pb); rsize++; | |
1101 asf->packet_segments = asf->packet_segsizetype & 0x3f; | |
1102 } else { | |
1103 asf->packet_segments = 1; | |
1104 asf->packet_segsizetype = 0x80; | |
1105 } | |
1106 asf->packet_size_left = packet_length - padsize - rsize; | |
1107 if (packet_length < asf->hdr.min_pktsize) | |
1108 padsize += asf->hdr.min_pktsize - packet_length; | |
1109 asf->packet_padsize = padsize; | |
1110 #ifdef DEBUG | |
1111 printf("packet: size=%d padsize=%d left=%d\n", asf->packet_size, asf->packet_padsize, asf->packet_size_left); | |
1112 #endif | |
1113 return 0; | |
1114 } | |
1115 | |
1116 static int asf_read_packet(AVFormatContext *s, AVPacket *pkt) | |
1117 { | |
1118 ASFContext *asf = s->priv_data; | |
1119 ASFStream *asf_st = 0; | |
1120 ByteIOContext *pb = &s->pb; | |
1121 //static int pc = 0; | |
1122 for (;;) { | |
1123 int rsize = 0; | |
1124 if (asf->packet_size_left < FRAME_HEADER_SIZE | |
1125 || asf->packet_segments < 1) { | |
1126 //asf->packet_size_left <= asf->packet_padsize) { | |
1127 int ret = asf->packet_size_left + asf->packet_padsize; | |
1128 //printf("PacketLeftSize:%d Pad:%d Pos:%Ld\n", asf->packet_size_left, asf->packet_padsize, url_ftell(pb)); | |
1129 /* fail safe */ | |
1130 url_fskip(pb, ret); | |
349 | 1131 asf->packet_pos= url_ftell(&s->pb); |
0 | 1132 ret = asf_get_packet(s); |
1133 //printf("READ ASF PACKET %d r:%d c:%d\n", ret, asf->packet_size_left, pc++); | |
1134 if (ret < 0 || url_feof(pb)) | |
1135 return -EIO; | |
1136 asf->packet_time_start = 0; | |
1137 continue; | |
1138 } | |
1139 if (asf->packet_time_start == 0) { | |
1140 /* read frame header */ | |
1141 int num = get_byte(pb); | |
1142 asf->packet_segments--; | |
1143 rsize++; | |
1144 asf->packet_key_frame = (num & 0x80) >> 7; | |
1145 asf->stream_index = asf->asfid2avid[num & 0x7f]; | |
1146 // sequence should be ignored! | |
1147 DO_2BITS(asf->packet_property >> 4, asf->packet_seq, 0); | |
1148 DO_2BITS(asf->packet_property >> 2, asf->packet_frag_offset, 0); | |
1149 DO_2BITS(asf->packet_property, asf->packet_replic_size, 0); | |
349 | 1150 //printf("key:%d stream:%d seq:%d offset:%d replic_size:%d\n", asf->packet_key_frame, asf->stream_index, asf->packet_seq, //asf->packet_frag_offset, asf->packet_replic_size); |
0 | 1151 if (asf->packet_replic_size > 1) { |
352
c5ea5cdb5b58
replic_size==0 fix, needed so that G.726 asf file, so ffmpeg can at least decode the video without segfaulting
michael
parents:
351
diff
changeset
|
1152 assert(asf->packet_replic_size >= 8); |
0 | 1153 // it should be always at least 8 bytes - FIXME validate |
1154 asf->packet_obj_size = get_le32(pb); | |
1155 asf->packet_frag_timestamp = get_le32(pb); // timestamp | |
1156 if (asf->packet_replic_size > 8) | |
1157 url_fskip(pb, asf->packet_replic_size - 8); | |
1158 rsize += asf->packet_replic_size; // FIXME - check validity | |
352
c5ea5cdb5b58
replic_size==0 fix, needed so that G.726 asf file, so ffmpeg can at least decode the video without segfaulting
michael
parents:
351
diff
changeset
|
1159 } else if (asf->packet_replic_size==1){ |
0 | 1160 // multipacket - frag_offset is begining timestamp |
1161 asf->packet_time_start = asf->packet_frag_offset; | |
1162 asf->packet_frag_offset = 0; | |
1163 asf->packet_frag_timestamp = asf->packet_timestamp; | |
1164 | |
352
c5ea5cdb5b58
replic_size==0 fix, needed so that G.726 asf file, so ffmpeg can at least decode the video without segfaulting
michael
parents:
351
diff
changeset
|
1165 asf->packet_time_delta = get_byte(pb); |
c5ea5cdb5b58
replic_size==0 fix, needed so that G.726 asf file, so ffmpeg can at least decode the video without segfaulting
michael
parents:
351
diff
changeset
|
1166 rsize++; |
c5ea5cdb5b58
replic_size==0 fix, needed so that G.726 asf file, so ffmpeg can at least decode the video without segfaulting
michael
parents:
351
diff
changeset
|
1167 }else{ |
c5ea5cdb5b58
replic_size==0 fix, needed so that G.726 asf file, so ffmpeg can at least decode the video without segfaulting
michael
parents:
351
diff
changeset
|
1168 assert(asf->packet_replic_size==0); |
c5ea5cdb5b58
replic_size==0 fix, needed so that G.726 asf file, so ffmpeg can at least decode the video without segfaulting
michael
parents:
351
diff
changeset
|
1169 } |
0 | 1170 if (asf->packet_flags & 0x01) { |
1171 DO_2BITS(asf->packet_segsizetype >> 6, asf->packet_frag_size, 0); // 0 is illegal | |
1172 #undef DO_2BITS | |
1173 //printf("Fragsize %d\n", asf->packet_frag_size); | |
1174 } else { | |
1175 asf->packet_frag_size = asf->packet_size_left - rsize; | |
1176 //printf("Using rest %d %d %d\n", asf->packet_frag_size, asf->packet_size_left, rsize); | |
1177 } | |
1178 if (asf->packet_replic_size == 1) { | |
1179 asf->packet_multi_size = asf->packet_frag_size; | |
1180 if (asf->packet_multi_size > asf->packet_size_left) { | |
1181 asf->packet_segments = 0; | |
1182 continue; | |
1183 } | |
1184 } | |
1185 asf->packet_size_left -= rsize; | |
1186 //printf("___objsize____ %d %d rs:%d\n", asf->packet_obj_size, asf->packet_frag_offset, rsize); | |
1187 | |
1188 if (asf->stream_index < 0) { | |
1189 asf->packet_time_start = 0; | |
1190 /* unhandled packet (should not happen) */ | |
1191 url_fskip(pb, asf->packet_frag_size); | |
1192 asf->packet_size_left -= asf->packet_frag_size; | |
1193 printf("ff asf skip %d %d\n", asf->packet_frag_size, num & 0x7f); | |
1194 continue; | |
1195 } | |
1196 asf->asf_st = s->streams[asf->stream_index]->priv_data; | |
1197 } | |
1198 asf_st = asf->asf_st; | |
1199 | |
1200 if ((asf->packet_frag_offset != asf_st->frag_offset | |
1201 || (asf->packet_frag_offset | |
1202 && asf->packet_seq != asf_st->seq)) // seq should be ignored | |
1203 ) { | |
1204 /* cannot continue current packet: free it */ | |
1205 // FIXME better check if packet was already allocated | |
1206 printf("ff asf parser skips: %d - %d o:%d - %d %d %d fl:%d\n", | |
1207 asf_st->pkt.size, | |
1208 asf->packet_obj_size, | |
1209 asf->packet_frag_offset, asf_st->frag_offset, | |
1210 asf->packet_seq, asf_st->seq, asf->packet_frag_size); | |
1211 if (asf_st->pkt.size) | |
1212 av_free_packet(&asf_st->pkt); | |
1213 asf_st->frag_offset = 0; | |
1214 if (asf->packet_frag_offset != 0) { | |
1215 url_fskip(pb, asf->packet_frag_size); | |
1216 printf("ff asf parser skiping %db\n", asf->packet_frag_size); | |
1217 asf->packet_size_left -= asf->packet_frag_size; | |
1218 continue; | |
1219 } | |
1220 } | |
1221 if (asf->packet_replic_size == 1) { | |
1222 // frag_offset is here used as the begining timestamp | |
1223 asf->packet_frag_timestamp = asf->packet_time_start; | |
1224 asf->packet_time_start += asf->packet_time_delta; | |
1225 asf->packet_obj_size = asf->packet_frag_size = get_byte(pb); | |
1226 asf->packet_size_left--; | |
1227 asf->packet_multi_size--; | |
1228 if (asf->packet_multi_size < asf->packet_obj_size) | |
1229 { | |
1230 asf->packet_time_start = 0; | |
1231 url_fskip(pb, asf->packet_multi_size); | |
1232 asf->packet_size_left -= asf->packet_multi_size; | |
1233 continue; | |
1234 } | |
1235 asf->packet_multi_size -= asf->packet_obj_size; | |
1236 //printf("COMPRESS size %d %d %d ms:%d\n", asf->packet_obj_size, asf->packet_frag_timestamp, asf->packet_size_left, asf->packet_multi_size); | |
1237 } | |
1238 if (asf_st->frag_offset == 0) { | |
1239 /* new packet */ | |
1240 av_new_packet(&asf_st->pkt, asf->packet_obj_size); | |
1241 asf_st->seq = asf->packet_seq; | |
1242 asf_st->pkt.pts = asf->packet_frag_timestamp - asf->hdr.preroll; | |
1243 asf_st->pkt.stream_index = asf->stream_index; | |
352
c5ea5cdb5b58
replic_size==0 fix, needed so that G.726 asf file, so ffmpeg can at least decode the video without segfaulting
michael
parents:
351
diff
changeset
|
1244 asf_st->packet_pos= asf->packet_pos; |
c5ea5cdb5b58
replic_size==0 fix, needed so that G.726 asf file, so ffmpeg can at least decode the video without segfaulting
michael
parents:
351
diff
changeset
|
1245 //printf("new packet: stream:%d key:%d packet_key:%d audio:%d size:%d\n", |
349 | 1246 //asf->stream_index, asf->packet_key_frame, asf_st->pkt.flags & PKT_FLAG_KEY, |
352
c5ea5cdb5b58
replic_size==0 fix, needed so that G.726 asf file, so ffmpeg can at least decode the video without segfaulting
michael
parents:
351
diff
changeset
|
1247 //s->streams[asf->stream_index]->codec.codec_type == CODEC_TYPE_AUDIO, asf->packet_obj_size); |
347
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1248 if (s->streams[asf->stream_index]->codec.codec_type == CODEC_TYPE_AUDIO) |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1249 asf->packet_key_frame = 1; |
0 | 1250 if (asf->packet_key_frame) |
1251 asf_st->pkt.flags |= PKT_FLAG_KEY; | |
1252 } | |
1253 | |
1254 /* read data */ | |
1255 //printf("READ PACKET s:%d os:%d o:%d,%d l:%d DATA:%p\n", | |
1256 // asf->packet_size, asf_st->pkt.size, asf->packet_frag_offset, | |
1257 // asf_st->frag_offset, asf->packet_frag_size, asf_st->pkt.data); | |
1258 asf->packet_size_left -= asf->packet_frag_size; | |
1259 if (asf->packet_size_left < 0) | |
1260 continue; | |
1261 get_buffer(pb, asf_st->pkt.data + asf->packet_frag_offset, | |
1262 asf->packet_frag_size); | |
1263 asf_st->frag_offset += asf->packet_frag_size; | |
1264 /* test if whole packet is read */ | |
1265 if (asf_st->frag_offset == asf_st->pkt.size) { | |
1266 /* return packet */ | |
1267 if (asf_st->ds_span > 1) { | |
1268 /* packet descrambling */ | |
1269 char* newdata = av_malloc(asf_st->pkt.size); | |
1270 if (newdata) { | |
1271 int offset = 0; | |
1272 while (offset < asf_st->pkt.size) { | |
1273 int off = offset / asf_st->ds_chunk_size; | |
1274 int row = off / asf_st->ds_span; | |
1275 int col = off % asf_st->ds_span; | |
1276 int idx = row + col * asf_st->ds_packet_size / asf_st->ds_chunk_size; | |
1277 //printf("off:%d row:%d col:%d idx:%d\n", off, row, col, idx); | |
1278 memcpy(newdata + offset, | |
1279 asf_st->pkt.data + idx * asf_st->ds_chunk_size, | |
1280 asf_st->ds_chunk_size); | |
1281 offset += asf_st->ds_chunk_size; | |
1282 } | |
1283 av_free(asf_st->pkt.data); | |
1284 asf_st->pkt.data = newdata; | |
1285 } | |
1286 } | |
1287 asf_st->frag_offset = 0; | |
1288 memcpy(pkt, &asf_st->pkt, sizeof(AVPacket)); | |
1289 //printf("packet %d %d\n", asf_st->pkt.size, asf->packet_frag_size); | |
1290 asf_st->pkt.size = 0; | |
1291 asf_st->pkt.data = 0; | |
1292 break; // packet completed | |
1293 } | |
1294 } | |
1295 return 0; | |
1296 } | |
1297 | |
1298 static int asf_read_close(AVFormatContext *s) | |
1299 { | |
1300 int i; | |
1301 | |
1302 for(i=0;i<s->nb_streams;i++) { | |
1303 AVStream *st = s->streams[i]; | |
1304 av_free(st->priv_data); | |
1305 av_free(st->codec.extradata); | |
297
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
277
diff
changeset
|
1306 av_free(st->codec.palctrl); |
0 | 1307 } |
1308 return 0; | |
1309 } | |
1310 | |
347
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1311 // Added to support seeking after packets have been read |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1312 // If information is not reset, read_packet fails due to |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1313 // leftover information from previous reads |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1314 static void asf_reset_header(AVFormatContext *s) |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1315 { |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1316 ASFContext *asf = s->priv_data; |
349 | 1317 ASFStream *asf_st; |
1318 int i; | |
347
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1319 |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1320 asf->packet_nb_frames = 0; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1321 asf->packet_timestamp_start = -1; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1322 asf->packet_timestamp_end = -1; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1323 asf->packet_size_left = 0; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1324 asf->packet_segments = 0; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1325 asf->packet_flags = 0; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1326 asf->packet_property = 0; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1327 asf->packet_timestamp = 0; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1328 asf->packet_segsizetype = 0; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1329 asf->packet_segments = 0; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1330 asf->packet_seq = 0; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1331 asf->packet_replic_size = 0; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1332 asf->packet_key_frame = 0; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1333 asf->packet_padsize = 0; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1334 asf->packet_frag_offset = 0; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1335 asf->packet_frag_size = 0; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1336 asf->packet_frag_timestamp = 0; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1337 asf->packet_multi_size = 0; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1338 asf->packet_obj_size = 0; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1339 asf->packet_time_delta = 0; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1340 asf->packet_time_start = 0; |
349 | 1341 |
1342 for(i=0; i<s->nb_streams; i++){ | |
1343 asf_st= s->streams[i]->priv_data; | |
1344 av_free_packet(&asf_st->pkt); | |
1345 asf_st->frag_offset=0; | |
1346 asf_st->seq=0; | |
1347 } | |
1348 asf->asf_st= NULL; | |
347
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1349 } |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1350 |
348 | 1351 static int64_t asf_read_pts(AVFormatContext *s, int64_t *ppos, int stream_index) |
347
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1352 { |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1353 ASFContext *asf = s->priv_data; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1354 AVPacket pkt1, *pkt = &pkt1; |
349 | 1355 ASFStream *asf_st; |
1356 int64_t pts; | |
348 | 1357 int64_t pos= *ppos; |
354
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1358 int i; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1359 int64_t start_pos[s->nb_streams]; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1360 |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1361 for(i=0; i<s->nb_streams; i++){ |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1362 start_pos[i]= pos; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1363 } |
348 | 1364 |
349 | 1365 //printf("asf_read_pts\n"); |
351
c072833fe7f4
use packet number instead of byte number internally for seeking
michael
parents:
350
diff
changeset
|
1366 url_fseek(&s->pb, pos*asf->packet_size + s->data_offset, SEEK_SET); |
349 | 1367 asf_reset_header(s); |
354
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1368 for(;;){ |
349 | 1369 if (av_read_frame(s, pkt) < 0){ |
1370 printf("seek failed\n"); | |
348 | 1371 return AV_NOPTS_VALUE; |
349 | 1372 } |
348 | 1373 pts= pkt->pts; |
347
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1374 |
348 | 1375 av_free_packet(pkt); |
354
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1376 if(pkt->flags&PKT_FLAG_KEY){ |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1377 i= pkt->stream_index; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1378 |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1379 asf_st= s->streams[i]->priv_data; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1380 |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1381 assert((asf_st->packet_pos - s->data_offset) % asf->packet_size == 0); |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1382 pos= (asf_st->packet_pos - s->data_offset) / asf->packet_size; |
351
c072833fe7f4
use packet number instead of byte number internally for seeking
michael
parents:
350
diff
changeset
|
1383 |
354
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1384 av_add_index_entry(s->streams[i], pos, pts, pos - start_pos[i] + 1, AVINDEX_KEYFRAME); |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1385 start_pos[i]= pos + 1; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1386 |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1387 if(pkt->stream_index == stream_index) |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1388 break; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1389 } |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1390 } |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1391 |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1392 *ppos= pos; |
349 | 1393 //printf("found keyframe at %Ld stream %d stamp:%Ld\n", *ppos, stream_index, pts); |
348 | 1394 |
1395 return pts; | |
347
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1396 } |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1397 |
312
8a04d2e1be2f
frame rate should be completely disabled in asf (closer now) - disabled seek
bellard
parents:
300
diff
changeset
|
1398 static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts) |
0 | 1399 { |
312
8a04d2e1be2f
frame rate should be completely disabled in asf (closer now) - disabled seek
bellard
parents:
300
diff
changeset
|
1400 ASFContext *asf = s->priv_data; |
354
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1401 AVStream *st; |
347
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1402 int64_t pos; |
349 | 1403 int64_t pos_min, pos_max, pts_min, pts_max, cur_pts, pos_limit; |
355 | 1404 int no_change; |
354
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1405 |
347
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1406 if (stream_index == -1) |
348 | 1407 stream_index= av_find_default_stream_index(s); |
1408 | |
350 | 1409 if (asf->packet_size <= 0) |
347
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1410 return -1; |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1411 |
354
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1412 pts_max= |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1413 pts_min= AV_NOPTS_VALUE; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1414 pos_max= pos_limit= -1; // gcc thinks its uninitalized |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1415 |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1416 st= s->streams[stream_index]; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1417 if(st->index_entries){ |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1418 AVIndexEntry *e; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1419 int index; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1420 |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1421 index= av_index_search_timestamp(st, pts); |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1422 e= &st->index_entries[index]; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1423 if(e->timestamp <= pts){ |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1424 pos_min= e->pos; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1425 pts_min= e->timestamp; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1426 #ifdef DEBUG_SEEK |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1427 printf("unsing cached pos_min=0x%llx dts_min=%0.3f\n", |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1428 pos_min,pts_min / 90000.0); |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1429 #endif |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1430 }else{ |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1431 assert(index==0); |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1432 } |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1433 index++; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1434 if(index < st->nb_index_entries){ |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1435 e= &st->index_entries[index]; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1436 assert(e->timestamp >= pts); |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1437 pos_max= e->pos; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1438 pts_max= e->timestamp; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1439 pos_limit= pos_max - e->min_distance; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1440 #ifdef DEBUG_SEEK |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1441 printf("unsing cached pos_max=0x%llx dts_max=%0.3f\n", |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1442 pos_max,pts_max / 90000.0); |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1443 #endif |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1444 } |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1445 } |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1446 |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1447 if(pts_min == AV_NOPTS_VALUE){ |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1448 pos_min = 0; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1449 pts_min = asf_read_pts(s, &pos_min, stream_index); |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1450 if (pts_min == AV_NOPTS_VALUE) return -1; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1451 } |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1452 if(pts_max == AV_NOPTS_VALUE){ |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1453 pos_max = (url_filesize(url_fileno(&s->pb)) - 1 - s->data_offset) / asf->packet_size; //FIXME wrong |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1454 pts_max = s->duration; //FIXME wrong |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1455 pos_limit= pos_max; |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1456 } |
347
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1457 |
355 | 1458 no_change=0; |
349 | 1459 while (pos_min < pos_limit) { |
1460 int64_t start_pos; | |
1461 assert(pos_limit <= pos_max); | |
312
8a04d2e1be2f
frame rate should be completely disabled in asf (closer now) - disabled seek
bellard
parents:
300
diff
changeset
|
1462 |
355 | 1463 if(no_change==0){ |
1464 int64_t approximate_keyframe_distance= pos_max - pos_limit; | |
1465 // interpolate position (better than dichotomy) | |
1466 pos = (int64_t)((double)(pos_max - pos_min) * | |
1467 (double)(pts - pts_min) / | |
1468 (double)(pts_max - pts_min)) + pos_min - approximate_keyframe_distance; | |
1469 }else if(no_change==1){ | |
1470 // bisection, if interpolation failed to change min or max pos last time | |
1471 pos = (pos_min + pos_limit)>>1; | |
1472 }else{ | |
1473 // linear search if bisection failed, can only happen if there are very few or no keyframes between min/max | |
1474 pos=pos_min; | |
1475 } | |
349 | 1476 if(pos <= pos_min) |
351
c072833fe7f4
use packet number instead of byte number internally for seeking
michael
parents:
350
diff
changeset
|
1477 pos= pos_min + 1; |
349 | 1478 else if(pos > pos_limit) |
1479 pos= pos_limit; | |
1480 start_pos= pos; | |
347
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1481 |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1482 // read the next timestamp |
348 | 1483 cur_pts = asf_read_pts(s, &pos, stream_index); |
355 | 1484 if(pos == pos_max) |
1485 no_change++; | |
1486 else | |
1487 no_change=0; | |
1488 | |
354
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1489 #ifdef DEBUG_SEEK |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1490 printf("%Ld %Ld %Ld / %Ld %Ld %Ld target:%Ld limit:%Ld start:%Ld\n", pos_min, pos, pos_max, pts_min, cur_pts, pts_max, pts, pos_limit, start_pos); |
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
353
diff
changeset
|
1491 #endif |
355 | 1492 assert (cur_pts != AV_NOPTS_VALUE); |
1493 if (pts < cur_pts) { | |
351
c072833fe7f4
use packet number instead of byte number internally for seeking
michael
parents:
350
diff
changeset
|
1494 pos_limit = start_pos - 1; |
347
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1495 pos_max = pos; |
349 | 1496 pts_max = cur_pts; |
347
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1497 } else { |
349 | 1498 pos_min = pos; |
1499 pts_min = cur_pts; | |
1500 /* check if we are lucky */ | |
1501 if (pts == cur_pts) | |
1502 break; | |
347
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1503 } |
312
8a04d2e1be2f
frame rate should be completely disabled in asf (closer now) - disabled seek
bellard
parents:
300
diff
changeset
|
1504 } |
347
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1505 pos = pos_min; |
351
c072833fe7f4
use packet number instead of byte number internally for seeking
michael
parents:
350
diff
changeset
|
1506 url_fseek(&s->pb, pos*asf->packet_size + s->data_offset, SEEK_SET); |
347
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1507 asf_reset_header(s); |
2b485a3c5cfb
seeking in single stream asf patch by ("Kevin Kuphal" <kevin dot kuphal at sitecity dot net>)
michael
parents:
341
diff
changeset
|
1508 return 0; |
0 | 1509 } |
1510 | |
1511 static AVInputFormat asf_iformat = { | |
1512 "asf", | |
1513 "asf format", | |
1514 sizeof(ASFContext), | |
1515 asf_probe, | |
1516 asf_read_header, | |
1517 asf_read_packet, | |
1518 asf_read_close, | |
1519 asf_read_seek, | |
1520 }; | |
1521 | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
241
diff
changeset
|
1522 #ifdef CONFIG_ENCODERS |
0 | 1523 static AVOutputFormat asf_oformat = { |
1524 "asf", | |
1525 "asf format", | |
14
b167760cd0aa
mimetype fixes patch by (Ryutaroh Matsumoto <ryutaroh at it dot ss dot titech dot ac dot jp>)
michaelni
parents:
7
diff
changeset
|
1526 "video/x-ms-asf", |
0 | 1527 "asf,wmv", |
1528 sizeof(ASFContext), | |
1529 #ifdef CONFIG_MP3LAME | |
232 | 1530 CODEC_ID_MP3, |
0 | 1531 #else |
1532 CODEC_ID_MP2, | |
1533 #endif | |
1534 CODEC_ID_MSMPEG4V3, | |
1535 asf_write_header, | |
1536 asf_write_packet, | |
1537 asf_write_trailer, | |
1538 }; | |
1539 | |
1540 static AVOutputFormat asf_stream_oformat = { | |
1541 "asf_stream", | |
1542 "asf format", | |
14
b167760cd0aa
mimetype fixes patch by (Ryutaroh Matsumoto <ryutaroh at it dot ss dot titech dot ac dot jp>)
michaelni
parents:
7
diff
changeset
|
1543 "video/x-ms-asf", |
0 | 1544 "asf,wmv", |
1545 sizeof(ASFContext), | |
1546 #ifdef CONFIG_MP3LAME | |
232 | 1547 CODEC_ID_MP3, |
0 | 1548 #else |
1549 CODEC_ID_MP2, | |
1550 #endif | |
1551 CODEC_ID_MSMPEG4V3, | |
1552 asf_write_stream_header, | |
1553 asf_write_packet, | |
1554 asf_write_trailer, | |
1555 }; | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
241
diff
changeset
|
1556 #endif //CONFIG_ENCODERS |
0 | 1557 |
1558 int asf_init(void) | |
1559 { | |
1560 av_register_input_format(&asf_iformat); | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
241
diff
changeset
|
1561 #ifdef CONFIG_ENCODERS |
0 | 1562 av_register_output_format(&asf_oformat); |
1563 av_register_output_format(&asf_stream_oformat); | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
241
diff
changeset
|
1564 #endif //CONFIG_ENCODERS |
0 | 1565 return 0; |
1566 } |