~medibuntu-maintainers/mplayer/medibuntu.precise

« back to all changes in this revision

Viewing changes to ffmpeg/libavformat/xmv.c

  • Committer: Gauvain Pocentek
  • Date: 2012-03-06 11:59:12 UTC
  • mfrom: (66.1.15 precise)
  • Revision ID: gauvain@pocentek.net-20120306115912-h9d6kt9j0l532oo5
* Merge from Ubuntu:
  - put back faac support
  - recommends apport-hooks-medibuntu
  - change Maintainer, Uploaders & Vcs-* fields.
* New upstream snapshot
* upload to unstable
* Build against external libmpeg2
* drop 51_FTBFS_arm.patch again
* no longer build depend on libcdparanoia-dev on the Hurd
* Fix FTBFS on the hurd.
  Thanks to Samuel Thibault <sthibault@debian.org> (Closes: #654974)
* Fix FTBFS on arm
* New upstream snapshot, Closes: #650339, #643621, #481807
* Imported Upstream version 1.0~rc4+svn34492
* Bump standards version
* Bump dependency on libav >= 4:0.8~, Closes: #653887
* Fix build-indep
* Build mplayer-gui again, Closes: #568514
* Drop debian/all-lang-config-mak.sh, no longer needed
* include .dfsg1 in version number
* remove get-orig-source target
* no longer prune compiler flags from the environment
* No longer advertise nor build 3fdx, mga and dxr3 backends,
  Closes: #496106, #442181, #533546
* beautify mplayer version identification string
* Brown paperbag upload.
* Next try to fix build failure on sparce after recent binutils change.
* Brown paperbag upload.
* Really fix build failure on sparc after recent binutils change.
* Properly set Replaces/Conflicts on mplayer2{,-dbg} to avoid
  file overwrite errors.
* Adjust versioning of mplayer listed in the mplayer-dbg's Depends field.
* Fix build failure on sparc after recent binutils change.
* Urgency medium bumped because of RC-level bugfix
  and speeding up x264 transition.
* Update to my @debian.org email.
* Upload to unstable
* Enable joystick support on Linux only, Closes: #638408
* Rebuild fixes toolchain issue on arm, Closes: #637077
* New upstream snapshot
* following the discussion started by Diego Biurrun <diego@biurrun.de>
  in debian-devel, I have prepared a new packaging of 'mplayer'
  (with code that comes from CVS)
* the upstream tar.bz cannot be distributed by Debian, since it contains
   CSS code; so I am repackaging it 
* I have tried my best to address all known issues:
  - the package contains the detailed Copyright made by Diego Biurrun 
  - the package does not contain CSS code, or  AFAIK other code on which 
     there is active patent enforcement
  - there is a script  debian/cvs-changelog.sh  that shows all changes
     done to files included in this source.
    This should comply with GPLv2 sec 2.a  (in spirit if not in letter)
    For this reason, the source code contains CVS directories.
* needs   make (>= 3.80) for 'html-chunked-$(1)' in DOCS/xml/Makefile

* some corrections, as suggested Diego Biurrun
  - binary codecs should go into /usr/lib/codecs (upstream default)
  - better template 'mplayer/install_codecs'
  - an empty 'font=' in mplayer.conf breaks mplayer: postinst corrected
* correction in 'mplayer/cfgnote'
* better mplayer.postinst and mplayer.config

* New upstream release
* better debian/copyright file
* do not ship a skin
* New upstream release
* changed DEB_BUILD_OPTIONS to DEB_BUILD_CONFIGURE ,
  DEB_BUILD_OPTIONS is used as in debian policy
* use gcc-3.4
* changed xlibs-dev to a long list of dependencies, for Debian/etch
* try to adhere to  http://www.mplayerhq.hu/DOCS/tech/binary-packaging.txt
  (see README.Debian for details)
* removed dependency on xlibmesa-dev, disabled opengl
* New upstream release
* Simon McVittie <hacks@pseudorandom.co.uk> wonderful work:
- Work around Debian bug #267442 (glibc's sys/uio.h and gcc's altivec.h have
  conflicting uses for __vector) by re-ordering #includes
- Fix potential symlink attack in ./configure
- Disable support for binary codecs on platforms for which those codecs
  aren't available; also disable the corresponding Debconf note when it's
  inappropriate
- Changed Build-Depends: so it works in pbuilder
- Explicitly build-depend on libjpeg62-dev, libfontconfig1-dev,
  libungif4-dev 
- Tweak debian/rules to avoid certain errors being ignored
- Use --language=all
* provide a target  'debian/rules get-orig-source' 
  that recreates the orig.tar.gz ; then use the above orig.tar.gz
* rewrote some parts of debian/rules
* don't clean and recompile docs if upstream ships them
* mplayer-doc was shipping too much stuff
* translated man pages where not installed properly
* compile with libdv4-dev
* correct README.Debian
* Forgot build-dep on libtheora
* Must not depend on libxvidcore
* New upstream release
* new release.
* rc1 to become 0.90
* new pre-release
* new pre-release
* gtk bug fixed.
* new release.
* version bumped
* 0.60 pre2 release
* 0.60 pre-release.

Show diffs side-by-side

added added

removed removed

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