1328 lines
33 KiB
C
Executable File
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);
|
|
}
|