T1 decoder: check code stream errors when predictable termination is enabled and...
[openjpeg.git] / src / lib / openjp2 / mqc_inl.h
index 7e1c17d159b4f1aafe6236cfe116ecdd4f662e50..832331ee683c7e1440ec1f517782582a105ffcb6 100644 (file)
 
 #ifndef __MQC_INL_H
 #define __MQC_INL_H
-/**
-FIXME DOC
-@param mqc MQC handle
-@return
-*/
-static INLINE OPJ_INT32 opj_mqc_mpsexchange(opj_mqc_t *const mqc)
-{
-    OPJ_INT32 d;
-    if (mqc->a < (*mqc->curctx)->qeval) {
-        d = (OPJ_INT32)(1 - (*mqc->curctx)->mps);
-        *mqc->curctx = (*mqc->curctx)->nlps;
-    } else {
-        d = (OPJ_INT32)(*mqc->curctx)->mps;
-        *mqc->curctx = (*mqc->curctx)->nmps;
-    }
 
-    return d;
+/* For internal use of opj_mqc_decode_macro() */
+#define opj_mqc_mpsexchange_macro(d, curctx, a) \
+{ \
+    if (a < (*curctx)->qeval) { \
+        d = !((*curctx)->mps); \
+        *curctx = (*curctx)->nlps; \
+    } else { \
+        d = (*curctx)->mps; \
+        *curctx = (*curctx)->nmps; \
+    } \
 }
 
-/**
-FIXME DOC
-@param mqc MQC handle
-@return
-*/
-static INLINE OPJ_INT32 opj_mqc_lpsexchange(opj_mqc_t *const mqc)
-{
-    OPJ_INT32 d;
-    if (mqc->a < (*mqc->curctx)->qeval) {
-        mqc->a = (*mqc->curctx)->qeval;
-        d = (OPJ_INT32)(*mqc->curctx)->mps;
-        *mqc->curctx = (*mqc->curctx)->nmps;
-    } else {
-        mqc->a = (*mqc->curctx)->qeval;
-        d = (OPJ_INT32)(1 - (*mqc->curctx)->mps);
-        *mqc->curctx = (*mqc->curctx)->nlps;
-    }
-
-    return d;
+/* For internal use of opj_mqc_decode_macro() */
+#define opj_mqc_lpsexchange_macro(d, curctx, a) \
+{ \
+    if (a < (*curctx)->qeval) { \
+        a = (*curctx)->qeval; \
+        d = (*curctx)->mps; \
+        *curctx = (*curctx)->nmps; \
+    } else { \
+        a = (*curctx)->qeval; \
+        d = !((*curctx)->mps); \
+        *curctx = (*curctx)->nlps; \
+    } \
 }
 
+
 /**
-Input a byte
+Decode a symbol using raw-decoder. Cfr p.506 TAUBMAN
 @param mqc MQC handle
+@return Returns the decoded symbol (0 or 1)
 */
-#ifdef MQC_PERF_OPT
-static INLINE void opj_mqc_bytein(opj_mqc_t *const mqc)
-{
-    unsigned int i = *((unsigned int *) mqc->bp);
-    mqc->c += i & 0xffff00;
-    mqc->ct = i & 0x0f;
-    mqc->bp += (i >> 2) & 0x04;
-}
-#else
-static INLINE void opj_mqc_bytein(opj_mqc_t *const mqc)
+static INLINE OPJ_UINT32 opj_mqc_raw_decode(opj_mqc_t *mqc)
 {
-    if (mqc->bp != mqc->end) {
-        OPJ_UINT32 c;
-        if (mqc->bp + 1 != mqc->end) {
-            c = *(mqc->bp + 1);
-        } else {
-            c = 0xff;
-        }
-        if (*mqc->bp == 0xff) {
-            if (c > 0x8f) {
-                mqc->c += 0xff00;
+    OPJ_UINT32 d;
+    if (mqc->ct == 0) {
+        /* Given opj_mqc_raw_init_dec() we know that at some point we will */
+        /* have a 0xFF 0xFF artificial marker */
+        if (mqc->c == 0xff) {
+            if (*mqc->bp  > 0x8f) {
+                mqc->c = 0xff;
                 mqc->ct = 8;
             } else {
-                mqc->bp++;
-                mqc->c += c << 9;
+                mqc->c = *mqc->bp;
+                mqc->bp ++;
                 mqc->ct = 7;
             }
         } else {
-            mqc->bp++;
-            mqc->c += c << 8;
+            mqc->c = *mqc->bp;
+            mqc->bp ++;
             mqc->ct = 8;
         }
-    } else {
-        mqc->c += 0xff00;
-        mqc->ct = 8;
     }
+    mqc->ct--;
+    d = ((OPJ_UINT32)mqc->c >> mqc->ct) & 0x01U;
+
+    return d;
+}
+
+
+#define opj_mqc_bytein_macro(mqc, c, ct) \
+{ \
+        OPJ_UINT32 l_c;  \
+        /* Given opj_mqc_init_dec() we know that at some point we will */ \
+        /* have a 0xFF 0xFF artificial marker */ \
+        l_c = *(mqc->bp + 1); \
+        if (*mqc->bp == 0xff) { \
+            if (l_c > 0x8f) { \
+                c += 0xff00; \
+                ct = 8; \
+                mqc->end_of_byte_stream_counter ++; \
+            } else { \
+                mqc->bp++; \
+                c += l_c << 9; \
+                ct = 7; \
+            } \
+        } else { \
+            mqc->bp++; \
+            c += l_c << 8; \
+            ct = 8; \
+        } \
+}
+
+/* For internal use of opj_mqc_decode_macro() */
+#define opj_mqc_renormd_macro(mqc, a, c, ct) \
+{ \
+    do { \
+        if (ct == 0) { \
+            opj_mqc_bytein_macro(mqc, c, ct); \
+        } \
+        a <<= 1; \
+        c <<= 1; \
+        ct--; \
+    } while (a < 0x8000); \
 }
-#endif
+
+#define opj_mqc_decode_macro(d, mqc, curctx, a, c, ct) \
+{ \
+    /* Implements ISO 15444-1 C.3.2 Decoding a decision (DECODE) */ \
+    /* Note: alternate "J.2 - Decoding an MPS or an LPS in the */ \
+    /* software-conventions decoder" has been tried, but does not bring any */ \
+    /* improvement. See https://github.com/uclouvain/openjpeg/issues/921 */ \
+    a -= (*curctx)->qeval;  \
+    if ((c >> 16) < (*curctx)->qeval) {  \
+        opj_mqc_lpsexchange_macro(d, curctx, a);  \
+        opj_mqc_renormd_macro(mqc, a, c, ct);  \
+    } else {  \
+        c -= (*curctx)->qeval << 16;  \
+        if ((a & 0x8000) == 0) { \
+            opj_mqc_mpsexchange_macro(d, curctx, a); \
+            opj_mqc_renormd_macro(mqc, a, c, ct); \
+        } else { \
+            d = (*curctx)->mps; \
+        } \
+    } \
+}
+
+#define DOWNLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct) \
+        register opj_mqc_state_t **curctx = mqc->curctx; \
+        register OPJ_UINT32 c = mqc->c; \
+        register OPJ_UINT32 a = mqc->a; \
+        register OPJ_UINT32 ct = mqc->ct
+
+#define UPLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct) \
+        mqc->curctx = curctx; \
+        mqc->c = c; \
+        mqc->a = a; \
+        mqc->ct = ct;
 
 /**
-Renormalize mqc->a and mqc->c while decoding
+Input a byte
 @param mqc MQC handle
 */
-static INLINE void opj_mqc_renormd(opj_mqc_t *const mqc)
+static INLINE void opj_mqc_bytein(opj_mqc_t *const mqc)
 {
-    do {
-        if (mqc->ct == 0) {
-            opj_mqc_bytein(mqc);
-        }
-        mqc->a <<= 1;
-        mqc->c <<= 1;
-        mqc->ct--;
-    } while (mqc->a < 0x8000);
+    opj_mqc_bytein_macro(mqc, mqc->c, mqc->ct);
 }
 
 /**
-Decode a symbol
+Renormalize mqc->a and mqc->c while decoding
 @param mqc MQC handle
-@return Returns the decoded symbol (0 or 1)
 */
-static INLINE OPJ_INT32 opj_mqc_decode(opj_mqc_t *const mqc)
-{
-    OPJ_INT32 d;
-    mqc->a -= (*mqc->curctx)->qeval;
-    if ((mqc->c >> 16) < (*mqc->curctx)->qeval) {
-        d = opj_mqc_lpsexchange(mqc);
-        opj_mqc_renormd(mqc);
-    } else {
-        mqc->c -= (*mqc->curctx)->qeval << 16;
-        if ((mqc->a & 0x8000) == 0) {
-            d = opj_mqc_mpsexchange(mqc);
-            opj_mqc_renormd(mqc);
-        } else {
-            d = (OPJ_INT32)(*mqc->curctx)->mps;
-        }
-    }
+#define opj_mqc_renormd(mqc) \
+    opj_mqc_renormd_macro(mqc, mqc->a, mqc->c, mqc->ct)
 
-    return d;
-}
+/**
+Decode a symbol
+@param d OPJ_UINT32 value where to store the decoded symbol
+@param mqc MQC handle
+@return Returns the decoded symbol (0 or 1) in d
+*/
+#define opj_mqc_decode(d, mqc) \
+    opj_mqc_decode_macro(d, mqc, mqc->curctx, mqc->a, mqc->c, mqc->ct)
 
 #endif /* __MQC_INL_H */