summaryrefslogtreecommitdiff
path: root/libavcodec/mqcdec.c
diff options
context:
space:
mode:
authorNicolas Bertrand <nicoinattendu@gmail.com>2013-04-22 11:41:01 +0200
committerDiego Biurrun <diego@biurrun.de>2013-04-22 15:38:29 +0200
commitc81a70638116eaf4251075475e5cbb600a33c5ec (patch)
treeaa1763bfcab7c9d475bba445ca99de2bfe805826 /libavcodec/mqcdec.c
parent0c15a9aa7e1654a19144eb594f9639a57fd47482 (diff)
JPEG 2000 decoder for DCinema
Based on the 2007 GSoC project from Kamil Nowosad <k.nowosad@students.mimuw.edu.pl> Updated to current programming standards, style and many more small fixes by Diego Biurrun <diego@biurrun.de>. Signed-off-by: Diego Biurrun <diego@biurrun.de>
Diffstat (limited to 'libavcodec/mqcdec.c')
-rw-r--r--libavcodec/mqcdec.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/libavcodec/mqcdec.c b/libavcodec/mqcdec.c
new file mode 100644
index 0000000000..889763ac66
--- /dev/null
+++ b/libavcodec/mqcdec.c
@@ -0,0 +1,93 @@
+/*
+ * MQ-coder decoder
+ * Copyright (c) 2007 Kamil Nowosad
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * MQ-coder decoder
+ * @file
+ * @author Kamil Nowosad
+ */
+
+#include "mqc.h"
+
+static void bytein(MqcState *mqc)
+{
+ if (*mqc->bp == 0xff) {
+ if (*(mqc->bp + 1) > 0x8f)
+ mqc->c++;
+ else {
+ mqc->bp++;
+ mqc->c += 2 + 0xfe00 - (*mqc->bp << 9);
+ }
+ } else {
+ mqc->bp++;
+ mqc->c += 1 + 0xff00 - (*mqc->bp << 8);
+ }
+}
+
+static int exchange(MqcState *mqc, uint8_t *cxstate, int lps)
+{
+ int d;
+ if ((mqc->a < ff_mqc_qe[*cxstate]) ^ (!lps)) {
+ if (lps)
+ mqc->a = ff_mqc_qe[*cxstate];
+ d = *cxstate & 1;
+ *cxstate = ff_mqc_nmps[*cxstate];
+ } else {
+ if (lps)
+ mqc->a = ff_mqc_qe[*cxstate];
+ d = 1 - (*cxstate & 1);
+ *cxstate = ff_mqc_nlps[*cxstate];
+ }
+ // do RENORMD: see ISO/IEC 15444-1:2002 §C.3.3
+ do {
+ if (!(mqc->c & 0xff)) {
+ mqc->c -= 0x100;
+ bytein(mqc);
+ }
+ mqc->a += mqc->a;
+ mqc->c += mqc->c;
+ } while (!(mqc->a & 0x8000));
+ return d;
+}
+
+void ff_mqc_initdec(MqcState *mqc, uint8_t *bp)
+{
+ ff_mqc_init_contexts(mqc);
+ mqc->bp = bp;
+ mqc->c = (*mqc->bp ^ 0xff) << 16;
+ bytein(mqc);
+ mqc->c = mqc->c << 7;
+ mqc->a = 0x8000;
+}
+
+int ff_mqc_decode(MqcState *mqc, uint8_t *cxstate)
+{
+ mqc->a -= ff_mqc_qe[*cxstate];
+ if ((mqc->c >> 16) < mqc->a) {
+ if (mqc->a & 0x8000)
+ return *cxstate & 1;
+ else
+ return exchange(mqc, cxstate, 0);
+ } else {
+ mqc->c -= mqc->a << 16;
+ return exchange(mqc, cxstate, 1);
+ }
+}