📄 mp4_decode.cpp
字号:
/*****************************************************************************
*
* This program 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.
*
* This program 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
*
*****************************************************************************
*
* Authors:
*
* Andrea Graziani (Ag): Original source code (Open Divx Decoder 0.4a).
* Marc Dukette (Md) and
* Pedro Mateu (Pm) and
* Gabor Kovacs (Kg) Heavily modified and optimized code
* Michal Bacik Porting into C++, optimizations
*
****************************************************************************/
#include "Util.h"
#include "SoftIdct.h"
#include "profiling.h"
#include "VideoCodec.h"
#include "C_buffer.h"
//----------------------------
#define MPEG4_ERROR_QPEL 0x200
#define MPEG4_ERROR_INTERLACE 0x201
#define MPEG4_ERROR_GMC 0x202
#define MPEG4_ERROR_PARTITIONING 0x205
#define POSX(pos) ((pos) & (MAX_MACROBLOCKS_X-1))
#define POSY(pos) ((pos) >> MB_X2)
// maximun picture size in macroblocks (16x16)
// example MB_X2=6 -> 2^6=64 macroblocks -> 1024 pixels
#define MB_X2 6
#define MB_Y2 6
#define MAX_MACROBLOCKS_X (1<<MB_X2)
#define MAX_MACROBLOCKS_Y (1<<MB_Y2)
#define DC_LUM_MASK ((MAX_MACROBLOCKS_X*2)*4-1)
#define DC_CHR_MASK (MAX_MACROBLOCKS_X*2-1)
//----------------------------
#define MAKE_MOVEMENT_VECTOR_PAIR(x, y) (((y)<<16) | ((x)&0xffff))
#define MOVE_VECTOR_X(a) short(a)
#define MOVE_VECTOR_Y(a) ((a)>>16)
//----------------------------
//macros for fast bit-access in frequently-used locations
#define GetBits1() ((bits << bitpos++) < 0)
#define LoadBits() \
if(bitpos >= 8){ \
do{ \
bits = (bits << 8) | *bit_ptr++; \
bitpos -= 8; \
}while(bitpos >= 8); \
}
#define ShowBits(n) ((dword)(bits << bitpos) >> (32-(n)))
#define FlushBits(n) bitpos += n
//----------------------------
#if 0
static int Divide(int a, int b){
return ((a>0) ? (a+(b>>1))/b : (a-(b>>1))/b);
}
#else
//optimized division for most common divisors
// (using multiplication by reciprocal in 12.20 fixed-point format)
#define RET_DIV(a, N) return (a*N+524288) >> 20;
#define RET_SHR(a, N, S) return (a+N) >> S;
static int Divide(int a, int b){
switch(b){
case 1: return a;
case 2: RET_SHR(a, 1, 1);
case 4: RET_SHR(a, 2, 2);
case 8: RET_SHR(a, 4, 3);
case 16: RET_SHR(a, 8, 4);
case 32: RET_SHR(a, 16, 5);
case 3: RET_DIV(a, 349525);
case 5: RET_DIV(a, 209715);
case 6: RET_DIV(a, 174763);
case 7: RET_DIV(a, 149797);
case 9: RET_DIV(a, 116509);
case 10: RET_DIV(a, 104858);
case 11: RET_DIV(a, 95325);
case 12: RET_DIV(a, 87382);
case 13: RET_DIV(a, 80660);
case 14: RET_DIV(a, 74899);
case 15: RET_DIV(a, 69905);
case 17: RET_DIV(a, 61681);
case 18: RET_DIV(a, 58255);
case 19: RET_DIV(a, 55189);
case 20: RET_DIV(a, 52429);
case 21: RET_DIV(a, 49933);
case 22: RET_DIV(a, 47663);
case 23: RET_DIV(a, 45591);
case 24: RET_DIV(a, 43691);
case 25: RET_DIV(a, 41943);
case 26: RET_DIV(a, 40330);
case 27: RET_DIV(a, 38837);
case 28: RET_DIV(a, 37450);
case 29: RET_DIV(a, 36158);
case 30: RET_DIV(a, 34953);
case 31: RET_DIV(a, 33825);
}
if(a>0)
a += b>>1;
else
a -= b>>1;
return a/b;
}
#endif
//----------------------------
static dword FindHighestBit(dword mask){
int base = 0;
if(mask&0xffff0000){
base = 16;
mask >>= 16;
}
if(mask&0x0000ff00){
base += 8;
mask >>= 8;
}
if(mask&0x000000f0){
base += 4;
mask >>= 4;
}
static const int lut[] = {-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3};
return base + lut[mask];
}
//----------------------------
static void Clear32(void* p){
int *i = (int*)p;
i[0] = 0; i[1] = 0; i[2] = 0; i[3] = 0;
i[4] = 0; i[5] = 0; i[6] = 0; i[7] = 0;
}
//----------------------------
//----------------------------
struct S_bit_reader{
int bits, pos;
const byte *ptr, *bitend;
void Init(const byte *stream, int len){
bits = 0;
pos = 32;
ptr = stream;
bitend = stream+len+6; //adding more just to be safe
Flush(0);
}
inline void Flush(int n){
pos += n;
}
//----------------------------
// n=1..24 (or ..32 after bytealign)
inline dword Show(int n) const{
return (dword)(bits << pos) >> (32-n);
}
//----------------------------
inline int Get(int n){
int i = Show(n);
Flush(n);
return i;
}
//----------------------------
inline bool Get1(){
return Get(1);
}
inline int BitsToNextByte() const{
return 8-(pos & 7);
}
inline bool Eof() const{
return (ptr >= bitend);
}
inline int ShowLarge(int n){
int i = Show(n);
i |= *ptr >> (40-n-pos);
return i;
}
inline void Rewind(const byte *p){
pos = 32;
ptr = p;
}
inline void ByteAlign(){
pos = (pos + 7) & ~7;
}
void Load();
//----------------------------
int GetCodedBlockPatternLuminance();
int GetMCodedBlockPatternChrominance_i();
int GetMCodedBlockPatternChrominance_p();
void GetQuantMatrix(byte m[2*8*8]);
//----------------------------
// Get single move value from bitstream.
int GetMoveData(int fcode);
//----------------------------
// Get movement vector from stream. The vector is stored in stream as delta, so pass in previous value, which is added to read values.
int GetMovementVectorPair(int fcode, int prev_vector_pair);
int GetDCsizeLum();
int GetDCsizeChr();
int GetDCdiff(int dct_dc_size);
};
//----------------------------
void S_bit_reader::Load(){
if(pos >= 8){
do{
bits = (bits << 8) | *ptr++;
pos -= 8;
}while(pos >= 8);
}
}
//----------------------------
// Meaning of CBPY (Coded Block Pattern-luminance), indicates which blocks within a macroblock contain coded coefficients.
// First byte encodes bits 0-3 associated with 2x2 luminance (Y) blocks in one 16x16 maxroblock.
// Second byte encodes number of bits representing this information in the bitstream.
static const byte tab_coded_block_pattern_luminance[] = {
0, 0, 0, 0, 6, 6, 9,6, 8,5, 8,5, 4,5, 4,5,
2, 5, 2, 5, 1, 5, 1,5, 0,4, 0,4, 0,4, 0,4,
12,4, 12,4, 12,4, 12,4, 10,4, 10,4, 10,4, 10,4,
14,4, 14,4, 14,4, 14,4, 5,4, 5,4, 5,4, 5,4,
13,4, 13,4, 13,4, 13,4, 3,4, 3,4, 3,4, 3,4,
11,4, 11,4, 11,4, 11,4, 7,4, 7,4, 7,4, 7,4
};
//----------------------------
int S_bit_reader::GetCodedBlockPatternLuminance(){
//max 6 bits
int code = Show(6);
if(code < 2)
return -1;
if(code >= 0x30){
Flush(2);
return 0xf;
}
code *= 2;
Flush(tab_coded_block_pattern_luminance[code+1]);
return tab_coded_block_pattern_luminance[code];
}
//----------------------------
static const byte MCBPCtabIntra[] = {
0, 0, //-1,0
20,6, 36, 6, 52,6, 4,4, 4, 4, 4, 4,
4, 4, 19, 3, 19,3, 19,3, 19, 3, 19, 3,
19,3, 19, 3, 19,3, 35,3, 35, 3, 35, 3,
35,3, 35, 3, 35,3, 35,3, 35, 3, 51, 3,
51,3, 51, 3, 51,3, 51,3, 51, 3, 51, 3,
51,3
};
//----------------------------
int S_bit_reader::GetMCodedBlockPatternChrominance_i(){
//max 9bits
int code = Show(9);
if(code == 1){
Flush(9); // stuffing
return 0;
}
if(code < 8)
return -1;
code >>= 3;
if(code >= 32){
Flush(1);
return 3;
}
code *= 2;
Flush(MCBPCtabIntra[code+1]);
return MCBPCtabIntra[code];
}
//----------------------------
static const byte MCBPCtabInter[] = {
0,0, //-1,0
0,9, 52,9, 36,9, 20,9, 49,9, 35,8, 35,8, 19,8, 19,8,
50,8, 50,8, 51,7, 51,7, 51,7, 51,7, 34,7, 34,7, 34,7,
34,7, 18,7, 18,7, 18,7, 18,7, 33,7, 33,7, 33,7, 33,7,
17,7, 17,7, 17,7, 17,7, 4,6, 4,6, 4,6, 4,6, 4,6,
4,6, 4,6, 4,6, 48,6, 48,6, 48,6, 48,6, 48,6, 48,6,
48,6, 48,6, 3,5, 3,5, 3,5, 3,5, 3,5, 3,5, 3,5,
3,5, 3,5, 3,5, 3,5, 3,5, 3,5, 3,5, 3,5, 3,5,
32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 32,4,
32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 32,4,
32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 32,4,
32,4, 32,4, 32,4, 32,4, 32,4, 16,4, 16,4, 16,4, 16,4,
16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 16,4,
16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 16,4,
16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 16,4,
16,4, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3,
2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3,
2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3,
2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3,
2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3,
2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3,
2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3,
2,3, 2,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3,
1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3,
1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3,
1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3,
1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3,
1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3,
1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3,
1,3, 1,3, 1,3
};
//----------------------------
int S_bit_reader::GetMCodedBlockPatternChrominance_p(){
//max 9bits
int code = Show(9);
if(code == 0)
return -1;
if(code >= 256){
Flush(1);
return 0;
}
code *= 2;
Flush(MCBPCtabInter[code+1]);
return MCBPCtabInter[code];
}
//----------------------------
static const byte scan_table[3][64] = {
{
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
},
{
0, 1, 2, 3, 8, 9, 16, 17,
10, 11, 4, 5, 6, 7, 15, 14,
13, 12, 19, 18, 24, 25, 32, 33,
26, 27, 20, 21, 22, 23, 28, 29,
30, 31, 34, 35, 40, 41, 48, 49,
42, 43, 36, 37, 38, 39, 44, 45,
46, 47, 50, 51, 56, 57, 58, 59,
52, 53, 54, 55, 60, 61, 62, 63
},
{
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
}
};
//----------------------------
void S_bit_reader::GetQuantMatrix(byte* m){
int i = 0;
int last, value = 0;
do{
last = value;
Load();
value = Get(8);
m[scan_table[0][i++]] = (byte)value;
}while(value!=0 && i<64);
i--;
while(i < 64)
m[scan_table[0][i++]] = (byte)last;
}
//----------------------------
#define _M(mv, bits) (mv<<8) | (bits)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -