On 01/02/2014 03:41 PM, Maxim Polijakowski wrote:
+static int atrac3p_decode_frame(AVCodecContext *avctx, void *data,
+                                int *got_frame_ptr, AVPacket *avpkt)
+{
+    ATRAC3PContext *ctx = avctx->priv_data;
+    AVFrame *frame      = data;
+    int i, ret, ch_unit_id, ch_block = 0, out_ch_index = 0, 
channels_to_process;
+    float **samples_p = (float **)frame->extended_data;
+
+    frame->nb_samples = ATRAC3P_FRAME_SAMPLES;
+    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
+        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+        return ret;
+    }
+
+    if ((ret = init_get_bits8(&ctx->gb, avpkt->data, avpkt->size)) < 0)
+        return ret;
+
+    if (get_bits1(&ctx->gb)) {
+        av_log(avctx, AV_LOG_ERROR, "Invalid start bit!\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    while (get_bits_left(&ctx->gb) >= 2 &&
+           (ch_unit_id = get_bits(&ctx->gb, 2)) != CH_UNIT_TERMINATOR) {
+        if (ch_unit_id == CH_UNIT_EXTENSION) {
+            avpriv_report_missing_feature(avctx, "Channel unit extension");
+            return AVERROR_PATCHWELCOME;
+        }
+        if (ch_block >= ctx->num_channel_blocks ||
+            ctx->channel_blocks[ch_block] != ch_unit_id) {
+            av_log(avctx, AV_LOG_ERROR,
+                   "Frame data doesn't match channel configuration!\n");
+            return AVERROR_INVALIDDATA;
+        }
+
+        ctx->ch_units[ch_block].unit_type = ch_unit_id;
+        channels_to_process               = ch_unit_id + 1;
+
+        if ((ret = ff_atrac3p_decode_channel_unit(&ctx->gb,
+                                                  &ctx->ch_units[ch_block],
+                                                  channels_to_process,
+                                                  avctx)) < 0)
+            return ret;
+
+        decode_residual_spectrum(&ctx->ch_units[ch_block], ctx->samples,
+                                 channels_to_process, avctx);
+        reconstruct_frame(ctx, &ctx->ch_units[ch_block],
+                          channels_to_process, avctx);
+
+        for (i = 0; i < channels_to_process; i++)
+            memcpy(samples_p[out_ch_index + i], ctx->outp_buf[i],
+                   ATRAC3P_FRAME_SAMPLES * sizeof(**samples_p));
+
+        ch_block++;
+        out_ch_index += channels_to_process;
+    }
+
+    *got_frame_ptr = 1;
+
+    return avctx->block_align;
+}

We need to be careful here with how multiple frames-per-packet are handled. Do you know when that occurs and when it does not occur? What containers can ATRAC3+ be in, and do all of them set block_align? We at least need a check to ensure that block_align is non-zero, otherwise it can lead to an infinite loop. We fixed a similar issue recently with WMA.

-Justin

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to