+/**
+ *@brief Decode a single WMA packet.
+ *@param avctx codec context
+ *@param data the output buffer
+ *@param avpkt input packet
+ *@return number of bytes that were read from the input buffer
+ */
+static int wmapro_decode_packet(AVCodecContext *avctx, void *data,
+ int *got_frame_ptr, AVPacket *avpkt)
+{
+ WMAProDecodeCtx *s = avctx->priv_data;
+ AVFrame *frame = data;
+ int ret;
+
+ /* get output buffer */
+ frame->nb_samples = s->samples_per_frame;
+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
+ s->packet_loss = 1;
+ return 0;
+ }
+
+ return decode_packet(avctx, s, data, got_frame_ptr, avpkt);
+}
+
+static int xma_decode_packet(AVCodecContext *avctx, void *data,
+ int *got_frame_ptr, AVPacket *avpkt)
+{
+ XMADecodeCtx *s = avctx->priv_data;
+ int got_stream_frame_ptr = 0;
+ AVFrame *frame = data;
+ int i, ret, offset = INT_MAX;
+
+ ret = decode_packet(avctx, &s->xma[s->current_stream], s->frames[s->current_stream],
+ &got_stream_frame_ptr, avpkt);
+
+ if (got_stream_frame_ptr) {
+ memcpy(&s->samples[s->current_stream * 2 + 0][s->offset[s->current_stream] * 512],
+ s->frames[s->current_stream]->extended_data[0], 512 * 4);
+ memcpy(&s->samples[s->current_stream * 2 + 1][s->offset[s->current_stream] * 512],
+ s->frames[s->current_stream]->extended_data[1], 512 * 4);
+ s->offset[s->current_stream]++;
+ }
+
+ if (s->xma[s->current_stream].packet_done ||
+ s->xma[s->current_stream].packet_loss) {
+ int bret;
+
+ if (s->xma[0].skip_packets == 0) {
+ s->current_stream = 0;
+ } else if (s->xma[1].skip_packets == 0) {
+ s->current_stream = 1;
+ } else if (s->xma[2].skip_packets == 0) {
+ s->current_stream = 2;
+ } else if (s->xma[3].skip_packets == 0) {
+ s->current_stream = 3;
+ } else {
+ s->current_stream++;
+ if (s->current_stream >= avctx->channels / 2)
+ s->current_stream = 0;
+ }
+ for (i = 0; i < avctx->channels / 2; i++) {
+ s->xma[i].skip_packets = FFMAX(0, s->xma[i].skip_packets - 1);
+ }
+
+ for (i = 0; i < avctx->channels / 2; i++) {
+ offset = FFMIN(offset, s->offset[i]);
+ }
+
+ if (offset > 0) {
+ frame->nb_samples = 512 * offset;
+ if ((bret = ff_get_buffer(avctx, frame, 0)) < 0)
+ return bret;
+
+ for (i = 0; i < avctx->channels / 2; i++) {
+ memcpy(frame->extended_data[i * 2 + 0], s->samples[i * 2 + 0], frame->nb_samples * 4);
+ memcpy(frame->extended_data[i * 2 + 1], s->samples[i * 2 + 1], frame->nb_samples * 4);
+ s->offset[i] -= offset;
+ if (s->offset[i]) {
+ memmove(s->samples[i * 2 + 0], s->samples[i * 2 + 0] + frame->nb_samples, s->offset[i] * 4 * 512);
+ memmove(s->samples[i * 2 + 1], s->samples[i * 2 + 1] + frame->nb_samples, s->offset[i] * 4 * 512);
+ }
+ }
+
+ *got_frame_ptr = 1;
+ }
+ }
+
+ return ret;
+}
+
+static av_cold int xma_decode_init(AVCodecContext *avctx)
+{
+ XMADecodeCtx *s = avctx->priv_data;
+ int i, ret;
+
+ for (i = 0; i < avctx->channels / 2; i++) {
+ ret = decode_init(&s->xma[i], avctx);
+ s->frames[i] = av_frame_alloc();
+ if (!s->frames[i])
+ return AVERROR(ENOMEM);
+ s->frames[i]->nb_samples = 512;
+ if ((ret = ff_get_buffer(avctx, s->frames[i], 0)) < 0) {
+ return AVERROR(ENOMEM);
+ }
+
+ }
+
+ return ret;
+}
+
+static av_cold int xma_decode_end(AVCodecContext *avctx)
+{
+ XMADecodeCtx *s = avctx->priv_data;
+ int i;
+
+ for (i = 0; i < avctx->channels / 2; i++) {
+ decode_end(&s->xma[i]);
+ av_frame_free(&s->frames[i]);
+ }
+
+ return 0;
+}
+