Am 03.01.2014 16:57, schrieb Justin Ruggles:
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?

Currently, ATRAC3+ streams are known to be shipped either within Sony's OMA or RIFF WAV containers. These demuxers seem to set block_align appropriately. PSMF container used with PlayStation can supply ATRAC3+ tracks as well but Libav doesn't currently support PSMF.

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.

OK, a check for non-zero block align sounds indeed like a good idea to me.
Nevertheless, zero block-align doesn't make any sense and would indicate a broken media file...

Best regards
Maxim
_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to