* Microsoft XMV demuxer
*/
-#include <stdint.h>
+#include <inttypes.h>
#include "libavutil/intreadwrite.h"
#include "avformat.h"
+#include "internal.h"
#include "riff.h"
#define XMV_MIN_HEADER_SIZE 36
XMV_AUDIO_ADPCM51_FRONTCENTERLOW | \
XMV_AUDIO_ADPCM51_REARLEFTRIGHT)
+#define XMV_BLOCK_ALIGN_SIZE 36
+
typedef struct XMVAudioTrack {
uint16_t compression;
uint16_t channels;
uint16_t block_align;
uint16_t block_samples;
- enum CodecID codec_id;
+ enum AVCodecID codec_id;
} XMVAudioTrack;
typedef struct XMVVideoPacket {
return 0;
}
-static int xmv_read_header(AVFormatContext *s,
- AVFormatParameters *ap)
+static int xmv_read_close(AVFormatContext *s)
+{
+ XMVDemuxContext *xmv = s->priv_data;
+
+ av_free(xmv->audio);
+ av_free(xmv->audio_tracks);
+
+ return 0;
+}
+
+static int xmv_read_header(AVFormatContext *s)
{
XMVDemuxContext *xmv = s->priv_data;
AVIOContext *pb = s->pb;
uint32_t file_version;
uint32_t this_packet_size;
uint16_t audio_track;
+ int ret;
avio_skip(pb, 4); /* Next packet size */
file_version = avio_rl32(pb);
if ((file_version != 4) && (file_version != 2))
- av_log_ask_for_sample(s, "Found uncommon version %d\n", file_version);
+ avpriv_request_sample(s, "Uncommon version %"PRIu32"", file_version);
/* Video track */
- vst = av_new_stream(s, 0);
+ vst = avformat_new_stream(s, NULL);
if (!vst)
return AVERROR(ENOMEM);
- av_set_pts_info(vst, 32, 1, 1000);
+ avpriv_set_pts_info(vst, 32, 1, 1000);
- vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
- vst->codec->codec_id = CODEC_ID_WMV2;
- vst->codec->codec_tag = MKBETAG('W', 'M', 'V', '2');
- vst->codec->width = avio_rl32(pb);
- vst->codec->height = avio_rl32(pb);
+ vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+ vst->codecpar->codec_id = AV_CODEC_ID_WMV2;
+ vst->codecpar->codec_tag = MKBETAG('W', 'M', 'V', '2');
+ vst->codecpar->width = avio_rl32(pb);
+ vst->codecpar->height = avio_rl32(pb);
vst->duration = avio_rl32(pb);
return AVERROR(ENOMEM);
xmv->audio = av_malloc(xmv->audio_track_count * sizeof(XMVAudioPacket));
- if (!xmv->audio)
- return AVERROR(ENOMEM);
+ if (!xmv->audio) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) {
XMVAudioTrack *track = &xmv->audio_tracks[audio_track];
track->bit_rate = track->bits_per_sample *
track->sample_rate *
track->channels;
- track->block_align = 36 * track->channels;
+ track->block_align = XMV_BLOCK_ALIGN_SIZE * track->channels;
track->block_samples = 64;
track->codec_id = ff_wav_codec_get_id(track->compression,
track->bits_per_sample);
av_log(s, AV_LOG_WARNING, "Unsupported 5.1 ADPCM audio stream "
"(0x%04X)\n", track->flags);
- ast = av_new_stream(s, audio_track);
- if (!ast)
- return AVERROR(ENOMEM);
+ if (!track->channels || !track->sample_rate ||
+ track->channels >= UINT16_MAX / XMV_BLOCK_ALIGN_SIZE) {
+ av_log(s, AV_LOG_ERROR, "Invalid parameters for audio track %"PRIu16".\n",
+ audio_track);
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
+ ast = avformat_new_stream(s, NULL);
+ if (!ast) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
- ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
- ast->codec->codec_id = track->codec_id;
- ast->codec->codec_tag = track->compression;
- ast->codec->channels = track->channels;
- ast->codec->sample_rate = track->sample_rate;
- ast->codec->bits_per_coded_sample = track->bits_per_sample;
- ast->codec->bit_rate = track->bit_rate;
- ast->codec->block_align = 36 * track->channels;
+ ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+ ast->codecpar->codec_id = track->codec_id;
+ ast->codecpar->codec_tag = track->compression;
+ ast->codecpar->channels = track->channels;
+ ast->codecpar->sample_rate = track->sample_rate;
+ ast->codecpar->bits_per_coded_sample = track->bits_per_sample;
+ ast->codecpar->bit_rate = track->bit_rate;
+ ast->codecpar->block_align = 36 * track->channels;
- av_set_pts_info(ast, 32, track->block_samples, track->sample_rate);
+ avpriv_set_pts_info(ast, 32, track->block_samples, track->sample_rate);
packet->stream_index = ast->index;
/** 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;
- xmv->stream_count = xmv->audio_track_count + 1;
+ xmv->next_packet_size = this_packet_size - xmv->next_packet_offset;
+ xmv->stream_count = xmv->audio_track_count + 1;
return 0;
+
+fail:
+ xmv_read_close(s);
+ return ret;
}
static void xmv_read_extradata(uint8_t *extradata, AVIOContext *pb)
* short for every audio track. But as playing around with XMV files with
* ADPCM audio showed, taking the extra 4 bytes from the audio data gives
* you either completely distorted audio or click (when skipping the
- * remaining 68 bytes of the ADPCM block). Substracting 4 bytes for every
+ * remaining 68 bytes of the ADPCM block). Subtracting 4 bytes for every
* audio track from the video data works at least for the audio. Probably
* some alignment thing?
* The video data has (always?) lots of padding, so it should work out...
assert(xmv->video.stream_index < s->nb_streams);
- if (vst->codec->extradata_size < 4) {
- av_free(vst->codec->extradata);
+ if (vst->codecpar->extradata_size < 4) {
+ av_free(vst->codecpar->extradata);
- vst->codec->extradata =
- av_malloc(4 + FF_INPUT_BUFFER_PADDING_SIZE);
- vst->codec->extradata_size = 4;
+ vst->codecpar->extradata =
+ av_malloc(4 + AV_INPUT_BUFFER_PADDING_SIZE);
+ vst->codecpar->extradata_size = 4;
}
- memcpy(vst->codec->extradata, xmv->video.extradata, 4);
+ memcpy(vst->codecpar->extradata, xmv->video.extradata, 4);
}
}
}
return 0;
}
-static int xmv_read_close(AVFormatContext *s)
-{
- XMVDemuxContext *xmv = s->priv_data;
-
- av_free(xmv->audio);
- av_free(xmv->audio_tracks);
-
- return 0;
-}
-
AVInputFormat ff_xmv_demuxer = {
.name = "xmv",
.long_name = NULL_IF_CONFIG_SMALL("Microsoft XMV"),