X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Frsd.c;h=98e793e9ef5e2a5aafb5aad7bc4a324b326808f1;hb=12e95d156ae95e7db7f5a524112569b29cbdf0be;hp=1eff5de7e657b4ce328afe8c838969d71fff6339;hpb=0cd8170dd2b5aa274707aace60a9807ffcff3825;p=ffmpeg diff --git a/libavformat/rsd.c b/libavformat/rsd.c index 1eff5de7e65..98e793e9ef5 100644 --- a/libavformat/rsd.c +++ b/libavformat/rsd.c @@ -26,8 +26,11 @@ #include "internal.h" static const AVCodecTag rsd_tags[] = { + { AV_CODEC_ID_ADPCM_PSX, MKTAG('V','A','G',' ') }, { 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') }, { AV_CODEC_ID_PCM_S16LE, MKTAG('P','C','M',' ') }, { AV_CODEC_ID_NONE, 0 }, @@ -35,9 +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','A','D','P'), MKTAG('X','M','A',' '), }; @@ -55,7 +55,7 @@ static int rsd_probe(AVProbeData *p) static int rsd_read_header(AVFormatContext *s) { AVIOContext *pb = s->pb; - int i, version, start = 0x800; + int i, ret, version, start = 0x800; AVCodecContext *codec; AVStream *st = avformat_new_stream(s, NULL); @@ -95,25 +95,52 @@ static int rsd_read_header(AVFormatContext *s) avio_skip(pb, 4); // Unknown switch (codec->codec_id) { + case AV_CODEC_ID_ADPCM_PSX: + codec->block_align = 16 * codec->channels; + if (pb->seekable) + st->duration = av_get_audio_frame_duration(codec, avio_size(pb) - start); + break; case AV_CODEC_ID_ADPCM_IMA_RAD: codec->block_align = 20 * codec->channels; if (pb->seekable) st->duration = av_get_audio_frame_duration(codec, avio_size(pb) - start); break; + case AV_CODEC_ID_ADPCM_IMA_WAV: + if (version == 2) + start = avio_rl32(pb); + + codec->bits_per_coded_sample = 4; + codec->block_align = 36 * codec->channels; + if (pb->seekable) + 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); + if ((ret = ff_get_extradata(codec, s->pb, 32)) < 0) + return ret; - for (i = 0; i < 16; i++) - AV_WB16(codec->extradata + i * 2, AV_RL16(codec->extradata + i * 2)); + for (i = 0; i < 16; i++) + AV_WB16(codec->extradata + i * 2, AV_RL16(codec->extradata + i * 2)); + } else { + codec->block_align = 8 * codec->channels; + avio_skip(s->pb, 0x1A4 - avio_tell(s->pb)); + + if ((ret = ff_alloc_extradata(st->codec, 32 * st->codec->channels)) < 0) + return ret; + + 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: @@ -140,18 +167,28 @@ static int rsd_read_packet(AVFormatContext *s, AVPacket *pkt) if (avio_feof(s->pb)) return AVERROR_EOF; - if (codec->codec_id == AV_CODEC_ID_ADPCM_IMA_RAD) + if (codec->codec_id == AV_CODEC_ID_ADPCM_IMA_RAD || + codec->codec_id == AV_CODEC_ID_ADPCM_PSX || + 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); + } else if (codec->codec_tag == MKTAG('W','A','D','P') && + codec->channels > 1) { + int i, ch; - if (ret != size) { - if (ret < 0) { - av_free_packet(pkt); + ret = av_new_packet(pkt, codec->block_align); + if (ret < 0) return ret; + 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;