diff options
Diffstat (limited to 'libavformat/takdec.c')
-rw-r--r-- | libavformat/takdec.c | 62 |
1 files changed, 44 insertions, 18 deletions
diff --git a/libavformat/takdec.c b/libavformat/takdec.c index 4b3037d..1535bec 100644 --- a/libavformat/takdec.c +++ b/libavformat/takdec.c @@ -2,29 +2,31 @@ * Raw TAK demuxer * Copyright (c) 2012 Paul B Mahol * - * 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 */ +#include "libavutil/crc.h" + #define BITSTREAM_READER_LE -#include "libavcodec/bitstream.h" #include "libavcodec/tak.h" #include "apetag.h" #include "avformat.h" +#include "avio_internal.h" #include "internal.h" #include "rawdec.h" @@ -40,11 +42,17 @@ static int tak_probe(AVProbeData *p) return 0; } +static unsigned long tak_check_crc(unsigned long checksum, const uint8_t *buf, + unsigned int len) +{ + return av_crc(av_crc_get_table(AV_CRC_24_IEEE), checksum, buf, len); +} + static int tak_read_header(AVFormatContext *s) { TAKDemuxContext *tc = s->priv_data; AVIOContext *pb = s->pb; - BitstreamContext bc; + GetBitContext gb; AVStream *st; uint8_t *buffer = NULL; int ret; @@ -55,7 +63,7 @@ static int tak_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_TAK; - st->need_parsing = AVSTREAM_PARSE_FULL; + st->need_parsing = AVSTREAM_PARSE_FULL_RAW; tc->mlast_frame = 0; if (avio_rl32(pb) != MKTAG('t', 'B', 'a', 'K')) { @@ -63,7 +71,7 @@ static int tak_read_header(AVFormatContext *s) return 0; } - while (!pb->eof_reached) { + while (!avio_feof(pb)) { enum TAKMetaDataType type; int size; @@ -74,16 +82,28 @@ static int tak_read_header(AVFormatContext *s) case TAK_METADATA_STREAMINFO: case TAK_METADATA_LAST_FRAME: case TAK_METADATA_ENCODER: - buffer = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (size <= 3) + return AVERROR_INVALIDDATA; + + buffer = av_malloc(size - 3 + AV_INPUT_BUFFER_PADDING_SIZE); if (!buffer) return AVERROR(ENOMEM); + memset(buffer + size - 3, 0, AV_INPUT_BUFFER_PADDING_SIZE); - if (avio_read(pb, buffer, size) != size) { + ffio_init_checksum(pb, tak_check_crc, 0xCE04B7U); + if (avio_read(pb, buffer, size - 3) != size - 3) { av_freep(&buffer); return AVERROR(EIO); } + if (ffio_get_checksum(s->pb) != avio_rb24(pb)) { + av_log(s, AV_LOG_ERROR, "%d metadata block CRC error.\n", type); + if (s->error_recognition & AV_EF_EXPLODE) { + av_freep(&buffer); + return AVERROR_INVALIDDATA; + } + } - bitstream_init8(&bc, buffer, size); + init_get_bits8(&gb, buffer, size - 3); break; case TAK_METADATA_MD5: { uint8_t md5[16]; @@ -91,8 +111,14 @@ static int tak_read_header(AVFormatContext *s) if (size != 19) return AVERROR_INVALIDDATA; + ffio_init_checksum(pb, tak_check_crc, 0xCE04B7U); avio_read(pb, md5, 16); - avio_skip(pb, 3); + if (ffio_get_checksum(s->pb) != avio_rb24(pb)) { + av_log(s, AV_LOG_ERROR, "MD5 metadata block CRC error.\n"); + if (s->error_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + } + av_log(s, AV_LOG_VERBOSE, "MD5="); for (i = 0; i < 16; i++) av_log(s, AV_LOG_VERBOSE, "%02x", md5[i]); @@ -119,7 +145,7 @@ static int tak_read_header(AVFormatContext *s) if (type == TAK_METADATA_STREAMINFO) { TAKStreamInfo ti; - avpriv_tak_parse_streaminfo(&bc, &ti); + avpriv_tak_parse_streaminfo(&gb, &ti); if (ti.samples > 0) st->duration = ti.samples; st->codecpar->bits_per_coded_sample = ti.bps; @@ -130,18 +156,18 @@ static int tak_read_header(AVFormatContext *s) st->start_time = 0; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); st->codecpar->extradata = buffer; - st->codecpar->extradata_size = size; + st->codecpar->extradata_size = size - 3; buffer = NULL; } else if (type == TAK_METADATA_LAST_FRAME) { if (size != 11) return AVERROR_INVALIDDATA; tc->mlast_frame = 1; - tc->data_end = bitstream_read_63(&bc, TAK_LAST_FRAME_POS_BITS) + - bitstream_read(&bc, TAK_LAST_FRAME_SIZE_BITS); + tc->data_end = get_bits64(&gb, TAK_LAST_FRAME_POS_BITS) + + get_bits(&gb, TAK_LAST_FRAME_SIZE_BITS); av_freep(&buffer); } else if (type == TAK_METADATA_ENCODER) { av_log(s, AV_LOG_VERBOSE, "encoder version: %0X\n", - bitstream_read(&bc, TAK_ENCODER_VERSION_BITS)); + get_bits_long(&gb, TAK_ENCODER_VERSION_BITS)); av_freep(&buffer); } } @@ -158,7 +184,7 @@ static int raw_read_packet(AVFormatContext *s, AVPacket *pkt) AVIOContext *pb = s->pb; int64_t size, left; - left = tc->data_end - avio_tell(s->pb); + left = tc->data_end - avio_tell(pb); size = FFMIN(left, 1024); if (size <= 0) return AVERROR_EOF; |