opus_packet_parse_impl() now computes the packet size with padding

This should fix decoding of padded multistream packets and (hopefully)
multistream fec.
This commit is contained in:
Jean-Marc Valin 2013-10-14 13:45:58 -04:00
parent 2a82908062
commit 58042adc19
3 changed files with 24 additions and 24 deletions

View file

@ -601,7 +601,8 @@ static int parse_size(const unsigned char *data, opus_int32 len, opus_int16 *siz
int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
int self_delimited, unsigned char *out_toc, int self_delimited, unsigned char *out_toc,
const unsigned char *frames[48], opus_int16 size[48], int *payload_offset) const unsigned char *frames[48], opus_int16 size[48],
int *payload_offset, opus_int32 *packet_offset)
{ {
int i, bytes; int i, bytes;
int count; int count;
@ -609,6 +610,7 @@ int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
unsigned char ch, toc; unsigned char ch, toc;
int framesize; int framesize;
opus_int32 last_size; opus_int32 last_size;
opus_int32 pad = 0;
const unsigned char *data0 = data; const unsigned char *data0 = data;
if (size==NULL) if (size==NULL)
@ -664,11 +666,14 @@ int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
{ {
int p; int p;
do { do {
int tmp;
if (len<=0) if (len<=0)
return OPUS_INVALID_PACKET; return OPUS_INVALID_PACKET;
p = *data++; p = *data++;
len--; len--;
len -= p==255 ? 254: p; tmp = p==255 ? 254: p;
len -= tmp;
pad += tmp;
} while (p==255); } while (p==255);
} }
if (len<0) if (len<0)
@ -731,15 +736,16 @@ int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
if (payload_offset) if (payload_offset)
*payload_offset = (int)(data-data0); *payload_offset = (int)(data-data0);
if (frames) for (i=0;i<count;i++)
{ {
for (i=0;i<count;i++) if (frames)
{
frames[i] = data; frames[i] = data;
data += size[i]; data += size[i];
}
} }
if (packet_offset)
*packet_offset = pad+(opus_int32)(data-data0);
if (out_toc) if (out_toc)
*out_toc = toc; *out_toc = toc;
@ -751,7 +757,7 @@ int opus_packet_parse(const unsigned char *data, opus_int32 len,
opus_int16 size[48], int *payload_offset) opus_int16 size[48], int *payload_offset)
{ {
return opus_packet_parse_impl(data, len, 0, out_toc, return opus_packet_parse_impl(data, len, 0, out_toc,
frames, size, payload_offset); frames, size, payload_offset, NULL);
} }
int opus_decode_native(OpusDecoder *st, const unsigned char *data, int opus_decode_native(OpusDecoder *st, const unsigned char *data,
@ -761,7 +767,6 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data,
int i, nb_samples; int i, nb_samples;
int count, offset; int count, offset;
unsigned char toc; unsigned char toc;
int tot_offset;
int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels; int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels;
/* 48 x 2.5 ms = 120 ms */ /* 48 x 2.5 ms = 120 ms */
opus_int16 size[48]; opus_int16 size[48];
@ -793,8 +798,8 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data,
packet_frame_size = opus_packet_get_samples_per_frame(data, st->Fs); packet_frame_size = opus_packet_get_samples_per_frame(data, st->Fs);
packet_stream_channels = opus_packet_get_nb_channels(data); packet_stream_channels = opus_packet_get_nb_channels(data);
count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL, size, &offset); count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL,
size, &offset, packet_offset);
if (count<0) if (count<0)
return count; return count;
@ -835,7 +840,6 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data,
return frame_size; return frame_size;
} }
} }
tot_offset = offset;
if (count*packet_frame_size > frame_size) if (count*packet_frame_size > frame_size)
return OPUS_BUFFER_TOO_SMALL; return OPUS_BUFFER_TOO_SMALL;
@ -855,11 +859,8 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data,
return ret; return ret;
celt_assert(ret==packet_frame_size); celt_assert(ret==packet_frame_size);
data += size[i]; data += size[i];
tot_offset += size[i];
nb_samples += ret; nb_samples += ret;
} }
if (packet_offset != NULL)
*packet_offset = tot_offset;
st->last_packet_duration = nb_samples; st->last_packet_duration = nb_samples;
if (OPUS_CHECK_ARRAY(pcm, nb_samples*st->channels)) if (OPUS_CHECK_ARRAY(pcm, nb_samples*st->channels))
OPUS_PRINT_INT(nb_samples); OPUS_PRINT_INT(nb_samples);

View file

@ -156,29 +156,27 @@ static int opus_multistream_packet_validate(const unsigned char *data,
opus_int32 len, int nb_streams, opus_int32 Fs) opus_int32 len, int nb_streams, opus_int32 Fs)
{ {
int s; int s;
int i;
int count; int count;
unsigned char toc; unsigned char toc;
opus_int16 size[48]; opus_int16 size[48];
int offset;
int samples=0; int samples=0;
opus_int32 packet_offset;
for (s=0;s<nb_streams;s++) for (s=0;s<nb_streams;s++)
{ {
int tmp_samples; int tmp_samples;
if (len<=0) if (len<=0)
return OPUS_INVALID_PACKET; return OPUS_INVALID_PACKET;
count = opus_packet_parse_impl(data, len, s!=nb_streams-1, &toc, NULL, size, &offset); count = opus_packet_parse_impl(data, len, s!=nb_streams-1, &toc, NULL,
size, NULL, &packet_offset);
if (count<0) if (count<0)
return count; return count;
for (i=0;i<count;i++) tmp_samples = opus_packet_get_nb_samples(data, packet_offset, Fs);
offset += size[i];
tmp_samples = opus_packet_get_nb_samples(data, offset, Fs);
if (s!=0 && samples != tmp_samples) if (s!=0 && samples != tmp_samples)
return OPUS_INVALID_PACKET; return OPUS_INVALID_PACKET;
samples = tmp_samples; samples = tmp_samples;
data += offset; data += packet_offset;
len -= offset; len -= packet_offset;
} }
return samples; return samples;
} }

View file

@ -114,7 +114,8 @@ static inline int align(int i)
int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
int self_delimited, unsigned char *out_toc, int self_delimited, unsigned char *out_toc,
const unsigned char *frames[48], opus_int16 size[48], int *payload_offset); const unsigned char *frames[48], opus_int16 size[48],
int *payload_offset, int *opus_int32);
opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen, int self_delimited); opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen, int self_delimited);