diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 4a3ef3a3ea..f4b6912000 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -1950,113 +1950,95 @@ static bool handle_realaudio(demuxer_t *demuxer, mkv_track_t *track, uint8_t *buffer = orig->buffer; uint32_t size = orig->len; demux_packet_t *dp; - // track->audio_buf allocation size size_t audiobuf_size = sph * w; - if ((track->a_formattag == MP_FOURCC('2', '8', '_', '8')) - || (track->a_formattag == MP_FOURCC('c', 'o', 'o', 'k')) - || (track->a_formattag == MP_FOURCC('a', 't', 'r', 'c')) - || (track->a_formattag == MP_FOURCC('s', 'i', 'p', 'r'))) - { - switch (track->a_formattag) { - case MP_FOURCC('2', '8', '_', '8'): - for (int x = 0; x < sph / 2; x++) { - uint64_t dst_offset = x * 2 * w + spc * (uint64_t)cfs; - if (dst_offset + cfs > audiobuf_size) - goto error; - uint64_t src_offset = x * (uint64_t)cfs; - if (src_offset + cfs > size) - goto error; - memcpy(track->audio_buf + dst_offset, buffer + src_offset, cfs); - } - break; - case MP_FOURCC('c', 'o', 'o', 'k'): - case MP_FOURCC('a', 't', 'r', 'c'): - for (int x = 0; x < w / sps; x++) { - uint32_t dst_offset = sps * (sph * x + ((sph + 1) / 2) * (spc & 1) - + (spc >> 1)); - if (dst_offset + sps > audiobuf_size) - goto error; - uint32_t src_offset = sps * x; - if (src_offset + sps > size) - goto error; - memcpy(track->audio_buf + dst_offset, buffer + src_offset, sps); - } - break; - case MP_FOURCC('s', 'i', 'p', 'r'): - if (spc * w + w > audiobuf_size || w > size) + switch (track->a_formattag) { + case MP_FOURCC('2', '8', '_', '8'): + for (int x = 0; x < sph / 2; x++) { + uint64_t dst_offset = x * 2 * w + spc * (uint64_t)cfs; + if (dst_offset + cfs > audiobuf_size) goto error; - memcpy(track->audio_buf + spc * w, buffer, w); - if (spc == sph - 1) { - int n; - int bs = sph * w * 2 / 96; // nibbles per subpacket - // Perform reordering - for (n = 0; n < 38; n++) { - unsigned int i = bs * sipr_swaps[n][0]; // 77 max - unsigned int o = bs * sipr_swaps[n][1]; // 95 max - // swap nibbles of block 'i' with 'o' - for (int j = 0; j < bs; j++) { - if (i / 2 >= audiobuf_size || o / 2 >= audiobuf_size) - goto error; - int x = (i & 1) ? - (track->audio_buf[i / 2] >> 4) : - (track->audio_buf[i / 2] & 0x0F); - int y = (o & 1) ? - (track->audio_buf[o / 2] >> 4) : - (track->audio_buf[o / 2] & 0x0F); - if (o & 1) - track->audio_buf[o / 2] = - (track->audio_buf[o / 2] & 0x0F) | (x << 4); - else - track->audio_buf[o / 2] = - (track->audio_buf[o / 2] & 0xF0) | x; - if (i & 1) - track->audio_buf[i / 2] = - (track->audio_buf[i / 2] & 0x0F) | (y << 4); - else - track->audio_buf[i / 2] = - (track->audio_buf[i / 2] & 0xF0) | y; - ++i; - ++o; - } + uint64_t src_offset = x * (uint64_t)cfs; + if (src_offset + cfs > size) + goto error; + memcpy(track->audio_buf + dst_offset, buffer + src_offset, cfs); + } + break; + case MP_FOURCC('c', 'o', 'o', 'k'): + case MP_FOURCC('a', 't', 'r', 'c'): + for (int x = 0; x < w / sps; x++) { + uint32_t dst_offset = + sps * (sph * x + ((sph + 1) / 2) * (spc & 1) + (spc >> 1)); + if (dst_offset + sps > audiobuf_size) + goto error; + uint32_t src_offset = sps * x; + if (src_offset + sps > size) + goto error; + memcpy(track->audio_buf + dst_offset, buffer + src_offset, sps); + } + break; + case MP_FOURCC('s', 'i', 'p', 'r'): + if (spc * w + w > audiobuf_size || w > size) + goto error; + memcpy(track->audio_buf + spc * w, buffer, w); + if (spc == sph - 1) { + int n; + int bs = sph * w * 2 / 96; // nibbles per subpacket + // Perform reordering + for (n = 0; n < 38; n++) { + unsigned int i = bs * sipr_swaps[n][0]; // 77 max + unsigned int o = bs * sipr_swaps[n][1]; // 95 max + // swap nibbles of block 'i' with 'o' + for (int j = 0; j < bs; j++) { + if (i / 2 >= audiobuf_size || o / 2 >= audiobuf_size) + goto error; + uint8_t iv = track->audio_buf[i / 2]; + uint8_t ov = track->audio_buf[o / 2]; + int x = (i & 1) ? iv >> 4 : iv & 0x0F; + int y = (o & 1) ? ov >> 4 : ov & 0x0F; + track->audio_buf[o / 2] = ov & 0x0F | (o & 1 ? x << 4 : x); + track->audio_buf[i / 2] = iv & 0x0F | (i & 1 ? y << 4 : y); + i++; + o++; } } - break; } - track->audio_timestamp[track->sub_packet_cnt] = - track->ra_pts == orig->pts ? 0 : orig->pts; - track->ra_pts = orig->pts; - if (++(track->sub_packet_cnt) == sph) { - track->sub_packet_cnt = 0; - // apk_usize has same range as coded_framesize in worst case - uint32_t apk_usize = track->stream->audio->block_align; - if (apk_usize > audiobuf_size) - goto error; - // Release all the audio packets - for (int x = 0; x < sph * w / apk_usize; x++) { - dp = new_demux_packet_from(track->audio_buf + x * apk_usize, - apk_usize); - if (!dp) - goto error; - /* Put timestamp only on packets that correspond to original - * audio packets in file */ - dp->pts = (x * apk_usize % w) ? MP_NOPTS_VALUE : - track->audio_timestamp[x * apk_usize / w]; - dp->pos = orig->pos; - dp->keyframe = !x; // Mark first packet as keyframe - demux_add_packet(track->stream, dp); - } - } - talloc_free(orig); - return true; - error: - MP_ERR(demuxer, "RealAudio packet extraction or decryption error.\n"); - talloc_free(orig); - return true; - } else { // Not a codec that requires reordering + break; + default: + // Not a codec that requires reordering return false; } + + track->audio_timestamp[track->sub_packet_cnt] = + track->ra_pts == orig->pts ? 0 : orig->pts; + track->ra_pts = orig->pts; + + if (++(track->sub_packet_cnt) == sph) { + track->sub_packet_cnt = 0; + // apk_usize has same range as coded_framesize in worst case + uint32_t apk_usize = track->stream->audio->block_align; + if (apk_usize > audiobuf_size) + goto error; + // Release all the audio packets + for (int x = 0; x < sph * w / apk_usize; x++) { + dp = new_demux_packet_from(track->audio_buf + x * apk_usize, + apk_usize); + if (!dp) + goto error; + /* Put timestamp only on packets that correspond to original + * audio packets in file */ + dp->pts = (x * apk_usize % w) ? MP_NOPTS_VALUE : + track->audio_timestamp[x * apk_usize / w]; + dp->pos = orig->pos; + dp->keyframe = !x; // Mark first packet as keyframe + demux_add_packet(track->stream, dp); + } + } + +error: + talloc_free(orig); + return true; } static void mkv_seek_reset(demuxer_t *demuxer)