From patchwork Tue Oct 3 21:49:00 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: bananaman255@gmail.com X-Patchwork-Id: 5402 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.161.76 with SMTP id m12csp137610jah; Tue, 3 Oct 2017 14:58:20 -0700 (PDT) X-Received: by 10.28.191.138 with SMTP id o10mr13281093wmi.61.1507067900003; Tue, 03 Oct 2017 14:58:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1507067899; cv=none; d=google.com; s=arc-20160816; b=DGyCBRNDvpBekU4u5+I8MmvSU2PPP/ANY9wc/9OEKTepOMb8vds5BfM8bdNTUcM+t8 OER6q+mwCfB0eY42mPdnbyuEzzzL4BH2oSeukmW1rC5oShx36aPp0lIjwzHDmSGHU7P4 65EgrYg302xyzRO2VWbCoQCcwGRL6ftBrrlbaOaYwT27/6TRr6OMvFwDBo1+Pg9bDNaE JvanyH7YbsQ7sfTg196iGXZ9v/gHYZGTLJ02SNBGhJ2qK1JyPYDJ2DEqVQAz1fMbfV5F Rh7FgHeW2wf+iAJO6VrBmjs0C3LPiwhKb/+IsJXDa5EKl99WiXP7edHfdsNs3Be+JONB yWmw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:message-id:date:to:from:dkim-signature :delivered-to:arc-authentication-results; bh=7gFgJu7uGJhRgiqmLLJQ0HR7zGBeGrI2DI/SNvshOyQ=; b=H88t4XBRaHUmOgmbhu+KBFHZcY660EGbIkT8mm7+ilXqUs04UEokT8IX+a/GvRBJu5 yynWGvXUqQG39qslEYc1HocsWJsaGfWYm9tz1KJoIr8quOnpcQC7Oj/CtwV0TT0s/gey Y5r/XJSSnGyY+dcQFJYZGwR9k+lquupjt7Zyf/IS3Ad5XNRi50r4K8/6VrE1WpXw4N8E z7zSuYabc5TBKXRxIvYV2mpqXenE6rmexDZUycF9F74nC3xZdIazLbc6b6WTnFH4e2xX KPscsSpELHbQAc3z3dCR/sD4+VXtKLNjfnLxeSsNQizjYjrB85Sz2ds9Z8b16oR0PdRp dGYA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=Jwp3JWW6; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id d14si7381044wmh.241.2017.10.03.14.58.18; Tue, 03 Oct 2017 14:58:19 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=Jwp3JWW6; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E49F468A127; Wed, 4 Oct 2017 00:58:00 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm0-f68.google.com (mail-wm0-f68.google.com [74.125.82.68]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id D414968A03F for ; Wed, 4 Oct 2017 00:57:54 +0300 (EEST) Received: by mail-wm0-f68.google.com with SMTP id t69so19294880wmt.2 for ; Tue, 03 Oct 2017 14:58:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=JquYQJjS9Q6ILgLz8VHIxtEm9EdFTPxWgVIV5MBEbPs=; b=Jwp3JWW6hqIXrL+f3i/6KHhiWLBv02QcNwWiHZ069KCByERSSQbHkQ5xJ7HH7lEUWC 36SD2B0X6Xs9LHU0Cp9hWrwHecpmnqJm4fJwc1EspJYx6mx+1XsRG0bPji4RDAVxZbt3 HmNnFalfI5gg+wYDgWQ7dIJoiv+0ZRjiO3DISIpm4s5apKKdIM1IcS4nlF+OKqqluwak 85JXdBu6Vs2zgMSo5Hhq/fwUU2SF++TYinUVkxZef0G0uzEW0qV+E4nEAHRgufK3AVrg KXvTf02IfcvNTzfMmLONXeL2eJgYwi1LAfnxK6LkfPnmCnOwwsS2ijYgIHq1KNzS2BAv UWsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=JquYQJjS9Q6ILgLz8VHIxtEm9EdFTPxWgVIV5MBEbPs=; b=QQKB8aqjNkJD//VGmsRflDEFAD/lj8m6bcbEKpRwQdZzzpOJGngw+OoJzVd3rof2xO zWZKP+VeikGNCMUy9Rxyo7I/fXLoPPjnMBAJ/IWeFiApdH5n+bGDVEOZo57Gl3EsvYvr agOpxRQMCjWEgWDRNgMAU6VpT7bsG+UaIP7He1JRB6jyELhx4RZLy8T6Lhiogc+Ip+HV ZL0GBHfOhKGZxcuQZyLBtC82SZo7Q1EwuWlt0Vq6IHfedyaa66ySTUC6Itt5gvVHzRRQ BpHhYYWYeCQzNl2yWXo4tHm0cmaSQqm5MyLnvGunz40HY9LSTmcd2pUWxEgcRJTjEZwO Bluw== X-Gm-Message-State: AMCzsaXjFIjt+L2D15wbzByyUEa+aypyfDDU3VjWKA281hY/o4fND2pV J9qh+JMTjA6n7Bpkc9InDHlG4A== X-Google-Smtp-Source: AOwi7QD5nMUud0SkwIql31Aj1iSc6V4oSHFgEf+ljnlYRqnibQbUWAyoDu9xZ5F+J3/R28+NL65uaw== X-Received: by 10.28.74.89 with SMTP id x86mr14404621wma.57.1507067412887; Tue, 03 Oct 2017 14:50:12 -0700 (PDT) Received: from localhost.localdomain (4.91.134.37.dynamic.jazztel.es. [37.134.91.4]) by smtp.googlemail.com with ESMTPSA id e17sm30345728wmf.46.2017.10.03.14.50.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 03 Oct 2017 14:50:11 -0700 (PDT) From: bananaman255@gmail.com To: ffmpeg-devel@ffmpeg.org Date: Tue, 3 Oct 2017 23:49:00 +0200 Message-Id: <20171003214900.1936-1-bananaman255@gmail.com> X-Mailer: git-send-email 2.11.0.windows.3 Subject: [FFmpeg-devel] [PATCH] avcodec/wmaprodec: support multichannel XMA stream configurations X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: bnnm MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: bnnm Signed-off-by: bnnm Now accepts any combination of 1/2ch streams, described in the RIFF chunks/extradata --- libavcodec/wmaprodec.c | 151 ++++++++++++++++++++++++++++++++----------------- libavformat/wavdec.c | 20 ++++--- 2 files changed, 112 insertions(+), 59 deletions(-) diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c index 5c99628c52..77a49c9db8 100644 --- a/libavcodec/wmaprodec.c +++ b/libavcodec/wmaprodec.c @@ -106,6 +106,9 @@ #define MAX_SUBFRAMES 32 ///< max number of subframes per channel #define MAX_BANDS 29 ///< max number of scale factor bands #define MAX_FRAMESIZE 32768 ///< maximum compressed frame size +#define XMA_MAX_STREAMS 8 +#define XMA_MAX_CHANNELS 8 +#define XMA_MAX_CHANNELS_STREAM 2 #define WMAPRO_BLOCK_MIN_BITS 6 ///< log2 of min block size #define WMAPRO_BLOCK_MAX_BITS 13 ///< log2 of max block size @@ -215,7 +218,7 @@ typedef struct WMAProDecodeCtx { uint8_t drc_gain; ///< gain for the DRC tool int8_t skip_frame; ///< skip output step int8_t parsed_all_subframes; ///< all subframes decoded? - uint8_t skip_packets; + uint8_t skip_packets; ///< packets to skip to find next packet in a stream (XMA1/2) /* subframe/block decode state */ int16_t subframe_len; ///< current subframe length @@ -235,11 +238,13 @@ typedef struct WMAProDecodeCtx { } WMAProDecodeCtx; typedef struct XMADecodeCtx { - WMAProDecodeCtx xma[4]; - AVFrame *frames[4]; + WMAProDecodeCtx xma[XMA_MAX_STREAMS]; + AVFrame *frames[XMA_MAX_STREAMS]; int current_stream; - float samples[8][512 * 64]; - int offset[4]; + int num_streams; + float samples[XMA_MAX_CHANNELS][512 * 64]; + int offset[XMA_MAX_STREAMS]; + int start_channel[XMA_MAX_STREAMS]; } XMADecodeCtx; /** @@ -306,7 +311,7 @@ static av_cold int get_rate(AVCodecContext *avctx) *@param avctx codec context *@return 0 on success, -1 otherwise */ -static av_cold int decode_init(WMAProDecodeCtx *s, AVCodecContext *avctx) +static av_cold int decode_init(WMAProDecodeCtx *s, AVCodecContext *avctx, int num_stream) { uint8_t *edata_ptr = avctx->extradata; unsigned int channel_mask; @@ -333,18 +338,30 @@ static av_cold int decode_init(WMAProDecodeCtx *s, AVCodecContext *avctx) for (i = 0; i < avctx->extradata_size; i++) av_log(avctx, AV_LOG_DEBUG, "[%x] ", avctx->extradata[i]); av_log(avctx, AV_LOG_DEBUG, "\n"); - if (avctx->codec_id == AV_CODEC_ID_XMA2 && (!avctx->extradata || avctx->extradata_size >= 6)) { + + if (avctx->codec_id == AV_CODEC_ID_XMA2 && avctx->extradata_size == 34) { /* XMA2WAVEFORMATEX */ + s->decode_flags = 0x10d6; + s->bits_per_sample = 16; + channel_mask = 0; //AV_RL32(edata_ptr+2); /* not always in expected order */ + if ((num_stream+1) * XMA_MAX_CHANNELS_STREAM > avctx->channels) /* stream config is 2ch + 2ch + ... + 1/2ch */ + s->nb_channels = 1; + else + s->nb_channels = 2; + } else if (avctx->codec_id == AV_CODEC_ID_XMA2) { /* XMA2WAVEFORMAT */ s->decode_flags = 0x10d6; - channel_mask = avctx->extradata ? AV_RL32(edata_ptr+2) : 0; s->bits_per_sample = 16; - } else if (avctx->codec_id == AV_CODEC_ID_XMA1) { + channel_mask = 0; /* would need to aggregate from all streams */ + s->nb_channels = edata_ptr[32 + ((edata_ptr[0]==3)?0:8) + 4*num_stream + 0]; /* nth stream config */ + } else if (avctx->codec_id == AV_CODEC_ID_XMA1) { /* XMAWAVEFORMAT */ s->decode_flags = 0x10d6; s->bits_per_sample = 16; - channel_mask = 0; - } else if (avctx->codec_id == AV_CODEC_ID_WMAPRO && avctx->extradata_size >= 18) { + channel_mask = 0; /* would need to aggregate from all streams */ + s->nb_channels = edata_ptr[8 + 20*num_stream + 17]; /* nth stream config */ + } else if (avctx->codec_id == AV_CODEC_ID_WMAPRO && avctx->extradata_size >= 18) { s->decode_flags = AV_RL16(edata_ptr+14); channel_mask = AV_RL32(edata_ptr+2); s->bits_per_sample = AV_RL16(edata_ptr); + s->nb_channels = avctx->channels; if (s->bits_per_sample > 32 || s->bits_per_sample < 1) { avpriv_request_sample(avctx, "bits per sample is %d", s->bits_per_sample); @@ -355,12 +372,6 @@ static av_cold int decode_init(WMAProDecodeCtx *s, AVCodecContext *avctx) return AVERROR_PATCHWELCOME; } - if (avctx->codec_id != AV_CODEC_ID_WMAPRO && avctx->channels > 2) { - s->nb_channels = 2; - } else { - s->nb_channels = avctx->channels; - } - /** generic init */ s->log2_frame_size = av_log2(avctx->block_align) + 4; if (s->log2_frame_size > 25) { @@ -421,6 +432,10 @@ static av_cold int decode_init(WMAProDecodeCtx *s, AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "invalid number of channels %d\n", s->nb_channels); return AVERROR_INVALIDDATA; + } else if (avctx->codec_id != AV_CODEC_ID_WMAPRO && s->nb_channels > XMA_MAX_CHANNELS_STREAM) { + av_log(avctx, AV_LOG_ERROR, "invalid number of channels per XMA stream %d\n", + s->nb_channels); + return AVERROR_INVALIDDATA; } else if (s->nb_channels > WMAPRO_MAX_CHANNELS) { avpriv_request_sample(avctx, "More than %d channels", WMAPRO_MAX_CHANNELS); @@ -566,7 +581,7 @@ static av_cold int wmapro_decode_init(AVCodecContext *avctx) { WMAProDecodeCtx *s = avctx->priv_data; - return decode_init(s, avctx); + return decode_init(s, avctx, 0); } /** @@ -1750,14 +1765,17 @@ static int xma_decode_packet(AVCodecContext *avctx, void *data, AVFrame *frame = data; int i, ret, offset = INT_MAX; + /* decode current stream packet */ ret = decode_packet(avctx, &s->xma[s->current_stream], s->frames[s->current_stream], &got_stream_frame_ptr, avpkt); + /* copy stream samples (1/2ch) to sample buffer (Nch) */ if (got_stream_frame_ptr) { - memcpy(&s->samples[s->current_stream * 2 + 0][s->offset[s->current_stream] * 512], + int start_ch = s->start_channel[s->current_stream]; + memcpy(&s->samples[start_ch + 0][s->offset[s->current_stream] * 512], s->frames[s->current_stream]->extended_data[0], 512 * 4); - if (avctx->channels > 1) - memcpy(&s->samples[s->current_stream * 2 + 1][s->offset[s->current_stream] * 512], + if (s->xma[s->current_stream].nb_channels > 1) + memcpy(&s->samples[start_ch + 1][s->offset[s->current_stream] * 512], s->frames[s->current_stream]->extended_data[1], 512 * 4); s->offset[s->current_stream]++; } else if (ret < 0) { @@ -1766,58 +1784,57 @@ static int xma_decode_packet(AVCodecContext *avctx, void *data, return ret; } + /* find next XMA packet's owner stream, and update. + * XMA streams find their packets following packet_skips + * (at start there is one packet per stream, then interleave non-linearly). */ if (s->xma[s->current_stream].packet_done || s->xma[s->current_stream].packet_loss) { - int bret; - - if (s->xma[s->current_stream].skip_packets == 0) { - ; - } else if (s->xma[0].skip_packets == 0 && avctx->channels >= 2) { - s->current_stream = 0; - } else if (s->xma[1].skip_packets == 0 && avctx->channels >= 4) { - s->current_stream = 1; - } else if (s->xma[2].skip_packets == 0 && avctx->channels >= 6) { - s->current_stream = 2; - } else if (s->xma[3].skip_packets == 0 && avctx->channels == 8) { - s->current_stream = 3; - } else { + + /* select stream with 0 skip_packets (= uses next packet) */ + if (s->xma[s->current_stream].skip_packets != 0) { int min[2]; min[0] = s->xma[0].skip_packets; min[1] = i = 0; - for (i = 1; i < avctx->channels / 2; i++) { + for (i = 1; i < s->num_streams; i++) { if (s->xma[i].skip_packets < min[0]) { - min[1] = i; min[0] = s->xma[i].skip_packets; + min[1] = i; } } s->current_stream = min[1]; } - for (i = 0; i < avctx->channels / 2; i++) { + /* all other streams skip next packet */ + for (i = 0; i < s->num_streams; i++) { s->xma[i].skip_packets = FFMAX(0, s->xma[i].skip_packets - 1); } - for (i = 0; i < (avctx->channels + 1) / 2; i++) { + /* copy samples from buffer to output if possible */ + for (i = 0; i < s->num_streams; i++) { offset = FFMIN(offset, s->offset[i]); } - if (offset > 0) { + int bret; + frame->nb_samples = 512 * offset; if ((bret = ff_get_buffer(avctx, frame, 0)) < 0) return bret; - for (i = 0; i < (avctx->channels + 1) / 2; i++) { - memcpy(frame->extended_data[i * 2 + 0], s->samples[i * 2 + 0], frame->nb_samples * 4); - if (avctx->channels > 1) - memcpy(frame->extended_data[i * 2 + 1], s->samples[i * 2 + 1], frame->nb_samples * 4); + /* copy samples buffer (Nch) to frame samples (Nch), move unconsumed samples */ + for (i = 0; i < s->num_streams; i++) { + int start_ch = s->start_channel[i]; + memcpy(frame->extended_data[start_ch + 0], s->samples[start_ch + 0], frame->nb_samples * 4); + if (s->xma[i].nb_channels > 1) + memcpy(frame->extended_data[start_ch + 1], s->samples[start_ch + 1], frame->nb_samples * 4); + s->offset[i] -= offset; if (s->offset[i]) { - memmove(s->samples[i * 2 + 0], s->samples[i * 2 + 0] + frame->nb_samples, s->offset[i] * 4 * 512); - if (avctx->channels > 1) - memmove(s->samples[i * 2 + 1], s->samples[i * 2 + 1] + frame->nb_samples, s->offset[i] * 4 * 512); + memmove(s->samples[start_ch + 0], s->samples[start_ch + 0] + frame->nb_samples, s->offset[i] * 4 * 512); + if (s->xma[i].nb_channels > 1) + memmove(s->samples[start_ch + 1], s->samples[start_ch + 1] + frame->nb_samples, s->offset[i] * 4 * 512); } } @@ -1831,13 +1848,40 @@ static int xma_decode_packet(AVCodecContext *avctx, void *data, static av_cold int xma_decode_init(AVCodecContext *avctx) { XMADecodeCtx *s = avctx->priv_data; - int i, ret; + int i, ret, start_channels = 0; - if (avctx->channels <= 0 || avctx->channels > 8) + if (avctx->channels <= 0 || avctx->extradata_size == 0) return AVERROR_INVALIDDATA; - for (i = 0; i < (avctx->channels + 1) / 2; i++) { - ret = decode_init(&s->xma[i], avctx); + /* get stream config */ + if (avctx->codec_id == AV_CODEC_ID_XMA2 && avctx->extradata_size == 34) { /* XMA2WAVEFORMATEX */ + s->num_streams = (avctx->channels + 1) / 2; + } else if (avctx->codec_id == AV_CODEC_ID_XMA2 && avctx->extradata_size >= 2) { /* XMA2WAVEFORMAT */ + s->num_streams = avctx->extradata[1]; + if (avctx->extradata_size != (32 + ((avctx->extradata[0]==3)?0:8) + 4*s->num_streams)) { + av_log(avctx, AV_LOG_ERROR, "Incorrect XMA2 extradata size\n"); + return AVERROR(EINVAL); + } + } else if (avctx->codec_id == AV_CODEC_ID_XMA1 && avctx->extradata_size >= 4) { /* XMAWAVEFORMAT */ + s->num_streams = avctx->extradata[4]; + if (avctx->extradata_size != (8 + 20*s->num_streams)) { + av_log(avctx, AV_LOG_ERROR, "Incorrect XMA1 extradata size\n"); + return AVERROR(EINVAL); + } + } else { + av_log(avctx, AV_LOG_ERROR, "Incorrect XMA config\n"); + return AVERROR(EINVAL); + } + + /* encoder supports up to 64 streams / 64*2 channels (would have to alloc arrays) */ + if (avctx->channels > XMA_MAX_CHANNELS || s->num_streams > XMA_MAX_STREAMS) { + avpriv_request_sample(avctx, "More than %d channels in %d streams", XMA_MAX_CHANNELS, s->num_streams); + return AVERROR_PATCHWELCOME; + } + + /* init all streams (several streams of 1/2ch make Nch files) */ + for (i = 0; i < s->num_streams; i++) { + ret = decode_init(&s->xma[i], avctx, i); if (ret < 0) return ret; s->frames[i] = av_frame_alloc(); @@ -1848,6 +1892,8 @@ static av_cold int xma_decode_init(AVCodecContext *avctx) return AVERROR(ENOMEM); } + s->start_channel[i] = start_channels; + start_channels += s->xma[i].nb_channels; } return ret; @@ -1858,7 +1904,7 @@ static av_cold int xma_decode_end(AVCodecContext *avctx) XMADecodeCtx *s = avctx->priv_data; int i; - for (i = 0; i < avctx->channels / 2; i++) { + for (i = 0; i < s->num_streams; i++) { decode_end(&s->xma[i]); av_frame_free(&s->frames[i]); } @@ -1894,7 +1940,8 @@ static void xma_flush(AVCodecContext *avctx) { XMADecodeCtx *s = avctx->priv_data; int i; - for (i = 0; i < (avctx->channels + 1) / 2; i++) + + for (i = 0; i < s->num_streams; i++) flush(&s->xma[i]); memset(s->offset, 0, sizeof(s->offset)); diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c index 81dbc9f16e..b016185a1b 100644 --- a/libavformat/wavdec.c +++ b/libavformat/wavdec.c @@ -180,9 +180,9 @@ static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream **st) static int wav_parse_xma2_tag(AVFormatContext *s, int64_t size, AVStream **st) { AVIOContext *pb = s->pb; - int num_streams, i, channels = 0; + int version, num_streams, i, channels = 0; - if (size < 44) + if (size < 36) return AVERROR_INVALIDDATA; *st = avformat_new_stream(s, NULL); @@ -193,13 +193,17 @@ static int wav_parse_xma2_tag(AVFormatContext *s, int64_t size, AVStream **st) (*st)->codecpar->codec_id = AV_CODEC_ID_XMA2; (*st)->need_parsing = AVSTREAM_PARSE_FULL_RAW; - avio_skip(pb, 1); + version = avio_r8(pb); + if (version != 3 && version != 4) + return AVERROR_INVALIDDATA; num_streams = avio_r8(pb); - if (size < 40 + num_streams * 4) + if (size != (32 + ((version==3)?0:8) + 4*num_streams)) return AVERROR_INVALIDDATA; avio_skip(pb, 10); (*st)->codecpar->sample_rate = avio_rb32(pb); - avio_skip(pb, 12); + if (version == 4) + avio_skip(pb, 8); + avio_skip(pb, 4); (*st)->duration = avio_rb32(pb); avio_skip(pb, 8); @@ -213,9 +217,11 @@ static int wav_parse_xma2_tag(AVFormatContext *s, int64_t size, AVStream **st) return AVERROR_INVALIDDATA; avpriv_set_pts_info(*st, 64, 1, (*st)->codecpar->sample_rate); - if (ff_alloc_extradata((*st)->codecpar, 34)) + + avio_seek(pb, -size, SEEK_CUR); + av_freep(&(*st)->codecpar->extradata); + if (ff_get_extradata(s, (*st)->codecpar, pb, size) < 0) return AVERROR(ENOMEM); - memset((*st)->codecpar->extradata, 0, 34); return 0; }