[FFmpeg-soc] [soc]: r3331 - mlp/mlpenc.c

ramiro subversion at mplayerhq.hu
Fri Aug 15 23:06:31 CEST 2008


Author: ramiro
Date: Fri Aug 15 23:06:31 2008
New Revision: 3331

Log:
Add support for buffering frames.

Modified:
   mlp/mlpenc.c

Modified: mlp/mlpenc.c
==============================================================================
--- mlp/mlpenc.c	(original)
+++ mlp/mlpenc.c	Fri Aug 15 23:06:31 2008
@@ -86,6 +86,16 @@ typedef struct {
     int             sample_rate;    ///< Sample rate encoded for MLP
 
     int32_t         sample_buffer[MAX_BLOCKSIZE][MAX_CHANNELS+2];
+    uint8_t        *big_sample_buffer;
+    uint8_t        *last_frame;
+
+    unsigned int    frame_size[MAJOR_HEADER_INTERVAL];
+    unsigned int    frame_number[MAJOR_HEADER_INTERVAL];
+    unsigned int    frame_index;
+
+    unsigned int    one_sample_buffer_size;
+
+    unsigned int    major_header_interval;
 
     uint16_t        timestamp;
 
@@ -222,6 +232,7 @@ static uint8_t code_channels3(int channe
 static av_cold int mlp_encode_init(AVCodecContext *avctx)
 {
     MLPEncodeContext *ctx = avctx->priv_data;
+    unsigned int sample_size, big_sample_buffer_size;
     unsigned int quant_step_size;
     unsigned int substr;
 
@@ -243,9 +254,9 @@ static av_cold int mlp_encode_init(AVCod
     }
 
     switch (avctx->sample_fmt) {
-    case SAMPLE_FMT_S16: ctx->sample_fmt = BITS_16; quant_step_size = 8; break;
+    case SAMPLE_FMT_S16: sample_size = sizeof(int16_t); ctx->sample_fmt = BITS_16; quant_step_size = 8; break;
     /* TODO 20 bits: */
-    case SAMPLE_FMT_S24: ctx->sample_fmt = BITS_24; quant_step_size = 0; break;
+    case SAMPLE_FMT_S24: sample_size = sizeof(int32_t); ctx->sample_fmt = BITS_24; quant_step_size = 0; break;
     default:
         av_log(avctx, AV_LOG_ERROR, "Sample format not supported. "
                "Only 16- and 24-bit samples are supported.\n");
@@ -256,6 +267,20 @@ static av_cold int mlp_encode_init(AVCod
     avctx->coded_frame              = avcodec_alloc_frame();
     avctx->coded_frame->key_frame   = 1;
 
+    ctx->one_sample_buffer_size = sample_size * avctx->frame_size
+                                              * avctx->channels;
+    ctx->major_header_interval = MAJOR_HEADER_INTERVAL;
+
+    big_sample_buffer_size = ctx->one_sample_buffer_size
+                           * ctx->major_header_interval;
+
+    ctx->big_sample_buffer = av_malloc(big_sample_buffer_size);
+    if (!ctx->big_sample_buffer) {
+        av_log(avctx, AV_LOG_ERROR,
+               "Not enough memory for buffering samples.\n");
+        return -1;
+    }
+
     ff_mlp_init_crc();
     ff_mlp_init_crc2D(NULL);
 
@@ -276,8 +301,6 @@ static av_cold int mlp_encode_init(AVCod
         rh->max_channel        = avctx->channels - 1;
         rh->max_matrix_channel = 1;
 
-        dp->blocksize          = avctx->frame_size;
-
         for (channel = 0; channel <= rh->max_channel; channel++) {
             ChannelParams *cp = &ctx->channel_params[channel];
 
@@ -578,7 +601,7 @@ static int apply_filter(MLPEncodeContext
                MAX_FILTER_ORDER * sizeof(int32_t));
     }
 
-    for (i = 0; i < ctx->avctx->frame_size; i++) {
+    for (i = 0; i < ctx->frame_size[ctx->frame_index]; i++) {
         int32_t sample = ctx->sample_buffer[i][channel];
         unsigned int order;
         int64_t accum = 0;
@@ -602,7 +625,7 @@ static int apply_filter(MLPEncodeContext
     }
 
     index = MAX_BLOCKSIZE;
-    for (i = 0; i < ctx->avctx->frame_size; i++) {
+    for (i = 0; i < ctx->frame_size[ctx->frame_index]; i++) {
         int32_t residual = filter_state_buffer[IIR][--index];
 
         /* Store residual. */
@@ -1048,8 +1071,8 @@ static uint8_t *write_substrs(MLPEncodeC
         int params_changed;
         int last_block = 0;
 
-        if (ctx->avctx->frame_size < dp->blocksize) {
-            dp->blocksize = ctx->avctx->frame_size;
+        if (ctx->frame_size[ctx->frame_index] < dp->blocksize) {
+            dp->blocksize = ctx->frame_size[ctx->frame_index];
             last_block = 1;
         }
 
@@ -1121,13 +1144,36 @@ static int mlp_encode_frame(AVCodecConte
     ChannelParams channel_params[MAX_CHANNELS];
     MLPEncodeContext *ctx = avctx->priv_data;
     uint8_t *buf2, *buf1, *buf0 = buf;
-    int total_length;
+    int total_length = 0;
     unsigned int substr;
+    uint8_t *data0 = data;
     int restart_frame;
 
-    if (avctx->frame_size > MAX_BLOCKSIZE) {
+    ctx->frame_index = avctx->frame_number % ctx->major_header_interval;
+
+    data = ctx->big_sample_buffer + ctx->frame_index * ctx->one_sample_buffer_size;
+
+    if (ctx->last_frame == data) {
+        return 0;
+    }
+
+    if (avctx->frame_number < ctx->major_header_interval) {
+        if (data0) {
+            goto buffer_and_return;
+        } else {
+            /* There are less frames than the requested major header interval.
+             * Update the context and *data to reflect this.
+             */
+            ctx->major_header_interval = avctx->frame_number;
+            ctx->frame_index = 0;
+
+            data = ctx->big_sample_buffer;
+        }
+    }
+
+    if (ctx->frame_size[ctx->frame_index] > MAX_BLOCKSIZE) {
         av_log(avctx, AV_LOG_ERROR, "Invalid frame size (%d > %d)\n",
-               avctx->frame_size, MAX_BLOCKSIZE);
+               ctx->frame_size[ctx->frame_index], MAX_BLOCKSIZE);
         return -1;
     }
 
@@ -1141,7 +1187,7 @@ static int mlp_encode_frame(AVCodecConte
     buf      += 4;
     buf_size -= 4;
 
-    restart_frame = !(avctx->frame_number & (MAJOR_HEADER_INTERVAL - 1));
+    restart_frame = !(ctx->frame_number[ctx->frame_index] & (MAJOR_HEADER_INTERVAL - 1));
 
     if (restart_frame) {
         if (buf_size < 28)
@@ -1155,6 +1201,10 @@ static int mlp_encode_frame(AVCodecConte
 
     /* Substream headers will be written at the end. */
     for (substr = 0; substr < ctx->num_substreams; substr++) {
+        DecodingParams *dp = &ctx->decoding_params[substr];
+
+        dp->blocksize = ctx->frame_size[ctx->frame_index];
+
         buf      += 2;
         buf_size -= 2;
     }
@@ -1174,13 +1224,26 @@ static int mlp_encode_frame(AVCodecConte
 
     write_frame_headers(ctx, buf0, buf1, total_length / 2, substream_data_len);
 
-    ctx->timestamp += avctx->frame_size;
+    ctx->timestamp += ctx->frame_size[ctx->frame_index];
+
+buffer_and_return:
+
+    if (data0) {
+        ctx->frame_size[ctx->frame_index] = avctx->frame_size;
+        ctx->frame_number[ctx->frame_index] = avctx->frame_number;
+        memcpy(data, data0, ctx->one_sample_buffer_size);
+    } else if (!ctx->last_frame) {
+        ctx->last_frame = data;
+    }
 
     return total_length;
 }
 
 static av_cold int mlp_encode_close(AVCodecContext *avctx)
 {
+    MLPEncodeContext *ctx = avctx->priv_data;
+
+    av_freep(&ctx->big_sample_buffer);
     av_freep(&avctx->coded_frame);
 
     return 0;
@@ -1194,7 +1257,7 @@ AVCodec mlp_encoder = {
     mlp_encode_init,
     mlp_encode_frame,
     mlp_encode_close,
-    .capabilities = CODEC_CAP_SMALL_LAST_FRAME,
+    .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY,
     .sample_fmts = (enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_S24,SAMPLE_FMT_NONE},
     .long_name = NULL_IF_CONFIG_SMALL("Meridian Lossless Packing"),
 };



More information about the FFmpeg-soc mailing list