summaryrefslogtreecommitdiff
path: root/libavcodec/mpeg12.c
diff options
context:
space:
mode:
authorVittorio Giovara <vittorio.giovara@gmail.com>2016-01-25 12:56:11 -0500
committerDiego Biurrun <diego@biurrun.de>2016-02-09 20:04:59 +0100
commit7c25ffe070c286874a8c3513f7504b90e1626b0c (patch)
tree8532cb662850f35681472362c3a1eab3fa597d77 /libavcodec/mpeg12.c
parent249827f736db4c94dfcb24a3883aa4c04f9b119b (diff)
mpeg1: Make intra-block decoding independent of MpegEncContext
This allows untangling the eatqi decoder from the MPEG-1 decoder. Signed-off-by: Vittorio Giovara <vittorio.giovara@gmail.com> Signed-off-by: Diego Biurrun <diego@biurrun.de>
Diffstat (limited to 'libavcodec/mpeg12.c')
-rw-r--r--libavcodec/mpeg12.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c
index 69c6d0a09a..c0c680d867 100644
--- a/libavcodec/mpeg12.c
+++ b/libavcodec/mpeg12.c
@@ -236,3 +236,91 @@ int ff_mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size,
pc->state = state;
return END_NOT_FOUND;
}
+
+#define MAX_INDEX (64 - 1)
+
+int ff_mpeg1_decode_block_intra(GetBitContext *gb,
+ const uint16_t *quant_matrix,
+ uint8_t *const scantable, int last_dc[3],
+ int16_t *block, int index, int qscale)
+{
+ int dc, diff, i = 0, component;
+ RLTable *rl = &ff_rl_mpeg1;
+
+ /* DC coefficient */
+ component = index <= 3 ? 0 : index - 4 + 1;
+
+ diff = decode_dc(gb, component);
+ if (diff >= 0xffff)
+ return AVERROR_INVALIDDATA;
+
+ dc = last_dc[component];
+ dc += diff;
+ last_dc[component] = dc;
+
+ block[0] = dc * quant_matrix[0];
+
+ {
+ OPEN_READER(re, gb);
+ /* now quantify & encode AC coefficients */
+ while (1) {
+ int level, run, j;
+
+ UPDATE_CACHE(re, gb);
+ GET_RL_VLC(level, run, re, gb, rl->rl_vlc[0], TEX_VLC_BITS, 2, 0);
+
+ if (level == 127) {
+ break;
+ } else if (level != 0) {
+ i += run;
+ if (i > MAX_INDEX)
+ break;
+
+ j = scantable[i];
+ level = (level * qscale * quant_matrix[j]) >> 4;
+ level = (level - 1) | 1;
+ level = (level ^ SHOW_SBITS(re, gb, 1)) -
+ SHOW_SBITS(re, gb, 1);
+ LAST_SKIP_BITS(re, gb, 1);
+ } else {
+ /* escape */
+ run = SHOW_UBITS(re, gb, 6) + 1;
+ LAST_SKIP_BITS(re, gb, 6);
+ UPDATE_CACHE(re, gb);
+ level = SHOW_SBITS(re, gb, 8);
+ SKIP_BITS(re, gb, 8);
+
+ if (level == -128) {
+ level = SHOW_UBITS(re, gb, 8) - 256;
+ LAST_SKIP_BITS(re, gb, 8);
+ } else if (level == 0) {
+ level = SHOW_UBITS(re, gb, 8);
+ LAST_SKIP_BITS(re, gb, 8);
+ }
+
+ i += run;
+ if (i > MAX_INDEX)
+ break;
+
+ j = scantable[i];
+ if (level < 0) {
+ level = -level;
+ level = (level * qscale * quant_matrix[j]) >> 4;
+ level = (level - 1) | 1;
+ level = -level;
+ } else {
+ level = (level * qscale * quant_matrix[j]) >> 4;
+ level = (level - 1) | 1;
+ }
+ }
+
+ block[j] = level;
+ }
+ CLOSE_READER(re, gb);
+ }
+
+ if (i > MAX_INDEX)
+ i = AVERROR_INVALIDDATA;
+
+ return i;
+}