matroskadec_haali: export full wavpack blocks
This commit is contained in:
parent
c531e5a224
commit
bdb9056577
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue