From 3a63890154179a0fc608152b9be9f4d72b6a96ad Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 16 Oct 2015 00:09:02 +0200 Subject: avformat/rsd: add WADP support Signed-off-by: Paul B Mahol --- libavformat/rsd.c | 55 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 18 deletions(-) (limited to 'libavformat') diff --git a/libavformat/rsd.c b/libavformat/rsd.c index 115dee7f61..6c43b1464a 100644 --- a/libavformat/rsd.c +++ b/libavformat/rsd.c @@ -27,6 +27,7 @@ static const AVCodecTag rsd_tags[] = { { AV_CODEC_ID_ADPCM_THP, MKTAG('G','A','D','P') }, + { AV_CODEC_ID_ADPCM_THP, MKTAG('W','A','D','P') }, { AV_CODEC_ID_ADPCM_IMA_RAD, MKTAG('R','A','D','P') }, { AV_CODEC_ID_ADPCM_IMA_WAV, MKTAG('X','A','D','P') }, { AV_CODEC_ID_PCM_S16BE, MKTAG('P','C','M','B') }, @@ -37,7 +38,6 @@ static const AVCodecTag rsd_tags[] = { static const uint32_t rsd_unsupported_tags[] = { MKTAG('O','G','G',' '), MKTAG('V','A','G',' '), - MKTAG('W','A','D','P'), MKTAG('X','M','A',' '), }; @@ -110,19 +110,32 @@ static int rsd_read_header(AVFormatContext *s) st->duration = av_get_audio_frame_duration(codec, avio_size(pb) - start); break; case AV_CODEC_ID_ADPCM_THP: - /* RSD3GADP is mono, so only alloc enough memory - to store the coeff table for a single channel. */ + if (st->codec->codec_tag == MKTAG('G','A','D','P')) { + /* RSD3GADP is mono, so only alloc enough memory + to store the coeff table for a single channel. */ - start = avio_rl32(pb); + start = avio_rl32(pb); + + if (ff_get_extradata(codec, s->pb, 32) < 0) + return AVERROR(ENOMEM); + + for (i = 0; i < 16; i++) + AV_WB16(codec->extradata + i * 2, AV_RL16(codec->extradata + i * 2)); - if (ff_get_extradata(codec, s->pb, 32) < 0) - return AVERROR(ENOMEM); + } else { + codec->block_align = 8 * codec->channels; + avio_skip(s->pb, 0x1A4 - avio_tell(s->pb)); - for (i = 0; i < 16; i++) - AV_WB16(codec->extradata + i * 2, AV_RL16(codec->extradata + i * 2)); + if (ff_alloc_extradata(st->codec, 32 * st->codec->channels) < 0) + return AVERROR(ENOMEM); + for (i = 0; i < st->codec->channels; i++) { + avio_read(s->pb, st->codec->extradata + 32 * i, 32); + avio_skip(s->pb, 8); + } + } if (pb->seekable) - st->duration = (avio_size(pb) - start) / 8 * 14; + st->duration = (avio_size(pb) - start) / (8 * st->codec->channels) * 14; break; case AV_CODEC_ID_PCM_S16LE: case AV_CODEC_ID_PCM_S16BE: @@ -150,18 +163,24 @@ static int rsd_read_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR_EOF; if (codec->codec_id == AV_CODEC_ID_ADPCM_IMA_RAD || - codec->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) + codec->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) { ret = av_get_packet(s->pb, pkt, codec->block_align); - else - ret = av_get_packet(s->pb, pkt, size); - - if (ret != size) { - if (ret < 0) { - av_free_packet(pkt); - return ret; + } else if (codec->codec_tag == MKTAG('W','A','D','P') && + codec->channels > 1) { + int i, ch; + + av_new_packet(pkt, codec->block_align); + for (i = 0; i < 4; i++) { + for (ch = 0; ch < codec->channels; ch++) { + pkt->data[ch * 8 + i * 2 + 0] = avio_r8(s->pb); + pkt->data[ch * 8 + i * 2 + 1] = avio_r8(s->pb); + } } - av_shrink_packet(pkt, ret); + ret = 0; + } else { + ret = av_get_packet(s->pb, pkt, size); } + pkt->stream_index = 0; return ret; -- cgit v1.2.3