internal int opus_repacketizer_cat_impl(byte[] data, int data_ptr, int len, int self_delimited) { byte dummy_toc; int dummy_offset; int curr_nb_frames, ret; /* Set of check ToC */ if (len < 1) { return(OpusError.OPUS_INVALID_PACKET); } if (this.nb_frames == 0) { this.toc = data[data_ptr]; this.framesize = OpusPacketInfo.GetNumSamplesPerFrame(data, data_ptr, 8000); } else if ((this.toc & 0xFC) != (data[data_ptr] & 0xFC)) { /*fprintf(stderr, "toc mismatch: 0x%x vs 0x%x\n", rp.toc, data[0]);*/ return(OpusError.OPUS_INVALID_PACKET); } curr_nb_frames = OpusPacketInfo.GetNumFrames(data, data_ptr, len); if (curr_nb_frames < 1) { return(OpusError.OPUS_INVALID_PACKET); } /* Check the 120 ms maximum packet size */ if ((curr_nb_frames + this.nb_frames) * this.framesize > 960) { return(OpusError.OPUS_INVALID_PACKET); } ret = OpusPacketInfo.opus_packet_parse_impl(data, data_ptr, len, self_delimited, out dummy_toc, this.frames, this.frames_ptrs, this.nb_frames, this.len, this.nb_frames, out dummy_offset, out dummy_offset); if (ret < 1) { return(ret); } this.nb_frames += curr_nb_frames; return(OpusError.OPUS_OK); }
internal int opus_decode_native(byte[] data, int data_ptr, int len, short[] pcm_out, int pcm_out_ptr, int frame_size, int decode_fec, int self_delimited, out int packet_offset, int soft_clip) { int i, nb_samples; int count, offset; byte toc; int packet_frame_size, packet_stream_channels; packet_offset = 0; OpusBandwidth packet_bandwidth; OpusMode packet_mode; /* 48 x 2.5 ms = 120 ms */ // fixme: make sure these values can fit in an int16 short[] size = new short[48]; if (decode_fec < 0 || decode_fec > 1) { return(OpusError.OPUS_BAD_ARG); } /* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */ if ((decode_fec != 0 || len == 0 || data == null) && frame_size % (this.Fs / 400) != 0) { return(OpusError.OPUS_BAD_ARG); } if (len == 0 || data == null) { int pcm_count = 0; do { int ret; ret = opus_decode_frame(null, 0, 0, pcm_out, pcm_out_ptr + (pcm_count * this.channels), frame_size - pcm_count, 0); if (ret < 0) { return(ret); } pcm_count += ret; } while (pcm_count < frame_size); Inlines.OpusAssert(pcm_count == frame_size); this.last_packet_duration = pcm_count; return(pcm_count); } else if (len < 0) { return(OpusError.OPUS_BAD_ARG); } packet_mode = OpusPacketInfo.GetEncoderMode(data, data_ptr); packet_bandwidth = OpusPacketInfo.GetBandwidth(data, data_ptr); packet_frame_size = OpusPacketInfo.GetNumSamplesPerFrame(data, data_ptr, this.Fs); packet_stream_channels = OpusPacketInfo.GetNumEncodedChannels(data, data_ptr); count = OpusPacketInfo.opus_packet_parse_impl(data, data_ptr, len, self_delimited, out toc, null, null, 0, size, 0, out offset, out packet_offset); if (count < 0) { return(count); } data_ptr += offset; if (decode_fec != 0) { int dummy; int duration_copy; int ret; /* If no FEC can be present, run the PLC (recursive call) */ if (frame_size < packet_frame_size || packet_mode == OpusMode.MODE_CELT_ONLY || this.mode == OpusMode.MODE_CELT_ONLY) { return(opus_decode_native(null, 0, 0, pcm_out, pcm_out_ptr, frame_size, 0, 0, out dummy, soft_clip)); } /* Otherwise, run the PLC on everything except the size for which we might have FEC */ duration_copy = this.last_packet_duration; if (frame_size - packet_frame_size != 0) { ret = opus_decode_native(null, 0, 0, pcm_out, pcm_out_ptr, frame_size - packet_frame_size, 0, 0, out dummy, soft_clip); if (ret < 0) { this.last_packet_duration = duration_copy; return(ret); } Inlines.OpusAssert(ret == frame_size - packet_frame_size); } /* Complete with FEC */ this.mode = packet_mode; this.bandwidth = packet_bandwidth; this.frame_size = packet_frame_size; this.stream_channels = packet_stream_channels; ret = opus_decode_frame(data, data_ptr, size[0], pcm_out, pcm_out_ptr + (this.channels * (frame_size - packet_frame_size)), packet_frame_size, 1); if (ret < 0) { return(ret); } else { this.last_packet_duration = frame_size; return(frame_size); } } if (count * packet_frame_size > frame_size) { return(OpusError.OPUS_BUFFER_TOO_SMALL); } /* Update the state as the last step to avoid updating it on an invalid packet */ this.mode = packet_mode; this.bandwidth = packet_bandwidth; this.frame_size = packet_frame_size; this.stream_channels = packet_stream_channels; nb_samples = 0; for (i = 0; i < count; i++) { int ret; ret = opus_decode_frame(data, data_ptr, size[i], pcm_out, pcm_out_ptr + (nb_samples * this.channels), frame_size - nb_samples, 0); if (ret < 0) { return(ret); } Inlines.OpusAssert(ret == packet_frame_size); data_ptr += size[i]; nb_samples += ret; } this.last_packet_duration = nb_samples; return(nb_samples); }