annotate ffmpeg/libavformat/xmv.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * Microsoft XMV demuxer
yading@11 3 * Copyright (c) 2011 Sven Hesse <drmccoy@drmccoy.de>
yading@11 4 * Copyright (c) 2011 Matthew Hoops <clone2727@gmail.com>
yading@11 5 *
yading@11 6 * This file is part of FFmpeg.
yading@11 7 *
yading@11 8 * FFmpeg is free software; you can redistribute it and/or
yading@11 9 * modify it under the terms of the GNU Lesser General Public
yading@11 10 * License as published by the Free Software Foundation; either
yading@11 11 * version 2.1 of the License, or (at your option) any later version.
yading@11 12 *
yading@11 13 * FFmpeg is distributed in the hope that it will be useful,
yading@11 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 16 * Lesser General Public License for more details.
yading@11 17 *
yading@11 18 * You should have received a copy of the GNU Lesser General Public
yading@11 19 * License along with FFmpeg; if not, write to the Free Software
yading@11 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 21 */
yading@11 22
yading@11 23 /**
yading@11 24 * @file
yading@11 25 * Microsoft XMV demuxer
yading@11 26 */
yading@11 27
yading@11 28 #include <stdint.h>
yading@11 29
yading@11 30 #include "libavutil/intreadwrite.h"
yading@11 31
yading@11 32 #include "avformat.h"
yading@11 33 #include "internal.h"
yading@11 34 #include "riff.h"
yading@11 35 #include "libavutil/avassert.h"
yading@11 36
yading@11 37 /** The min size of an XMV header. */
yading@11 38 #define XMV_MIN_HEADER_SIZE 36
yading@11 39
yading@11 40 /** Audio flag: ADPCM'd 5.1 stream, front left / right channels */
yading@11 41 #define XMV_AUDIO_ADPCM51_FRONTLEFTRIGHT 1
yading@11 42 /** Audio flag: ADPCM'd 5.1 stream, front center / low frequency channels */
yading@11 43 #define XMV_AUDIO_ADPCM51_FRONTCENTERLOW 2
yading@11 44 /** Audio flag: ADPCM'd 5.1 stream, rear left / right channels */
yading@11 45 #define XMV_AUDIO_ADPCM51_REARLEFTRIGHT 4
yading@11 46
yading@11 47 /** Audio flag: Any of the ADPCM'd 5.1 stream flags. */
yading@11 48 #define XMV_AUDIO_ADPCM51 (XMV_AUDIO_ADPCM51_FRONTLEFTRIGHT | \
yading@11 49 XMV_AUDIO_ADPCM51_FRONTCENTERLOW | \
yading@11 50 XMV_AUDIO_ADPCM51_REARLEFTRIGHT)
yading@11 51
yading@11 52 /** A video packet with an XMV file. */
yading@11 53 typedef struct XMVVideoPacket {
yading@11 54 int stream_index; ///< The decoder stream index for this video packet.
yading@11 55
yading@11 56 uint32_t data_size; ///< The size of the remaining video data.
yading@11 57 uint64_t data_offset; ///< The offset of the video data within the file.
yading@11 58
yading@11 59 uint32_t current_frame; ///< The current frame within this video packet.
yading@11 60 uint32_t frame_count; ///< The amount of frames within this video packet.
yading@11 61
yading@11 62 int has_extradata; ///< Does the video packet contain extra data?
yading@11 63 uint8_t extradata[4]; ///< The extra data
yading@11 64
yading@11 65 int64_t last_pts; ///< PTS of the last video frame.
yading@11 66 int64_t pts; ///< PTS of the most current video frame.
yading@11 67 } XMVVideoPacket;
yading@11 68
yading@11 69 /** An audio packet with an XMV file. */
yading@11 70 typedef struct XMVAudioPacket {
yading@11 71 int stream_index; ///< The decoder stream index for this audio packet.
yading@11 72
yading@11 73 /* Stream format properties. */
yading@11 74 uint16_t compression; ///< The type of compression.
yading@11 75 uint16_t channels; ///< Number of channels.
yading@11 76 uint32_t sample_rate; ///< Sampling rate.
yading@11 77 uint16_t bits_per_sample; ///< Bits per compressed sample.
yading@11 78 uint32_t bit_rate; ///< Bits of compressed data per second.
yading@11 79 uint16_t flags; ///< Flags
yading@11 80 unsigned block_align; ///< Bytes per compressed block.
yading@11 81 uint16_t block_samples; ///< Decompressed samples per compressed block.
yading@11 82
yading@11 83 enum AVCodecID codec_id; ///< The codec ID of the compression scheme.
yading@11 84
yading@11 85 uint32_t data_size; ///< The size of the remaining audio data.
yading@11 86 uint64_t data_offset; ///< The offset of the audio data within the file.
yading@11 87
yading@11 88 uint32_t frame_size; ///< Number of bytes to put into an audio frame.
yading@11 89
yading@11 90 uint64_t block_count; ///< Running counter of decompressed audio block.
yading@11 91 } XMVAudioPacket;
yading@11 92
yading@11 93 /** Context for demuxing an XMV file. */
yading@11 94 typedef struct XMVDemuxContext {
yading@11 95 uint16_t audio_track_count; ///< Number of audio track in this file.
yading@11 96
yading@11 97 uint32_t this_packet_size; ///< Size of the current packet.
yading@11 98 uint32_t next_packet_size; ///< Size of the next packet.
yading@11 99
yading@11 100 uint64_t this_packet_offset; ///< Offset of the current packet.
yading@11 101 uint64_t next_packet_offset; ///< Offset of the next packet.
yading@11 102
yading@11 103 uint16_t current_stream; ///< The index of the stream currently handling.
yading@11 104 uint16_t stream_count; ///< The number of streams in this file.
yading@11 105
yading@11 106 XMVVideoPacket video; ///< The video packet contained in each packet.
yading@11 107 XMVAudioPacket *audio; ///< The audio packets contained in each packet.
yading@11 108 } XMVDemuxContext;
yading@11 109
yading@11 110 static int xmv_probe(AVProbeData *p)
yading@11 111 {
yading@11 112 uint32_t file_version;
yading@11 113
yading@11 114 if (p->buf_size < XMV_MIN_HEADER_SIZE)
yading@11 115 return 0;
yading@11 116
yading@11 117 file_version = AV_RL32(p->buf + 16);
yading@11 118 if ((file_version == 0) || (file_version > 4))
yading@11 119 return 0;
yading@11 120
yading@11 121 if (!memcmp(p->buf + 12, "xobX", 4))
yading@11 122 return AVPROBE_SCORE_MAX;
yading@11 123
yading@11 124 return 0;
yading@11 125 }
yading@11 126
yading@11 127 static int xmv_read_close(AVFormatContext *s)
yading@11 128 {
yading@11 129 XMVDemuxContext *xmv = s->priv_data;
yading@11 130
yading@11 131 av_freep(&xmv->audio);
yading@11 132
yading@11 133 return 0;
yading@11 134 }
yading@11 135
yading@11 136 static int xmv_read_header(AVFormatContext *s)
yading@11 137 {
yading@11 138 XMVDemuxContext *xmv = s->priv_data;
yading@11 139 AVIOContext *pb = s->pb;
yading@11 140 AVStream *vst = NULL;
yading@11 141
yading@11 142 uint32_t file_version;
yading@11 143 uint32_t this_packet_size;
yading@11 144 uint16_t audio_track;
yading@11 145 int ret;
yading@11 146
yading@11 147 avio_skip(pb, 4); /* Next packet size */
yading@11 148
yading@11 149 this_packet_size = avio_rl32(pb);
yading@11 150
yading@11 151 avio_skip(pb, 4); /* Max packet size */
yading@11 152 avio_skip(pb, 4); /* "xobX" */
yading@11 153
yading@11 154 file_version = avio_rl32(pb);
yading@11 155 if ((file_version != 4) && (file_version != 2))
yading@11 156 avpriv_request_sample(s, "Uncommon version %d", file_version);
yading@11 157
yading@11 158
yading@11 159 /* Video track */
yading@11 160
yading@11 161 vst = avformat_new_stream(s, NULL);
yading@11 162 if (!vst)
yading@11 163 return AVERROR(ENOMEM);
yading@11 164
yading@11 165 avpriv_set_pts_info(vst, 32, 1, 1000);
yading@11 166
yading@11 167 vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
yading@11 168 vst->codec->codec_id = AV_CODEC_ID_WMV2;
yading@11 169 vst->codec->codec_tag = MKBETAG('W', 'M', 'V', '2');
yading@11 170 vst->codec->width = avio_rl32(pb);
yading@11 171 vst->codec->height = avio_rl32(pb);
yading@11 172
yading@11 173 vst->duration = avio_rl32(pb);
yading@11 174
yading@11 175 xmv->video.stream_index = vst->index;
yading@11 176
yading@11 177 /* Audio tracks */
yading@11 178
yading@11 179 xmv->audio_track_count = avio_rl16(pb);
yading@11 180
yading@11 181 avio_skip(pb, 2); /* Unknown (padding?) */
yading@11 182
yading@11 183 xmv->audio = av_malloc(xmv->audio_track_count * sizeof(XMVAudioPacket));
yading@11 184 if (!xmv->audio) {
yading@11 185 ret = AVERROR(ENOMEM);
yading@11 186 goto fail;
yading@11 187 }
yading@11 188
yading@11 189 for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) {
yading@11 190 XMVAudioPacket *packet = &xmv->audio[audio_track];
yading@11 191 AVStream *ast = NULL;
yading@11 192
yading@11 193 packet->compression = avio_rl16(pb);
yading@11 194 packet->channels = avio_rl16(pb);
yading@11 195 packet->sample_rate = avio_rl32(pb);
yading@11 196 packet->bits_per_sample = avio_rl16(pb);
yading@11 197 packet->flags = avio_rl16(pb);
yading@11 198
yading@11 199 packet->bit_rate = packet->bits_per_sample *
yading@11 200 packet->sample_rate *
yading@11 201 packet->channels;
yading@11 202 packet->block_align = 36 * packet->channels;
yading@11 203 packet->block_samples = 64;
yading@11 204 packet->codec_id = ff_wav_codec_get_id(packet->compression,
yading@11 205 packet->bits_per_sample);
yading@11 206
yading@11 207 packet->stream_index = -1;
yading@11 208
yading@11 209 packet->frame_size = 0;
yading@11 210 packet->block_count = 0;
yading@11 211
yading@11 212 /* TODO: ADPCM'd 5.1 sound is encoded in three separate streams.
yading@11 213 * Those need to be interleaved to a proper 5.1 stream. */
yading@11 214 if (packet->flags & XMV_AUDIO_ADPCM51)
yading@11 215 av_log(s, AV_LOG_WARNING, "Unsupported 5.1 ADPCM audio stream "
yading@11 216 "(0x%04X)\n", packet->flags);
yading@11 217
yading@11 218 if (!packet->channels || !packet->sample_rate) {
yading@11 219 av_log(s, AV_LOG_ERROR, "Invalid parameters for audio track %d.\n",
yading@11 220 audio_track);
yading@11 221 ret = AVERROR_INVALIDDATA;
yading@11 222 goto fail;
yading@11 223 }
yading@11 224
yading@11 225 ast = avformat_new_stream(s, NULL);
yading@11 226 if (!ast) {
yading@11 227 ret = AVERROR(ENOMEM);
yading@11 228 goto fail;
yading@11 229 }
yading@11 230
yading@11 231 ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
yading@11 232 ast->codec->codec_id = packet->codec_id;
yading@11 233 ast->codec->codec_tag = packet->compression;
yading@11 234 ast->codec->channels = packet->channels;
yading@11 235 ast->codec->sample_rate = packet->sample_rate;
yading@11 236 ast->codec->bits_per_coded_sample = packet->bits_per_sample;
yading@11 237 ast->codec->bit_rate = packet->bit_rate;
yading@11 238 ast->codec->block_align = 36 * packet->channels;
yading@11 239
yading@11 240 avpriv_set_pts_info(ast, 32, packet->block_samples, packet->sample_rate);
yading@11 241
yading@11 242 packet->stream_index = ast->index;
yading@11 243
yading@11 244 ast->duration = vst->duration;
yading@11 245 }
yading@11 246
yading@11 247
yading@11 248 /* Initialize the packet context */
yading@11 249
yading@11 250 xmv->next_packet_offset = avio_tell(pb);
yading@11 251 xmv->next_packet_size = this_packet_size - xmv->next_packet_offset;
yading@11 252 xmv->stream_count = xmv->audio_track_count + 1;
yading@11 253
yading@11 254 return 0;
yading@11 255
yading@11 256 fail:
yading@11 257 xmv_read_close(s);
yading@11 258 return ret;
yading@11 259 }
yading@11 260
yading@11 261 static void xmv_read_extradata(uint8_t *extradata, AVIOContext *pb)
yading@11 262 {
yading@11 263 /* Read the XMV extradata */
yading@11 264
yading@11 265 uint32_t data = avio_rl32(pb);
yading@11 266
yading@11 267 int mspel_bit = !!(data & 0x01);
yading@11 268 int loop_filter = !!(data & 0x02);
yading@11 269 int abt_flag = !!(data & 0x04);
yading@11 270 int j_type_bit = !!(data & 0x08);
yading@11 271 int top_left_mv_flag = !!(data & 0x10);
yading@11 272 int per_mb_rl_bit = !!(data & 0x20);
yading@11 273 int slice_count = (data >> 6) & 7;
yading@11 274
yading@11 275 /* Write it back as standard WMV2 extradata */
yading@11 276
yading@11 277 data = 0;
yading@11 278
yading@11 279 data |= mspel_bit << 15;
yading@11 280 data |= loop_filter << 14;
yading@11 281 data |= abt_flag << 13;
yading@11 282 data |= j_type_bit << 12;
yading@11 283 data |= top_left_mv_flag << 11;
yading@11 284 data |= per_mb_rl_bit << 10;
yading@11 285 data |= slice_count << 7;
yading@11 286
yading@11 287 AV_WB32(extradata, data);
yading@11 288 }
yading@11 289
yading@11 290 static int xmv_process_packet_header(AVFormatContext *s)
yading@11 291 {
yading@11 292 XMVDemuxContext *xmv = s->priv_data;
yading@11 293 AVIOContext *pb = s->pb;
yading@11 294
yading@11 295 uint8_t data[8];
yading@11 296 uint16_t audio_track;
yading@11 297 uint64_t data_offset;
yading@11 298
yading@11 299 /* Next packet size */
yading@11 300 xmv->next_packet_size = avio_rl32(pb);
yading@11 301
yading@11 302 /* Packet video header */
yading@11 303
yading@11 304 if (avio_read(pb, data, 8) != 8)
yading@11 305 return AVERROR(EIO);
yading@11 306
yading@11 307 xmv->video.data_size = AV_RL32(data) & 0x007FFFFF;
yading@11 308
yading@11 309 xmv->video.current_frame = 0;
yading@11 310 xmv->video.frame_count = (AV_RL32(data) >> 23) & 0xFF;
yading@11 311
yading@11 312 xmv->video.has_extradata = (data[3] & 0x80) != 0;
yading@11 313
yading@11 314 /* Adding the audio data sizes and the video data size keeps you 4 bytes
yading@11 315 * short for every audio track. But as playing around with XMV files with
yading@11 316 * ADPCM audio showed, taking the extra 4 bytes from the audio data gives
yading@11 317 * you either completely distorted audio or click (when skipping the
yading@11 318 * remaining 68 bytes of the ADPCM block). Subtracting 4 bytes for every
yading@11 319 * audio track from the video data works at least for the audio. Probably
yading@11 320 * some alignment thing?
yading@11 321 * The video data has (always?) lots of padding, so it should work out...
yading@11 322 */
yading@11 323 xmv->video.data_size -= xmv->audio_track_count * 4;
yading@11 324
yading@11 325 xmv->current_stream = 0;
yading@11 326 if (!xmv->video.frame_count) {
yading@11 327 xmv->video.frame_count = 1;
yading@11 328 xmv->current_stream = xmv->stream_count > 1;
yading@11 329 }
yading@11 330
yading@11 331 /* Packet audio header */
yading@11 332
yading@11 333 for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) {
yading@11 334 XMVAudioPacket *packet = &xmv->audio[audio_track];
yading@11 335
yading@11 336 if (avio_read(pb, data, 4) != 4)
yading@11 337 return AVERROR(EIO);
yading@11 338
yading@11 339 packet->data_size = AV_RL32(data) & 0x007FFFFF;
yading@11 340 if ((packet->data_size == 0) && (audio_track != 0))
yading@11 341 /* This happens when I create an XMV with several identical audio
yading@11 342 * streams. From the size calculations, duplicating the previous
yading@11 343 * stream's size works out, but the track data itself is silent.
yading@11 344 * Maybe this should also redirect the offset to the previous track?
yading@11 345 */
yading@11 346 packet->data_size = xmv->audio[audio_track - 1].data_size;
yading@11 347
yading@11 348 /* Carve up the audio data in frame_count slices */
yading@11 349 packet->frame_size = packet->data_size / xmv->video.frame_count;
yading@11 350 packet->frame_size -= packet->frame_size % packet->block_align;
yading@11 351 }
yading@11 352
yading@11 353 /* Packet data offsets */
yading@11 354
yading@11 355 data_offset = avio_tell(pb);
yading@11 356
yading@11 357 xmv->video.data_offset = data_offset;
yading@11 358 data_offset += xmv->video.data_size;
yading@11 359
yading@11 360 for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) {
yading@11 361 xmv->audio[audio_track].data_offset = data_offset;
yading@11 362 data_offset += xmv->audio[audio_track].data_size;
yading@11 363 }
yading@11 364
yading@11 365 /* Video frames header */
yading@11 366
yading@11 367 /* Read new video extra data */
yading@11 368 if (xmv->video.data_size > 0) {
yading@11 369 if (xmv->video.has_extradata) {
yading@11 370 xmv_read_extradata(xmv->video.extradata, pb);
yading@11 371
yading@11 372 xmv->video.data_size -= 4;
yading@11 373 xmv->video.data_offset += 4;
yading@11 374
yading@11 375 if (xmv->video.stream_index >= 0) {
yading@11 376 AVStream *vst = s->streams[xmv->video.stream_index];
yading@11 377
yading@11 378 av_assert0(xmv->video.stream_index < s->nb_streams);
yading@11 379
yading@11 380 if (vst->codec->extradata_size < 4) {
yading@11 381 av_free(vst->codec->extradata);
yading@11 382
yading@11 383 vst->codec->extradata =
yading@11 384 av_malloc(4 + FF_INPUT_BUFFER_PADDING_SIZE);
yading@11 385 vst->codec->extradata_size = 4;
yading@11 386 }
yading@11 387
yading@11 388 memcpy(vst->codec->extradata, xmv->video.extradata, 4);
yading@11 389 }
yading@11 390 }
yading@11 391 }
yading@11 392
yading@11 393 return 0;
yading@11 394 }
yading@11 395
yading@11 396 static int xmv_fetch_new_packet(AVFormatContext *s)
yading@11 397 {
yading@11 398 XMVDemuxContext *xmv = s->priv_data;
yading@11 399 AVIOContext *pb = s->pb;
yading@11 400 int result;
yading@11 401
yading@11 402 if (xmv->this_packet_offset == xmv->next_packet_offset)
yading@11 403 return AVERROR_EOF;
yading@11 404
yading@11 405 /* Seek to it */
yading@11 406 xmv->this_packet_offset = xmv->next_packet_offset;
yading@11 407 if (avio_seek(pb, xmv->this_packet_offset, SEEK_SET) != xmv->this_packet_offset)
yading@11 408 return AVERROR(EIO);
yading@11 409
yading@11 410 /* Update the size */
yading@11 411 xmv->this_packet_size = xmv->next_packet_size;
yading@11 412 if (xmv->this_packet_size < (12 + xmv->audio_track_count * 4))
yading@11 413 return AVERROR(EIO);
yading@11 414
yading@11 415 /* Process the header */
yading@11 416 result = xmv_process_packet_header(s);
yading@11 417 if (result)
yading@11 418 return result;
yading@11 419
yading@11 420 /* Update the offset */
yading@11 421 xmv->next_packet_offset = xmv->this_packet_offset + xmv->this_packet_size;
yading@11 422
yading@11 423 return 0;
yading@11 424 }
yading@11 425
yading@11 426 static int xmv_fetch_audio_packet(AVFormatContext *s,
yading@11 427 AVPacket *pkt, uint32_t stream)
yading@11 428 {
yading@11 429 XMVDemuxContext *xmv = s->priv_data;
yading@11 430 AVIOContext *pb = s->pb;
yading@11 431 XMVAudioPacket *audio = &xmv->audio[stream];
yading@11 432
yading@11 433 uint32_t data_size;
yading@11 434 uint32_t block_count;
yading@11 435 int result;
yading@11 436
yading@11 437 /* Seek to it */
yading@11 438 if (avio_seek(pb, audio->data_offset, SEEK_SET) != audio->data_offset)
yading@11 439 return AVERROR(EIO);
yading@11 440
yading@11 441 if ((xmv->video.current_frame + 1) < xmv->video.frame_count)
yading@11 442 /* Not the last frame, get at most frame_size bytes. */
yading@11 443 data_size = FFMIN(audio->frame_size, audio->data_size);
yading@11 444 else
yading@11 445 /* Last frame, get the rest. */
yading@11 446 data_size = audio->data_size;
yading@11 447
yading@11 448 /* Read the packet */
yading@11 449 result = av_get_packet(pb, pkt, data_size);
yading@11 450 if (result <= 0)
yading@11 451 return result;
yading@11 452
yading@11 453 pkt->stream_index = audio->stream_index;
yading@11 454
yading@11 455 /* Calculate the PTS */
yading@11 456
yading@11 457 block_count = data_size / audio->block_align;
yading@11 458
yading@11 459 pkt->duration = block_count;
yading@11 460 pkt->pts = audio->block_count;
yading@11 461 pkt->dts = AV_NOPTS_VALUE;
yading@11 462
yading@11 463 audio->block_count += block_count;
yading@11 464
yading@11 465 /* Advance offset */
yading@11 466 audio->data_size -= data_size;
yading@11 467 audio->data_offset += data_size;
yading@11 468
yading@11 469 return 0;
yading@11 470 }
yading@11 471
yading@11 472 static int xmv_fetch_video_packet(AVFormatContext *s,
yading@11 473 AVPacket *pkt)
yading@11 474 {
yading@11 475 XMVDemuxContext *xmv = s->priv_data;
yading@11 476 AVIOContext *pb = s->pb;
yading@11 477 XMVVideoPacket *video = &xmv->video;
yading@11 478
yading@11 479 int result;
yading@11 480 uint32_t frame_header;
yading@11 481 uint32_t frame_size, frame_timestamp;
yading@11 482 uint8_t *data, *end;
yading@11 483
yading@11 484 /* Seek to it */
yading@11 485 if (avio_seek(pb, video->data_offset, SEEK_SET) != video->data_offset)
yading@11 486 return AVERROR(EIO);
yading@11 487
yading@11 488 /* Read the frame header */
yading@11 489 frame_header = avio_rl32(pb);
yading@11 490
yading@11 491 frame_size = (frame_header & 0x1FFFF) * 4 + 4;
yading@11 492 frame_timestamp = (frame_header >> 17);
yading@11 493
yading@11 494 if ((frame_size + 4) > video->data_size)
yading@11 495 return AVERROR(EIO);
yading@11 496
yading@11 497 /* Get the packet data */
yading@11 498 result = av_get_packet(pb, pkt, frame_size);
yading@11 499 if (result != frame_size)
yading@11 500 return result;
yading@11 501
yading@11 502 /* Contrary to normal WMV2 video, the bit stream in XMV's
yading@11 503 * WMV2 is little-endian.
yading@11 504 * TODO: This manual swap is of course suboptimal.
yading@11 505 */
yading@11 506 for (data = pkt->data, end = pkt->data + frame_size; data < end; data += 4)
yading@11 507 AV_WB32(data, AV_RL32(data));
yading@11 508
yading@11 509 pkt->stream_index = video->stream_index;
yading@11 510
yading@11 511 /* Calculate the PTS */
yading@11 512
yading@11 513 video->last_pts = frame_timestamp + video->pts;
yading@11 514
yading@11 515 pkt->duration = 0;
yading@11 516 pkt->pts = video->last_pts;
yading@11 517 pkt->dts = AV_NOPTS_VALUE;
yading@11 518
yading@11 519 video->pts += frame_timestamp;
yading@11 520
yading@11 521 /* Keyframe? */
yading@11 522 pkt->flags = (pkt->data[0] & 0x80) ? 0 : AV_PKT_FLAG_KEY;
yading@11 523
yading@11 524 /* Advance offset */
yading@11 525 video->data_size -= frame_size + 4;
yading@11 526 video->data_offset += frame_size + 4;
yading@11 527
yading@11 528 return 0;
yading@11 529 }
yading@11 530
yading@11 531 static int xmv_read_packet(AVFormatContext *s,
yading@11 532 AVPacket *pkt)
yading@11 533 {
yading@11 534 XMVDemuxContext *xmv = s->priv_data;
yading@11 535 int result;
yading@11 536
yading@11 537 if (xmv->video.current_frame == xmv->video.frame_count) {
yading@11 538 /* No frames left in this packet, so we fetch a new one */
yading@11 539
yading@11 540 result = xmv_fetch_new_packet(s);
yading@11 541 if (result)
yading@11 542 return result;
yading@11 543 }
yading@11 544
yading@11 545 if (xmv->current_stream == 0) {
yading@11 546 /* Fetch a video frame */
yading@11 547
yading@11 548 result = xmv_fetch_video_packet(s, pkt);
yading@11 549 if (result)
yading@11 550 return result;
yading@11 551
yading@11 552 } else {
yading@11 553 /* Fetch an audio frame */
yading@11 554
yading@11 555 result = xmv_fetch_audio_packet(s, pkt, xmv->current_stream - 1);
yading@11 556 if (result)
yading@11 557 return result;
yading@11 558 }
yading@11 559
yading@11 560 /* Increase our counters */
yading@11 561 if (++xmv->current_stream >= xmv->stream_count) {
yading@11 562 xmv->current_stream = 0;
yading@11 563 xmv->video.current_frame += 1;
yading@11 564 }
yading@11 565
yading@11 566 return 0;
yading@11 567 }
yading@11 568
yading@11 569 AVInputFormat ff_xmv_demuxer = {
yading@11 570 .name = "xmv",
yading@11 571 .long_name = NULL_IF_CONFIG_SMALL("Microsoft XMV"),
yading@11 572 .priv_data_size = sizeof(XMVDemuxContext),
yading@11 573 .read_probe = xmv_probe,
yading@11 574 .read_header = xmv_read_header,
yading@11 575 .read_packet = xmv_read_packet,
yading@11 576 .read_close = xmv_read_close,
yading@11 577 };