static int opus_decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *avpkt) { OpusContext *c = avctx->priv_data; AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; int coded_samples = 0; int decoded_samples = 0; int i, ret; for (i = 0; i < c->nb_streams; i++) { OpusStreamContext *s = &c->streams[i]; s->out[0] = s->out[1] = NULL; } /* decode the header of the first sub-packet to find out the sample count */ if (buf) { OpusPacket *pkt = &c->streams[0].packet; ret = ff_opus_parse_packet(pkt, buf, buf_size, c->nb_streams > 1); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error parsing the packet header.\n"); return ret; } coded_samples += pkt->frame_count * pkt->frame_duration; c->streams[0].silk_samplerate = get_silk_samplerate(pkt->config); } frame->nb_samples = coded_samples + c->streams[0].delayed_samples; /* no input or buffered data => nothing to do */ if (!frame->nb_samples) { *got_frame_ptr = 0; return 0; } /* setup the data buffers */ ret = ff_get_buffer(avctx, frame, 0); if (ret < 0) return ret; frame->nb_samples = 0; for (i = 0; i < avctx->channels; i++) { ChannelMap *map = &c->channel_maps[i]; if (!map->copy) c->streams[map->stream_idx].out[map->channel_idx] = (float*)frame->extended_data[i]; } for (i = 0; i < c->nb_streams; i++) c->streams[i].out_size = frame->linesize[0]; /* decode each sub-packet */ for (i = 0; i < c->nb_streams; i++) { OpusStreamContext *s = &c->streams[i]; if (i && buf) { ret = ff_opus_parse_packet(&s->packet, buf, buf_size, i != c->nb_streams - 1); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error parsing the packet header.\n"); return ret; } if (coded_samples != s->packet.frame_count * s->packet.frame_duration) { av_log(avctx, AV_LOG_ERROR, "Mismatching coded sample count in substream %d.\n", i); return AVERROR_INVALIDDATA; } s->silk_samplerate = get_silk_samplerate(s->packet.config); } ret = opus_decode_subpacket(&c->streams[i], buf, s->packet.data_size, coded_samples); if (ret < 0) return ret; if (decoded_samples && ret != decoded_samples) { av_log(avctx, AV_LOG_ERROR, "Different numbers of decoded samples " "in a multi-channel stream\n"); return AVERROR_INVALIDDATA; } decoded_samples = ret; buf += s->packet.packet_size; buf_size -= s->packet.packet_size; } for (i = 0; i < avctx->channels; i++) { ChannelMap *map = &c->channel_maps[i]; /* handle copied channels */ if (map->copy) { memcpy(frame->extended_data[i], frame->extended_data[map->copy_idx], frame->linesize[0]); } else if (map->silence) { memset(frame->extended_data[i], 0, frame->linesize[0]); } if (c->gain_i) { c->fdsp->vector_fmul_scalar((float*)frame->extended_data[i], (float*)frame->extended_data[i], c->gain, FFALIGN(decoded_samples, 8)); } } frame->nb_samples = decoded_samples; *got_frame_ptr = !!decoded_samples; return avpkt->size; }