summaryrefslogtreecommitdiffstats
path: root/demux
diff options
context:
space:
mode:
Diffstat (limited to 'demux')
-rw-r--r--demux/demux_mkv.c176
1 files changed, 79 insertions, 97 deletions
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;
- }
- }
- }
- break;
+ 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);
}
- 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)
+ 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;
- // 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);
+ 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++;
+ }
}
}
- 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)