00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "avformat.h"
00022 #include "riff.h"
00023 #include "mpegaudio.h"
00024 #include "asf.h"
00025 #include "common.h"
00026 #include "asfcrypt.h"
00027
00028 extern void ff_mms_set_stream_selection(URLContext *h, AVFormatContext *format);
00029
00030 #undef NDEBUG
00031 #include <assert.h>
00032
00033 #define FRAME_HEADER_SIZE 17
00034
00035
00036 static const GUID index_guid = {
00037 0x90, 0x08, 0x00, 0x33, 0xb1, 0xe5, 0xcf, 0x11, 0x89, 0xf4, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb
00038 };
00039
00040 static const GUID stream_bitrate_guid = {
00041 0xce, 0x75, 0xf8, 0x7b, 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2
00042 };
00043
00044
00045
00046
00047
00048 #ifdef DEBUG
00049 #define PRINT_IF_GUID(g,cmp) \
00050 if (!memcmp(g, &cmp, sizeof(GUID))) \
00051 printf("(GUID: %s) ", #cmp)
00052
00053 static void print_guid(const GUID *g)
00054 {
00055 int i;
00056 PRINT_IF_GUID(g, asf_header);
00057 else PRINT_IF_GUID(g, file_header);
00058 else PRINT_IF_GUID(g, stream_header);
00059 else PRINT_IF_GUID(g, audio_stream);
00060 else PRINT_IF_GUID(g, audio_conceal_none);
00061 else PRINT_IF_GUID(g, video_stream);
00062 else PRINT_IF_GUID(g, video_conceal_none);
00063 else PRINT_IF_GUID(g, command_stream);
00064 else PRINT_IF_GUID(g, comment_header);
00065 else PRINT_IF_GUID(g, codec_comment_header);
00066 else PRINT_IF_GUID(g, codec_comment1_header);
00067 else PRINT_IF_GUID(g, data_header);
00068 else PRINT_IF_GUID(g, index_guid);
00069 else PRINT_IF_GUID(g, head1_guid);
00070 else PRINT_IF_GUID(g, head2_guid);
00071 else PRINT_IF_GUID(g, my_guid);
00072 else PRINT_IF_GUID(g, ext_stream_header);
00073 else PRINT_IF_GUID(g, extended_content_header);
00074 else PRINT_IF_GUID(g, ext_stream_embed_stream_header);
00075 else PRINT_IF_GUID(g, ext_stream_audio_stream);
00076 else PRINT_IF_GUID(g, metadata_header);
00077 else PRINT_IF_GUID(g, stream_bitrate_guid);
00078 else
00079 printf("(GUID: unknown) ");
00080 for(i=0;i<16;i++)
00081 printf(" 0x%02x,", (*g)[i]);
00082 printf("}\n");
00083 }
00084 #undef PRINT_IF_GUID
00085 #endif
00086
00087 static void get_guid(ByteIOContext *s, GUID *g)
00088 {
00089 assert(sizeof(*g) == 16);
00090 get_buffer(s, g, sizeof(*g));
00091 }
00092
00093 #if 0
00094 static void get_str16(ByteIOContext *pb, char *buf, int buf_size)
00095 {
00096 int len, c;
00097 char *q;
00098
00099 len = get_le16(pb);
00100 q = buf;
00101 while (len > 0) {
00102 c = get_le16(pb);
00103 if ((q - buf) < buf_size - 1)
00104 *q++ = c;
00105 len--;
00106 }
00107 *q = '\0';
00108 }
00109 #endif
00110
00111 static int is_mms(ByteIOContext *pb)
00112 {
00113 return url_fileno(pb) && url_fileno(pb)->prot &&
00114 !strcmp(url_fileno(pb)->prot->name, "mmsh");
00115 }
00116
00117 static void get_str16_nolen(ByteIOContext *pb, int len, char *buf, int buf_size)
00118 {
00119 char* q = buf;
00120 len /= 2;
00121 while (len--) {
00122 uint8_t tmp;
00123 PUT_UTF8(get_le16(pb), tmp, if (q - buf < buf_size - 1) *q++ = tmp;)
00124 }
00125 *q = '\0';
00126 }
00127
00128 static int asf_probe(AVProbeData *pd)
00129 {
00130
00131 if (!memcmp(pd->buf, &asf_header, sizeof(GUID)))
00132 return AVPROBE_SCORE_MAX;
00133 else
00134 return 0;
00135 }
00136
00137 static int get_value(ByteIOContext *pb, int type){
00138 switch(type){
00139 case 2: return get_le32(pb);
00140 case 3: return get_le32(pb);
00141 case 4: return get_le64(pb);
00142 case 5: return get_le16(pb);
00143 default:return INT_MIN;
00144 }
00145 }
00146
00147 static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
00148 {
00149 ASFContext *asf = s->priv_data;
00150 GUID g;
00151 ByteIOContext *pb = &s->pb;
00152 AVStream *st;
00153 ASFStream *asf_st;
00154 int size, i;
00155 int64_t gsize;
00156 AVRational dar[128];
00157 uint32_t bitrate[128];
00158
00159 memset(dar, 0, sizeof(dar));
00160 memset(bitrate, 0, sizeof(bitrate));
00161
00162 get_guid(pb, &g);
00163 if (memcmp(&g, &asf_header, sizeof(GUID)))
00164 goto fail;
00165 get_le64(pb);
00166 get_le32(pb);
00167 get_byte(pb);
00168 get_byte(pb);
00169 memset(&asf->asfid2avid, -1, sizeof(asf->asfid2avid));
00170 for(;;) {
00171 get_guid(pb, &g);
00172 gsize = get_le64(pb);
00173 #ifdef DEBUG
00174 printf("%08"PRIx64": ", url_ftell(pb) - 24);
00175 print_guid(&g);
00176 printf(" size=0x%"PRIx64"\n", gsize);
00177 #endif
00178 if (!memcmp(&g, &data_header, sizeof(GUID))) {
00179 asf->data_object_offset = url_ftell(pb);
00180
00181 if (!(asf->hdr.flags & 0x01) && gsize >= 100) {
00182 asf->data_object_size = gsize - 24;
00183 } else {
00184 asf->data_object_size = (uint64_t)-1;
00185 }
00186 break;
00187 }
00188 if (gsize < 24)
00189 goto fail;
00190 if (!memcmp(&g, &file_header, sizeof(GUID))) {
00191 get_guid(pb, &asf->hdr.guid);
00192 asf->hdr.file_size = get_le64(pb);
00193 asf->hdr.create_time = get_le64(pb);
00194 asf->nb_packets = get_le64(pb);
00195 asf->hdr.send_time = get_le64(pb);
00196 asf->hdr.play_time = get_le64(pb);
00197 asf->hdr.preroll = get_le32(pb);
00198 asf->hdr.ignore = get_le32(pb);
00199 asf->hdr.flags = get_le32(pb);
00200 asf->hdr.min_pktsize = get_le32(pb);
00201 asf->hdr.max_pktsize = get_le32(pb);
00202 asf->hdr.max_bitrate = get_le32(pb);
00203 asf->packet_size = asf->hdr.max_pktsize;
00204 } else if (!memcmp(&g, &stream_header, sizeof(GUID))) {
00205 int type, type_specific_size, sizeX;
00206 uint64_t total_size;
00207 unsigned int tag1;
00208 int64_t pos1, pos2, start_time;
00209 int test_for_ext_stream_audio, is_dvr_ms_audio=0;
00210
00211 pos1 = url_ftell(pb);
00212
00213 st = av_new_stream(s, 0);
00214 if (!st)
00215 goto fail;
00216 av_set_pts_info(st, 32, 1, 1000);
00217 asf_st = av_mallocz(sizeof(ASFStream));
00218 if (!asf_st)
00219 goto fail;
00220 st->priv_data = asf_st;
00221 start_time = asf->hdr.preroll;
00222
00223 if(!(asf->hdr.flags & 0x01)) {
00224 st->duration = asf->hdr.send_time /
00225 (10000000 / 1000) - start_time;
00226 }
00227 get_guid(pb, &g);
00228
00229 test_for_ext_stream_audio = 0;
00230 if (!memcmp(&g, &audio_stream, sizeof(GUID))) {
00231 type = CODEC_TYPE_AUDIO;
00232 } else if (!memcmp(&g, &video_stream, sizeof(GUID))) {
00233 type = CODEC_TYPE_VIDEO;
00234 } else if (!memcmp(&g, &command_stream, sizeof(GUID))) {
00235 type = CODEC_TYPE_UNKNOWN;
00236 } else if (!memcmp(&g, &ext_stream_embed_stream_header, sizeof(GUID))) {
00237 test_for_ext_stream_audio = 1;
00238 type = CODEC_TYPE_UNKNOWN;
00239 } else {
00240 goto fail;
00241 }
00242 get_guid(pb, &g);
00243 total_size = get_le64(pb);
00244 type_specific_size = get_le32(pb);
00245 get_le32(pb);
00246 st->id = get_le16(pb) & 0x7f;
00247
00248 asf->asfid2avid[st->id] = s->nb_streams - 1;
00249
00250 get_le32(pb);
00251
00252 if (test_for_ext_stream_audio) {
00253 get_guid(pb, &g);
00254 if (!memcmp(&g, &ext_stream_audio_stream, sizeof(GUID))) {
00255 type = CODEC_TYPE_AUDIO;
00256 is_dvr_ms_audio=1;
00257 get_guid(pb, &g);
00258 get_le32(pb);
00259 get_le32(pb);
00260 get_le32(pb);
00261 get_guid(pb, &g);
00262 get_le32(pb);
00263 }
00264 }
00265
00266 st->codec->codec_type = type;
00267 if (type == CODEC_TYPE_AUDIO) {
00268 get_wav_header(pb, st->codec, type_specific_size);
00269 if (is_dvr_ms_audio) {
00270
00271
00272 st->codec->codec_id = CODEC_ID_NONE;
00273 st->codec->codec_tag = 0;
00274 }
00275 st->need_parsing = AVSTREAM_PARSE_FULL;
00276
00277 pos2 = url_ftell(pb);
00278 if (gsize >= (pos2 + 8 - pos1 + 24)) {
00279 asf_st->ds_span = get_byte(pb);
00280 asf_st->ds_packet_size = get_le16(pb);
00281 asf_st->ds_chunk_size = get_le16(pb);
00282 get_le16(pb);
00283 get_byte(pb);
00284 }
00285
00286
00287
00288 if (asf_st->ds_span > 1) {
00289 if (!asf_st->ds_chunk_size
00290 || (asf_st->ds_packet_size/asf_st->ds_chunk_size <= 1)
00291 || asf_st->ds_packet_size % asf_st->ds_chunk_size)
00292 asf_st->ds_span = 0;
00293 }
00294 switch (st->codec->codec_id) {
00295 case CODEC_ID_MP3:
00296 st->codec->frame_size = MPA_FRAME_SIZE;
00297 break;
00298 case CODEC_ID_PCM_S16LE:
00299 case CODEC_ID_PCM_S16BE:
00300 case CODEC_ID_PCM_U16LE:
00301 case CODEC_ID_PCM_U16BE:
00302 case CODEC_ID_PCM_S8:
00303 case CODEC_ID_PCM_U8:
00304 case CODEC_ID_PCM_ALAW:
00305 case CODEC_ID_PCM_MULAW:
00306 st->codec->frame_size = 1;
00307 break;
00308 default:
00309
00310 st->codec->frame_size = 1;
00311 break;
00312 }
00313 } else if (type == CODEC_TYPE_VIDEO) {
00314 get_le32(pb);
00315 get_le32(pb);
00316 get_byte(pb);
00317 size = get_le16(pb);
00318 sizeX= get_le32(pb);
00319 st->codec->width = get_le32(pb);
00320 st->codec->height = get_le32(pb);
00321
00322 get_le16(pb);
00323 st->codec->bits_per_sample = get_le16(pb);
00324 tag1 = get_le32(pb);
00325 url_fskip(pb, 20);
00326
00327 size= sizeX;
00328 if (size > 40) {
00329 st->codec->extradata_size = size - 40;
00330 st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
00331 get_buffer(pb, st->codec->extradata, st->codec->extradata_size);
00332 }
00333
00334
00335
00336
00337 if (st->codec->extradata_size && (st->codec->bits_per_sample <= 8)) {
00338 st->codec->palctrl = av_mallocz(sizeof(AVPaletteControl));
00339 #ifdef WORDS_BIGENDIAN
00340 for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)/4; i++)
00341 st->codec->palctrl->palette[i] = bswap_32(((uint32_t*)st->codec->extradata)[i]);
00342 #else
00343 memcpy(st->codec->palctrl->palette, st->codec->extradata,
00344 FFMIN(st->codec->extradata_size, AVPALETTE_SIZE));
00345 #endif
00346 st->codec->palctrl->palette_changed = 1;
00347 }
00348
00349 st->codec->codec_tag = tag1;
00350 st->codec->codec_id = codec_get_id(codec_bmp_tags, tag1);
00351 if(tag1 == MKTAG('D', 'V', 'R', ' '))
00352 st->need_parsing = AVSTREAM_PARSE_FULL;
00353 }
00354 pos2 = url_ftell(pb);
00355 url_fskip(pb, gsize - (pos2 - pos1 + 24));
00356 } else if (!memcmp(&g, &comment_header, sizeof(GUID))) {
00357 int len1, len2, len3, len4, len5;
00358
00359 len1 = get_le16(pb);
00360 len2 = get_le16(pb);
00361 len3 = get_le16(pb);
00362 len4 = get_le16(pb);
00363 len5 = get_le16(pb);
00364 get_str16_nolen(pb, len1, s->title , sizeof(s->title));
00365 get_str16_nolen(pb, len2, s->author , sizeof(s->author));
00366 get_str16_nolen(pb, len3, s->copyright, sizeof(s->copyright));
00367 get_str16_nolen(pb, len4, s->comment , sizeof(s->comment));
00368 url_fskip(pb, len5);
00369 } else if (!memcmp(&g, &stream_bitrate_guid, sizeof(GUID))) {
00370 int stream_count = get_le16(pb);
00371 int j;
00372
00373
00374
00375 for(j = 0; j < stream_count; j++) {
00376 int flags, bitrate, stream_id;
00377
00378 flags= get_le16(pb);
00379 bitrate= get_le32(pb);
00380 stream_id= (flags & 0x7f);
00381
00382 asf->stream_bitrates[stream_id]= bitrate;
00383 }
00384 } else if (!memcmp(&g, &extended_content_header, sizeof(GUID))) {
00385 int desc_count, i;
00386
00387 desc_count = get_le16(pb);
00388 for(i=0;i<desc_count;i++)
00389 {
00390 int name_len,value_type,value_len;
00391 uint64_t value_num = 0;
00392 char name[1024];
00393
00394 name_len = get_le16(pb);
00395 get_str16_nolen(pb, name_len, name, sizeof(name));
00396 value_type = get_le16(pb);
00397 value_len = get_le16(pb);
00398 if ((value_type == 0) || (value_type == 1))
00399 {
00400 if (!strcmp(name,"WM/AlbumTitle")) get_str16_nolen(pb, value_len, s->album, sizeof(s->album));
00401 else if(!strcmp(name,"WM/Genre" )) get_str16_nolen(pb, value_len, s->genre, sizeof(s->genre));
00402 else if(!strcmp(name,"WM/Year" )) {
00403 char year[8];
00404 get_str16_nolen(pb, value_len, year, sizeof(year));
00405 s->year = atoi(year);
00406 }
00407 else if(!strcmp(name,"WM/Track") && s->track == 0) {
00408 char track[8];
00409 get_str16_nolen(pb, value_len, track, sizeof(track));
00410 s->track = strtol(track, NULL, 10) + 1;
00411 }
00412 else if(!strcmp(name,"WM/TrackNumber")) {
00413 char track[8];
00414 get_str16_nolen(pb, value_len, track, sizeof(track));
00415 s->track = strtol(track, NULL, 10);
00416 }
00417 else url_fskip(pb, value_len);
00418 }
00419 if ((value_type >= 2) && (value_type <= 5))
00420 {
00421 value_num= get_value(pb, value_type);
00422 if (!strcmp(name,"WM/Track" ) && s->track == 0) s->track = value_num + 1;
00423 if (!strcmp(name,"WM/TrackNumber")) s->track = value_num;
00424 }
00425 }
00426 } else if (!memcmp(&g, &metadata_header, sizeof(GUID))) {
00427 int n, stream_num, name_len, value_len, value_type, value_num;
00428 n = get_le16(pb);
00429
00430 for(i=0;i<n;i++) {
00431 char name[1024];
00432
00433 get_le16(pb);
00434 stream_num= get_le16(pb);
00435 name_len= get_le16(pb);
00436 value_type= get_le16(pb);
00437 value_len= get_le32(pb);
00438
00439 get_str16_nolen(pb, name_len, name, sizeof(name));
00440
00441 value_num= get_le16(pb);
00442 url_fskip(pb, value_len - 2);
00443
00444 if(stream_num<128){
00445 if (!strcmp(name, "AspectRatioX")) dar[stream_num].num= value_num;
00446 else if(!strcmp(name, "AspectRatioY")) dar[stream_num].den= value_num;
00447 }
00448 }
00449 } else if (!memcmp(&g, &ext_stream_header, sizeof(GUID))) {
00450 int ext_len, payload_ext_ct, stream_ct;
00451 uint32_t ext_d, leak_rate, stream_num;
00452 int64_t pos_ex_st;
00453 pos_ex_st = url_ftell(pb);
00454
00455 get_le64(pb);
00456 get_le64(pb);
00457 leak_rate = get_le32(pb);
00458 get_le32(pb);
00459 get_le32(pb);
00460 get_le32(pb);
00461 get_le32(pb);
00462 get_le32(pb);
00463 get_le32(pb);
00464 get_le32(pb);
00465 stream_num = get_le16(pb);
00466 get_le16(pb);
00467 get_le64(pb);
00468 stream_ct = get_le16(pb);
00469 payload_ext_ct = get_le16(pb);
00470
00471 if (stream_num < 128)
00472 bitrate[stream_num] = leak_rate;
00473
00474 for (i=0; i<stream_ct; i++){
00475 get_le16(pb);
00476 ext_len = get_le16(pb);
00477 url_fseek(pb, ext_len, SEEK_CUR);
00478 }
00479
00480 for (i=0; i<payload_ext_ct; i++){
00481 get_guid(pb, &g);
00482 ext_d=get_le16(pb);
00483 ext_len=get_le32(pb);
00484 url_fseek(pb, ext_len, SEEK_CUR);
00485 }
00486
00487
00488
00489 } else if (!memcmp(&g, &head1_guid, sizeof(GUID))) {
00490 int v1, v2;
00491 get_guid(pb, &g);
00492 v1 = get_le32(pb);
00493 v2 = get_le16(pb);
00494 #if 0
00495 } else if (!memcmp(&g, &codec_comment_header, sizeof(GUID))) {
00496 int len, v1, n, num;
00497 char str[256], *q;
00498 char tag[16];
00499
00500 get_guid(pb, &g);
00501 print_guid(&g);
00502
00503 n = get_le32(pb);
00504 for(i=0;i<n;i++) {
00505 num = get_le16(pb);
00506 get_str16(pb, str, sizeof(str));
00507 get_str16(pb, str, sizeof(str));
00508 len = get_le16(pb);
00509 q = tag;
00510 while (len > 0) {
00511 v1 = get_byte(pb);
00512 if ((q - tag) < sizeof(tag) - 1)
00513 *q++ = v1;
00514 len--;
00515 }
00516 *q = '\0';
00517 }
00518 #endif
00519 } else if (url_feof(pb)) {
00520 goto fail;
00521 } else {
00522 url_fseek(pb, gsize - 24, SEEK_CUR);
00523 }
00524 }
00525 get_guid(pb, &g);
00526 get_le64(pb);
00527 get_byte(pb);
00528 get_byte(pb);
00529 if (url_feof(pb))
00530 goto fail;
00531 asf->data_offset = url_ftell(pb);
00532 asf->packet_size_left = 0;
00533
00534
00535 for(i=0; i<128; i++){
00536 int stream_num= asf->asfid2avid[i];
00537 if(stream_num>=0){
00538 AVCodecContext *codec= s->streams[stream_num]->codec;
00539 if (!codec->bit_rate)
00540 codec->bit_rate = bitrate[i];
00541 if (dar[i].num > 0 && dar[i].den > 0)
00542 av_reduce(&codec->sample_aspect_ratio.num,
00543 &codec->sample_aspect_ratio.den,
00544 dar[i].num, dar[i].den, INT_MAX);
00545
00546 }
00547 }
00548
00549 #ifdef CONFIG_MMSH_PROTOCOL
00550
00551 if(is_mms(pb))
00552 ff_mms_set_stream_selection(url_fileno(pb), s);
00553 #endif
00554
00555 return 0;
00556
00557 fail:
00558 for(i=0;i<s->nb_streams;i++) {
00559 AVStream *st = s->streams[i];
00560 if (st) {
00561 av_free(st->priv_data);
00562 av_free(st->codec->extradata);
00563 }
00564 av_free(st);
00565 }
00566 return -1;
00567 }
00568
00569 #define DO_2BITS(bits, var, defval) \
00570 switch (bits & 3) \
00571 { \
00572 case 3: var = get_le32(pb); rsize += 4; break; \
00573 case 2: var = get_le16(pb); rsize += 2; break; \
00574 case 1: var = get_byte(pb); rsize++; break; \
00575 default: var = defval; break; \
00576 }
00577
00582 static int asf_get_packet(AVFormatContext *s)
00583 {
00584 ASFContext *asf = s->priv_data;
00585 ByteIOContext *pb = &s->pb;
00586 uint32_t packet_length, padsize;
00587 int rsize = 8;
00588 int c, d, e, off;
00589
00590 off= (url_ftell(&s->pb) - s->data_offset) % asf->packet_size + 3;
00591
00592 c=d=e=-1;
00593 while(off-- > 0){
00594 c=d; d=e;
00595 e= get_byte(pb);
00596 if(c == 0x82 && !d && !e)
00597 break;
00598 }
00599
00600 if (c != 0x82) {
00601 if (!url_feof(pb))
00602 av_log(s, AV_LOG_ERROR, "ff asf bad header %x at:%"PRId64"\n", c, url_ftell(pb));
00603 }
00604 if ((c & 0x8f) == 0x82) {
00605 if (d || e) {
00606 if (!url_feof(pb))
00607 av_log(s, AV_LOG_ERROR, "ff asf bad non zero\n");
00608 return -1;
00609 }
00610 c= get_byte(pb);
00611 d= get_byte(pb);
00612 rsize+=3;
00613 }else{
00614 url_fseek(pb, -1, SEEK_CUR);
00615 }
00616
00617 asf->packet_flags = c;
00618 asf->packet_property = d;
00619
00620 DO_2BITS(asf->packet_flags >> 5, packet_length, asf->packet_size);
00621 DO_2BITS(asf->packet_flags >> 1, padsize, 0);
00622 DO_2BITS(asf->packet_flags >> 3, padsize, 0);
00623
00624
00625 if(packet_length >= (1U<<29)){
00626 av_log(s, AV_LOG_ERROR, "invalid packet_length %d at:%"PRId64"\n", packet_length, url_ftell(pb));
00627 return -1;
00628 }
00629 if(padsize >= packet_length){
00630 av_log(s, AV_LOG_ERROR, "invalid padsize %d at:%"PRId64"\n", padsize, url_ftell(pb));
00631 return -1;
00632 }
00633
00634 asf->packet_timestamp = get_le32(pb);
00635 get_le16(pb);
00636
00637
00638 if (asf->packet_flags & 0x01) {
00639 asf->packet_segsizetype = get_byte(pb); rsize++;
00640 asf->packet_segments = asf->packet_segsizetype & 0x3f;
00641 } else {
00642 asf->packet_segments = 1;
00643 asf->packet_segsizetype = 0x80;
00644 }
00645 asf->packet_size_left = packet_length - padsize - rsize;
00646 if (packet_length < asf->hdr.min_pktsize)
00647 padsize += asf->hdr.min_pktsize - packet_length;
00648 asf->packet_padsize = padsize;
00649 #ifdef DEBUG
00650 printf("packet: size=%d padsize=%d left=%d\n", asf->packet_size, asf->packet_padsize, asf->packet_size_left);
00651 #endif
00652 return 0;
00653 }
00654
00659 static int asf_read_frame_header(AVFormatContext *s){
00660 ASFContext *asf = s->priv_data;
00661 ByteIOContext *pb = &s->pb;
00662 int rsize = 1;
00663 int num = get_byte(pb);
00664 int64_t ts0, ts1;
00665
00666 asf->packet_segments--;
00667 asf->packet_key_frame = num >> 7;
00668 asf->stream_index = asf->asfid2avid[num & 0x7f];
00669
00670 DO_2BITS(asf->packet_property >> 4, asf->packet_seq, 0);
00671 DO_2BITS(asf->packet_property >> 2, asf->packet_frag_offset, 0);
00672 DO_2BITS(asf->packet_property, asf->packet_replic_size, 0);
00673
00674 if (asf->packet_replic_size >= 8) {
00675 asf->packet_obj_size = get_le32(pb);
00676 if(asf->packet_obj_size >= (1<<24) || asf->packet_obj_size <= 0){
00677 av_log(s, AV_LOG_ERROR, "packet_obj_size invalid\n");
00678 return -1;
00679 }
00680 asf->packet_frag_timestamp = get_le32(pb);
00681 if(asf->packet_replic_size >= 8+38+4){
00682
00683
00684
00685 url_fskip(pb, 10);
00686 ts0= get_le64(pb);
00687 ts1= get_le64(pb);
00688 url_fskip(pb, 12);
00689 get_le32(pb);
00690 url_fskip(pb, asf->packet_replic_size - 8 - 38 - 4);
00691 if(ts0!= -1) asf->packet_frag_timestamp= ts0/10000;
00692 else asf->packet_frag_timestamp= AV_NOPTS_VALUE;
00693 }else
00694 url_fskip(pb, asf->packet_replic_size - 8);
00695 rsize += asf->packet_replic_size;
00696 } else if (asf->packet_replic_size==1){
00697
00698 asf->packet_time_start = asf->packet_frag_offset;
00699 asf->packet_frag_offset = 0;
00700 asf->packet_frag_timestamp = asf->packet_timestamp;
00701
00702 asf->packet_time_delta = get_byte(pb);
00703 rsize++;
00704 }else if(asf->packet_replic_size!=0){
00705 av_log(s, AV_LOG_ERROR, "unexpected packet_replic_size of %d\n", asf->packet_replic_size);
00706 return -1;
00707 }
00708 if (asf->packet_flags & 0x01) {
00709 DO_2BITS(asf->packet_segsizetype >> 6, asf->packet_frag_size, 0);
00710 if(asf->packet_frag_size > asf->packet_size_left - rsize){
00711 av_log(s, AV_LOG_ERROR, "packet_frag_size is invalid\n");
00712 return -1;
00713 }
00714
00715 } else {
00716 asf->packet_frag_size = asf->packet_size_left - rsize;
00717
00718 }
00719 if (asf->packet_replic_size == 1) {
00720 asf->packet_multi_size = asf->packet_frag_size;
00721 if (asf->packet_multi_size > asf->packet_size_left)
00722 return -1;
00723 }
00724 asf->packet_size_left -= rsize;
00725
00726
00727 return 0;
00728 }
00729
00730 static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
00731 {
00732 ASFContext *asf = s->priv_data;
00733 ASFStream *asf_st = 0;
00734 ByteIOContext *pb = &s->pb;
00735
00736 for (;;) {
00737 if(url_feof(pb))
00738 return AVERROR(EIO);
00739 if (asf->packet_size_left < FRAME_HEADER_SIZE
00740 || asf->packet_segments < 1) {
00741
00742 int ret = asf->packet_size_left + asf->packet_padsize;
00743
00744 assert(ret>=0);
00745
00746 url_fskip(pb, ret);
00747
00748 asf->packet_pos= url_ftell(&s->pb);
00749 if (asf->data_object_size != (uint64_t)-1 &&
00750 (asf->packet_pos - asf->data_object_offset >= asf->data_object_size))
00751 return AVERROR(EIO);
00752 ret = asf_get_packet(s);
00753
00754 if (ret < 0)
00755 assert(asf->packet_size_left < FRAME_HEADER_SIZE || asf->packet_segments < 1);
00756 asf->packet_time_start = 0;
00757 continue;
00758 }
00759 if (asf->packet_time_start == 0) {
00760 if(asf_read_frame_header(s) < 0){
00761 asf->packet_segments= 0;
00762 continue;
00763 }
00764 if (asf->stream_index < 0
00765 || s->streams[asf->stream_index]->discard >= AVDISCARD_ALL
00766 || (!asf->packet_key_frame && s->streams[asf->stream_index]->discard >= AVDISCARD_NONKEY)
00767 ) {
00768 asf->packet_time_start = 0;
00769
00770 url_fskip(pb, asf->packet_frag_size);
00771 asf->packet_size_left -= asf->packet_frag_size;
00772 if(asf->stream_index < 0)
00773 av_log(s, AV_LOG_ERROR, "ff asf skip %d (unknown stream)\n", asf->packet_frag_size);
00774 continue;
00775 }
00776 asf->asf_st = s->streams[asf->stream_index]->priv_data;
00777 }
00778 asf_st = asf->asf_st;
00779
00780 if (asf->packet_replic_size == 1) {
00781
00782 asf->packet_frag_timestamp = asf->packet_time_start;
00783 asf->packet_time_start += asf->packet_time_delta;
00784 asf->packet_obj_size = asf->packet_frag_size = get_byte(pb);
00785 asf->packet_size_left--;
00786 asf->packet_multi_size--;
00787 if (asf->packet_multi_size < asf->packet_obj_size)
00788 {
00789 asf->packet_time_start = 0;
00790 url_fskip(pb, asf->packet_multi_size);
00791 asf->packet_size_left -= asf->packet_multi_size;
00792 continue;
00793 }
00794 asf->packet_multi_size -= asf->packet_obj_size;
00795
00796 }
00797 if(
00798 asf_st->frag_offset + asf->packet_frag_size <= asf_st->pkt.size
00799 && asf_st->frag_offset + asf->packet_frag_size > asf->packet_obj_size){
00800 av_log(s, AV_LOG_INFO, "ignoring invalid packet_obj_size (%d %d %d %d)\n",
00801 asf_st->frag_offset, asf->packet_frag_size,
00802 asf->packet_obj_size, asf_st->pkt.size);
00803 asf->packet_obj_size= asf_st->pkt.size;
00804 }
00805
00806 if ( asf_st->pkt.size != asf->packet_obj_size
00807 || asf_st->frag_offset + asf->packet_frag_size > asf_st->pkt.size) {
00808 if(asf_st->pkt.data){
00809 av_log(s, AV_LOG_INFO, "freeing incomplete packet size %d, new %d\n", asf_st->pkt.size, asf->packet_obj_size);
00810 asf_st->frag_offset = 0;
00811 av_free_packet(&asf_st->pkt);
00812 }
00813
00814 av_new_packet(&asf_st->pkt, asf->packet_obj_size);
00815 asf_st->seq = asf->packet_seq;
00816 asf_st->pkt.pts = asf->packet_frag_timestamp;
00817 asf_st->pkt.stream_index = asf->stream_index;
00818 asf_st->pkt.pos =
00819 asf_st->packet_pos= asf->packet_pos;
00820
00821
00822
00823 if (s->streams[asf->stream_index]->codec->codec_type == CODEC_TYPE_AUDIO)
00824 asf->packet_key_frame = 1;
00825 if (asf->packet_key_frame)
00826 asf_st->pkt.flags |= PKT_FLAG_KEY;
00827 }
00828
00829
00830
00831
00832
00833 asf->packet_size_left -= asf->packet_frag_size;
00834 if (asf->packet_size_left < 0)
00835 continue;
00836
00837 if( asf->packet_frag_offset >= asf_st->pkt.size
00838 || asf->packet_frag_size > asf_st->pkt.size - asf->packet_frag_offset){
00839 av_log(s, AV_LOG_ERROR, "packet fragment position invalid %u,%u not in %u\n",
00840 asf->packet_frag_offset, asf->packet_frag_size, asf_st->pkt.size);
00841 continue;
00842 }
00843
00844 get_buffer(pb, asf_st->pkt.data + asf->packet_frag_offset,
00845 asf->packet_frag_size);
00846 if (s->key && s->keylen == 20)
00847 ff_asfcrypt_dec(s->key, asf_st->pkt.data + asf->packet_frag_offset,
00848 asf->packet_frag_size);
00849 asf_st->frag_offset += asf->packet_frag_size;
00850
00851 if (asf_st->frag_offset == asf_st->pkt.size) {
00852
00853 if( s->streams[asf->stream_index]->codec->codec_id == CODEC_ID_MPEG2VIDEO
00854 && asf_st->pkt.size > 100){
00855 int i;
00856 for(i=0; i<asf_st->pkt.size && !asf_st->pkt.data[i]; i++);
00857 if(i == asf_st->pkt.size){
00858 av_log(s, AV_LOG_DEBUG, "discarding ms fart\n");
00859 asf_st->frag_offset = 0;
00860 av_free_packet(&asf_st->pkt);
00861 continue;
00862 }
00863 }
00864
00865
00866 if (asf_st->ds_span > 1) {
00867 if(asf_st->pkt.size != asf_st->ds_packet_size * asf_st->ds_span){
00868 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);
00869 }else{
00870
00871 uint8_t *newdata = av_malloc(asf_st->pkt.size);
00872 if (newdata) {
00873 int offset = 0;
00874 while (offset < asf_st->pkt.size) {
00875 int off = offset / asf_st->ds_chunk_size;
00876 int row = off / asf_st->ds_span;
00877 int col = off % asf_st->ds_span;
00878 int idx = row + col * asf_st->ds_packet_size / asf_st->ds_chunk_size;
00879
00880
00881 assert(offset + asf_st->ds_chunk_size <= asf_st->pkt.size);
00882 assert(idx+1 <= asf_st->pkt.size / asf_st->ds_chunk_size);
00883 memcpy(newdata + offset,
00884 asf_st->pkt.data + idx * asf_st->ds_chunk_size,
00885 asf_st->ds_chunk_size);
00886 offset += asf_st->ds_chunk_size;
00887 }
00888 av_free(asf_st->pkt.data);
00889 asf_st->pkt.data = newdata;
00890 }
00891 }
00892 }
00893 asf_st->frag_offset = 0;
00894 *pkt= asf_st->pkt;
00895
00896 asf_st->pkt.size = 0;
00897 asf_st->pkt.data = 0;
00898 break;
00899 }
00900 }
00901 return 0;
00902 }
00903
00904
00905
00906
00907 static void asf_reset_header(AVFormatContext *s)
00908 {
00909 ASFContext *asf = s->priv_data;
00910 ASFStream *asf_st;
00911 int i;
00912
00913 asf->packet_nb_frames = 0;
00914 asf->packet_size_left = 0;
00915 asf->packet_segments = 0;
00916 asf->packet_flags = 0;
00917 asf->packet_property = 0;
00918 asf->packet_timestamp = 0;
00919 asf->packet_segsizetype = 0;
00920 asf->packet_segments = 0;
00921 asf->packet_seq = 0;
00922 asf->packet_replic_size = 0;
00923 asf->packet_key_frame = 0;
00924 asf->packet_padsize = 0;
00925 asf->packet_frag_offset = 0;
00926 asf->packet_frag_size = 0;
00927 asf->packet_frag_timestamp = 0;
00928 asf->packet_multi_size = 0;
00929 asf->packet_obj_size = 0;
00930 asf->packet_time_delta = 0;
00931 asf->packet_time_start = 0;
00932
00933 for(i=0; i<s->nb_streams; i++){
00934 asf_st= s->streams[i]->priv_data;
00935 av_free_packet(&asf_st->pkt);
00936 asf_st->frag_offset=0;
00937 asf_st->seq=0;
00938 }
00939 asf->asf_st= NULL;
00940 }
00941
00942 static int asf_read_close(AVFormatContext *s)
00943 {
00944 int i;
00945
00946 asf_reset_header(s);
00947 for(i=0;i<s->nb_streams;i++) {
00948 AVStream *st = s->streams[i];
00949 av_free(st->priv_data);
00950 av_free(st->codec->palctrl);
00951 }
00952 return 0;
00953 }
00954
00955 static int64_t asf_read_pts(AVFormatContext *s, int stream_index, int64_t *ppos, int64_t pos_limit)
00956 {
00957 ASFContext *asf = s->priv_data;
00958 AVPacket pkt1, *pkt = &pkt1;
00959 ASFStream *asf_st;
00960 int64_t pts;
00961 int64_t pos= *ppos;
00962 int i;
00963 int64_t start_pos[s->nb_streams];
00964
00965 for(i=0; i<s->nb_streams; i++){
00966 start_pos[i]= pos;
00967 }
00968
00969 pos= (pos+asf->packet_size-1-s->data_offset)/asf->packet_size*asf->packet_size+ s->data_offset;
00970 *ppos= pos;
00971 url_fseek(&s->pb, pos, SEEK_SET);
00972
00973
00974 asf_reset_header(s);
00975 for(;;){
00976 if (av_read_frame(s, pkt) < 0){
00977 av_log(s, AV_LOG_INFO, "asf_read_pts failed\n");
00978 return AV_NOPTS_VALUE;
00979 }
00980
00981 pts= pkt->pts;
00982
00983 av_free_packet(pkt);
00984 if(pkt->flags&PKT_FLAG_KEY){
00985 i= pkt->stream_index;
00986
00987 asf_st= s->streams[i]->priv_data;
00988
00989
00990 pos= asf_st->packet_pos;
00991
00992 av_add_index_entry(s->streams[i], pos, pts, pkt->size, pos - start_pos[i] + 1, AVINDEX_KEYFRAME);
00993 start_pos[i]= asf_st->packet_pos + 1;
00994
00995 if(pkt->stream_index == stream_index)
00996 break;
00997 }
00998 }
00999
01000 *ppos= pos;
01001
01002
01003 return pts;
01004 }
01005
01006 static void asf_build_simple_index(AVFormatContext *s, int stream_index)
01007 {
01008 GUID g;
01009 ASFContext *asf = s->priv_data;
01010 int64_t gsize, itime;
01011 int64_t pos, current_pos, index_pts;
01012 int i;
01013 int pct,ict;
01014
01015 current_pos = url_ftell(&s->pb);
01016
01017 url_fseek(&s->pb, asf->data_object_offset + asf->data_object_size, SEEK_SET);
01018 get_guid(&s->pb, &g);
01019 if (!memcmp(&g, &index_guid, sizeof(GUID))) {
01020 gsize = get_le64(&s->pb);
01021 get_guid(&s->pb, &g);
01022 itime=get_le64(&s->pb);
01023 pct=get_le32(&s->pb);
01024 ict=get_le32(&s->pb);
01025 av_log(NULL, AV_LOG_DEBUG, "itime:0x%"PRIx64", pct:%d, ict:%d\n",itime,pct,ict);
01026
01027 for (i=0;i<ict;i++){
01028 int pktnum=get_le32(&s->pb);
01029 int pktct =get_le16(&s->pb);
01030 av_log(NULL, AV_LOG_DEBUG, "pktnum:%d, pktct:%d\n", pktnum, pktct);
01031
01032 pos=s->data_offset + asf->packet_size*(int64_t)pktnum;
01033 index_pts=av_rescale(itime, i, 10000);
01034
01035 av_add_index_entry(s->streams[stream_index], pos, index_pts, asf->packet_size, 0, AVINDEX_KEYFRAME);
01036 }
01037 asf->index_read= 1;
01038 }
01039 url_fseek(&s->pb, current_pos, SEEK_SET);
01040 }
01041
01042 static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flags)
01043 {
01044 ASFContext *asf = s->priv_data;
01045 AVStream *st = s->streams[stream_index];
01046 int64_t pos;
01047 int index;
01048
01049 if (asf->packet_size <= 0)
01050 return -1;
01051
01052 if (!asf->index_read)
01053 asf_build_simple_index(s, stream_index);
01054
01055 if(!(asf->index_read && st->index_entries)){
01056 if(av_seek_frame_binary(s, stream_index, pts, flags)<0)
01057 return -1;
01058 }else{
01059 index= av_index_search_timestamp(st, pts, flags);
01060 if(index<0)
01061 return -1;
01062
01063
01064 pos = st->index_entries[index].pos;
01065 pts = st->index_entries[index].timestamp;
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089 av_log(NULL, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos);
01090 url_fseek(&s->pb, pos, SEEK_SET);
01091 }
01092 asf_reset_header(s);
01093 return 0;
01094 }
01095
01096 AVInputFormat asf_demuxer = {
01097 "asf",
01098 "asf format",
01099 sizeof(ASFContext),
01100 asf_probe,
01101 asf_read_header,
01102 asf_read_packet,
01103 asf_read_close,
01104 asf_read_seek,
01105 asf_read_pts,
01106 };