Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(179)

Unified Diff: src/opus_decoder.c

Issue 12388030: Update Opus to 1.0.2. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/opus
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/opus_compare.c ('k') | src/opus_demo.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/opus_decoder.c
diff --git a/src/opus_decoder.c b/src/opus_decoder.c
index f0188cdaedbb4866967d267b5c041c20202634f5..ad5f747016242b43a042e4f44217a5a377412096 100644
--- a/src/opus_decoder.c
+++ b/src/opus_decoder.c
@@ -30,7 +30,7 @@
#endif
#ifndef OPUS_BUILD
-#error "OPUS_BUILD _MUST_ be defined to build Opus and you probably want a decent config.h, see README for more details."
+#error "OPUS_BUILD _MUST_ be defined to build Opus. This probably means you need other defines as well, as in a config.h. See the included build files for details."
#endif
#include <stdarg.h>
@@ -64,6 +64,7 @@ struct OpusDecoder {
int prev_mode;
int frame_size;
int prev_redundancy;
+ int last_packet_duration;
opus_uint32 rangeFinal;
};
@@ -257,23 +258,10 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
}
}
- /* For CELT/hybrid PLC of more than 20 ms, do multiple calls */
- if (data==NULL && frame_size > F20 && mode != MODE_SILK_ONLY)
- {
- int nb_samples = 0;
- do {
- int ret = opus_decode_frame(st, NULL, 0, pcm, F20, 0);
- if (ret != F20)
- {
- RESTORE_STACK;
- return OPUS_INTERNAL_ERROR;
- }
- pcm += F20*st->channels;
- nb_samples += F20;
- } while (nb_samples < frame_size);
- RESTORE_STACK;
- return frame_size;
- }
+ /* For CELT/hybrid PLC of more than 20 ms, opus_decode_native() will do
+ multiple calls */
+ if (data==NULL && mode != MODE_SILK_ONLY)
+ frame_size = IMIN(frame_size, F20);
ALLOC(pcm_transition, F5*st->channels, opus_val16);
if (data!=NULL && st->prev_mode > 0 && (
@@ -560,7 +548,7 @@ static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
int cbr;
unsigned char ch, toc;
int framesize;
- int last_size;
+ opus_int32 last_size;
const unsigned char *data0 = data;
if (size==NULL)
@@ -586,7 +574,9 @@ static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
{
if (len&0x1)
return OPUS_INVALID_PACKET;
- size[0] = last_size = len/2;
+ last_size = len/2;
+ /* If last_size doesn't fit in size[0], we'll catch it later */
+ size[0] = (short)last_size;
}
break;
/* Two VBR frames */
@@ -647,7 +637,7 @@ static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
if (last_size*count!=len)
return OPUS_INVALID_PACKET;
for (i=0;i<count-1;i++)
- size[i] = last_size;
+ size[i] = (short)last_size;
}
break;
}
@@ -675,7 +665,7 @@ static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
1275. Reject them here.*/
if (last_size > 1275)
return OPUS_INVALID_PACKET;
- size[count-1] = last_size;
+ size[count-1] = (short)last_size;
}
if (frames)
@@ -712,30 +702,81 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data,
int count, offset;
unsigned char toc;
int tot_offset;
+ int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels;
/* 48 x 2.5 ms = 120 ms */
short size[48];
if (decode_fec<0 || decode_fec>1)
return OPUS_BAD_ARG;
+ /* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */
+ if ((decode_fec || len==0 || data==NULL) && frame_size%(st->Fs/400)!=0)
+ return OPUS_BAD_ARG;
if (len==0 || data==NULL)
- return opus_decode_frame(st, NULL, 0, pcm, frame_size, 0);
- else if (len<0)
+ {
+ int pcm_count=0;
+ do {
+ int ret;
+ ret = opus_decode_frame(st, NULL, 0, pcm, frame_size-pcm_count, 0);
+ if (ret<0)
+ return ret;
+ pcm += st->channels*ret;
+ pcm_count += ret;
+ } while (pcm_count < frame_size);
+ st->last_packet_duration = pcm_count;
+ return pcm_count;
+ } else if (len<0)
return OPUS_BAD_ARG;
- tot_offset = 0;
- st->mode = opus_packet_get_mode(data);
- st->bandwidth = opus_packet_get_bandwidth(data);
- st->frame_size = opus_packet_get_samples_per_frame(data, st->Fs);
- st->stream_channels = opus_packet_get_nb_channels(data);
+ packet_mode = opus_packet_get_mode(data);
+ packet_bandwidth = opus_packet_get_bandwidth(data);
+ packet_frame_size = opus_packet_get_samples_per_frame(data, st->Fs);
+ packet_stream_channels = opus_packet_get_nb_channels(data);
count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL, size, &offset);
+
+ data += offset;
+
+ if (decode_fec)
+ {
+ int duration_copy;
+ int ret;
+ /* If no FEC can be present, run the PLC (recursive call) */
+ if (frame_size <= packet_frame_size || packet_mode == MODE_CELT_ONLY || st->mode == MODE_CELT_ONLY)
+ return opus_decode_native(st, NULL, 0, pcm, frame_size, 0, 0, NULL);
+ /* Otherwise, run the PLC on everything except the size for which we might have FEC */
+ duration_copy = st->last_packet_duration;
+ ret = opus_decode_native(st, NULL, 0, pcm, frame_size-packet_frame_size, 0, 0, NULL);
+ if (ret<0)
+ {
+ st->last_packet_duration = duration_copy;
+ return ret;
+ }
+ /* Complete with FEC */
+ st->mode = packet_mode;
+ st->bandwidth = packet_bandwidth;
+ st->frame_size = packet_frame_size;
+ st->stream_channels = packet_stream_channels;
+ ret = opus_decode_frame(st, data, size[0], pcm+st->channels*(frame_size-packet_frame_size),
+ packet_frame_size, 1);
+ if (ret<0)
+ return ret;
+ st->last_packet_duration = frame_size;
+ return frame_size;
+ }
+ tot_offset = 0;
if (count < 0)
return count;
- data += offset;
tot_offset += offset;
- if (count*st->frame_size > frame_size)
+ if (count*packet_frame_size > frame_size)
return OPUS_BUFFER_TOO_SMALL;
+
+ /* Update the state as the last step to avoid updating it on an invalid packet */
+ st->mode = packet_mode;
+ st->bandwidth = packet_bandwidth;
+ st->frame_size = packet_frame_size;
+ st->stream_channels = packet_stream_channels;
+
nb_samples=0;
for (i=0;i<count;i++)
{
@@ -750,6 +791,7 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data,
}
if (packet_offset != NULL)
*packet_offset = tot_offset;
+ st->last_packet_duration = nb_samples;
return nb_samples;
}
@@ -903,6 +945,12 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
st->decode_gain = value;
}
break;
+ case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
+ {
+ opus_uint32 *value = va_arg(ap, opus_uint32*);
+ *value = st->last_packet_duration;
+ }
+ break;
default:
/*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/
ret = OPUS_UNIMPLEMENTED;
@@ -979,8 +1027,8 @@ int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len)
return packet[1]&0x3F;
}
-int opus_decoder_get_nb_samples(const OpusDecoder *dec,
- const unsigned char packet[], opus_int32 len)
+int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len,
+ opus_int32 Fs)
{
int samples;
int count = opus_packet_get_nb_frames(packet, len);
@@ -988,10 +1036,16 @@ int opus_decoder_get_nb_samples(const OpusDecoder *dec,
if (count<0)
return count;
- samples = count*opus_packet_get_samples_per_frame(packet, dec->Fs);
+ samples = count*opus_packet_get_samples_per_frame(packet, Fs);
/* Can't have more than 120 ms */
- if (samples*25 > dec->Fs*3)
+ if (samples*25 > Fs*3)
return OPUS_INVALID_PACKET;
else
return samples;
}
+
+int opus_decoder_get_nb_samples(const OpusDecoder *dec,
+ const unsigned char packet[], opus_int32 len)
+{
+ return opus_packet_get_nb_samples(packet, len, dec->Fs);
+}
« no previous file with comments | « src/opus_compare.c ('k') | src/opus_demo.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698