From 024cad828e20a9fe5354b7418fdace45e60b348e Mon Sep 17 00:00:00 2001 From: Andy Kent Date: Mon, 16 Aug 2021 08:42:42 +0100 Subject: [PATCH 01/15] map channels for mapping family 255 --- src/info.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index 000c74b..a3c46e2 100644 --- a/src/info.c +++ b/src/info.c @@ -80,7 +80,31 @@ int opus_head_parse(OpusHead *_head,const unsigned char *_data,size_t _len){ } /*General purpose players should not attempt to play back content with channel mapping family 255.*/ - else if(head.mapping_family==255)return OP_EIMPL; + else if(head.mapping_family==255) + { + size_t size; + int ci; + if (head.channel_count != 16) + return OP_EBADHEADER; + size = 21 + head.channel_count; + if (_len < size || head.version <= 1 && _len > size) + return OP_EBADHEADER; + head.stream_count = _data[19]; + if (head.stream_count < 1) + return OP_EBADHEADER; + head.coupled_count = _data[20]; + if (head.coupled_count > head.stream_count) + return OP_EBADHEADER; + for (ci = 0; ci < head.channel_count; ci++) + { + if (_data[21 + ci] >= head.stream_count + head.coupled_count && _data[21 + ci] != 255) + { + return OP_EBADHEADER; + } + } + if (_head != NULL) + memcpy(_head->mapping, _data + 21, head.channel_count); + } /*No other channel mapping families are currently defined.*/ else return OP_EBADHEADER; if(_head!=NULL)memcpy(_head,&head,head.mapping-(unsigned char *)&head); From 796356b81dc637f6a7704ecebd797604c9add070 Mon Sep 17 00:00:00 2001 From: Andy Kent Date: Mon, 16 Aug 2021 08:43:59 +0100 Subject: [PATCH 02/15] increase OP_NCHANNELS_MAX to 16 --- src/internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal.h b/src/internal.h index 0c2d2bb..41c3633 100644 --- a/src/internal.h +++ b/src/internal.h @@ -109,7 +109,7 @@ void op_fatal_impl(const char *_str,const char *_file,int _line); (OP_MIN(_offset,OP_INT64_MAX-(_amount))+(_amount)) /*The maximum channel count for any mapping we'll actually decode.*/ -# define OP_NCHANNELS_MAX (8) +# define OP_NCHANNELS_MAX (16) /*Initial state.*/ # define OP_NOTOPEN (0) From cc7c445ed8cc88dd02a12e4bd019b289b61958ed Mon Sep 17 00:00:00 2001 From: Andy Kent Date: Tue, 29 Mar 2022 10:35:48 +0100 Subject: [PATCH 03/15] allow channel mapping 255 to support a variable channel count --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index a3c46e2..cd76e9f 100644 --- a/src/info.c +++ b/src/info.c @@ -84,7 +84,7 @@ int opus_head_parse(OpusHead *_head,const unsigned char *_data,size_t _len){ { size_t size; int ci; - if (head.channel_count != 16) + if (head.channel_count < 1 || head.channel_count > OP_NCHANNELS_MAX) return OP_EBADHEADER; size = 21 + head.channel_count; if (_len < size || head.version <= 1 && _len > size) From 1f581af690ec3c92143d1d6d240cb401bf19787b Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Sat, 12 Aug 2023 16:03:14 +0300 Subject: [PATCH 04/15] Correct OP_NCHANNELS_MAX --- src/internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal.h b/src/internal.h index 41c3633..5d9562f 100644 --- a/src/internal.h +++ b/src/internal.h @@ -109,7 +109,7 @@ void op_fatal_impl(const char *_str,const char *_file,int _line); (OP_MIN(_offset,OP_INT64_MAX-(_amount))+(_amount)) /*The maximum channel count for any mapping we'll actually decode.*/ -# define OP_NCHANNELS_MAX (16) +# define OP_NCHANNELS_MAX (255) /*Initial state.*/ # define OP_NOTOPEN (0) From 796c442c339e37e42f9cc5682449797f95c640bb Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Sat, 12 Aug 2023 16:03:36 +0300 Subject: [PATCH 05/15] Enable channel mapping family 2 and 3 --- src/info.c | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index cd76e9f..1cb6fc3 100644 --- a/src/info.c +++ b/src/info.c @@ -78,6 +78,45 @@ int opus_head_parse(OpusHead *_head,const unsigned char *_data,size_t _len){ } if(_head!=NULL)memcpy(_head->mapping,_data+21,head.channel_count); } + /*Ambisonics channel mapping*/ + else if(head.mapping_family==2) + { + size_t size; + int ci; + if (head.channel_count < 1 || head.channel_count > OP_NCHANNELS_MAX) + return OP_EBADHEADER; + size = 21 + head.channel_count; + if (_len < size || head.version <= 1 && _len > size) + return OP_EBADHEADER; + head.stream_count = _data[19]; + if (head.stream_count < 1) + return OP_EBADHEADER; + head.coupled_count = _data[20]; + if (head.coupled_count > head.stream_count) + return OP_EBADHEADER; + for (ci = 0; ci < head.channel_count; ci++) + { + if (_data[21 + ci] >= head.stream_count + head.coupled_count && + _data[21 + ci] != 255) + { + return OP_EBADHEADER; + } + } + if (_head != NULL) + memcpy(_head->mapping, _data + 21, head.channel_count); + } + else if(head.mapping_family==3) + { + /*Use channel mapping 3 for orders {1, 2, 3} with 4 to 18 channels + (including the non-diegetic stereo track). For other orders with no + demixing matrices currently available, use channel mapping 2.*/ + size_t size; + int ci; + if (head.channel_count < 1 || + (head.channel_count >=4 && head.channel_count<=18)) + return OP_EBADHEADER; + fprintf(stderr, "Mapping family 3 not implemented!\n"); + } /*General purpose players should not attempt to play back content with channel mapping family 255.*/ else if(head.mapping_family==255) @@ -97,7 +136,8 @@ int opus_head_parse(OpusHead *_head,const unsigned char *_data,size_t _len){ return OP_EBADHEADER; for (ci = 0; ci < head.channel_count; ci++) { - if (_data[21 + ci] >= head.stream_count + head.coupled_count && _data[21 + ci] != 255) + if (_data[21 + ci] >= head.stream_count + head.coupled_count && + _data[21 + ci] != 255) { return OP_EBADHEADER; } From e1ce7c05e0483a1ddb0f7ba39bf6c20404e5aed4 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Fri, 20 Oct 2023 19:34:14 +0300 Subject: [PATCH 06/15] Start channel mapping 3 --- include/opusfile.h | 2 ++ src/info.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/include/opusfile.h b/include/opusfile.h index 8e7aa09..5675780 100644 --- a/include/opusfile.h +++ b/include/opusfile.h @@ -266,6 +266,8 @@ struct OpusHead{ Otherwise, it refers to the output of the uncoupled stream (index-coupled_count).*/ unsigned char mapping[OPUS_CHANNEL_COUNT_MAX]; + + unsigned char dmatrix[38*38*2]; }; /**The metadata from an Ogg Opus stream. diff --git a/src/info.c b/src/info.c index 1cb6fc3..2bc1509 100644 --- a/src/info.c +++ b/src/info.c @@ -112,10 +112,47 @@ int opus_head_parse(OpusHead *_head,const unsigned char *_data,size_t _len){ demixing matrices currently available, use channel mapping 2.*/ size_t size; int ci; - if (head.channel_count < 1 || - (head.channel_count >=4 && head.channel_count<=18)) + int i, k, s; + fprintf(stderr, "Mapping family 3 not actually implemented!\n"); + if (head.channel_count < 1 || head.channel_count > OP_NCHANNELS_MAX) + return OP_EBADHEADER; + + head.stream_count = _data[19]; + if (head.stream_count < 1) + return OP_EBADHEADER; + + head.coupled_count = _data[20]; + if (head.coupled_count > head.stream_count) + return OP_EBADHEADER; + + fprintf(stderr, "streams %d, coupled %d \n", head.stream_count, head.coupled_count); + + size = 21 + (head.channel_count * (head.stream_count+head.coupled_count)*2); + + if (_len < size || head.version <= 1 && _len > size) return OP_EBADHEADER; - fprintf(stderr, "Mapping family 3 not implemented!\n"); + + + for (i = 0; i < head.stream_count+head.coupled_count; i++) + { + for (ci = 0; ci < head.channel_count; ci++) + { + /*if (_data[21 + j] >= (head.stream_count+head.coupled_count)*2 && + _data[21 + j] != 255) + { + return OP_EBADHEADER; + }*/ + + k=ci*(head.stream_count+head.coupled_count)+i; + s = _data[21 + 2*k + 1] << 8 | _data[21 + 2*k]; + s = ((s & 0xFFFF) ^ 0x8000) - 0x8000; + /* fprintf(stderr, "%s%6d%s",ci==0?"\t[":", ",s,ci==head.channel_count-1?"]\n":""); */ + + _head->dmatrix[k] = s; + } + } + if (_head != NULL) + memcpy(_head->mapping, _data + 21, head.channel_count); } /*General purpose players should not attempt to play back content with channel mapping family 255.*/ From 089c01569bed5ccb6bd6bae8976f75b80d3d2194 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 7 Nov 2023 18:33:33 +0200 Subject: [PATCH 07/15] Start decoding ambix map 3 --- include/opusfile.h | 4 +++- src/info.c | 5 ++--- src/internal.h | 2 ++ src/opusfile.c | 39 ++++++++++++++++++++++++++++++++++----- 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/include/opusfile.h b/include/opusfile.h index 5675780..9b5faa1 100644 --- a/include/opusfile.h +++ b/include/opusfile.h @@ -108,7 +108,9 @@ extern "C" { # include # include # include - +#ifdef OPUS_HAVE_OPUS_PROJECTION_H +#include +#endif /**@cond PRIVATE*/ /*Enable special features for gcc and gcc-compatible compilers.*/ diff --git a/src/info.c b/src/info.c index 2bc1509..212f5c5 100644 --- a/src/info.c +++ b/src/info.c @@ -113,7 +113,7 @@ int opus_head_parse(OpusHead *_head,const unsigned char *_data,size_t _len){ size_t size; int ci; int i, k, s; - fprintf(stderr, "Mapping family 3 not actually implemented!\n"); + fprintf(stderr, "Mapping family 3!\n"); if (head.channel_count < 1 || head.channel_count > OP_NCHANNELS_MAX) return OP_EBADHEADER; @@ -146,8 +146,7 @@ int opus_head_parse(OpusHead *_head,const unsigned char *_data,size_t _len){ k=ci*(head.stream_count+head.coupled_count)+i; s = _data[21 + 2*k + 1] << 8 | _data[21 + 2*k]; s = ((s & 0xFFFF) ^ 0x8000) - 0x8000; - /* fprintf(stderr, "%s%6d%s",ci==0?"\t[":", ",s,ci==head.channel_count-1?"]\n":""); */ - + fprintf(stderr, "%s%6d%s",ci==0?"\t[":", ",s,ci==head.channel_count-1?"]\n":""); _head->dmatrix[k] = s; } } diff --git a/src/internal.h b/src/internal.h index 5d9562f..d5a0a64 100644 --- a/src/internal.h +++ b/src/internal.h @@ -213,6 +213,8 @@ struct OggOpusFile{ int op_count; /*Central working state for the packet-to-PCM decoder.*/ OpusMSDecoder *od; + /*Projection decoder state.*/ + OpusProjectionDecoder *st; /*The application-provided packet decode callback.*/ op_decode_cb_func decode_cb; /*The application-provided packet decode callback context.*/ diff --git a/src/opusfile.c b/src/opusfile.c index 3c3c81e..5768bf7 100644 --- a/src/opusfile.c +++ b/src/opusfile.c @@ -27,6 +27,8 @@ #include #include "opusfile.h" +#include "opus_projection.h" + /*This implementation is largely based off of libvorbisfile. All of the Ogg bits work roughly the same, though I have made some @@ -1335,7 +1337,12 @@ static void op_update_gain(OggOpusFile *_of){ gain_q8=OP_CLAMP(-32768,gain_q8,32767); OP_ASSERT(_of->od!=NULL); #if defined(OPUS_SET_GAIN) - opus_multistream_decoder_ctl(_of->od,OPUS_SET_GAIN(gain_q8)); + if(_of->od==NULL){ + fprintf(stderr, "Set gain not available.\n"); + } + else{ + opus_multistream_decoder_ctl(_of->od,OPUS_SET_GAIN(gain_q8)); + } #else /*A fallback that works with both float and fixed-point is a bunch of work, so just force people to use a sufficiently new version. @@ -1366,10 +1373,25 @@ static int op_make_decode_ready(OggOpusFile *_of){ } else{ int err; - opus_multistream_decoder_destroy(_of->od); - _of->od=opus_multistream_decoder_create(48000,channel_count, - stream_count,coupled_count,head->mapping,&err); - if(_of->od==NULL)return OP_EFAULT; + if(head->mapping_family==3){ /*probably also better for mapping 2*/ + OpusProjectionDecoder *st_dec; + /*opus_projection_decoder_destroy(_of->od);*/ + const unsigned char *matrix = head->dmatrix; + /* opus_int32 matrix_size = mapping_matrix_get_size(stream_count + coupled_count, channel_count); */ + opus_int32 matrix_size = (stream_count + coupled_count) * channel_count * sizeof(opus_int16); + st_dec = opus_projection_decoder_create(48000,channel_count, + stream_count,coupled_count,matrix,matrix_size,&err); + _of->od = NULL; + _of->st = st_dec; + /*Override od*/ + if(_of->st==NULL)return OP_EFAULT; + } + else{ + opus_multistream_decoder_destroy(_of->od); + _of->od=opus_multistream_decoder_create(48000,channel_count, + stream_count,coupled_count,head->mapping,&err); + if(_of->od==NULL)return OP_EFAULT; + } _of->od_stream_count=stream_count; _of->od_coupled_count=coupled_count; _of->od_channel_count=channel_count; @@ -2808,9 +2830,16 @@ static int op_decode(OggOpusFile *_of,op_sample *_pcm, #if defined(OP_FIXED_POINT) ret=opus_multistream_decode(_of->od, _op->packet,_op->bytes,_pcm,_nsamples,0); +#else +#ifdef OPUS_HAVE_OPUS_PROJECTION_H +if(_of->st!=NULL){ + ret=opus_projection_decode_float(_of->st, + _op->packet,_op->bytes,_pcm,_nsamples,0); +} #else ret=opus_multistream_decode_float(_of->od, _op->packet,_op->bytes,_pcm,_nsamples,0); +#endif #endif OP_ASSERT(ret<0||ret==_nsamples); } From 26e03b8cea14c9162e2377bc23f70d3dd3a98839 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Wed, 8 Nov 2023 16:34:40 +0200 Subject: [PATCH 08/15] Fix and cleanup demixing matrix parsing --- include/opusfile.h | 4 +++- src/info.c | 31 +++++++++---------------------- src/opusfile.c | 7 ++++--- 3 files changed, 16 insertions(+), 26 deletions(-) diff --git a/include/opusfile.h b/include/opusfile.h index 9b5faa1..5c38316 100644 --- a/include/opusfile.h +++ b/include/opusfile.h @@ -211,6 +211,8 @@ typedef struct OggOpusFile OggOpusFile; /**The maximum number of channels in an Ogg Opus stream.*/ #define OPUS_CHANNEL_COUNT_MAX (255) +#define OPUS_DEMIXING_MATRIX_SIZE_MAX (18 * 18 * 2) + /**Ogg Opus bitstream information. This contains the basic playback parameters for a stream, and corresponds to the initial ID header packet of an Ogg Opus stream.*/ @@ -269,7 +271,7 @@ struct OpusHead{ (index-coupled_count).*/ unsigned char mapping[OPUS_CHANNEL_COUNT_MAX]; - unsigned char dmatrix[38*38*2]; + unsigned char dmatrix[OPUS_DEMIXING_MATRIX_SIZE_MAX]; }; /**The metadata from an Ogg Opus stream. diff --git a/src/info.c b/src/info.c index 212f5c5..86c1d37 100644 --- a/src/info.c +++ b/src/info.c @@ -111,9 +111,9 @@ int opus_head_parse(OpusHead *_head,const unsigned char *_data,size_t _len){ (including the non-diegetic stereo track). For other orders with no demixing matrices currently available, use channel mapping 2.*/ size_t size; - int ci; - int i, k, s; - fprintf(stderr, "Mapping family 3!\n"); + size_t dmatrix_size; + int i; + fprintf(stderr, "Mapping family 3!\n"); if (head.channel_count < 1 || head.channel_count > OP_NCHANNELS_MAX) return OP_EBADHEADER; @@ -132,26 +132,13 @@ int opus_head_parse(OpusHead *_head,const unsigned char *_data,size_t _len){ if (_len < size || head.version <= 1 && _len > size) return OP_EBADHEADER; - - for (i = 0; i < head.stream_count+head.coupled_count; i++) - { - for (ci = 0; ci < head.channel_count; ci++) - { - /*if (_data[21 + j] >= (head.stream_count+head.coupled_count)*2 && - _data[21 + j] != 255) - { - return OP_EBADHEADER; - }*/ - - k=ci*(head.stream_count+head.coupled_count)+i; - s = _data[21 + 2*k + 1] << 8 | _data[21 + 2*k]; - s = ((s & 0xFFFF) ^ 0x8000) - 0x8000; - fprintf(stderr, "%s%6d%s",ci==0?"\t[":", ",s,ci==head.channel_count-1?"]\n":""); - _head->dmatrix[k] = s; - } + dmatrix_size = head.channel_count*(head.stream_count+head.coupled_count) * + sizeof(opus_int16); + memcpy(_head->dmatrix, _data + 21, dmatrix_size); + if (_head != NULL){ + for (i = 0; i < head.channel_count; i++) + _head->mapping[i] = i; } - if (_head != NULL) - memcpy(_head->mapping, _data + 21, head.channel_count); } /*General purpose players should not attempt to play back content with channel mapping family 255.*/ diff --git a/src/opusfile.c b/src/opusfile.c index 5768bf7..21dcc8a 100644 --- a/src/opusfile.c +++ b/src/opusfile.c @@ -1376,11 +1376,12 @@ static int op_make_decode_ready(OggOpusFile *_of){ if(head->mapping_family==3){ /*probably also better for mapping 2*/ OpusProjectionDecoder *st_dec; /*opus_projection_decoder_destroy(_of->od);*/ - const unsigned char *matrix = head->dmatrix; /* opus_int32 matrix_size = mapping_matrix_get_size(stream_count + coupled_count, channel_count); */ - opus_int32 matrix_size = (stream_count + coupled_count) * channel_count * sizeof(opus_int16); + const int dmatrix_size = (stream_count + coupled_count) * channel_count * + sizeof(opus_int16); + opus_projection_decoder_destroy(_of->st); st_dec = opus_projection_decoder_create(48000,channel_count, - stream_count,coupled_count,matrix,matrix_size,&err); + stream_count,coupled_count,head->dmatrix,dmatrix_size,&err); _of->od = NULL; _of->st = st_dec; /*Override od*/ From 014d57a5ca0460632f2b29611dbf3b5f17fc91fb Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Wed, 8 Nov 2023 18:30:21 +0200 Subject: [PATCH 09/15] Fix pre-processor bug --- src/opusfile.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/opusfile.c b/src/opusfile.c index 21dcc8a..bf66f22 100644 --- a/src/opusfile.c +++ b/src/opusfile.c @@ -2832,15 +2832,19 @@ static int op_decode(OggOpusFile *_of,op_sample *_pcm, ret=opus_multistream_decode(_of->od, _op->packet,_op->bytes,_pcm,_nsamples,0); #else -#ifdef OPUS_HAVE_OPUS_PROJECTION_H -if(_of->st!=NULL){ - ret=opus_projection_decode_float(_of->st, - _op->packet,_op->bytes,_pcm,_nsamples,0); -} -#else +# ifdef OPUS_HAVE_OPUS_PROJECTION_H + if(_of->st!=NULL){ + ret=opus_projection_decode_float(_of->st, + _op->packet,_op->bytes,_pcm,_nsamples,0); + } + else{ + ret=opus_multistream_decode_float(_of->od, + _op->packet,_op->bytes,_pcm,_nsamples,0); + } +# else ret=opus_multistream_decode_float(_of->od, - _op->packet,_op->bytes,_pcm,_nsamples,0); -#endif + _op->packet,_op->bytes,_pcm,_nsamples,0); +# endif #endif OP_ASSERT(ret<0||ret==_nsamples); } From f4df8d2c88d3f557feef8cc235571e19c1eb9441 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Wed, 22 Nov 2023 13:59:27 +0200 Subject: [PATCH 10/15] Enable set_gain for projection_decoder --- src/opusfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opusfile.c b/src/opusfile.c index bf66f22..36c426d 100644 --- a/src/opusfile.c +++ b/src/opusfile.c @@ -1338,7 +1338,7 @@ static void op_update_gain(OggOpusFile *_of){ OP_ASSERT(_of->od!=NULL); #if defined(OPUS_SET_GAIN) if(_of->od==NULL){ - fprintf(stderr, "Set gain not available.\n"); + opus_projection_decoder_ctl(_of->st,OPUS_SET_GAIN(gain_q8)); } else{ opus_multistream_decoder_ctl(_of->od,OPUS_SET_GAIN(gain_q8)); From 2daa5c2174844cb057c1d22c5bffcd6febb0fc65 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Wed, 22 Nov 2023 14:21:23 +0200 Subject: [PATCH 11/15] Guard feature to OPUS_HAVE_OPUS_PROJECTION_H --- src/internal.h | 2 ++ src/opusfile.c | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/internal.h b/src/internal.h index d5a0a64..545e27d 100644 --- a/src/internal.h +++ b/src/internal.h @@ -213,8 +213,10 @@ struct OggOpusFile{ int op_count; /*Central working state for the packet-to-PCM decoder.*/ OpusMSDecoder *od; +#ifdef OPUS_HAVE_OPUS_PROJECTION_H /*Projection decoder state.*/ OpusProjectionDecoder *st; +#endif /*The application-provided packet decode callback.*/ op_decode_cb_func decode_cb; /*The application-provided packet decode callback context.*/ diff --git a/src/opusfile.c b/src/opusfile.c index 36c426d..2052bc4 100644 --- a/src/opusfile.c +++ b/src/opusfile.c @@ -27,7 +27,6 @@ #include #include "opusfile.h" -#include "opus_projection.h" /*This implementation is largely based off of libvorbisfile. @@ -1337,12 +1336,16 @@ static void op_update_gain(OggOpusFile *_of){ gain_q8=OP_CLAMP(-32768,gain_q8,32767); OP_ASSERT(_of->od!=NULL); #if defined(OPUS_SET_GAIN) +# ifdef OPUS_HAVE_OPUS_PROJECTION_H if(_of->od==NULL){ opus_projection_decoder_ctl(_of->st,OPUS_SET_GAIN(gain_q8)); } else{ opus_multistream_decoder_ctl(_of->od,OPUS_SET_GAIN(gain_q8)); } +# else + opus_multistream_decoder_ctl(_of->od,OPUS_SET_GAIN(gain_q8)); +# endif #else /*A fallback that works with both float and fixed-point is a bunch of work, so just force people to use a sufficiently new version. @@ -1374,6 +1377,7 @@ static int op_make_decode_ready(OggOpusFile *_of){ else{ int err; if(head->mapping_family==3){ /*probably also better for mapping 2*/ +#ifdef OPUS_HAVE_OPUS_PROJECTION_H OpusProjectionDecoder *st_dec; /*opus_projection_decoder_destroy(_of->od);*/ /* opus_int32 matrix_size = mapping_matrix_get_size(stream_count + coupled_count, channel_count); */ @@ -1386,6 +1390,9 @@ static int op_make_decode_ready(OggOpusFile *_of){ _of->st = st_dec; /*Override od*/ if(_of->st==NULL)return OP_EFAULT; +#else + return OP_EIMPL; +#endif } else{ opus_multistream_decoder_destroy(_of->od); From 5b8874794c939ea0d7b02e3af8d79ee9063d0ace Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 6 Feb 2024 19:21:58 +0200 Subject: [PATCH 12/15] Cleanup and docs --- include/opusfile.h | 8 +++++++- src/opusfile.c | 8 +++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/include/opusfile.h b/include/opusfile.h index 5c38316..675c910 100644 --- a/include/opusfile.h +++ b/include/opusfile.h @@ -211,7 +211,10 @@ typedef struct OggOpusFile OggOpusFile; /**The maximum number of channels in an Ogg Opus stream.*/ #define OPUS_CHANNEL_COUNT_MAX (255) -#define OPUS_DEMIXING_MATRIX_SIZE_MAX (18 * 18 * 2) +#ifdef OPUS_HAVE_OPUS_PROJECTION_H +/**The maximum size of projection decoder demixing matrix.*/ +#define OPUS_DEMIXING_MATRIX_SIZE_MAX (38 * 38 * 2) +#endif /**Ogg Opus bitstream information. This contains the basic playback parameters for a stream, and corresponds to @@ -271,7 +274,10 @@ struct OpusHead{ (index-coupled_count).*/ unsigned char mapping[OPUS_CHANNEL_COUNT_MAX]; +#ifdef OPUS_HAVE_OPUS_PROJECTION_H + /**The maximum size of projection decoder demixing matrix. */ unsigned char dmatrix[OPUS_DEMIXING_MATRIX_SIZE_MAX]; +#endif }; /**The metadata from an Ogg Opus stream. diff --git a/src/opusfile.c b/src/opusfile.c index 2052bc4..3e4d68b 100644 --- a/src/opusfile.c +++ b/src/opusfile.c @@ -1379,16 +1379,14 @@ static int op_make_decode_ready(OggOpusFile *_of){ if(head->mapping_family==3){ /*probably also better for mapping 2*/ #ifdef OPUS_HAVE_OPUS_PROJECTION_H OpusProjectionDecoder *st_dec; - /*opus_projection_decoder_destroy(_of->od);*/ - /* opus_int32 matrix_size = mapping_matrix_get_size(stream_count + coupled_count, channel_count); */ const int dmatrix_size = (stream_count + coupled_count) * channel_count * sizeof(opus_int16); opus_projection_decoder_destroy(_of->st); st_dec = opus_projection_decoder_create(48000,channel_count, - stream_count,coupled_count,head->dmatrix,dmatrix_size,&err); - _of->od = NULL; + stream_count,coupled_count,(unsigned char*)head->dmatrix,dmatrix_size,&err); + /*Replace od with st*/ + opus_multistream_decoder_destroy(_of->od); _of->st = st_dec; - /*Override od*/ if(_of->st==NULL)return OP_EFAULT; #else return OP_EIMPL; From 49b9f87e1740a3a01242029f0181005260ba11c3 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 6 Feb 2024 20:01:37 +0200 Subject: [PATCH 13/15] Cleanup --- include/opusfile.h | 2 +- src/info.c | 3 --- src/opusfile.c | 3 +-- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/include/opusfile.h b/include/opusfile.h index 675c910..a68d345 100644 --- a/include/opusfile.h +++ b/include/opusfile.h @@ -275,7 +275,7 @@ struct OpusHead{ unsigned char mapping[OPUS_CHANNEL_COUNT_MAX]; #ifdef OPUS_HAVE_OPUS_PROJECTION_H - /**The maximum size of projection decoder demixing matrix. */ + /**The demixing matrix of the projection decoder.*/ unsigned char dmatrix[OPUS_DEMIXING_MATRIX_SIZE_MAX]; #endif }; diff --git a/src/info.c b/src/info.c index 86c1d37..53729ca 100644 --- a/src/info.c +++ b/src/info.c @@ -113,7 +113,6 @@ int opus_head_parse(OpusHead *_head,const unsigned char *_data,size_t _len){ size_t size; size_t dmatrix_size; int i; - fprintf(stderr, "Mapping family 3!\n"); if (head.channel_count < 1 || head.channel_count > OP_NCHANNELS_MAX) return OP_EBADHEADER; @@ -125,8 +124,6 @@ int opus_head_parse(OpusHead *_head,const unsigned char *_data,size_t _len){ if (head.coupled_count > head.stream_count) return OP_EBADHEADER; - fprintf(stderr, "streams %d, coupled %d \n", head.stream_count, head.coupled_count); - size = 21 + (head.channel_count * (head.stream_count+head.coupled_count)*2); if (_len < size || head.version <= 1 && _len > size) diff --git a/src/opusfile.c b/src/opusfile.c index 3e4d68b..0e4433d 100644 --- a/src/opusfile.c +++ b/src/opusfile.c @@ -28,7 +28,6 @@ #include "opusfile.h" - /*This implementation is largely based off of libvorbisfile. All of the Ogg bits work roughly the same, though I have made some "improvements" that have not been folded back there, yet.*/ @@ -1376,7 +1375,7 @@ static int op_make_decode_ready(OggOpusFile *_of){ } else{ int err; - if(head->mapping_family==3){ /*probably also better for mapping 2*/ + if(head->mapping_family==3){ #ifdef OPUS_HAVE_OPUS_PROJECTION_H OpusProjectionDecoder *st_dec; const int dmatrix_size = (stream_count + coupled_count) * channel_count * From fd09394af1702b53589bf2173931726911659302 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 6 Feb 2024 20:02:01 +0200 Subject: [PATCH 14/15] Set OPUS_DEMIXING_MATRIX_SIZE_MAX to current max --- include/opusfile.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/opusfile.h b/include/opusfile.h index a68d345..00f16f4 100644 --- a/include/opusfile.h +++ b/include/opusfile.h @@ -213,7 +213,7 @@ typedef struct OggOpusFile OggOpusFile; #ifdef OPUS_HAVE_OPUS_PROJECTION_H /**The maximum size of projection decoder demixing matrix.*/ -#define OPUS_DEMIXING_MATRIX_SIZE_MAX (38 * 38 * 2) +#define OPUS_DEMIXING_MATRIX_SIZE_MAX (18 * 18 * 2) #endif /**Ogg Opus bitstream information. From f2398273d24790cd9e91ba3205b84f6f0eda2348 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 6 Feb 2024 20:02:42 +0200 Subject: [PATCH 15/15] Guard and check in opus_head_parse with map3 --- src/info.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/info.c b/src/info.c index 53729ca..b1f2fbf 100644 --- a/src/info.c +++ b/src/info.c @@ -110,6 +110,7 @@ int opus_head_parse(OpusHead *_head,const unsigned char *_data,size_t _len){ /*Use channel mapping 3 for orders {1, 2, 3} with 4 to 18 channels (including the non-diegetic stereo track). For other orders with no demixing matrices currently available, use channel mapping 2.*/ +#ifdef OPUS_HAVE_OPUS_PROJECTION_H size_t size; size_t dmatrix_size; int i; @@ -131,11 +132,16 @@ int opus_head_parse(OpusHead *_head,const unsigned char *_data,size_t _len){ dmatrix_size = head.channel_count*(head.stream_count+head.coupled_count) * sizeof(opus_int16); + if (dmatrix_size > OPUS_DEMIXING_MATRIX_SIZE_MAX) + return OP_EBADHEADER; memcpy(_head->dmatrix, _data + 21, dmatrix_size); if (_head != NULL){ for (i = 0; i < head.channel_count; i++) _head->mapping[i] = i; } +#else + return OP_EIMPL; +#endif } /*General purpose players should not attempt to play back content with channel mapping family 255.*/