1
0
Fork 0

matroskadec_haali: export full wavpack blocks

This commit is contained in:
Hendrik Leppkes 2013-07-13 10:27:34 +02:00
parent c531e5a224
commit bdb9056577
Signed by: hendrik
GPG Key ID: 846079A4B0A7C1B5
1 changed files with 97 additions and 0 deletions

View File

@ -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;