shithub: opus-tools

Download patch

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