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