ZeroCodec Decoder
authorDerek Buitenhuis <derek.buitenhuis@gmail.com>
Sun, 18 Mar 2012 19:04:38 +0000 (15:04 -0400)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Mon, 19 Mar 2012 18:02:23 +0000 (19:02 +0100)
An obscure Japanese lossless video codec, originally intended
for use with a remote desktop application.

Signed-off-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
Signed-off-by: Kostya Shishkov <kostya.shishkov@gmail.com>
Changelog
configure
doc/general.texi
libavcodec/Makefile
libavcodec/allcodecs.c
libavcodec/avcodec.h
libavcodec/version.h
libavcodec/zerocodec.c [new file with mode: 0644]
libavformat/riff.c

index 4a23d22..493b323 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -14,6 +14,7 @@ version <next>:
 - WMA Lossless decoder
 - XBM encoder
 -┬áRealAudio Lossless decoder
+- ZeroCodec decoder
 
 
 version 0.8:
index 29fb432..eba9cfe 100755 (executable)
--- a/configure
+++ b/configure
@@ -1399,6 +1399,7 @@ wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel"
 wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel"
 wmv3_vdpau_decoder_select="vc1_vdpau_decoder"
 wmv3image_decoder_select="wmv3_decoder"
+zerocodec_decoder_select="zlib"
 zlib_decoder_select="zlib"
 zlib_encoder_select="zlib"
 zmbv_decoder_select="zlib"
index bbadb21..0c14003 100644 (file)
@@ -329,6 +329,7 @@ library:
     @tab Microsoft audio container used by XAudio 2.
 @item YUV4MPEG pipe             @tab X @tab X
 @item Psygnosis YOP             @tab   @tab X
+@item ZeroCodec Lossless Video  @tab   @tab X
 @end multitable
 
 @code{X} means that encoding (resp. decoding) is supported.
index 9d4266e..0c459f6 100644 (file)
@@ -448,6 +448,7 @@ OBJS-$(CONFIG_XSUB_ENCODER)            += xsubenc.o
 OBJS-$(CONFIG_XWD_DECODER)             += xwddec.o
 OBJS-$(CONFIG_XWD_ENCODER)             += xwdenc.o
 OBJS-$(CONFIG_YOP_DECODER)             += yop.o
+OBJS-$(CONFIG_ZEROCODEC_DECODER)       += zerocodec.o
 OBJS-$(CONFIG_ZLIB_DECODER)            += lcldec.o
 OBJS-$(CONFIG_ZLIB_ENCODER)            += lclenc.o
 OBJS-$(CONFIG_ZMBV_DECODER)            += zmbv.o
index f7fc7ce..60b3e08 100644 (file)
@@ -234,6 +234,7 @@ void avcodec_register_all(void)
     REGISTER_DECODER (XL, xl);
     REGISTER_ENCDEC  (XWD, xwd);
     REGISTER_DECODER (YOP, yop);
+    REGISTER_DECODER (ZEROCODEC, zerocodec);
     REGISTER_ENCDEC  (ZLIB, zlib);
     REGISTER_ENCDEC  (ZMBV, zmbv);
 
