1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Westwood Studios AUD Format Demuxer 3cabdff1aSopenharmony_ci * Copyright (c) 2003 The FFmpeg project 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci/** 23cabdff1aSopenharmony_ci * @file 24cabdff1aSopenharmony_ci * Westwood Studios AUD file demuxer 25cabdff1aSopenharmony_ci * by Mike Melanson (melanson@pcisys.net) 26cabdff1aSopenharmony_ci * for more information on the Westwood file formats, visit: 27cabdff1aSopenharmony_ci * http://www.pcisys.net/~melanson/codecs/ 28cabdff1aSopenharmony_ci * http://www.geocities.com/SiliconValley/8682/aud3.txt 29cabdff1aSopenharmony_ci * 30cabdff1aSopenharmony_ci * Implementation note: There is no definite file signature for AUD files. 31cabdff1aSopenharmony_ci * The demuxer uses a probabilistic strategy for content detection. This 32cabdff1aSopenharmony_ci * entails performing sanity checks on certain header values in order to 33cabdff1aSopenharmony_ci * qualify a file. Refer to wsaud_probe() for the precise parameters. 34cabdff1aSopenharmony_ci */ 35cabdff1aSopenharmony_ci 36cabdff1aSopenharmony_ci#include "libavutil/channel_layout.h" 37cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 38cabdff1aSopenharmony_ci#include "avformat.h" 39cabdff1aSopenharmony_ci#include "internal.h" 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_ci#define AUD_HEADER_SIZE 12 42cabdff1aSopenharmony_ci#define AUD_CHUNK_PREAMBLE_SIZE 8 43cabdff1aSopenharmony_ci#define AUD_CHUNK_SIGNATURE 0x0000DEAF 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_cistatic int wsaud_probe(const AVProbeData *p) 46cabdff1aSopenharmony_ci{ 47cabdff1aSopenharmony_ci int field; 48cabdff1aSopenharmony_ci 49cabdff1aSopenharmony_ci /* Probabilistic content detection strategy: There is no file signature 50cabdff1aSopenharmony_ci * so perform sanity checks on various header parameters: 51cabdff1aSopenharmony_ci * 8000 <= sample rate (16 bits) <= 48000 ==> 40001 acceptable numbers 52cabdff1aSopenharmony_ci * flags <= 0x03 (2 LSBs are used) ==> 4 acceptable numbers 53cabdff1aSopenharmony_ci * compression type (8 bits) = 1 or 99 ==> 2 acceptable numbers 54cabdff1aSopenharmony_ci * first audio chunk signature (32 bits) ==> 1 acceptable number 55cabdff1aSopenharmony_ci * The number space contains 2^64 numbers. There are 40001 * 4 * 2 * 1 = 56cabdff1aSopenharmony_ci * 320008 acceptable number combinations. 57cabdff1aSopenharmony_ci */ 58cabdff1aSopenharmony_ci 59cabdff1aSopenharmony_ci if (p->buf_size < AUD_HEADER_SIZE + AUD_CHUNK_PREAMBLE_SIZE) 60cabdff1aSopenharmony_ci return 0; 61cabdff1aSopenharmony_ci 62cabdff1aSopenharmony_ci /* check sample rate */ 63cabdff1aSopenharmony_ci field = AV_RL16(&p->buf[0]); 64cabdff1aSopenharmony_ci if ((field < 8000) || (field > 48000)) 65cabdff1aSopenharmony_ci return 0; 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_ci /* enforce the rule that the top 6 bits of this flags field are reserved (0); 68cabdff1aSopenharmony_ci * this might not be true, but enforce it until deemed unnecessary */ 69cabdff1aSopenharmony_ci if (p->buf[10] & 0xFC) 70cabdff1aSopenharmony_ci return 0; 71cabdff1aSopenharmony_ci 72cabdff1aSopenharmony_ci if (p->buf[11] != 99 && p->buf[11] != 1) 73cabdff1aSopenharmony_ci return 0; 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_ci /* read ahead to the first audio chunk and validate the first header signature */ 76cabdff1aSopenharmony_ci if (AV_RL32(&p->buf[16]) != AUD_CHUNK_SIGNATURE) 77cabdff1aSopenharmony_ci return 0; 78cabdff1aSopenharmony_ci 79cabdff1aSopenharmony_ci /* return 1/2 certainty since this file check is a little sketchy */ 80cabdff1aSopenharmony_ci return AVPROBE_SCORE_EXTENSION; 81cabdff1aSopenharmony_ci} 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_cistatic int wsaud_read_header(AVFormatContext *s) 84cabdff1aSopenharmony_ci{ 85cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 86cabdff1aSopenharmony_ci AVStream *st; 87cabdff1aSopenharmony_ci unsigned char header[AUD_HEADER_SIZE]; 88cabdff1aSopenharmony_ci int sample_rate, channels, codec; 89cabdff1aSopenharmony_ci 90cabdff1aSopenharmony_ci if (avio_read(pb, header, AUD_HEADER_SIZE) != AUD_HEADER_SIZE) 91cabdff1aSopenharmony_ci return AVERROR(EIO); 92cabdff1aSopenharmony_ci 93cabdff1aSopenharmony_ci sample_rate = AV_RL16(&header[0]); 94cabdff1aSopenharmony_ci channels = (header[10] & 0x1) + 1; 95cabdff1aSopenharmony_ci codec = header[11]; 96cabdff1aSopenharmony_ci 97cabdff1aSopenharmony_ci /* initialize the audio decoder stream */ 98cabdff1aSopenharmony_ci st = avformat_new_stream(s, NULL); 99cabdff1aSopenharmony_ci if (!st) 100cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ci switch (codec) { 103cabdff1aSopenharmony_ci case 1: 104cabdff1aSopenharmony_ci if (channels != 1) { 105cabdff1aSopenharmony_ci avpriv_request_sample(s, "Stereo WS-SND1"); 106cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 107cabdff1aSopenharmony_ci } 108cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_WESTWOOD_SND1; 109cabdff1aSopenharmony_ci break; 110cabdff1aSopenharmony_ci case 99: 111cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_WS; 112cabdff1aSopenharmony_ci st->codecpar->bits_per_coded_sample = 4; 113cabdff1aSopenharmony_ci st->codecpar->bit_rate = channels * sample_rate * 4; 114cabdff1aSopenharmony_ci break; 115cabdff1aSopenharmony_ci default: 116cabdff1aSopenharmony_ci avpriv_request_sample(s, "Unknown codec: %d", codec); 117cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 118cabdff1aSopenharmony_ci } 119cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 64, 1, sample_rate); 120cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; 121cabdff1aSopenharmony_ci av_channel_layout_default(&st->codecpar->ch_layout, channels); 122cabdff1aSopenharmony_ci st->codecpar->sample_rate = sample_rate; 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_ci return 0; 125cabdff1aSopenharmony_ci} 126cabdff1aSopenharmony_ci 127cabdff1aSopenharmony_cistatic int wsaud_read_packet(AVFormatContext *s, 128cabdff1aSopenharmony_ci AVPacket *pkt) 129cabdff1aSopenharmony_ci{ 130cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 131cabdff1aSopenharmony_ci unsigned char preamble[AUD_CHUNK_PREAMBLE_SIZE]; 132cabdff1aSopenharmony_ci unsigned int chunk_size; 133cabdff1aSopenharmony_ci int ret = 0; 134cabdff1aSopenharmony_ci AVStream *st = s->streams[0]; 135cabdff1aSopenharmony_ci 136cabdff1aSopenharmony_ci if (avio_read(pb, preamble, AUD_CHUNK_PREAMBLE_SIZE) != 137cabdff1aSopenharmony_ci AUD_CHUNK_PREAMBLE_SIZE) 138cabdff1aSopenharmony_ci return AVERROR(EIO); 139cabdff1aSopenharmony_ci 140cabdff1aSopenharmony_ci /* validate the chunk */ 141cabdff1aSopenharmony_ci if (AV_RL32(&preamble[4]) != AUD_CHUNK_SIGNATURE) 142cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 143cabdff1aSopenharmony_ci 144cabdff1aSopenharmony_ci chunk_size = AV_RL16(&preamble[0]); 145cabdff1aSopenharmony_ci 146cabdff1aSopenharmony_ci if (st->codecpar->codec_id == AV_CODEC_ID_WESTWOOD_SND1) { 147cabdff1aSopenharmony_ci /* For Westwood SND1 audio we need to add the output size and input 148cabdff1aSopenharmony_ci size to the start of the packet to match what is in VQA. 149cabdff1aSopenharmony_ci Specifically, this is needed to signal when a packet should be 150cabdff1aSopenharmony_ci decoding as raw 8-bit pcm or variable-size ADPCM. */ 151cabdff1aSopenharmony_ci int out_size = AV_RL16(&preamble[2]); 152cabdff1aSopenharmony_ci if ((ret = av_new_packet(pkt, chunk_size + 4)) < 0) 153cabdff1aSopenharmony_ci return ret; 154cabdff1aSopenharmony_ci if ((ret = avio_read(pb, &pkt->data[4], chunk_size)) != chunk_size) 155cabdff1aSopenharmony_ci return ret < 0 ? ret : AVERROR(EIO); 156cabdff1aSopenharmony_ci AV_WL16(&pkt->data[0], out_size); 157cabdff1aSopenharmony_ci AV_WL16(&pkt->data[2], chunk_size); 158cabdff1aSopenharmony_ci 159cabdff1aSopenharmony_ci pkt->duration = out_size; 160cabdff1aSopenharmony_ci } else { 161cabdff1aSopenharmony_ci ret = av_get_packet(pb, pkt, chunk_size); 162cabdff1aSopenharmony_ci if (ret != chunk_size) 163cabdff1aSopenharmony_ci return AVERROR(EIO); 164cabdff1aSopenharmony_ci 165cabdff1aSopenharmony_ci if (st->codecpar->ch_layout.nb_channels <= 0) { 166cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "invalid number of channels %d\n", 167cabdff1aSopenharmony_ci st->codecpar->ch_layout.nb_channels); 168cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 169cabdff1aSopenharmony_ci } 170cabdff1aSopenharmony_ci 171cabdff1aSopenharmony_ci /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */ 172cabdff1aSopenharmony_ci pkt->duration = (chunk_size * 2) / st->codecpar->ch_layout.nb_channels; 173cabdff1aSopenharmony_ci } 174cabdff1aSopenharmony_ci pkt->stream_index = st->index; 175cabdff1aSopenharmony_ci 176cabdff1aSopenharmony_ci return ret; 177cabdff1aSopenharmony_ci} 178cabdff1aSopenharmony_ci 179cabdff1aSopenharmony_ciconst AVInputFormat ff_wsaud_demuxer = { 180cabdff1aSopenharmony_ci .name = "wsaud", 181cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("Westwood Studios audio"), 182cabdff1aSopenharmony_ci .read_probe = wsaud_probe, 183cabdff1aSopenharmony_ci .read_header = wsaud_read_header, 184cabdff1aSopenharmony_ci .read_packet = wsaud_read_packet, 185cabdff1aSopenharmony_ci}; 186