00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00036 #include "libavutil/intreadwrite.h"
00037 #include "avformat.h"
00038 #include "internal.h"
00039
00040 #define AUD_HEADER_SIZE 12
00041 #define AUD_CHUNK_PREAMBLE_SIZE 8
00042 #define AUD_CHUNK_SIGNATURE 0x0000DEAF
00043
00044 static int wsaud_probe(AVProbeData *p)
00045 {
00046 int field;
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 if (p->buf_size < AUD_HEADER_SIZE + AUD_CHUNK_PREAMBLE_SIZE)
00059 return 0;
00060
00061
00062 field = AV_RL16(&p->buf[0]);
00063 if ((field < 8000) || (field > 48000))
00064 return 0;
00065
00066
00067
00068 if (p->buf[10] & 0xFC)
00069 return 0;
00070
00071
00072
00073 if (p->buf[11] != 99 && p->buf[11] != 1)
00074 return 0;
00075
00076
00077 if (AV_RL32(&p->buf[16]) != AUD_CHUNK_SIGNATURE)
00078 return 0;
00079
00080
00081 return AVPROBE_SCORE_MAX / 2;
00082 }
00083
00084 static int wsaud_read_header(AVFormatContext *s,
00085 AVFormatParameters *ap)
00086 {
00087 AVIOContext *pb = s->pb;
00088 AVStream *st;
00089 unsigned char header[AUD_HEADER_SIZE];
00090 int sample_rate, channels, codec;
00091
00092 if (avio_read(pb, header, AUD_HEADER_SIZE) != AUD_HEADER_SIZE)
00093 return AVERROR(EIO);
00094
00095 sample_rate = AV_RL16(&header[0]);
00096 channels = (header[10] & 0x1) + 1;
00097 codec = header[11];
00098
00099
00100 st = avformat_new_stream(s, NULL);
00101 if (!st)
00102 return AVERROR(ENOMEM);
00103
00104 switch (codec) {
00105 case 1:
00106 if (channels != 1) {
00107 av_log_ask_for_sample(s, "Stereo WS-SND1 is not supported.\n");
00108 return AVERROR_PATCHWELCOME;
00109 }
00110 st->codec->codec_id = CODEC_ID_WESTWOOD_SND1;
00111 break;
00112 case 99:
00113 st->codec->codec_id = CODEC_ID_ADPCM_IMA_WS;
00114 st->codec->bits_per_coded_sample = 4;
00115 st->codec->bit_rate = channels * sample_rate * 4;
00116 break;
00117 default:
00118 av_log_ask_for_sample(s, "Unknown codec: %d\n", codec);
00119 return AVERROR_PATCHWELCOME;
00120 }
00121 avpriv_set_pts_info(st, 64, 1, sample_rate);
00122 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00123 st->codec->channels = channels;
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 == 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 format"),
00178 .read_probe = wsaud_probe,
00179 .read_header = wsaud_read_header,
00180 .read_packet = wsaud_read_packet,
00181 };