[FFmpeg-cvslog] avcodec: add TrueMotion 2.0 Real Time decoder

Paul B Mahol git at videolan.org
Thu Apr 21 20:15:45 CEST 2016


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Wed Apr  6 11:02:39 2016 +0200| [c85d04251df613db0e94a0bca50dbedfd38f41dd] | committer: Paul B Mahol

avcodec: add TrueMotion 2.0 Real Time decoder

Signed-off-by: Paul B Mahol <onemda at gmail.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=c85d04251df613db0e94a0bca50dbedfd38f41dd
---

 Changelog                  |    1 +
 libavcodec/Makefile        |    1 +
 libavcodec/allcodecs.c     |    1 +
 libavcodec/avcodec.h       |    1 +
 libavcodec/codec_desc.c    |    7 ++
 libavcodec/truemotion2rt.c |  220 ++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/version.h       |    2 +-
 libavformat/riff.c         |    1 +
 8 files changed, 233 insertions(+), 1 deletion(-)

diff --git a/Changelog b/Changelog
index 58ac1d7..328ba46 100644
--- a/Changelog
+++ b/Changelog
@@ -28,6 +28,7 @@ version <next>:
 - readvitc filter
 - VAAPI-accelerated format conversion and scaling
 - libnpp/CUDA-accelerated format conversion and scaling
+- Duck TrueMotion 2.0 Real Time decoder
 
 version 3.0:
 - Common Encryption (CENC) MP4 encoding and decoding support
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 6a2450e..bc4c97f 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -524,6 +524,7 @@ OBJS-$(CONFIG_TMV_DECODER)             += tmv.o cga_data.o
 OBJS-$(CONFIG_TRUEHD_DECODER)          += mlpdec.o mlpdsp.o
 OBJS-$(CONFIG_TRUEMOTION1_DECODER)     += truemotion1.o
 OBJS-$(CONFIG_TRUEMOTION2_DECODER)     += truemotion2.o
+OBJS-$(CONFIG_TRUEMOTION2RT_DECODER)   += truemotion2rt.o
 OBJS-$(CONFIG_TRUESPEECH_DECODER)      += truespeech.o
 OBJS-$(CONFIG_TSCC_DECODER)            += tscc.o msrledec.o
 OBJS-$(CONFIG_TSCC2_DECODER)           += tscc2.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index f88c0ff..2b46a13 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -310,6 +310,7 @@ void avcodec_register_all(void)
     REGISTER_DECODER(TMV,               tmv);
     REGISTER_DECODER(TRUEMOTION1,       truemotion1);
     REGISTER_DECODER(TRUEMOTION2,       truemotion2);
