Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHendrik Leppkes <h.leppkes@gmail.com>2013-07-13 12:27:34 +0400
committerHendrik Leppkes <h.leppkes@gmail.com>2017-08-04 20:12:12 +0300
commit10f5f18d174baf6fd15d9018b214cbb4d6a4bd92 (patch)
tree0071a89b18a383a39280b0662cd210061fe6088d
parentd48a3716785c12e6510ad61ccbf2c0520172db00 (diff)
matroskadec_haali: export full wavpack blocks
-rw-r--r--libavformat/matroskadec_haali.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/libavformat/matroskadec_haali.c b/libavformat/matroskadec_haali.c
index 2f4036a1bc..9648ebb223 100644
--- a/libavformat/matroskadec_haali.c
+++ b/libavformat/matroskadec_haali.c
@@ -963,6 +963,8 @@ static int mkv_generate_extradata(AVFormatContext *s, TrackInfo *info, enum AVCo
avio_wl16(&b, info->AV.Audio.BitDepth);
avio_wl32(&b, mkv_TruncFloat(info->AV.Audio.OutputSamplingFreq));
avio_wl32(&b, s->duration * info->AV.Audio.OutputSamplingFreq);
+ } else if (codec_id == AV_CODEC_ID_WAVPACK) {
+ return 0;
}
if (*extradata_ptr)
@@ -1346,6 +1348,88 @@ static void mkv_packet_param_change(AVFormatContext *s, TrackInfo *info, enum AV
}
}
+/* reconstruct full wavpack blocks from mangled matroska ones */
+static int matroska_parse_wavpack(MatroskaTrack *track, uint8_t *src,
+ uint8_t **pdst, int *size)
+{
+ uint8_t *dst = NULL;
+ int dstlen = 0;
+ int srclen = *size;
+ uint32_t samples;
+ uint16_t ver = 0;
+ int ret, offset = 0;
+
+ if (srclen < 12)
+ return AVERROR_INVALIDDATA;
+
+ if (track->info->CodecPrivateSize >= 2)
+ ver = AV_RL16(track->info->CodecPrivate);
+
+ samples = AV_RL32(src);
+ src += 4;
+ srclen -= 4;
+
+ while (srclen >= 8) {
+ int multiblock;
+ uint32_t blocksize;
+ uint8_t *tmp;
+
+ uint32_t flags = AV_RL32(src);
+ uint32_t crc = AV_RL32(src + 4);
+ src += 8;
+ srclen -= 8;
+
+ multiblock = (flags & 0x1800) != 0x1800;
+ if (multiblock) {
+ if (srclen < 4) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ blocksize = AV_RL32(src);
+ src += 4;
+ srclen -= 4;
+ } else
+ blocksize = srclen;
+
+ if (blocksize > srclen) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
+ tmp = av_realloc(dst, dstlen + blocksize + 32);
+ if (!tmp) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+ dst = tmp;
+ dstlen += blocksize + 32;
+
+ AV_WL32(dst + offset, MKTAG('w', 'v', 'p', 'k')); // tag
+ AV_WL32(dst + offset + 4, blocksize + 24); // blocksize - 8
+ AV_WL16(dst + offset + 8, ver); // version
+ AV_WL16(dst + offset + 10, 0); // track/index_no
+ AV_WL32(dst + offset + 12, 0); // total samples
+ AV_WL32(dst + offset + 16, 0); // block index
+ AV_WL32(dst + offset + 20, samples); // number of samples
+ AV_WL32(dst + offset + 24, flags); // flags
+ AV_WL32(dst + offset + 28, crc); // crc
+ memcpy (dst + offset + 32, src, blocksize); // block data
+
+ src += blocksize;
+ srclen -= blocksize;
+ offset += blocksize + 32;
+ }
+
+ *pdst = dst;
+ *size = dstlen;
+
+ return 0;
+
+fail:
+ av_freep(&dst);
+ return ret;
+}
+
static int mkv_read_packet(AVFormatContext *s, AVPacket *pkt)
{
MatroskaDemuxContext *ctx = (MatroskaDemuxContext *)s->priv_data;
@@ -1431,6 +1515,19 @@ again:
}
}
+ if (track->stream->codec->codec_id == AV_CODEC_ID_WAVPACK) {
+ uint8_t *wv_data;
+ int wv_size = pkt->size;
+ ret = matroska_parse_wavpack(track, pkt->data, &wv_data, &wv_size);
+ if (ret < 0) {
+ av_log(s, AV_LOG_ERROR, "Error parsing a wavpack block.\n");
+ av_free_packet(pkt);
+ return ret;
+ }
+ av_buffer_unref(pkt->buf);
+ av_packet_from_data(pkt, wv_data, wv_size);
+ }
+
if (track->refresh_extradata) {
mkv_packet_param_change(s, track->info, track->stream->codec->codec_id, pkt);
track->refresh_extradata = 0;