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, AVFormatParameters *ap)
00044 {
00045 int64_t size, av_uninit(data_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 != 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
00119 avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
00120
00121
00122 for (;;) {
00123 if (pb->eof_reached)
00124 return -1;
00125
00126 tag = avio_rl32(pb);
00127 size = avio_rl32(pb);
00128 if (tag == MKTAG('d', 'a', 't', 'a')) {
00129
00130 break;
00131 } else if (tag == MKTAG('d','p','d','s')) {
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 if (dpds_table) {
00144 av_log(s, AV_LOG_ERROR, "two dpds chunks present\n");
00145 return -1;
00146 }
00147
00148
00149 if (size & 3) {
00150 av_log(s, AV_LOG_WARNING,
00151 "dpds chunk size %"PRId64" not divisible by 4\n", size);
00152 }
00153 dpds_table_size = size / 4;
00154 if (dpds_table_size == 0 || dpds_table_size >= INT_MAX / 4) {
00155 av_log(s, AV_LOG_ERROR,
00156 "dpds chunk size %"PRId64" invalid\n", size);
00157 return -1;
00158 }
00159
00160
00161
00162
00163 dpds_table = av_malloc(dpds_table_size * sizeof(uint32_t));
00164 if (!dpds_table) {
00165 return AVERROR(ENOMEM);
00166 }
00167
00168 for (i = 0; i < dpds_table_size; ++i) {
00169 dpds_table[i] = avio_rl32(pb);
00170 size -= 4;
00171 }
00172 }
00173 avio_skip(pb, size);
00174 }
00175
00176
00177 if (size < 0)
00178 return -1;
00179 if (!size) {
00180 xwma->data_end = INT64_MAX;
00181 } else
00182 xwma->data_end = avio_tell(pb) + size;
00183
00184
00185 if (dpds_table && dpds_table_size) {
00186 int64_t cur_pos;
00187 const uint32_t bytes_per_sample
00188 = (st->codec->channels * st->codec->bits_per_coded_sample) >> 3;
00189
00190
00191 const uint64_t total_decoded_bytes = dpds_table[dpds_table_size - 1];
00192 st->duration = total_decoded_bytes / bytes_per_sample;
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 cur_pos = avio_tell(pb);
00204 for (i = 0; i < dpds_table_size; ++i) {
00205
00206
00207
00208
00209 av_add_index_entry(st,
00210 cur_pos + (i+1) * st->codec->block_align,
00211 dpds_table[i] / bytes_per_sample,
00212 st->codec->block_align,
00213 0,
00214 AVINDEX_KEYFRAME);
00215 }
00216 } else if (st->codec->bit_rate) {
00217
00218
00219
00220
00221 st->duration = (size<<3) * st->codec->sample_rate / st->codec->bit_rate;
00222 }
00223
00224 av_free(dpds_table);
00225
00226 return 0;
00227 }
00228
00229 static int xwma_read_packet(AVFormatContext *s, AVPacket *pkt)
00230 {
00231 int ret, size;
00232 int64_t left;
00233 AVStream *st;
00234 XWMAContext *xwma = s->priv_data;
00235
00236 st = s->streams[0];
00237
00238 left = xwma->data_end - avio_tell(s->pb);
00239 if (left <= 0) {
00240 return AVERROR_EOF;
00241 }
00242
00243
00244 size = (st->codec->block_align > 1) ? st->codec->block_align : 2230;
00245 size = FFMIN(size, left);
00246
00247 ret = av_get_packet(s->pb, pkt, size);
00248 if (ret < 0)
00249 return ret;
00250
00251 pkt->stream_index = 0;
00252 return ret;
00253 }
00254
00255 AVInputFormat ff_xwma_demuxer = {
00256 .name = "xwma",
00257 .long_name = NULL_IF_CONFIG_SMALL("Microsoft xWMA"),
00258 .priv_data_size = sizeof(XWMAContext),
00259 .read_probe = xwma_probe,
00260 .read_header = xwma_read_header,
00261 .read_packet = xwma_read_packet,
00262 };