index f09ee36..3af4df1 100644 (file)
@@ -246,6 +246,7 @@ enum CodecID {
     CODEC_ID_XWD,
     CODEC_ID_CDXL,
     CODEC_ID_XBM,
+    CODEC_ID_ZEROCODEC,
 
     /* various PCM "codecs" */
     CODEC_ID_FIRST_AUDIO = 0x10000,     ///< A dummy id pointing at the start of audio codecs
index 39ecd68..9e42a27 100644 (file)
@@ -21,7 +21,7 @@
 #define AVCODEC_VERSION_H
 
 #define LIBAVCODEC_VERSION_MAJOR 54
-#define LIBAVCODEC_VERSION_MINOR 10
+#define LIBAVCODEC_VERSION_MINOR 11
 #define LIBAVCODEC_VERSION_MICRO  0
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
diff --git a/libavcodec/zerocodec.c b/libavcodec/zerocodec.c
new file mode 100644 (file)
index 0000000..3bf1fd9
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * ZeroCodec Decoder
+ *
+ * Copyright (c) 2012, Derek Buitenhuis
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <zlib.h>
+
+#include "avcodec.h"
+
+typedef struct {
+    AVFrame  previous_frame;
+    z_stream zstream;
+    int size;
+} ZeroCodecContext;
+
+static int zerocodec_decode_frame(AVCodecContext *avctx, void *data,
+                                  int *data_size, AVPacket *avpkt)
+{
+    ZeroCodecContext *zc = avctx->priv_data;
+    AVFrame *pic         = avctx->coded_frame;
+    AVFrame *prev_pic    = &zc->previous_frame;
+    z_stream *zstream    = &zc->zstream;
+    uint8_t *prev, *dst;
+    int i, j, zret;
+
+    pic->reference = 3;
+
+    if (avctx->get_buffer(avctx, pic) < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n");
+        return AVERROR(ENOMEM);
+    }
+
+    zret = inflateReset(zstream);
+
+    if (zret != Z_OK) {
+        av_log(avctx, AV_LOG_ERROR, "Could not reset inflate: %d\n", zret);
+        return AVERROR(EINVAL);
+    }
+
+    zstream->next_in  = avpkt->data;
+    zstream->avail_in = avpkt->size;
+
+    prev = prev_pic->data[0];
+    dst  = pic->data[0];
+
+    /**
+     * ZeroCodec has very simple interframe compression. If a value
+     * is the same as the previous frame, set it to 0.
+     */
+
+    if (avpkt->flags & AV_PKT_FLAG_KEY) {
+
+        pic->key_frame = 1;
+        pic->pict_type = AV_PICTURE_TYPE_I;
+
+        for (i = 0; i < avctx->height; i++) {
+
+            zstream->next_out  = dst;
+            zstream->avail_out = avctx->width << 1;
+
+            zret = inflate(zstream, Z_SYNC_FLUSH);
+
+            if (zret != Z_OK && zret != Z_STREAM_END) {
+                av_log(avctx, AV_LOG_ERROR,
+                       "Inflate failed with return code: %d\n", zret);
+                return AVERROR(EINVAL);
+            }
+
+            dst += pic->linesize[0];
+        }
+    } else {
+
+        pic->key_frame = 0;
+        pic->pict_type = AV_PICTURE_TYPE_P;
+
+        for (i = 0; i < avctx->height; i++) {
+
+            zstream->next_out  = dst;
+            zstream->avail_out = avctx->width << 1;
+
+            zret = inflate(zstream, Z_SYNC_FLUSH);
+
+            if (zret != Z_OK && zret != Z_STREAM_END) {
+                av_log(avctx, AV_LOG_ERROR,
+                       "Inflate failed with return code: %d\n", zret);
+                return AVERROR(EINVAL);
+            }
+
+            for (j = 0; j < avctx->width << 1; j++)
+                dst[j] += prev[j] & -!dst[j];
+
+            prev += prev_pic->linesize[0];
+            dst  += pic->linesize[0];
+        }
+    }
+
+    /* Release the previous buffer if need be */
+    if (prev_pic->data[0])
+        avctx->release_buffer(avctx, prev_pic);
+
+    /* Store the previouse frame for use later */
+    *prev_pic = *pic;
+
+    *data_size       = sizeof(AVFrame);
+    *(AVFrame *)data = *pic;
+
+    return avpkt->size;
+}
+
+static av_cold int zerocodec_decode_close(AVCodecContext *avctx)
+{
+    ZeroCodecContext *zc = avctx->priv_data;
+    AVFrame *prev_pic    = &zc->previous_frame;
+
+    inflateEnd(&zc->zstream);
+
+    /* Release last frame */
+    if (prev_pic->data[0])
+        avctx->release_buffer(avctx, prev_pic);
+
+    av_freep(&avctx->coded_frame);
+
+    return 0;
+}
+
+static av_cold int zerocodec_decode_init(AVCodecContext *avctx)
+{
+    ZeroCodecContext *zc = avctx->priv_data;
+    z_stream *zstream    = &zc->zstream;
+    int zret;
+
+    avctx->pix_fmt             = PIX_FMT_UYVY422;
+    avctx->bits_per_raw_sample = 8;
+
+    zc->size = avpicture_get_size(avctx->pix_fmt,
+                                  avctx->width, avctx->height);
+
+    zstream->zalloc = Z_NULL;
+    zstream->zfree  = Z_NULL;
+    zstream->opaque = Z_NULL;
+
+    zret = inflateInit(zstream);
+
+    if (zret != Z_OK) {
+        av_log(avctx, AV_LOG_ERROR, "Could not initialize inflate: %d\n", zret);
+        return AVERROR(ENOMEM);
+    }
+
+    avctx->coded_frame = avcodec_alloc_frame();
+
+    if (!avctx->coded_frame) {
+        av_log(avctx, AV_LOG_ERROR, "Could not allocate frame buffer.\n");
+        zerocodec_decode_close(avctx);
+        return AVERROR(ENOMEM);
+    }
+
+    return 0;
+}
+
+AVCodec ff_zerocodec_decoder = {
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .name           = "zerocodec",
+    .id             = CODEC_ID_ZEROCODEC,
+    .priv_data_size = sizeof(ZeroCodecContext),
+    .init           = zerocodec_decode_init,
+    .decode         = zerocodec_decode_frame,
+    .close          = zerocodec_decode_close,
+    .capabilities   = CODEC_CAP_DR1,
+    .long_name      = NULL_IF_CONFIG_SMALL("ZeroCodec Lossless Video"),
+};
index 5b2fd80..2b6165e 100644 (file)
@@ -283,6 +283,7 @@ const AVCodecTag ff_codec_bmp_tags[] = {
     { CODEC_ID_UTVIDEO,      MKTAG('U', 'L', 'Y', '2') },
     { CODEC_ID_VBLE,         MKTAG('V', 'B', 'L', 'E') },
     { CODEC_ID_DXTORY,       MKTAG('x', 't', 'o', 'r') },
+    { CODEC_ID_ZEROCODEC,    MKTAG('Z', 'E', 'C', 'O') },
     { CODEC_ID_NONE,         0 }
 };