/*
* Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
*
* This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
* See http://libmpeg2.sourceforge.net/ for updates.
*
* mpeg2dec is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* mpeg2dec 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "stdafx.h"
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include "libmpeg2.h"
#include "..\..\..\DSUtil\vd.h"
// decode
#define SEQ_EXT 2
#define SEQ_DISPLAY_EXT 4
#define QUANT_MATRIX_EXT 8
#define COPYRIGHT_EXT 0x10
#define PIC_DISPLAY_EXT 0x80
#define PIC_CODING_EXT 0x100
/* default intra quant matrix, in zig-zag order */
static const uint8_t default_intra_quantizer_matrix[64] = {
8,
16, 16,
19, 16, 19,
22, 22, 22, 22,
22, 22, 26, 24, 26,
27, 27, 27, 26, 26, 26,
26, 27, 27, 27, 29, 29, 29,
34, 34, 34, 29, 29, 29, 27, 27,
29, 29, 32, 32, 34, 34, 37,
38, 37, 35, 35, 34, 35,
38, 38, 40, 40, 40,
48, 48, 46, 46,
56, 56, 58,
69, 69,
83
};
static uint8_t mpeg2_scan_norm_2[64] = {
/* Zig-Zag scan pattern */
0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28,
35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63
};
static uint8_t mpeg2_scan_alt_2[64] = {
/* Alternate scan pattern */
0, 8, 16, 24, 1, 9, 2, 10, 17, 25, 32, 40, 48, 56, 57, 49,
41, 33, 26, 18, 3, 11, 4, 12, 19, 27, 34, 42, 50, 58, 35, 43,
51, 59, 20, 28, 5, 13, 6, 14, 21, 29, 36, 44, 52, 60, 37, 45,
53, 61, 22, 30, 7, 15, 23, 31, 38, 46, 54, 62, 39, 47, 55, 63
};
// dummy
extern "C" uint8_t mpeg2_scan_norm[64];
extern "C" uint8_t mpeg2_scan_alt[64];
uint8_t mpeg2_scan_norm[64];
uint8_t mpeg2_scan_alt[64];
// idct (c)
#define W1 2841 /* 2048 * sqrt (2) * cos (1 * pi / 16) */
#define W2 2676 /* 2048 * sqrt (2) * cos (2 * pi / 16) */
#define W3 2408 /* 2048 * sqrt (2) * cos (3 * pi / 16) */
#define W5 1609 /* 2048 * sqrt (2) * cos (5 * pi / 16) */
#define W6 1108 /* 2048 * sqrt (2) * cos (6 * pi / 16) */
#define W7 565 /* 2048 * sqrt (2) * cos (7 * pi / 16) */
/*
* In legal streams, the IDCT output should be between -384 and +384.
* In corrupted streams, it is possible to force the IDCT output to go
* to +-3826 - this is the worst case for a column IDCT where the
* column inputs are 16-bit values.
*/
static uint8_t mpeg2_clip[3840 * 2 + 256];
#define CLIP(i) ((mpeg2_clip + 3840)[i])
#define BUTTERFLY(t0,t1,W0,W1,d0,d1) \
{ \
int tmp = W0 * (d0 + d1); \
t0 = tmp + (W1 - W0) * d1; \
t1 = tmp - (W1 + W0) * d0; \
}
static void __inline idct_row(int16_t* block)
{
int d0, d1, d2, d3;
int a0, a1, a2, a3, b0, b1, b2, b3;
int t0, t1, t2, t3;
/* shortcut */
if(!(block[1] | ((int32_t *)block)[1] | ((int32_t *)block)[2] | ((int32_t *)block)[3]))
{
uint32_t tmp = (uint16_t) (block[0] << 3);
tmp |= tmp << 16;
((int32_t *)block)[0] = tmp;
((int32_t *)block)[1] = tmp;
((int32_t *)block)[2] = tmp;
((int32_t *)block)[3] = tmp;
return;
}
d0 = (block[0] << 11) + 128;
d1 = block[1];
d2 = block[2] << 11;
d3 = block[3];
t0 = d0 + d2;
t1 = d0 - d2;
BUTTERFLY(t2, t3, W6, W2, d3, d1);
a0 = t0 + t2;
a1 = t1 + t3;
a2 = t1 - t3;
a3 = t0 - t2;
d0 = block[4];
d1 = block[5];
d2 = block[6];
d3 = block[7];
BUTTERFLY(t0, t1, W7, W1, d3, d0);
BUTTERFLY(t2, t3, W3, W5, d1, d2);
b0 = t0 + t2;
b3 = t1 + t3;
t0 -= t2;
t1 -= t3;
b1 = ((t0 + t1) * 181) >> 8;
b2 = ((t0 - t1) * 181) >> 8;
block[0] = (a0 + b0) >> 8;
block[1] = (a1 + b1) >> 8;
block[2] = (a2 + b2) >> 8;
block[3] = (a3 + b3) >> 8;
block[4] = (a3 - b3) >> 8;
block[5] = (a2 - b2) >> 8;
block[6] = (a1 - b1) >> 8;
block[7] = (a0 - b0) >> 8;
}
static void __inline idct_col(int16_t* block)
{
int d0, d1, d2, d3;
int a0, a1, a2, a3, b0, b1, b2, b3;
int t0, t1, t2, t3;
d0 = (block[8*0] << 11) + 65536;
d1 = block[8*1];
d2 = block[8*2] << 11;
d3 = block[8*3];
t0 = d0 + d2;
t1 = d0 - d2;
BUTTERFLY(t2, t3, W6, W2, d3, d1);
a0 = t0 + t2;
a1 = t1 + t3;
a2 = t1 - t3;
a3 = t0 - t2;
d0 = block[8*4];
d1 = block[8*5];
d2 = block[8*6];
d3 = block[8*7];
BUTTERFLY(t0, t1, W7, W1, d3, d0);
BUTTERFLY(t2, t3, W3, W5, d1, d2);
b0 = t0 + t2;
b3 = t1 + t3;
t0 = (t0 - t2) >> 8;
t1 = (t1 - t3) >> 8;
b1 = (t0 + t1) * 181;
b2 = (t0 - t1) * 181;
block[8*0] = (a0 + b0) >> 17;
block[8*1] = (a1 + b1) >> 17;
block[8*2] = (a2 + b2) >> 17;
block[8*3] = (a3 + b3) >> 17;
block[8*4] = (a3 - b3) >> 17;
block[8*5] = (a2 - b2) >> 17;
block[8*6] = (a1 - b1) >> 17;
block[8*7] = (a0 - b0) >> 17;
}
static void mpeg2_idct_copy_c(int16_t* block, uint8_t* dest, const int stride)
{
for(int i = 0; i < 8; i++) idct_row(block + 8 * i);
for(int i = 0; i < 8; i++) idct_col(block + i);
for(int i = 0; i < 8; i++)
{
dest[0] = CLIP(block[0]);
dest[1] = CLIP(block[1]);
dest[2] = CLIP(block[2]);
dest[3] = CLIP(block[3]);
dest[4] = CLIP(block[4]);
dest[5] = CLIP(block[5]);
dest[6] = CLIP(block[6]);
dest[7] = CLIP(block[7]);
block[0] = 0; block[1] = 0; block[2] = 0; block[3] = 0;
block[4] = 0; block[5] = 0; block[6] = 0; block[7] = 0;
dest += stride;
block += 8;
}
}
static void mpeg2_idct_add_c(const int last, int16_t* block, uint8_t* dest, const int stride)
{
if(last != 129 || (block[0] & 7) == 4)
{
for(int i = 0; i < 8; i++) idct_row(block + 8 * i);
for(int i = 0; i < 8; i++) idct_col(block + i);
for(int i = 0; i < 8; i++)
{
dest[0] = CLIP(block[0] + dest[0]);
dest[1] = CLIP(block[1] + dest[1]);
dest[2] = CLIP(block[2] + dest[2]);
dest[3] = CLIP(block[3] + dest[3]);
dest[4] = CLIP(block[4] + dest[4]);
dest[5] = CLIP(block[5] + dest[5]);
dest[6] = CLIP(block[6] + dest[6]);
dest[7] = CLIP(block[7] + dest[7]);
block[0] = 0; block[1] = 0; block[2] = 0; block[3] = 0;
block[4] = 0; block[5] = 0; block[6] = 0; block[7] = 0;
dest += stride;
block += 8;
}
}
else
{
int DC = (block[0] + 4) >> 3;
block[0] = block[63] = 0;
for(int i = 0; i < 8; i++)
{
dest[0] = CLIP(DC + dest[0]);
dest[1] = CLIP(DC + dest[1]);
dest[2] = CLIP(DC + dest[2]);
dest[3] = CLIP(DC + dest[3]);
dest[4] = CLIP(DC + dest[4]);
dest[5] = CLIP(DC + dest[5]);
dest[6] = CLIP(DC + dest[6]);
dest[7] = CLIP(DC + dest[7]);
dest += stride;
}
}
}
static void mpeg2_idct_init_c()
{
for(int i = -3840; i < 3840 + 256; i++)
{
CLIP(i) = (i < 0) ? 0 : ((i > 255) ? 255 : i);
}
// only needed with idct_c
for(int i = 0; i < 64; i++)
{
mpeg2_scan_norm_2[i] = ((mpeg2_scan_norm_2[i] & 0x36) >> 1) | ((mpeg2_scan_norm_2[i] & 0x09) << 2);
mpeg2_scan_alt_2[i] = ((mpeg2_scan_alt_2[i] & 0x36) >> 1) | ((mpeg2_scan_alt_2[i] & 0x09) << 2);
}
}
// mc (c)
#define avg2(a,b) ((a+b+1)>>1)
#define avg4(a,b,c,d) ((a+b+c+d+2)>>2)
#define predict_o(i) (ref[i])
#define predict_x(i) (avg2(ref[i], ref[i+1]))
#define predict_y(i) (avg2(ref[i], (ref+stride)[i]))
#define predict_xy(i) (avg4(ref[i], ref[i+1], (ref+stride)[i], (ref+stride)[i+1]))
#define put(predictor,i) dest[i] = predictor(i)
#define avg(predictor,i) dest[i] = avg2(predictor(i), dest[i])
/* mc function template */
#define MC_FUNC(op,xy) \
static void MC_##op##_##xy##_16_c (uint8_t* dest, const uint8_t* ref, const int stride, int height) \
{ \
do { \
op (predict_##xy, 0); \
op (predict_##xy, 1); \
op (predict_##xy, 2); \
op (predict_##xy, 3); \
op (predict_##xy, 4); \
op (predict_##xy, 5); \
op (predict_##xy, 6); \
op (predict_##xy, 7); \
op (predict_##xy, 8); \
op (predict_##xy, 9); \
op (predict_##xy, 10); \
op (predict_##xy, 11); \
op (predict_##xy, 12); \
op (predict_##xy, 13); \
op (predict_##xy, 14); \
op (predict_##xy, 15); \
ref += stride; \
dest += stride; \
} while (--height); \
} \
static void MC_##op##_##xy##_8_c (uint8_t * dest, const uint8_t * ref, const int stride, int height) \
{ \
do { \
op (predict_##xy, 0); \
op (predict_##xy, 1); \
op (predict_##xy, 2); \
op (predict_##xy, 3); \
op (predict_##xy, 4); \
op (predict_##xy, 5); \
op (predict_##xy, 6); \
op (predict_##xy, 7); \
ref += stride; \
dest += stride; \
} while (--height); \
}
/* definitions of the actual mc functions */
MC_FUNC(put,o)
MC_FUNC(avg,o)
MC_FUNC(put,x)
MC_FUNC(avg,x)
MC_FUNC(put,y)
MC_FUNC(avg,y)
MC_FUNC(put,xy)
MC_FUNC(avg,xy)
#define MPEG2_MC_EXTERN(x) mpeg2_mc_t mpeg2_mc_##x = { \
{MC_put_o_16_##x, MC_put_x_16_##x, MC_put_y_16_##x, MC_put_xy_16_##x, \
MC_put_o_8_##x, MC_put_x_8_##x, MC_put_y_8_##x, MC_put_xy_8_##x}, \
{MC_avg_o_16_##x, MC_avg_x_16_##x, MC_avg_y_16_##x, MC_avg_xy_16_##x, \
MC_avg_o_8_##x, MC_avg_x_8_##x, MC_avg_y_8_##x, MC_avg_xy_8_##x} \
};
MPEG2_MC_EXTERN(c)
// idct (mmx)
extern "C" void mpeg2_idct_copy_mmx(int16_t* block, uint8_t* dest, const int stride);
extern "C" void mpeg2_idct_add_mmx(const int last, int16_t* block, uint8_t* dest, const int stride);
static void mpeg2_idct_init_mmx()
{
for(int i = 0; i < 64; i++)
{
mpeg2_scan_norm_2[i] = (mpeg2_scan_norm_2[i] & 0x38) | ((mpeg2_scan_norm_2[i] & 6) >> 1) | ((mpeg2_scan_norm_2[i] & 1) << 2);
mpeg2_scan_alt_2[i] = (mpeg2_scan_alt_2[i] & 0x38) | ((mpeg2_scan_alt_2[i] & 6) >> 1) | ((mpeg2_scan_alt_2[i] & 1) << 2);
}
}
// mc (mmx)
extern "C" mpeg2_mc_t mpeg2_mc_mmx;
// idct (sse2)
extern void mpeg2_idct_init_sse2();
extern void mpeg2_idct_copy_sse2(int16_t* block, uint8_t* dest, const int stride);
extern void mpeg2_idct_add_sse2(const int last, int16_t* block, uint8_t* dest, const int stride);
// mc (sse2)
extern mpeg2_mc_t mpeg2_mc_sse2;
// idct (null)
static void mpeg2_idct_init_null() {}
static void mpeg2_idct_copy_null(int16_t* block, uint8_t* dest, const int stride) {}
static void mpeg2_idct_add_null(const int last, int16_t* block, uint8_t* dest, const int stride) {}
// mc (null)
static void MC_null(uint8_t* dest, const uint8_t* ref, const int stride, int height) {}
mpeg2_mc_t mpeg2_mc_null =
{
{MC_null, MC_null, MC_null, MC_null, MC_null, MC_null, MC_null, MC_null},
{MC_null, MC_null, MC_null, MC_null, MC_null, MC_null, MC_null, MC_null}
};
//
CMpeg2Dec::CMpeg2Dec()
{
m_shift = 0;
m_is_display_initialized = 0;
m_action = NULL;
m_state = STATE_BUFFER;
m_ext_state = 0;
m_chunk_buffer = m_chunk_start = m_chunk_ptr = NULL;
m_code = 0;
m_pts_current = m_pts_previous = 0;
m_num_pts = m_bytes_since_pts = 0;
m_first = 0;
m_alloc_index = 0;
m_first_decode_slice = m_nb_decode_slices = 0;
memset(&m_new_sequence, 0, sizeof(m_new_sequence));
memset(&m_sequence, 0, sizeof(m_sequence));
memset(&m_gop, 0, sizeof(m_gop));
memset(&m_pictures, 0, sizeof(m_pictures));
m_picture = NULL;
memset(&m_fbuf, 0, sizeof(m_fbuf));
memset(&m_fbuf_alloc, 0, sizeof(m_fbuf_alloc));
m_buf_start = m_buf_end = NULL;
m_display_offset_x = m_display_offset_y = 0;
m_copy_matrix = 0;
memset(&m_intra_quantizer_matrix, 0, sizeof(m_intra_quantizer_matrix));
memset(&m_non_intra_quantizer_matrix, 0, sizeof(m_non_intra_quantizer_matrix));
//
mpeg2_init();
}
CMpeg2Dec::~CMpeg2Dec()
{
mpeg2_close();
}
void CMpeg2Dec::mpeg2_init()
{
m_chunk_buffer = (uint8_t*)_aligned_malloc(BUFFER_SIZE + 4, 16);
m_shift = 0xffffff00;
m_code = 0xb4;
m_action = &CMpeg2Dec::mpeg2_seek_sequence;
m_sequence.width = (unsigned)-1;
}
void CMpeg2Dec::mpeg2_close()
{
/* static uint8_t finalizer[] = {0,0,1,0xb4}; */
/* mpeg2_decode_data (mpeg2dec, finalizer, finalizer+4); */
mpeg2_header_state_init();
_aligned_free(m_chunk_buffer);
}
//
int CMpeg2Dec::skip_chunk(int bytes)
{
if(!bytes)
return 0;
int len = 0;
uint8_t* current = m_buf_start;
uint8_t* limit = current + bytes;
while(current < limit)
{
if(m_shift == 0x00000100)
{
m_shift = 0xffffff00;
len = ++current - m_buf_start;
break;
}
m_shift = (m_shift | *current++) << 8;
}
m_buf_start = current;
return len;
}
int CMpeg2Dec::copy_chunk(int bytes)
{
if(!bytes)
return 0;
int len = 0;
// this assembly gives us a nice speed up
// 36 sec down to 32 sec decoding the ts.stream.tpr test file
// (idtc, mc was set to null)
__asm
{
mov ebx, this
mov esi, [ebx].m_buf_start
mov edi, [ebx].m_chunk_ptr
mov ecx, bytes
mov edx, [ebx].m_shift
copy_chunk_loop:
cmp edx, 0x00000100
jne copy_chunk_continue
mov edx, 0xffffff00
inc edi
mov [ebx].m_chunk_ptr, edi
inc esi
mov eax, esi
sub eax, [ebx].m_buf_start
mov len, eax
jmp copy_chunk_end
copy_chunk_continue:
movzx eax, byte ptr [esi]
or edx, eax
shl edx, 8
mov byte ptr [edi], al
inc esi
inc edi
dec ecx
jnz copy_chunk_loop
copy_chunk_end:
mov [ebx].m_buf_start, esi
mov [ebx].m_shift, edx
}
/*
uint8_t* chunk_ptr = m_chunk_ptr;
uint8_t* current = m_buf_start;
uint8_t* limit = current + bytes;
while(current < limit)
{
if(m_shift == 0x00000100)
{
m_shift = 0xffffff00;
len = ++current - m_buf_start;
m_chunk_ptr = ++chunk_ptr;
break;
}
m_shift = (m_shift | (*chunk_ptr++ = *current++)) << 8;
}
m_buf_start = current;
*/
return len;
}
mpeg2_state_t CMpeg2Dec::seek_chunk()
{
int size = m_buf_end - m_buf_start;
if(int skipped = skip_chunk(size))
{
m_bytes_since_pts += skipped;
m_code = m_buf_start[-1];
return (mpeg2_state_t)-1;
}
m_bytes_since_pts += size;
return STATE_BUFFER;
}
mpeg2_state_t CMpeg2Dec::seek_header()
{
while(m_code != 0xb3 && (m_code != 0xb7 && m_code != 0xb8 && m_code || m_sequence.width == (unsigned)-1))
{
if(seek_chunk() == STATE_BUFFER)
return STATE_BUFFER;
}
m_chunk_start = m_chunk_ptr = m_chunk_buffer;
return m_code
? mpeg2_parse_header()
: mpeg2_header_picture_start();
}
mpeg2_state_t CMpeg2Dec::seek_sequence()
{
mpeg2_header_state_init();
m_action = &CMpeg2Dec::seek_header;
return seek_header();
}
//
void CMpeg2Dec::mpeg2_buffer(uint8_t* start, uint8_t* end)
{
m_buf_start = start;
m_buf_end = end;
}
int CMpeg2Dec::mpeg2_getpos()
{
return m_buf_end - m_buf_start;
}
//
mpeg2_state_t CMpeg2Dec::mpeg2_parse()
{
if(m_action)
{
mpeg2_state_t state = (this->*m_action)();
if((int)state >= 0)
return state;
}
while(1)
{
while((unsigned)(m_code - m_first_decode_slice) < m_nb_decode_slices)
{
int size_buffer = m_buf_end - m_buf_start;
int size_chunk = (m_chunk_buffer + BUFFER_SIZE - m_chunk_ptr);
int copied;
if(size_buffer <= size_chunk)
{
copied = copy_chunk(size_buffer);
if(!copied)
{
m_bytes_since_pts += size_buffer;
m_chunk_ptr += size_buffer;
return STATE_BUFFER;
}
}
else
{
copied = copy_chunk(size_chunk);
if(!copied)
{
/* filled the chunk buffer without finding a start code */
m_bytes_since_pts += size_chunk;
m_action = &CMpeg2Dec::seek_chunk;
return STATE_INVALID;
}
}
m_bytes_since_pts += copied;
m_decoder.mpeg2_slice(m_code, m_chunk_start);
m_code = m_buf_start[-1];
m_chunk_ptr = m_chunk_start;
}
if((unsigned)(m_code - 1) >= 0xb0 - 1)
break;
if(seek_chunk() == STATE_BUFFER)
return STATE_BUFFER;
}
switch(m_code)
{
case 0x00:
m_action = &CMpeg2Dec::mpeg2_header_picture_start;
return m_state;
case 0xb7:
m_action = &CMpeg2Dec::mpeg2_header_end;
break;
case 0xb3:
case 0xb8:
m_action = &CMpeg2Dec::mpeg2_parse_header;
break;
case 0xbe:
m_action = &CMpeg2Dec::seek_chunk;
return STATE_PADDING;
default:
m_action = &CMpeg2Dec::seek_chunk;
return STATE_INVALID;
}
if(m_state != STATE_SLICE)
m_state = STATE_INVALID;
return m_state;
}
void CMpeg2Dec::mpeg2_skip(int skip)
{
m_first_decode_slice = 1;
m_nb_decode_slices = skip ? 0 : (0xb0 - 1);
}
void CMpeg2Dec::mpeg2_slice_region(int start, int end)
{
start = (start < 1) ? 1 : (start > 0xb0) ? 0xb0 : start;
end = (end < start) ? start : (end > 0xb0) ? 0xb0 : end;
m_first_decode_slice = start;
m_nb_decode_slices = end - start;
}
void CMpeg2Dec::mpeg2_pts(uint32_t pts)
{
m_pts_previous = m_pts_current;
m_pts_current = pts;
m_num_pts++;
m_bytes_since_pts = 0;
}
//
/* decode.c */
#define RECEIVED(code,state) (((state) << 8) + (code))
mpeg2_state_t CMpeg2Dec::mpeg2_seek_sequence()
{
mpeg2_header_state_init();
m_action = &CMpeg2Dec::seek_header;
return seek_header();
}
mpeg2_state_t CMpeg2Dec::mpeg2_parse_header()
{
static int (CMpeg2Dec::* process_header[]) () =
{
&CMpeg2Dec::mpeg2_header_picture,
&CMpeg2Dec::mpeg2_header_extension,
&CMpeg2Dec::mpeg2_header_user_data,
&CMpeg2Dec::mpeg2_header_sequence,
NULL, NULL, NULL, NULL,
&CMpeg2Dec::mpeg2_header_gop
};
m_action = &CMpeg2Dec::mpeg2_parse_header;
while(1)
{
int size_buffer = m_buf_end - m_buf_start;
int size_chunk = (m_chunk_buffer + BUFFER_SIZE - m_chunk_ptr);
int copied;
if(size_buffer <= size_chunk)
{
copied = copy_chunk(size_buffer);
if(!copied)
{
m_bytes_since_pts += size_buffer;
m_chunk_ptr += size_buffer;
return STATE_BUFFER;
}
}
else
{
copied = copy_chunk(size_chunk);
if(!copied)
{
/* filled the chunk buffer without finding a start code */
m_bytes_since_pts += size_chunk;
m_code = 0xb4;
m_action = &CMpeg2Dec::seek_header;
return STATE_INVALID;
}
}
m_bytes_since_pts += copied;
if((this->*(process_header[m_code & 0x0b]))())
{
m_code = m_buf_start[-1];
m_action = &CMpeg2Dec::seek_header;
return STATE_INVALID;
}
m_code = m_buf_start[-1];
switch(RECEIVED(m_code, m_state))
{
/* state transition after a sequence header */
case RECEIVED(0x00, STATE_SEQUENCE):
m_action = &CMpeg2Dec::mpeg2_header_picture_start;
case RECEIVED(0xb8, STATE_SEQUENCE):
mpeg2_header_sequence_finalize();
break;
/* other legal state transitions */
case RECEIVED (0x00, STATE_GOP):
m_action = &CMpeg2Dec::mpeg2_header_picture_start;
break;
case RECEIVED (0x01, STATE_PICTURE):
case RECEIVED (0x01, STATE_PICTURE_2ND):
mpeg2_header_matrix_finalize();
m_action = &CMpeg2Dec::mpeg2_header_slice_start;
break;
/* legal headers within a given state */
case RECEIVED (0xb2, STATE_SEQUENCE):
case RECEIVED (0xb2, STATE_GOP):
case RECEIVED (0xb2, STATE_PICTURE):
case RECEIVED (0xb2, STATE_PICTURE_2ND):
case RECEIVED (0xb5, STATE_SEQUENCE):
case RECEIVED (0xb5, STATE_PICTURE):
case RECEIVED (0xb5, STATE_PICTURE_2ND):
m_chunk_ptr = m_chunk_start;
continue;
default:
m_action = &CMpeg2Dec::seek_header;
return STATE_INVALID;
}
m_chunk_start = m_chunk_ptr = m_chunk_buffer;
return m_state;
}
}
/* header.c */
void CMpeg2Dec::mpeg2_header_state_init()
{
if(m_sequence.width != (unsigned)-1)
{
m_sequence.width = (unsigned)-1;
for(int i = 0; i < m_alloc_index; i++)
_aligned_free(m_fbuf_alloc[i].buf[0]);
}
m_decoder.m_scan = mpeg2_scan_norm_2;
m_picture = m_pictures;
m_fbuf[0] = &m_fbuf_alloc[0];
m_fbuf[1] = &m_fbuf_alloc[1];
m_fbuf[2] = &m_fbuf_alloc[2];
m_first = true;
m_alloc_index = 0;
m_first_decode_slice = 1;
m_nb_decode_slices = 0xb0 - 1;
}
int CMpeg2Dec::mpeg2_header_sequence()
{
uint8_t* buffer = m_chunk_start;
mpeg2_sequence_t* sequence = &m_new_sequence;
static unsigned int frame_period[9] = {0, 1126125, 1125000, 1080000, 900900, 900000, 540000, 450450, 450000};
if((buffer[6] & 0x20) != 0x20) /* missing marker_bit */
return 1;
int i = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
if(!(sequence->display_width = sequence->picture_width = i >> 12))
return 1;
if(!(sequence->display_height = sequence->picture_height = i & 0xfff))
return 1;
sequence->width = (sequence->picture_width + 15) & ~15;
sequence->height = (sequence->picture_height + 15) & ~15;
sequence->chroma_width = sequence->width >> 1;
sequence->chroma_height = sequence->height >> 1;
sequence->flags = (SEQ_FLAG_PROGRESSIVE_SEQUENCE | SEQ_VIDEO_FORMAT_UNSPECIFIED);
sequence->pixel_width = buffer[3] >> 4; /* aspect ratio */
sequence->frame_period = 0;
if((buffer[3] & 15) < 9) sequence->frame_period = frame_period[buffer[3] & 15];
sequence->byte_rate = (buffer[4]<<10) | (buffer[5]<<2) | (buffer[6]>>6);
sequence->vbv_buffer_size = ((buffer[6]<<16)|(buffer[7]<<8))&0x1ff800;
if(buffer[7] & 4) sequence->flags |= SEQ_FLAG_CONSTRAINED_PARAMETERS;
m_copy_matrix = 3;
if(buffer[7] & 2)
{
for(i = 0; i < 64; i++)
m_intra_quantizer_matrix[mpeg2_scan_norm_2[i]] = (buffer[i+7] << 7) | (buffer[i+8] >> 1);
buffer += 64;
}
else
{
for (i = 0; i < 64; i++)
m_intra_quantizer_matrix[mpeg2_scan_norm_2[i]] = default_intra_quantizer_matrix[i];
}
if(buffer[7] & 1)
{
for(i = 0; i < 64; i++)
m_non_intra_quantizer_matrix[mpeg2_scan_norm_2[i]] = buffer[i+8];
}
else
{
for(i = 0; i < 64; i++)
m_non_intra_quantizer_matrix[i] = 16;
}
sequence->profile_level_id = 0x80;
sequence->colour_primaries = 0;
sequence->transfer_characteristics = 0;
sequence->matrix_coefficients = 0;
m_ext_state = SEQ_EXT;
m_state = STATE_SEQUENCE;
m_display_offset_x = m_display_offset_y = 0;
m_info.Reset();
m_info.m_gop = NULL;
return 0;
}
int CMpeg2Dec::mpeg2_header_gop()
{
uint8_t* buffer = m_chunk_start;
m_info.Reset();
if(!(buffer[1] & 8))
return 1;
m_info.m_gop = &m_gop;
m_gop.hours = (buffer[0] >> 2) & 31;
m_gop.minutes = ((buffer[0] << 4) | (buffer[1] >> 4)) & 63;
m_gop.seconds = ((buffer[1] << 3) | (buffer[2] >> 5)) & 63;
m_gop.pictures = ((buffer[2] << 1) | (buffer[3] >> 7)) & 63;
m_gop.flags = (buffer[0] >> 7) | ((buffer[3] >> 4) & 6);
m_state = STATE_GOP;
return 0;
}
mpeg2_state_t CMpeg2Dec::mpeg2_header_picture_start()
{
{
mpeg2_picture_t* picture;
if(m_state != STATE_SLICE_1ST)
{
m_state = STATE_PICTURE;
picture = m_pictures;
if((m_decoder.m_coding_type != PIC_FLAG_CODING_TYPE_B) ^ (m_picture >= m_pictures + 2))
picture += 2;
}
else
{
m_state = STATE_PICTURE_2ND;
picture = m_picture + 1; /* second field picture */
}
m_picture = picture;
}
m_picture->flags = 0;
if(m_num_pts)
{
if(m_bytes_since_pts >= 4)
{
m_num_pts = 0;
m_picture->pts = m_pts_current;
m_picture->flags = PIC_FLAG_PTS;
}
else if(m_num_pts > 1)
{
m_num_pts = 1;
m_picture->pts = m_pts_previous;
m_picture->flags = PIC_FLAG_PTS;
}
}
m_picture->display_offset[0].x =
m_picture->display_offset[1].x =
m_picture->display_offset[2].x = m_display_offset_x;
m_picture->display_offset[0].y =
m_picture->display_offset[1].y =
m_picture->display_offset[2].y = m_display_offset_y;
return mpeg2_parse_header();
}
int CMpeg2Dec::mpeg2_header_picture()
{
uint8_t* buffer = m_chunk_start;
mpeg2_picture_t* picture = m_picture;
int type;
int low_delay;
type = (buffer [1] >> 3) & 7;
low_delay = m_sequence.flags & SEQ_FLAG_LOW_DELAY;
if(m_state == STATE_PICTURE)
{
mpeg2_picture_t* other;
m_decoder.m_second_field = 0;
other = m_pictures;
if(other == picture)
other += 2;
if(m_decoder.m_coding_type != PIC_FLAG_CODING_TYPE_B)
{
m_fbuf[2] = m_fbuf[1];
m_fbuf[1] = m_fbuf[0];
}
m_fbuf[0] = NULL;
m_info.Reset();
m_info.m_current_picture = picture;
m_info.m_display_picture = picture;
if(type != PIC_FLAG_CODING_TYPE_B)
{
if(!low_delay)
{
if(m_first) {
m_info.m_display_picture = NULL;
m_first = false;
}
else
{
m_info.m_display_picture = other;
if(other->nb_fields == 1)
m_info.m_display_picture_2nd = other + 1;
m_info.m_display_fbuf = m_fbuf[1];
}
}
if(!low_delay + !NULL/*m_convert_start*/)
m_info.m_discard_fbuf = m_fbuf[!low_delay + !NULL/*m_convert_start*/];
}
while(m_alloc_index < 3)
{
mpeg2_fbuf_t* fbuf = &m_fbuf_alloc[m_alloc_index++];
fbuf->id = NULL;
int size = m_decoder.m_width * m_decoder.m_height;
fbuf->buf[0] = (uint8_t*)_aligned_malloc(6 * size >> 2, 16);
fbuf->buf[1] = fbuf->buf[0] + size;
fbuf->buf[2] = fbuf->buf[1] + (size >> 2);
memset(fbuf->buf[0], 0x10, size);
memset(fbuf->buf[1], 0x80, size >> 2);
memset(fbuf->buf[2], 0x80, size >> 2);
}
mpeg2_set_fbuf(type);
}
else
{
m_decoder.m_second_field = 1;
m_info.m_current_picture_2nd = picture;
m_info.m_user_data = NULL; m_info.m_user_data_len = 0;
if(low_delay || type == PIC_FLAG_CODING_TYPE_B)
m_info.m_display_picture_2nd = picture;
}
m_ext_state = PIC_CODING_EXT;
picture->temporal_reference = (buffer[0] << 2) | (buffer[1] >> 6);
m_decoder.m_coding_type = type;
picture->flags |= type;
if(type == PIC_FLAG_CODING_TYPE_P || type == PIC_FLAG_CODING_TYPE_B)
{
/* forward_f_code and backward_f_code - used in mpeg1 only */
m_decoder.m_f_motion.f_code[1] = (buffer[3] >> 2) & 1;
m_decoder.m_f_motion.f_code[0] = (((buffer[3] << 1) | (buffer[4] >> 7)) & 7) - 1;
m_decoder.m_b_motion.f_code[1] = (buffer[4] >> 6) & 1;
m_decoder.m_b_motion.f_code[0] = ((buffer[4] >> 3) & 7) - 1;
}
/* XXXXXX decode extra_information_picture as well */
picture->nb_fields = 2;
m_decoder.m_intra_dc_precision = 0;
m_decoder.m_frame_pred_frame_dct = 1;
m_decoder.m_q_scale_type = 0;
m_decoder.m_concealment_motion_vectors = 0;
m_decoder.m_scan = mpeg2_scan_norm_2;
m_decoder.m_picture_structure = FRAME_PICTURE;
m_copy_matrix = 0;
return 0;
}
int CMpeg2Dec::mpeg2_header_extension()
{
static int (CMpeg2Dec::* parser[]) () =
{
NULL,
&CMpeg2Dec::sequence_ext,
&CMpeg2Dec::sequence_display_ext,
&CMpeg2Dec::quant_matrix_ext,
&CMpeg2Dec::copyright_ext,
NULL, NULL,
&CMpeg2Dec::picture_display_ext,
&CMpeg2Dec::picture_coding_ext
};
int ext, ext_bit;
ext = m_chunk_start[0] >> 4;
ext_bit = 1 << ext;
if(!(m_ext_state & ext_bit)) /* ignore illegal extensions */
return 0;
m_ext_state &= ~ext_bit;
return (this->*parser[ext])();
}
int CMpeg2Dec::mpeg2_header_user_data()
{
if(!m_info.m_user_data_len) m_info.m_user_data = m_chunk_start;
else m_info.m_user_data_len += 3;
m_info.m_user_data_len += (m_chunk_ptr - 4 - m_chunk_start);
m_chunk_start = m_chunk_ptr - 1;
return 0;
}
void CMpeg2Dec::mpeg2_header_matrix_finalize()
{
if(m_copy_matrix & 1)
memcpy(m_decoder.m_intra_quantizer_matrix, m_intra_quantizer_matrix, 64);
if(m_copy_matrix & 2)
memcpy(m_decoder.m_non_intra_quantizer_matrix, m_non_intra_quantizer_matrix, 64);
}
void mpeg2_sequence_t::finalize()
{
int w, h;
byte_rate *= 50;
if(flags & SEQ_FLAG_MPEG2)
{
switch(pixel_width)
{
case 1: /* square pixels */
pixel_width = pixel_height = 1; return;
case 2: /* 4:3 aspect ratio */
w = 4; h = 3; break;
case 3: /* 16:9 aspect ratio */
w = 16; h = 9; break;
case 4: /* 2.21:1 aspect ratio */
w = 221; h = 100; break;
default: /* illegal */
pixel_width = pixel_height = 0; return;
}
w *= display_height;
h *= display_width;
}
else
{
if(byte_rate == 50 * 0x3ffff)
byte_rate = 0; /* mpeg-1 VBR */
switch(pixel_width)
{
case 0: case 15: /* illegal */
pixel_width = pixel_height = 0; return;
case 1: /* square pixels */
pixel_width = pixel_height = 1; return;
case 3: /* 720x576 16:9 */
pixel_width = 64; pixel_height = 45; return;
case 6: /* 720x480 16:9 */
pixel_width = 32; pixel_height = 27; return;
case 12: /* 720*480 4:3 */
pixel_width = 8; pixel_height = 9; return;
default:
h = 88 * pixel_width + 1171;
w = 2000;
}
}
pixel_width = w;
pixel_height = h;
/* find greatest common divisor */
while(w) {int tmp = w; w = h % tmp; h = tmp;}
pixel_width /= h;
pixel_height /= h;
}
void CMpeg2Dec::mpeg2_header_sequence_finalize()
{
mpeg2_sequence_t* sequence = &m_new_sequence;
sequence->finalize();
mpeg2_header_matrix_finalize();
m_decoder.m_mpeg1 = !(sequence->flags & SEQ_FLAG_MPEG2);
m_decoder.m_width = sequence->width;
m_decoder.m_height = sequence->height;
m_decoder.m_vertical_position_extension = (sequence->picture_height > 2800);
/*
* according to 6.1.1.6, repeat sequence headers should be
* identical to the original. However some DVDs dont respect that
* and have different bitrates in the repeat sequence headers. So
* we'll ignore that in the comparison and still consider these as
* repeat sequence headers.
*/
// EDIT: some dvds will work if we allow the last three fields to vary (which aren't needed anyway)
m_sequence.byte_rate = sequence->byte_rate;
if(!memcmp(&m_sequence, sequence, FIELD_OFFSET(mpeg2_sequence_t, colour_primaries) /*sizeof(mpeg2_sequence_t)*/))
{
m_state = STATE_SEQUENCE_REPEATED;
}
else if(m_sequence.width != (unsigned)-1)
{
m_action = &CMpeg2Dec::mpeg2_seek_sequence;
m_state = STATE_INVALID; /* XXXX STATE_INVALID_END ? */
return;
}
m_sequence = *sequence;
m_info.m_sequence = &m_sequence;
}
mpeg2_state_t CMpeg2Dec::mpeg2_header_slice_start()
{
m_info.m_user_data = NULL;
m_info.m_user_data_len = 0;
m_state = (m_picture->nb_fields > 1 || m_state == STATE_PICTURE_2ND) ? STATE_SLICE : STATE_SLICE_1ST;
if(!m_nb_decode_slices)
{
m_picture->flags |= PIC_FLAG_SKIP;
}
else
{
int b_type = m_decoder.m_coding_type == B_TYPE;
m_decoder.mpeg2_init_fbuf(m_fbuf[0]->buf, m_fbuf[b_type + 1]->buf, m_fbuf[b_type]->buf);
}
m_action = NULL;
return (mpeg2_state_t)-1;
}
mpeg2_state_t CMpeg2Dec::mpeg2_header_end()
{
mpeg2_picture_t* picture = m_pictures;
int b_type = m_decoder.m_coding_type == B_TYPE;
if((m_picture >= picture + 2) ^ b_type)
picture = m_pictures + 2;
m_state = STATE_END;
m_info.Reset();
if(!(m_sequence.flags & SEQ_FLAG_LOW_DELAY))
{
m_info.m_display_picture = picture;
if(picture->nb_fields == 1)
m_info.m_display_picture_2nd = picture + 1;
m_info.m_display_fbuf = m_fbuf[b_type];
m_info.m_discard_fbuf = m_fbuf[b_type + 1];
}
else
{
m_info.m_discard_fbuf = m_fbuf[b_type];
}
m_action = &CMpeg2Dec::mpeg2_seek_sequence;
m_first = true;
return STATE_END;
}
void CMpeg2Dec::mpeg2_set_fbuf(int coding_type)
{
for(int i = 0; i < 3; i++)
{
if(m_fbuf[1] != &m_fbuf_alloc[i] && m_fbuf[2] != &m_fbuf_alloc[i])
{
m_fbuf[0] = &m_fbuf_alloc[i];
m_info.m_current_fbuf = m_fbuf[0];
if(coding_type == B_TYPE || (m_sequence.flags & SEQ_FLAG_LOW_DELAY))
{
if(coding_type == B_TYPE)
m_info.m_discard_fbuf = m_fbuf[0];
m_info.m_display_fbuf = m_fbuf[0];
}
break;
}
}
}
//
int CMpeg2Dec::sequence_ext()
{
uint8_t* buffer = m_chunk_start;
mpeg2_sequence_t* sequence = &m_new_sequence;
if(!(buffer[3]&1))
return 1;
sequence->profile_level_id = (buffer[0] << 4) | (buffer[1] >> 4);
sequence->display_width =
sequence->picture_width += ((buffer[1] << 13) | (buffer[2] << 5)) & 0x3000;
sequence->display_height =
sequence->picture_height += (buffer[2] << 7) & 0x3000;
sequence->width = (sequence->picture_width + 15) & ~15;
sequence->height = (sequence->picture_height + 15) & ~15;
sequence->flags |= SEQ_FLAG_MPEG2;
if(!(buffer[1] & 8))
{
sequence->flags &= ~SEQ_FLAG_PROGRESSIVE_SEQUENCE;
sequence->height = (sequence->height + 31) & ~31;
}
if(buffer[5] & 0x80)
{
sequence->flags |= SEQ_FLAG_LOW_DELAY;
}
sequence->chroma_width = sequence->width;
sequence->chroma_height = sequence->height;
switch(buffer[1] & 6)
{
case 0: /* invalid */
return 1;
case 2: /* 4:2:0 */
sequence->chroma_height >>= 1;
case 4: /* 4:2:2 */
sequence->chroma_width >>= 1;
}
sequence->byte_rate += ((buffer[2]<<25) | (buffer[3]<<17)) & 0x3ffc0000;
sequence->vbv_buffer_size |= buffer[4] << 21;
sequence->frame_period =
sequence->frame_period * ((buffer[5]&31)+1) / (((buffer[5]>>2)&3)+1);
m_ext_state = SEQ_DISPLAY_EXT;
return 0;
}
int CMpeg2Dec::sequence_display_ext()
{
uint8_t* buffer = m_chunk_start;
mpeg2_sequence_t* sequence = &m_new_sequence;
uint32_t flags = (sequence->flags & ~SEQ_MASK_VIDEO_FORMAT) | ((buffer[0]<<4) & SEQ_MASK_VIDEO_FORMAT);
if(buffer[0] & 1)
{
flags |= SEQ_FLAG_COLOUR_DESCRIPTION;
sequence->colour_primaries = buffer[1];
sequence->transfer_characteristics = buffer[2];
sequence->matrix_coefficients = buffer[3];
buffer += 3;
}
if(!(buffer[2] & 2)) /* missing marker_bit */
return 1;
// ???
// sequence->flags = flags;
sequence->display_width = (buffer[1] << 6) | (buffer[2] >> 2);
sequence->display_height = ((buffer[2]& 1 ) << 13) | (buffer[3] << 5) | (buffer[4] >> 3);
return 0;
}
int CMpeg2Dec::quant_matrix_ext()
{
uint8_t* buffer = m_chunk_start;
if(buffer[0] & 8)
{
for(int i = 0; i < 64; i++)
m_intra_quantizer_matrix[mpeg2_scan_norm_2[i]] = (buffer[i] << 5) | (buffer[i+1] >> 3);
m_copy_matrix |= 1;
buffer += 64;
}
if(buffer[0] & 4)
{
for(int i = 0; i < 64; i++)
m_non_intra_quantizer_matrix[mpeg2_scan_norm_2[i]] = (buffer[i] << 6) | (buffer[i+1] >> 2);
m_copy_matrix |= 2;
}
return 0;
}
int CMpeg2Dec::copyright_ext()
{
return 0;
}
int CMpeg2Dec::picture_display_ext()
{
uint8_t* buffer = m_chunk_start;
mpeg2_picture_t* picture = m_picture;
int nb_pos = picture->nb_fields;
if(m_sequence.flags & SEQ_FLAG_PROGRESSIVE_SEQUENCE)
nb_pos >>= 1;
int i = 0;
for(; i < nb_pos; i++)
{
int x = ((buffer[4*i] << 24) | (buffer[4*i+1] << 16) |
(buffer[4*i+2] << 8) | buffer[4*i+3]) >> (11-2*i);
int y = ((buffer[4*i+2] << 24) | (buffer[4*i+3] << 16) |
(buffer[4*i+4] << 8) | buffer[4*i+5]) >> (10-2*i);
if(!(x&y&1))
return 1;
picture->display_offset[i].x = m_display_offset_x = x >> 1;
picture->display_offset[i].y = m_display_offset_y = y >> 1;
}
for(; i < 3; i++)
{
picture->display_offset[i].x = m_display_offset_x;
picture->display_offset[i].y = m_display_offset_y;
}
return 0;
}
int CMpeg2Dec::picture_coding_ext()
{
uint8_t* buffer = m_chunk_start;
mpeg2_picture_t* picture = m_picture;
/* pre subtract 1 for use later in compute_motion_vector */
m_decoder.m_f_motion.f_code[0] = (buffer[0] & 15) - 1;
m_decoder.m_f_motion.f_code[1] = (buffer[1] >> 4) - 1;
m_decoder.m_b_motion.f_code[0] = (buffer[1] & 15) - 1;
m_decoder.m_b_motion.f_code[1] = (buffer[2] >> 4) - 1;
m_decoder.m_intra_dc_precision = (buffer[2] >> 2) & 3;
m_decoder.m_picture_structure = buffer[2] & 3;
switch(m_decoder.m_picture_structure)
{
case TOP_FIELD:
picture->flags |= PIC_FLAG_TOP_FIELD_FIRST;
case BOTTOM_FIELD:
picture->nb_fields = 1;
break;
case FRAME_PICTURE:
if(!(m_sequence.flags & SEQ_FLAG_PROGRESSIVE_SEQUENCE))
{
picture->nb_fields = (buffer[3] & 2) ? 3 : 2;
picture->flags |= (buffer[3] & 128) ? PIC_FLAG_TOP_FIELD_FIRST : 0;
}
else
{
picture->nb_fields = (buffer[3]&2) ? ((buffer[3]&128) ? 6 : 4) : 2;
}
break;
default:
return 1;
}
m_decoder.m_top_field_first = buffer[3] >> 7;
m_decoder.m_frame_pred_frame_dct = (buffer[3] >> 6) & 1;
m_decoder.m_concealment_motion_vectors = (buffer[3] >> 5) & 1;
m_decoder.m_q_scale_type = (buffer[3] >> 4) & 1;
m_decoder.m_intra_vlc_format = (buffer[3] >> 3) & 1;
m_decoder.m_scan = (buffer[3] & 4) ? mpeg2_scan_alt_2 : mpeg2_scan_norm_2;
if(buffer[3] & 2)
picture->flags |= PIC_FLAG_REPEAT_FIRST_FIELD;
picture->flags |= (buffer[4] & 0x80) ? PIC_FLAG_PROGRESSIVE_FRAME : 0;
if(buffer[4] & 0x40)
picture->flags |= (((buffer[4]<<26) | (buffer[5]<<18) | (buffer[6]<<10)) & PIC_MASK_COMPOSITE_DISPLAY) | PIC_FLAG_COMPOSITE_DISPLAY;
m_ext_state = PIC_DISPLAY_EXT | COPYRIGHT_EXT | QUANT_MATRIX_EXT;
return 0;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
// vlc
#define GETWORD(bit_buf,shift,bit_ptr) \
do { \
bit_buf |= ((bit_ptr[0] << 8) | bit_ptr[1]) << (shift); \
bit_ptr += 2; \
} while (0)
/*
void bitstream_init(const uint8_t * start)
{
m_bitstream_buf =
(start[0] << 24) | (start[1] << 16) | (start[2] << 8) | start[3];
m_bitstream_ptr = start + 4;
m_bitstream_bits = -16;
}
*/
/* make sure that there are at least 16 valid bits in bit_buf */
#define NEEDBITS \
do { \
if (bits > 0) { \
GETWORD (bit_buf, bits, bit_ptr); \
bits -= 16; \
} \
} while (0)
/* remove num valid bits from bit_buf */
#define DUMPBITS(num) \
do { \
bit_buf <<= (num); \
bits += (num); \
} while (0)
/* take num bits from the high part of bit_buf and zero extend them */
#define UBITS(bit_buf,num) (((uint32_t)(bit_buf)) >> (32 - (num)))
/* take num bits from the high part of bit_buf and sign extend them */
#define SBITS(bit_buf,num) (((int32_t)(bit_buf)) >> (32 - (num)))
typedef struct {
uint8_t modes;
uint8_t len;
} MBtab;
typedef struct {
uint8_t delta;
uint8_t len;
} MVtab;
typedef struct {
int8_t dmv;
uint8_t len;
} DMVtab;
typedef struct {
uint8_t cbp;
uint8_t len;
} CBPtab;
typedef struct {
uint8_t size;
uint8_t len;
} DCtab;
typedef struct {
uint8_t run;
uint8_t level;
uint8_t len;
} DCTtab;
typedef struct {
uint8_t mba;
uint8_t len;
} MBAtab;
#define INTRA MACROBLOCK_INTRA
#define QUANT MACROBLOCK_QUANT
static const MBtab MB_I [] = {
{INTRA|QUANT, 2}, {INTRA, 1}
};
#define MC MACROBLOCK_MOTION_FORWARD
#define CODED MACROBLOCK_PATTERN
static const MBtab MB_P [] = {
{INTRA|QUANT, 6}, {CODED|QUANT, 5}, {MC|CODED|QUANT, 5}, {INTRA, 5},
{MC, 3}, {MC, 3}, {MC, 3}, {MC, 3},
{CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2},
{CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2},
{MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1},
{MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1},
{MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1},
{MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}
};
#define FWD MACROBLOCK_MOTION_FORWARD
#define BWD MACROBLOCK_MOTION_BACKWARD
#define INTER MACROBLOCK_MOTION_FORWARD|MACROBLOCK_MOTION_BACKWARD
static const MBtab MB_B [] = {
{0, 0}, {INTRA|QUANT, 6},
{BWD|CODED|QUANT, 6}, {FWD|CODED|QUANT, 6},
{INTER|CODED|QUANT, 5}, {INTER|CODED|QUANT, 5},
{INTRA, 5}, {INTRA, 5},
{FWD, 4}, {FWD, 4}, {FWD, 4}, {FWD, 4},
{FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4},
{BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3},
{BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3},
{BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3},
{BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3},
{INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2},
{INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2},
{INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2},
{INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2},
{INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2},
{INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2},
{INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2},
{INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}
};
#undef INTRA
#undef QUANT
#undef MC
#undef CODED
#undef FWD
#undef BWD
#undef INTER
static const MVtab MV_4 [] = {
{ 3, 6}, { 2, 4}, { 1, 3}, { 1, 3}, { 0, 2}, { 0, 2}, { 0, 2}, { 0, 2}
};
static const MVtab MV_10 [] = {
{ 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10},
{ 0,10}, { 0,10}, { 0,10}, { 0,10}, {15,10}, {14,10}, {13,10}, {12,10},
{11,10}, {10,10}, { 9, 9}, { 9, 9}, { 8, 9}, { 8, 9}, { 7, 9}, { 7, 9},
{ 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7},
{ 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7},
{ 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}
};
static const DMVtab DMV_2 [] = {
{ 0, 1}, { 0, 1}, { 1, 2}, {-1, 2}
};
static const CBPtab CBP_7 [] = {
{0x22, 7}, {0x12, 7}, {0x0a, 7}, {0x06, 7},
{0x21, 7}, {0x11, 7}, {0x09, 7}, {0x05, 7},
{0x3f, 6}, {0x3f, 6}, {0x03, 6}, {0x03, 6},
{0x24, 6}, {0x24, 6}, {0x18, 6}, {0x18, 6},
{0x3e, 5}, {0x3e, 5}, {0x3e, 5}, {0x3e, 5},
{0x02, 5}, {0x02, 5}, {0x02, 5}, {0x02, 5},
{0x3d, 5}, {0x3d, 5}, {0x3d, 5}, {0x3d, 5},
{0x01, 5}, {0x01, 5}, {0x01, 5}, {0x01, 5},
{0x38, 5}, {0x38, 5}, {0x38, 5}, {0x38, 5},
{0x34, 5}, {0x34, 5}, {0x34, 5}, {0x34, 5},
{0x2c, 5}, {0x2c, 5}, {0x2c, 5}, {0x2c, 5},
{0x1c, 5}, {0x1c, 5}, {0x1c, 5}, {0x1c, 5},
{0x28, 5}, {0x28, 5}, {0x28, 5}, {0x28, 5},
{0x14, 5}, {0x14, 5}, {0x14, 5}, {0x14, 5},
{0x30, 5}, {0x30, 5}, {0x30, 5}, {0x30, 5},
{0x0c, 5}, {0x0c, 5}, {0x0c, 5}, {0x0c, 5},
{0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4},
{0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4},
{0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4},
{0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4},
{0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4},
{0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4},
{0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4},
{0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4},
{0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3},
{0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3},
{0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3},
{0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}
};
static const CBPtab CBP_9 [] = {
{0, 0}, {0x00, 9}, {0x27, 9}, {0x1b, 9},
{0x3b, 9}, {0x37, 9}, {0x2f, 9}, {0x1f, 9},
{0x3a, 8}, {0x3a, 8}, {0x36, 8}, {0x36, 8},
{0x2e, 8}, {0x2e, 8}, {0x1e, 8}, {0x1e, 8},
{0x39, 8}, {0x39, 8}, {0x35, 8}, {0x35, 8},
{0x2d, 8}, {0x2d, 8}, {0x1d, 8}, {0x1d, 8},
{0x26, 8}, {0x26, 8}, {0x1a, 8}, {0x1a, 8},
{0x25, 8}, {0x25, 8}, {0x19, 8}, {0x19, 8},
{0x2b, 8}, {0x2b, 8}, {0x17, 8}, {0x17, 8},
{0x33, 8}, {0x33, 8}, {0x0f, 8}, {0x0f, 8},
{0x2a, 8}, {0x2a, 8}, {0x16, 8}, {0x16, 8},
{0x32, 8}, {0x32, 8}, {0x0e, 8}, {0x0e, 8},
{0x29, 8}, {0x29, 8}, {0x15, 8}, {0x15, 8},
{0x31, 8}, {0x31, 8}, {0x0d, 8}, {0x0d, 8},
{0x23, 8}, {0x23, 8}, {0x13, 8}, {0x13, 8},
{0x0b, 8}, {0x0b, 8}, {0x07, 8}, {0x07, 8}
};
static const DCtab DC_lum_5 [] = {
{1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2},
{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2},
{0, 3}, {0, 3}, {0, 3}, {0, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3},
{4, 3}, {4, 3}, {4, 3}, {4, 3}, {5, 4}, {5, 4}, {6, 5}
};
static const DCtab DC_chrom_5 [] = {
{0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2},
{1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2},
{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2},
{3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 4}, {4, 4}, {5, 5}
};
static const DCtab DC_long [] = {
{6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5},
{6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5},
{7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, { 7, 6}, { 7, 6},
{8, 7}, {8, 7}, {8, 7}, {8, 7}, {9, 8}, {9, 8}, {10, 9}, {11, 9}
};
static const DCTtab DCT_16 [] = {
{129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
{129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
{129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
{129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
{ 2,18, 0}, { 2,17, 0}, { 2,16, 0}, { 2,15, 0},
{ 7, 3, 0}, { 17, 2, 0}, { 16, 2, 0}, { 15, 2, 0},
{ 14, 2, 0}, { 13, 2, 0}, { 12, 2, 0}, { 32, 1, 0},
{ 31, 1, 0}, { 30, 1, 0}, { 29, 1, 0}, { 28, 1, 0}
};
static const DCTtab DCT_15 [] = {
{ 1,40,15}, { 1,39,15}, { 1,38,15}, { 1,37,15},
{ 1,36,15}, { 1,35,15}, { 1,34,15}, { 1,33,15},
{ 1,32,15}, { 2,14,15}, { 2,13,15}, { 2,12,15},
{ 2,11,15}, { 2,10,15}, { 2, 9,15}, { 2, 8,15},
{ 1,31,14}, { 1,31,14}, { 1,30,14}, { 1,30,14},
{ 1,29,14}, { 1,29,14}, { 1,28,14}, { 1,28,14},
{ 1,27,14}, { 1,27,14}, { 1,26,14}, { 1,26,14},
{ 1,25,14}, { 1,25,14}, { 1,24,14}, { 1,24,14},
{ 1,23,14}, { 1,23,14}, { 1,22,14}, { 1,22,14},
{ 1,21,14}, { 1,21,14}, { 1,20,14}, { 1,20,14},
{ 1,19,14}, { 1,19,14}, { 1,18,14}, { 1,18,14},
{ 1,17,14}, { 1,17,14}, { 1,16,14}, { 1,16,14}
};
static const DCTtab DCT_13 [] = {
{ 11, 2,13}, { 10, 2,13}, { 6, 3,13}, { 4, 4,13},
{ 3, 5,13}, { 2, 7,13}, { 2, 6,13}, { 1,15,13},
{ 1,14,13}, { 1,13,13}, { 1,12,13}, { 27, 1,13},
{ 26, 1,13}, { 25, 1,13}, { 24, 1,13}, { 23, 1,13},
{ 1,11,12}, { 1,11,12}, { 9, 2,12}, { 9, 2,12},
{ 5, 3,12}, { 5, 3,12}, { 1,10,12}, { 1,10,12},
{ 3, 4,12}, { 3, 4,12}, { 8, 2,12}, { 8, 2,12},
{ 22, 1,12}, { 22, 1,12}, { 21, 1,12}, { 21, 1,12},
{ 1, 9,12}, { 1, 9,12}, { 20, 1,12}, { 20, 1,12},
{ 19, 1,12}, { 19, 1,12}, { 2, 5,12}, { 2, 5,12},
{ 4, 3,12}, { 4, 3,12}, { 1, 8,12}, { 1, 8,12},
{ 7, 2,12}, { 7, 2,12}, { 18, 1,12}, { 18, 1,12}
};
static const DCTtab DCT_B14_10 [] = {
{ 17, 1,10}, { 6, 2,10}, { 1, 7,10}, { 3, 3,10},
{ 2, 4,10}, { 16, 1,10}, { 15, 1,10}, { 5, 2,10}
};
static const DCTtab DCT_B14_8 [] = {
{ 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6},
{ 3, 2, 7}, { 3, 2, 7}, { 10, 1, 7}, { 10, 1, 7},
{ 1, 4, 7}, { 1, 4, 7}, { 9, 1, 7}, { 9, 1, 7},
{ 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6},
{ 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6},
{ 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6},
{ 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6},
{ 14, 1, 8}, { 1, 6, 8}, { 13, 1, 8}, { 12, 1, 8},
{ 4, 2, 8}, { 2, 3, 8}, { 1, 5, 8}, { 11, 1, 8}
};
static const DCTtab DCT_B14AC_5 [] = {
{ 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5},
{ 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4},
{ 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
{129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2},
{129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2},
{ 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
{ 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}
};
static const DCTtab DCT_B14DC_5 [] = {
{ 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5},
{ 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4},
{ 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
{ 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1},
{ 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1},
{ 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1},
{ 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}
};
static const DCTtab DCT_B15_10 [] = {
{ 6, 2, 9}, { 6, 2, 9}, { 15, 1, 9}, { 15, 1, 9},
{ 3, 4,10}, { 17, 1,10}, { 16, 1, 9}, { 16, 1, 9}
};
static const DCTtab DCT_B15_8 [] = {
{ 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6},
{ 8, 1, 7}, { 8, 1, 7}, { 9, 1, 7}, { 9, 1, 7},
{ 7, 1, 7}, { 7, 1, 7}, { 3, 2, 7}, { 3, 2, 7},
{ 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6},
{ 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6},
{ 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6},
{ 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6},
{ 2, 5, 8}, { 12, 1, 8}, { 1,11, 8}, { 1,10, 8},
{ 14, 1, 8}, { 13, 1, 8}, { 4, 2, 8}, { 2, 4, 8},
{ 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5},
{ 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5},
{ 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5},
{ 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5},
{ 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5},
{ 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5},
{ 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
{ 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
{ 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
{ 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
{ 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
{ 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
{ 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
{ 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
{129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
{129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
{129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
{129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
{ 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4},
{ 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4},
{ 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4},
{ 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4},
{ 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
{ 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
{ 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
{ 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
{ 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
{ 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
{ 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
{ 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
{ 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
{ 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
{ 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
{ 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
{ 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
{ 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
{ 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
{ 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
{ 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
{ 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
{ 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
{ 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
{ 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
{ 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
{ 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
{ 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
{ 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5},
{ 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5},
{ 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5},
{ 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5},
{ 10, 1, 7}, { 10, 1, 7}, { 2, 3, 7}, { 2, 3, 7},
{ 11, 1, 7}, { 11, 1, 7}, { 1, 8, 7}, { 1, 8, 7},
{ 1, 9, 7}, { 1, 9, 7}, { 1,12, 8}, { 1,13, 8},
{ 3, 3, 8}, { 5, 2, 8}, { 1,14, 8}, { 1,15, 8}
};
static const MBAtab MBA_5 [] = {
{6, 5}, {5, 5}, {4, 4}, {4, 4}, {3, 4}, {3, 4},
{2, 3}, {2, 3}, {2, 3}, {2, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3},
{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1},
{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}
};
static const MBAtab MBA_11 [] = {
{32, 11}, {31, 11}, {30, 11}, {29, 11},
{28, 11}, {27, 11}, {26, 11}, {25, 11},
{24, 11}, {23, 11}, {22, 11}, {21, 11},
{20, 10}, {20, 10}, {19, 10}, {19, 10},
{18, 10}, {18, 10}, {17, 10}, {17, 10},
{16, 10}, {16, 10}, {15, 10}, {15, 10},
{14, 8}, {14, 8}, {14, 8}, {14, 8},
{14, 8}, {14, 8}, {14, 8}, {14, 8},
{13, 8}, {13, 8}, {13, 8}, {13, 8},
{13, 8}, {13, 8}, {13, 8}, {13, 8},
{12, 8}, {12, 8}, {12, 8}, {12, 8},
{12, 8}, {12, 8}, {12, 8}, {12, 8},
{11, 8}, {11, 8}, {11, 8}, {11, 8},
{11, 8}, {11, 8}, {11, 8}, {11, 8},
{10, 8}, {10, 8}, {10, 8}, {10, 8},
{10, 8}, {10, 8}, {10, 8}, {10, 8},
{ 9, 8}, { 9, 8}, { 9, 8}, { 9, 8},
{ 9, 8}, { 9, 8}, { 9, 8}, { 9, 8},
{ 8, 7}, { 8, 7}, { 8, 7}, { 8, 7},
{ 8, 7}, { 8, 7}, { 8, 7}, { 8, 7},
{ 8, 7}, { 8, 7}, { 8, 7}, { 8, 7},
{ 8, 7}, { 8, 7}, { 8, 7}, { 8, 7},
{ 7, 7}, { 7, 7}, { 7, 7}, { 7, 7},
{ 7, 7}, { 7, 7}, { 7, 7}, { 7, 7},
{ 7, 7}, { 7, 7}, { 7, 7}, { 7, 7},
{ 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}
};
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
static int non_linear_quantizer_scale [] = {
0, 1, 2, 3, 4, 5, 6, 7,
8, 10, 12, 14, 16, 18, 20, 22,
24, 28, 32, 36, 40, 44, 48, 52,
56, 64, 72, 80, 88, 96, 104, 112
};
bool CMpeg2Decoder::m_idct_initialized = false;
CMpeg2Decoder::CMpeg2Decoder()
{
memset(&m_b_motion, 0, sizeof(m_b_motion));
memset(&m_f_motion, 0, sizeof(m_f_motion));
m_DCTblock = (int16_t*)_aligned_malloc(64*sizeof(int16_t), 16);
memset(m_DCTblock, 0, 64*sizeof(int16_t));
m_bitstream_buf = 0;
m_bitstream_bits = 0;
m_bitstream_ptr = NULL;
memset(&m_dest, 0, sizeof(m_dest));
memset(&m_picture_dest, 0, sizeof(m_picture_dest));
m_offset = m_stride = m_uv_stride = 0;
m_limit_x = m_limit_y_16 = m_limit_y_8 = m_limit_y = 0;
memset(&m_dc_dct_pred, 0, sizeof(m_dc_dct_pred));
m_quantizer_scale = m_dmv_offset = 0;
m_v_offset = 0;
memset(&m_intra_quantizer_matrix, 0, sizeof(m_intra_quantizer_matrix));
memset(&m_non_intra_quantizer_matrix, 0, sizeof(m_non_intra_quantizer_matrix));
m_width = m_height = 0;
m_vertical_position_extension = 0;
m_coding_type = 0;
m_intra_dc_precision = 0;
m_picture_structure = 0;
m_frame_pred_frame_dct = 0;
m_concealment_motion_vectors = 0;
m_q_scale_type = 0;
m_intra_vlc_format = 0;
m_top_field_first = 0;
m_scan = NULL;
m_second_field = 0;
m_mpeg1 = 0;
// //
/**/
if(g_cpuid.m_flags&CCpuID::sse2)
{
m_idct_init = mpeg2_idct_init_sse2;
m_idct_copy = mpeg2_idct_copy_sse2;
m_idct_add = mpeg2_idct_add_sse2;
m_mc = &mpeg2_mc_sse2;
}
else if(g_cpuid.m_flags&CCpuID::mmx)
{
m_idct_init = mpeg2_idct_init_mmx;
m_idct_copy = mpeg2_idct_copy_mmx;
m_idct_add = mpeg2_idct_add_mmx;
m_mc = &mpeg2_mc_mmx;
}
else
{
m_idct_init = mpeg2_idct_init_c;
m_idct_copy = mpeg2_idct_copy_c;
m_idct_add = mpeg2_idct_add_c;
m_mc = &mpeg2_mc_c;
}
/*
m_idct_init = mpeg2_idct_init_null;
m_idct_copy = mpeg2_idct_copy_null;
m_idct_add = mpeg2_idct_add_null;
m_mc = &mpeg2_mc_null;
*/
if(!m_idct_initialized)
{
m_idct_init();
m_idct_initialized = true;
}
}
CMpeg2Decoder::~CMpeg2Decoder()
{
if(m_DCTblock) _aligned_free(m_DCTblock);
}
#define bit_buf (m_bitstream_buf)
#define bits (m_bitstream_bits)
#define bit_ptr (m_bitstream_ptr)
int CMpeg2Decoder::get_macroblock_modes()
{
int macroblock_modes;
const MBtab* tab;
switch(m_coding_type)
{
case P_TYPE:
tab = MB_P + UBITS(bit_buf, 5);
DUMPBITS(tab->len);
macroblock_modes = tab->modes;
if(m_picture_structure != FRAME_PICTURE)
{
if(macroblock_modes & MACROBLOCK_MOTION_FORWARD)
{
macroblock_modes |= UBITS(bit_buf, 2) * MOTION_TYPE_BASE;
DUMPBITS(2);
}
return macroblock_modes;
}
else if(m_frame_pred_frame_dct)
{
if(macroblock_modes & MACROBLOCK_MOTION_FORWARD)
macroblock_modes |= MC_FRAME;
return macroblock_modes;
}
if(macroblock_modes & MACROBLOCK_MOTION_FORWARD)
{
macroblock_modes |= UBITS(bit_buf, 2) * MOTION_TYPE_BASE;
DUMPBITS(2);
}
if(macroblock_modes & (MACROBLOCK_INTRA|MACROBLOCK_PATTERN))
{
macroblock_modes |= UBITS(bit_buf, 1) * DCT_TYPE_INTERLACED;
DUMPBITS(1);
}
return macroblock_modes;
case B_TYPE:
tab = MB_B + UBITS(bit_buf, 6);
DUMPBITS(tab->len);
macroblock_modes = tab->modes;
if(m_picture_structure != FRAME_PICTURE)
{
if(!(macroblock_modes & MACROBLOCK_INTRA))
{
macroblock_modes |= UBITS(bit_buf, 2) * MOTION_TYPE_BASE;
DUMPBITS(2);
}
return macroblock_modes;
}
else if(m_frame_pred_frame_dct)
{
// if(!(macroblock_modes & MACROBLOCK_INTRA))
macroblock_modes |= MC_FRAME;
return macroblock_modes;
}
/*
if(macroblock_modes & MACROBLOCK_INTRA)
goto intra;
macroblock_modes |= UBITS(bit_buf, 2) * MOTION_TYPE_BASE;
DUMPBITS(2);
if(macroblock_modes & (MACROBLOCK_INTRA|MACROBLOCK_PATTERN))
{
intra:
macroblock_modes |= UBITS(bit_buf, 1) * DCT_TYPE_INTERLACED;
DUMPBITS(1);
}
*/
if(!(macroblock_modes & MACROBLOCK_INTRA))
{
macroblock_modes |= UBITS(bit_buf, 2) * MOTION_TYPE_BASE;
DUMPBITS(2);
}
if(macroblock_modes & (MACROBLOCK_INTRA|MACROBLOCK_PATTERN))
{
macroblock_modes |= UBITS(bit_buf, 1) * DCT_TYPE_INTERLACED;
DUMPBITS(1);
}
return macroblock_modes;
case I_TYPE:
tab = MB_I + UBITS(bit_buf, 1);
DUMPBITS(tab->len);
macroblock_modes = tab->modes;
if(!m_frame_pred_frame_dct && m_picture_structure == FRAME_PICTURE)
{
macroblock_modes |= UBITS(bit_buf, 1) * DCT_TYPE_INTERLACED;
DUMPBITS(1);
}
return macroblock_modes;
case D_TYPE:
DUMPBITS(1);
return MACROBLOCK_INTRA;
}
return 0;
}
int CMpeg2Decoder::get_quantizer_scale()
{
int quantizer_scale_code = UBITS(bit_buf, 5);
DUMPBITS(5);
return m_q_scale_type
? non_linear_quantizer_scale[quantizer_scale_code]
: (quantizer_scale_code << 1);
}
int CMpeg2Decoder::get_motion_delta(const int f_code)
{
int delta;
int sign;
const MVtab* tab;
if(bit_buf & 0x80000000)
{
DUMPBITS(1);
return 0;
}
else if(bit_buf >= 0x0c000000)
{
tab = MV_4 + UBITS(bit_buf, 4);
delta = (tab->delta << f_code) + 1;
bits += tab->len + f_code + 1;
bit_buf <<= tab->len;
sign = SBITS(bit_buf, 1);
bit_buf <<= 1;
if(f_code)
{
delta += UBITS(bit_buf, f_code);
}
bit_buf <<= f_code;
return (delta ^ sign) - sign;
}
else
{
tab = MV_10 + UBITS(bit_buf, 10);
delta = (tab->delta << f_code) + 1;
bits += tab->len + 1;
bit_buf <<= tab->len;
sign = SBITS(bit_buf, 1);
bit_buf <<= 1;
if(f_code)
{
NEEDBITS;
delta += UBITS(bit_buf, f_code);
DUMPBITS(f_code);
}
return (delta ^ sign) - sign;
}
}
int CMpeg2Decoder::bound_motion_vector(const int vector, const int f_code)
{
return ((int32_t)vector << (27 - f_code)) >> (27 - f_code);
}
int CMpeg2Decoder::get_dmv()
{
const DMVtab* tab = DMV_2 + UBITS(bit_buf, 2);
DUMPBITS(tab->len);
return tab->dmv;
}
int CMpeg2Decoder::get_coded_block_pattern()
{
const CBPtab* tab;
NEEDBITS;
if(bit_buf >= 0x20000000)
{
tab = CBP_7 + (UBITS(bit_buf, 7) - 16);
DUMPBITS(tab->len);
return tab->cbp;
}
else
{
tab = CBP_9 + UBITS(bit_buf, 9);
DUMPBITS(tab->len);
return tab->cbp;
}
}
int CMpeg2Decoder::get_luma_dc_dct_diff()
{
const DCtab* tab;
int size;
int dc_diff;
if(bit_buf < 0xf8000000)
{
tab = DC_lum_5 + UBITS(bit_buf, 5);
size = tab->size;
if(size)
{
bits += tab->len + size;
bit_buf <<= tab->len;
dc_diff = UBITS(bit_buf, size) - UBITS(SBITS(~bit_buf, 1), size);
bit_buf <<= size;
return dc_diff;
}
else
{
DUMPBITS(3);
return 0;
}
}
else
{
tab = DC_long + (UBITS(bit_buf, 9) - 0x1e0);
size = tab->size;
DUMPBITS(tab->len);
NEEDBITS;
dc_diff = UBITS(bit_buf, size) - UBITS(SBITS(~bit_buf, 1), size);
DUMPBITS(size);
return dc_diff;
}
}
int CMpeg2Decoder::get_chroma_dc_dct_diff()
{
const DCtab* tab;
int size;
int dc_diff;
if(bit_buf < 0xf8000000)
{
tab = DC_chrom_5 + UBITS(bit_buf, 5);
size = tab->size;
if(size)
{
bits += tab->len + size;
bit_buf <<= tab->len;
dc_diff = UBITS(bit_buf, size) - UBITS(SBITS(~bit_buf, 1), size);
bit_buf <<= size;
return dc_diff;
}
else
{
DUMPBITS(2);
return 0;
}
}
else
{
tab = DC_long + (UBITS(bit_buf, 10) - 0x3e0);
size = tab->size;
DUMPBITS(tab->len + 1);
NEEDBITS;
dc_diff = UBITS(bit_buf, size) - UBITS(SBITS(~bit_buf, 1), size);
DUMPBITS(size);
return dc_diff;
}
}
#undef bit_buf
#undef bits
#undef bit_ptr
#define SATURATE(val) \
do { \
if((uint32_t)(val + 2048) > 4095) \
val = SBITS(val, 1) ^ 2047; \
} while (0)
void CMpeg2Decoder::get_intra_block_B14()
{
int i, j;
int val;
const uint8_t* scan = m_scan;
const uint8_t* quant_matrix = m_intra_quantizer_matrix;
int quantizer_scale = m_quantizer_scale;
int mismatch;
const DCTtab* tab;
uint32_t bit_buf;
int bits;
const uint8_t* bit_ptr;
int16_t* dest;
dest = m_DCTblock;
i = 0;
mismatch = ~dest[0];
bit_buf = m_bitstream_buf;
bits = m_bitstream_bits;
bit_ptr = m_bitstream_ptr;
NEEDBITS;
while(1)
{
if(bit_buf >= 0x28000000)
{
tab = DCT_B14AC_5 + (UBITS(bit_buf, 5) - 5);
i += tab->run;
if(i >= 64)
break; /* end of block */
normal_code:
j = scan[i];
bit_buf <<= tab->len;
bits += tab->len + 1;
val = (tab->level * quantizer_scale * quant_matrix[j]) >> 4;
// if(bitstream_get (1)) val = -val;
val = (val ^ SBITS(bit_buf, 1)) - SBITS(bit_buf, 1);
SATURATE(val);
dest[j] = val;
mismatch ^= val;
bit_buf <<= 1;
NEEDBITS;
continue;
}
else if(bit_buf >= 0x04000000)
{
tab = DCT_B14_8 + (UBITS(bit_buf, 8) - 4);
i += tab->run;
if(i < 64)
goto normal_code;
/* escape code */
i += UBITS(bit_buf << 6, 6) - 64;
if(i >= 64)
break; /* illegal, check needed to avoid buffer overflow */
j = scan[i];
DUMPBITS(12);
NEEDBITS;
val = (SBITS(bit_buf, 12) * quantizer_scale * quant_matrix[j]) / 16;
SATURATE(val);
dest[j] = val;
mismatch ^= val;
DUMPBITS(12);
NEEDBITS;
continue;
}
else if(bit_buf >= 0x02000000)
{
tab = DCT_B14_10 + (UBITS(bit_buf, 10) - 8);
i += tab->run;
if(i < 64)
goto normal_code;
}
else if(bit_buf >= 0x00800000)
{
tab = DCT_13 + (UBITS(bit_buf, 13) - 16);
i += tab->run;
if(i < 64)
goto normal_code;
}
else if(bit_buf >= 0x00200000)
{
tab = DCT_15 + (UBITS(bit_buf, 15) - 16);
i += tab->run;
if(i < 64)
goto normal_code;
}
else
{
tab = DCT_16 + UBITS(bit_buf, 16);
bit_buf <<= 16;
GETWORD (bit_buf, bits + 16, bit_ptr);
i += tab->run;
if(i < 64)
goto normal_code;
}
break; /* illegal, check needed to avoid buffer overflow */
}
dest[63] ^= mismatch & 1;
DUMPBITS(2); /* dump end of block code */
m_bitstream_buf = bit_buf;
m_bitstream_bits = bits;
m_bitstream_ptr = bit_ptr;
}
void CMpeg2Decoder::get_intra_block_B15()
{
int i, j;
int val;
const uint8_t* scan = m_scan;
const uint8_t* quant_matrix = m_intra_quantizer_matrix;
int quantizer_scale = m_quantizer_scale;
int mismatch;
const DCTtab* tab;
uint32_t bit_buf;
int bits;
const uint8_t* bit_ptr;
int16_t* dest;
dest = m_DCTblock;
i = 0;
mismatch = ~dest[0];
bit_buf = m_bitstream_buf;
bits = m_bitstream_bits;
bit_ptr = m_bitstream_ptr;
NEEDBITS;
while(1)
{
if(bit_buf >= 0x04000000)
{
tab = DCT_B15_8 + (UBITS(bit_buf, 8) - 4);
i += tab->run;
if(i < 64)
{
normal_code:
j = scan[i];
bit_buf <<= tab->len;
bits += tab->len + 1;
val = (tab->level * quantizer_scale * quant_matrix[j]) >> 4;
// if(bitstream_get (1)) val = -val;
val = (val ^ SBITS(bit_buf, 1)) - SBITS(bit_buf, 1);
SATURATE(val);
dest[j] = val;
mismatch ^= val;
bit_buf <<= 1;
NEEDBITS;
continue;
}
else
{
/* end of block. I commented out this code because if we */
/* dont exit here we will still exit at the later test :) */
/* if(i >= 128) break; */ /* end of block */
/* escape code */
i += UBITS(bit_buf << 6, 6) - 64;
if(i >= 64)
break; /* illegal, check against buffer overflow */
j = scan[i];
DUMPBITS(12);
NEEDBITS;
val = (SBITS(bit_buf, 12) *
quantizer_scale * quant_matrix[j]) / 16;
SATURATE(val);
dest[j] = val;
mismatch ^= val;
DUMPBITS(12);
NEEDBITS;
continue;
}
}
else if(bit_buf >= 0x02000000)
{
tab = DCT_B15_10 + (UBITS(bit_buf, 10) - 8);
i += tab->run;
if(i < 64)
goto normal_code;
}
else if(bit_buf >= 0x00800000)
{
tab = DCT_13 + (UBITS(bit_buf, 13) - 16);
i += tab->run;
if(i < 64)
goto normal_code;
}
else if(bit_buf >= 0x00200000)
{
tab = DCT_15 + (UBITS(bit_buf, 15) - 16);
i += tab->run;
if(i < 64)
goto normal_code;
}
else
{
tab = DCT_16 + UBITS(bit_buf, 16);
bit_buf <<= 16;
GETWORD(bit_buf, bits + 16, bit_ptr);
i += tab->run;
if(i < 64)
goto normal_code;
}
break; /* illegal, check needed to avoid buffer overflow */
}
dest[63] ^= mismatch & 1;
DUMPBITS(4); /* dump end of block code */
m_bitstream_buf = bit_buf;
m_bitstream_bits = bits;
m_bitstream_ptr = bit_ptr;
}
int CMpeg2Decoder::get_non_intra_block()
{
int i, j;
int val;
const uint8_t* scan = m_scan;
const uint8_t* quant_matrix = m_non_intra_quantizer_matrix;
int quantizer_scale = m_quantizer_scale;
int mismatch;
const DCTtab* tab;
uint32_t bit_buf;
int bits;
const uint8_t* bit_ptr;
int16_t* dest;
i = -1;
mismatch = 1;
dest = m_DCTblock;
bit_buf = m_bitstream_buf;
bits = m_bitstream_bits;
bit_ptr = m_bitstream_ptr;
NEEDBITS;
if(bit_buf >= 0x28000000)
{
tab = DCT_B14DC_5 + (UBITS(bit_buf, 5) - 5);
goto entry_1;
}
else
{
goto entry_2;
}
while(1)
{
if(bit_buf >= 0x28000000)
{
tab = DCT_B14AC_5 + (UBITS(bit_buf, 5) - 5);
entry_1:
i += tab->run;
if(i >= 64)
break; /* end of block */
normal_code:
j = scan[i];
bit_buf <<= tab->len;
bits += tab->len + 1;
val = ((2*tab->level+1) * quantizer_scale * quant_matrix[j]) >> 5;
/* if(bitstream_get (1)) val = -val; */
val = (val ^ SBITS(bit_buf, 1)) - SBITS(bit_buf, 1);
SATURATE(val);
dest[j] = val;
mismatch ^= val;
bit_buf <<= 1;
NEEDBITS;
continue;
}
entry_2:
if(bit_buf >= 0x04000000)
{
tab = DCT_B14_8 + (UBITS(bit_buf, 8) - 4);
i += tab->run;
if(i < 64)
goto normal_code;
/* escape code */
i += UBITS(bit_buf << 6, 6) - 64;
if(i >= 64)
break; /* illegal, check needed to avoid buffer overflow */
j = scan[i];
DUMPBITS(12);
NEEDBITS;
val = 2 * (SBITS(bit_buf, 12) + SBITS(bit_buf, 1)) + 1;
val = (val * quantizer_scale * quant_matrix[j]) / 32;
SATURATE(val);
dest[j] = val;
mismatch ^= val;
DUMPBITS(12);
NEEDBITS;
continue;
}
else if(bit_buf >= 0x02000000)
{
tab = DCT_B14_10 + (UBITS(bit_buf, 10) - 8);
i += tab->run;
if(i < 64)
goto normal_code;
}
else if(bit_buf >= 0x00800000)
{
tab = DCT_13 + (UBITS(bit_buf, 13) - 16);
i += tab->run;
if(i < 64)
goto normal_code;
}
else if(bit_buf >= 0x00200000)
{
tab = DCT_15 + (UBITS(bit_buf, 15) - 16);
i += tab->run;
if(i < 64)
goto normal_code;
}
else
{
tab = DCT_16 + UBITS(bit_buf, 16);
bit_buf <<= 16;
GETWORD (bit_buf, bits + 16, bit_ptr);
i += tab->run;
if(i < 64)
goto normal_code;
}
break; /* illegal, check needed to avoid buffer overflow */
}
dest[63] ^= mismatch & 1;
DUMPBITS(2); /* dump end of block code */
m_bitstream_buf = bit_buf;
m_bitstream_bits = bits;
m_bitstream_ptr = bit_ptr;
return i;
}
void CMpeg2Decoder::get_mpeg1_intra_block()
{
int i, j;
int val;
const uint8_t* scan = m_scan;
const uint8_t* quant_matrix = m_intra_quantizer_matrix;
int quantizer_scale = m_quantizer_scale;
const DCTtab* tab;
uint32_t bit_buf;
int bits;
const uint8_t* bit_ptr;
int16_t* dest;
i = 0;
dest = m_DCTblock;
bit_buf = m_bitstream_buf;
bits = m_bitstream_bits;
bit_ptr = m_bitstream_ptr;
NEEDBITS;
while(1)
{
if(bit_buf >= 0x28000000)
{
tab = DCT_B14AC_5 + (UBITS(bit_buf, 5) - 5);
i += tab->run;
if(i >= 64)
break; /* end of block */
normal_code:
j = scan[i];
bit_buf <<= tab->len;
bits += tab->len + 1;
val = (tab->level * quantizer_scale * quant_matrix[j]) >> 4;
/* oddification */
val = (val - 1) | 1;
/* if(bitstream_get (1)) val = -val; */
val = (val ^ SBITS(bit_buf, 1)) - SBITS(bit_buf, 1);
SATURATE(val);
dest[j] = val;
bit_buf <<= 1;
NEEDBITS;
continue;
}
else if(bit_buf >= 0x04000000)
{
tab = DCT_B14_8 + (UBITS(bit_buf, 8) - 4);
i += tab->run;
if(i < 64)
goto normal_code;
/* escape code */
i += UBITS(bit_buf << 6, 6) - 64;
if(i >= 64)
break; /* illegal, check needed to avoid buffer overflow */
j = scan[i];
DUMPBITS(12);
NEEDBITS;
val = SBITS(bit_buf, 8);
if(!(val & 0x7f))
{
DUMPBITS(8);
val = UBITS(bit_buf, 8) + 2 * val;
}
val = (val * quantizer_scale * quant_matrix[j]) / 16;
/* oddification */
val = (val + ~SBITS(val, 1)) | 1;
SATURATE(val);
dest[j] = val;
DUMPBITS(8);
NEEDBITS;
continue;
}
else if(bit_buf >= 0x02000000)
{
tab = DCT_B14_10 + (UBITS(bit_buf, 10) - 8);
i += tab->run;
if(i < 64)
goto normal_code;
}
else if(bit_buf >= 0x00800000)
{
tab = DCT_13 + (UBITS(bit_buf, 13) - 16);
i += tab->run;
if(i < 64)
goto normal_code;
}
else if(bit_buf >= 0x00200000)
{
tab = DCT_15 + (UBITS(bit_buf, 15) - 16);
i += tab->run;
if(i < 64)
goto normal_code;
}
else
{
tab = DCT_16 + UBITS(bit_buf, 16);
bit_buf <<= 16;
GETWORD(bit_buf, bits + 16, bit_ptr);
i += tab->run;
if(i < 64)
goto normal_code;
}
break; /* illegal, check needed to avoid buffer overflow */
}
DUMPBITS(2); /* dump end of block code */
m_bitstream_buf = bit_buf;
m_bitstream_bits = bits;
m_bitstream_ptr = bit_ptr;
}
int CMpeg2Decoder::get_mpeg1_non_intra_block()
{
int i, j;
int val;
const uint8_t* scan = m_scan;
const uint8_t* quant_matrix = m_non_intra_quantizer_matrix;
int quantizer_scale = m_quantizer_scale;
const DCTtab* tab;
uint32_t bit_buf;
int bits;
const uint8_t* bit_ptr;
int16_t* dest;
i = -1;
dest = m_DCTblock;
bit_buf = m_bitstream_buf;
bits = m_bitstream_bits;
bit_ptr = m_bitstream_ptr;
NEEDBITS;
if(bit_buf >= 0x28000000)
{
tab = DCT_B14DC_5 + (UBITS(bit_buf, 5) - 5);
goto entry_1;
}
else
{
goto entry_2;
}
while(1)
{
if(bit_buf >= 0x28000000)
{
tab = DCT_B14AC_5 + (UBITS(bit_buf, 5) - 5);
entry_1:
i += tab->run;
if(i >= 64)
break; /* end of block */
normal_code:
j = scan[i];
bit_buf <<= tab->len;
bits += tab->len + 1;
val = ((2*tab->level+1) * quantizer_scale * quant_matrix[j]) >> 5;
/* oddification */
val = (val - 1) | 1;
/* if(bitstream_get (1)) val = -val; */
val = (val ^ SBITS(bit_buf, 1)) - SBITS(bit_buf, 1);
SATURATE(val);
dest[j] = val;
bit_buf <<= 1;
NEEDBITS;
continue;
}
entry_2:
if(bit_buf >= 0x04000000)
{
tab = DCT_B14_8 + (UBITS(bit_buf, 8) - 4);
i += tab->run;
if(i < 64)
goto normal_code;
/* escape code */
i += UBITS(bit_buf << 6, 6) - 64;
if(i >= 64)
break; /* illegal, check needed to avoid buffer overflow */
j = scan[i];
DUMPBITS(12);
NEEDBITS;
val = SBITS(bit_buf, 8);
if(!(val & 0x7f))
{
DUMPBITS(8);
val = UBITS(bit_buf, 8) + 2 * val;
}
val = 2 * (val + SBITS(val, 1)) + 1;
val = (val * quantizer_scale * quant_matrix[j]) / 32;
/* oddification */
val = (val + ~SBITS(val, 1)) | 1;
SATURATE(val);
dest[j] = val;
DUMPBITS(8);
NEEDBITS;
continue;
}
else if(bit_buf >= 0x02000000)
{
tab = DCT_B14_10 + (UBITS(bit_buf, 10) - 8);
i += tab->run;
if(i < 64)
goto normal_code;
}
else if(bit_buf >= 0x00800000)
{
tab = DCT_13 + (UBITS(bit_buf, 13) - 16);
i += tab->run;
if(i < 64)
goto normal_code;
}
else if(bit_buf >= 0x00200000)
{
tab = DCT_15 + (UBITS(bit_buf, 15) - 16);
i += tab->run;
if(i < 64)
goto normal_code;
}
else
{
tab = DCT_16 + UBITS(bit_buf, 16);
bit_buf <<= 16;
GETWORD (bit_buf, bits + 16, bit_ptr);
i += tab->run;
if(i < 64)
goto normal_code;
}
break; /* illegal, check needed to avoid buffer overflow */
}
DUMPBITS(2); /* dump end of block code */
m_bitstream_buf = bit_buf;
m_bitstream_bits = bits;
m_bitstream_ptr = bit_ptr;
return i;
}
#define bit_buf (m_bitstream_buf)
#define bits (m_bitstream_bits)
#define bit_ptr (m_bitstream_ptr)
void CMpeg2Decoder::slice_intra_DCT(const int cc, uint8_t* dest, int stride)
{
NEEDBITS;
/* Get the intra DC coefficient and inverse quantize it */
m_dc_dct_pred[cc] += (cc == 0)
? get_luma_dc_dct_diff()
: get_chroma_dc_dct_diff();
m_DCTblock[0] = m_dc_dct_pred[cc] << (3 - m_intra_dc_precision);
if(m_mpeg1)
{
if(m_coding_type != D_TYPE)
get_mpeg1_intra_block();
}
else if(m_intra_vlc_format)
{
get_intra_block_B15();
}
else
{
get_intra_block_B14();
}
m_idct_copy(m_DCTblock, dest, stride);
}
void CMpeg2Decoder::slice_non_intra_DCT(uint8_t* dest, int stride)
{
int last = m_mpeg1
? get_mpeg1_non_intra_block()
: get_non_intra_block ();
m_idct_add(last, m_DCTblock, dest, stride);
}
void CMpeg2Decoder::MOTION(
mpeg2_mc_fct * const * const table, uint8_t** ref,
int motion_x, int motion_y,
unsigned int size, unsigned int y, unsigned int limit_y)
{
unsigned int pos_x, pos_y, xy_half, offset, dest_offset;
pos_x = 2 * m_offset + motion_x;
pos_y = 2 * m_v_offset + motion_y + 2 * y;
if(pos_x > m_limit_x)
{
pos_x = ((int)pos_x < 0) ? 0 : m_limit_x;
motion_x = pos_x - 2 * m_offset;
}
if(pos_y > limit_y)
{
pos_y = ((int)pos_y < 0) ? 0 : limit_y;
motion_y = pos_y - 2 * m_v_offset - 2 * y;
}
xy_half = ((pos_y & 1) << 1) | (pos_x & 1);
offset = (pos_x >> 1) + (pos_y >> 1) * m_stride;
table[xy_half] (m_dest[0] + y * m_stride + m_offset, ref[0] + offset, m_stride, size);
motion_x /= 2; motion_y /= 2;
xy_half = ((motion_y & 1) << 1) | (motion_x & 1);
offset = ((m_offset + motion_x) >> 1) + ((((m_v_offset + motion_y) >> 1) + y/2) * m_uv_stride);
dest_offset = y/2 * m_uv_stride + (m_offset >> 1);
table[4+xy_half] (m_dest[1] + dest_offset, ref[1] + offset, m_uv_stride, size/2);
table[4+xy_half] (m_dest[2] + dest_offset, ref[2] + offset, m_uv_stride, size/2);
}
void CMpeg2Decoder::MOTION_FIELD(
mpeg2_mc_fct * const * const table, uint8_t** ref,
int motion_x, int motion_y,
int dest_field, int src_field, unsigned int op)
{
unsigned int pos_x, pos_y, xy_half, offset, dest_offset;
pos_x = 2 * m_offset + motion_x;
pos_y = m_v_offset + motion_y;
if(pos_x > m_limit_x)
{
pos_x = ((int)pos_x < 0) ? 0 : m_limit_x;
motion_x = pos_x - 2 * m_offset;
}
if(pos_y > m_limit_y)
{
pos_y = ((int)pos_y < 0) ? 0 : m_limit_y;
motion_y = pos_y - m_v_offset;
}
xy_half = ((pos_y & 1) << 1) | (pos_x & 1);
offset = (pos_x >> 1) + ((op ? (pos_y | 1) : (pos_y & ~1)) + src_field) * m_stride;
table[xy_half] (m_dest[0] + dest_field * m_stride + m_offset, ref[0] + offset, 2 * m_stride, 8);
motion_x /= 2; motion_y /= 2;
xy_half = ((motion_y & 1) << 1) | (motion_x & 1);
offset = ((m_offset + motion_x) >> 1) + (((m_v_offset >> 1) + (op ? (motion_y | 1) :(motion_y & ~1)) + src_field) * m_uv_stride);
dest_offset = dest_field * m_uv_stride + (m_offset >> 1);
table[4+xy_half] (m_dest[1] + dest_offset, ref[1] + offset, 2 * m_uv_stride, 4);
table[4+xy_half] (m_dest[2] + dest_offset, ref[2] + offset, 2 * m_uv_stride, 4);
}
void CMpeg2Decoder::motion_mp1(motion_t* motion, mpeg2_mc_fct * const * const table)
{
int motion_x, motion_y;
NEEDBITS;
motion_x = motion->pmv[0][0] + (get_motion_delta(motion->f_code[0]) << motion->f_code[1]);
motion_x = bound_motion_vector(motion_x, motion->f_code[0] + motion->f_code[1]);
motion->pmv[0][0] = motion_x;
NEEDBITS;
motion_y = motion->pmv[0][1] + (get_motion_delta(motion->f_code[0]) << motion->f_code[1]);
motion_y = bound_motion_vector(motion_y, motion->f_code[0] + motion->f_code[1]);
motion->pmv[0][1] = motion_y;
MOTION(table, motion->ref[0], motion_x, motion_y, 16, 0, m_limit_y_16);
}
void CMpeg2Decoder::motion_fr_frame(motion_t* motion, mpeg2_mc_fct * const * const table)
{
int motion_x, motion_y;
NEEDBITS;
motion_x = motion->pmv[0][0] + get_motion_delta(motion->f_code[0]);
motion_x = bound_motion_vector(motion_x, motion->f_code[0]);
motion->pmv[1][0] = motion->pmv[0][0] = motion_x;
NEEDBITS;
motion_y = motion->pmv[0][1] + get_motion_delta(motion->f_code[1]);
motion_y = bound_motion_vector (motion_y, motion->f_code[1]);
motion->pmv[1][1] = motion->pmv[0][1] = motion_y;
MOTION(table, motion->ref[0], motion_x, motion_y, 16, 0, m_limit_y_16);
}
void CMpeg2Decoder::motion_fr_field(motion_t* motion, mpeg2_mc_fct * const * const table)
{
int motion_x, motion_y, field;
NEEDBITS;
field = UBITS(bit_buf, 1);
DUMPBITS(1);
motion_x = motion->pmv[0][0] + get_motion_delta(motion->f_code[0]);
motion_x = bound_motion_vector(motion_x, motion->f_code[0]);
motion->pmv[0][0] = motion_x;
NEEDBITS;
motion_y = (motion->pmv[0][1] >> 1) + get_motion_delta(motion->f_code[1]);
/* motion_y = bound_motion_vector(motion_y, motion->f_code[1]); */
motion->pmv[0][1] = motion_y << 1;
MOTION_FIELD(table, motion->ref[0], motion_x, motion_y, 0, field, 0);
NEEDBITS;
field = UBITS(bit_buf, 1);
DUMPBITS(1);
motion_x = motion->pmv[1][0] + get_motion_delta(motion->f_code[0]);
motion_x = bound_motion_vector(motion_x, motion->f_code[0]);
motion->pmv[1][0] = motion_x;
NEEDBITS;
motion_y = (motion->pmv[1][1] >> 1) + get_motion_delta(motion->f_code[1]);
/* motion_y = bound_motion_vector(motion_y, motion->f_code[1]); */
motion->pmv[1][1] = motion_y << 1;
MOTION_FIELD(table, motion->ref[0], motion_x, motion_y, 1, field, 0);
}
void CMpeg2Decoder::motion_fr_dmv(motion_t* motion, mpeg2_mc_fct * const * const table)
{
int motion_x, motion_y, dmv_x, dmv_y, m, other_x, other_y;
NEEDBITS;
motion_x = motion->pmv[0][0] + get_motion_delta(motion->f_code[0]);
motion_x = bound_motion_vector(motion_x, motion->f_code[0]);
motion->pmv[1][0] = motion->pmv[0][0] = motion_x;
NEEDBITS;
dmv_x = get_dmv();
motion_y = (motion->pmv[0][1] >> 1) + get_motion_delta(motion->f_code[1]);
/* motion_y = bound_motion_vector (motion_y, motion->f_code[1]); */
motion->pmv[1][1] = motion->pmv[0][1] = motion_y << 1;
dmv_y = get_dmv();
m = m_top_field_first ? 1 : 3;
other_x = ((motion_x * m + (motion_x > 0)) >> 1) + dmv_x;
other_y = ((motion_y * m + (motion_y > 0)) >> 1) + dmv_y - 1;
MOTION_FIELD(m_mc->put, motion->ref[0], other_x, other_y, 0, 0, 1);
m = m_top_field_first ? 3 : 1;
other_x = ((motion_x * m + (motion_x > 0)) >> 1) + dmv_x;
other_y = ((motion_y * m + (motion_y > 0)) >> 1) + dmv_y + 1;
MOTION_FIELD(m_mc->put, motion->ref[0], other_x, other_y, 1, 0, 0);
unsigned int pos_x, pos_y, xy_half, offset;
pos_x = 2 * m_offset + motion_x;
pos_y = m_v_offset + motion_y;
if(pos_x > m_limit_x)
{
pos_x = ((int)pos_x < 0) ? 0 : m_limit_x;
motion_x = pos_x - 2 * m_offset;
}
if(pos_y > m_limit_y)
{
pos_y = ((int)pos_y < 0) ? 0 : m_limit_y;
motion_y = pos_y - m_v_offset;
}
xy_half = ((pos_y & 1) << 1) | (pos_x & 1);
offset = (pos_x >> 1) + (pos_y & ~1) * m_stride;
m_mc->avg[xy_half](m_dest[0] + m_offset, motion->ref[0][0] + offset, 2 * m_stride, 8);
m_mc->avg[xy_half](m_dest[0] + m_stride + m_offset, motion->ref[0][0] + m_stride + offset, 2 * m_stride, 8);
motion_x /= 2;
motion_y /= 2;
xy_half = ((motion_y & 1) << 1) | (motion_x & 1);
offset = ((m_offset + motion_x) >> 1) + ((m_v_offset >> 1) + (motion_y & ~1)) * m_uv_stride;
m_mc->avg[4+xy_half](m_dest[1] + (m_offset >> 1), motion->ref[0][1] + offset, 2 * m_uv_stride, 4);
m_mc->avg[4+xy_half](m_dest[1] + m_uv_stride + (m_offset >> 1), motion->ref[0][1] + m_uv_stride + offset, 2 * m_uv_stride, 4);
m_mc->avg[4+xy_half](m_dest[2] + (m_offset >> 1), motion->ref[0][2] + offset, 2 * m_uv_stride, 4);
m_mc->avg[4+xy_half](m_dest[2] + m_uv_stride + (m_offset >> 1), motion->ref[0][2] + m_uv_stride + offset, 2 * m_uv_stride, 4);
}
void CMpeg2Decoder::motion_reuse(motion_t* motion, mpeg2_mc_fct * const * const table)
{
int motion_x, motion_y;
motion_x = motion->pmv[0][0];
motion_y = motion->pmv[0][1];
MOTION(table, motion->ref[0], motion_x, motion_y, 16, 0, m_limit_y_16);
}
void CMpeg2Decoder::motion_zero(motion_t* motion, mpeg2_mc_fct * const * const table)
{
unsigned int offset;
table[0](m_dest[0] + m_offset, motion->ref[0][0] + m_offset + m_v_offset * m_stride, m_stride, 16);
offset = (m_offset >> 1) + (m_v_offset >> 1) * m_uv_stride;
table[4](m_dest[1] + (m_offset >> 1), motion->ref[0][1] + offset, m_uv_stride, 8);
table[4](m_dest[2] + (m_offset >> 1), motion->ref[0][2] + offset, m_uv_stride, 8);
}
/* like motion_frame, but parsing without actual motion compensation */
void CMpeg2Decoder::motion_fr_conceal()
{
int tmp;
NEEDBITS;
tmp = (m_f_motion.pmv[0][0] + get_motion_delta(m_f_motion.f_code[0]));
tmp = bound_motion_vector(tmp, m_f_motion.f_code[0]);
m_f_motion.pmv[1][0] = m_f_motion.pmv[0][0] = tmp;
NEEDBITS;
tmp = m_f_motion.pmv[0][1] + get_motion_delta(m_f_motion.f_code[1]);
tmp = bound_motion_vector(tmp, m_f_motion.f_code[1]);
m_f_motion.pmv[1][1] = m_f_motion.pmv[0][1] = tmp;
DUMPBITS(1); /* remove marker_bit */
}
void CMpeg2Decoder::motion_fi_field(motion_t * motion, mpeg2_mc_fct * const * const table)
{
int motion_x, motion_y;
uint8_t** ref_field;
NEEDBITS;
ref_field = motion->ref2[UBITS(bit_buf, 1)];
DUMPBITS(1);
motion_x = motion->pmv[0][0] + get_motion_delta(motion->f_code[0]);
motion_x = bound_motion_vector (motion_x, motion->f_code[0]);
motion->pmv[1][0] = motion->pmv[0][0] = motion_x;
NEEDBITS;
motion_y = motion->pmv[0][1] + get_motion_delta(motion->f_code[1]);
motion_y = bound_motion_vector(motion_y, motion->f_code[1]);
motion->pmv[1][1] = motion->pmv[0][1] = motion_y;
MOTION(table, ref_field, motion_x, motion_y, 16, 0, m_limit_y_16);
}
void CMpeg2Decoder::motion_fi_16x8(motion_t* motion, mpeg2_mc_fct * const * const table)
{
int motion_x, motion_y;
uint8_t** ref_field;
NEEDBITS;
ref_field = motion->ref2[UBITS(bit_buf, 1)];
DUMPBITS(1);
motion_x = motion->pmv[0][0] + get_motion_delta(motion->f_code[0]);
motion_x = bound_motion_vector(motion_x, motion->f_code[0]);
motion->pmv[0][0] = motion_x;
NEEDBITS;
motion_y = motion->pmv[0][1] + get_motion_delta(motion->f_code[1]);
motion_y = bound_motion_vector(motion_y, motion->f_code[1]);
motion->pmv[0][1] = motion_y;
MOTION(table, ref_field, motion_x, motion_y, 8, 0, m_limit_y_8);
NEEDBITS;
ref_field = motion->ref2[UBITS(bit_buf, 1)];
DUMPBITS(1);
motion_x = motion->pmv[1][0] + get_motion_delta(motion->f_code[0]);
motion_x = bound_motion_vector (motion_x, motion->f_code[0]);
motion->pmv[1][0] = motion_x;
NEEDBITS;
motion_y = motion->pmv[1][1] + get_motion_delta(motion->f_code[1]);
motion_y = bound_motion_vector(motion_y, motion->f_code[1]);
motion->pmv[1][1] = motion_y;
MOTION(table, ref_field, motion_x, motion_y, 8, 8, m_limit_y_8);
}
void CMpeg2Decoder::motion_fi_dmv(motion_t* motion, mpeg2_mc_fct * const * const table)
{
int motion_x, motion_y, other_x, other_y;
NEEDBITS;
motion_x = motion->pmv[0][0] + get_motion_delta(motion->f_code[0]);
motion_x = bound_motion_vector(motion_x, motion->f_code[0]);
motion->pmv[1][0] = motion->pmv[0][0] = motion_x;
NEEDBITS;
other_x = ((motion_x + (motion_x > 0)) >> 1) + get_dmv();
motion_y = motion->pmv[0][1] + get_motion_delta(motion->f_code[1]);
motion_y = bound_motion_vector(motion_y, motion->f_code[1]);
motion->pmv[1][1] = motion->pmv[0][1] = motion_y;
other_y = ((motion_y + (motion_y > 0)) >> 1) + get_dmv () + m_dmv_offset;
MOTION(m_mc->put, motion->ref[0], motion_x, motion_y, 16, 0, m_limit_y_16);
MOTION(m_mc->avg, motion->ref[1], other_x, other_y, 16, 0, m_limit_y_16);
}
void CMpeg2Decoder::motion_fi_conceal()
{
int tmp;
NEEDBITS;
DUMPBITS(1); /* remove field_select */
tmp = m_f_motion.pmv[0][0] + get_motion_delta (m_f_motion.f_code[0]);
tmp = bound_motion_vector(tmp, m_f_motion.f_code[0]);
m_f_motion.pmv[1][0] = m_f_motion.pmv[0][0] = tmp;
NEEDBITS;
tmp = m_f_motion.pmv[0][1] + get_motion_delta(m_f_motion.f_code[1]);
tmp = bound_motion_vector(tmp, m_f_motion.f_code[1]);
m_f_motion.pmv[1][1] = m_f_motion.pmv[0][1] = tmp;
DUMPBITS(1); /* remove marker_bit */
}
#define MOTION_CALL(routine, direction) \
do { \
if((direction) & MACROBLOCK_MOTION_FORWARD) \
routine(&m_f_motion, m_mc->put); \
if((direction) & MACROBLOCK_MOTION_BACKWARD) \
routine(&m_b_motion, (direction & MACROBLOCK_MOTION_FORWARD) ? m_mc->avg : m_mc->put); \
} while (0)
#define NEXT_MACROBLOCK \
do { \
m_offset += 16; \
if(m_offset == m_width) { \
m_dest[0] += 16 * m_stride; \
m_dest[1] += 4 * m_stride; \
m_dest[2] += 4 * m_stride; \
m_v_offset += 16; \
if(m_v_offset > m_limit_y) \
return; \
m_offset = 0; \
} \
} while (0)
void CMpeg2Decoder::mpeg2_init_fbuf(uint8_t* current_fbuf[3], uint8_t* forward_fbuf[3], uint8_t* backward_fbuf[3])
{
int offset, stride, height, bottom_field;
stride = m_width;
bottom_field = (m_picture_structure == BOTTOM_FIELD);
offset = bottom_field ? stride : 0;
height = m_height;
m_picture_dest[0] = current_fbuf[0] + offset;
m_picture_dest[1] = current_fbuf[1] + (offset >> 1);
m_picture_dest[2] = current_fbuf[2] + (offset >> 1);
m_f_motion.ref[0][0] = forward_fbuf[0] + offset;
m_f_motion.ref[0][1] = forward_fbuf[1] + (offset >> 1);
m_f_motion.ref[0][2] = forward_fbuf[2] + (offset >> 1);
m_b_motion.ref[0][0] = backward_fbuf[0] + offset;
m_b_motion.ref[0][1] = backward_fbuf[1] + (offset >> 1);
m_b_motion.ref[0][2] = backward_fbuf[2] + (offset >> 1);
if(m_picture_structure != FRAME_PICTURE)
{
m_dmv_offset = bottom_field ? 1 : -1;
m_f_motion.ref2[0] = m_f_motion.ref[bottom_field];
m_f_motion.ref2[1] = m_f_motion.ref[!bottom_field];
m_b_motion.ref2[0] = m_b_motion.ref[bottom_field];
m_b_motion.ref2[1] = m_b_motion.ref[!bottom_field];
offset = stride - offset;
if(m_second_field && (m_coding_type != B_TYPE))
forward_fbuf = current_fbuf;
m_f_motion.ref[1][0] = forward_fbuf[0] + offset;
m_f_motion.ref[1][1] = forward_fbuf[1] + (offset >> 1);
m_f_motion.ref[1][2] = forward_fbuf[2] + (offset >> 1);
m_b_motion.ref[1][0] = backward_fbuf[0] + offset;
m_b_motion.ref[1][1] = backward_fbuf[1] + (offset >> 1);
m_b_motion.ref[1][2] = backward_fbuf[2] + (offset >> 1);
stride <<= 1;
height >>= 1;
}
m_stride = stride;
m_uv_stride = stride >> 1;
m_limit_x = 2 * m_width - 32;
m_limit_y_16 = 2 * height - 32;
m_limit_y_8 = 2 * height - 16;
m_limit_y = height - 16;
}
int CMpeg2Decoder::slice_init(int code)
{
int offset;
const MBAtab* mba;
m_dc_dct_pred[0] = m_dc_dct_pred[1] =
m_dc_dct_pred[2] = 128 << m_intra_dc_precision;
m_f_motion.pmv[0][0] = m_f_motion.pmv[0][1] = 0;
m_f_motion.pmv[1][0] = m_f_motion.pmv[1][1] = 0;
m_b_motion.pmv[0][0] = m_b_motion.pmv[0][1] = 0;
m_b_motion.pmv[1][0] = m_b_motion.pmv[1][1] = 0;
if(m_vertical_position_extension)
{
code += UBITS(bit_buf, 3) << 7;
DUMPBITS(3);
}
m_v_offset = (code - 1) * 16;
offset = (code - 1) * m_stride * 4;
m_dest[0] = m_picture_dest[0] + offset * 4;
m_dest[1] = m_picture_dest[1] + offset;
m_dest[2] = m_picture_dest[2] + offset;
m_quantizer_scale = get_quantizer_scale();
/* ignore intra_slice and all the extra data */
while(bit_buf & 0x80000000)
{
DUMPBITS(9);
NEEDBITS;
}
/* decode initial macroblock address increment */
offset = 0;
while(1)
{
if(bit_buf >= 0x08000000)
{
mba = MBA_5 + (UBITS(bit_buf, 6) - 2);
break;
}
else if(bit_buf >= 0x01800000)
{
mba = MBA_11 + (UBITS(bit_buf, 12) - 24);
break;
}
else
{
switch(UBITS(bit_buf, 12))
{
case 8: /* macroblock_escape */
offset += 33;
DUMPBITS(11);
NEEDBITS;
continue;
case 15: /* macroblock_stuffing (MPEG1 only) */
bit_buf &= 0xfffff;
DUMPBITS(11);
NEEDBITS;
continue;
default: /* error */
return 1;
}
}
}
DUMPBITS(mba->len + 1);
m_offset = (offset + mba->mba) << 4;
while(m_offset - m_width >= 0)
{
m_offset -= m_width;
m_dest[0] += 16 * m_stride;
m_dest[1] += 4 * m_stride;
m_dest[2] += 4 * m_stride;
m_v_offset += 16;
}
if(m_v_offset > m_limit_y)
return 1;
return 0;
}
void CMpeg2Decoder::mpeg2_slice(int code, const uint8_t* buffer)
{
m_bitstream_buf = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
m_bitstream_ptr = buffer + 4;
m_bitstream_bits = -16;
if(slice_init(code))
return;
while(1)
{
int macroblock_modes;
int mba_inc;
const MBAtab * mba;
NEEDBITS;
macroblock_modes = get_macroblock_modes();
/* maybe integrate MACROBLOCK_QUANT test into get_macroblock_modes ? */
if(macroblock_modes & MACROBLOCK_QUANT)
m_quantizer_scale = get_quantizer_scale();
if(macroblock_modes & MACROBLOCK_INTRA)
{
int DCT_offset, DCT_stride;
int offset;
uint8_t* dest_y;
if(m_concealment_motion_vectors)
{
if(m_picture_structure == FRAME_PICTURE) motion_fr_conceal();
else motion_fi_conceal();
}
else
{
m_f_motion.pmv[0][0] = m_f_motion.pmv[0][1] = 0;
m_f_motion.pmv[1][0] = m_f_motion.pmv[1][1] = 0;
m_b_motion.pmv[0][0] = m_b_motion.pmv[0][1] = 0;
m_b_motion.pmv[1][0] = m_b_motion.pmv[1][1] = 0;
}
if(macroblock_modes & DCT_TYPE_INTERLACED)
{
DCT_offset = m_stride;
DCT_stride = m_stride * 2;
}
else
{
DCT_offset = m_stride * 8;
DCT_stride = m_stride;
}
offset = m_offset;
dest_y = m_dest[0] + offset;
slice_intra_DCT(0, dest_y, DCT_stride);
slice_intra_DCT(0, dest_y + 8, DCT_stride);
slice_intra_DCT(0, dest_y + DCT_offset, DCT_stride);
slice_intra_DCT(0, dest_y + DCT_offset + 8, DCT_stride);
slice_intra_DCT(1, m_dest[1] + (offset >> 1), m_uv_stride);
slice_intra_DCT (2, m_dest[2] + (offset >> 1), m_uv_stride);
if(m_coding_type == D_TYPE)
{
NEEDBITS;
DUMPBITS(1);
}
}
else
{
if(m_picture_structure == FRAME_PICTURE)
{
switch((macroblock_modes >> 6) & 3) // macroblock_modes & MOTION_TYPE_MASK
{
case 0:
// non-intra mb without forward mv in a P picture //
m_f_motion.pmv[0][0] = 0;
m_f_motion.pmv[0][1] = 0;
m_f_motion.pmv[1][0] = 0;
m_f_motion.pmv[1][1] = 0;
MOTION_CALL(motion_zero, MACROBLOCK_MOTION_FORWARD);
break;
case 1: // MC_FIELD:
MOTION_CALL(motion_fr_field, macroblock_modes);
break;
case 2: // MC_FRAME:
if(m_mpeg1) MOTION_CALL(motion_mp1, macroblock_modes);
else MOTION_CALL (motion_fr_frame, macroblock_modes);
break;
case 3: // MC_DMV:
MOTION_CALL(motion_fr_dmv, MACROBLOCK_MOTION_FORWARD);
break;
default:
__assume(0);
}
}
else
{
switch((macroblock_modes >> 6) & 3) // macroblock_modes & MOTION_TYPE_MASK
{
case 0:
/* non-intra mb without forward mv in a P picture */
m_f_motion.pmv[0][0] = 0;
m_f_motion.pmv[0][1] = 0;
m_f_motion.pmv[1][0] = 0;
m_f_motion.pmv[1][1] = 0;
MOTION_CALL(motion_zero, MACROBLOCK_MOTION_FORWARD);
break;
case 1: // MC_FIELD
MOTION_CALL(motion_fi_field, macroblock_modes);
break;
case 2: // MC_16X8
MOTION_CALL(motion_fi_16x8, macroblock_modes);
break;
case 3: // MC_DMV
MOTION_CALL(motion_fi_dmv, MACROBLOCK_MOTION_FORWARD);
break;
default:
__assume(0);
}
}
if(macroblock_modes & MACROBLOCK_PATTERN)
{
int coded_block_pattern;
int DCT_offset, DCT_stride;
int offset;
uint8_t* dest_y;
if(macroblock_modes & DCT_TYPE_INTERLACED)
{
DCT_offset = m_stride;
DCT_stride = m_stride * 2;
}
else
{
DCT_offset = m_stride * 8;
DCT_stride = m_stride;
}
coded_block_pattern = get_coded_block_pattern();
offset = m_offset;
dest_y = m_dest[0] + offset;
if(coded_block_pattern & 0x20)
slice_non_intra_DCT(dest_y, DCT_stride);
if(coded_block_pattern & 0x10)
slice_non_intra_DCT(dest_y + 8, DCT_stride);
if(coded_block_pattern & 0x08)
slice_non_intra_DCT(dest_y + DCT_offset, DCT_stride);
if(coded_block_pattern & 0x04)
slice_non_intra_DCT(dest_y + DCT_offset + 8, DCT_stride);
if(coded_block_pattern & 0x2)
slice_non_intra_DCT(m_dest[1] + (offset >> 1), m_uv_stride);
if(coded_block_pattern & 0x1)
slice_non_intra_DCT(m_dest[2] + (offset >> 1), m_uv_stride);
}
m_dc_dct_pred[0] =
m_dc_dct_pred[1] =
m_dc_dct_pred[2] = 128 << m_intra_dc_precision;
}
NEXT_MACROBLOCK;
NEEDBITS;
mba_inc = 0;
while(1)
{
if(bit_buf >= 0x10000000)
{
mba = MBA_5 + (UBITS(bit_buf, 5) - 2);
break;
}
else if(bit_buf >= 0x03000000)
{
mba = MBA_11 + (UBITS(bit_buf, 11) - 24);
break;
}
else
{
switch(UBITS(bit_buf, 11))
{
case 8: /* macroblock_escape */
mba_inc += 33;
/* pass through */
case 15: /* macroblock_stuffing (MPEG1 only) */
DUMPBITS(11);
NEEDBITS;
continue;
default: /* end of slice, or error */
return;
}
}
}
DUMPBITS(mba->len);
mba_inc += mba->mba;
if(mba_inc)
{
m_dc_dct_pred[0] =
m_dc_dct_pred[1] =
m_dc_dct_pred[2] = 128 << m_intra_dc_precision;
if(m_coding_type == P_TYPE)
{
m_f_motion.pmv[0][0] = m_f_motion.pmv[0][1] = 0;
m_f_motion.pmv[1][0] = m_f_motion.pmv[1][1] = 0;
do {
MOTION_CALL(motion_zero, MACROBLOCK_MOTION_FORWARD);
NEXT_MACROBLOCK;
} while(--mba_inc);
}
else
{
do {
MOTION_CALL (motion_reuse, macroblock_modes);
NEXT_MACROBLOCK;
} while(--mba_inc);
}
}
}
}
#undef bit_buf
#undef bits
#undef bit_ptr
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
CMpeg2Info::CMpeg2Info()
{
m_sequence = NULL;
m_gop = NULL;
Reset();
}
CMpeg2Info::~CMpeg2Info()
{
}
void CMpeg2Info::Reset()
{
m_current_picture = m_current_picture_2nd = NULL;
m_display_picture = m_display_picture_2nd = NULL;
m_current_fbuf = m_display_fbuf = m_discard_fbuf = NULL;
m_user_data = NULL;
m_user_data_len = 0;
}