[FFmpeg-devel] [Toy] Aura 1 and 2 decoder

Kostya kostya.shishkov
Mon Mar 16 08:32:59 CET 2009


$subj - a lazy hack done with a left leg.
Released before it too rotten.
-------------- next part --------------
Index: libavcodec/aura.c
===================================================================
--- libavcodec/aura.c	(revision 0)
+++ libavcodec/aura.c	(revision 0)
@@ -0,0 +1,156 @@
+/*
+ * Aura Video Decoder
+ * based on Creative YUV (CYUV) decoder
+ *
+ * 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
+ */
+
+/**
+ * @file libavcodec/aura.c
+ * Aura Video Decoder.
+ */
+
+#include "avcodec.h"
+
+
+typedef struct AuraDecodeContext {
+    AVCodecContext *avctx;
+    int width, height;
+    AVFrame frame;
+} AuraDecodeContext;
+
+static av_cold int aura_decode_init(AVCodecContext *avctx)
+{
+    AuraDecodeContext *s = avctx->priv_data;
+
+    s->avctx = avctx;
+    s->width = avctx->width;
+    /* width needs to be divisible by 4 for this codec to work */
+    if (s->width & 0x3)
+        return -1;
+    s->height = avctx->height;
+    avctx->pix_fmt = PIX_FMT_YUV422P;
+
+    return 0;
+}
+
+static int aura_decode_frame(AVCodecContext *avctx,
+                             void *data, int *data_size,
+                             const uint8_t *buf, int buf_size)
+{
+    AuraDecodeContext *s=avctx->priv_data;
+
+    uint8_t *y_plane;
+    uint8_t *u_plane;
+    uint8_t *v_plane;
+    int y_ptr;
+    int u_ptr;
+    int v_ptr;
+
+    /* prediction error tables (make it clear that they are signed values) */
+    const int8_t *y_table = (const int8_t*)buf + 16;
+    const int8_t *c_table = (const int8_t*)buf + 16;
+
+    uint8_t y_pred, u_pred, v_pred;
+    int stream_ptr;
+    uint8_t cur_byte;
+    int pixel_groups;
+
+    /* sanity check the buffer size: A buffer has 3x16-bytes tables
+     * followed by (height) lines each with 3 bytes to represent groups
+     * of 4 pixels. Thus, the total size of the buffer ought to be:
+     *    (3 * 16) + height * (width * 3 / 4) */
+    if (buf_size != 48 + s->height * s->width) {
+      av_log(avctx, AV_LOG_ERROR, "ffmpeg: cyuv: got a buffer with %d bytes when %d were expected\n",
+        buf_size,
+        48 + s->height * s->width);
+      return -1;
+    }
+
+    /* pixel data starts 48 bytes in, after 3x16-byte tables */
+    stream_ptr = 48;
+
+    if(s->frame.data[0])
+        avctx->release_buffer(avctx, &s->frame);
+
+    s->frame.buffer_hints = FF_BUFFER_HINTS_VALID;
+    s->frame.reference = 0;
+    if(avctx->get_buffer(avctx, &s->frame) < 0) {
+        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+        return -1;
+    }
+
+    y_plane = s->frame.data[0];
+    u_plane = s->frame.data[1];
+    v_plane = s->frame.data[2];
+
+    /* iterate through each line in the height */
+    for (y_ptr = 0, u_ptr = 0, v_ptr = 0;
+         y_ptr < (s->height * s->frame.linesize[0]);
+         y_ptr += s->frame.linesize[0] - s->width,
+         u_ptr += s->frame.linesize[1] - s->width / 2,
+         v_ptr += s->frame.linesize[2] - s->width / 2) {
+
+        /* reset predictors */
+        cur_byte = buf[stream_ptr++];
+        u_plane[u_ptr++] = u_pred = cur_byte & 0xF0;
+        y_plane[y_ptr++] = y_pred = (cur_byte & 0x0F) << 4;
+
+        cur_byte = buf[stream_ptr++];
+        v_plane[v_ptr++] = v_pred = cur_byte & 0xF0;
+        y_pred += y_table[cur_byte & 0x0F];
+        y_plane[y_ptr++] = y_pred;
+
+        /* iterate through the remaining pixel groups (4 pixels/group) */
+        pixel_groups = s->width / 2 - 1;
+        while (pixel_groups--) {
+
+            cur_byte = buf[stream_ptr++];
+            u_pred += c_table[(cur_byte & 0xF0) >> 4];
+            u_plane[u_ptr++] = u_pred;
+            y_pred += y_table[cur_byte & 0x0F];
+            y_plane[y_ptr++] = y_pred;
+
+            cur_byte = buf[stream_ptr++];
+            v_pred += c_table[(cur_byte & 0xF0) >> 4];
+            v_plane[v_ptr++] = v_pred;
+            y_pred += y_table[cur_byte & 0x0F];
+            y_plane[y_ptr++] = y_pred;
+
+        }
+    }
+
+    *data_size=sizeof(AVFrame);
+    *(AVFrame*)data= s->frame;
+
+    return buf_size;
+}
+
+AVCodec aura2_decoder = {
+    "aura2",
+    CODEC_TYPE_VIDEO,
+    CODEC_ID_AURA2,
+    sizeof(AuraDecodeContext),
+    aura_decode_init,
+    NULL,
+    NULL,
+    aura_decode_frame,
+    CODEC_CAP_DR1,
+    NULL,
+    .long_name = NULL_IF_CONFIG_SMALL("Auravision Aura 2"),
+};
+
Index: libavcodec/Makefile
===================================================================
--- libavcodec/Makefile	(revision 17586)
+++ libavcodec/Makefile	(working copy)
@@ -46,6 +46,8 @@
 OBJS-$(CONFIG_ASV2_DECODER)            += asv1.o mpeg12data.o
 OBJS-$(CONFIG_ASV2_ENCODER)            += asv1.o mpeg12data.o
 OBJS-$(CONFIG_ATRAC3_DECODER)          += atrac3.o
