diff options
Diffstat (limited to 'libavformat/asfdec.c')
-rw-r--r-- | libavformat/asfdec.c | 93 |
1 files changed, 51 insertions, 42 deletions
diff --git a/libavformat/asfdec.c b/libavformat/asfdec.c index b39d2f2d9c..6bcfe0ac34 100644 --- a/libavformat/asfdec.c +++ b/libavformat/asfdec.c @@ -2,20 +2,20 @@ * ASF compatible demuxer * Copyright (c) 2000, 2001 Fabrice Bellard * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -97,10 +97,6 @@ static const AVClass asf_class = { #define FRAME_HEADER_SIZE 17 // Fix Me! FRAME_HEADER_SIZE may be different. -static const ff_asf_guid index_guid = { - 0x90, 0x08, 0x00, 0x33, 0xb1, 0xe5, 0xcf, 0x11, 0x89, 0xf4, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb -}; - #ifdef DEBUG static const ff_asf_guid stream_bitrate_guid = { /* (http://get.to/sdp) */ 0xce, 0x75, 0xf8, 0x7b, 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2 @@ -125,7 +121,7 @@ static void print_guid(const ff_asf_guid *g) else PRINT_IF_GUID(g, ff_asf_codec_comment_header); else PRINT_IF_GUID(g, ff_asf_codec_comment1_header); else PRINT_IF_GUID(g, ff_asf_data_header); - else PRINT_IF_GUID(g, index_guid); + else PRINT_IF_GUID(g, ff_asf_simple_index_header); else PRINT_IF_GUID(g, ff_asf_head1_guid); else PRINT_IF_GUID(g, ff_asf_head2_guid); else PRINT_IF_GUID(g, ff_asf_my_guid); @@ -148,12 +144,6 @@ static void print_guid(const ff_asf_guid *g) #define print_guid(g) #endif -void ff_get_guid(AVIOContext *s, ff_asf_guid *g) -{ - assert(sizeof(*g) == 16); - avio_read(s, *g, sizeof(*g)); -} - static int asf_probe(AVProbeData *pd) { /* check file header */ @@ -187,6 +177,9 @@ static void get_tag(AVFormatContext *s, const char *key, int type, int len) if (type == 0) { // UTF16-LE avio_get_str16le(s->pb, len, value, 2*len + 1); + } else if (type == -1) { // ASCII + avio_read(s->pb, value, len); + value[len]=0; } else if (type > 1 && type <= 5) { // boolean or DWORD or QWORD or WORD uint64_t num = get_value(s->pb, type); snprintf(value, len, "%"PRIu64, num); @@ -253,7 +246,6 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size) if (!asf_st) return AVERROR(ENOMEM); st->priv_data = asf_st; - st->start_time = 0; start_time = asf->hdr.preroll; asf_st->stream_language_index = 128; // invalid stream index means no language info @@ -312,7 +304,7 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size) if (is_dvr_ms_audio) { // codec_id and codec_tag are unreliable in dvr_ms // files. Set them later by probing stream. - st->codec->codec_id = CODEC_ID_PROBE; + st->request_probe= 1; st->codec->codec_tag = 0; } if (st->codec->codec_id == CODEC_ID_AAC) { @@ -639,16 +631,28 @@ static int asf_read_header(AVFormatContext *s) continue; } else if (!ff_guidcmp(&g, &ff_asf_marker_header)) { asf_read_marker(s, gsize); - } else if (pb->eof_reached) { + } else if (url_feof(pb)) { return -1; } else { if (!s->keylen) { if (!ff_guidcmp(&g, &ff_asf_content_encryption)) { + unsigned int len; + AVPacket pkt; av_log(s, AV_LOG_WARNING, "DRM protected stream detected, decoding will likely fail!\n"); + len= avio_rl32(pb); + av_log(s, AV_LOG_DEBUG, "Secret data:\n"); + av_get_packet(pb, &pkt, len); av_hex_dump_log(s, AV_LOG_DEBUG, pkt.data, pkt.size); av_free_packet(&pkt); + len= avio_rl32(pb); + get_tag(s, "ASF_Protection_Type", -1, len); + len= avio_rl32(pb); + get_tag(s, "ASF_Key_ID", -1, len); + len= avio_rl32(pb); + get_tag(s, "ASF_License_URL", -1, len); } else if (!ff_guidcmp(&g, &ff_asf_ext_content_encryption)) { av_log(s, AV_LOG_WARNING, "Ext DRM protected stream detected, decoding will likely fail!\n"); + av_dict_set(&s->metadata, "encryption", "ASF Extended Content Encryption", 0); } else if (!ff_guidcmp(&g, &ff_asf_digital_signature)) { - av_log(s, AV_LOG_WARNING, "Digital signature detected, decoding will likely fail!\n"); + av_log(s, AV_LOG_INFO, "Digital signature detected!\n"); } } } @@ -660,7 +664,7 @@ static int asf_read_header(AVFormatContext *s) avio_rl64(pb); avio_r8(pb); avio_r8(pb); - if (pb->eof_reached) + if (url_feof(pb)) return -1; asf->data_offset = avio_tell(pb); asf->packet_size_left = 0; @@ -747,19 +751,19 @@ static int ff_asf_get_packet(AVFormatContext *s, AVIOContext *pb) */ if (pb->error == AVERROR(EAGAIN)) return AVERROR(EAGAIN); - if (!pb->eof_reached) + if (!url_feof(pb)) av_log(s, AV_LOG_ERROR, "ff asf bad header %x at:%"PRId64"\n", c, avio_tell(pb)); } if ((c & 0x8f) == 0x82) { if (d || e) { - if (!pb->eof_reached) + if (!url_feof(pb)) av_log(s, AV_LOG_ERROR, "ff asf bad non zero\n"); return -1; } c= avio_r8(pb); d= avio_r8(pb); rsize+=3; - } else if (!pb->eof_reached) { + }else if(!url_feof(pb)){ avio_seek(pb, -1, SEEK_CUR); //FIXME } @@ -814,7 +818,7 @@ static int asf_read_frame_header(AVFormatContext *s, AVIOContext *pb){ ASFContext *asf = s->priv_data; int rsize = 1; int num = avio_r8(pb); - int64_t ts0; + int64_t ts0, ts1 av_unused; asf->packet_segments--; asf->packet_key_frame = num >> 7; @@ -824,6 +828,10 @@ static int asf_read_frame_header(AVFormatContext *s, AVIOContext *pb){ DO_2BITS(asf->packet_property >> 2, asf->packet_frag_offset, 0); DO_2BITS(asf->packet_property, asf->packet_replic_size, 0); //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); + if (rsize+asf->packet_replic_size > asf->packet_size_left) { + av_log(s, AV_LOG_ERROR, "packet_replic_size %d is invalid\n", asf->packet_replic_size); + return -1; + } if (asf->packet_replic_size >= 8) { asf->packet_obj_size = avio_rl32(pb); if(asf->packet_obj_size >= (1<<24) || asf->packet_obj_size <= 0){ @@ -837,7 +845,7 @@ static int asf_read_frame_header(AVFormatContext *s, AVIOContext *pb){ // av_log(s, AV_LOG_DEBUG, "\n"); avio_skip(pb, 10); ts0= avio_rl64(pb); - avio_skip(pb, 8);; + ts1= avio_rl64(pb); avio_skip(pb, 12); avio_rl32(pb); avio_skip(pb, asf->packet_replic_size - 8 - 38 - 4); @@ -875,10 +883,6 @@ static int asf_read_frame_header(AVFormatContext *s, AVIOContext *pb){ } //printf("Fragsize %d\n", asf->packet_frag_size); } else { - if (rsize > asf->packet_size_left) { - av_log(s, AV_LOG_ERROR, "packet_replic_size is invalid\n"); - return -1; - } asf->packet_frag_size = asf->packet_size_left - rsize; //printf("Using rest %d %d %d\n", asf->packet_frag_size, asf->packet_size_left, rsize); } @@ -908,7 +912,7 @@ static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pk ASFStream *asf_st = 0; for (;;) { int ret; - if(pb->eof_reached) + if(url_feof(pb)) return AVERROR_EOF; if (asf->packet_size_left < FRAME_HEADER_SIZE || asf->packet_segments < 1) { @@ -1174,12 +1178,13 @@ static int64_t asf_read_pts(AVFormatContext *s, int stream_index, int64_t *ppos, if (s->packet_size > 0) pos= (pos+s->packet_size-1-s->data_offset)/s->packet_size*s->packet_size+ s->data_offset; *ppos= pos; - avio_seek(s->pb, pos, SEEK_SET); + if (avio_seek(s->pb, pos, SEEK_SET) < 0) + return AV_NOPTS_VALUE; //printf("asf_read_pts\n"); asf_reset_header(s); for(;;){ - if (asf_read_packet(s, pkt) < 0){ + if (av_read_frame(s, pkt) < 0){ av_log(s, AV_LOG_INFO, "asf_read_pts failed\n"); return AV_NOPTS_VALUE; } @@ -1214,17 +1219,21 @@ static void asf_build_simple_index(AVFormatContext *s, int stream_index) ff_asf_guid g; ASFContext *asf = s->priv_data; int64_t current_pos= avio_tell(s->pb); - int i; - avio_seek(s->pb, asf->data_object_offset + asf->data_object_size, SEEK_SET); + if(avio_seek(s->pb, asf->data_object_offset + asf->data_object_size, SEEK_SET) < 0) { + asf->index_read= -1; + return; + } + ff_get_guid(s->pb, &g); /* the data object can be followed by other top-level objects, skip them until the simple index object is reached */ - while (ff_guidcmp(&g, &index_guid)) { + while (ff_guidcmp(&g, &ff_asf_simple_index_header)) { int64_t gsize= avio_rl64(s->pb); - if (gsize < 24 || s->pb->eof_reached) { + if (gsize < 24 || url_feof(s->pb)) { avio_seek(s->pb, current_pos, SEEK_SET); + asf->index_read= -1; return; } avio_skip(s->pb, gsize-24); @@ -1234,6 +1243,7 @@ static void asf_build_simple_index(AVFormatContext *s, int stream_index) { int64_t itime, last_pos=-1; int pct, ict; + int i; int64_t av_unused gsize= avio_rl64(s->pb); ff_get_guid(s->pb, &g); itime=avio_rl64(s->pb); @@ -1262,8 +1272,6 @@ static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int { ASFContext *asf = s->priv_data; AVStream *st = s->streams[stream_index]; - int64_t pos; - int index; if (s->packet_size <= 0) return -1; @@ -1280,15 +1288,16 @@ static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int if (!asf->index_read) asf_build_simple_index(s, stream_index); - if((asf->index_read && st->index_entries)){ - index= av_index_search_timestamp(st, pts, flags); + if((asf->index_read > 0 && st->index_entries)){ + int index= av_index_search_timestamp(st, pts, flags); if(index >= 0) { /* find the position */ - pos = st->index_entries[index].pos; + uint64_t pos = st->index_entries[index].pos; /* do the seek */ av_log(s, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos); - avio_seek(s->pb, pos, SEEK_SET); + if(avio_seek(s->pb, pos, SEEK_SET) < 0) + return -1; asf_reset_header(s); return 0; } |