ref: 10aae4df73b66acdfb31e1ff54b45b4ca6b94b2b
parent: 2df05010cd766652a3f4e83d3bfc87f15f29d415
author: Andrew Allen <bitllama@google.com>
date: Tue Apr 10 06:48:29 EDT 2018
opusinfo: support for ambisonics [mark.hsj: Update family numbers and fix buffer overflow] Signed-off-by: Mark Harris <mark.hsj@gmail.com>
--- a/src/info_opus.c
+++ b/src/info_opus.c
@@ -261,7 +261,7 @@
oi_info(_("Opus stream %d:\n"),stream->num);
if(inf && inf->total_packets>0){
- int i;
+ int i, j;
long minutes, seconds, milliseconds;
double time;
time = (inf->lastgranulepos-inf->firstgranule-inf->oh.preskip) / 48000.;
@@ -284,8 +284,25 @@
if(inf->oh.input_sample_rate)oi_info(_("\tOriginal sample rate: %d Hz\n"),inf->oh.input_sample_rate);
if(inf->oh.nb_streams>1)oi_info(_("\tStreams: %d, Coupled: %d\n"),inf->oh.nb_streams,inf->oh.nb_coupled);
if(inf->oh.channel_mapping>0) {
- oi_info(_("\tChannel Mapping family: %d Map:"),inf->oh.channel_mapping);
- for(i=0;i<inf->oh.channels;i++)oi_info("%s%d%s",i==0?" [":", ",inf->oh.stream_map[i],i==inf->oh.channels-1?"]\n":"");
+ oi_info(_("\tChannel Mapping Family: %d"),inf->oh.channel_mapping);
+ if(inf->oh.channel_mapping==3) {
+ oi_info(_("\n"));
+ if(inf->oh.channels*(inf->oh.nb_streams+inf->oh.nb_coupled)*2 <= OPUS_DEMIXING_MATRIX_SIZE_MAX) {
+ oi_info(_("\tDemixing Matrix [%dx%d]:\n"),inf->oh.nb_streams+inf->oh.nb_coupled,inf->oh.channels);
+ for(i=0;i<inf->oh.nb_streams+inf->oh.nb_coupled;i++) {
+ for(j=0;j<inf->oh.channels;j++) {
+ int k=j*(inf->oh.nb_streams+inf->oh.nb_coupled)+i;
+ int s=inf->oh.dmatrix[2*k + 1] << 8 | inf->oh.dmatrix[2*k];
+ s = ((s & 0xFFFF) ^ 0x8000) - 0x8000;
+ oi_info("%s%6d%s",j==0?"\t[":", ",s,j==inf->oh.channels-1?"]\n":"");
+ }
+ }
+ }
+ }
+ else {
+ oi_info(_(" Map:"));
+ for(i=0;i<inf->oh.channels;i++)oi_info("%s%d%s",i==0?" [":", ",inf->oh.stream_map[i],i==inf->oh.channels-1?"]\n":"");
+ }
}
if(inf->total_packets)oi_info(_("\tPacket duration: %6.1fms (max), %6.1fms (avg), %6.1fms (min)\n"),
inf->max_packet_duration/48.,inf->total_samples/(double)inf->total_packets/48.,inf->min_packet_duration/48.);
--- a/src/opus_header.c
+++ b/src/opus_header.c
@@ -156,12 +156,28 @@
h->nb_coupled = ch;
/* Multi-stream support */
- for (i=0;i<h->channels;i++)
+ if (h->channel_mapping == 3)
{
- if (!read_chars(&p, &h->stream_map[i], 1))
+ int dmatrix_size = h->channels * (h->nb_streams + h->nb_coupled) * 2;
+ if (dmatrix_size > len - p.pos)
return 0;
- if (h->stream_map[i]>(h->nb_streams+h->nb_coupled) && h->stream_map[i]!=255)
+ if (dmatrix_size > OPUS_DEMIXING_MATRIX_SIZE_MAX)
+ p.pos += dmatrix_size;
+ else if (!read_chars(&p, h->dmatrix, dmatrix_size))
return 0;
+ for (i=0;i<h->channels;i++) {
+ h->stream_map[i] = i;
+ }
+ }
+ else
+ {
+ for (i=0;i<h->channels;i++)
+ {
+ if (!read_chars(&p, &h->stream_map[i], 1))
+ return 0;
+ if (h->stream_map[i]>(h->nb_streams+h->nb_coupled) && h->stream_map[i]!=255)
+ return 0;
+ }
}
} else {
if(h->channels>2)
--- a/src/opus_header.h
+++ b/src/opus_header.h
@@ -30,6 +30,8 @@
#include <ogg/ogg.h>
+#define OPUS_DEMIXING_MATRIX_SIZE_MAX (18 * 18 * 2)
+
typedef struct {
int version;
int channels; /* Number of channels: 1..255 */
@@ -41,6 +43,7 @@
int nb_streams;
int nb_coupled;
unsigned char stream_map[255];
+ unsigned char dmatrix[OPUS_DEMIXING_MATRIX_SIZE_MAX];
} OpusHeader;
int opus_header_parse(const unsigned char *header, int len, OpusHeader *h);