diff --git a/src/opus_multistream.c b/src/opus_multistream.c index be96f4e67c9354a13427a586825453315fa46b91..b02636a7a4680a32c96b3876ab7eccf674cde6b2 100644 --- a/src/opus_multistream.c +++ b/src/opus_multistream.c @@ -235,10 +235,15 @@ int opus_multistream_encode_float( char *ptr; int tot_size; VARDECL(opus_val16, buf); - unsigned char tmp_data[1276]; + /* Max size in case the encoder decides to return three frames */ + unsigned char tmp_data[3*1275+7]; + VARDECL(unsigned char, rp_); + OpusRepacketizer *rp; ALLOC_STACK; ALLOC(buf, 2*frame_size, opus_val16); + ALLOC(rp_, opus_repacketizer_get_size(), unsigned char); + rp = (OpusRepacketizer*)rp_; ptr = (char*)st + align(sizeof(OpusMSEncoder)); coupled_size = opus_encoder_get_size(2); mono_size = opus_encoder_get_size(1); @@ -256,6 +261,7 @@ int opus_multistream_encode_float( int len; int curr_max; + opus_repacketizer_init(rp); enc = (OpusEncoder*)ptr; if (s < st->layout.nb_coupled_streams) { @@ -284,17 +290,13 @@ int opus_multistream_encode_float( RESTORE_STACK; return len; } - /* ToC first */ - *data++ = tmp_data[0]; - if (s != st->layout.nb_streams-1) - { - int tmp = encode_size(len-1, data); - data += tmp; - tot_size += tmp; - } - /* IMPORTANT: Here we assume that the encoder only returned one frame */ + /* We need to use the repacketizer to add the self-delimiting lengths + while taking into account the fact that the encoder can now return + more than one frame at a time (e.g. 60 ms CELT-only) */ + opus_repacketizer_cat(rp, tmp_data, len); + len = opus_repacketizer_out_range_impl(rp, 0, opus_repacketizer_get_nb_frames(rp), data, max_data_bytes-tot_size, s != st->layout.nb_streams-1); + data += len; tot_size += len; - OPUS_COPY(data, &tmp_data[1], len-1); } RESTORE_STACK; return tot_size; diff --git a/src/opus_private.h b/src/opus_private.h index fd1310ce61889100f159884d6e6ddd8e80db5381..555f8b07bd72cdf2063532b1717be50df5d1f06d 100644 --- a/src/opus_private.h +++ b/src/opus_private.h @@ -52,4 +52,6 @@ static inline int align(int i) return (i+3)&-4; } +int opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end, unsigned char *data, int maxlen, int self_delimited); + #endif /* OPUS_PRIVATE_H_ */ diff --git a/src/repacketizer.c b/src/repacketizer.c index f72925dd1221a26ad9d42fb29fae077ea9b473f4..7ee0e497f9f2d53e7651bc4396edbb257f835f13 100644 --- a/src/repacketizer.c +++ b/src/repacketizer.c @@ -97,7 +97,7 @@ int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp) return rp->nb_frames; } -int opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, int maxlen) +int opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end, unsigned char *data, int maxlen, int self_delimited) { int i, count, tot_size; short *len; @@ -112,12 +112,17 @@ int opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsign len = rp->len+begin; frames = rp->frames+begin; + if (self_delimited) + tot_size = 1 + len[count-1]>=252; + else + tot_size = 0; + switch (count) { case 1: { /* Code 0 */ - tot_size = len[0]+1; + tot_size += len[0]+1; if (tot_size > maxlen) return OPUS_BUFFER_TOO_SMALL; *data++ = rp->toc&0xFC; @@ -128,13 +133,13 @@ int opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsign if (len[1] == len[0]) { /* Code 1 */ - tot_size = 2*len[0]+1; + tot_size += 2*len[0]+1; if (tot_size > maxlen) return OPUS_BUFFER_TOO_SMALL; *data++ = (rp->toc&0xFC) | 0x1; } else { /* Code 2 */ - tot_size = len[0]+len[1]+2+(len[0]>=252); + tot_size += len[0]+len[1]+2+(len[0]>=252); if (tot_size > maxlen) return OPUS_BUFFER_TOO_SMALL; *data++ = (rp->toc&0xFC) | 0x2; @@ -158,7 +163,7 @@ int opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsign } if (vbr) { - tot_size = 2; + tot_size += 2; for (i=0;i<count-1;i++) tot_size += 1 + (len[i]>=252) + len[i]; tot_size += len[count-1]; @@ -170,7 +175,7 @@ int opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsign for (i=0;i<count-1;i++) data += encode_size(len[i], data); } else { - tot_size = count*len[0]+2; + tot_size += count*len[0]+2; if (tot_size > maxlen) return OPUS_BUFFER_TOO_SMALL; *data++ = (rp->toc&0xFC) | 0x3; @@ -179,6 +184,8 @@ int opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsign } break; } + if (self_delimited) + data += encode_size(len[count-1], data); /* Copy the actual data */ for (i=0;i<count;i++) { @@ -188,9 +195,14 @@ int opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsign return tot_size; } +int opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, int maxlen) +{ + return opus_repacketizer_out_range_impl(rp, begin, end, data, maxlen, 0); +} + int opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, int maxlen) { - return opus_repacketizer_out_range(rp, 0, rp->nb_frames, data, maxlen); + return opus_repacketizer_out_range_impl(rp, 0, rp->nb_frames, data, maxlen, 0); }