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