Mercurial > audlegacy-plugins
comparison src/wma/libffwma/asf.c @ 3123:a2093254960a
Sanity check to work around a WMA decoding error.
author | John Lindgren <john.lindgren@tds.net> |
---|---|
date | Wed, 06 May 2009 12:11:06 -0400 |
parents | 55703f60fd54 |
children |
comparison
equal
deleted
inserted
replaced
3122:5744479b31f4 | 3123:a2093254960a |
---|---|
39 int ds_span; /* descrambling */ | 39 int ds_span; /* descrambling */ |
40 int ds_packet_size; | 40 int ds_packet_size; |
41 int ds_chunk_size; | 41 int ds_chunk_size; |
42 int ds_data_size; | 42 int ds_data_size; |
43 int ds_silence_data; | 43 int ds_silence_data; |
44 | 44 |
45 int packet_pos; | 45 int packet_pos; |
46 | 46 |
47 } ASFStream; | 47 } ASFStream; |
48 | 48 |
49 typedef struct { | 49 typedef struct { |
187 const CodecTag codec_wav_tags[] = { | 187 const CodecTag codec_wav_tags[] = { |
188 /* { CODEC_ID_MP2, 0x50 }, | 188 /* { CODEC_ID_MP2, 0x50 }, |
189 { CODEC_ID_MP3, 0x55 }, | 189 { CODEC_ID_MP3, 0x55 }, |
190 { CODEC_ID_AC3, 0x2000 }, | 190 { CODEC_ID_AC3, 0x2000 }, |
191 { CODEC_ID_PCM_S16LE, 0x01 }, | 191 { CODEC_ID_PCM_S16LE, 0x01 }, |
192 { CODEC_ID_PCM_U8, 0x01 }, | 192 { CODEC_ID_PCM_U8, 0x01 }, |
193 { CODEC_ID_PCM_ALAW, 0x06 }, | 193 { CODEC_ID_PCM_ALAW, 0x06 }, |
194 { CODEC_ID_PCM_MULAW, 0x07 }, | 194 { CODEC_ID_PCM_MULAW, 0x07 }, |
195 { CODEC_ID_ADPCM_MS, 0x02 }, | 195 { CODEC_ID_ADPCM_MS, 0x02 }, |
196 { CODEC_ID_ADPCM_IMA_WAV, 0x11 }, | 196 { CODEC_ID_ADPCM_IMA_WAV, 0x11 }, |
197 { CODEC_ID_ADPCM_IMA_DK4, 0x61 }, | 197 { CODEC_ID_ADPCM_IMA_DK4, 0x61 }, |
198 { CODEC_ID_ADPCM_IMA_DK3, 0x62 },*/ | 198 { CODEC_ID_ADPCM_IMA_DK3, 0x62 },*/ |
199 { CODEC_ID_WMAV1, 0x160, 0 }, | 199 { CODEC_ID_WMAV1, 0x160, 0 }, |
200 { CODEC_ID_WMAV2, 0x161, 0 }, | 200 { CODEC_ID_WMAV2, 0x161, 0 }, |
201 { 0, 0, 0 }, | 201 { 0, 0, 0 }, |
202 }; | 202 }; |
358 AVStream *st; | 358 AVStream *st; |
359 ASFStream *asf_st; | 359 ASFStream *asf_st; |
360 //int size, i; | 360 //int size, i; |
361 int i; | 361 int i; |
362 int64_t gsize; | 362 int64_t gsize; |
363 uint64_t block_begin; | |
363 | 364 |
364 av_set_pts_info(s, 32, 1, 1000); /* 32 bit pts in ms */ | 365 av_set_pts_info(s, 32, 1, 1000); /* 32 bit pts in ms */ |
365 | 366 |
366 get_guid(pb, &g); | 367 get_guid(pb, &g); |
367 if (memcmp(&g, &asf_header, sizeof(GUID))) | 368 if (memcmp(&g, &asf_header, sizeof(GUID))) |
368 goto fail; | 369 goto fail; |
369 get_le64(pb); | 370 get_le64(pb); |
370 get_le32(pb); | 371 get_le32(pb); |
371 get_byte(pb); | 372 get_byte(pb); |
372 get_byte(pb); | 373 get_byte(pb); |
374 | |
375 block_begin = 30; | |
376 | |
373 memset(&asf->asfid2avid, -1, sizeof(asf->asfid2avid)); | 377 memset(&asf->asfid2avid, -1, sizeof(asf->asfid2avid)); |
374 for(;;) { | 378 for(;;) { |
379 if (url_ftell (pb) != block_begin) /* sanity check */ | |
380 { | |
381 printf ("ASF: error reading header; trying to recover...\n"); | |
382 url_fseek (pb, block_begin, SEEK_SET); | |
383 } | |
384 | |
375 get_guid(pb, &g); | 385 get_guid(pb, &g); |
376 gsize = get_le64(pb); | 386 gsize = get_le64(pb); |
377 #ifdef DEBUG | 387 #ifdef DEBUG |
378 printf("%08Lx: ", url_ftell(pb) - 24); | 388 printf("%08Lx: ", url_ftell(pb) - 24); |
379 print_guid(&g); | 389 print_guid(&g); |
380 printf(" size=0x%Lx\n", gsize); | 390 printf(" size=0x%Lx\n", gsize); |
381 #endif | 391 #endif |
382 if (gsize < 24) | 392 if (gsize < 24) |
383 goto fail; | 393 goto fail; |
394 | |
395 block_begin += gsize; | |
396 | |
384 if (!memcmp(&g, &file_header, sizeof(GUID))) { | 397 if (!memcmp(&g, &file_header, sizeof(GUID))) { |
385 get_guid(pb, &asf->hdr.guid); | 398 get_guid(pb, &asf->hdr.guid); |
386 asf->hdr.file_size = get_le64(pb); | 399 asf->hdr.file_size = get_le64(pb); |
387 asf->hdr.create_time = get_le64(pb); | 400 asf->hdr.create_time = get_le64(pb); |
388 asf->hdr.packets_count = get_le64(pb); | 401 asf->hdr.packets_count = get_le64(pb); |
409 asf_st = av_mallocz(sizeof(ASFStream)); | 422 asf_st = av_mallocz(sizeof(ASFStream)); |
410 if (!asf_st) | 423 if (!asf_st) |
411 goto fail; | 424 goto fail; |
412 st->priv_data = asf_st; | 425 st->priv_data = asf_st; |
413 st->start_time = asf->hdr.preroll / (10000000 / AV_TIME_BASE); | 426 st->start_time = asf->hdr.preroll / (10000000 / AV_TIME_BASE); |
414 st->duration = (asf->hdr.send_time - asf->hdr.preroll) / | 427 st->duration = (asf->hdr.send_time - asf->hdr.preroll) / |
415 (10000000 / AV_TIME_BASE); | 428 (10000000 / AV_TIME_BASE); |
416 get_guid(pb, &g); | 429 get_guid(pb, &g); |
417 if (!memcmp(&g, &audio_stream, sizeof(GUID))) { | 430 if (!memcmp(&g, &audio_stream, sizeof(GUID))) { |
418 type = CODEC_TYPE_AUDIO; | 431 type = CODEC_TYPE_AUDIO; |
419 } else { | 432 } else { |
428 asf->asfid2avid[st->id] = s->nb_streams - 1; | 441 asf->asfid2avid[st->id] = s->nb_streams - 1; |
429 | 442 |
430 get_le32(pb); | 443 get_le32(pb); |
431 st->codec.codec_type = type; | 444 st->codec.codec_type = type; |
432 /* 1 fps default (XXX: put 0 fps instead) */ | 445 /* 1 fps default (XXX: put 0 fps instead) */ |
433 st->codec.frame_rate = 1; | 446 st->codec.frame_rate = 1; |
434 st->codec.frame_rate_base = 1; | 447 st->codec.frame_rate_base = 1; |
435 if (type == CODEC_TYPE_AUDIO) { | 448 if (type == CODEC_TYPE_AUDIO) { |
436 get_wav_header(pb, &st->codec, type_specific_size); | 449 get_wav_header(pb, &st->codec, type_specific_size); |
437 st->need_parsing = 1; | 450 st->need_parsing = 1; |
438 /* We have to init the frame size at some point .... */ | 451 /* We have to init the frame size at some point .... */ |
563 ASFContext *asf = s->priv_data; | 576 ASFContext *asf = s->priv_data; |
564 ByteIOContext *pb = &s->pb; | 577 ByteIOContext *pb = &s->pb; |
565 uint32_t packet_length, padsize; | 578 uint32_t packet_length, padsize; |
566 int rsize = 9; | 579 int rsize = 9; |
567 int c; | 580 int c; |
568 | 581 |
569 assert((url_ftell(&s->pb) - s->data_offset) % asf->packet_size == 0); | 582 assert((url_ftell(&s->pb) - s->data_offset) % asf->packet_size == 0); |
570 | 583 |
571 c = get_byte(pb); | 584 c = get_byte(pb); |
572 if ((c & 0x0f) == 2) { // always true for now | 585 if ((c & 0x0f) == 2) { // always true for now |
573 if (get_le16(pb) != 0) { | 586 if (get_le16(pb) != 0) { |
574 if (!url_feof(pb)) | 587 if (!url_feof(pb)) |
575 printf("ff asf bad non zero\n"); | 588 printf("ff asf bad non zero\n"); |
736 /* new packet */ | 749 /* new packet */ |
737 av_new_packet(&asf_st->pkt, asf->packet_obj_size); | 750 av_new_packet(&asf_st->pkt, asf->packet_obj_size); |
738 asf_st->seq = asf->packet_seq; | 751 asf_st->seq = asf->packet_seq; |
739 asf_st->pkt.pts = asf->packet_frag_timestamp - asf->hdr.preroll; | 752 asf_st->pkt.pts = asf->packet_frag_timestamp - asf->hdr.preroll; |
740 asf_st->pkt.stream_index = asf->stream_index; | 753 asf_st->pkt.stream_index = asf->stream_index; |
741 asf_st->packet_pos= asf->packet_pos; | 754 asf_st->packet_pos= asf->packet_pos; |
742 //printf("new packet: stream:%d key:%d packet_key:%d audio:%d size:%d\n", | 755 //printf("new packet: stream:%d key:%d packet_key:%d audio:%d size:%d\n", |
743 //asf->stream_index, asf->packet_key_frame, asf_st->pkt.flags & PKT_FLAG_KEY, | 756 //asf->stream_index, asf->packet_key_frame, asf_st->pkt.flags & PKT_FLAG_KEY, |
744 //s->streams[asf->stream_index]->codec.codec_type == CODEC_TYPE_AUDIO, asf->packet_obj_size); | 757 //s->streams[asf->stream_index]->codec.codec_type == CODEC_TYPE_AUDIO, asf->packet_obj_size); |
745 if (s->streams[asf->stream_index]->codec.codec_type == CODEC_TYPE_AUDIO) | 758 if (s->streams[asf->stream_index]->codec.codec_type == CODEC_TYPE_AUDIO) |
746 asf->packet_key_frame = 1; | 759 asf->packet_key_frame = 1; |
747 if (asf->packet_key_frame) | 760 if (asf->packet_key_frame) |
748 asf_st->pkt.flags |= PKT_FLAG_KEY; | 761 asf_st->pkt.flags |= PKT_FLAG_KEY; |
749 } | 762 } |
750 | 763 |
833 asf->packet_frag_timestamp = 0; | 846 asf->packet_frag_timestamp = 0; |
834 asf->packet_multi_size = 0; | 847 asf->packet_multi_size = 0; |
835 asf->packet_obj_size = 0; | 848 asf->packet_obj_size = 0; |
836 asf->packet_time_delta = 0; | 849 asf->packet_time_delta = 0; |
837 asf->packet_time_start = 0; | 850 asf->packet_time_start = 0; |
838 | 851 |
839 for(i=0; i<s->nb_streams; i++){ | 852 for(i=0; i<s->nb_streams; i++){ |
840 asf_st= s->streams[i]->priv_data; | 853 asf_st= s->streams[i]->priv_data; |
841 av_free_packet(&asf_st->pkt); | 854 av_free_packet(&asf_st->pkt); |
842 asf_st->frag_offset=0; | 855 asf_st->frag_offset=0; |
843 asf_st->seq=0; | 856 asf_st->seq=0; |
852 ASFStream *asf_st; | 865 ASFStream *asf_st; |
853 int64_t pts; | 866 int64_t pts; |
854 int64_t pos= *ppos; | 867 int64_t pos= *ppos; |
855 int i; | 868 int i; |
856 int64_t start_pos[s->nb_streams]; | 869 int64_t start_pos[s->nb_streams]; |
857 | 870 |
858 for(i=0; i<s->nb_streams; i++){ | 871 for(i=0; i<s->nb_streams; i++){ |
859 start_pos[i]= pos; | 872 start_pos[i]= pos; |
860 } | 873 } |
861 | 874 |
862 //printf("asf_read_pts\n"); | 875 //printf("asf_read_pts\n"); |
878 assert((asf_st->packet_pos - s->data_offset) % asf->packet_size == 0); | 891 assert((asf_st->packet_pos - s->data_offset) % asf->packet_size == 0); |
879 pos= (asf_st->packet_pos - s->data_offset) / asf->packet_size; | 892 pos= (asf_st->packet_pos - s->data_offset) / asf->packet_size; |
880 | 893 |
881 av_add_index_entry(s->streams[i], pos, pts, pos - start_pos[i] + 1, AVINDEX_KEYFRAME); | 894 av_add_index_entry(s->streams[i], pos, pts, pos - start_pos[i] + 1, AVINDEX_KEYFRAME); |
882 start_pos[i]= pos + 1; | 895 start_pos[i]= pos + 1; |
883 | 896 |
884 if(pkt->stream_index == stream_index) | 897 if(pkt->stream_index == stream_index) |
885 break; | 898 break; |
886 } | 899 } |
887 } | 900 } |
888 | 901 |
897 ASFContext *asf = s->priv_data; | 910 ASFContext *asf = s->priv_data; |
898 AVStream *st; | 911 AVStream *st; |
899 int64_t pos; | 912 int64_t pos; |
900 int64_t pos_min, pos_max, pts_min, pts_max, cur_pts, pos_limit; | 913 int64_t pos_min, pos_max, pts_min, pts_max, cur_pts, pos_limit; |
901 int no_change; | 914 int no_change; |
902 | 915 |
903 if (stream_index == -1) | 916 if (stream_index == -1) |
904 stream_index= av_find_default_stream_index(s); | 917 stream_index= av_find_default_stream_index(s); |
905 | 918 |
906 if (asf->packet_size <= 0) | 919 if (asf->packet_size <= 0) |
907 return -1; | 920 return -1; |
908 | 921 |
909 pts_max= | 922 pts_max= |
910 pts_min= AV_NOPTS_VALUE; | 923 pts_min= AV_NOPTS_VALUE; |
940 } | 953 } |
941 if(pts_max == (int64_t)AV_NOPTS_VALUE){ | 954 if(pts_max == (int64_t)AV_NOPTS_VALUE){ |
942 pos_max = (url_filesize(url_fileno(&s->pb)) - 1 - s->data_offset) / asf->packet_size; //FIXME wrong | 955 pos_max = (url_filesize(url_fileno(&s->pb)) - 1 - s->data_offset) / asf->packet_size; //FIXME wrong |
943 pts_max = s->duration; //FIXME wrong | 956 pts_max = s->duration; //FIXME wrong |
944 pos_limit= pos_max; | 957 pos_limit= pos_max; |
945 } | 958 } |
946 | 959 |
947 no_change=0; | 960 no_change=0; |
948 while (pos_min < pos_limit) { | 961 while (pos_min < pos_limit) { |
949 int64_t start_pos; | 962 int64_t start_pos; |
950 assert(pos_limit <= pos_max); | 963 assert(pos_limit <= pos_max); |
966 pos= pos_min + 1; | 979 pos= pos_min + 1; |
967 else if(pos > pos_limit) | 980 else if(pos > pos_limit) |
968 pos= pos_limit; | 981 pos= pos_limit; |
969 start_pos= pos; | 982 start_pos= pos; |
970 | 983 |
971 // read the next timestamp | 984 // read the next timestamp |
972 cur_pts = asf_read_pts(s, &pos, stream_index); | 985 cur_pts = asf_read_pts(s, &pos, stream_index); |
973 if(pos == pos_max) | 986 if(pos == pos_max) |
974 no_change++; | 987 no_change++; |
975 else | 988 else |
976 no_change=0; | 989 no_change=0; |
977 | 990 |
1007 }; | 1020 }; |
1008 | 1021 |
1009 int asf_init(void) | 1022 int asf_init(void) |
1010 { | 1023 { |
1011 av_register_input_format(&asf_iformat); | 1024 av_register_input_format(&asf_iformat); |
1012 | 1025 |
1013 return 0; | 1026 return 0; |
1014 } | 1027 } |