diff options
author | Jean-Marc Valin <jmvalin@amazon.com> | 2022-11-28 16:34:28 -0500 |
---|---|---|
committer | Jean-Marc Valin <jmvalin@amazon.com> | 2022-12-02 03:03:14 -0500 |
commit | 5586ffbc5f8804f323ffc3b9f770371200628116 (patch) | |
tree | b9650f31c69ec9a12791e2ceaf5ad65e103f32c5 /src | |
parent | 27f0c3b2b73c910061e8a3234e4016ee16c389b9 (diff) | |
download | opus-5586ffbc5f8804f323ffc3b9f770371200628116.tar.gz |
Code for inserting/extracting DRED in/from packets
Diffstat (limited to 'src')
-rw-r--r-- | src/extensions.c | 2 | ||||
-rw-r--r-- | src/opus.c | 10 | ||||
-rw-r--r-- | src/opus_decoder.c | 53 | ||||
-rw-r--r-- | src/opus_encoder.c | 11 | ||||
-rw-r--r-- | src/opus_multistream_decoder.c | 2 | ||||
-rw-r--r-- | src/opus_private.h | 8 | ||||
-rw-r--r-- | src/repacketizer.c | 15 |
7 files changed, 89 insertions, 12 deletions
diff --git a/src/extensions.c b/src/extensions.c index b7bafb99..e899ad2b 100644 --- a/src/extensions.c +++ b/src/extensions.c @@ -38,7 +38,7 @@ /* Given an extension payload, advance data to the next extension and return the length of the remaining extensions. */ -static opus_int32 skip_extension(const unsigned char **data, opus_int32 len, opus_int32 *header_size) +opus_int32 skip_extension(const unsigned char **data, opus_int32 len, opus_int32 *header_size) { int id, L; if (len==0) @@ -194,7 +194,8 @@ int opus_packet_get_samples_per_frame(const unsigned char *data, int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, int self_delimited, unsigned char *out_toc, const unsigned char *frames[48], opus_int16 size[48], - int *payload_offset, opus_int32 *packet_offset) + int *payload_offset, opus_int32 *packet_offset, + const unsigned char **padding, opus_int32 *padding_len) { int i, bytes; int count; @@ -337,6 +338,11 @@ int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, data += size[i]; } + if (padding != NULL) + { + *padding = data; + *padding_len = pad; + } if (packet_offset) *packet_offset = pad+(opus_int32)(data-data0); @@ -351,6 +357,6 @@ int opus_packet_parse(const unsigned char *data, opus_int32 len, opus_int16 size[48], int *payload_offset) { return opus_packet_parse_impl(data, len, 0, out_toc, - frames, size, payload_offset, NULL); + frames, size, payload_offset, NULL, NULL, NULL); } diff --git a/src/opus_decoder.c b/src/opus_decoder.c index 6520e748..8cd58a91 100644 --- a/src/opus_decoder.c +++ b/src/opus_decoder.c @@ -672,7 +672,7 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data, packet_stream_channels = opus_packet_get_nb_channels(data); count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL, - size, &offset, packet_offset); + size, &offset, packet_offset, NULL, NULL); if (count<0) return count; @@ -1039,3 +1039,54 @@ int opus_decoder_get_nb_samples(const OpusDecoder *dec, { return opus_packet_get_nb_samples(packet, len, dec->Fs); } + +int opus_decoder_dred_input(OpusDecoder *st, const unsigned char *data, + opus_int32 len, int offset) +{ + const unsigned char *data0; + int len0; + const unsigned char *payload = NULL; + opus_int32 payload_len; + int frame = 0; + int ret; + const unsigned char *frames[48]; + opus_int16 size[48]; + + /* Get the padding section of the packet. */ + ret = opus_packet_parse_impl(data, len, 0, NULL, frames, size, NULL, NULL, &data0, &len0); + data = data0; + len = len0; + /* Scan extensions in order until we find the earliest frame with DRED data. */ + while (len > 0) + { + opus_int32 header_size; + int id, L; + len0 = len; + data0 = data; + id = *data0 >> 1; + L = *data0 & 0x1; + len = skip_extension(&data, len, &header_size); + if (len < 0) + break; + if (id == 1) + { + if (L==0) + { + frame++; + } else { + frame += data[1]; + } + } else if (id == 127) + { + payload = data0+header_size; + payload_len = (data-data0)-header_size; + break; + } + } + if (payload != NULL) + { + /* Found something -- do the decoding. */ + return 1; + } + return 0; +} diff --git a/src/opus_encoder.c b/src/opus_encoder.c index 75f23f8e..2db121a1 100644 --- a/src/opus_encoder.c +++ b/src/opus_encoder.c @@ -1003,6 +1003,7 @@ static opus_int32 encode_multiframe_packet(OpusEncoder *st, } } + /* FIXME: Handle extensions here. */ ret = opus_repacketizer_out_range_impl(rp, 0, nb_frames, data, repacketize_len, 0, !st->use_vbr, NULL, 0); if (ret<0) @@ -2178,7 +2179,15 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ } /* Count ToC and redundancy */ ret += 1+redundancy_bytes; - if (!st->use_vbr) + if (0) { + opus_extension_data extension = {127, 0, (const unsigned char *)"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 50}; + ret = opus_packet_pad_impl(data, ret, max_data_bytes, !st->use_vbr, &extension, 1); + if (ret < 0) + { + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } + } else if (!st->use_vbr) { if (opus_packet_pad(data, ret, max_data_bytes) != OPUS_OK) { diff --git a/src/opus_multistream_decoder.c b/src/opus_multistream_decoder.c index a2837c35..9648c4a7 100644 --- a/src/opus_multistream_decoder.c +++ b/src/opus_multistream_decoder.c @@ -162,7 +162,7 @@ static int opus_multistream_packet_validate(const unsigned char *data, if (len<=0) return OPUS_INVALID_PACKET; count = opus_packet_parse_impl(data, len, s!=nb_streams-1, &toc, NULL, - size, NULL, &packet_offset); + size, NULL, &packet_offset, NULL, NULL); if (count<0) return count; tmp_samples = opus_packet_get_nb_samples(data, packet_offset, Fs); diff --git a/src/opus_private.h b/src/opus_private.h index fe1cc755..4fcd9e34 100644 --- a/src/opus_private.h +++ b/src/opus_private.h @@ -169,10 +169,14 @@ static OPUS_INLINE int align(int i) return ((i + alignment - 1) / alignment) * alignment; } +/* More than that is ridiculous for now (3 * max frames per packet)*/ +opus_int32 skip_extension(const unsigned char **data, opus_int32 len, opus_int32 *header_size); + int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, int self_delimited, unsigned char *out_toc, const unsigned char *frames[48], opus_int16 size[48], - int *payload_offset, opus_int32 *packet_offset); + int *payload_offset, opus_int32 *packet_offset, + const unsigned char **padding, opus_int32 *padding_len); opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen, int self_delimited, int pad, @@ -210,4 +214,6 @@ opus_int32 opus_packet_extensions_parse(const unsigned char *data, opus_int32 le opus_int32 opus_packet_extensions_generate(unsigned char *data, opus_int32 len, const opus_extension_data *extensions, int nb_extensions, int pad); +opus_int32 opus_packet_pad_impl(unsigned char *data, opus_int32 len, opus_int32 new_len, int pad, const opus_extension_data *extensions, int nb_extensions); + #endif /* OPUS_PRIVATE_H */ diff --git a/src/repacketizer.c b/src/repacketizer.c index 0e1e157b..df283ac8 100644 --- a/src/repacketizer.c +++ b/src/repacketizer.c @@ -82,7 +82,7 @@ static int opus_repacketizer_cat_impl(OpusRepacketizer *rp, const unsigned char return OPUS_INVALID_PACKET; } - ret=opus_packet_parse_impl(data, len, self_delimited, &tmp_toc, &rp->frames[rp->nb_frames], &rp->len[rp->nb_frames], NULL, NULL); + ret=opus_packet_parse_impl(data, len, self_delimited, &tmp_toc, &rp->frames[rp->nb_frames], &rp->len[rp->nb_frames], NULL, NULL, NULL, NULL); if(ret<1)return ret; rp->nb_frames += curr_nb_frames; @@ -251,7 +251,7 @@ opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus return opus_repacketizer_out_range_impl(rp, 0, rp->nb_frames, data, maxlen, 0, 0, NULL, 0); } -int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len) +opus_int32 opus_packet_pad_impl(unsigned char *data, opus_int32 len, opus_int32 new_len, int pad, const opus_extension_data *extensions, int nb_extensions) { OpusRepacketizer rp; opus_int32 ret; @@ -267,7 +267,12 @@ int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len) ret = opus_repacketizer_cat(&rp, data+new_len-len, len); if (ret != OPUS_OK) return ret; - ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, new_len, 0, 1, NULL, 0); + return opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, new_len, 0, pad, extensions, nb_extensions); +} + +int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len) +{ + opus_int32 ret = opus_packet_pad_impl(data, len, new_len, 1, NULL, 0); if (ret > 0) return OPUS_OK; else @@ -311,7 +316,7 @@ int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32 if (len<=0) return OPUS_INVALID_PACKET; count = opus_packet_parse_impl(data, len, 1, &toc, NULL, - size, NULL, &packet_offset); + size, NULL, &packet_offset, NULL, NULL); if (count<0) return count; data += packet_offset; @@ -343,7 +348,7 @@ opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, in return OPUS_INVALID_PACKET; opus_repacketizer_init(&rp); ret = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL, - size, NULL, &packet_offset); + size, NULL, &packet_offset, NULL, NULL); if (ret<0) return ret; ret = opus_repacketizer_cat_impl(&rp, data, packet_offset, self_delimited); |