1/* 2 * RSD demuxer 3 * Copyright (c) 2013 James Almer 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22#include "libavcodec/bytestream.h" 23#include "libavutil/intreadwrite.h" 24#include "avformat.h" 25#include "avio.h" 26#include "internal.h" 27 28static const AVCodecTag rsd_tags[] = { 29 { AV_CODEC_ID_ADPCM_THP, MKTAG('G','A','D','P') }, 30 { AV_CODEC_ID_ADPCM_IMA_RAD, MKTAG('R','A','D','P') }, 31 { AV_CODEC_ID_PCM_S16BE, MKTAG('P','C','M','B') }, 32 { AV_CODEC_ID_PCM_S16LE, MKTAG('P','C','M',' ') }, 33 { AV_CODEC_ID_NONE, 0 }, 34}; 35 36static const uint32_t rsd_unsupported_tags[] = { 37 MKTAG('O','G','G',' '), 38 MKTAG('V','A','G',' '), 39 MKTAG('W','A','D','P'), 40 MKTAG('X','A','D','P'), 41 MKTAG('X','M','A',' '), 42}; 43 44static int rsd_probe(AVProbeData *p) 45{ 46 if (memcmp(p->buf, "RSD", 3) || p->buf[3] - '0' < 2 || p->buf[3] - '0' > 6) 47 return 0; 48 if (AV_RL32(p->buf + 8) > 256 || !AV_RL32(p->buf + 8)) 49 return AVPROBE_SCORE_MAX / 8; 50 if (AV_RL32(p->buf + 16) > 8*48000 || !AV_RL32(p->buf + 16)) 51 return AVPROBE_SCORE_MAX / 8; 52 return AVPROBE_SCORE_MAX; 53} 54 55static int rsd_read_header(AVFormatContext *s) 56{ 57 AVIOContext *pb = s->pb; 58 int i, version, start = 0x800; 59 AVCodecContext *codec; 60 AVStream *st = avformat_new_stream(s, NULL); 61 62 if (!st) 63 return AVERROR(ENOMEM); 64 65 avio_skip(pb, 3); // "RSD" 66 version = avio_r8(pb) - '0'; 67 68 codec = st->codec; 69 codec->codec_type = AVMEDIA_TYPE_AUDIO; 70 codec->codec_tag = avio_rl32(pb); 71 codec->codec_id = ff_codec_get_id(rsd_tags, codec->codec_tag); 72 if (!codec->codec_id) { 73 char tag_buf[5]; 74 75 av_get_codec_tag_string(tag_buf, sizeof(tag_buf), codec->codec_tag); 76 for (i=0; i < FF_ARRAY_ELEMS(rsd_unsupported_tags); i++) { 77 if (codec->codec_tag == rsd_unsupported_tags[i]) { 78 avpriv_request_sample(s, "Codec tag: %s", tag_buf); 79 return AVERROR_PATCHWELCOME; 80 } 81 } 82 av_log(s, AV_LOG_ERROR, "Unknown codec tag: %s\n", tag_buf); 83 return AVERROR_INVALIDDATA; 84 } 85 86 codec->channels = avio_rl32(pb); 87 if (!codec->channels) 88 return AVERROR_INVALIDDATA; 89 90 avio_skip(pb, 4); // Bit depth 91 codec->sample_rate = avio_rl32(pb); 92 if (!codec->sample_rate) 93 return AVERROR_INVALIDDATA; 94 95 avio_skip(pb, 4); // Unknown 96 97 switch (codec->codec_id) { 98 case AV_CODEC_ID_ADPCM_IMA_RAD: 99 codec->block_align = 20 * codec->channels; 100 if (pb->seekable) 101 st->duration = av_get_audio_frame_duration(codec, avio_size(pb) - start); 102 break; 103 case AV_CODEC_ID_ADPCM_THP: 104 /* RSD3GADP is mono, so only alloc enough memory 105 to store the coeff table for a single channel. */ 106 107 start = avio_rl32(pb); 108 109 if (ff_get_extradata(codec, s->pb, 32) < 0) 110 return AVERROR(ENOMEM); 111 112 for (i = 0; i < 16; i++) 113 AV_WB16(codec->extradata + i * 2, AV_RL16(codec->extradata + i * 2)); 114 115 if (pb->seekable) 116 st->duration = (avio_size(pb) - start) / 8 * 14; 117 break; 118 case AV_CODEC_ID_PCM_S16LE: 119 case AV_CODEC_ID_PCM_S16BE: 120 if (version != 4) 121 start = avio_rl32(pb); 122 123 if (pb->seekable) 124 st->duration = (avio_size(pb) - start) / 2 / codec->channels; 125 break; 126 } 127 128 avio_skip(pb, start - avio_tell(pb)); 129 130 avpriv_set_pts_info(st, 64, 1, codec->sample_rate); 131 132 return 0; 133} 134 135static int rsd_read_packet(AVFormatContext *s, AVPacket *pkt) 136{ 137 AVCodecContext *codec = s->streams[0]->codec; 138 int ret, size = 1024; 139 140 if (url_feof(s->pb)) 141 return AVERROR_EOF; 142 143 if (codec->codec_id == AV_CODEC_ID_ADPCM_IMA_RAD) 144 ret = av_get_packet(s->pb, pkt, codec->block_align); 145 else 146 ret = av_get_packet(s->pb, pkt, size); 147 148 if (ret != size) { 149 if (ret < 0) { 150 av_free_packet(pkt); 151 return ret; 152 } 153 av_shrink_packet(pkt, ret); 154 } 155 pkt->stream_index = 0; 156 157 return ret; 158} 159 160AVInputFormat ff_rsd_demuxer = { 161 .name = "rsd", 162 .long_name = NULL_IF_CONFIG_SMALL("GameCube RSD"), 163 .read_probe = rsd_probe, 164 .read_header = rsd_read_header, 165 .read_packet = rsd_read_packet, 166 .extensions = "rsd", 167 .codec_tag = (const AVCodecTag* const []){rsd_tags, 0}, 168}; 169