static int opus_repacketizer_cat_impl(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len, int self_delimited) { unsigned char tmp_toc; int curr_nb_frames,ret; /* Set of check ToC */ if (len<1) return OPUS_INVALID_PACKET; if (rp->nb_frames == 0) { rp->toc = data[0]; rp->framesize = opus_packet_get_samples_per_frame(data, 8000); } else if ((rp->toc&0xFC) != (data[0]&0xFC)) { /*fprintf(stderr, "toc mismatch: 0x%x vs 0x%x\n", rp->toc, data[0]);*/ return OPUS_INVALID_PACKET; } curr_nb_frames = opus_packet_get_nb_frames(data, len); if(curr_nb_frames<1) return OPUS_INVALID_PACKET; /* Check the 120 ms maximum packet size */ if ((curr_nb_frames+rp->nb_frames)*rp->framesize > 960) { 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); if(ret<1)return ret; rp->nb_frames += curr_nb_frames; return OPUS_OK; }
int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len, int nb_streams) { int s; int count; unsigned char toc; opus_int16 size[48]; opus_int32 packet_offset; opus_int32 amount; if (len < 1) return OPUS_BAD_ARG; if (len==new_len) return OPUS_OK; else if (len > new_len) return OPUS_BAD_ARG; amount = new_len - len; /* Seek to last stream */ for (s=0;s<nb_streams-1;s++) { if (len<=0) return OPUS_INVALID_PACKET; count = opus_packet_parse_impl(data, len, 1, &toc, NULL, size, NULL, &packet_offset); if (count<0) return count; data += packet_offset; len -= packet_offset; } return opus_packet_pad(data, len, len+amount); }
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); }
static int opus_multistream_packet_validate(const unsigned char *data, opus_int32 len, int nb_streams, opus_int32 Fs) { int s; int count; unsigned char toc; opus_int16 size[48]; int samples=0; opus_int32 packet_offset; for (s=0;s<nb_streams;s++) { int tmp_samples; if (len<=0) return OPUS_INVALID_PACKET; count = opus_packet_parse_impl(data, len, s!=nb_streams-1, &toc, NULL, size, NULL, &packet_offset); if (count<0) return count; tmp_samples = opus_packet_get_nb_samples(data, packet_offset, Fs); if (s!=0 && samples != tmp_samples) return OPUS_INVALID_PACKET; samples = tmp_samples; data += packet_offset; len -= packet_offset; } return samples; }
void save_range(FILE *frange, int frame_size, unsigned char *packet, int nbBytes, opus_uint32 *rngs, int nb_streams){ int i, parsed_size; const unsigned char *subpkt; static const char *bw_strings[5]={"NB","MB","WB","SWB","FB"}; static const char *mode_strings[3]={"LP","HYB","MDCT"}; fprintf(frange,"%d, %d, ",frame_size,nbBytes); subpkt=packet; parsed_size=nbBytes; for(i=0;i<nb_streams;i++){ int j,payload_offset,nf; const unsigned char *frames[48]; unsigned char toc; short size[48]; payload_offset=0; nf=opus_packet_parse_impl(subpkt,parsed_size,i+1!=nb_streams, &toc,frames,size,&payload_offset); fprintf(frange,"[[%d",(int)(frames[0]-subpkt)); for(j=0;j<nf;j++)fprintf(frange,", %d",size[j]); fprintf(frange,"], %s, %s, %c, %d", mode_strings[((((subpkt[0]>>3)+48)&92)+4)>>5], bw_strings[opus_packet_get_bandwidth(subpkt)-OPUS_BANDWIDTH_NARROWBAND], subpkt[0]&4?'S':'M',opus_packet_get_samples_per_frame(subpkt,48000)); fprintf(frange,", %" I64uFORMAT "]%s",(unsigned long long)rngs[i],i+1==nb_streams?"\n":", "); parsed_size-=payload_offset; subpkt+=payload_offset; } }
int opus_decode_native(OpusDecoder *st, const unsigned char *data, int len, opus_val16 *pcm, int frame_size, int decode_fec, int self_delimited, int *packet_offset) { int i, nb_samples; int count, offset; unsigned char toc; int tot_offset; /* 48 x 2.5 ms = 120 ms */ short size[48]; if (decode_fec<0 || decode_fec>1) return OPUS_BAD_ARG; if (len==0 || data==NULL) return opus_decode_frame(st, NULL, 0, pcm, frame_size, 0); 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); count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL, size, &offset); if (count < 0) return count; data += offset; tot_offset += offset; if (count*st->frame_size > frame_size) return OPUS_BUFFER_TOO_SMALL; nb_samples=0; for (i=0;i<count;i++) { int ret; ret = opus_decode_frame(st, data, size[i], pcm, frame_size-nb_samples, decode_fec); if (ret<0) return ret; data += size[i]; tot_offset += size[i]; pcm += ret*st->channels; nb_samples += ret; } if (packet_offset != NULL) *packet_offset = tot_offset; return nb_samples; }
opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, int nb_streams) { int s; unsigned char toc; opus_int16 size[48]; opus_int32 packet_offset; OpusRepacketizer rp; unsigned char *dst; opus_int32 dst_len; if (len < 1) return OPUS_BAD_ARG; dst = data; dst_len = 0; /* Unpad all frames */ for (s=0;s<nb_streams;s++) { opus_int32 ret; int self_delimited = s!=nb_streams-1; if (len<=0) return OPUS_INVALID_PACKET; opus_repacketizer_init(&rp); ret = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL, size, NULL, &packet_offset); if (ret<0) return ret; ret = opus_repacketizer_cat_impl(&rp, data, packet_offset, self_delimited); if (ret < 0) return ret; ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, dst, len, self_delimited, 0); if (ret < 0) return ret; else dst_len += ret; dst += ret; data += packet_offset; len -= packet_offset; } return dst_len; }
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) { int i, nb_samples; int count, offset; unsigned char toc; int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels; /* 48 x 2.5 ms = 120 ms */ opus_int16 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) { int pcm_count=0; do { int ret; ret = opus_decode_frame(st, NULL, 0, pcm+pcm_count*st->channels, frame_size-pcm_count, 0); if (ret<0) return ret; pcm_count += ret; } while (pcm_count < frame_size); celt_assert(pcm_count == frame_size); if (OPUS_CHECK_ARRAY(pcm, pcm_count*st->channels)) OPUS_PRINT_INT(pcm_count); st->last_packet_duration = pcm_count; return pcm_count; } else if (len<0) return OPUS_BAD_ARG; 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, packet_offset); if (count<0) return count; 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, soft_clip); /* Otherwise, run the PLC on everything except the size for which we might have FEC */ duration_copy = st->last_packet_duration; if (frame_size-packet_frame_size!=0) { ret = opus_decode_native(st, NULL, 0, pcm, frame_size-packet_frame_size, 0, 0, NULL, soft_clip); if (ret<0) { st->last_packet_duration = duration_copy; return ret; } celt_assert(ret==frame_size-packet_frame_size); } /* 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; else { if (OPUS_CHECK_ARRAY(pcm, frame_size*st->channels)) OPUS_PRINT_INT(frame_size); st->last_packet_duration = frame_size; return 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++) { int ret; ret = opus_decode_frame(st, data, size[i], pcm+nb_samples*st->channels, frame_size-nb_samples, 0); if (ret<0) return ret; celt_assert(ret==packet_frame_size); data += size[i]; nb_samples += ret; } st->last_packet_duration = nb_samples; if (OPUS_CHECK_ARRAY(pcm, nb_samples*st->channels)) OPUS_PRINT_INT(nb_samples); #ifndef FIXED_POINT if (soft_clip) opus_pcm_soft_clip(pcm, nb_samples, st->channels, st->softclip_mem); else st->softclip_mem[0]=st->softclip_mem[1]=0; #endif return nb_samples; }
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, int *packet_offset) { int i, nb_samples; 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) { 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; 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; tot_offset += offset; 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++) { int ret; ret = opus_decode_frame(st, data, size[i], pcm, frame_size-nb_samples, decode_fec); if (ret<0) return ret; data += size[i]; tot_offset += size[i]; pcm += ret*st->channels; nb_samples += ret; } if (packet_offset != NULL) *packet_offset = tot_offset; st->last_packet_duration = nb_samples; return nb_samples; }