/* * Copyright (C) 2000-2003 Michel Lespinasse * Copyright (C) 1999-2000 Aaron Holtzman * * 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 #include #include #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 (c) static void mpeg2_idct_init_c(); static void mpeg2_idct_copy_c(int16_t* block, uint8_t* dest, const int stride); static void mpeg2_idct_add_c(const int last, int16_t* block, uint8_t* dest, const int stride); // mc (c) static void MC_c(uint8_t* dest, const uint8_t* ref, const int stride, int height); extern mpeg2_mc_t mpeg2_mc_c; // 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) #ifndef _WIN64 __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 } #else 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; #endif 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]; sequence->display_width = sequence->picture_width = i >> 12; if(!sequence->display_width) return 1; sequence->display_height = sequence->picture_height = i & 0xfff; if(!sequence->display_height) 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) // EDIT2: vbv_buffer_size can be ignored as well, not used by libmpeg2 m_sequence.byte_rate = sequence->byte_rate; m_sequence.vbv_buffer_size = sequence->vbv_buffer_size; 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->width = (sequence->width + 31) & ~31; 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; } #ifndef _WIN64 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 #endif { 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; } 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; }