[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