[FFmpeg-devel] [PATCH] lavf: Add an XMV demuxer

Michael Niedermayer michaelni at gmx.at
Thu Aug 18 18:03:15 CEST 2011


Hi Sven

On Tue, Aug 16, 2011 at 09:26:40PM +0200, Sven Hesse wrote:
> New version.
> 
> The wmv2dec hack was removed; the demuxer now manually converts the
> extradata into the standard WMV2 format. This has the added benefit
> that remuxing works now. Additionally, the keyframe flag is also
> passed to video packets containing key frames, this is apparently
> necessary for remuxing to work correctly.

This patch has been applied by diego and merged into
ffmpeg.

"late" Review below


[...]
> +
> +/**
> + * @file
> + * Microsoft XMV demuxer
> + */
> +
> +#include <stdint.h>
> +
> +#include "libavutil/intreadwrite.h"
> +
> +#include "avformat.h"
> +#include "riff.h"
> +
> +#define XMV_MIN_HEADER_SIZE 36
> +
> +#define XMV_AUDIO_ADPCM51_FRONTLEFTRIGHT 1
> +#define XMV_AUDIO_ADPCM51_FRONTCENTERLOW 2
> +#define XMV_AUDIO_ADPCM51_REARLEFTRIGHT  4
> +
> +#define XMV_AUDIO_ADPCM51 (XMV_AUDIO_ADPCM51_FRONTLEFTRIGHT | \
> +                           XMV_AUDIO_ADPCM51_FRONTCENTERLOW | \
> +                           XMV_AUDIO_ADPCM51_REARLEFTRIGHT)
> +
> +typedef struct XMVAudioTrack {
> +    uint16_t compression;
> +    uint16_t channels;
> +    uint32_t sample_rate;
> +    uint16_t bits_per_sample;
> +    uint32_t bit_rate;
> +    uint16_t flags;
> +    uint16_t block_align;
> +    uint16_t block_samples;
> +
> +    enum CodecID codec_id;
> +} XMVAudioTrack;
> +
> +typedef struct XMVVideoPacket {
> +    /* The decoder stream index for this video packet. */
> +    int stream_index;
> +
> +    uint32_t data_size;
> +    uint32_t data_offset;
> +
> +    uint32_t current_frame;
> +    uint32_t frame_count;
> +
> +    /* Does the video packet contain extra data? */
> +    int has_extradata;
> +
> +    /* Extra data */
> +    uint8_t extradata[4];
> +
> +    int64_t last_pts;
> +    int64_t pts;
> +} XMVVideoPacket;

The comments should use doxygen compatible syntax

The various offsets in the various structs should possibly be 64bit
or there may be need for integer overflow checks on their updates


> +
> +typedef struct XMVAudioPacket {
> +    /* The decoder stream index for this audio packet. */
> +    int stream_index;
> +
> +    /* The audio track this packet encodes. */
> +    XMVAudioTrack *track;
> +
> +    uint32_t data_size;
> +    uint32_t data_offset;
> +
> +    uint32_t frame_size;
> +
> +    uint32_t block_count;
> +} XMVAudioPacket;

this struct could be put in XMVAudioTrack to avoid the second malloc
& free, also it would possibly avoid a memleak if the second
alloc fails


[...]
> +    /** Initialize the packet context */
> +
> +    xmv->next_packet_offset = avio_tell(pb);
> +
> +    xmv->next_packet_size = this_packet_size - xmv->next_packet_offset;

> +    xmv->this_packet_size = 0;
> +
> +    xmv->video.current_frame = 0;
> +    xmv->video.frame_count   = 0;
> +    xmv->video.pts           = 0;
> +    xmv->video.last_pts      = 0;
> +
> +    xmv->current_stream = 0;

The struct fields should already be 0 at the begin from av_mallocz() thats
used to allocate the context


[...]
> +    /* Packet audio header */
> +
> +    for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) {
> +        XMVAudioPacket *packet = &xmv->audio[audio_track];
> +
> +        if (avio_read(pb, data, 4) != 4)
> +            return AVERROR(EIO);
> +
> +        packet->data_size = AV_RL32(data) & 0x007FFFFF;
> +        if ((packet->data_size == 0) && (audio_track != 0))
> +            /* This happens when I create an XMV with several identical audio
> +             * streams. From the size calculations, duplicating the previous
> +             * stream's size works out, but the track data itself is silent.
> +             * Maybe this should also redirect the offset to the previous track?
> +             */
> +            packet->data_size = xmv->audio[audio_track - 1].data_size;
> +
> +        /** Carve up the audio data in frame_count slices */
> +        packet->frame_size  = packet->data_size  / xmv->video.frame_count;
> +        packet->frame_size -= packet->frame_size % packet->track->block_align;

Can these variables be 0 ? If so some checks are needed to avoid div
by zero


[...]
> +static int xmv_fetch_video_packet(AVFormatContext *s,
> +                                  AVPacket *pkt)
> +{
> +    XMVDemuxContext *xmv   = s->priv_data;
> +    AVIOContext     *pb    = s->pb;
> +    XMVVideoPacket  *video = &xmv->video;
> +
> +    int result;
> +    uint32_t frame_header;
> +    uint32_t frame_size, frame_timestamp;
> +    uint32_t i;
> +
> +    /* Seek to it */
> +    if (avio_seek(pb, video->data_offset, SEEK_SET) != video->data_offset)
> +        return AVERROR(EIO);
> +
> +    /* Read the frame header */
> +    frame_header = avio_rl32(pb);
> +
> +    frame_size      = (frame_header & 0x1FFFF) * 4 + 4;
> +    frame_timestamp = (frame_header >> 17);
> +
> +    if ((frame_size + 4) > video->data_size)
> +        return AVERROR(EIO);
> +
> +    /* Create the packet */
> +    result = av_new_packet(pkt, frame_size);
> +    if (result)
> +        return result;
> +
> +    /* Contrary to normal WMV2 video, the bit stream in XMV's
> +     * WMV2 is little-endian.
> +     * TODO: This manual swap is of course suboptimal.
> +     */
> +    for (i = 0; i < frame_size; i += 4)
> +        AV_WB32(pkt->data + i, avio_rl32(pb));

it might be faster (yet stil suboptimal) to read the whole and then
seperately bswap it
note there is also DSPContext.bswap_buf() but that may be hard/ugly
to use from a demuxer

Also you might want to add yourself to MAINTAINERS if you want to
maintain this demuxer in the future

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Into a blind darkness they enter who follow after the Ignorance,
they as if into a greater darkness enter who devote themselves
to the Knowledge alone. -- Isha Upanishad
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20110818/bdf6b612/attachment.asc>


More information about the ffmpeg-devel mailing list