+OBJS-$(CONFIG_AURA_DECODER)            += cyuv.o
+OBJS-$(CONFIG_AURA2_DECODER)           += aura.o
 OBJS-$(CONFIG_AVS_DECODER)             += avs.o
 OBJS-$(CONFIG_BETHSOFTVID_DECODER)     += bethsoftvideo.o
 OBJS-$(CONFIG_BFI_DECODER)             += bfi.o
Index: libavcodec/allcodecs.c
===================================================================
--- libavcodec/allcodecs.c	(revision 17586)
+++ libavcodec/allcodecs.c	(working copy)
@@ -54,6 +54,8 @@
     REGISTER_DECODER (AMV, amv);
     REGISTER_ENCDEC  (ASV1, asv1);
     REGISTER_ENCDEC  (ASV2, asv2);
+    REGISTER_DECODER (AURA, aura);
+    REGISTER_DECODER (AURA2, aura2);
     REGISTER_DECODER (AVS, avs);
     REGISTER_DECODER (BETHSOFTVID, bethsoftvid);
     REGISTER_DECODER (BFI, bfi);
Index: libavcodec/avcodec.h
===================================================================
--- libavcodec/avcodec.h	(revision 17586)
+++ libavcodec/avcodec.h	(working copy)
@@ -191,6 +191,8 @@
     CODEC_ID_TGV,
     CODEC_ID_TGQ,
     CODEC_ID_TQI,
+    CODEC_ID_AURA,
+    CODEC_ID_AURA2,
 
     /* various PCM "codecs" */
     CODEC_ID_PCM_S16LE= 0x10000,
Index: libavcodec/cyuv.c
===================================================================
--- libavcodec/cyuv.c	(revision 17586)
+++ libavcodec/cyuv.c	(working copy)
@@ -81,12 +81,16 @@
     unsigned char cur_byte;
     int pixel_groups;
 
+    if (avctx->codec_id == CODEC_ID_AURA) {
+        y_table = u_table;
+        u_table = v_table;
+    }
     /* sanity check the buffer size: A buffer has 3x16-bytes tables
      * followed by (height) lines each with 3 bytes to represent groups
      * of 4 pixels. Thus, the total size of the buffer ought to be:
      *    (3 * 16) + height * (width * 3 / 4) */
     if (buf_size != 48 + s->height * (s->width * 3 / 4)) {
-      av_log(avctx, AV_LOG_ERROR, "ffmpeg: cyuv: got a buffer with %d bytes when %d were expected\n",
+      av_log(avctx, AV_LOG_ERROR, "ffmpeg: got a buffer with %d bytes when %d were expected\n",
         buf_size,
         48 + s->height * (s->width * 3 / 4));
       return -1;
@@ -163,6 +167,20 @@
     return buf_size;
 }
 
+AVCodec aura_decoder = {
+    "aura",
+    CODEC_TYPE_VIDEO,
+    CODEC_ID_AURA,
+    sizeof(CyuvDecodeContext),
+    cyuv_decode_init,
+    NULL,
+    NULL,
+    cyuv_decode_frame,
+    CODEC_CAP_DR1,
+    NULL,
+    .long_name = NULL_IF_CONFIG_SMALL("Auravision AURA"),
+};
+
 AVCodec cyuv_decoder = {
     "cyuv",
     CODEC_TYPE_VIDEO,
Index: libavformat/riff.c
===================================================================
--- libavformat/riff.c	(revision 17586)
+++ libavformat/riff.c	(working copy)
@@ -201,6 +201,8 @@
     { CODEC_ID_RPZA,         MKTAG('R', 'P', 'Z', 'A') },
     { CODEC_ID_RPZA,         MKTAG('r', 'p', 'z', 'a') },
     { CODEC_ID_SP5X,         MKTAG('S', 'P', '5', '4') },
+    { CODEC_ID_AURA,         MKTAG('A', 'U', 'R', 'A') },
+    { CODEC_ID_AURA2,        MKTAG('A', 'U', 'R', '2') },
     { CODEC_ID_NONE,         0 }
 };
 



More information about the ffmpeg-devel mailing list