libavformat/xmv.c
Go to the documentation of this file.
00001 /*
00002  * Microsoft XMV demuxer
00003  * Copyright (c) 2011 Sven Hesse <drmccoy@drmccoy.de>
00004  * Copyright (c) 2011 Matthew Hoops <clone2727@gmail.com>
00005  *
00006  * This file is part of Libav.
00007  *
00008  * Libav is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * Libav is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with Libav; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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     /* The decoder stream index for this video packet. */
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     /* Does the video packet contain extra data? */
00070     int has_extradata;
00071 
00072     /* Extra data */
00073     uint8_t extradata[4];
00074 
00075     int64_t last_pts;
00076     int64_t pts;
00077 } XMVVideoPacket;
00078 
00079 typedef struct XMVAudioPacket {
00080     /* The decoder stream index for this audio packet. */
00081     int stream_index;
00082 
00083     /* The audio track this packet encodes. */
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_close(AVFormatContext *s)
00130 {
00131     XMVDemuxContext *xmv = s->priv_data;
00132 
00133     av_free(xmv->audio);
00134     av_free(xmv->audio_tracks);
00135 
00136     return 0;
00137 }
00138 
00139 static int xmv_read_header(AVFormatContext *s,
00140                            AVFormatParameters *ap)
00141 {
00142     XMVDemuxContext *xmv = s->priv_data;
00143     AVIOContext     *pb  = s->pb;
00144     AVStream        *vst = NULL;
00145 
00146     uint32_t file_version;
00147     uint32_t this_packet_size;
00148     uint16_t audio_track;
00149     int ret;
00150 
00151     avio_skip(pb, 4); /* Next packet size */
00152 
00153     this_packet_size = avio_rl32(pb);
00154 
00155     avio_skip(pb, 4); /* Max packet size */
00156     avio_skip(pb, 4); /* "xobX" */
00157 
00158     file_version = avio_rl32(pb);
00159     if ((file_version != 4) && (file_version != 2))
00160         av_log_ask_for_sample(s, "Found uncommon version %d\n", file_version);
00161 
00162 
00163     /* Video track */
00164 
00165     vst = avformat_new_stream(s, NULL);
00166     if (!vst)
00167         return AVERROR(ENOMEM);
00168 
00169     avpriv_set_pts_info(vst, 32, 1, 1000);
00170 
00171     vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00172     vst->codec->codec_id   = CODEC_ID_WMV2;
00173     vst->codec->codec_tag  = MKBETAG('W', 'M', 'V', '2');
00174     vst->codec->width      = avio_rl32(pb);
00175     vst->codec->height     = avio_rl32(pb);
00176 
00177     vst->duration          = avio_rl32(pb);
00178 
00179     xmv->video.stream_index = vst->index;
00180 
00181     /* Audio tracks */
00182 
00183     xmv->audio_track_count = avio_rl16(pb);
00184 
00185     avio_skip(pb, 2); /* Unknown (padding?) */
00186 
00187     xmv->audio_tracks = av_malloc(xmv->audio_track_count * sizeof(XMVAudioTrack));
00188     if (!xmv->audio_tracks)
00189         return AVERROR(ENOMEM);
00190 
00191     xmv->audio = av_malloc(xmv->audio_track_count * sizeof(XMVAudioPacket));
00192     if (!xmv->audio) {
00193         ret = AVERROR(ENOMEM);
00194         goto fail;
00195     }
00196 
00197     for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) {
00198         XMVAudioTrack  *track  = &xmv->audio_tracks[audio_track];
00199         XMVAudioPacket *packet = &xmv->audio       [audio_track];
00200         AVStream *ast = NULL;
00201 
00202         track->compression     = avio_rl16(pb);
00203         track->channels        = avio_rl16(pb);
00204         track->sample_rate     = avio_rl32(pb);
00205         track->bits_per_sample = avio_rl16(pb);
00206         track->flags           = avio_rl16(pb);
00207 
00208         track->bit_rate      = track->bits_per_sample *
00209                                track->sample_rate *
00210                                track->channels;
00211         track->block_align   = 36 * track->channels;
00212         track->block_samples = 64;
00213         track->codec_id      = ff_wav_codec_get_id(track->compression,
00214                                                    track->bits_per_sample);
00215 
00216         packet->track        = track;
00217         packet->stream_index = -1;
00218 
00219         packet->frame_size  = 0;
00220         packet->block_count = 0;
00221 
00222         /* TODO: ADPCM'd 5.1 sound is encoded in three separate streams.
00223          *       Those need to be interleaved to a proper 5.1 stream. */
00224         if (track->flags & XMV_AUDIO_ADPCM51)
00225             av_log(s, AV_LOG_WARNING, "Unsupported 5.1 ADPCM audio stream "
00226                                       "(0x%04X)\n", track->flags);
00227 
00228         if (!track->channels || !track->sample_rate) {
00229             av_log(s, AV_LOG_ERROR, "Invalid parameters for audio track %d.\n",
00230                    audio_track);
00231             ret = AVERROR_INVALIDDATA;
00232             goto fail;
00233         }
00234 
00235         ast = avformat_new_stream(s, NULL);
00236         if (!ast) {
00237             ret = AVERROR(ENOMEM);
00238             goto fail;
00239         }
00240 
00241         ast->codec->codec_type            = AVMEDIA_TYPE_AUDIO;
00242         ast->codec->codec_id              = track->codec_id;
00243         ast->codec->codec_tag             = track->compression;
00244         ast->codec->channels              = track->channels;
00245         ast->codec->sample_rate           = track->sample_rate;
00246         ast->codec->bits_per_coded_sample = track->bits_per_sample;
00247         ast->codec->bit_rate              = track->bit_rate;
00248         ast->codec->block_align           = 36 * track->channels;
00249 
00250         avpriv_set_pts_info(ast, 32, track->block_samples, track->sample_rate);
00251 
00252         packet->stream_index = ast->index;
00253 
00254         ast->duration = vst->duration;
00255     }
00256 
00257 
00260     xmv->next_packet_offset = avio_tell(pb);
00261     xmv->next_packet_size   = this_packet_size - xmv->next_packet_offset;
00262     xmv->stream_count       = xmv->audio_track_count + 1;
00263 
00264     return 0;
00265 
00266 fail:
00267     xmv_read_close(s);
00268     return ret;
00269 }
00270 
00271 static void xmv_read_extradata(uint8_t *extradata, AVIOContext *pb)
00272 {
00273     /* Read the XMV extradata */
00274 
00275     uint32_t data = avio_rl32(pb);
00276 
00277     int mspel_bit        = !!(data & 0x01);
00278     int loop_filter      = !!(data & 0x02);
00279     int abt_flag         = !!(data & 0x04);
00280     int j_type_bit       = !!(data & 0x08);
00281     int top_left_mv_flag = !!(data & 0x10);
00282     int per_mb_rl_bit    = !!(data & 0x20);
00283     int slice_count      = (data >> 6) & 7;
00284 
00285     /* Write it back as standard WMV2 extradata */
00286 
00287     data = 0;
00288 
00289     data |= mspel_bit        << 15;
00290     data |= loop_filter      << 14;
00291     data |= abt_flag         << 13;
00292     data |= j_type_bit       << 12;
00293     data |= top_left_mv_flag << 11;
00294     data |= per_mb_rl_bit    << 10;
00295     data |= slice_count      <<  7;
00296 
00297     AV_WB32(extradata, data);
00298 }
00299 
00300 static int xmv_process_packet_header(AVFormatContext *s)
00301 {
00302     XMVDemuxContext *xmv = s->priv_data;
00303     AVIOContext     *pb  = s->pb;
00304 
00305     uint8_t  data[8];
00306     uint16_t audio_track;
00307     uint32_t data_offset;
00308 
00309     /* Next packet size */
00310     xmv->next_packet_size = avio_rl32(pb);
00311 
00312     /* Packet video header */
00313 
00314     if (avio_read(pb, data, 8) != 8)
00315         return AVERROR(EIO);
00316 
00317     xmv->video.data_size     = AV_RL32(data) & 0x007FFFFF;
00318 
00319     xmv->video.current_frame = 0;
00320     xmv->video.frame_count   = (AV_RL32(data) >> 23) & 0xFF;
00321 
00322     xmv->video.has_extradata = (data[3] & 0x80) != 0;
00323 
00324     /* Adding the audio data sizes and the video data size keeps you 4 bytes
00325      * short for every audio track. But as playing around with XMV files with
00326      * ADPCM audio showed, taking the extra 4 bytes from the audio data gives
00327      * you either completely distorted audio or click (when skipping the
00328      * remaining 68 bytes of the ADPCM block). Substracting 4 bytes for every
00329      * audio track from the video data works at least for the audio. Probably
00330      * some alignment thing?
00331      * The video data has (always?) lots of padding, so it should work out...
00332      */
00333     xmv->video.data_size -= xmv->audio_track_count * 4;
00334 
00335     xmv->current_stream = 0;
00336     if (!xmv->video.frame_count) {
00337         xmv->video.frame_count = 1;
00338         xmv->current_stream    = 1;
00339     }
00340 
00341     /* Packet audio header */
00342 
00343     for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) {
00344         XMVAudioPacket *packet = &xmv->audio[audio_track];
00345 
00346         if (avio_read(pb, data, 4) != 4)
00347             return AVERROR(EIO);
00348 
00349         packet->data_size = AV_RL32(data) & 0x007FFFFF;
00350         if ((packet->data_size == 0) && (audio_track != 0))
00351             /* This happens when I create an XMV with several identical audio
00352              * streams. From the size calculations, duplicating the previous
00353              * stream's size works out, but the track data itself is silent.
00354              * Maybe this should also redirect the offset to the previous track?
00355              */
00356             packet->data_size = xmv->audio[audio_track - 1].data_size;
00357 
00359         packet->frame_size  = packet->data_size  / xmv->video.frame_count;
00360         packet->frame_size -= packet->frame_size % packet->track->block_align;
00361     }
00362 
00363     /* Packet data offsets */
00364 
00365     data_offset = avio_tell(pb);
00366 
00367     xmv->video.data_offset = data_offset;
00368     data_offset += xmv->video.data_size;
00369 
00370     for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) {
00371         xmv->audio[audio_track].data_offset = data_offset;
00372         data_offset += xmv->audio[audio_track].data_size;
00373     }
00374 
00375     /* Video frames header */
00376 
00377     /* Read new video extra data */
00378     if (xmv->video.data_size > 0) {
00379         if (xmv->video.has_extradata) {
00380             xmv_read_extradata(xmv->video.extradata, pb);
00381 
00382             xmv->video.data_size   -= 4;
00383             xmv->video.data_offset += 4;
00384 
00385             if (xmv->video.stream_index >= 0) {
00386                 AVStream *vst = s->streams[xmv->video.stream_index];
00387 
00388                 assert(xmv->video.stream_index < s->nb_streams);
00389 
00390                 if (vst->codec->extradata_size < 4) {
00391                     av_free(vst->codec->extradata);
00392 
00393                     vst->codec->extradata =
00394                         av_malloc(4 + FF_INPUT_BUFFER_PADDING_SIZE);
00395                     vst->codec->extradata_size = 4;
00396                 }
00397 
00398                 memcpy(vst->codec->extradata, xmv->video.extradata, 4);
00399             }
00400         }
00401     }
00402 
00403     return 0;
00404 }
00405 
00406 static int xmv_fetch_new_packet(AVFormatContext *s)
00407 {
00408     XMVDemuxContext *xmv = s->priv_data;
00409     AVIOContext     *pb  = s->pb;
00410     int result;
00411 
00412     /* Seek to it */
00413     xmv->this_packet_offset = xmv->next_packet_offset;
00414     if (avio_seek(pb, xmv->this_packet_offset, SEEK_SET) != xmv->this_packet_offset)
00415         return AVERROR(EIO);
00416 
00417     /* Update the size */
00418     xmv->this_packet_size = xmv->next_packet_size;
00419     if (xmv->this_packet_size < (12 + xmv->audio_track_count * 4))
00420         return AVERROR(EIO);
00421 
00422     /* Process the header */
00423     result = xmv_process_packet_header(s);
00424     if (result)
00425         return result;
00426 
00427     /* Update the offset */
00428     xmv->next_packet_offset = xmv->this_packet_offset + xmv->this_packet_size;
00429 
00430     return 0;
00431 }
00432 
00433 static int xmv_fetch_audio_packet(AVFormatContext *s,
00434                                   AVPacket *pkt, uint32_t stream)
00435 {
00436     XMVDemuxContext *xmv   = s->priv_data;
00437     AVIOContext     *pb    = s->pb;
00438     XMVAudioPacket  *audio = &xmv->audio[stream];
00439 
00440     uint32_t data_size;
00441     uint32_t block_count;
00442     int result;
00443 
00444     /* Seek to it */
00445     if (avio_seek(pb, audio->data_offset, SEEK_SET) != audio->data_offset)
00446         return AVERROR(EIO);
00447 
00448     if ((xmv->video.current_frame + 1) < xmv->video.frame_count)
00449         /* Not the last frame, get at most frame_size bytes. */
00450         data_size = FFMIN(audio->frame_size, audio->data_size);
00451     else
00452         /* Last frame, get the rest. */
00453         data_size = audio->data_size;
00454 
00455     /* Read the packet */
00456     result = av_get_packet(pb, pkt, data_size);
00457     if (result <= 0)
00458         return result;
00459 
00460     pkt->stream_index = audio->stream_index;
00461 
00462     /* Calculate the PTS */
00463 
00464     block_count = data_size / audio->track->block_align;
00465 
00466     pkt->duration = block_count;
00467     pkt->pts      = audio->block_count;
00468     pkt->dts      = AV_NOPTS_VALUE;
00469 
00470     audio->block_count += block_count;
00471 
00472     /* Advance offset */
00473     audio->data_size   -= data_size;
00474     audio->data_offset += data_size;
00475 
00476     return 0;
00477 }
00478 
00479 static int xmv_fetch_video_packet(AVFormatContext *s,
00480                                   AVPacket *pkt)
00481 {
00482     XMVDemuxContext *xmv   = s->priv_data;
00483     AVIOContext     *pb    = s->pb;
00484     XMVVideoPacket  *video = &xmv->video;
00485 
00486     int result;
00487     uint32_t frame_header;
00488     uint32_t frame_size, frame_timestamp;
00489     uint32_t i;
00490 
00491     /* Seek to it */
00492     if (avio_seek(pb, video->data_offset, SEEK_SET) != video->data_offset)
00493         return AVERROR(EIO);
00494 
00495     /* Read the frame header */
00496     frame_header = avio_rl32(pb);
00497 
00498     frame_size      = (frame_header & 0x1FFFF) * 4 + 4;
00499     frame_timestamp = (frame_header >> 17);
00500 
00501     if ((frame_size + 4) > video->data_size)
00502         return AVERROR(EIO);
00503 
00504     /* Create the packet */
00505     result = av_new_packet(pkt, frame_size);
00506     if (result)
00507         return result;
00508 
00509     /* Contrary to normal WMV2 video, the bit stream in XMV's
00510      * WMV2 is little-endian.
00511      * TODO: This manual swap is of course suboptimal.
00512      */
00513     for (i = 0; i < frame_size; i += 4)
00514         AV_WB32(pkt->data + i, avio_rl32(pb));
00515 
00516     pkt->stream_index = video->stream_index;
00517 
00518     /* Calculate the PTS */
00519 
00520     video->last_pts = frame_timestamp + video->pts;
00521 
00522     pkt->duration = 0;
00523     pkt->pts      = video->last_pts;
00524     pkt->dts      = AV_NOPTS_VALUE;
00525 
00526     video->pts += frame_timestamp;
00527 
00528     /* Keyframe? */
00529     pkt->flags = (pkt->data[0] & 0x80) ? 0 : AV_PKT_FLAG_KEY;
00530 
00531     /* Advance offset */
00532     video->data_size   -= frame_size + 4;
00533     video->data_offset += frame_size + 4;
00534 
00535     return 0;
00536 }
00537 
00538 static int xmv_read_packet(AVFormatContext *s,
00539                            AVPacket *pkt)
00540 {
00541     XMVDemuxContext *xmv = s->priv_data;
00542     int result;
00543 
00544     if (xmv->video.current_frame == xmv->video.frame_count) {
00545         /* No frames left in this packet, so we fetch a new one */
00546 
00547         result = xmv_fetch_new_packet(s);
00548         if (result)
00549             return result;
00550     }
00551 
00552     if (xmv->current_stream == 0) {
00553         /* Fetch a video frame */
00554 
00555         result = xmv_fetch_video_packet(s, pkt);
00556         if (result)
00557             return result;
00558 
00559     } else {
00560         /* Fetch an audio frame */
00561 
00562         result = xmv_fetch_audio_packet(s, pkt, xmv->current_stream - 1);
00563         if (result)
00564             return result;
00565     }
00566 
00567     /* Increase our counters */
00568     if (++xmv->current_stream >= xmv->stream_count) {
00569         xmv->current_stream       = 0;
00570         xmv->video.current_frame += 1;
00571     }
00572 
00573     return 0;
00574 }
00575 
00576 AVInputFormat ff_xmv_demuxer = {
00577     .name           = "xmv",
00578     .long_name      = NULL_IF_CONFIG_SMALL("Microsoft XMV"),
00579     .priv_data_size = sizeof(XMVDemuxContext),
00580     .read_probe     = xmv_probe,
00581     .read_header    = xmv_read_header,
00582     .read_packet    = xmv_read_packet,
00583     .read_close     = xmv_read_close,
00584 };