Libav
|
00001 /* 00002 * ASF compatible demuxer 00003 * Copyright (c) 2000, 2001 Fabrice Bellard 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 //#define DEBUG 00023 00024 #include "libavutil/common.h" 00025 #include "libavutil/avstring.h" 00026 #include "libavcodec/mpegaudio.h" 00027 #include "avformat.h" 00028 #include "riff.h" 00029 #include "asf.h" 00030 #include "asfcrypt.h" 00031 #include "avlanguage.h" 00032 00033 void ff_mms_set_stream_selection(URLContext *h, AVFormatContext *format); 00034 00035 #undef NDEBUG 00036 #include <assert.h> 00037 00038 #define FRAME_HEADER_SIZE 17 00039 // Fix Me! FRAME_HEADER_SIZE may be different. 00040 00041 static const ff_asf_guid index_guid = { 00042 0x90, 0x08, 0x00, 0x33, 0xb1, 0xe5, 0xcf, 0x11, 0x89, 0xf4, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb 00043 }; 00044 00045 static const ff_asf_guid stream_bitrate_guid = { /* (http://get.to/sdp) */ 00046 0xce, 0x75, 0xf8, 0x7b, 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2 00047 }; 00048 /**********************************/ 00049 /* decoding */ 00050 00051 static int guidcmp(const void *g1, const void *g2) 00052 { 00053 return memcmp(g1, g2, sizeof(ff_asf_guid)); 00054 } 00055 00056 #ifdef DEBUG 00057 #define PRINT_IF_GUID(g,cmp) \ 00058 if (!guidcmp(g, &cmp)) \ 00059 dprintf(NULL, "(GUID: %s) ", #cmp) 00060 00061 static void print_guid(const ff_asf_guid *g) 00062 { 00063 int i; 00064 PRINT_IF_GUID(g, ff_asf_header); 00065 else PRINT_IF_GUID(g, ff_asf_file_header); 00066 else PRINT_IF_GUID(g, ff_asf_stream_header); 00067 else PRINT_IF_GUID(g, ff_asf_audio_stream); 00068 else PRINT_IF_GUID(g, ff_asf_audio_conceal_none); 00069 else PRINT_IF_GUID(g, ff_asf_video_stream); 00070 else PRINT_IF_GUID(g, ff_asf_video_conceal_none); 00071 else PRINT_IF_GUID(g, ff_asf_command_stream); 00072 else PRINT_IF_GUID(g, ff_asf_comment_header); 00073 else PRINT_IF_GUID(g, ff_asf_codec_comment_header); 00074 else PRINT_IF_GUID(g, ff_asf_codec_comment1_header); 00075 else PRINT_IF_GUID(g, ff_asf_data_header); 00076 else PRINT_IF_GUID(g, index_guid); 00077 else PRINT_IF_GUID(g, ff_asf_head1_guid); 00078 else PRINT_IF_GUID(g, ff_asf_head2_guid); 00079 else PRINT_IF_GUID(g, ff_asf_my_guid); 00080 else PRINT_IF_GUID(g, ff_asf_ext_stream_header); 00081 else PRINT_IF_GUID(g, ff_asf_extended_content_header); 00082 else PRINT_IF_GUID(g, ff_asf_ext_stream_embed_stream_header); 00083 else PRINT_IF_GUID(g, ff_asf_ext_stream_audio_stream); 00084 else PRINT_IF_GUID(g, ff_asf_metadata_header); 00085 else PRINT_IF_GUID(g, ff_asf_marker_header); 00086 else PRINT_IF_GUID(g, stream_bitrate_guid); 00087 else PRINT_IF_GUID(g, ff_asf_language_guid); 00088 else 00089 dprintf(NULL, "(GUID: unknown) "); 00090 for(i=0;i<16;i++) 00091 dprintf(NULL, " 0x%02x,", (*g)[i]); 00092 dprintf(NULL, "}\n"); 00093 } 00094 #undef PRINT_IF_GUID 00095 #else 00096 #define print_guid(g) 00097 #endif 00098 00099 static void get_guid(ByteIOContext *s, ff_asf_guid *g) 00100 { 00101 assert(sizeof(*g) == 16); 00102 get_buffer(s, *g, sizeof(*g)); 00103 } 00104 00105 #if 0 00106 static void get_str16(ByteIOContext *pb, char *buf, int buf_size) 00107 { 00108 int len, c; 00109 char *q; 00110 00111 len = get_le16(pb); 00112 q = buf; 00113 while (len > 0) { 00114 c = get_le16(pb); 00115 if ((q - buf) < buf_size - 1) 00116 *q++ = c; 00117 len--; 00118 } 00119 *q = '\0'; 00120 } 00121 #endif 00122 00123 static void get_str16_nolen(ByteIOContext *pb, int len, char *buf, int buf_size) 00124 { 00125 char* q = buf; 00126 while (len > 1) { 00127 uint8_t tmp; 00128 uint32_t ch; 00129 00130 GET_UTF16(ch, (len -= 2) >= 0 ? get_le16(pb) : 0, break;) 00131 PUT_UTF8(ch, tmp, if (q - buf < buf_size - 1) *q++ = tmp;) 00132 } 00133 if (len > 0) 00134 url_fskip(pb, len); 00135 *q = '\0'; 00136 } 00137 00138 static int asf_probe(AVProbeData *pd) 00139 { 00140 /* check file header */ 00141 if (!guidcmp(pd->buf, &ff_asf_header)) 00142 return AVPROBE_SCORE_MAX; 00143 else 00144 return 0; 00145 } 00146 00147 static int get_value(ByteIOContext *pb, int type){ 00148 switch(type){ 00149 case 2: return get_le32(pb); 00150 case 3: return get_le32(pb); 00151 case 4: return get_le64(pb); 00152 case 5: return get_le16(pb); 00153 default:return INT_MIN; 00154 } 00155 } 00156 00157 static void get_tag(AVFormatContext *s, const char *key, int type, int len) 00158 { 00159 char *value; 00160 00161 if ((unsigned)len >= (UINT_MAX - 1)/2) 00162 return; 00163 00164 value = av_malloc(2*len+1); 00165 if (!value) 00166 return; 00167 00168 if (type == 0) { // UTF16-LE 00169 get_str16_nolen(s->pb, len, value, 2*len + 1); 00170 } else if (type > 1 && type <= 5) { // boolean or DWORD or QWORD or WORD 00171 uint64_t num = get_value(s->pb, type); 00172 snprintf(value, len, "%"PRIu64, num); 00173 } else { 00174 url_fskip(s->pb, len); 00175 av_freep(&value); 00176 av_log(s, AV_LOG_DEBUG, "Unsupported value type %d in tag %s.\n", type, key); 00177 return; 00178 } 00179 av_metadata_set2(&s->metadata, key, value, 0); 00180 av_freep(&value); 00181 } 00182 00183 static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap) 00184 { 00185 ASFContext *asf = s->priv_data; 00186 ff_asf_guid g; 00187 ByteIOContext *pb = s->pb; 00188 AVStream *st; 00189 ASFStream *asf_st; 00190 int size, i; 00191 int64_t gsize; 00192 AVRational dar[128]; 00193 uint32_t bitrate[128]; 00194 00195 memset(dar, 0, sizeof(dar)); 00196 memset(bitrate, 0, sizeof(bitrate)); 00197 00198 get_guid(pb, &g); 00199 if (guidcmp(&g, &ff_asf_header)) 00200 return -1; 00201 get_le64(pb); 00202 get_le32(pb); 00203 get_byte(pb); 00204 get_byte(pb); 00205 memset(&asf->asfid2avid, -1, sizeof(asf->asfid2avid)); 00206 for(;;) { 00207 uint64_t gpos= url_ftell(pb); 00208 get_guid(pb, &g); 00209 gsize = get_le64(pb); 00210 dprintf(s, "%08"PRIx64": ", gpos); 00211 print_guid(&g); 00212 dprintf(s, " size=0x%"PRIx64"\n", gsize); 00213 if (!guidcmp(&g, &ff_asf_data_header)) { 00214 asf->data_object_offset = url_ftell(pb); 00215 // if not streaming, gsize is not unlimited (how?), and there is enough space in the file.. 00216 if (!(asf->hdr.flags & 0x01) && gsize >= 100) { 00217 asf->data_object_size = gsize - 24; 00218 } else { 00219 asf->data_object_size = (uint64_t)-1; 00220 } 00221 break; 00222 } 00223 if (gsize < 24) 00224 return -1; 00225 if (!guidcmp(&g, &ff_asf_file_header)) { 00226 get_guid(pb, &asf->hdr.guid); 00227 asf->hdr.file_size = get_le64(pb); 00228 asf->hdr.create_time = get_le64(pb); 00229 asf->nb_packets = get_le64(pb); 00230 asf->hdr.play_time = get_le64(pb); 00231 asf->hdr.send_time = get_le64(pb); 00232 asf->hdr.preroll = get_le32(pb); 00233 asf->hdr.ignore = get_le32(pb); 00234 asf->hdr.flags = get_le32(pb); 00235 asf->hdr.min_pktsize = get_le32(pb); 00236 asf->hdr.max_pktsize = get_le32(pb); 00237 asf->hdr.max_bitrate = get_le32(pb); 00238 s->packet_size = asf->hdr.max_pktsize; 00239 } else if (!guidcmp(&g, &ff_asf_stream_header)) { 00240 enum AVMediaType type; 00241 int type_specific_size, sizeX; 00242 uint64_t total_size; 00243 unsigned int tag1; 00244 int64_t pos1, pos2, start_time; 00245 int test_for_ext_stream_audio, is_dvr_ms_audio=0; 00246 00247 pos1 = url_ftell(pb); 00248 00249 st = av_new_stream(s, 0); 00250 if (!st) 00251 return AVERROR(ENOMEM); 00252 av_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */ 00253 asf_st = av_mallocz(sizeof(ASFStream)); 00254 if (!asf_st) 00255 return AVERROR(ENOMEM); 00256 st->priv_data = asf_st; 00257 start_time = asf->hdr.preroll; 00258 00259 asf_st->stream_language_index = 128; // invalid stream index means no language info 00260 00261 if(!(asf->hdr.flags & 0x01)) { // if we aren't streaming... 00262 st->duration = asf->hdr.play_time / 00263 (10000000 / 1000) - start_time; 00264 } 00265 get_guid(pb, &g); 00266 00267 test_for_ext_stream_audio = 0; 00268 if (!guidcmp(&g, &ff_asf_audio_stream)) { 00269 type = AVMEDIA_TYPE_AUDIO; 00270 } else if (!guidcmp(&g, &ff_asf_video_stream)) { 00271 type = AVMEDIA_TYPE_VIDEO; 00272 } else if (!guidcmp(&g, &ff_asf_command_stream)) { 00273 type = AVMEDIA_TYPE_DATA; 00274 } else if (!guidcmp(&g, &ff_asf_ext_stream_embed_stream_header)) { 00275 test_for_ext_stream_audio = 1; 00276 type = AVMEDIA_TYPE_UNKNOWN; 00277 } else { 00278 return -1; 00279 } 00280 get_guid(pb, &g); 00281 total_size = get_le64(pb); 00282 type_specific_size = get_le32(pb); 00283 get_le32(pb); 00284 st->id = get_le16(pb) & 0x7f; /* stream id */ 00285 // mapping of asf ID to AV stream ID; 00286 asf->asfid2avid[st->id] = s->nb_streams - 1; 00287 00288 get_le32(pb); 00289 00290 if (test_for_ext_stream_audio) { 00291 get_guid(pb, &g); 00292 if (!guidcmp(&g, &ff_asf_ext_stream_audio_stream)) { 00293 type = AVMEDIA_TYPE_AUDIO; 00294 is_dvr_ms_audio=1; 00295 get_guid(pb, &g); 00296 get_le32(pb); 00297 get_le32(pb); 00298 get_le32(pb); 00299 get_guid(pb, &g); 00300 get_le32(pb); 00301 } 00302 } 00303 00304 st->codec->codec_type = type; 00305 if (type == AVMEDIA_TYPE_AUDIO) { 00306 ff_get_wav_header(pb, st->codec, type_specific_size); 00307 if (is_dvr_ms_audio) { 00308 // codec_id and codec_tag are unreliable in dvr_ms 00309 // files. Set them later by probing stream. 00310 st->codec->codec_id = CODEC_ID_PROBE; 00311 st->codec->codec_tag = 0; 00312 } 00313 if (st->codec->codec_id == CODEC_ID_AAC) { 00314 st->need_parsing = AVSTREAM_PARSE_NONE; 00315 } else { 00316 st->need_parsing = AVSTREAM_PARSE_FULL; 00317 } 00318 /* We have to init the frame size at some point .... */ 00319 pos2 = url_ftell(pb); 00320 if (gsize >= (pos2 + 8 - pos1 + 24)) { 00321 asf_st->ds_span = get_byte(pb); 00322 asf_st->ds_packet_size = get_le16(pb); 00323 asf_st->ds_chunk_size = get_le16(pb); 00324 get_le16(pb); //ds_data_size 00325 get_byte(pb); //ds_silence_data 00326 } 00327 //printf("Descrambling: ps:%d cs:%d ds:%d s:%d sd:%d\n", 00328 // asf_st->ds_packet_size, asf_st->ds_chunk_size, 00329 // asf_st->ds_data_size, asf_st->ds_span, asf_st->ds_silence_data); 00330 if (asf_st->ds_span > 1) { 00331 if (!asf_st->ds_chunk_size 00332 || (asf_st->ds_packet_size/asf_st->ds_chunk_size <= 1) 00333 || asf_st->ds_packet_size % asf_st->ds_chunk_size) 00334 asf_st->ds_span = 0; // disable descrambling 00335 } 00336 switch (st->codec->codec_id) { 00337 case CODEC_ID_MP3: 00338 st->codec->frame_size = MPA_FRAME_SIZE; 00339 break; 00340 case CODEC_ID_PCM_S16LE: 00341 case CODEC_ID_PCM_S16BE: 00342 case CODEC_ID_PCM_U16LE: 00343 case CODEC_ID_PCM_U16BE: 00344 case CODEC_ID_PCM_S8: 00345 case CODEC_ID_PCM_U8: 00346 case CODEC_ID_PCM_ALAW: 00347 case CODEC_ID_PCM_MULAW: 00348 st->codec->frame_size = 1; 00349 break; 00350 default: 00351 /* This is probably wrong, but it prevents a crash later */ 00352 st->codec->frame_size = 1; 00353 break; 00354 } 00355 } else if (type == AVMEDIA_TYPE_VIDEO) { 00356 get_le32(pb); 00357 get_le32(pb); 00358 get_byte(pb); 00359 size = get_le16(pb); /* size */ 00360 sizeX= get_le32(pb); /* size */ 00361 st->codec->width = get_le32(pb); 00362 st->codec->height = get_le32(pb); 00363 /* not available for asf */ 00364 get_le16(pb); /* panes */ 00365 st->codec->bits_per_coded_sample = get_le16(pb); /* depth */ 00366 tag1 = get_le32(pb); 00367 url_fskip(pb, 20); 00368 // av_log(s, AV_LOG_DEBUG, "size:%d tsize:%d sizeX:%d\n", size, total_size, sizeX); 00369 size= sizeX; 00370 if (size > 40) { 00371 st->codec->extradata_size = size - 40; 00372 st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); 00373 get_buffer(pb, st->codec->extradata, st->codec->extradata_size); 00374 } 00375 00376 /* Extract palette from extradata if bpp <= 8 */ 00377 /* This code assumes that extradata contains only palette */ 00378 /* This is true for all paletted codecs implemented in ffmpeg */ 00379 if (st->codec->extradata_size && (st->codec->bits_per_coded_sample <= 8)) { 00380 st->codec->palctrl = av_mallocz(sizeof(AVPaletteControl)); 00381 #if HAVE_BIGENDIAN 00382 for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)/4; i++) 00383 st->codec->palctrl->palette[i] = bswap_32(((uint32_t*)st->codec->extradata)[i]); 00384 #else 00385 memcpy(st->codec->palctrl->palette, st->codec->extradata, 00386 FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)); 00387 #endif 00388 st->codec->palctrl->palette_changed = 1; 00389 } 00390 00391 st->codec->codec_tag = tag1; 00392 st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag1); 00393 if(tag1 == MKTAG('D', 'V', 'R', ' ')) 00394 st->need_parsing = AVSTREAM_PARSE_FULL; 00395 } 00396 pos2 = url_ftell(pb); 00397 url_fskip(pb, gsize - (pos2 - pos1 + 24)); 00398 } else if (!guidcmp(&g, &ff_asf_comment_header)) { 00399 int len1, len2, len3, len4, len5; 00400 00401 len1 = get_le16(pb); 00402 len2 = get_le16(pb); 00403 len3 = get_le16(pb); 00404 len4 = get_le16(pb); 00405 len5 = get_le16(pb); 00406 get_tag(s, "title" , 0, len1); 00407 get_tag(s, "author" , 0, len2); 00408 get_tag(s, "copyright", 0, len3); 00409 get_tag(s, "comment" , 0, len4); 00410 url_fskip(pb, len5); 00411 } else if (!guidcmp(&g, &stream_bitrate_guid)) { 00412 int stream_count = get_le16(pb); 00413 int j; 00414 00415 // av_log(s, AV_LOG_ERROR, "stream bitrate properties\n"); 00416 // av_log(s, AV_LOG_ERROR, "streams %d\n", streams); 00417 for(j = 0; j < stream_count; j++) { 00418 int flags, bitrate, stream_id; 00419 00420 flags= get_le16(pb); 00421 bitrate= get_le32(pb); 00422 stream_id= (flags & 0x7f); 00423 // av_log(s, AV_LOG_ERROR, "flags: 0x%x stream id %d, bitrate %d\n", flags, stream_id, bitrate); 00424 asf->stream_bitrates[stream_id]= bitrate; 00425 } 00426 } else if (!guidcmp(&g, &ff_asf_language_guid)) { 00427 int j; 00428 int stream_count = get_le16(pb); 00429 for(j = 0; j < stream_count; j++) { 00430 char lang[6]; 00431 unsigned int lang_len = get_byte(pb); 00432 get_str16_nolen(pb, lang_len, lang, sizeof(lang)); 00433 if (j < 128) 00434 av_strlcpy(asf->stream_languages[j], lang, sizeof(*asf->stream_languages)); 00435 } 00436 } else if (!guidcmp(&g, &ff_asf_extended_content_header)) { 00437 int desc_count, i; 00438 00439 desc_count = get_le16(pb); 00440 for(i=0;i<desc_count;i++) { 00441 int name_len,value_type,value_len; 00442 char name[1024]; 00443 00444 name_len = get_le16(pb); 00445 if (name_len%2) // must be even, broken lavf versions wrote len-1 00446 name_len += 1; 00447 get_str16_nolen(pb, name_len, name, sizeof(name)); 00448 value_type = get_le16(pb); 00449 value_len = get_le16(pb); 00450 if (!value_type && value_len%2) 00451 value_len += 1; 00452 get_tag(s, name, value_type, value_len); 00453 } 00454 } else if (!guidcmp(&g, &ff_asf_metadata_header)) { 00455 int n, stream_num, name_len, value_len, value_type, value_num; 00456 n = get_le16(pb); 00457 00458 for(i=0;i<n;i++) { 00459 char name[1024]; 00460 00461 get_le16(pb); //lang_list_index 00462 stream_num= get_le16(pb); 00463 name_len= get_le16(pb); 00464 value_type= get_le16(pb); 00465 value_len= get_le32(pb); 00466 00467 get_str16_nolen(pb, name_len, name, sizeof(name)); 00468 //av_log(s, AV_LOG_ERROR, "%d %d %d %d %d <%s>\n", i, stream_num, name_len, value_type, value_len, name); 00469 value_num= get_le16(pb);//we should use get_value() here but it does not work 2 is le16 here but le32 elsewhere 00470 url_fskip(pb, value_len - 2); 00471 00472 if(stream_num<128){ 00473 if (!strcmp(name, "AspectRatioX")) dar[stream_num].num= value_num; 00474 else if(!strcmp(name, "AspectRatioY")) dar[stream_num].den= value_num; 00475 } 00476 } 00477 } else if (!guidcmp(&g, &ff_asf_ext_stream_header)) { 00478 int ext_len, payload_ext_ct, stream_ct; 00479 uint32_t ext_d, leak_rate, stream_num; 00480 unsigned int stream_languageid_index; 00481 00482 get_le64(pb); // starttime 00483 get_le64(pb); // endtime 00484 leak_rate = get_le32(pb); // leak-datarate 00485 get_le32(pb); // bucket-datasize 00486 get_le32(pb); // init-bucket-fullness 00487 get_le32(pb); // alt-leak-datarate 00488 get_le32(pb); // alt-bucket-datasize 00489 get_le32(pb); // alt-init-bucket-fullness 00490 get_le32(pb); // max-object-size 00491 get_le32(pb); // flags (reliable,seekable,no_cleanpoints?,resend-live-cleanpoints, rest of bits reserved) 00492 stream_num = get_le16(pb); // stream-num 00493 00494 stream_languageid_index = get_le16(pb); // stream-language-id-index 00495 if (stream_num < 128) 00496 asf->streams[stream_num].stream_language_index = stream_languageid_index; 00497 00498 get_le64(pb); // avg frametime in 100ns units 00499 stream_ct = get_le16(pb); //stream-name-count 00500 payload_ext_ct = get_le16(pb); //payload-extension-system-count 00501 00502 if (stream_num < 128) 00503 bitrate[stream_num] = leak_rate; 00504 00505 for (i=0; i<stream_ct; i++){ 00506 get_le16(pb); 00507 ext_len = get_le16(pb); 00508 url_fseek(pb, ext_len, SEEK_CUR); 00509 } 00510 00511 for (i=0; i<payload_ext_ct; i++){ 00512 get_guid(pb, &g); 00513 ext_d=get_le16(pb); 00514 ext_len=get_le32(pb); 00515 url_fseek(pb, ext_len, SEEK_CUR); 00516 } 00517 00518 // there could be a optional stream properties object to follow 00519 // if so the next iteration will pick it up 00520 } else if (!guidcmp(&g, &ff_asf_head1_guid)) { 00521 int v1, v2; 00522 get_guid(pb, &g); 00523 v1 = get_le32(pb); 00524 v2 = get_le16(pb); 00525 } else if (!guidcmp(&g, &ff_asf_marker_header)) { 00526 int i, count, name_len; 00527 char name[1024]; 00528 00529 get_le64(pb); // reserved 16 bytes 00530 get_le64(pb); // ... 00531 count = get_le32(pb); // markers count 00532 get_le16(pb); // reserved 2 bytes 00533 name_len = get_le16(pb); // name length 00534 for(i=0;i<name_len;i++){ 00535 get_byte(pb); // skip the name 00536 } 00537 00538 for(i=0;i<count;i++){ 00539 int64_t pres_time; 00540 int name_len; 00541 00542 get_le64(pb); // offset, 8 bytes 00543 pres_time = get_le64(pb); // presentation time 00544 get_le16(pb); // entry length 00545 get_le32(pb); // send time 00546 get_le32(pb); // flags 00547 name_len = get_le32(pb); // name length 00548 get_str16_nolen(pb, name_len * 2, name, sizeof(name)); 00549 ff_new_chapter(s, i, (AVRational){1, 10000000}, pres_time, AV_NOPTS_VALUE, name ); 00550 } 00551 #if 0 00552 } else if (!guidcmp(&g, &ff_asf_codec_comment_header)) { 00553 int len, v1, n, num; 00554 char str[256], *q; 00555 char tag[16]; 00556 00557 get_guid(pb, &g); 00558 print_guid(&g); 00559 00560 n = get_le32(pb); 00561 for(i=0;i<n;i++) { 00562 num = get_le16(pb); /* stream number */ 00563 get_str16(pb, str, sizeof(str)); 00564 get_str16(pb, str, sizeof(str)); 00565 len = get_le16(pb); 00566 q = tag; 00567 while (len > 0) { 00568 v1 = get_byte(pb); 00569 if ((q - tag) < sizeof(tag) - 1) 00570 *q++ = v1; 00571 len--; 00572 } 00573 *q = '\0'; 00574 } 00575 #endif 00576 } else if (url_feof(pb)) { 00577 return -1; 00578 } else { 00579 if (!s->keylen) { 00580 if (!guidcmp(&g, &ff_asf_content_encryption)) { 00581 av_log(s, AV_LOG_WARNING, "DRM protected stream detected, decoding will likely fail!\n"); 00582 } else if (!guidcmp(&g, &ff_asf_ext_content_encryption)) { 00583 av_log(s, AV_LOG_WARNING, "Ext DRM protected stream detected, decoding will likely fail!\n"); 00584 } else if (!guidcmp(&g, &ff_asf_digital_signature)) { 00585 av_log(s, AV_LOG_WARNING, "Digital signature detected, decoding will likely fail!\n"); 00586 } 00587 } 00588 } 00589 if(url_ftell(pb) != gpos + gsize) 00590 av_log(s, AV_LOG_DEBUG, "gpos mismatch our pos=%"PRIu64", end=%"PRIu64"\n", url_ftell(pb)-gpos, gsize); 00591 url_fseek(pb, gpos + gsize, SEEK_SET); 00592 } 00593 get_guid(pb, &g); 00594 get_le64(pb); 00595 get_byte(pb); 00596 get_byte(pb); 00597 if (url_feof(pb)) 00598 return -1; 00599 asf->data_offset = url_ftell(pb); 00600 asf->packet_size_left = 0; 00601 00602 00603 for(i=0; i<128; i++){ 00604 int stream_num= asf->asfid2avid[i]; 00605 if(stream_num>=0){ 00606 AVStream *st = s->streams[stream_num]; 00607 if (!st->codec->bit_rate) 00608 st->codec->bit_rate = bitrate[i]; 00609 if (dar[i].num > 0 && dar[i].den > 0) 00610 av_reduce(&st->sample_aspect_ratio.num, 00611 &st->sample_aspect_ratio.den, 00612 dar[i].num, dar[i].den, INT_MAX); 00613 //av_log(s, AV_LOG_ERROR, "dar %d:%d sar=%d:%d\n", dar[i].num, dar[i].den, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den); 00614 00615 // copy and convert language codes to the frontend 00616 if (asf->streams[i].stream_language_index < 128) { 00617 const char *rfc1766 = asf->stream_languages[asf->streams[i].stream_language_index]; 00618 if (rfc1766 && strlen(rfc1766) > 1) { 00619 const char primary_tag[3] = { rfc1766[0], rfc1766[1], '\0' }; // ignore country code if any 00620 const char *iso6392 = av_convert_lang_to(primary_tag, AV_LANG_ISO639_2_BIBL); 00621 if (iso6392) 00622 av_metadata_set2(&st->metadata, "language", iso6392, 0); 00623 } 00624 } 00625 } 00626 } 00627 00628 return 0; 00629 } 00630 00631 #define DO_2BITS(bits, var, defval) \ 00632 switch (bits & 3) \ 00633 { \ 00634 case 3: var = get_le32(pb); rsize += 4; break; \ 00635 case 2: var = get_le16(pb); rsize += 2; break; \ 00636 case 1: var = get_byte(pb); rsize++; break; \ 00637 default: var = defval; break; \ 00638 } 00639 00646 static int ff_asf_get_packet(AVFormatContext *s, ByteIOContext *pb) 00647 { 00648 ASFContext *asf = s->priv_data; 00649 uint32_t packet_length, padsize; 00650 int rsize = 8; 00651 int c, d, e, off; 00652 00653 // if we do not know packet size, allow skipping up to 32 kB 00654 off= 32768; 00655 if (s->packet_size > 0) 00656 off= (url_ftell(pb) - s->data_offset) % s->packet_size + 3; 00657 00658 c=d=e=-1; 00659 while(off-- > 0){ 00660 c=d; d=e; 00661 e= get_byte(pb); 00662 if(c == 0x82 && !d && !e) 00663 break; 00664 } 00665 00666 if (c != 0x82) { 00673 if (url_ferror(pb) == AVERROR(EAGAIN)) 00674 return AVERROR(EAGAIN); 00675 if (!url_feof(pb)) 00676 av_log(s, AV_LOG_ERROR, "ff asf bad header %x at:%"PRId64"\n", c, url_ftell(pb)); 00677 } 00678 if ((c & 0x8f) == 0x82) { 00679 if (d || e) { 00680 if (!url_feof(pb)) 00681 av_log(s, AV_LOG_ERROR, "ff asf bad non zero\n"); 00682 return -1; 00683 } 00684 c= get_byte(pb); 00685 d= get_byte(pb); 00686 rsize+=3; 00687 }else{ 00688 url_fseek(pb, -1, SEEK_CUR); //FIXME 00689 } 00690 00691 asf->packet_flags = c; 00692 asf->packet_property = d; 00693 00694 DO_2BITS(asf->packet_flags >> 5, packet_length, s->packet_size); 00695 DO_2BITS(asf->packet_flags >> 1, padsize, 0); // sequence ignored 00696 DO_2BITS(asf->packet_flags >> 3, padsize, 0); // padding length 00697 00698 //the following checks prevent overflows and infinite loops 00699 if(!packet_length || packet_length >= (1U<<29)){ 00700 av_log(s, AV_LOG_ERROR, "invalid packet_length %d at:%"PRId64"\n", packet_length, url_ftell(pb)); 00701 return -1; 00702 } 00703 if(padsize >= packet_length){ 00704 av_log(s, AV_LOG_ERROR, "invalid padsize %d at:%"PRId64"\n", padsize, url_ftell(pb)); 00705 return -1; 00706 } 00707 00708 asf->packet_timestamp = get_le32(pb); 00709 get_le16(pb); /* duration */ 00710 // rsize has at least 11 bytes which have to be present 00711 00712 if (asf->packet_flags & 0x01) { 00713 asf->packet_segsizetype = get_byte(pb); rsize++; 00714 asf->packet_segments = asf->packet_segsizetype & 0x3f; 00715 } else { 00716 asf->packet_segments = 1; 00717 asf->packet_segsizetype = 0x80; 00718 } 00719 asf->packet_size_left = packet_length - padsize - rsize; 00720 if (packet_length < asf->hdr.min_pktsize) 00721 padsize += asf->hdr.min_pktsize - packet_length; 00722 asf->packet_padsize = padsize; 00723 dprintf(s, "packet: size=%d padsize=%d left=%d\n", s->packet_size, asf->packet_padsize, asf->packet_size_left); 00724 return 0; 00725 } 00726 00731 static int asf_read_frame_header(AVFormatContext *s, ByteIOContext *pb){ 00732 ASFContext *asf = s->priv_data; 00733 int rsize = 1; 00734 int num = get_byte(pb); 00735 int64_t ts0, ts1; 00736 00737 asf->packet_segments--; 00738 asf->packet_key_frame = num >> 7; 00739 asf->stream_index = asf->asfid2avid[num & 0x7f]; 00740 // sequence should be ignored! 00741 DO_2BITS(asf->packet_property >> 4, asf->packet_seq, 0); 00742 DO_2BITS(asf->packet_property >> 2, asf->packet_frag_offset, 0); 00743 DO_2BITS(asf->packet_property, asf->packet_replic_size, 0); 00744 //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); 00745 if (asf->packet_replic_size >= 8) { 00746 asf->packet_obj_size = get_le32(pb); 00747 if(asf->packet_obj_size >= (1<<24) || asf->packet_obj_size <= 0){ 00748 av_log(s, AV_LOG_ERROR, "packet_obj_size invalid\n"); 00749 return -1; 00750 } 00751 asf->packet_frag_timestamp = get_le32(pb); // timestamp 00752 if(asf->packet_replic_size >= 8+38+4){ 00753 // for(i=0; i<asf->packet_replic_size-8; i++) 00754 // av_log(s, AV_LOG_DEBUG, "%02X ",get_byte(pb)); 00755 // av_log(s, AV_LOG_DEBUG, "\n"); 00756 url_fskip(pb, 10); 00757 ts0= get_le64(pb); 00758 ts1= get_le64(pb); 00759 url_fskip(pb, 12); 00760 get_le32(pb); 00761 url_fskip(pb, asf->packet_replic_size - 8 - 38 - 4); 00762 if(ts0!= -1) asf->packet_frag_timestamp= ts0/10000; 00763 else asf->packet_frag_timestamp= AV_NOPTS_VALUE; 00764 }else 00765 url_fskip(pb, asf->packet_replic_size - 8); 00766 rsize += asf->packet_replic_size; // FIXME - check validity 00767 } else if (asf->packet_replic_size==1){ 00768 // multipacket - frag_offset is beginning timestamp 00769 asf->packet_time_start = asf->packet_frag_offset; 00770 asf->packet_frag_offset = 0; 00771 asf->packet_frag_timestamp = asf->packet_timestamp; 00772 00773 asf->packet_time_delta = get_byte(pb); 00774 rsize++; 00775 }else if(asf->packet_replic_size!=0){ 00776 av_log(s, AV_LOG_ERROR, "unexpected packet_replic_size of %d\n", asf->packet_replic_size); 00777 return -1; 00778 } 00779 if (asf->packet_flags & 0x01) { 00780 DO_2BITS(asf->packet_segsizetype >> 6, asf->packet_frag_size, 0); // 0 is illegal 00781 if(asf->packet_frag_size > asf->packet_size_left - rsize){ 00782 av_log(s, AV_LOG_ERROR, "packet_frag_size is invalid\n"); 00783 return -1; 00784 } 00785 //printf("Fragsize %d\n", asf->packet_frag_size); 00786 } else { 00787 asf->packet_frag_size = asf->packet_size_left - rsize; 00788 //printf("Using rest %d %d %d\n", asf->packet_frag_size, asf->packet_size_left, rsize); 00789 } 00790 if (asf->packet_replic_size == 1) { 00791 asf->packet_multi_size = asf->packet_frag_size; 00792 if (asf->packet_multi_size > asf->packet_size_left) 00793 return -1; 00794 } 00795 asf->packet_size_left -= rsize; 00796 //printf("___objsize____ %d %d rs:%d\n", asf->packet_obj_size, asf->packet_frag_offset, rsize); 00797 00798 return 0; 00799 } 00800 00810 static int ff_asf_parse_packet(AVFormatContext *s, ByteIOContext *pb, AVPacket *pkt) 00811 { 00812 ASFContext *asf = s->priv_data; 00813 ASFStream *asf_st = 0; 00814 for (;;) { 00815 if(url_feof(pb)) 00816 return AVERROR_EOF; 00817 if (asf->packet_size_left < FRAME_HEADER_SIZE 00818 || asf->packet_segments < 1) { 00819 //asf->packet_size_left <= asf->packet_padsize) { 00820 int ret = asf->packet_size_left + asf->packet_padsize; 00821 //printf("PacketLeftSize:%d Pad:%d Pos:%"PRId64"\n", asf->packet_size_left, asf->packet_padsize, url_ftell(pb)); 00822 assert(ret>=0); 00823 /* fail safe */ 00824 url_fskip(pb, ret); 00825 00826 asf->packet_pos= url_ftell(pb); 00827 if (asf->data_object_size != (uint64_t)-1 && 00828 (asf->packet_pos - asf->data_object_offset >= asf->data_object_size)) 00829 return AVERROR_EOF; /* Do not exceed the size of the data object */ 00830 return 1; 00831 } 00832 if (asf->packet_time_start == 0) { 00833 if(asf_read_frame_header(s, pb) < 0){ 00834 asf->packet_segments= 0; 00835 continue; 00836 } 00837 if (asf->stream_index < 0 00838 || s->streams[asf->stream_index]->discard >= AVDISCARD_ALL 00839 || (!asf->packet_key_frame && s->streams[asf->stream_index]->discard >= AVDISCARD_NONKEY) 00840 ) { 00841 asf->packet_time_start = 0; 00842 /* unhandled packet (should not happen) */ 00843 url_fskip(pb, asf->packet_frag_size); 00844 asf->packet_size_left -= asf->packet_frag_size; 00845 if(asf->stream_index < 0) 00846 av_log(s, AV_LOG_ERROR, "ff asf skip %d (unknown stream)\n", asf->packet_frag_size); 00847 continue; 00848 } 00849 asf->asf_st = s->streams[asf->stream_index]->priv_data; 00850 } 00851 asf_st = asf->asf_st; 00852 00853 if (asf->packet_replic_size == 1) { 00854 // frag_offset is here used as the beginning timestamp 00855 asf->packet_frag_timestamp = asf->packet_time_start; 00856 asf->packet_time_start += asf->packet_time_delta; 00857 asf->packet_obj_size = asf->packet_frag_size = get_byte(pb); 00858 asf->packet_size_left--; 00859 asf->packet_multi_size--; 00860 if (asf->packet_multi_size < asf->packet_obj_size) 00861 { 00862 asf->packet_time_start = 0; 00863 url_fskip(pb, asf->packet_multi_size); 00864 asf->packet_size_left -= asf->packet_multi_size; 00865 continue; 00866 } 00867 asf->packet_multi_size -= asf->packet_obj_size; 00868 //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); 00869 } 00870 if( /*asf->packet_frag_size == asf->packet_obj_size*/ 00871 asf_st->frag_offset + asf->packet_frag_size <= asf_st->pkt.size 00872 && asf_st->frag_offset + asf->packet_frag_size > asf->packet_obj_size){ 00873 av_log(s, AV_LOG_INFO, "ignoring invalid packet_obj_size (%d %d %d %d)\n", 00874 asf_st->frag_offset, asf->packet_frag_size, 00875 asf->packet_obj_size, asf_st->pkt.size); 00876 asf->packet_obj_size= asf_st->pkt.size; 00877 } 00878 00879 if ( asf_st->pkt.size != asf->packet_obj_size 00880 || asf_st->frag_offset + asf->packet_frag_size > asf_st->pkt.size) { //FIXME is this condition sufficient? 00881 if(asf_st->pkt.data){ 00882 av_log(s, AV_LOG_INFO, "freeing incomplete packet size %d, new %d\n", asf_st->pkt.size, asf->packet_obj_size); 00883 asf_st->frag_offset = 0; 00884 av_free_packet(&asf_st->pkt); 00885 } 00886 /* new packet */ 00887 av_new_packet(&asf_st->pkt, asf->packet_obj_size); 00888 asf_st->seq = asf->packet_seq; 00889 asf_st->pkt.dts = asf->packet_frag_timestamp; 00890 asf_st->pkt.stream_index = asf->stream_index; 00891 asf_st->pkt.pos = 00892 asf_st->packet_pos= asf->packet_pos; 00893 //printf("new packet: stream:%d key:%d packet_key:%d audio:%d size:%d\n", 00894 //asf->stream_index, asf->packet_key_frame, asf_st->pkt.flags & AV_PKT_FLAG_KEY, 00895 //s->streams[asf->stream_index]->codec->codec_type == AVMEDIA_TYPE_AUDIO, asf->packet_obj_size); 00896 if (s->streams[asf->stream_index]->codec->codec_type == AVMEDIA_TYPE_AUDIO) 00897 asf->packet_key_frame = 1; 00898 if (asf->packet_key_frame) 00899 asf_st->pkt.flags |= AV_PKT_FLAG_KEY; 00900 } 00901 00902 /* read data */ 00903 //printf("READ PACKET s:%d os:%d o:%d,%d l:%d DATA:%p\n", 00904 // s->packet_size, asf_st->pkt.size, asf->packet_frag_offset, 00905 // asf_st->frag_offset, asf->packet_frag_size, asf_st->pkt.data); 00906 asf->packet_size_left -= asf->packet_frag_size; 00907 if (asf->packet_size_left < 0) 00908 continue; 00909 00910 if( asf->packet_frag_offset >= asf_st->pkt.size 00911 || asf->packet_frag_size > asf_st->pkt.size - asf->packet_frag_offset){ 00912 av_log(s, AV_LOG_ERROR, "packet fragment position invalid %u,%u not in %u\n", 00913 asf->packet_frag_offset, asf->packet_frag_size, asf_st->pkt.size); 00914 continue; 00915 } 00916 00917 get_buffer(pb, asf_st->pkt.data + asf->packet_frag_offset, 00918 asf->packet_frag_size); 00919 if (s->key && s->keylen == 20) 00920 ff_asfcrypt_dec(s->key, asf_st->pkt.data + asf->packet_frag_offset, 00921 asf->packet_frag_size); 00922 asf_st->frag_offset += asf->packet_frag_size; 00923 /* test if whole packet is read */ 00924 if (asf_st->frag_offset == asf_st->pkt.size) { 00925 //workaround for macroshit radio DVR-MS files 00926 if( s->streams[asf->stream_index]->codec->codec_id == CODEC_ID_MPEG2VIDEO 00927 && asf_st->pkt.size > 100){ 00928 int i; 00929 for(i=0; i<asf_st->pkt.size && !asf_st->pkt.data[i]; i++); 00930 if(i == asf_st->pkt.size){ 00931 av_log(s, AV_LOG_DEBUG, "discarding ms fart\n"); 00932 asf_st->frag_offset = 0; 00933 av_free_packet(&asf_st->pkt); 00934 continue; 00935 } 00936 } 00937 00938 /* return packet */ 00939 if (asf_st->ds_span > 1) { 00940 if(asf_st->pkt.size != asf_st->ds_packet_size * asf_st->ds_span){ 00941 av_log(s, AV_LOG_ERROR, "pkt.size != ds_packet_size * ds_span (%d %d %d)\n", asf_st->pkt.size, asf_st->ds_packet_size, asf_st->ds_span); 00942 }else{ 00943 /* packet descrambling */ 00944 uint8_t *newdata = av_malloc(asf_st->pkt.size); 00945 if (newdata) { 00946 int offset = 0; 00947 while (offset < asf_st->pkt.size) { 00948 int off = offset / asf_st->ds_chunk_size; 00949 int row = off / asf_st->ds_span; 00950 int col = off % asf_st->ds_span; 00951 int idx = row + col * asf_st->ds_packet_size / asf_st->ds_chunk_size; 00952 //printf("off:%d row:%d col:%d idx:%d\n", off, row, col, idx); 00953 00954 assert(offset + asf_st->ds_chunk_size <= asf_st->pkt.size); 00955 assert(idx+1 <= asf_st->pkt.size / asf_st->ds_chunk_size); 00956 memcpy(newdata + offset, 00957 asf_st->pkt.data + idx * asf_st->ds_chunk_size, 00958 asf_st->ds_chunk_size); 00959 offset += asf_st->ds_chunk_size; 00960 } 00961 av_free(asf_st->pkt.data); 00962 asf_st->pkt.data = newdata; 00963 } 00964 } 00965 } 00966 asf_st->frag_offset = 0; 00967 *pkt= asf_st->pkt; 00968 //printf("packet %d %d\n", asf_st->pkt.size, asf->packet_frag_size); 00969 asf_st->pkt.size = 0; 00970 asf_st->pkt.data = 0; 00971 break; // packet completed 00972 } 00973 } 00974 return 0; 00975 } 00976 00977 static int asf_read_packet(AVFormatContext *s, AVPacket *pkt) 00978 { 00979 ASFContext *asf = s->priv_data; 00980 00981 for (;;) { 00982 int ret; 00983 00984 /* parse cached packets, if any */ 00985 if ((ret = ff_asf_parse_packet(s, s->pb, pkt)) <= 0) 00986 return ret; 00987 if ((ret = ff_asf_get_packet(s, s->pb)) < 0) 00988 assert(asf->packet_size_left < FRAME_HEADER_SIZE || asf->packet_segments < 1); 00989 asf->packet_time_start = 0; 00990 } 00991 00992 return 0; 00993 } 00994 00995 // Added to support seeking after packets have been read 00996 // If information is not reset, read_packet fails due to 00997 // leftover information from previous reads 00998 static void asf_reset_header(AVFormatContext *s) 00999 { 01000 ASFContext *asf = s->priv_data; 01001 ASFStream *asf_st; 01002 int i; 01003 01004 asf->packet_nb_frames = 0; 01005 asf->packet_size_left = 0; 01006 asf->packet_segments = 0; 01007 asf->packet_flags = 0; 01008 asf->packet_property = 0; 01009 asf->packet_timestamp = 0; 01010 asf->packet_segsizetype = 0; 01011 asf->packet_segments = 0; 01012 asf->packet_seq = 0; 01013 asf->packet_replic_size = 0; 01014 asf->packet_key_frame = 0; 01015 asf->packet_padsize = 0; 01016 asf->packet_frag_offset = 0; 01017 asf->packet_frag_size = 0; 01018 asf->packet_frag_timestamp = 0; 01019 asf->packet_multi_size = 0; 01020 asf->packet_obj_size = 0; 01021 asf->packet_time_delta = 0; 01022 asf->packet_time_start = 0; 01023 01024 for(i=0; i<s->nb_streams; i++){ 01025 asf_st= s->streams[i]->priv_data; 01026 av_free_packet(&asf_st->pkt); 01027 asf_st->frag_offset=0; 01028 asf_st->seq=0; 01029 } 01030 asf->asf_st= NULL; 01031 } 01032 01033 static int asf_read_close(AVFormatContext *s) 01034 { 01035 int i; 01036 01037 asf_reset_header(s); 01038 for(i=0;i<s->nb_streams;i++) { 01039 AVStream *st = s->streams[i]; 01040 av_free(st->codec->palctrl); 01041 } 01042 return 0; 01043 } 01044 01045 static int64_t asf_read_pts(AVFormatContext *s, int stream_index, int64_t *ppos, int64_t pos_limit) 01046 { 01047 AVPacket pkt1, *pkt = &pkt1; 01048 ASFStream *asf_st; 01049 int64_t pts; 01050 int64_t pos= *ppos; 01051 int i; 01052 int64_t start_pos[s->nb_streams]; 01053 01054 for(i=0; i<s->nb_streams; i++){ 01055 start_pos[i]= pos; 01056 } 01057 01058 if (s->packet_size > 0) 01059 pos= (pos+s->packet_size-1-s->data_offset)/s->packet_size*s->packet_size+ s->data_offset; 01060 *ppos= pos; 01061 url_fseek(s->pb, pos, SEEK_SET); 01062 01063 //printf("asf_read_pts\n"); 01064 asf_reset_header(s); 01065 for(;;){ 01066 if (av_read_frame(s, pkt) < 0){ 01067 av_log(s, AV_LOG_INFO, "asf_read_pts failed\n"); 01068 return AV_NOPTS_VALUE; 01069 } 01070 01071 pts= pkt->pts; 01072 01073 av_free_packet(pkt); 01074 if(pkt->flags&AV_PKT_FLAG_KEY){ 01075 i= pkt->stream_index; 01076 01077 asf_st= s->streams[i]->priv_data; 01078 01079 // assert((asf_st->packet_pos - s->data_offset) % s->packet_size == 0); 01080 pos= asf_st->packet_pos; 01081 01082 av_add_index_entry(s->streams[i], pos, pts, pkt->size, pos - start_pos[i] + 1, AVINDEX_KEYFRAME); 01083 start_pos[i]= asf_st->packet_pos + 1; 01084 01085 if(pkt->stream_index == stream_index) 01086 break; 01087 } 01088 } 01089 01090 *ppos= pos; 01091 //printf("found keyframe at %"PRId64" stream %d stamp:%"PRId64"\n", *ppos, stream_index, pts); 01092 01093 return pts; 01094 } 01095 01096 static void asf_build_simple_index(AVFormatContext *s, int stream_index) 01097 { 01098 ff_asf_guid g; 01099 ASFContext *asf = s->priv_data; 01100 int64_t current_pos= url_ftell(s->pb); 01101 int i; 01102 01103 url_fseek(s->pb, asf->data_object_offset + asf->data_object_size, SEEK_SET); 01104 get_guid(s->pb, &g); 01105 if (!guidcmp(&g, &index_guid)) { 01106 int64_t itime, last_pos=-1; 01107 int pct, ict; 01108 int64_t av_unused gsize= get_le64(s->pb); 01109 get_guid(s->pb, &g); 01110 itime=get_le64(s->pb); 01111 pct=get_le32(s->pb); 01112 ict=get_le32(s->pb); 01113 av_log(s, AV_LOG_DEBUG, "itime:0x%"PRIx64", pct:%d, ict:%d\n",itime,pct,ict); 01114 01115 for (i=0;i<ict;i++){ 01116 int pktnum=get_le32(s->pb); 01117 int pktct =get_le16(s->pb); 01118 int64_t pos = s->data_offset + s->packet_size*(int64_t)pktnum; 01119 int64_t index_pts= av_rescale(itime, i, 10000); 01120 01121 if(pos != last_pos){ 01122 av_log(s, AV_LOG_DEBUG, "pktnum:%d, pktct:%d\n", pktnum, pktct); 01123 av_add_index_entry(s->streams[stream_index], pos, index_pts, s->packet_size, 0, AVINDEX_KEYFRAME); 01124 last_pos=pos; 01125 } 01126 } 01127 asf->index_read= 1; 01128 } 01129 url_fseek(s->pb, current_pos, SEEK_SET); 01130 } 01131 01132 static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flags) 01133 { 01134 ASFContext *asf = s->priv_data; 01135 AVStream *st = s->streams[stream_index]; 01136 int64_t pos; 01137 int index; 01138 01139 if (s->packet_size <= 0) 01140 return -1; 01141 01142 /* Try using the protocol's read_seek if available */ 01143 if(s->pb) { 01144 int ret = av_url_read_fseek(s->pb, stream_index, pts, flags); 01145 if(ret >= 0) 01146 asf_reset_header(s); 01147 if (ret != AVERROR(ENOSYS)) 01148 return ret; 01149 } 01150 01151 if (!asf->index_read) 01152 asf_build_simple_index(s, stream_index); 01153 01154 if(!(asf->index_read && st->index_entries)){ 01155 if(av_seek_frame_binary(s, stream_index, pts, flags)<0) 01156 return -1; 01157 }else{ 01158 index= av_index_search_timestamp(st, pts, flags); 01159 if(index<0) 01160 return -1; 01161 01162 /* find the position */ 01163 pos = st->index_entries[index].pos; 01164 01165 // various attempts to find key frame have failed so far 01166 // asf_reset_header(s); 01167 // url_fseek(s->pb, pos, SEEK_SET); 01168 // key_pos = pos; 01169 // for(i=0;i<16;i++){ 01170 // pos = url_ftell(s->pb); 01171 // if (av_read_frame(s, &pkt) < 0){ 01172 // av_log(s, AV_LOG_INFO, "seek failed\n"); 01173 // return -1; 01174 // } 01175 // asf_st = s->streams[stream_index]->priv_data; 01176 // pos += st->parser->frame_offset; 01177 // 01178 // if (pkt.size > b) { 01179 // b = pkt.size; 01180 // key_pos = pos; 01181 // } 01182 // 01183 // av_free_packet(&pkt); 01184 // } 01185 01186 /* do the seek */ 01187 av_log(s, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos); 01188 url_fseek(s->pb, pos, SEEK_SET); 01189 } 01190 asf_reset_header(s); 01191 return 0; 01192 } 01193 01194 AVInputFormat asf_demuxer = { 01195 "asf", 01196 NULL_IF_CONFIG_SMALL("ASF format"), 01197 sizeof(ASFContext), 01198 asf_probe, 01199 asf_read_header, 01200 asf_read_packet, 01201 asf_read_close, 01202 asf_read_seek, 01203 asf_read_pts, 01204 .metadata_conv = ff_asf_metadata_conv, 01205 };