Coverage Report

Created: 2026-04-01 07:42

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