diff options
author | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2013-10-29 00:41:26 +0400 |
---|---|---|
committer | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2013-10-29 00:41:26 +0400 |
commit | 0fb0fd715cc85a7c4d710a94d740a1ece11ad275 (patch) | |
tree | 97d3d1a50fec486a5ca88b5e9d4fc2c2a2e9788b | |
parent | 811db62ead34b114244892d1d594bb3564211e6e (diff) |
Moves opus_packet_parse_impl() from opus_decoder.c to opus.c
Because it's indirectly used in the encoder (through the repackerizer).
-rw-r--r-- | src/opus.c | 181 | ||||
-rw-r--r-- | src/opus_decoder.c | 181 |
2 files changed, 181 insertions, 181 deletions
@@ -144,3 +144,184 @@ int encode_size(int size, unsigned char *data) } } +static int parse_size(const unsigned char *data, opus_int32 len, opus_int16 *size) +{ + if (len<1) + { + *size = -1; + return -1; + } else if (data[0]<252) + { + *size = data[0]; + return 1; + } else if (len<2) + { + *size = -1; + return -1; + } else { + *size = 4*data[1] + data[0]; + return 2; + } +} + +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 i, bytes; + int count; + int cbr; + unsigned char ch, toc; + int framesize; + opus_int32 last_size; + opus_int32 pad = 0; + const unsigned char *data0 = data; + + if (size==NULL) + return OPUS_BAD_ARG; + + framesize = opus_packet_get_samples_per_frame(data, 48000); + + cbr = 0; + toc = *data++; + len--; + last_size = len; + switch (toc&0x3) + { + /* One frame */ + case 0: + count=1; + break; + /* Two CBR frames */ + case 1: + count=2; + cbr = 1; + if (!self_delimited) + { + if (len&0x1) + return OPUS_INVALID_PACKET; + last_size = len/2; + /* If last_size doesn't fit in size[0], we'll catch it later */ + size[0] = (opus_int16)last_size; + } + break; + /* Two VBR frames */ + case 2: + count = 2; + bytes = parse_size(data, len, size); + len -= bytes; + if (size[0]<0 || size[0] > len) + return OPUS_INVALID_PACKET; + data += bytes; + last_size = len-size[0]; + break; + /* Multiple CBR/VBR frames (from 0 to 120 ms) */ + default: /*case 3:*/ + if (len<1) + return OPUS_INVALID_PACKET; + /* Number of frames encoded in bits 0 to 5 */ + ch = *data++; + count = ch&0x3F; + if (count <= 0 || framesize*count > 5760) + return OPUS_INVALID_PACKET; + len--; + /* Padding flag is bit 6 */ + if (ch&0x40) + { + int p; + do { + int tmp; + if (len<=0) + return OPUS_INVALID_PACKET; + p = *data++; + len--; + tmp = p==255 ? 254: p; + len -= tmp; + pad += tmp; + } while (p==255); + } + if (len<0) + return OPUS_INVALID_PACKET; + /* VBR flag is bit 7 */ + cbr = !(ch&0x80); + if (!cbr) + { + /* VBR case */ + last_size = len; + for (i=0;i<count-1;i++) + { + bytes = parse_size(data, len, size+i); + len -= bytes; + if (size[i]<0 || size[i] > len) + return OPUS_INVALID_PACKET; + data += bytes; + last_size -= bytes+size[i]; + } + if (last_size<0) + return OPUS_INVALID_PACKET; + } else if (!self_delimited) + { + /* CBR case */ + last_size = len/count; + if (last_size*count!=len) + return OPUS_INVALID_PACKET; + for (i=0;i<count-1;i++) + size[i] = (opus_int16)last_size; + } + break; + } + /* Self-delimited framing has an extra size for the last frame. */ + if (self_delimited) + { + bytes = parse_size(data, len, size+count-1); + len -= bytes; + if (size[count-1]<0 || size[count-1] > len) + return OPUS_INVALID_PACKET; + data += bytes; + /* For CBR packets, apply the size to all the frames. */ + if (cbr) + { + if (size[count-1]*count > len) + return OPUS_INVALID_PACKET; + for (i=0;i<count-1;i++) + size[i] = size[count-1]; + } else if (bytes+size[count-1] > last_size) + return OPUS_INVALID_PACKET; + } else + { + /* Because it's not encoded explicitly, it's possible the size of the + last packet (or all the packets, for the CBR case) is larger than + 1275. Reject them here.*/ + if (last_size > 1275) + return OPUS_INVALID_PACKET; + size[count-1] = (opus_int16)last_size; + } + + if (payload_offset) + *payload_offset = (int)(data-data0); + + for (i=0;i<count;i++) + { + if (frames) + frames[i] = data; + data += size[i]; + } + + if (packet_offset) + *packet_offset = pad+(opus_int32)(data-data0); + + if (out_toc) + *out_toc = toc; + + return count; +} + +int opus_packet_parse(const unsigned char *data, opus_int32 len, + unsigned char *out_toc, const unsigned char *frames[48], + opus_int16 size[48], int *payload_offset) +{ + return opus_packet_parse_impl(data, len, 0, out_toc, + frames, size, payload_offset, NULL); +} + diff --git a/src/opus_decoder.c b/src/opus_decoder.c index 666109ae..fc6f7b04 100644 --- a/src/opus_decoder.c +++ b/src/opus_decoder.c @@ -583,187 +583,6 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, } -static int parse_size(const unsigned char *data, opus_int32 len, opus_int16 *size) -{ - if (len<1) - { - *size = -1; - return -1; - } else if (data[0]<252) - { - *size = data[0]; - return 1; - } else if (len<2) - { - *size = -1; - return -1; - } else { - *size = 4*data[1] + data[0]; - return 2; - } -} - -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 i, bytes; - int count; - int cbr; - unsigned char ch, toc; - int framesize; - opus_int32 last_size; - opus_int32 pad = 0; - const unsigned char *data0 = data; - - if (size==NULL) - return OPUS_BAD_ARG; - - framesize = opus_packet_get_samples_per_frame(data, 48000); - - cbr = 0; - toc = *data++; - len--; - last_size = len; - switch (toc&0x3) - { - /* One frame */ - case 0: - count=1; - break; - /* Two CBR frames */ - case 1: - count=2; - cbr = 1; - if (!self_delimited) - { - if (len&0x1) - return OPUS_INVALID_PACKET; - last_size = len/2; - /* If last_size doesn't fit in size[0], we'll catch it later */ - size[0] = (opus_int16)last_size; - } - break; - /* Two VBR frames */ - case 2: - count = 2; - bytes = parse_size(data, len, size); - len -= bytes; - if (size[0]<0 || size[0] > len) - return OPUS_INVALID_PACKET; - data += bytes; - last_size = len-size[0]; - break; - /* Multiple CBR/VBR frames (from 0 to 120 ms) */ - default: /*case 3:*/ - if (len<1) - return OPUS_INVALID_PACKET; - /* Number of frames encoded in bits 0 to 5 */ - ch = *data++; - count = ch&0x3F; - if (count <= 0 || framesize*count > 5760) - return OPUS_INVALID_PACKET; - len--; - /* Padding flag is bit 6 */ - if (ch&0x40) - { - int p; - do { - int tmp; - if (len<=0) - return OPUS_INVALID_PACKET; - p = *data++; - len--; - tmp = p==255 ? 254: p; - len -= tmp; - pad += tmp; - } while (p==255); - } - if (len<0) - return OPUS_INVALID_PACKET; - /* VBR flag is bit 7 */ - cbr = !(ch&0x80); - if (!cbr) - { - /* VBR case */ - last_size = len; - for (i=0;i<count-1;i++) - { - bytes = parse_size(data, len, size+i); - len -= bytes; - if (size[i]<0 || size[i] > len) - return OPUS_INVALID_PACKET; - data += bytes; - last_size -= bytes+size[i]; - } - if (last_size<0) - return OPUS_INVALID_PACKET; - } else if (!self_delimited) - { - /* CBR case */ - last_size = len/count; - if (last_size*count!=len) - return OPUS_INVALID_PACKET; - for (i=0;i<count-1;i++) - size[i] = (opus_int16)last_size; - } - break; - } - /* Self-delimited framing has an extra size for the last frame. */ - if (self_delimited) - { - bytes = parse_size(data, len, size+count-1); - len -= bytes; - if (size[count-1]<0 || size[count-1] > len) - return OPUS_INVALID_PACKET; - data += bytes; - /* For CBR packets, apply the size to all the frames. */ - if (cbr) - { - if (size[count-1]*count > len) - return OPUS_INVALID_PACKET; - for (i=0;i<count-1;i++) - size[i] = size[count-1]; - } else if (bytes+size[count-1] > last_size) - return OPUS_INVALID_PACKET; - } else - { - /* Because it's not encoded explicitly, it's possible the size of the - last packet (or all the packets, for the CBR case) is larger than - 1275. Reject them here.*/ - if (last_size > 1275) - return OPUS_INVALID_PACKET; - size[count-1] = (opus_int16)last_size; - } - - if (payload_offset) - *payload_offset = (int)(data-data0); - - for (i=0;i<count;i++) - { - if (frames) - frames[i] = data; - data += size[i]; - } - - if (packet_offset) - *packet_offset = pad+(opus_int32)(data-data0); - - if (out_toc) - *out_toc = toc; - - return count; -} - -int opus_packet_parse(const unsigned char *data, opus_int32 len, - unsigned char *out_toc, const unsigned char *frames[48], - opus_int16 size[48], int *payload_offset) -{ - return opus_packet_parse_impl(data, len, 0, out_toc, - frames, size, payload_offset, NULL); -} - int opus_decode_native(OpusDecoder *st, const unsigned char *data, opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec, int self_delimited, opus_int32 *packet_offset, int soft_clip) |