00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <inttypes.h>
00023
00024 #include "avformat.h"
00025 #include "internal.h"
00026 #include "riff.h"
00027
00028
00029
00030
00031
00032 typedef struct {
00033 int64_t data_end;
00034 } XWMAContext;
00035
00036 static int xwma_probe(AVProbeData *p)
00037 {
00038 if (!memcmp(p->buf, "RIFF", 4) && !memcmp(p->buf + 8, "XWMA", 4))
00039 return AVPROBE_SCORE_MAX;
00040 return 0;
00041 }
00042
00043 static int xwma_read_header(AVFormatContext *s)
00044 {
00045 int64_t size;
00046 int ret;
00047 uint32_t dpds_table_size = 0;
00048 uint32_t *dpds_table = 0;
00049 unsigned int tag;
00050 AVIOContext *pb = s->pb;
00051 AVStream *st;
00052 XWMAContext *xwma = s->priv_data;
00053 int i;
00054
00055
00056
00057
00058
00059
00060 tag = avio_rl32(pb);
00061 if (tag != MKTAG('R', 'I', 'F', 'F'))
00062 return -1;
00063 avio_rl32(pb);
00064 tag = avio_rl32(pb);
00065 if (tag != MKTAG('X', 'W', 'M', 'A'))
00066 return -1;
00067
00068
00069 tag = avio_rl32(pb);
00070 if (tag != MKTAG('f', 'm', 't', ' '))
00071 return -1;
00072 size = avio_rl32(pb);
00073 st = avformat_new_stream(s, NULL);
00074 if (!st)
00075 return AVERROR(ENOMEM);
00076
00077 ret = ff_get_wav_header(pb, st->codec, size);
00078 if (ret < 0)
00079 return ret;
00080 st->need_parsing = AVSTREAM_PARSE_NONE;
00081
00082
00083
00084
00085
00086
00087 if (st->codec->codec_id != AV_CODEC_ID_WMAV2) {
00088 av_log(s, AV_LOG_WARNING, "unexpected codec (tag 0x04%x; id %d)\n",
00089 st->codec->codec_tag, st->codec->codec_id);
00090 av_log_ask_for_sample(s, NULL);
00091 } else {
00092
00093
00094
00095
00096
00097
00098
00099 if (st->codec->extradata_size != 0) {
00100
00101
00102
00103
00104 av_log(s, AV_LOG_WARNING, "unexpected extradata (%d bytes)\n",
00105 st->codec->extradata_size);
00106 av_log_ask_for_sample(s, NULL);
00107 } else {
00108 st->codec->extradata_size = 6;
00109 st->codec->extradata = av_mallocz(6 + FF_INPUT_BUFFER_PADDING_SIZE);
00110 if (!st->codec->extradata)
00111 return AVERROR(ENOMEM);
00112
00113
00114 st->codec->extradata[4] = 31;
00115 }
00116 }
00117
00118 if (!st->codec->channels) {
00119 av_log(s, AV_LOG_WARNING, "Invalid channel count: %d\n",
00120 st->codec->channels);
00121 return AVERROR_INVALIDDATA;
00122 }
00123 if (!st->codec->bits_per_coded_sample) {
00124 av_log(s, AV_LOG_WARNING, "Invalid bits_per_coded_sample: %d\n",
00125 st->codec->bits_per_coded_sample);
00126 return AVERROR_INVALIDDATA;
00127 }
00128
00129
00130 avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
00131
00132
00133 for (;;) {
00134 if (pb->eof_reached)
00135 return -1;
00136
00137 tag = avio_rl32(pb);
00138 size = avio_rl32(pb);
00139 if (tag == MKTAG('d', 'a', 't', 'a')) {
00140
00141 break;
00142 } else if (tag == MKTAG('d','p','d','s')) {
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 if (dpds_table) {
00155 av_log(s, AV_LOG_ERROR, "two dpds chunks present\n");
00156 return -1;
00157 }
00158
00159
00160 if (size & 3) {
00161 av_log(s, AV_LOG_WARNING,
00162 "dpds chunk size %"PRId64" not divisible by 4\n", size);
00163 }
00164 dpds_table_size = size / 4;
00165 if (dpds_table_size == 0 || dpds_table_size >= INT_MAX / 4) {
00166 av_log(s, AV_LOG_ERROR,
00167 "dpds chunk size %"PRId64" invalid\n", size);
00168 return -1;
00169 }
00170
00171
00172
00173
00174 dpds_table = av_malloc(dpds_table_size * sizeof(uint32_t));
00175 if (!dpds_table) {
00176 return AVERROR(ENOMEM);
00177 }
00178
00179 for (i = 0; i < dpds_table_size; ++i) {
00180 dpds_table[i] = avio_rl32(pb);
00181 size -= 4;
00182 }
00183 }
00184 avio_skip(pb, size);
00185 }
00186
00187
00188 if (size < 0)
00189 return -1;
00190 if (!size) {
00191 xwma->data_end = INT64_MAX;
00192 } else
00193 xwma->data_end = avio_tell(pb) + size;
00194
00195
00196 if (dpds_table && dpds_table_size) {
00197 int64_t cur_pos;
00198 const uint32_t bytes_per_sample
00199 = (st->codec->channels * st->codec->bits_per_coded_sample) >> 3;
00200
00201
00202 const uint64_t total_decoded_bytes = dpds_table[dpds_table_size - 1];
00203 st->duration = total_decoded_bytes / bytes_per_sample;
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 cur_pos = avio_tell(pb);
00215 for (i = 0; i < dpds_table_size; ++i) {
00216
00217
00218
00219
00220 av_add_index_entry(st,
00221 cur_pos + (i+1) * st->codec->block_align,
00222 dpds_table[i] / bytes_per_sample,
00223 st->codec->block_align,
00224 0,
00225 AVINDEX_KEYFRAME);
00226 }
00227 } else if (st->codec->bit_rate) {
00228
00229
00230
00231
00232 st->duration = (size<<3) * st->codec->sample_rate / st->codec->bit_rate;
00233 }
00234
00235 av_free(dpds_table);
00236
00237 return 0;
00238 }
00239
00240 static int xwma_read_packet(AVFormatContext *s, AVPacket *pkt)
00241 {
00242 int ret, size;
00243 int64_t left;
00244 AVStream *st;
00245 XWMAContext *xwma = s->priv_data;
00246
00247 st = s->streams[0];
00248
00249 left = xwma->data_end - avio_tell(s->pb);
00250 if (left <= 0) {
00251 return AVERROR_EOF;
00252 }
00253
00254
00255 size = (st->codec->block_align > 1) ? st->codec->block_align : 2230;
00256 size = FFMIN(size, left);
00257
00258 ret = av_get_packet(s->pb, pkt, size);
00259 if (ret < 0)
00260 return ret;
00261
00262 pkt->stream_index = 0;
00263 return ret;
00264 }
00265
00266 AVInputFormat ff_xwma_demuxer = {
00267 .name = "xwma",
00268 .long_name = NULL_IF_CONFIG_SMALL("Microsoft xWMA"),
00269 .priv_data_size = sizeof(XWMAContext),
00270 .read_probe = xwma_probe,
00271 .read_header = xwma_read_header,
00272 .read_packet = xwma_read_packet,
00273 };