+    REGISTER_DECODER(TRUEMOTION2RT,     truemotion2rt);
     REGISTER_DECODER(TSCC,              tscc);
     REGISTER_DECODER(TSCC2,             tscc2);
     REGISTER_DECODER(TXD,               txd);
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index da32a6b..161ee9d 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -404,6 +404,7 @@ enum AVCodecID {
     AV_CODEC_ID_APNG,
     AV_CODEC_ID_DAALA,
     AV_CODEC_ID_CFHD,
+    AV_CODEC_ID_TRUEMOTION2RT,
 
     /* various PCM "codecs" */
     AV_CODEC_ID_FIRST_AUDIO = 0x10000,     ///< A dummy id pointing at the start of audio codecs
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index b9c0c99..7b48ee6 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1528,6 +1528,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("Cineform HD"),
         .props     = AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_TRUEMOTION2RT,
+        .type      = AVMEDIA_TYPE_VIDEO,
+        .name      = "truemotion2rt",
+        .long_name = NULL_IF_CONFIG_SMALL("Duck TrueMotion 2.0 Real Time"),
+        .props     = AV_CODEC_PROP_LOSSY,
+    },
 
     /* various PCM "codecs" */
     {
diff --git a/libavcodec/truemotion2rt.c b/libavcodec/truemotion2rt.c
new file mode 100644
index 0000000..ef0e2cb
--- /dev/null
+++ b/libavcodec/truemotion2rt.c
@@ -0,0 +1,220 @@
+/*
+ * Duck TrueMotion 2.0 Real Time 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
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "avcodec.h"
+#define BITSTREAM_READER_LE
+#include "get_bits.h"
+#include "internal.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/internal.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/mem.h"
+
+typedef struct TrueMotion2RTContext {
+    GetBitContext gb;
+    const uint8_t *buf;
+    int size;
+    int delta_size;
+    int hscale;
+} TrueMotion2RTContext;
+
+static av_cold int decode_init(AVCodecContext *avctx)
+{
+    avctx->pix_fmt = AV_PIX_FMT_YUV410P;
+    return 0;
+}
+
+/* Returns the number of bytes consumed from the bytestream. Returns -1 if
+ * there was an error while decoding the header */
+static int truemotion2rt_decode_header(AVCodecContext *avctx)
+{
+    TrueMotion2RTContext *s = avctx->priv_data;
+    uint8_t header_buffer[128] = { 0 };  /* logical maximum size of the header */
+    int i, header_size;
+
+    header_size = ((s->buf[0] >> 5) | (s->buf[0] << 3)) & 0x7f;
+    if (header_size < 10) {
+        av_log(avctx, AV_LOG_ERROR, "invalid header size (%d)\n", header_size);
+        return AVERROR_INVALIDDATA;
+    }
+
+    if (header_size + 1 > s->size) {
+        av_log(avctx, AV_LOG_ERROR, "Input packet too small.\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    /* unscramble the header bytes with a XOR operation */
+    for (i = 1; i < header_size; i++)
+        header_buffer[i - 1] = s->buf[i] ^ s->buf[i + 1];
+
+    s->delta_size = header_buffer[1];
+    s->hscale = 1 + !!header_buffer[3];
+    if (s->delta_size < 2 || s->delta_size > 4)
+        return AVERROR_INVALIDDATA;
+
+    avctx->height = AV_RL16(header_buffer + 5);
+    avctx->width  = AV_RL16(header_buffer + 7);
+
+    return header_size;
+}
+
+static const int16_t delta_tab4[] = {
+    1, -1, 2, -3, 8, -8, 18, -18, 36, -36, 54, -54, 96, -96, 144, -144
+};
+
+static const int16_t delta_tab3[] = {
+    2, -3, 8, -8, 18, -18, 36, -36
+};
+
+static const int16_t delta_tab2[] = {
+    5, -7, 36, -36
+};
+
+static const int16_t *const delta_tabs[] = {
+    delta_tab2, delta_tab3, delta_tab4,
+};
+
+static int decode_frame(AVCodecContext *avctx,
+                        void *data, int *got_frame,
+                        AVPacket *avpkt)
+{
+    TrueMotion2RTContext *s = avctx->priv_data;
+    const uint8_t *buf = avpkt->data;
+    int ret, buf_size = avpkt->size;
+    AVFrame * const p = data;
+    GetBitContext *gb = &s->gb;
+    uint8_t *dst;
+    int x, y, delta_mode;
+
+    s->buf = buf;
+    s->size = buf_size;
+
+    if ((ret = truemotion2rt_decode_header(avctx)) < 0)
+        return ret;
+
+    if ((ret = init_get_bits8(gb, buf + ret, buf_size - ret)) < 0)
+        return ret;
+
+    if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
+        return ret;
+
+    skip_bits(gb, 32);
+    delta_mode = s->delta_size - 2;
+    dst = p->data[0];
+    for (y = 0; y < avctx->height; y++) {
+        int diff = 0;
+        for (x = 0; x < avctx->width; x += s->hscale) {
+            diff  += delta_tabs[delta_mode][get_bits(gb, s->delta_size)];
+            dst[x] = av_clip_uint8((y ? dst[x - p->linesize[0]] : 0) + diff);
+        }
+        dst += p->linesize[0];
+    }
+
+    if (s->hscale > 1) {
+        dst = p->data[0];
+        for (y = 0; y < avctx->height; y++) {
+            for (x = 1; x < avctx->width; x += s->hscale) {
+                dst[x] = dst[x - 1];
+            }
+            dst += p->linesize[0];
+        }
+    }
+
+    dst = p->data[0];
+    for (y = 0; y < avctx->height; y++) {
+        for (x = 0; x < avctx->width; x++)
+            dst[x] = av_clip_uint8(dst[x] + (dst[x] - 128) / 3);
+        dst += p->linesize[0];
+    }
+
+    dst = p->data[1];
+    for (y = 0; y < avctx->height >> 2; y++) {
+        int diff = 0;
+        for (x = 0; x < avctx->width >> 2; x += s->hscale) {
+            diff  += delta_tabs[delta_mode][get_bits(gb, s->delta_size)];
+            dst[x] = av_clip_uint8((y ? dst[x - p->linesize[1]] : 128) + diff);
+        }
+        dst += p->linesize[1];
+    }
+
+    if (s->hscale > 1) {
+        dst = p->data[1];
+        for (y = 0; y < avctx->height >> 2; y++) {
+            for (x = 1; x < avctx->width >> 2; x += s->hscale) {
+                dst[x] = dst[x - 1];
+            }
+            dst += p->linesize[1];
+        }
+    }
+
+    dst = p->data[1];
+    for (y = 0; y < avctx->height >> 2; y++) {
+        for (x = 0; x < avctx->width >> 2; x++)
+            dst[x] += (dst[x] - 128) / 8;
+        dst += p->linesize[1];
+    }
+
+    dst = p->data[2];
+    for (y = 0; y < avctx->height >> 2; y++) {
+        int diff = 0;
+        for (x = 0; x < avctx->width >> 2; x += s->hscale) {
+            diff  += delta_tabs[delta_mode][get_bits(gb, s->delta_size)];
+            dst[x] = av_clip_uint8((y ? dst[x - p->linesize[2]] : 128) + diff);
+        }
+        dst += p->linesize[2];
+    }
+
+    if (s->hscale > 1) {
+        dst = p->data[2];
+        for (y = 0; y < avctx->height >> 2; y++) {
+            for (x = 1; x < avctx->width >> 2; x += s->hscale) {
+                dst[x] = dst[x - 1];
+            }
+            dst += p->linesize[2];
+        }
+    }
+
+    dst = p->data[2];
+    for (y = 0; y < avctx->height >> 2; y++) {
+        for (x = 0; x < avctx->width >> 2; x++)
+            dst[x] += (dst[x] - 128) / 8;
+        dst += p->linesize[2];
+    }
+
+    p->pict_type = AV_PICTURE_TYPE_I;
+    *got_frame   = 1;
+
+    return buf_size;
+}
+
+AVCodec ff_truemotion2rt_decoder = {
+    .name           = "truemotion2rt",
+    .long_name      = NULL_IF_CONFIG_SMALL("Duck TrueMotion 2.0 Real Time"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_TRUEMOTION2RT,
+    .priv_data_size = sizeof(TrueMotion2RTContext),
+    .init           = decode_init,
+    .decode         = decode_frame,
+    .capabilities   = AV_CODEC_CAP_DR1,
+};
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 01d3d8e..084ae55 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -28,7 +28,7 @@
 #include "libavutil/version.h"
 
 #define LIBAVCODEC_VERSION_MAJOR  57
-#define LIBAVCODEC_VERSION_MINOR  37
+#define LIBAVCODEC_VERSION_MINOR  38
 #define LIBAVCODEC_VERSION_MICRO 100
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
diff --git a/libavformat/riff.c b/libavformat/riff.c
index 2641a53..5150f4d 100644
--- a/libavformat/riff.c
+++ b/libavformat/riff.c
@@ -352,6 +352,7 @@ const AVCodecTag ff_codec_bmp_tags[] = {
     { AV_CODEC_ID_FRAPS,        MKTAG('F', 'P', 'S', '1') },
     { AV_CODEC_ID_THEORA,       MKTAG('t', 'h', 'e', 'o') },
     { AV_CODEC_ID_TRUEMOTION2,  MKTAG('T', 'M', '2', '0') },
+    { AV_CODEC_ID_TRUEMOTION2RT,MKTAG('T', 'R', '2', '0') },
     { AV_CODEC_ID_CSCD,         MKTAG('C', 'S', 'C', 'D') },
     { AV_CODEC_ID_ZMBV,         MKTAG('Z', 'M', 'B', 'V') },
     { AV_CODEC_ID_KMVC,         MKTAG('K', 'M', 'V', 'C') },



More information about the ffmpeg-cvslog mailing list