Skip to content

Commit 7caef30

Browse files
authored
impl. Code 3: A Signaled Number of Frames in the Packet for CBR only
RFC 6716, Definition of the Opus Audio Codec, Issue 3.3.2.4 e.g. https://st03.sslstream.dlf.de/dlf/03/high/opus/stream.opus?aggregator=web // (Deutschlandfunk Nova) is working now
1 parent d2433d8 commit 7caef30

File tree

1 file changed

+86
-25
lines changed

1 file changed

+86
-25
lines changed

src/opus_decoder/opus_decoder.cpp

Lines changed: 86 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* based on Xiph.Org Foundation celt decoder
44
*
55
* Created on: 26.01.2023
6-
* Updated on: 07.04.2023
6+
* Updated on: 23.12.2023
77
*/
88
//----------------------------------------------------------------------------------------------------------------------
99
// O G G / O P U S I M P L.
@@ -16,7 +16,9 @@ bool s_f_opusSubsequentPage = false;
1616
bool s_f_opusParseOgg = false;
1717
bool s_f_newSteamTitle = false; // streamTitle
1818
bool s_f_opusFramePacket = false;
19+
bool s_f_opusStereoFlag = false;
1920
uint8_t s_opusChannels = 0;
21+
uint8_t s_opusCountCode = 0;
2022
uint16_t s_opusSamplerate = 0;
2123
uint32_t s_opusSegmentLength = 0;
2224
char *s_opusChbuf = NULL;
@@ -58,13 +60,15 @@ void OPUSsetDefaults(){
5860
s_f_opusParseOgg = false;
5961
s_f_newSteamTitle = false; // streamTitle
6062
s_f_opusFramePacket = false;
63+
s_f_opusStereoFlag = false;
6164
s_opusChannels = 0;
6265
s_opusSamplerate = 0;
6366
s_opusSegmentLength = 0;
6467
s_opusValidSamples = 0;
6568
s_opusSegmentTableSize = 0;
6669
s_opusOldMode = 0xFF;
6770
s_opusSegmentTableRdPtr = -1;
71+
s_opusCountCode = 0;
6872

6973
s_opusError = 0;
7074
}
@@ -73,38 +77,100 @@ void OPUSsetDefaults(){
7377

7478
int OPUSDecode(uint8_t *inbuf, int *bytesLeft, short *outbuf){
7579

80+
static uint16_t fs = 0;
81+
static uint8_t M = 0;
82+
static uint16_t paddingBytes = 0;
83+
static uint16_t samplesPerFrame = 0;
84+
int ret = ERR_OPUS_NONE;
85+
int len = 0;
86+
7687
if(s_f_opusParseOgg){
77-
int ret = OPUSparseOGG(inbuf, bytesLeft);
88+
fs = 0;
89+
M = 0;
90+
paddingBytes = 0;
91+
s_opusCountCode = 0;
92+
ret = OPUSparseOGG(inbuf, bytesLeft);
7893
if(ret == ERR_OPUS_NONE) return OPUS_PARSE_OGG_DONE; // ok
7994
else return ret; // error
8095
}
8196

97+
if(s_opusCountCode == 3) goto FramePacking;
98+
8299
if(s_f_opusFramePacket){
83100
if(s_opusSegmentTableSize > 0){
84101
s_opusSegmentTableRdPtr++;
85102
s_opusSegmentTableSize--;
86-
int len = s_opusSegmentTable[s_opusSegmentTableRdPtr];
103+
len = s_opusSegmentTable[s_opusSegmentTableRdPtr];
104+
}
105+
106+
ret = parseOpusTOC(inbuf[0]);
107+
samplesPerFrame = opus_packet_get_samples_per_frame(inbuf, 48000);
108+
if(ret < 0) goto exit; // error
109+
110+
FramePacking:
111+
112+
// https://www.tech-invite.com/y65/tinv-ietf-rfc-6716-2.html 3.2. Frame Packing
113+
if(s_opusCountCode == 0){ // Code 0: One Frame in the Packet
87114
*bytesLeft -= len;
88-
int32_t ret = parseOpusTOC(inbuf[0]);
89-
if(ret < 0) return ret;
90-
int frame_size = opus_packet_get_samples_per_frame(inbuf, 48000);
115+
ret = parseOpusTOC(inbuf[0]);
116+
if(ret < 0) goto exit; // error
91117
len--;
92118
inbuf++;
93-
94119
ec_dec_init((uint8_t *)inbuf, len);
95-
ret = celt_decode_with_ec(inbuf, len, (int16_t*)outbuf, frame_size);
96-
if(ret < 0) return ret; // celt error
120+
ret = celt_decode_with_ec(inbuf, len, (int16_t*)outbuf, samplesPerFrame);
121+
if(ret < 0) goto exit; // celt error
97122
s_opusValidSamples = ret;
98-
99-
if(s_opusSegmentTableSize== 0){
100-
s_opusSegmentTableRdPtr = -1; // back to the parking position
101-
s_f_opusFramePacket = false;
102-
s_f_opusParseOgg = true;
123+
ret = ERR_OPUS_NONE;
124+
}
125+
if(s_opusCountCode == 1){ // Code 1: Two Frames in the Packet, Each with Equal Compressed Size
126+
log_e("OPUS countCode 1 not supported yet"); vTaskDelay(1000); // todo
127+
}
128+
if(s_opusCountCode == 2){ // Code 2: Two Frames in the Packet, with Different Compressed Sizes
129+
log_e("OPUS countCode 2 not supported yet"); vTaskDelay(1000); // todo
130+
}
131+
if(s_opusCountCode == 3){ // Code 3: A Signaled Number of Frames in the Packet
132+
133+
if(M == 0){
134+
bool v = ((inbuf[1] & 0x80) == 0x80); // VBR indicator
135+
(void)v;
136+
bool p = ((inbuf[1] & 0x40) == 0x40); // padding bit
137+
M = inbuf[1] & 0x3F; // max framecount
138+
// log_i("v %i, p %i, M %i", v, p, M);
139+
paddingBytes = 0;
140+
if(p){
141+
int i = 0;
142+
while(inbuf[2 + i] == 255){
143+
paddingBytes += inbuf[2 + i];
144+
i++;
145+
}
146+
paddingBytes += inbuf[2 + i];
147+
fs = (len - 3 - i - paddingBytes) / M;
148+
*bytesLeft -= 3 + i;
149+
inbuf += 3 + i;
150+
}
103151
}
152+
*bytesLeft -= fs;
153+
ec_dec_init((uint8_t *)inbuf, fs);
154+
ret = celt_decode_with_ec(inbuf, fs, (int16_t*)outbuf, samplesPerFrame);
155+
if(ret < 0) goto exit; // celt error
156+
s_opusValidSamples = ret;
157+
M--;
158+
// log_i("M %i fs %i spf %i", M, fs, samplesPerFrame);
159+
ret = ERR_OPUS_NONE;
160+
if(M == 0) {s_opusCountCode = 0; *bytesLeft -= paddingBytes; goto exit;}
161+
return ret;
104162
}
105163
}
106-
return ERR_OPUS_NONE;
164+
165+
exit:
166+
if(s_opusSegmentTableSize== 0){
167+
s_opusSegmentTableRdPtr = -1; // back to the parking position
168+
s_f_opusFramePacket = false;
169+
s_f_opusParseOgg = true;
170+
}
171+
return ret;
107172
}
173+
108174
//----------------------------------------------------------------------------------------------------------------------
109175

110176
int32_t opus_packet_get_samples_per_frame(const uint8_t *data, int32_t Fs) {
@@ -155,8 +221,8 @@ int parseOpusTOC(uint8_t TOC_Byte){ // https://www.rfc-editor.org/rfc/rfc6716
155221

156222
uint8_t mode = 0;
157223
uint8_t configNr = 0;
158-
uint8_t s = 0;
159-
uint8_t c = 0; (void)c;
224+
uint8_t s = 0; // stereo flag
225+
uint8_t c = 0; (void)c; // count code
160226

161227
configNr = (TOC_Byte & 0b11111000) >> 3;
162228
s = (TOC_Byte & 0b00000100) >> 2;
@@ -184,18 +250,13 @@ int parseOpusTOC(uint8_t TOC_Byte){ // https://www.rfc-editor.org/rfc/rfc6716
184250
c = 2: 2 frames in the packet, with different compressed sizes
185251
c = 3: an arbitrary number of frames in the packet
186252
*/
187-
188-
// log_i("configNr %i, s %i, c %i", configNr, s, c);
189-
190-
if(c == 3) { // todo https://www.rfc-editor.org/rfc/rfc6716#page-16 3.2.3. at page 17
191-
log_e("an arbitrary number of frames in the packet is unsupported yet");
192-
vTaskDelay(1000);
193-
}
253+
s_opusCountCode = c;
254+
s_f_opusStereoFlag = s;
194255

195256
if(configNr < 12) return ERR_OPUS_SILK_MODE_UNSUPPORTED;
196257
if(configNr < 16) return ERR_OPUS_HYBRID_MODE_UNSUPPORTED;
197258

198-
return s;
259+
return configNr;
199260
}
200261
//----------------------------------------------------------------------------------------------------------------------
201262
int parseOpusComment(uint8_t *inbuf, int nBytes){ // reference https://exiftool.org/TagNames/Vorbis.html#Comments

0 commit comments

Comments
 (0)