00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00028 #include <stdint.h>
00029
00030 #include "libavutil/intreadwrite.h"
00031
00032 #include "avformat.h"
00033 #include "internal.h"
00034 #include "riff.h"
00035
00036 #define XMV_MIN_HEADER_SIZE 36
00037
00038 #define XMV_AUDIO_ADPCM51_FRONTLEFTRIGHT 1
00039 #define XMV_AUDIO_ADPCM51_FRONTCENTERLOW 2
00040 #define XMV_AUDIO_ADPCM51_REARLEFTRIGHT 4
00041
00042 #define XMV_AUDIO_ADPCM51 (XMV_AUDIO_ADPCM51_FRONTLEFTRIGHT | \
00043 XMV_AUDIO_ADPCM51_FRONTCENTERLOW | \
00044 XMV_AUDIO_ADPCM51_REARLEFTRIGHT)
00045
00046 typedef struct XMVAudioTrack {
00047 uint16_t compression;
00048 uint16_t channels;
00049 uint32_t sample_rate;
00050 uint16_t bits_per_sample;
00051 uint32_t bit_rate;
00052 uint16_t flags;
00053 uint16_t block_align;
00054 uint16_t block_samples;
00055
00056 enum CodecID codec_id;
00057 } XMVAudioTrack;
00058
00059 typedef struct XMVVideoPacket {
00060
00061 int stream_index;
00062
00063 uint32_t data_size;
00064 uint32_t data_offset;
00065
00066 uint32_t current_frame;
00067 uint32_t frame_count;
00068
00069
00070 int has_extradata;
00071
00072
00073 uint8_t extradata[4];
00074
00075 int64_t last_pts;
00076 int64_t pts;
00077 } XMVVideoPacket;
00078
00079 typedef struct XMVAudioPacket {
00080
00081 int stream_index;
00082
00083
00084 XMVAudioTrack *track;
00085
00086 uint32_t data_size;
00087 uint32_t data_offset;
00088
00089 uint32_t frame_size;
00090
00091 uint32_t block_count;
00092 } XMVAudioPacket;
00093
00094 typedef struct XMVDemuxContext {
00095 uint16_t audio_track_count;
00096
00097 XMVAudioTrack *audio_tracks;
00098
00099 uint32_t this_packet_size;
00100 uint32_t next_packet_size;
00101
00102 uint32_t this_packet_offset;
00103 uint32_t next_packet_offset;
00104
00105 uint16_t current_stream;
00106 uint16_t stream_count;
00107
00108 XMVVideoPacket video;
00109 XMVAudioPacket *audio;
00110 } XMVDemuxContext;
00111
00112 static int xmv_probe(AVProbeData *p)
00113 {
00114 uint32_t file_version;
00115
00116 if (p->buf_size < XMV_MIN_HEADER_SIZE)
00117 return 0;
00118
00119 file_version = AV_RL32(p->buf + 16);
00120 if ((file_version == 0) || (file_version > 4))
00121 return 0;
00122
00123 if (!memcmp(p->buf + 12, "xobX", 4))
00124 return AVPROBE_SCORE_MAX;
00125
00126 return 0;
00127 }
00128
00129 static int xmv_read_close(AVFormatContext *s)
00130 {
00131 XMVDemuxContext *xmv = s->priv_data;
00132
00133 av_free(xmv->audio);
00134 av_free(xmv->audio_tracks);
00135
00136 return 0;
00137 }
00138
00139 static int xmv_read_header(AVFormatContext *s,
00140 AVFormatParameters *ap)
00141 {
00142 XMVDemuxContext *xmv = s->priv_data;
00143 AVIOContext *pb = s->pb;
00144 AVStream *vst = NULL;
00145
00146 uint32_t file_version;
00147 uint32_t this_packet_size;
00148 uint16_t audio_track;
00149 int ret;
00150
00151 avio_skip(pb, 4);
00152
00153 this_packet_size = avio_rl32(pb);
00154
00155 avio_skip(pb, 4);
00156 avio_skip(pb, 4);
00157
00158 file_version = avio_rl32(pb);
00159 if ((file_version != 4) && (file_version != 2))
00160 av_log_ask_for_sample(s, "Found uncommon version %d\n", file_version);
00161
00162
00163
00164
00165 vst = avformat_new_stream(s, NULL);
00166 if (!vst)
00167 return AVERROR(ENOMEM);
00168
00169 avpriv_set_pts_info(vst, 32, 1, 1000);
00170
00171 vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00172 vst->codec->codec_id = CODEC_ID_WMV2;
00173 vst->codec->codec_tag = MKBETAG('W', 'M', 'V', '2');
00174 vst->codec->width = avio_rl32(pb);
00175 vst->codec->height = avio_rl32(pb);
00176
00177 vst->duration = avio_rl32(pb);
00178
00179 xmv->video.stream_index = vst->index;
00180
00181
00182
00183 xmv->audio_track_count = avio_rl16(pb);
00184
00185 avio_skip(pb, 2);
00186
00187 xmv->audio_tracks = av_malloc(xmv->audio_track_count * sizeof(XMVAudioTrack));
00188 if (!xmv->audio_tracks)
00189 return AVERROR(ENOMEM);
00190
00191 xmv->audio = av_malloc(xmv->audio_track_count * sizeof(XMVAudioPacket));
00192 if (!xmv->audio) {
00193 ret = AVERROR(ENOMEM);
00194 goto fail;
00195 }
00196
00197 for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) {
00198 XMVAudioTrack *track = &xmv->audio_tracks[audio_track];
00199 XMVAudioPacket *packet = &xmv->audio [audio_track];
00200 AVStream *ast = NULL;
00201
00202 track->compression = avio_rl16(pb);
00203 track->channels = avio_rl16(pb);
00204 track->sample_rate = avio_rl32(pb);
00205 track->bits_per_sample = avio_rl16(pb);
00206 track->flags = avio_rl16(pb);
00207
00208 track->bit_rate = track->bits_per_sample *
00209 track->sample_rate *
00210 track->channels;
00211 track->block_align = 36 * track->channels;
00212 track->block_samples = 64;
00213 track->codec_id = ff_wav_codec_get_id(track->compression,
00214 track->bits_per_sample);
00215
00216 packet->track = track;
00217 packet->stream_index = -1;
00218
00219 packet->frame_size = 0;
00220 packet->block_count = 0;
00221
00222
00223
00224 if (track->flags & XMV_AUDIO_ADPCM51)
00225 av_log(s, AV_LOG_WARNING, "Unsupported 5.1 ADPCM audio stream "
00226 "(0x%04X)\n", track->flags);
00227
00228 if (!track->channels || !track->sample_rate) {
00229 av_log(s, AV_LOG_ERROR, "Invalid parameters for audio track %d.\n",
00230 audio_track);
00231 ret = AVERROR_INVALIDDATA;
00232 goto fail;
00233 }
00234
00235 ast = avformat_new_stream(s, NULL);
00236 if (!ast) {
00237 ret = AVERROR(ENOMEM);
00238 goto fail;
00239 }
00240
00241 ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00242 ast->codec->codec_id = track->codec_id;
00243 ast->codec->codec_tag = track->compression;
00244 ast->codec->channels = track->channels;
00245 ast->codec->sample_rate = track->sample_rate;
00246 ast->codec->bits_per_coded_sample = track->bits_per_sample;
00247 ast->codec->bit_rate = track->bit_rate;
00248 ast->codec->block_align = 36 * track->channels;
00249
00250 avpriv_set_pts_info(ast, 32, track->block_samples, track->sample_rate);
00251
00252 packet->stream_index = ast->index;
00253
00254 ast->duration = vst->duration;
00255 }
00256
00257
00260 xmv->next_packet_offset = avio_tell(pb);
00261 xmv->next_packet_size = this_packet_size - xmv->next_packet_offset;
00262 xmv->stream_count = xmv->audio_track_count + 1;
00263
00264 return 0;
00265
00266 fail:
00267 xmv_read_close(s);
00268 return ret;
00269 }
00270
00271 static void xmv_read_extradata(uint8_t *extradata, AVIOContext *pb)
00272 {
00273
00274
00275 uint32_t data = avio_rl32(pb);
00276
00277 int mspel_bit = !!(data & 0x01);
00278 int loop_filter = !!(data & 0x02);
00279 int abt_flag = !!(data & 0x04);
00280 int j_type_bit = !!(data & 0x08);
00281 int top_left_mv_flag = !!(data & 0x10);
00282 int per_mb_rl_bit = !!(data & 0x20);
00283 int slice_count = (data >> 6) & 7;
00284
00285
00286
00287 data = 0;
00288
00289 data |= mspel_bit << 15;
00290 data |= loop_filter << 14;
00291 data |= abt_flag << 13;
00292 data |= j_type_bit << 12;
00293 data |= top_left_mv_flag << 11;
00294 data |= per_mb_rl_bit << 10;
00295 data |= slice_count << 7;
00296
00297 AV_WB32(extradata, data);
00298 }
00299
00300 static int xmv_process_packet_header(AVFormatContext *s)
00301 {
00302 XMVDemuxContext *xmv = s->priv_data;
00303 AVIOContext *pb = s->pb;
00304
00305 uint8_t data[8];
00306 uint16_t audio_track;
00307 uint32_t data_offset;
00308
00309
00310 xmv->next_packet_size = avio_rl32(pb);
00311
00312
00313
00314 if (avio_read(pb, data, 8) != 8)
00315 return AVERROR(EIO);
00316
00317 xmv->video.data_size = AV_RL32(data) & 0x007FFFFF;
00318
00319 xmv->video.current_frame = 0;
00320 xmv->video.frame_count = (AV_RL32(data) >> 23) & 0xFF;
00321
00322 xmv->video.has_extradata = (data[3] & 0x80) != 0;
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 xmv->video.data_size -= xmv->audio_track_count * 4;
00334
00335 xmv->current_stream = 0;
00336 if (!xmv->video.frame_count) {
00337 xmv->video.frame_count = 1;
00338 xmv->current_stream = 1;
00339 }
00340
00341
00342
00343 for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) {
00344 XMVAudioPacket *packet = &xmv->audio[audio_track];
00345
00346 if (avio_read(pb, data, 4) != 4)
00347 return AVERROR(EIO);
00348
00349 packet->data_size = AV_RL32(data) & 0x007FFFFF;
00350 if ((packet->data_size == 0) && (audio_track != 0))
00351
00352
00353
00354
00355
00356 packet->data_size = xmv->audio[audio_track - 1].data_size;
00357
00359 packet->frame_size = packet->data_size / xmv->video.frame_count;
00360 packet->frame_size -= packet->frame_size % packet->track->block_align;
00361 }
00362
00363
00364
00365 data_offset = avio_tell(pb);
00366
00367 xmv->video.data_offset = data_offset;
00368 data_offset += xmv->video.data_size;
00369
00370 for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) {
00371 xmv->audio[audio_track].data_offset = data_offset;
00372 data_offset += xmv->audio[audio_track].data_size;
00373 }
00374
00375
00376
00377
00378 if (xmv->video.data_size > 0) {
00379 if (xmv->video.has_extradata) {
00380 xmv_read_extradata(xmv->video.extradata, pb);
00381
00382 xmv->video.data_size -= 4;
00383 xmv->video.data_offset += 4;
00384
00385 if (xmv->video.stream_index >= 0) {
00386 AVStream *vst = s->streams[xmv->video.stream_index];
00387
00388 assert(xmv->video.stream_index < s->nb_streams);
00389
00390 if (vst->codec->extradata_size < 4) {
00391 av_free(vst->codec->extradata);
00392
00393 vst->codec->extradata =
00394 av_malloc(4 + FF_INPUT_BUFFER_PADDING_SIZE);
00395 vst->codec->extradata_size = 4;
00396 }
00397
00398 memcpy(vst->codec->extradata, xmv->video.extradata, 4);
00399 }
00400 }
00401 }
00402
00403 return 0;
00404 }
00405
00406 static int xmv_fetch_new_packet(AVFormatContext *s)
00407 {
00408 XMVDemuxContext *xmv = s->priv_data;
00409 AVIOContext *pb = s->pb;
00410 int result;
00411
00412
00413 xmv->this_packet_offset = xmv->next_packet_offset;
00414 if (avio_seek(pb, xmv->this_packet_offset, SEEK_SET) != xmv->this_packet_offset)
00415 return AVERROR(EIO);
00416
00417
00418 xmv->this_packet_size = xmv->next_packet_size;
00419 if (xmv->this_packet_size < (12 + xmv->audio_track_count * 4))
00420 return AVERROR(EIO);
00421
00422
00423 result = xmv_process_packet_header(s);
00424 if (result)
00425 return result;
00426
00427
00428 xmv->next_packet_offset = xmv->this_packet_offset + xmv->this_packet_size;
00429
00430 return 0;
00431 }
00432
00433 static int xmv_fetch_audio_packet(AVFormatContext *s,
00434 AVPacket *pkt, uint32_t stream)
00435 {
00436 XMVDemuxContext *xmv = s->priv_data;
00437 AVIOContext *pb = s->pb;
00438 XMVAudioPacket *audio = &xmv->audio[stream];
00439
00440 uint32_t data_size;
00441 uint32_t block_count;
00442 int result;
00443
00444
00445 if (avio_seek(pb, audio->data_offset, SEEK_SET) != audio->data_offset)
00446 return AVERROR(EIO);
00447
00448 if ((xmv->video.current_frame + 1) < xmv->video.frame_count)
00449
00450 data_size = FFMIN(audio->frame_size, audio->data_size);
00451 else
00452
00453 data_size = audio->data_size;
00454
00455
00456 result = av_get_packet(pb, pkt, data_size);
00457 if (result <= 0)
00458 return result;
00459
00460 pkt->stream_index = audio->stream_index;
00461
00462
00463
00464 block_count = data_size / audio->track->block_align;
00465
00466 pkt->duration = block_count;
00467 pkt->pts = audio->block_count;
00468 pkt->dts = AV_NOPTS_VALUE;
00469
00470 audio->block_count += block_count;
00471
00472
00473 audio->data_size -= data_size;
00474 audio->data_offset += data_size;
00475
00476 return 0;
00477 }
00478
00479 static int xmv_fetch_video_packet(AVFormatContext *s,
00480 AVPacket *pkt)
00481 {
00482 XMVDemuxContext *xmv = s->priv_data;
00483 AVIOContext *pb = s->pb;
00484 XMVVideoPacket *video = &xmv->video;
00485
00486 int result;
00487 uint32_t frame_header;
00488 uint32_t frame_size, frame_timestamp;
00489 uint32_t i;
00490
00491
00492 if (avio_seek(pb, video->data_offset, SEEK_SET) != video->data_offset)
00493 return AVERROR(EIO);
00494
00495
00496 frame_header = avio_rl32(pb);
00497
00498 frame_size = (frame_header & 0x1FFFF) * 4 + 4;
00499 frame_timestamp = (frame_header >> 17);
00500
00501 if ((frame_size + 4) > video->data_size)
00502 return AVERROR(EIO);
00503
00504
00505 result = av_new_packet(pkt, frame_size);
00506 if (result)
00507 return result;
00508
00509
00510
00511
00512
00513 for (i = 0; i < frame_size; i += 4)
00514 AV_WB32(pkt->data + i, avio_rl32(pb));
00515
00516 pkt->stream_index = video->stream_index;
00517
00518
00519
00520 video->last_pts = frame_timestamp + video->pts;
00521
00522 pkt->duration = 0;
00523 pkt->pts = video->last_pts;
00524 pkt->dts = AV_NOPTS_VALUE;
00525
00526 video->pts += frame_timestamp;
00527
00528
00529 pkt->flags = (pkt->data[0] & 0x80) ? 0 : AV_PKT_FLAG_KEY;
00530
00531
00532 video->data_size -= frame_size + 4;
00533 video->data_offset += frame_size + 4;
00534
00535 return 0;
00536 }
00537
00538 static int xmv_read_packet(AVFormatContext *s,
00539 AVPacket *pkt)
00540 {
00541 XMVDemuxContext *xmv = s->priv_data;
00542 int result;
00543
00544 if (xmv->video.current_frame == xmv->video.frame_count) {
00545
00546
00547 result = xmv_fetch_new_packet(s);
00548 if (result)
00549 return result;
00550 }
00551
00552 if (xmv->current_stream == 0) {
00553
00554
00555 result = xmv_fetch_video_packet(s, pkt);
00556 if (result)
00557 return result;
00558
00559 } else {
00560
00561
00562 result = xmv_fetch_audio_packet(s, pkt, xmv->current_stream - 1);
00563 if (result)
00564 return result;
00565 }
00566
00567
00568 if (++xmv->current_stream >= xmv->stream_count) {
00569 xmv->current_stream = 0;
00570 xmv->video.current_frame += 1;
00571 }
00572
00573 return 0;
00574 }
00575
00576 AVInputFormat ff_xmv_demuxer = {
00577 .name = "xmv",
00578 .long_name = NULL_IF_CONFIG_SMALL("Microsoft XMV"),
00579 .priv_data_size = sizeof(XMVDemuxContext),
00580 .read_probe = xmv_probe,
00581 .read_header = xmv_read_header,
00582 .read_packet = xmv_read_packet,
00583 .read_close = xmv_read_close,
00584 };