00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00036 #include "libavutil/channel_layout.h"
00037 #include "libavutil/intreadwrite.h"
00038 #include "avformat.h"
00039 #include "internal.h"
00040
00041 #define AUD_HEADER_SIZE 12
00042 #define AUD_CHUNK_PREAMBLE_SIZE 8
00043 #define AUD_CHUNK_SIGNATURE 0x0000DEAF
00044
00045 static int wsaud_probe(AVProbeData *p)
00046 {
00047 int field;
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 if (p->buf_size < AUD_HEADER_SIZE + AUD_CHUNK_PREAMBLE_SIZE)
00060 return 0;
00061
00062
00063 field = AV_RL16(&p->buf[0]);
00064 if ((field < 8000) || (field > 48000))
00065 return 0;
00066
00067
00068
00069 if (p->buf[10] & 0xFC)
00070 return 0;
00071
00072 if (p->buf[11] != 99 && p->buf[11] != 1)
00073 return 0;
00074
00075
00076 if (AV_RL32(&p->buf[16]) != AUD_CHUNK_SIGNATURE)
00077 return 0;
00078
00079
00080 return AVPROBE_SCORE_MAX / 2;
00081 }
00082
00083 static int wsaud_read_header(AVFormatContext *s)
00084 {
00085 AVIOContext *pb = s->pb;
00086 AVStream *st;
00087 unsigned char header[AUD_HEADER_SIZE];
00088 int sample_rate, channels, codec;
00089
00090 if (avio_read(pb, header, AUD_HEADER_SIZE) != AUD_HEADER_SIZE)
00091 return AVERROR(EIO);
00092
00093 sample_rate = AV_RL16(&header[0]);
00094 channels = (header[10] & 0x1) + 1;
00095 codec = header[11];
00096
00097
00098 st = avformat_new_stream(s, NULL);
00099 if (!st)
00100 return AVERROR(ENOMEM);
00101
00102 switch (codec) {
00103 case 1:
00104 if (channels != 1) {
00105 av_log_ask_for_sample(s, "Stereo WS-SND1 is not supported.\n");
00106 return AVERROR_PATCHWELCOME;
00107 }
00108 st->codec->codec_id = AV_CODEC_ID_WESTWOOD_SND1;
00109 break;
00110 case 99:
00111 st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_WS;
00112 st->codec->bits_per_coded_sample = 4;
00113 st->codec->bit_rate = channels * sample_rate * 4;
00114 break;
00115 default:
00116 av_log_ask_for_sample(s, "Unknown codec: %d\n", codec);
00117 return AVERROR_PATCHWELCOME;
00118 }
00119 avpriv_set_pts_info(st, 64, 1, sample_rate);
00120 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00121 st->codec->channels = channels;
00122 st->codec->channel_layout = channels == 1 ? AV_CH_LAYOUT_MONO :
00123 AV_CH_LAYOUT_STEREO;
00124 st->codec->sample_rate = sample_rate;
00125
00126 return 0;
00127 }
00128
00129 static int wsaud_read_packet(AVFormatContext *s,
00130 AVPacket *pkt)
00131 {
00132 AVIOContext *pb = s->pb;
00133 unsigned char preamble[AUD_CHUNK_PREAMBLE_SIZE];
00134 unsigned int chunk_size;
00135 int ret = 0;
00136 AVStream *st = s->streams[0];
00137
00138 if (avio_read(pb, preamble, AUD_CHUNK_PREAMBLE_SIZE) !=
00139 AUD_CHUNK_PREAMBLE_SIZE)
00140 return AVERROR(EIO);
00141
00142
00143 if (AV_RL32(&preamble[4]) != AUD_CHUNK_SIGNATURE)
00144 return AVERROR_INVALIDDATA;
00145
00146 chunk_size = AV_RL16(&preamble[0]);
00147
00148 if (st->codec->codec_id == AV_CODEC_ID_WESTWOOD_SND1) {
00149
00150
00151
00152
00153 int out_size = AV_RL16(&preamble[2]);
00154 if ((ret = av_new_packet(pkt, chunk_size + 4)))
00155 return ret;
00156 if ((ret = avio_read(pb, &pkt->data[4], chunk_size)) != chunk_size)
00157 return ret < 0 ? ret : AVERROR(EIO);
00158 AV_WL16(&pkt->data[0], out_size);
00159 AV_WL16(&pkt->data[2], chunk_size);
00160
00161 pkt->duration = out_size;
00162 } else {
00163 ret = av_get_packet(pb, pkt, chunk_size);
00164 if (ret != chunk_size)
00165 return AVERROR(EIO);
00166
00167
00168 pkt->duration = (chunk_size * 2) / st->codec->channels;
00169 }
00170 pkt->stream_index = st->index;
00171
00172 return ret;
00173 }
00174
00175 AVInputFormat ff_wsaud_demuxer = {
00176 .name = "wsaud",
00177 .long_name = NULL_IF_CONFIG_SMALL("Westwood Studios audio"),
00178 .read_probe = wsaud_probe,
00179 .read_header = wsaud_read_header,
00180 .read_packet = wsaud_read_packet,
00181 };