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