[FFmpeg-cvslog] r8922 - in trunk/libavcodec: Makefile allcodecs.c avcodec.h roqaudioenc.c

benoit subversion
Mon May 7 10:55:27 CEST 2007


Author: benoit
Date: Mon May  7 10:55:27 2007
New Revision: 8922

Log:

RoQ audio encoder
patch by Vitor vitor1001 gmail com



Added:
   trunk/libavcodec/roqaudioenc.c
Modified:
   trunk/libavcodec/Makefile
   trunk/libavcodec/allcodecs.c
   trunk/libavcodec/avcodec.h

Modified: trunk/libavcodec/Makefile
==============================================================================
--- trunk/libavcodec/Makefile	(original)
+++ trunk/libavcodec/Makefile	Mon May  7 10:55:27 2007
@@ -125,6 +125,7 @@ OBJS-$(CONFIG_RA_144_DECODER)          +
 OBJS-$(CONFIG_RA_288_DECODER)          += ra288.o
 OBJS-$(CONFIG_ROQ_DECODER)             += roqvideo.o
 OBJS-$(CONFIG_ROQ_DPCM_DECODER)        += dpcm.o
+OBJS-$(CONFIG_ROQ_DPCM_ENCODER)        += roqaudioenc.o
 OBJS-$(CONFIG_RPZA_DECODER)            += rpza.o
 OBJS-$(CONFIG_RV10_DECODER)            += rv10.o
 OBJS-$(CONFIG_RV10_ENCODER)            += rv10.o

Modified: trunk/libavcodec/allcodecs.c
==============================================================================
--- trunk/libavcodec/allcodecs.c	(original)
+++ trunk/libavcodec/allcodecs.c	Mon May  7 10:55:27 2007
@@ -226,7 +226,7 @@ void avcodec_register_all(void)
 
     /* dpcm codecs */
     REGISTER_DECODER(INTERPLAY_DPCM, interplay_dpcm);
-    REGISTER_DECODER(ROQ_DPCM, roq_dpcm);
+    REGISTER_ENCDEC (ROQ_DPCM, roq_dpcm);
     REGISTER_DECODER(SOL_DPCM, sol_dpcm);
     REGISTER_DECODER(XAN_DPCM, xan_dpcm);
 

Modified: trunk/libavcodec/avcodec.h
==============================================================================
--- trunk/libavcodec/avcodec.h	(original)
+++ trunk/libavcodec/avcodec.h	Mon May  7 10:55:27 2007
@@ -2225,6 +2225,7 @@ extern AVCodec pgm_encoder;
 extern AVCodec pgmyuv_encoder;
 extern AVCodec png_encoder;
 extern AVCodec ppm_encoder;
+extern AVCodec roq_dpcm_encoder;
 extern AVCodec rv10_encoder;
 extern AVCodec rv20_encoder;
 extern AVCodec sgi_encoder;

