gps/GPSResources/tcpmp/mpeg1/mpeg_decode.c

1328 lines
33 KiB
C
Executable File

/*****************************************************************************
*
* 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
*
* $Id: mpeg_decode.c 603 2006-01-19 13:00:33Z picard $
*
* The Core Pocket Media Player
* Copyright (c) 2004-2005 Gabor Kovacs
*
****************************************************************************/
#include "../common/common.h"
#include "mpeg1.h"
#include "mpeg_decode.h"
#include "mpeg_stream.h"
static _CONST uint8_t zigzag[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
};
static int UpdateSize(mpeg_decode* dec)
{
if (dec->Codec.IDCT.Width > (MB_X-1)*16 || dec->Codec.IDCT.Height > (MB_Y-1)*16)
{
if (!dec->ErrorShowed)
{
dec->ErrorShowed = 1;
ShowError(dec->Codec.Node.Class,VOUT_CLASS,VOUT_ERROR_SIZE,(MB_X-1)*16,(MB_Y-1)*16);
}
return ERR_NOT_SUPPORTED;
}
dec->mb_xsize = (dec->Codec.IDCT.Width + 15) / 16;
dec->mb_ysize = (dec->Codec.IDCT.Height + 15) / 16;
dec->pos_end = dec->mb_ysize * MB_X;
return ERR_NONE;
}
static int Discontinuity( mpeg_decode* dec )
{
dec->Frame = 0;
return ERR_NONE;
}
static int Flush( mpeg_decode* dec )
{
dec->StartState = -1;
dec->SliceFound = 0;
return ERR_NONE;
}
static int UpdateInput( mpeg_decode* dec )
{
int Result = ERR_NONE;
IDCT_BLOCK_PREPARE(dec,dec->blockptr);
dec->mb_xsize = 0;
dec->mb_ysize = 0;
dec->pos_end = 0;
dec->refframe = 0;
dec->Frame = 0;
dec->ValidSeq = 0;
dec->ErrorShowed = 0;
dec->OnlyIVOP = 1;
memcpy(dec->zigzag,zigzag,sizeof(zigzag));
if (dec->Codec.In.Format.Type == PACKET_VIDEO)
Result = CodecIDCTSetFormat(&dec->Codec,PF_YUV420,dec->Codec.In.Format.Format.Video.Width,dec->Codec.In.Format.Format.Video.Height,
dec->Codec.In.Format.Format.Video.Width,dec->Codec.In.Format.Format.Video.Height,
dec->Codec.In.Format.Format.Video.Aspect);
return Result;
}
static bool_t FindNext( mpeg_decode* dec )
{
const uint8_t* Ptr = dec->Codec.Buffer.Data;
int Len = dec->Codec.Buffer.WritePos;
int Pos = dec->Codec.FrameEnd;
int32_t v = dec->StartState;
for (;Pos<Len;++Pos)
{
v = (v<<8) | Ptr[Pos];
if ((v & ~0xFF) == 0x100)
{
if (v < SLICE_MIN_START_CODE || v > SLICE_MAX_START_CODE)
{
if (dec->SliceFound)
{
dec->Codec.FrameEnd = Pos-3;
dec->SliceFound = 0;
dec->StartState = -1;
return 1;
}
}
else
dec->SliceFound=1;
}
}
dec->Codec.FrameEnd = Pos;
dec->StartState = v;
return 0;
}
static _CONST int FrameRate[16] =
{
0, 24000, 24024, 25025,
30000, 30030, 50050, 60000,
60060, 15015, 5005, 10010,
12012, 15015, 25025, 25025,
};
static _CONST int8_t MPEG1_IntraMatrix[64] =
{
8, 16, 19, 22, 26, 27, 29, 34,
16, 16, 22, 24, 27, 29, 34, 37,
19, 22, 26, 27, 29, 34, 34, 38,
22, 22, 26, 27, 29, 34, 37, 40,
22, 26, 27, 29, 32, 35, 40, 48,
26, 27, 29, 32, 35, 40, 48, 58,
26, 27, 29, 34, 38, 46, 56, 69,
27, 29, 35, 38, 46, 56, 69, 83
};
static void initbits(mpeg_decode* dec,const uint8_t *stream, int len)
{
dec->bits = 0;
dec->bitpos = 32;
dec->bitptr = stream;
dec->bitend = stream+len+4;
}
static void loadbits( mpeg_decode* dec )
{
int bitpos = dec->bitpos;
loadbits_pos(dec,bitpos);
dec->bitpos = bitpos;
}
#ifndef NDEBUG
static int showbitslarge( mpeg_decode* dec, int n )
{
int i = showbits(dec,n);
i |= *dec->bitptr >> (40-n-dec->bitpos);
return i;
}
#endif
static void Sequence( mpeg_decode* dec )
{
int i;
loadbits(dec);
dec->width = getbits(dec,12);
dec->height = getbits(dec,12);
loadbits(dec);
dec->aspect = getbits(dec,4);
dec->Codec.In.Format.PacketRate.Den = 1001;
dec->Codec.In.Format.PacketRate.Num = FrameRate[getbits(dec,4)];
dec->Codec.FrameTime = Scale(TICKSPERSEC,dec->Codec.In.Format.PacketRate.Den,dec->Codec.In.Format.PacketRate.Num);
loadbits(dec);
dec->Codec.In.Format.ByteRate = getbits(dec,18) * 50;
if (dec->Codec.In.Format.ByteRate > 8*1024*1024)
dec->Codec.In.Format.ByteRate = 0;
flushbits(dec,1); // marker
flushbits(dec,10); // vbv_buffer_size
flushbits(dec,1);
loadbits(dec);
if (getbits1(dec))
{
for (i=0;i<64;i++)
{
loadbits(dec);
dec->IntraMatrix[i] = (uint8_t)getbits(dec,8);
}
}
else
{
for (i=0;i<64;i++)
dec->IntraMatrix[i] = MPEG1_IntraMatrix[dec->zigzag[i]];
}
if (getbits1(dec))
{
for (i=0;i<64;i++)
{
loadbits(dec);
dec->InterMatrix[i] = (uint8_t)getbits(dec, 8);
}
}
else
{
for (i=0;i<64;i++)
dec->InterMatrix[i] = 16;
}
dec->ValidSeq = 1;
}
static void Picture( mpeg_decode* dec )
{
static const int16_t aspect[16] =
{
0,10000, 6735, 7031,
7615, 8055, 8437, 8935,
9157, 9815,10255,10695,
10950,11575,12015, 0,
};
if (!dec->Codec.In.Format.Format.Video.Aspect && aspect[dec->aspect])
dec->Codec.In.Format.Format.Video.Aspect = Scale(ASPECT_ONE,10000,aspect[dec->aspect]);
CodecIDCTSetFormat(&dec->Codec,PF_YUV420,dec->width,dec->height,dec->width,dec->height,dec->Codec.In.Format.Format.Video.Aspect);
flushbits(dec,10); // temporal ref
loadbits(dec);
dec->prediction_type = getbits(dec,3);
flushbits(dec,16); // non constant bit rate
loadbits(dec);
if (dec->prediction_type == P_VOP || dec->prediction_type == B_VOP)
{
dec->full_pixel[0] = getbits(dec,1);
dec->fcode[0] = getbits(dec,3)-1;
}
if (dec->prediction_type == B_VOP)
{
dec->full_pixel[1] = getbits(dec,1);
dec->fcode[1] = getbits(dec,3)-1;
}
dec->frame_state = 1;
DEBUG_MSG1(DEBUG_VCODEC,T("MPEG Picture:%d"),dec->prediction_type);
}
static int StartFrame( mpeg_decode* dec )
{
int result = ERR_NONE;
switch (dec->prediction_type)
{
case P_VOP:
if (dec->Frame < 1)
{
if (dec->Codec.Dropping)
dec->Codec.IDCT.Ptr->Null(dec->Codec.IDCT.Ptr,NULL,0);
return ERR_INVALID_DATA;
}
// no break
case I_VOP:
dec->refframe ^= 1;
if (dec->OnlyIVOP && dec->Codec.State.DropLevel)
{
dec->Codec.IDCT.Ptr->Null(dec->Codec.IDCT.Ptr,NULL,0);
return ERR_NONE;
}
if (dec->Codec.IDCT.Count>=3)
dec->Codec.State.DropLevel = 0;
if (dec->Codec.IDCT.Count<3 || dec->Frame==0)
dec->Codec.Show = dec->refframe; // show this refframe
else
dec->Codec.Show = dec->refframe ^ 1; // show last refframe
if (dec->prediction_type == I_VOP)
{
result = dec->Codec.IDCT.Ptr->FrameStart(dec->Codec.IDCT.Ptr,dec->Frame,&dec->bufframe,dec->refframe,-1,-1,dec->Codec.Show,0);
}
else
{
dec->OnlyIVOP = 0;
result = dec->Codec.IDCT.Ptr->FrameStart(dec->Codec.IDCT.Ptr,dec->Frame,&dec->bufframe,dec->refframe,dec->refframe^1,-1,dec->Codec.Show,dec->Codec.State.DropLevel);
}
if (result != ERR_NONE)
dec->Codec.Show = -1;
break;
case B_VOP:
if (dec->Frame < 2)
{
if (dec->Codec.Dropping)
dec->Codec.IDCT.Ptr->Null(dec->Codec.IDCT.Ptr,NULL,0);
return ERR_INVALID_DATA;
}
if (dec->Codec.State.DropLevel)
{
dec->Codec.IDCT.Ptr->Null(dec->Codec.IDCT.Ptr,NULL,0);
return ERR_NONE;
}
if (dec->Codec.IDCT.Count<3)
{
CodecIDCTSetCount(&dec->Codec,3);
if (dec->Codec.IDCT.Count<3)
{
dec->Codec.IDCT.Ptr->Null(dec->Codec.IDCT.Ptr,NULL,0);
return ERR_INVALID_DATA;
}
}
dec->OnlyIVOP = 0;
dec->Codec.Show = 2;
result = dec->Codec.IDCT.Ptr->FrameStart(dec->Codec.IDCT.Ptr,-dec->Frame,&dec->bufframe,2,dec->refframe^1,dec->refframe,2,0);
break;
default:
result = ERR_INVALID_DATA;
break;
}
return result;
}
// max 9 bits
static INLINE int getDCsizeLum( mpeg_decode* dec )
{
int i,code;
if (!getbits1(dec))
return getbits(dec,1)+1;
if (!getbits1(dec))
return getbits(dec,1)*3;
code = showbits(dec,7);
for (i=1;i<8;i++,code<<=1)
if (!(code & 64))
{
flushbits(dec,i);
return i+3;
}
flushbits(dec,7);
return 11;
}
// max 10 bits
static INLINE int getDCsizeChr( mpeg_decode* dec )
{
int i,code;
if (!getbits1(dec))
return getbits(dec,1);
code = showbits(dec,9);
for (i=1;i<10;i++,code<<=1)
if (!(code & 256))
{
flushbits(dec,i);
return i+1;
}
flushbits(dec,9);
return 11;
}
// max 11bits
static INLINE int getDCdiff(int dct_dc_size, mpeg_decode* dec)
{
int code = showbits(dec,32); //we need only dct_dc_size bits (but in the higher bits)
int adj = 0;
flushbits(dec,dct_dc_size);
if (code >= 0)
adj = (-1 << dct_dc_size) + 1;
return adj + ((uint32_t)code >> (32-dct_dc_size));
}
#define TABLE_1 0
#define TABLE_2 252
#define TABLE_3 252+112
#define TABLE_END 252+112+112
static _CONST uint16_t vld_mpeg1[252+112+112] =
{
0x403e,0x403e,0x403e,0x403e,0x5082,0x5082,0x5241,0x5241,
0x5004,0x5004,0x5201,0x5201,0x41c1,0x41c1,0x41c1,0x41c1,
0x4181,0x4181,0x4181,0x4181,0x4042,0x4042,0x4042,0x4042,
0x4141,0x4141,0x4141,0x4141,0x6341,0x6006,0x6301,0x62c1,
0x60c2,0x6043,0x6005,0x6281,0x3003,0x3003,0x3003,0x3003,
0x3003,0x3003,0x3003,0x3003,0x3101,0x3101,0x3101,0x3101,
0x3101,0x3101,0x3101,0x3101,0x30c1,0x30c1,0x30c1,0x30c1,
0x30c1,0x30c1,0x30c1,0x30c1,0x2002,0x2002,0x2002,0x2002,
0x2002,0x2002,0x2002,0x2002,0x2002,0x2002,0x2002,0x2002,
0x2002,0x2002,0x2002,0x2002,0x2081,0x2081,0x2081,0x2081,
0x2081,0x2081,0x2081,0x2081,0x2081,0x2081,0x2081,0x2081,
0x2081,0x2081,0x2081,0x2081,0x1041,0x1041,0x1041,0x1041,
0x1041,0x1041,0x1041,0x1041,0x1041,0x1041,0x1041,0x1041,
0x1041,0x1041,0x1041,0x1041,0x1041,0x1041,0x1041,0x1041,
0x1041,0x1041,0x1041,0x1041,0x1041,0x1041,0x1041,0x1041,
0x1041,0x1041,0x1041,0x1041,0x003f,0x003f,0x003f,0x003f,
0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,
0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,
0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,
0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,
0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,
0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,
0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,0x003f,
0x003f,0x003f,0x003f,0x003f,0x0001,0x0001,0x0001,0x0001,
0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,
0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,
0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,
0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,
0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,
0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,
0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,
0x0001,0x0001,0x0001,0x0001,0xb282,0xb242,0xb143,0xb0c4,
0xb085,0xb047,0xb046,0xb00f,0xb00e,0xb00d,0xb00c,0xb681,
0xb641,0xb601,0xb5c1,0xb581,0xa00b,0xa00b,0xa202,0xa202,
0xa103,0xa103,0xa00a,0xa00a,0xa084,0xa084,0xa1c2,0xa1c2,
0xa541,0xa541,0xa501,0xa501,0xa009,0xa009,0xa4c1,0xa4c1,
0xa481,0xa481,0xa045,0xa045,0xa0c3,0xa0c3,0xa008,0xa008,
0xa182,0xa182,0xa441,0xa441,0x8401,0x8401,0x8401,0x8401,
0x8401,0x8401,0x8401,0x8401,0x8142,0x8142,0x8142,0x8142,
0x8142,0x8142,0x8142,0x8142,0x8007,0x8007,0x8007,0x8007,
0x8007,0x8007,0x8007,0x8007,0x8083,0x8083,0x8083,0x8083,
0x8083,0x8083,0x8083,0x8083,0x8044,0x8044,0x8044,0x8044,
0x8044,0x8044,0x8044,0x8044,0x83c1,0x83c1,0x83c1,0x83c1,
0x83c1,0x83c1,0x83c1,0x83c1,0x8381,0x8381,0x8381,0x8381,
0x8381,0x8381,0x8381,0x8381,0x8102,0x8102,0x8102,0x8102,
0x8102,0x8102,0x8102,0x8102,0xe052,0xe051,0xe050,0xe04f,
0xe183,0xe402,0xe3c2,0xe382,0xe342,0xe302,0xe2c2,0xe7c1,
0xe781,0xe741,0xe701,0xe6c1,0xd028,0xd028,0xd027,0xd027,
0xd026,0xd026,0xd025,0xd025,0xd024,0xd024,0xd023,0xd023,
0xd022,0xd022,0xd021,0xd021,0xd020,0xd020,0xd04e,0xd04e,
0xd04d,0xd04d,0xd04c,0xd04c,0xd04b,0xd04b,0xd04a,0xd04a,
0xd049,0xd049,0xd048,0xd048,0xc01f,0xc01f,0xc01f,0xc01f,
0xc01e,0xc01e,0xc01e,0xc01e,0xc01d,0xc01d,0xc01d,0xc01d,
0xc01c,0xc01c,0xc01c,0xc01c,0xc01b,0xc01b,0xc01b,0xc01b,
0xc01a,0xc01a,0xc01a,0xc01a,0xc019,0xc019,0xc019,0xc019,
0xc018,0xc018,0xc018,0xc018,0xc017,0xc017,0xc017,0xc017,
0xc016,0xc016,0xc016,0xc016,0xc015,0xc015,0xc015,0xc015,
0xc014,0xc014,0xc014,0xc014,0xc013,0xc013,0xc013,0xc013,
0xc012,0xc012,0xc012,0xc012,0xc011,0xc011,0xc011,0xc011,
0xc010,0xc010,0xc010,0xc010
};
// size:4 run:6 level:6
// size:4 escape 62
// size:4 end 63
#define vld_code \
code = showbits_pos(dec,bitpos,16); \
if (code >> 10) \
code = (code >> 8) - 4 + TABLE_1; \
else if (code >> 7) \
code = (code >> 3) - 16 + TABLE_2; \
else /* if (code >= 16) but we don't care about invalid huffman codes */ \
code = code - 16 + TABLE_3; \
code = table[code]; \
flushbits_pos(dec,bitpos,2+(code >> 12));
static void blockIntra( mpeg_decode* dec, int pos )
{
int j;
idct_block_t *block;
const uint16_t *table = vld_mpeg1;
int qscale;
dec->Codec.IDCT.Ptr->Process(dec->Codec.IDCT.Ptr,POSX(pos),POSY(pos));
block = dec->blockptr;
qscale = dec->qscale;
for (j=0;j<6;++j)
{
int bitpos;
int len;
ClearBlock(block);
loadbits(dec);
{
int dct_dc_size, dct_dc_diff;
dct_dc_diff = 0;
dct_dc_size = j<4 ? getDCsizeLum(dec) : getDCsizeChr(dec); //max11bit
if (dct_dc_size)
dct_dc_diff = getDCdiff(dct_dc_size,dec);
dct_dc_size = j<4 ? 0 : j-4+1;
DEBUG_MSG2(DEBUG_VCODEC2,T("dc=%d diff=%d"), dec->last_dc[dct_dc_size]+dct_dc_diff, dct_dc_diff );
dct_dc_diff += dec->last_dc[dct_dc_size];
dec->last_dc[dct_dc_size] = dct_dc_diff;
*block = (idct_block_t)(dct_dc_diff << 3);
len = 1;
}
bitpos = dec->bitpos;
for (;;) // event vld
{
int code,level;
loadbits_pos(dec,bitpos);
code = showbits_pos(dec,bitpos,16);
vld_code;
level = code & 63;
if (level < 62)
{
level *= qscale;
code >>= 6;
code &= 63;
len += code; // run
if (len >= 64)
break;
code = dec->zigzag[len];
level *= dec->IntraMatrix[len];
level >>= 3;
level = (level-1)|1;
if (getbits1_pos(dec,bitpos))
level = -level;
block[code] = (idct_block_t)level;
++len;
}
else
{
if (level==63)
break;
// this value is escaped
loadbits_pos(dec,bitpos);
len += showbits_pos(dec,bitpos,6); flushbits_pos(dec,bitpos,6);
if (len >= 64)
break;
code = showbits_pos(dec,bitpos,8); flushbits_pos(dec,bitpos,8);
level = (code << 24) >> 24; //sign extend the lower 8 bits
code = dec->zigzag[len];
if (level == -128)
{
level = showbits_pos(dec,bitpos,8)-256; flushbits_pos(dec,bitpos,8);
}
else
if (level == 0)
{
level = showbits_pos(dec,bitpos,8); flushbits_pos(dec,bitpos,8);
}
if (level<0)
{
level= -level;
level *= qscale * dec->IntraMatrix[len];
level >>= 3;
level= (level-1)|1;
level= -level;
block[code] = (idct_block_t)level;
++len;
}
else
{
level *= qscale * dec->IntraMatrix[len];
level >>= 3;
level = (level-1)|1;
block[code] = (idct_block_t)level;
++len;
}
}
DEBUG_MSG2(DEBUG_VCODEC2,T("intra_block[%i] %i"), code, level );
}
dec->bitpos = bitpos;
dec->Codec.IDCT.Ptr->Intra8x8(dec->Codec.IDCT.Ptr,block,len,IDCTSCAN_ZIGZAG);
}
dec->fmv[0] = dec->bmv[0] = 0;
}
static INLINE int readqscale( mpeg_decode* dec )
{
return getbits(dec,5);
}
static _CONST uint8_t mcbp_p[32*2+128*2] =
{
0x00,0x00,0x08,0x39,0x08,0x2b,0x08,0x29,0x07,0x22,0x07,0x21,0x06,0x3f,0x06,0x24,
0x05,0x3e,0x05,0x02,0x05,0x3d,0x05,0x01,0x05,0x38,0x05,0x34,0x05,0x2c,0x05,0x1c,
0x05,0x28,0x05,0x14,0x05,0x30,0x05,0x0c,0x04,0x20,0x04,0x20,0x04,0x10,0x04,0x10,
0x04,0x08,0x04,0x08,0x04,0x04,0x04,0x04,0x03,0x3c,0x03,0x3c,0x03,0x3c,0x03,0x3c,
0x00,0x00,0x00,0x00,0x09,0x27,0x09,0x1b,0x09,0x3b,0x09,0x37,0x09,0x2f,0x09,0x1f,
0x08,0x3a,0x08,0x3a,0x08,0x36,0x08,0x36,0x08,0x2e,0x08,0x2e,0x08,0x1e,0x08,0x1e,
0x08,0x39,0x08,0x39,0x08,0x35,0x08,0x35,0x08,0x2d,0x08,0x2d,0x08,0x1d,0x08,0x1d,
0x08,0x26,0x08,0x26,0x08,0x1a,0x08,0x1a,0x08,0x25,0x08,0x25,0x08,0x19,0x08,0x19,
0x08,0x2b,0x08,0x2b,0x08,0x17,0x08,0x17,0x08,0x33,0x08,0x33,0x08,0x0f,0x08,0x0f,
0x08,0x2a,0x08,0x2a,0x08,0x16,0x08,0x16,0x08,0x32,0x08,0x32,0x08,0x0e,0x08,0x0e,
0x08,0x29,0x08,0x29,0x08,0x15,0x08,0x15,0x08,0x31,0x08,0x31,0x08,0x0d,0x08,0x0d,
0x08,0x23,0x08,0x23,0x08,0x13,0x08,0x13,0x08,0x0b,0x08,0x0b,0x08,0x07,0x08,0x07,
0x07,0x22,0x07,0x22,0x07,0x22,0x07,0x22,0x07,0x12,0x07,0x12,0x07,0x12,0x07,0x12,
0x07,0x0a,0x07,0x0a,0x07,0x0a,0x07,0x0a,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x06,
0x07,0x21,0x07,0x21,0x07,0x21,0x07,0x21,0x07,0x11,0x07,0x11,0x07,0x11,0x07,0x11,
0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x05,0x07,0x05,0x07,0x05,0x07,0x05,
0x06,0x3f,0x06,0x3f,0x06,0x3f,0x06,0x3f,0x06,0x3f,0x06,0x3f,0x06,0x3f,0x06,0x3f,
0x06,0x03,0x06,0x03,0x06,0x03,0x06,0x03,0x06,0x03,0x06,0x03,0x06,0x03,0x06,0x03,
0x06,0x24,0x06,0x24,0x06,0x24,0x06,0x24,0x06,0x24,0x06,0x24,0x06,0x24,0x06,0x24,
0x06,0x18,0x06,0x18,0x06,0x18,0x06,0x18,0x06,0x18,0x06,0x18,0x06,0x18,0x06,0x18
};
static _CONST uint8_t mb_type_p[64] =
{
0x00,0xd1,0xa9,0xa9,0xab,0xab,0xb0,0xb0,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,
0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,
0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a
};
static _CONST uint8_t mb_type_b[64] =
{
0x00,0xd1,0xcd,0xcb,0xaf,0xaf,0xb0,0xb0,0x82,0x82,0x82,0x82,0x8a,0x8a,0x8a,0x8a,
0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,
0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,
0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e
};
#define SKIP_1 0
#define SKIP_2 16
#define SKIP_3 (16+8)
#define SKIP_END (16+8+64)
static _CONST uint8_t skip[SKIP_END*2] =
{
0x0a,0x22,0x07,0x0c,0x04,0x06,0x04,0x05,0x03,0x04,0x03,0x04,0x03,0x03,0x03,0x03,
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x01,0x02,0x01,0x02,0x01,0x02,0x01,
0x07,0x0c,0x07,0x0b,0x07,0x0a,0x07,0x09,0x06,0x08,0x06,0x08,0x06,0x07,0x06,0x07,
0x0a,0x22,0x0a,0x22,0x0a,0x22,0x0a,0x22,0x0a,0x22,0x0a,0x22,0x0a,0x22,0x0a,0x22,
0x0a,0x21,0x0a,0x22,0x0a,0x22,0x0a,0x22,0x0a,0x22,0x0a,0x22,0x0a,0x22,0x0a,0x22,
0x0a,0x22,0x0a,0x22,0x0a,0x22,0x0a,0x22,0x0a,0x22,0x0a,0x22,0x0a,0x22,0x0a,0x22,
0x0a,0x20,0x0a,0x1f,0x0a,0x1e,0x0a,0x1d,0x0a,0x1c,0x0a,0x1b,0x0a,0x1a,0x0a,0x19,
0x0a,0x18,0x0a,0x17,0x0a,0x16,0x0a,0x15,0x09,0x14,0x09,0x14,0x09,0x13,0x09,0x13,
0x09,0x12,0x09,0x12,0x09,0x11,0x09,0x11,0x09,0x10,0x09,0x10,0x09,0x0f,0x09,0x0f,
0x07,0x0e,0x07,0x0e,0x07,0x0e,0x07,0x0e,0x07,0x0e,0x07,0x0e,0x07,0x0e,0x07,0x0e,
0x07,0x0d,0x07,0x0d,0x07,0x0d,0x07,0x0d,0x07,0x0d,0x07,0x0d,0x07,0x0d,0x07,0x0d
};
static INLINE void readskip( mpeg_decode* dec )
{
int i;
dec->skip = 0;
while (!getbits1(dec))
{
inlineloadbits(dec);
i = showbits(dec,10);
if (i >> 7)
i = (i >> 6) + SKIP_1;
else
if (i >> 6)
i = (i >> 3)-8 + SKIP_2;
else
i = i + SKIP_3;
i <<= 1;
flushbits(dec,skip[i]);
i = skip[i+1];
if (i<33)
{
dec->skip += i;
break;
}
if (i==33)
dec->skip += 33;
if (eofbits(dec))
break;
}
}
static _CONST uint8_t mv_tab[64] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x7c,0x74,0x6c,
0x64,0x5c,0x53,0x53,0x4b,0x4b,0x43,0x43,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,
0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20
};
#define GetMVData( dec, table, shift, shift2, last, bitpos )\
{ \
int code,v; \
loadbits_pos(dec,bitpos); \
code = showbits_pos(dec,bitpos,10); \
if (code >= 512) \
{ \
flushbits_pos(dec,bitpos,1); \
} \
else \
{ \
if (code >= 64) \
{ \
v = 4; \
if (code >= 128) --v; \
if (code >= 256) --v; \
flushbits_pos(dec,bitpos,v); \
code = v-1; \
} \
else \
{ \
code = table[code]; \
v = (code & 7)+6; \
flushbits_pos(dec,bitpos,v); \
code >>= 3; \
} \
/* 14bits left */ \
v = showbits_pos(dec,bitpos,1); \
flushbits_pos(dec,bitpos,1); \
if (shift) /* max 6bits */ \
{ \
code = (code - 1) << shift; \
code |= showbits_pos(dec,bitpos,shift); \
flushbits_pos(dec,bitpos,shift); \
code++; \
} \
if (v) \
code = -code; \
last += code; \
last = ((last + shift2) & (shift2*2-1)) - shift2;\
} \
}
static void GetMV(int fcode, int* mv, int full, mpeg_decode* dec )
{
int mv_x = ((int16_t*)mv)[MVXIDX];
int mv_y = ((int16_t*)mv)[MVYIDX];
int bitpos = dec->bitpos;
int fcode2 = 1 << (fcode+4);
_CONST uint8_t* tab = mv_tab;
GetMVData(dec,tab,fcode,fcode2,mv_x,bitpos);
GetMVData(dec,tab,fcode,fcode2,mv_y,bitpos);
dec->bitpos = bitpos;
((int16_t*)mv)[MVXIDX] = (int16_t)mv_x;
((int16_t*)mv)[MVYIDX] = (int16_t)mv_y;
if (full)
{
mv_x <<= 1;
mv_y <<= 1;
}
mv_x &= 0xFFFF;
mv_y <<= 16;
mv_y |= mv_x;
mv[1] = mv_y;
mv[2] = mv_y;
mv[3] = mv_y;
mv[4] = mv_y;
mv_y >>= 1; //shift
mv_y &= ~0x8000; //replace dx sign bit with old signed bit
mv_x &= 0x8000;
mv_y |= mv_x;
mv[5] = mv_y;
mv[6] = mv_y;
}
static int decodeInter( mpeg_decode* dec )
{
idct_block_t *block = dec->blockptr;
const uint16_t *table = vld_mpeg1;
int qscale;
int bitpos;
int len;
int code,level;
ClearBlock(block);
bitpos = dec->bitpos;
loadbits_pos(dec,bitpos);
len = 0;
qscale = dec->qscale;
// special case for first
code = showbits_pos(dec,bitpos,2);
if (code & 2)
{
flushbits_pos(dec,bitpos,2);
level= (3 * qscale * dec->InterMatrix[0]) >> 4;
level= (level-1)|1;
if (code & 1)
level= -level;
block[0] = (idct_block_t)level;
DEBUG_MSG2(DEBUG_VCODEC2,T("inter_block[%i] %i"), 0, level );
++len;
}
for (;;) // event vld
{
loadbits_pos(dec,bitpos);
code = showbits_pos(dec,bitpos,16);
vld_code;
level = code & 63;
if (level < 62)
{
level = level*2+1;
level *= qscale;
code >>= 6;
code &= 63;
len += code; // run
if (len >= 64)
break;
code = dec->zigzag[len];
level *= dec->InterMatrix[len];
level >>= 4;
level = (level-1)|1;
if (getbits1_pos(dec,bitpos))
level = -level;
block[code] = (idct_block_t)level;
++len;
}
else
{
if (level==63)
break;
// this value is escaped
loadbits_pos(dec,bitpos);
len += showbits_pos(dec,bitpos,6); flushbits_pos(dec,bitpos,6);
if (len >= 64)
break;
code = showbits_pos(dec,bitpos,8); flushbits_pos(dec,bitpos,8);
level = (code << 24) >> 24; //sign extend the lower 8 bits
code = dec->zigzag[len];
if (level == -128)
{
level = showbits_pos(dec,bitpos,8)-256; flushbits_pos(dec,bitpos,8);
}
else
if (level == 0)
{
level = showbits_pos(dec,bitpos,8); flushbits_pos(dec,bitpos,8);
}
if (level<0)
{
level= -level;
level = level*2+1;
level *= qscale * dec->InterMatrix[len];
level >>= 4;
level= (level-1)|1;
level= -level;
block[code] = (idct_block_t)level;
++len;
}
else
{
level = level*2+1;
level *= qscale * dec->InterMatrix[len];
level >>= 4;
level = (level-1)|1;
block[code] = (idct_block_t)level;
++len;
}
}
DEBUG_MSG2(DEBUG_VCODEC2,T("inter_block[%i] %i"), code, level );
}
dec->bitpos = bitpos;
return len;
}
static void blockInter( mpeg_decode* dec, int mb_type, int pos )
{
int j;
idct* IDCT = dec->Codec.IDCT.Ptr;
IDCT->Process(IDCT,POSX(pos),POSY(pos));
IDCT->MComp16x16(IDCT,
dec->fmv[1]==NOMV?NULL:dec->fmv+1,
dec->bmv[1]==NOMV?NULL:dec->bmv+1);
if (mb_type & MB_PAT)
{
int len,cbp;
loadbits(dec);
len = showbits(dec,9);
if (len >= 128)
len >>= 4;
else
len += 32;
len <<= 1;
flushbits(dec,mcbp_p[len]);
cbp = mcbp_p[len+1];
for (j = 0; j < 6; j++, cbp+=cbp)
{
len = 0;
if (cbp & 32)
len = decodeInter(dec);
IDCT->Inter8x8(IDCT,dec->blockptr,len);
}
}
else
{
for (j = 0; j < 6; j++)
IDCT->Inter8x8(IDCT,dec->blockptr,0);
}
dec->last_dc[2] =
dec->last_dc[1] =
dec->last_dc[0] = 128;
}
static int IVOP_Slice( mpeg_decode* dec, int pos )
{
dec->lastrefframe = dec->Frame;
dec->mapofs = dec->Frame;
memset(dec->framemap,0,dec->pos_end); // set all block to current frame
for (;pos<dec->pos_end;pos+=MB_X-dec->mb_xsize)
{
for (;POSX(pos)<dec->mb_xsize;++pos)
{
if (!getbits1(dec))
{
flushbits(dec,1); // should be 1
dec->qscale = readqscale(dec);
}
blockIntra(dec, pos);
inlineloadbits(dec);
if (showbits(dec,8)==0) // eof slice
return ERR_NONE;
if (!getbits1(dec))
return ERR_NONE; // skip invalid with IVOP
}
}
return ERR_NONE;
}
static int PVOP_Slice( mpeg_decode* dec, int pos )
{
dec->currframemap = (dec->Frame - dec->mapofs) << 1;
dec->lastrefframe = dec->Frame;
dec->bmv[1] = NOMV;
for (;pos<dec->pos_end;pos+=MB_X-dec->mb_xsize)
{
for (;POSX(pos)<dec->mb_xsize;++pos)
{
if (!dec->skip)
{
int mb_type;
DEBUG_MSG3(DEBUG_VCODEC2,T("macro %d,%d %08x"),POSX(pos),POSY(pos),showbitslarge((loadbits(dec),dec),32));
dec->framemap[pos] = (uint8_t)dec->currframemap;
mb_type = mb_type_p[showbits(dec,6)];
flushbits(dec,mb_type >> 5); // after this 6bits left
if (mb_type & MB_QUANT)
dec->qscale = readqscale(dec);
if (mb_type & MB_INTRA)
blockIntra(dec, pos);
else
{
if (mb_type & MB_FOR)
GetMV(dec->fcode[0],dec->fmv,dec->full_pixel[0],dec);
else
dec->fmv[6] = dec->fmv[5] = dec->fmv[4] = dec->fmv[3] =
dec->fmv[2] = dec->fmv[1] = dec->fmv[0] = 0;
DEBUG_MSG3(DEBUG_VCODEC2,T("mv%d %d:%d"),0,MVX(dec->fmv[1]),MVY(dec->fmv[1]));
blockInter( dec, mb_type, pos );
}
inlineloadbits(dec);
if (showbits(dec,8)==0) // eof slice
return ERR_NONE;
readskip(dec); // after this 12bits left
}
else
{
int n;
dec->skip--;
// not coded macroblock
n = dec->framemap[pos];
// copy needed or the buffer already has this block?
if (dec->bufframe < dec->mapofs+(n>>1))
dec->Codec.IDCT.Ptr->Copy16x16(dec->Codec.IDCT.Ptr,POSX(pos),POSY(pos),0);
dec->fmv[0] = 0;
dec->last_dc[2] =
dec->last_dc[1] =
dec->last_dc[0] = 128;
}
}
}
return ERR_NONE;
}
static int BVOP_Slice( mpeg_decode* dec, int pos )
{
for (;pos<dec->pos_end;pos+=MB_X-dec->mb_xsize)
{
for (;POSX(pos)<dec->mb_xsize;++pos)
{
if (!dec->skip)
{
int mb_type;
DEBUG_MSG3(DEBUG_VCODEC2,T("macro %d,%d %08x"),POSX(pos),POSY(pos),showbitslarge((loadbits(dec),dec),32));
//dec->framemap[pos] |= 1;
mb_type = mb_type_b[showbits(dec,6)];
flushbits(dec,mb_type >> 5); // after this 6bits left
if (mb_type & MB_QUANT)
dec->qscale = readqscale(dec);
if (mb_type & MB_INTRA)
blockIntra(dec, pos);
else
{
if (mb_type & MB_FOR)
{
GetMV(dec->fcode[0],dec->fmv,dec->full_pixel[0],dec);
DEBUG_MSG3(DEBUG_VCODEC2,T("mv%d %d:%d"),0,MVX(dec->fmv[1]),MVY(dec->fmv[1]));
}
else
dec->fmv[1] = NOMV;
if (mb_type & MB_BACK)
{
GetMV(dec->fcode[1],dec->bmv,dec->full_pixel[1],dec);
DEBUG_MSG3(DEBUG_VCODEC2,T("mv%d %d:%d"),1,MVX(dec->bmv[1]),MVY(dec->bmv[1]));
}
else
dec->bmv[1] = NOMV;
blockInter( dec, mb_type, pos );
}
inlineloadbits(dec);
if (showbits(dec,8)==0) // eof slice
return ERR_NONE;
readskip(dec); // after this 12bits left
}
else
{
// not coded macroblock, use last motion compensation vectors
dec->skip--;
if (dec->fmv[1]==0 && dec->bmv[1]==NOMV)
{
dec->Codec.IDCT.Ptr->Copy16x16(dec->Codec.IDCT.Ptr,POSX(pos),POSY(pos),0);
dec->last_dc[2] =
dec->last_dc[1] =
dec->last_dc[0] = 128;
}
else
if (dec->bmv[1]==0 && dec->fmv[1]==NOMV)
{
dec->Codec.IDCT.Ptr->Copy16x16(dec->Codec.IDCT.Ptr,POSX(pos),POSY(pos),1);
dec->last_dc[2] =
dec->last_dc[1] =
dec->last_dc[0] = 128;
}
else
blockInter(dec, 0, pos );
}
}
}
return ERR_NONE;
}
static int Frame( mpeg_decode* dec, const uint8_t* Ptr, int Len )
{
int Result;
int Code;
if (Len == 0)
return ERR_INVALID_DATA;
initbits(dec,Ptr,Len);
Result = ERR_NONE;
DEBUG_MSG1(DEBUG_VCODEC,T("MPEG Frame Length:%d"),Len);
dec->frame_state = -1;
do
{
bytealign(dec);
loadbits(dec);
if (eofbits(dec))
break;
Code = showbits(dec,32);
if ((Code & ~0xFF)==0x100)
{
flushbits(dec,32);
if (Code >= SLICE_MIN_START_CODE && Code <= SLICE_MAX_START_CODE)
{
// found a slice
Code = (Code-1) & 0xFF;
if (Code >= dec->mb_ysize)
{
Result = ERR_INVALID_DATA;
break;
}
if (dec->frame_state)
{
if (dec->frame_state<0 || dec->Codec.IDCT.Count<2)
{
Result = ERR_INVALID_DATA; // no picture header
break;
}
Result = StartFrame(dec);
if (Result != ERR_NONE || dec->Codec.Show < 0)
break;
dec->frame_state = 0;
}
loadbits(dec);
dec->qscale = readqscale(dec);
while (getbits1(dec))
{
flushbits(dec,8);
loadbits(dec);
}
readskip(dec);
Code = MB_X*Code + dec->skip;
dec->skip = 0;
dec->last_dc[2] =
dec->last_dc[1] =
dec->last_dc[0] = 128;
dec->fmv[0] = dec->bmv[0] = 0;
loadbits(dec);
switch (dec->prediction_type)
{
case P_VOP:
Result = PVOP_Slice(dec,Code);
break;
case I_VOP:
Result = IVOP_Slice(dec,Code);
break;
case B_VOP:
Result = BVOP_Slice(dec,Code);
break;
}
}
else
if (Code == PICTURE_START_CODE)
{
if (dec->ValidSeq)
Picture(dec);
else
Result = ERR_INVALID_DATA;
}
else
if (Code == SEQ_START_CODE)
Sequence(dec);
else
if (Code == EXT_START_CODE)
{
if (!dec->ErrorShowed)
{
pin Pin;
Pin.No = CODECIDCT_INPUT;
Pin.Node = &dec->Codec.Node;
dec->ErrorShowed = 1;
if (!dec->Codec.NotSupported.Node ||
dec->Codec.NotSupported.Node->Set(dec->Codec.NotSupported.Node,dec->Codec.NotSupported.No,
&Pin,sizeof(pin))!=ERR_NONE)
ShowError(dec->Codec.Node.Class,MPEG1_ID,MPEG2_NOT_SUPPORTED);
else
Result = ERR_INVALID_DATA;
}
}
}
else
flushbits(dec,8);
}
while (Result == ERR_NONE);
if (dec->frame_state==0)
{
dec->Codec.IDCT.Ptr->FrameEnd(dec->Codec.IDCT.Ptr);
dec->Frame++;
// possible (uint8) framemap overflow?
if ((dec->Frame - dec->mapofs) >= 128)
{
int pos;
for (pos=0;pos<dec->pos_end;pos+=MB_X-dec->mb_xsize)
for (;POSX(pos)<dec->mb_xsize;++pos)
{
int i = dec->framemap[pos];
if (i >= (120<<1))
i -= 120<<1;
else
i &= 1;
dec->framemap[pos] = (uint8_t)i;
}
dec->mapofs += 120;
}
}
return Result;
}
static int Create( mpeg_decode* p )
{
p->Codec.MinCount = 2;
p->Codec.DefCount = 3; // default assuming B-frames (avoid reinit when reaching first B-frame)
p->Codec.FindNext = (codecidctnext)FindNext;
p->Codec.Frame = (codecidctframe)Frame;
p->Codec.UpdateSize = (nodefunc)UpdateSize;
p->Codec.UpdateInput = (nodefunc)UpdateInput;
p->Codec.Discontinuity = (nodefunc)Discontinuity;
p->Codec.Flush = (nodefunc)Flush;
return ERR_NONE;
}
static const nodedef MPEG1 =
{
sizeof(mpeg_decode),
MPEG1_ID,
CODECIDCT_CLASS,
PRI_DEFAULT,
(nodecreate)Create,
NULL,
};
void MPEG1_Init()
{
NodeRegisterClass(&MPEG1);
}
void MPEG1_Done()
{
NodeUnRegisterClass(MPEG1_ID);
}