Added: trunk/libavcodec/roqaudioenc.c
==============================================================================
--- (empty file)
+++ trunk/libavcodec/roqaudioenc.c	Mon May  7 10:55:27 2007
@@ -0,0 +1,177 @@
+/*
+ * RoQ audio encoder
+ *
+ * Copyright (c) 2005 Eric Lasota
+ *    Based on RoQ specs (c)2001 Tim Ferguson
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avcodec.h"
+#include "bytestream.h"
+
+#define ROQ_FIRST_FRAME_SIZE     (735*8)
+#define ROQ_FRAME_SIZE           735
+
+
+#define MAX_DPCM (127*127)
+static unsigned char dpcmValues[MAX_DPCM];
+
+
+typedef struct
+{
+    short lastSample[2];
+} ROQDPCMContext_t;
+
+static void roq_dpcm_table_init(void)
+{
+    int i;
+
+    /* Create a table of quick DPCM values */
+    for (i=0; i<MAX_DPCM; i++) {
+        int s= ff_sqrt(i);
+        int mid= s*s + s;
+        dpcmValues[i]= s + (i>mid);
+    }
+}
+
+static int roq_dpcm_encode_init(AVCodecContext *avctx)
+{
+    ROQDPCMContext_t *context = avctx->priv_data;
+
+    if (avctx->channels > 2) {
+        av_log(avctx, AV_LOG_ERROR, "Audio must be mono or stereo\n");
+        return -1;
+    }
+    if (avctx->sample_rate != 22050) {
+        av_log(avctx, AV_LOG_ERROR, "Audio must be 22050 Hz\n");
+        return -1;
+    }
+    if (avctx->sample_fmt != SAMPLE_FMT_S16) {
+        av_log(avctx, AV_LOG_ERROR, "Audio must be signed 16-bit\n");
+        return -1;
+    }
+
+    roq_dpcm_table_init();
+
+    avctx->frame_size = ROQ_FIRST_FRAME_SIZE;
+
+    context->lastSample[0] = context->lastSample[1] = 0;
+
+    avctx->coded_frame= avcodec_alloc_frame();
+    avctx->coded_frame->key_frame= 1;
+
+    return 0;
+}
+
+static unsigned char dpcm_predict(short *previous, short current)
+{
+    int diff;
+    int negative;
+    int result;
+    int predicted;
+
+    diff = current - *previous;
+
+    negative = diff<0;
+    diff = FFABS(diff);
+
+    if (diff >= MAX_DPCM)
+        result = 127;
+    else
+        result = dpcmValues[diff];
+
+    /* See if this overflows */
+ retry:
+    diff = result*result;
+    if (negative)
+        diff = -diff;
+    predicted = *previous + diff;
+
+    /* If it overflows, back off a step */
+    if (predicted > 32767 || predicted < -32768) {
+        result--;
+        goto retry;
+    }
+
+    /* Add the sign bit */
+    result |= negative << 7;   //if (negative) result |= 128;
+
+    *previous = predicted;
+
+    return result;
+}
+
+static int roq_dpcm_encode_frame(AVCodecContext *avctx,
+                unsigned char *frame, int buf_size, void *data)
+{
+    int i, samples, stereo, ch;
+    short *in;
+    unsigned char *out;
+
+    ROQDPCMContext_t *context = avctx->priv_data;
+
+    stereo = (avctx->channels == 2);
+
+    if (stereo) {
+        context->lastSample[0] &= 0xFF00;
+        context->lastSample[1] &= 0xFF00;
+    }
+
+    out = frame;
+    in = data;
+
+    bytestream_put_byte(&out, stereo ? 0x21 : 0x20);
+    bytestream_put_byte(&out, 0x10);
+    bytestream_put_le32(&out, avctx->frame_size*avctx->channels);
+
+    if (stereo) {
+        bytestream_put_byte(&out, (context->lastSample[1])>>8);
+        bytestream_put_byte(&out, (context->lastSample[0])>>8);
+    } else
+        bytestream_put_le16(&out, context->lastSample[0]);
+
+    /* Write the actual samples */
+    samples = avctx->frame_size;
+    for (i=0; i<samples; i++)
+        for (ch=0; ch<avctx->channels; ch++)
+            *out++ = dpcm_predict(&context->lastSample[ch], *in++);
+
+    /* Use smaller frames from now on */
+    avctx->frame_size = ROQ_FRAME_SIZE;
+
+    /* Return the result size */
+    return out - frame;
+}
+
+static int roq_dpcm_encode_close(AVCodecContext *avctx)
+{
+    av_freep(&avctx->coded_frame);
+
+    return 0;
+}
+
+AVCodec roq_dpcm_encoder = {
+    "roq_dpcm",
+    CODEC_TYPE_AUDIO,
+    CODEC_ID_ROQ_DPCM,
+    sizeof(ROQDPCMContext_t),
+    roq_dpcm_encode_init,
+    roq_dpcm_encode_frame,
+    roq_dpcm_encode_close,
+    NULL,
+};




More information about the ffmpeg-cvslog mailing list