Windows2003-3790/enduser/netmeeting/av/codecs/dec/dech263/getpic.c
2020-09-30 16:53:55 +02:00

1423 lines
49 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* File: sv_h263_getpic.c */
/*****************************************************************************
** Copyright (c) Digital Equipment Corporation, 1995, 1997 **
** **
** All Rights Reserved. Unpublished rights reserved under the copyright **
** laws of the United States. **
** **
** The software contained on this media is proprietary to and embodies **
** the confidential technology of Digital Equipment Corporation. **
** Possession, use, duplication or dissemination of the software and **
** media is authorized only pursuant to a valid written license from **
** Digital Equipment Corporation. **
** **
** RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure by the U.S. **
** Government is subject to restrictions as set forth in Subparagraph **
** (c)(1)(ii) of DFARS 252.227-7013, or in FAR 52.227-19, as applicable. **
******************************************************************************/
/*
#define _SLIBDEBUG_
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sv_h263.h"
#include "sv_intrn.h"
#include "SC_err.h"
#include "proto.h"
#ifdef _SLIBDEBUG_
#include "sc_debug.h"
#define _DEBUG_ 0 /* detailed debuging statements */
#define _VERBOSE_ 1 /* show progress */
#define _VERIFY_ 0 /* verify correct operation */
#define _WARN_ 1 /* warnings about strange behavior */
#endif
/* private prototypes*/
static void getMBs(SvH263DecompressInfo_t *H263Info, ScBitstream_t *BSIn);
static void clearblock(SvH263DecompressInfo_t *H263Info, int comp);
static int motion_decode(SvH263DecompressInfo_t *H263Info, int vec, int pmv);
static int find_pmv(SvH263DecompressInfo_t *H263Info, int x, int y, int block, int comp);
static void addblock(SvH263DecompressInfo_t *H263Info, int comp, int bx, int by, int addflag);
static void reconblock_b(SvH263DecompressInfo_t *H263Info, int comp, int bx, int by,
int mode, int bdx, int bdy);
static void find_bidir_limits(int vec, int *start, int*stop, int nhv);
static void find_bidir_chroma_limits(int vec, int *start, int*stop);
static void make_edge_image(unsigned char *src, unsigned char *dst, int width, int height, int edge);
void interpolate_image(unsigned char *in, unsigned char *out, int width, int height);
static void IDCT_add(int comp,int bx,int by,int addflag) ;
static int H263_roundtab[16]= {0,0,0,1,1,1,1,1,1,1,1,1,1,1,2,2};
static int H263_codtab[2]= {0,1};
static int H263_mcbpctab[21] = {0,16,32,48,1,17,33,49,2,18,34,50,3,19,35,51,4,20,36,52,255};
static int H263_mcbpc_intratab[9] = {3,19,35,51,4,20,36,52,255};
static int H263_modb_tab[3] = {0, 1, 2};
static int H263_ycbpb_tab[2] = {0, 1};
static int H263_uvcbpb_tab[2] = {0, 1};
static int H263_cbpytab[16] = {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0};
static int H263_cbpy_intratab[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
static int H263_dquanttab[4] = {1,0,3,4};
static int H263_mvdtab[64] = {32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31};
static int H263_intradctab[254] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,255,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254};
static int H263_cumf_COD[3]={16383, 6849, 0};
static int H263_cumf_MCBPC[22]={16383, 4105, 3088, 2367, 1988, 1621, 1612, 1609, 1608, 496, 353, 195, 77, 22, 17, 12, 5, 4, 3, 2, 1, 0};
static int H263_cumf_MCBPC_intra[10]={16383, 7410, 6549, 5188, 442, 182, 181, 141, 1, 0};
static int H263_cumf_MODB[4]={16383, 6062, 2130, 0};
static int H263_cumf_YCBPB[3]={16383,6062,0};
static int H263_cumf_UVCBPB[3]={16383,491,0};
static int H263_cumf_CBPY[17]={16383, 14481, 13869, 13196, 12568, 11931, 11185, 10814, 9796, 9150, 8781, 7933, 6860, 6116, 4873, 3538, 0};
static int H263_cumf_CBPY_intra[17]={16383, 13619, 13211, 12933, 12562, 12395, 11913, 11783, 11004, 10782, 10689, 9928, 9353, 8945, 8407, 7795, 0};
static int H263_cumf_DQUANT[5]={16383, 12287, 8192, 4095, 0};
static int H263_cumf_MVD[65]={16383, 16380, 16369, 16365, 16361, 16357, 16350, 16343, 16339, 16333, 16326, 16318, 16311, 16306, 16298, 16291, 16283, 16272, 16261, 16249, 16235, 16222, 16207, 16175, 16141, 16094, 16044, 15936, 15764, 15463, 14956, 13924, 11491, 4621, 2264, 1315, 854, 583, 420, 326, 273, 229, 196, 166, 148, 137, 123, 114, 101, 91, 82, 76, 66, 59, 53, 46, 36, 30, 26, 24, 18, 14, 10, 5, 0};
static int H263_cumf_INTRADC[255]={16383, 16380, 16379, 16378, 16377, 16376, 16370, 16361, 16360, 16359, 16358, 16357, 16356, 16355, 16343, 16238, 16237, 16236, 16230, 16221, 16220, 16205, 16190, 16169, 16151, 16130, 16109, 16094, 16070, 16037, 16007, 15962, 15938, 15899, 15854, 15815, 15788, 15743, 15689, 15656, 15617, 15560, 15473, 15404, 15296, 15178, 15106, 14992, 14868, 14738, 14593, 14438, 14283, 14169, 14064, 14004, 13914, 13824, 13752, 13671, 13590, 13515, 13458, 13380, 13305, 13230, 13143, 13025, 12935, 12878, 12794, 12743, 12656, 12596, 12521, 12443, 12359, 12278, 12200, 12131, 12047, 12002, 11948, 11891, 11828, 11744, 11663, 11588, 11495, 11402, 11288, 11204, 11126, 11039, 10961, 10883, 10787, 10679, 10583, 10481, 10360, 10227, 10113, 9961, 9828, 9717, 9584, 9485, 9324, 9112, 9019, 8908, 8766, 8584, 8426, 8211, 7920, 7663, 7406, 7152, 6904, 6677, 6453, 6265, 6101, 5904, 5716, 5489, 5307, 5056, 4850, 4569, 4284, 3966, 3712, 3518, 3342, 3206, 3048, 2909, 2773, 2668, 2596, 2512, 2370, 2295, 2232, 2166, 2103, 2022, 1956, 1887, 1830, 1803, 1770, 1728, 1674, 1635, 1599, 1557, 1500, 1482, 1434, 1389, 1356, 1317, 1284, 1245, 1200, 1179, 1140, 1110, 1092, 1062, 1044, 1035, 1014, 1008, 993, 981, 954, 936, 912, 894, 876, 864, 849, 828, 816, 801, 792, 777, 756, 732, 690, 660, 642, 615, 597, 576, 555, 522, 489, 459, 435, 411, 405, 396, 387, 375, 360, 354, 345, 344, 329, 314, 293, 278, 251, 236, 230, 224, 215, 214, 208, 199, 193, 184, 178, 169, 154, 127, 100, 94, 73, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 20, 19, 18, 17, 16, 15, 9, 0};
#define clearblk(comp) memset(H263Info->block[comp], 0, sizeof(int [66]));
/* decode one frame or field picture */
SvStatus_t sv_H263GetPicture(SvCodecInfo_t *Info)
{
int i;
unsigned char *tmp;
SvH263DecompressInfo_t *H263Info = Info->h263dcmp;
ScBitstream_t *BSIn=Info->BSIn;
_SlibDebug(_VERBOSE_, ScDebugPrintf(H263Info->dbg, "sv_H263GetPicture()\n") );
for (i=0; i<3; i++) {
tmp = H263Info->oldrefframe[i];
H263Info->oldrefframe[i] = H263Info->refframe[i];
H263Info->refframe[i] = tmp;
H263Info->newframe[i] = H263Info->refframe[i];
}
if (H263Info->mv_outside_frame && H263Info->framenum > 0) {
make_edge_image(H263Info->oldrefframe[0],H263Info->edgeframe[0],H263Info->coded_picture_width,
H263Info->coded_picture_height,32);
make_edge_image(H263Info->oldrefframe[1],H263Info->edgeframe[1],H263Info->chrom_width, H263Info->chrom_height,16);
make_edge_image(H263Info->oldrefframe[2],H263Info->edgeframe[2],H263Info->chrom_width, H263Info->chrom_height,16);
}
getMBs(H263Info, BSIn);
if (H263Info->pb_frame) {
if (H263Info->expand && H263Info->outtype == H263_T_X11) {
interpolate_image(H263Info->bframe[0], H263Info->exnewframe[0],
H263Info->coded_picture_width, H263Info->coded_picture_height);
interpolate_image(H263Info->bframe[1], H263Info->exnewframe[1], H263Info->chrom_width, H263Info->chrom_height);
interpolate_image(H263Info->bframe[2], H263Info->exnewframe[2], H263Info->chrom_width, H263Info->chrom_height);
/* svH263Storeframe(H263Info->exnewframe, *framenum); */
}
else
/* svH263Storeframe(H263Info->bframe,*framenum); */
H263Info->framenum += H263Info->pb_frame;
}
if (H263Info->expand && H263Info->outtype == H263_T_X11) {
interpolate_image(H263Info->newframe[0], H263Info->exnewframe[0],
H263Info->coded_picture_width, H263Info->coded_picture_height);
interpolate_image(H263Info->newframe[1], H263Info->exnewframe[1], H263Info->chrom_width, H263Info->chrom_height);
interpolate_image(H263Info->newframe[2], H263Info->exnewframe[2], H263Info->chrom_width, H263Info->chrom_height);
/* svH263Storeframe(H263Info->exnewframe, *framenum); */
}
else {
/* svH263Storeframe(H263Info->newframe,*framenum); */
}
return(SvErrorNone);
}
/* decode all macroblocks of the current picture */
#ifdef CAMERAMOTION
extern void setwintitle(char *);
#define MOVERIGHT (1<<0)
#define MOVELEFT (1<<1)
#define MOVEUP (1<<2)
#define MOVEDOWN (1<<3)
static int left_x,left_y;
static int top_x,top_y;
static int right_x,right_y;
static int bottom_x,bottom_y;
static int center_x,center_y;
static int strip_width = 3;
static int framewidth;
static int frameheight;
static int startoff;
static int filtermean,havecut;
static int loopstart = 0;
static int loopend;
static int scenenumber = 1;
static void initmotion(int width,int height)
{
left_x = left_y = 0;
right_x = right_y = 0;
bottom_x = bottom_y = 0;
top_x = top_y = 0;
center_x = center_y = 0;
framewidth = width;
frameheight = height;
startoff = svH263Tellbits();
}
static void analyzemotion(int xpos,int ypos,int mvx,int mvy)
{
/* Count Motion Vectors for 4 overlapping strips at the edges */
/* and the center area between them */
if (xpos < strip_width) { /* Left strip */
left_x += mvx;
left_y += mvy;
}
if (xpos >= (framewidth - strip_width)) { /* Right strip */
right_x += mvx;
right_y += mvy;
}
if (ypos < strip_width) { /* Top strip */
top_x += mvx;
top_y += mvy;
}
if (ypos >= (frameheight - strip_width)) { /* Bottom strip */
bottom_x += mvx;
bottom_y += mvy;
}
if (xpos >= strip_width && xpos < (framewidth - strip_width)
&& ypos >= strip_width && ypos < (frameheight - strip_width)) {
center_x += mvx;
center_y += mvy;
}
}
static int last_movement = 0;
static int keepdirection = 15;
static int movestartframe = 0;
static int moveendframe;
static int movesumx;
static int movesumy;
static void summarizemotion(int frameno)
{
int threshold = 8;
int striparea;
int sx,sy;
char title[128];
int cur_movement = 0;
int framesize;
title[0] = 0;
framesize = svH263Tellbits() - startoff;
if (frameno < 1) {
filtermean = framesize/2;
havecut = 1;
} else {
filtermean = (4*filtermean + framesize)/5;
}
if (!havecut && framesize > 1.8 * filtermean && frameno > 5) {
if (!last_movement) {
printf("dump %d\n",movestartframe + ((moveendframe-movestartframe)/2));
}
printf("mark %d %d %d %d\n",scenenumber,loopstart,frameno-1,filtermean);
printf("shot %d %d %d\n",scenenumber,loopstart,frameno-1);
movestartframe = frameno;
loopstart = frameno;
havecut = 1;
scenenumber++;
} else {
havecut = 0;
}
striparea = strip_width * framewidth;
top_x = (top_x*10)/striparea;
top_y = (top_y*10)/striparea;
bottom_x = (bottom_x*10)/striparea;
bottom_y = (bottom_y*10)/striparea;
striparea = strip_width * frameheight;
left_x = (left_x*10)/striparea;
left_y = (left_y*10)/striparea;
right_x = (right_x*10)/striparea;
right_y = (right_y*10)/striparea;
striparea = (framewidth - 2 * strip_width) * (frameheight - 2 * strip_width);
center_x = (center_x*10)/striparea;
center_y = (center_y*10)/striparea;
/* Horizontal left motion */
if (top_x < -threshold && bottom_x < -threshold
&& right_x < -threshold && left_x < -threshold) {
strcat(title,"Left ");
cur_movement |= MOVELEFT;
}
/* Horizontal right motion */
if (top_x > threshold && bottom_x > threshold
&& left_x > threshold && right_x > threshold) {
strcat(title,"Right ");
cur_movement |= MOVERIGHT;
}
/* Vertical up motion */
if (left_y < -threshold && right_y < -threshold
&& top_y < -threshold && bottom_y < -threshold) {
strcat(title,"Up");
cur_movement |= MOVEUP;
}
/* Vertical down motion */
if (left_y > threshold && right_y > threshold
&& bottom_y > threshold && top_y > threshold) {
strcat(title,"Down ");
cur_movement |= MOVEDOWN;
}
if (last_movement) {
movesumx += (top_x + bottom_x + right_x +left_x)/4;
movesumy += (top_y + bottom_y + right_y +left_y)/4;
}
if (!cur_movement != !last_movement) { /* Possible movement change */
if (--keepdirection < 0) { /* Seen move several times */
keepdirection = 10;
if (last_movement) { /* Have been in a move */
int movelength;
int i,images,fno;
movesumx = movesumx/(16*framewidth);
movesumy = movesumy/(16*frameheight);
movelength = moveendframe - movestartframe;
if (movelength > 25) {
images = ((abs(movesumx) + abs(movesumy)) / 5) + 1;
fno = movestartframe + movelength/(2*images);
for (i = 0; i < images; i++) {
printf("dump %d\n",fno);
fno += movelength/images;
}
}
} else { /* Last part was fixed */
if (havecut) {
/* Do nothing, was already handled */
} else {
printf("dump %d\n",movestartframe + ((moveendframe-movestartframe)/2));
movestartframe = frameno;
}
}
movesumx = 0;
movesumy = 0;
movestartframe = moveendframe+1;
last_movement = cur_movement;
if (H263Info->outtype == H263_T_X11) {
if (title[0] != 0) {
setwintitle(title);
} else {
setwintitle("fixed");
}
}
}
} else {
moveendframe = frameno;
}
fflush(stdout);
}
#endif /* CAMERAMOTION */
static void getMBs(SvH263DecompressInfo_t *H263Info, ScBitstream_t *BSIn)
{
int comp;
int MBA, MBAmax;
int bx, by;
int COD=0,MCBPC, CBPY, CBP=0, CBPB=0, MODB=0, Mode=0, DQUANT;
int COD_index, CBPY_index, MODB_index, DQUANT_index, MCBPC_index;
int INTRADC_index, YCBPB_index, UVCBPB_index, mvdbx_index, mvdby_index;
int mvx, mvy, mvy_index, mvx_index, pmv0, pmv1, xpos, ypos, gob, i,k;
int mvdbx=0, mvdby=0, pmvdbx, pmvdby, gfid, YCBPB, UVCBPB, gobheader_read;
int startmv,stopmv,offset,bsize,last_done=0,pCBP=0,pCBPB=0,pCOD=0;
int DQ_tab[4] = {-1,-2,1,2};
register int *bp;
_SlibDebug(_VERBOSE_, ScDebugPrintf(H263Info->dbg, "getMBs()\n") );
/* number of macroblocks per picture */
MBAmax = H263Info->mb_width*H263Info->mb_height;
MBA = 0; /* macroblock address */
H263Info->newgob = 0;
/* mark MV's above the picture */
for (i = 1; i < H263Info->mb_width+1; i++) {
for (k = 0; k < 5; k++) {
H263Info->MV[0][k][0][i] = H263_NO_VEC;
H263Info->MV[1][k][0][i] = H263_NO_VEC;
}
H263Info->modemap[0][i] = H263_MODE_INTRA;
}
/* zero MV's on the sides of the picture */
for (i = 0; i < H263Info->mb_height+1; i++) {
for (k = 0; k < 5; k++) {
H263Info->MV[0][k][i][0] = 0;
H263Info->MV[1][k][i][0] = 0;
H263Info->MV[0][k][i][H263Info->mb_width+1] = 0;
H263Info->MV[1][k][i][H263Info->mb_width+1] = 0;
}
H263Info->modemap[i][0] = H263_MODE_INTRA;
H263Info->modemap[i][H263Info->mb_width+1] = H263_MODE_INTRA;
}
H263Info->fault = 0;
gobheader_read = 0;
for (;;) {
_SlibDebug(_VERBOSE_, ScDebugPrintf(H263Info->dbg, "frame %d, MB %d, bytepos=%ld\n",
H263Info->framenum,MBA,ScBSBytePosition(BSIn)) );
/* if (MBA>15) return; */
resync:
/* This version of the decoder does not resync on every possible
error, and it does not do all possible error checks. It is not
difficult to make it much more error robust, but I do not think
it is necessary to include this in the freely available
version. */
if (H263Info->fault) {
_SlibDebug(_VERBOSE_, ScDebugPrintf(H263Info->dbg, "getMBs() fault\n") );
printf("Warning: A Fault Condition Has Occurred - Resyncing \n");
/* look for startcode */
if (sv_H263StartCode(BSIn)!=SvErrorNone) /* sync on new startcode */
{
_SlibDebug(_VERBOSE_, ScDebugPrintf(H263Info->dbg, "getMBs() couldn't get startcode\n") );
return;
}
H263Info->fault = 0;
}
if (!(ScBSPeekBits(BSIn, 22)>>6)) { /* startcode */
if (sv_H263StartCode(BSIn)!=SvErrorNone) /* sync on new startcode */
{
_SlibDebug(_VERBOSE_, ScDebugPrintf(H263Info->dbg, "getMBs() couldn't get startcode\n") );
return;
}
/* in case of byte aligned start code, ie. PSTUF, GSTUF or ESTUF
is used */
if (ScBSPeekBits(BSIn, 22) == (32|H263_SE_CODE)) { /* end of sequence */
_SlibDebug(_VERBOSE_, ScDebugPrintf(H263Info->dbg, "getMBs() end of sequence\n") );
if (!(H263Info->syntax_arith_coding && MBA < MBAmax))
{
return;
}
}
else if ((ScBSPeekBits(BSIn, 22) == H263_PSC<<5) ) { /* new picture */
_SlibDebug(_VERBOSE_, ScDebugPrintf(H263Info->dbg, "getMBs() new picture code, bytepos=%ld\n",
ScBSBytePosition(BSIn)) );
if (!(H263Info->syntax_arith_coding && MBA < MBAmax)) {
#ifdef CAMERAMOTION
goto summarize_motion;
#else
return;
#endif
}
}
else {
_SlibDebug(_VERBOSE_, ScDebugPrintf(H263Info->dbg, "getMBs() new group code, bytepos=%ld\n",
ScBSBytePosition(BSIn)) );
if (!(H263Info->syntax_arith_coding && MBA%H263Info->mb_width)) {
if (H263Info->syntax_arith_coding) { /* SAC hack to finish GOBs which */
gob = (int)(ScBSPeekBits(BSIn, 22) & 31); /* end with MBs coded with no bits */
if (gob * H263Info->mb_width != MBA)
{
_SlibDebug(_VERBOSE_, ScDebugPrintf(H263Info->dbg, "getMBs() goto finish_gob\n") );
goto finish_gob;
}
}
if (sv_H263GetHeader(H263Info, BSIn, &gob)!=SvErrorNone)
{
_SlibDebug(_VERBOSE_, ScDebugPrintf(H263Info->dbg, "getMBs() GetHeader failed\n") );
return;
}
/* gob--; */
if (gob > H263Info->mb_height) {
_SlibDebug(_VERBOSE_, ScDebugPrintf(H263Info->dbg, "getMBs() GN out of range: gob=%d\n", gob) );
return;
}
/* GFID is not allowed to change unless PTYPE in picture header
changes */
gfid = (int)ScBSGetBits(BSIn, 2);
/* NB: in error-prone environments the decoder can use this
value to determine whether a picture header where the PTYPE
has changed, has been lost */
H263Info->quant = (int)ScBSGetBits(BSIn, 5);
_SlibDebug(_VERBOSE_, ScDebugPrintf(H263Info->dbg, "getMBs() GQUANT=%d gob=%d\n",
H263Info->quant, gob) );
xpos = 0;
ypos = gob;
MBA = ypos * H263Info->mb_width;
H263Info->newgob = 1;
gobheader_read = 1;
if (H263Info->syntax_arith_coding)
sv_H263SACDecoderReset(BSIn); /* init. arithmetic decoder buffer after gob */
}
}
}
finish_gob: /* SAC specific label */
if (!gobheader_read) {
xpos = MBA%H263Info->mb_width;
ypos = MBA/H263Info->mb_width;
if (xpos == 0 && ypos > 0)
H263Info->newgob = 0;
}
else
gobheader_read = 0;
if (MBA>=MBAmax)
{
#ifdef CAMERAMOTION
goto summarize_motion;
#else
_SlibDebug(_VERBOSE_, ScDebugPrintf(H263Info->dbg, "getMBs() done MBA=%d\n", MBA) );
return; /* all macroblocks decoded */
#endif
}
read_cod:
if (H263Info->syntax_arith_coding) {
if (H263Info->pict_type == H263_PCT_INTER) {
COD_index = sv_H263SACDecode_a_symbol(BSIn,H263_cumf_COD);
COD = H263_codtab[COD_index];
_SlibDebug(_DEBUG_, ScDebugPrintf(H263Info->dbg,
"getMBs() Arithmetic Decoding, COD Index: %d COD: %d \n", COD_index, COD) );
}
else
COD = 0; /* COD not used in I-pictures, set to zero */
}
else {
if (H263Info->pict_type == H263_PCT_INTER)
COD = (int)ScBSPeekBits(BSIn, 1);
else
COD = 0; /* Intra picture -> not skipped */
}
if (!COD) { /* COD == 0 --> not skipped */
if (H263Info->syntax_arith_coding) {
if (H263Info->pict_type == H263_PCT_INTER) {
MCBPC_index = sv_H263SACDecode_a_symbol(BSIn,H263_cumf_MCBPC);
MCBPC = H263_mcbpctab[MCBPC_index];
_SlibDebug(_DEBUG_, ScDebugPrintf(H263Info->dbg,
"getMBs() (arith/inter) MCBPC Index: %ld MCBPC: %d \n",MCBPC_index, MCBPC) );
}
else {
int lastMCBPC=MCBPC;
MCBPC_index = sv_H263SACDecode_a_symbol(BSIn,H263_cumf_MCBPC_intra);
MCBPC = H263_mcbpc_intratab[MCBPC_index];
_SlibDebug(_DEBUG_, ScDebugPrintf(H263Info->dbg,
"getMBs() (arith) MCBPC Index: %ld MCBPC: %d \n",MCBPC_index, MCBPC) );
if (MCBPC==255 && lastMCBPC==255)
return;
}
}
else {
if (H263Info->pict_type == H263_PCT_INTER)
ScBSSkipBit(BSIn); /* flush COD bit */
if (H263Info->pict_type == H263_PCT_INTRA)
MCBPC = sv_H263GetMCBPCintra(H263Info, BSIn);
else
MCBPC = sv_H263GetMCBPC(H263Info, BSIn);
_SlibDebug(_DEBUG_, ScDebugPrintf(H263Info->dbg,
"getMBs() MCBPC: %d \n", MCBPC) );
}
if (H263Info->fault) goto resync;
if (MCBPC == 255) { /* stuffing */
goto read_cod; /* read next COD without advancing MB count */
}
else { /* normal MB data */
Mode = MCBPC & 7;
/* MODB and CBPB */
if (H263Info->pb_frame) {
CBPB = 0;
if (H263Info->syntax_arith_coding) {
MODB_index = sv_H263SACDecode_a_symbol(BSIn,H263_cumf_MODB);
MODB = H263_modb_tab[MODB_index];
}
else
MODB = sv_H263GetMODB(H263Info, BSIn);
_SlibDebug(_DEBUG_, ScDebugPrintf(H263Info->dbg, "getMBs() MODB: %d\n", MODB) );
if (MODB == H263_PBMODE_CBPB_MVDB) {
if (H263Info->syntax_arith_coding) {
for(i=0; i<4; i++) {
YCBPB_index = sv_H263SACDecode_a_symbol(BSIn,H263_cumf_YCBPB);
YCBPB = H263_ycbpb_tab[YCBPB_index];
CBPB |= (YCBPB << (6-1-i));
}
for(i=4; i<6; i++) {
UVCBPB_index = sv_H263SACDecode_a_symbol(BSIn,H263_cumf_UVCBPB);
UVCBPB = H263_uvcbpb_tab[UVCBPB_index];
CBPB |= (UVCBPB << (6-1-i));
}
}
else
CBPB = (int)ScBSGetBits(BSIn, 6);
_SlibDebug(_DEBUG_, ScDebugPrintf(H263Info->dbg, "getMBs() CBPB = %d\n",CBPB) );
}
}
if (H263Info->syntax_arith_coding) {
if (Mode == H263_MODE_INTRA || Mode == H263_MODE_INTRA_Q) { /* Intra */
CBPY_index = sv_H263SACDecode_a_symbol(BSIn,H263_cumf_CBPY_intra);
CBPY = H263_cbpy_intratab[CBPY_index];
}
else {
CBPY_index = sv_H263SACDecode_a_symbol(BSIn,H263_cumf_CBPY);
CBPY = H263_cbpytab[CBPY_index];
}
_SlibDebug(_DEBUG_, ScDebugPrintf(H263Info->dbg, "getMBs() CBPY Index: %d CBPY %d \n",CBPY_index, CBPY) );
}
else
{
CBPY = sv_H263GetCBPY(H263Info, BSIn);
_SlibDebug(_DEBUG_, ScDebugPrintf(H263Info->dbg, "getMBs() CBPY %d \n",CBPY) );
}
/* Decode Mode and CBP */
if (Mode == H263_MODE_INTRA || Mode == H263_MODE_INTRA_Q)
{/* Intra */
if (!H263Info->syntax_arith_coding)
CBPY = CBPY^15; /* needed in huffman coding only */
}
CBP = (CBPY << 2) | (MCBPC >> 4);
}
if (Mode == H263_MODE_INTER4V && !H263Info->adv_pred_mode)
{
_SlibDebug(_VERBOSE_,
ScDebugPrintf(H263Info->dbg, "getMBs() 8x8 vectors not allowed in normal prediction mode\n") );
/* Could set fault-flag and resync */
}
if (Mode == H263_MODE_INTER_Q || Mode == H263_MODE_INTRA_Q) {
/* Read DQUANT if necessary */
if (H263Info->syntax_arith_coding) {
DQUANT_index = sv_H263SACDecode_a_symbol(BSIn,H263_cumf_DQUANT);
DQUANT = H263_dquanttab[DQUANT_index] - 2;
H263Info->quant +=DQUANT;
_SlibDebug(_DEBUG_, ScDebugPrintf(H263Info->dbg, "getMBs() DQUANT Index: %d DQUANT %d \n",DQUANT_index, DQUANT) );
}
else {
DQUANT = (int)ScBSGetBits(BSIn, 2);
H263Info->quant += DQ_tab[DQUANT];
_SlibDebug(_DEBUG_, ScDebugPrintf(H263Info->dbg, "getMBs() DQUANT: %d\n", DQUANT) );
#if 0
if (H263Info->trace) {
printf("DQUANT (");
svH263Printbits(DQUANT,2,2);
printf("): %d = %d\n",DQUANT,DQ_tab[DQUANT]);
}
#endif
}
if (H263Info->quant > 31 || H263Info->quant < 1) {
_SlibDebug(_WARN_, ScDebugPrintf(H263Info->dbg, "GetMBs() Quantizer out of range: clipping\n") );
H263Info->quant = mmax(1,mmin(31,H263Info->quant));
/* could set fault-flag and resync here */
}
}
/* motion vectors */
if (Mode == H263_MODE_INTER || Mode == H263_MODE_INTER_Q ||
Mode == H263_MODE_INTER4V || H263Info->pb_frame) {
if (Mode == H263_MODE_INTER4V) { startmv = 1; stopmv = 4;}
else { startmv = 0; stopmv = 0;}
for (k = startmv; k <= stopmv; k++) {
if (H263Info->syntax_arith_coding) {
mvx_index = sv_H263SACDecode_a_symbol(BSIn,H263_cumf_MVD);
mvx = H263_mvdtab[mvx_index];
mvy_index = sv_H263SACDecode_a_symbol(BSIn,H263_cumf_MVD);
mvy = H263_mvdtab[mvy_index];
_SlibDebug(_WARN_, ScDebugPrintf(H263Info->dbg,
"GetMBs() mvx_index: %d mvy_index: %d \n", mvx_index, mvy_index) );
}
else {
mvx = sv_H263GetTMNMV(H263Info, BSIn);
mvy = sv_H263GetTMNMV(H263Info, BSIn);
}
pmv0 = find_pmv(H263Info, xpos,ypos,k,0);
pmv1 = find_pmv(H263Info, xpos,ypos,k,1);
mvx = motion_decode(H263Info, mvx, pmv0);
mvy = motion_decode(H263Info, mvy, pmv1);
#ifdef CAMERAMOTION
analyzemotion(xpos,ypos,mvx,mvy);
#else
_SlibDebug(_WARN_, ScDebugPrintf(H263Info->dbg,
"GetMBs() mvx: %d mvy: %d\n", mvx, mvy) );
#endif
/* Check mv's to prevent seg.faults when error rate is high */
if (!H263Info->mv_outside_frame) {
bsize = k ? 8 : 16;
offset = k ? (((k-1)&1)<<3) : 0;
/* checking only integer component */
if ((xpos<<4) + (mvx/2) + offset < 0 ||
(xpos<<4) + (mvx/2) + offset > (H263Info->mb_width<<4) - bsize) {
_SlibDebug(_WARN_, ScDebugPrintf(H263Info->dbg, "GetMBs() mvx out of range: searching for sync\n") );
H263Info->fault = 1;
}
offset = k ? (((k-1)&2)<<2) : 0;
if ((ypos<<4) + (mvy/2) + offset < 0 ||
(ypos<<4) + (mvy/2) + offset > (H263Info->mb_height<<4) - bsize) {
_SlibDebug(_WARN_, ScDebugPrintf(H263Info->dbg, "GetMBs() mvy out of range: searching for sync\n") );
H263Info->fault = 1;
}
}
H263Info->MV[0][k][ypos+1][xpos+1] = mvx;
H263Info->MV[1][k][ypos+1][xpos+1] = mvy;
}
/* PB frame delta vectors */
if (H263Info->pb_frame) {
if (MODB == H263_PBMODE_MVDB || MODB == H263_PBMODE_CBPB_MVDB) {
if (H263Info->syntax_arith_coding) {
mvdbx_index = sv_H263SACDecode_a_symbol(BSIn,H263_cumf_MVD);
mvdbx = H263_mvdtab[mvdbx_index];
mvdby_index = sv_H263SACDecode_a_symbol(BSIn,H263_cumf_MVD);
mvdby = H263_mvdtab[mvdby_index];
}
else {
mvdbx = sv_H263GetTMNMV(H263Info, BSIn);
mvdby = sv_H263GetTMNMV(H263Info, BSIn);
}
mvdbx = motion_decode(H263Info, mvdbx, 0);
mvdby = motion_decode(H263Info, mvdby, 0);
/* This will not work if the PB deltas are so large they
require the second colums of the motion vector VLC
table to be used. To fix this it is necessary to
calculate the MV predictor for the PB delta: TRB*MV/TRD
here, and use this as the second parameter to
motion_decode(). The B vector itself will then be
returned from motion_decode(). This will have to be
changed to the PB delta again, since it is the PB delta
which is used later in this program. I don't think PB
deltas outside the range mentioned above is useful, but
you never know... */
}
else {
mvdbx = 0;
mvdby = 0;
}
_SlibDebug(_DEBUG_, ScDebugPrintf(H263Info->dbg,
"GetMBs() MVDB x: %d MVDB y: %d\n", mvdbx, mvdby) );
}
}
if (H263Info->fault) goto resync;
}
else { /* COD == 1 --> skipped MB */
if (MBA>=MBAmax)
{
#ifdef CAMERAMOTION /* Burkhard */
goto summarize_motion;
#else
_SlibDebug(_VERBOSE_, ScDebugPrintf(H263Info->dbg, "getMBs() done MBA=%d\n", MBA) );
return; /* all macroblocks decoded */
#endif
}
if (!H263Info->syntax_arith_coding)
if (H263Info->pict_type == H263_PCT_INTER)
ScBSSkipBits(BSIn, 1);
Mode = H263_MODE_INTER;
/* Reset CBP */
CBP = CBPB = 0;
/* reset motion vectors */
H263Info->MV[0][0][ypos+1][xpos+1] = 0;
H263Info->MV[1][0][ypos+1][xpos+1] = 0;
mvdbx = 0;
mvdby = 0;
}
/* Store Mode*/
H263Info->modemap[ypos+1][xpos+1] = Mode;
if (Mode == H263_MODE_INTRA || Mode == H263_MODE_INTRA_Q)
if (!H263Info->pb_frame)
H263Info->MV[0][0][ypos+1][xpos+1]=H263Info->MV[1][0][ypos+1][xpos+1] = 0;
reconstruct_mb:
/* pixel coordinates of top left corner of current macroblock */
/* one delayed because of OBMC */
if (xpos > 0) {
bx = 16*(xpos-1);
by = 16*ypos;
}
else {
bx = H263Info->coded_picture_width-16;
by = 16*(ypos-1);
}
if (MBA > 0) {
Mode = H263Info->modemap[by/16+1][bx/16+1];
/* forward motion compensation for B-frame */
if (H263Info->pb_frame)
{
_SlibDebug(_VERBOSE_, ScDebugPrintf(H263Info->dbg, "getMBs() sv_H263Reconstruct(B-frame)\n") );
sv_H263Reconstruct(H263Info,bx,by,0,pmvdbx,pmvdby);
}
/* motion compensation for P-frame */
if (Mode == H263_MODE_INTER || Mode == H263_MODE_INTER_Q || Mode == H263_MODE_INTER4V)
{
_SlibDebug(_VERBOSE_, ScDebugPrintf(H263Info->dbg, "getMBs() sv_H263Reconstruct(P-frame)\n") );
sv_H263Reconstruct(H263Info,bx,by,1,0,0);
}
/* copy or add block data into P-picture */
for (comp=0; comp<H263Info->blk_cnt; comp++) {
bp = H263Info->block[comp];
/* inverse DCT */
if (Mode == H263_MODE_INTRA || Mode == H263_MODE_INTRA_Q) {
addblock(H263Info, comp,bx,by,0);
}
else if ( (pCBP & (1<<(H263Info->blk_cnt-1-comp))) ) {
/* No need to to do this for blocks with no coeffs */
addblock(H263Info,comp,bx,by,1);
}
}
if (H263Info->pb_frame) {
/* add block data into B-picture */
for (comp = 6; comp<H263Info->blk_cnt+6; comp++) {
if (!pCOD || H263Info->adv_pred_mode)
reconblock_b(H263Info, comp-6,bx,by,Mode,pmvdbx,pmvdby);
if ( (pCBPB & (1<<(H263Info->blk_cnt-1-comp%6))) ) {
bp = H263Info->block[comp];
addblock(H263Info,comp,bx,by,1);
}
}
}
} /* end if (MBA > 0) */
if (!COD) {
Mode = H263Info->modemap[ypos+1][xpos+1];
/* decode blocks */
for (comp=0; comp<H263Info->blk_cnt; comp++) {
clearblock(H263Info, comp);
if (Mode == H263_MODE_INTRA || Mode == H263_MODE_INTRA_Q) { /* Intra */
bp = H263Info->block[comp];
if(H263Info->syntax_arith_coding) {
INTRADC_index = sv_H263SACDecode_a_symbol(BSIn,H263_cumf_INTRADC);
bp[0] = H263_intradctab[INTRADC_index];
_SlibDebug(_VERBOSE_, ScDebugPrintf(H263Info->dbg,
"getMBs() INTRADC Index: %d INTRADC: %d \n", INTRADC_index, bp[0]) );
}
else {
bp[0] = (int)ScBSGetBits(BSIn, 8);
_SlibDebug(_DEBUG_, ScDebugPrintf(H263Info->dbg, "getMBs() DC: %d \n", (int)bp[0]));
}
_SlibDebug(_WARN_ && bp[0] == 128,
ScDebugPrintf(H263Info->dbg, "getMBs() Illegal DC-coeff: 1000000\n"));
if (bp[0] == 255) /* Spec. in H.26P, not in TMN4 */
bp[0] = 128;
bp[0] *= 8; /* Iquant */
/* DC scale */
bp[0] *= (int)((float)(1 << 20) * (float)0.125) ;
if ( (CBP & (1<<(H263Info->blk_cnt-1-comp))) ) {
if (!H263Info->syntax_arith_coding)
sv_H263GetBlock(H263Info,BSIn,comp,0);
else
sv_H263GetSACblock(H263Info,BSIn,comp,0);
}
}
else { /* Inter */
if ( (CBP & (1<<(H263Info->blk_cnt-1-comp))) ) {
if (!H263Info->syntax_arith_coding)
sv_H263GetBlock(H263Info,BSIn,comp,1);
else
sv_H263GetSACblock(H263Info,BSIn,comp,1);
}
}
if (H263Info->fault) goto resync;
}
/* Decode B blocks */
if (H263Info->pb_frame) {
for (comp=6; comp<H263Info->blk_cnt+6; comp++) {
clearblock(H263Info, comp);
if ( (CBPB & (1<<(H263Info->blk_cnt-1-comp%6))) ) {
if (!H263Info->syntax_arith_coding)
sv_H263GetBlock(H263Info,BSIn,comp,1);
else
sv_H263GetSACblock(H263Info,BSIn,comp,1);
}
if (H263Info->fault) goto resync;
}
}
}
/* advance to next macroblock */
MBA++;
pCBP = CBP; pCBPB = CBPB; pCOD = COD;
pmvdbx = mvdbx; pmvdby = mvdby;
/* fflush(stdout); */
if (MBA >= MBAmax && !last_done) {
COD = 1;
xpos = 0;
ypos++;
last_done = 1;
goto reconstruct_mb;
}
}
_SlibDebug(_VERBOSE_, ScDebugPrintf(H263Info->dbg, "getMBs() exiting at MBA=%d\n", MBA) );
/* Burkhard */
#ifdef CAMERAMOTION
summarize_motion:
summarizemotion(framenum);
#endif
}
/* set block to zero */
static void clearblock(SvH263DecompressInfo_t *H263Info, int comp)
{
clearblk(comp) ;
#if 0
qword *bp;
int i;
bp = (qword *)H263Info->block[comp];
for (i=0; i<8; i++)
{
bp[0] = bp[1] = 0;
bp += 2;
}
#endif
}
/* move/add 8x8-Block from block[comp] to refframe or bframe */
static void addblock(SvH263DecompressInfo_t *H263Info, int comp, int bx, int by, int addflag)
{
int cc, iincr, P = 1;
unsigned char *rfp;
#ifdef USE_C
int i ;
unsigned qword *lp;
unsigned qword acc,src;
#endif
register int *bp;
bp = H263Info->block[comp];
if (comp >= 6) {
/* This is a component for B-frame forward prediction */
P = 0;
addflag = 1;
comp -= 6;
}
cc = (comp<4) ? 0 : (comp&1)+1; /* color component index */
if (cc==0) {
/* luminance */
/* frame DCT coding */
if (P)
rfp = H263Info->newframe[0]
+ H263Info->coded_picture_width*(by+((comp&2)<<2)) + bx + ((comp&1)<<3);
else
rfp = H263Info->bframe[0]
+ H263Info->coded_picture_width*(by+((comp&2)<<2)) + bx + ((comp&1)<<3);
iincr = H263Info->coded_picture_width;
}
else {
/* chrominance */
/* scale coordinates */
bx >>= 1;
by >>= 1;
/* frame DCT coding */
if (P)
rfp = H263Info->newframe[cc] + H263Info->chrom_width*by + bx;
else
rfp = H263Info->bframe[cc] + H263Info->chrom_width*by + bx;
iincr = H263Info->chrom_width;
}
if (addflag) {
#ifdef USE_C
ScScaleIDCT8x8i_C(bp, bp);
for (i=0; i<8; i++) {
lp = (unsigned qword *) rfp;
src = lp[0];
acc = (unsigned qword) H263Info->clp[bp[0]+(src & 0xff)];
acc |= (unsigned qword) H263Info->clp[bp[1]+((src >> 8) & 0xff)] << 8;
acc |= (unsigned qword) H263Info->clp[bp[2]+((src >> 16) & 0xff)] << 16;
acc |= (unsigned qword) H263Info->clp[bp[3]+((src >> 24) & 0xff)] << 24;
acc |= (unsigned qword) H263Info->clp[bp[4]+((src >> 32) & 0xff)] << 32;
acc |= (unsigned qword) H263Info->clp[bp[5]+((src >> 40) & 0xff)] << 40;
acc |= (unsigned qword) H263Info->clp[bp[6]+((src >> 48) & 0xff)] << 48;
acc |= (unsigned qword) H263Info->clp[bp[7]+((src >> 56) & 0xff)] << 56;
lp[0] = acc;
bp += 8;
rfp+= iincr;
}
#else
sv_H263IDCTAddToFrameP_S(bp,rfp,iincr) ;
#endif
}
else {
#ifdef USE_C
ScScaleIDCT8x8i_C(bp, bp);
for (i=0; i<8; i++) {
lp = (unsigned qword *) rfp;
acc = (unsigned qword ) H263Info->clp[bp[0]];
acc |= (unsigned qword ) H263Info->clp[bp[1]] << 8;
acc |= (unsigned qword ) H263Info->clp[bp[2]] << 16;
acc |= (unsigned qword ) H263Info->clp[bp[3]] << 24;
acc |= (unsigned qword ) H263Info->clp[bp[4]] << 32;
acc |= (unsigned qword ) H263Info->clp[bp[5]] << 40;
acc |= (unsigned qword ) H263Info->clp[bp[6]] << 48;
acc |= (unsigned qword ) H263Info->clp[bp[7]] << 56;
lp[0] = acc;
bp += 8;
rfp += iincr;
}
#else
sv_H263IDCTToFrameP_S(bp,rfp,iincr) ;
#endif
}
}
/* bidirectionally reconstruct 8x8-Block from block[comp] to bframe */
static void reconblock_b(SvH263DecompressInfo_t *H263Info, int comp, int bx, int by,
int mode, int bdx, int bdy)
{
int cc,i,j,k, ii;
register unsigned char *bfr, *ffr;
int BMVx, BMVy;
int xa,xb,ya,yb,x,y,xvec,yvec,mvx,mvy;
int xint,xhalf,yint,yhalf,pel;
x = bx/16+1;y=by/16+1;
if (mode == H263_MODE_INTER4V) {
if (comp < 4) {
/* luma */
mvx = H263Info->MV[0][comp+1][y][x];
mvy = H263Info->MV[1][comp+1][y][x];
BMVx = (bdx == 0 ? (H263Info->trb-H263Info->trd)* mvx/H263Info->trd : H263Info->trb * mvx/H263Info->trd + bdx - mvx);
BMVy = (bdy == 0 ? (H263Info->trb-H263Info->trd)* mvy/H263Info->trd : H263Info->trb * mvy/H263Info->trd + bdy - mvy);
}
else {
/* chroma */
xvec = yvec = 0;
for (k = 1; k <= 4; k++) {
mvx = H263Info->MV[0][k][y][x];
mvy = H263Info->MV[1][k][y][x];
xvec += (bdx == 0 ? (H263Info->trb-H263Info->trd)* mvx/H263Info->trd : H263Info->trb * mvx/H263Info->trd + bdx - mvx);
yvec += (bdy == 0 ? (H263Info->trb-H263Info->trd)* mvy/H263Info->trd : H263Info->trb * mvy/H263Info->trd + bdy - mvy);
}
/* chroma rounding (table 16/H.263) */
BMVx = sign(xvec)*(H263_roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
BMVy = sign(yvec)*(H263_roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
}
}
else {
if (comp < 4) {
/* luma */
mvx = H263Info->MV[0][0][y][x];
mvy = H263Info->MV[1][0][y][x];
BMVx = (bdx == 0 ? (H263Info->trb-H263Info->trd)* mvx/H263Info->trd : H263Info->trb * mvx/H263Info->trd + bdx - mvx);
BMVy = (bdy == 0 ? (H263Info->trb-H263Info->trd)* mvy/H263Info->trd : H263Info->trb * mvy/H263Info->trd + bdy - mvy);
}
else {
/* chroma */
mvx = H263Info->MV[0][0][y][x];
mvy = H263Info->MV[1][0][y][x];
xvec = (bdx == 0 ? (H263Info->trb-H263Info->trd)* mvx/H263Info->trd : H263Info->trb * mvx/H263Info->trd + bdx - mvx);
yvec = (bdy == 0 ? (H263Info->trb-H263Info->trd)* mvy/H263Info->trd : H263Info->trb * mvy/H263Info->trd + bdy - mvy);
xvec *= 4;
yvec *= 4;
/* chroma rounding (table 16/H.263) */
BMVx = sign(xvec)*(H263_roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
BMVy = sign(yvec)*(H263_roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
}
}
cc = (comp<4) ? 0 : (comp&1)+1; /* color component index */
if (cc==0) {
/* luminance */
find_bidir_limits(BMVx,&xa,&xb,comp&1);
find_bidir_limits(BMVy,&ya,&yb,(comp&2)>>1);
bfr = H263Info->bframe[0] +
H263Info->coded_picture_width*(by+((comp&2)<<2)) + bx + ((comp&1)<<3);
ffr = H263Info->newframe[0] +
H263Info->coded_picture_width*(by+((comp&2)<<2)) + bx + ((comp&1)<<3);
ii = H263Info->coded_picture_width;
}
else {
/* chrominance */
/* scale coordinates and vectors*/
bx >>= 1;
by >>= 1;
find_bidir_chroma_limits(BMVx,&xa,&xb);
find_bidir_chroma_limits(BMVy,&ya,&yb);
bfr = H263Info->bframe[cc] + H263Info->chrom_width*(by+((comp&2)<<2)) + bx + (comp&8);
ffr = H263Info->newframe[cc] + H263Info->chrom_width*(by+((comp&2)<<2)) + bx + (comp&8);
ii = H263Info->chrom_width;
}
xint = BMVx>>1;
xhalf = BMVx - 2*xint;
yint = BMVy>>1;
yhalf = BMVy - 2*yint;
ffr += xint + (yint+ya)*ii;
bfr += ya*ii;
if (!xhalf && !yhalf) {
for (j = ya; j < yb; j++) {
for (i = xa; i < xb; i++) {
pel = ffr[i];
bfr[i] = ((unsigned int)(pel + bfr[i]))>>1;
}
bfr += ii;
ffr += ii;
}
}
else if (xhalf && !yhalf) {
for (j = ya; j < yb; j++) {
for (i = xa; i < xb; i++) {
pel = ((unsigned int)(ffr[i]+ffr[i+1]+1))>>1;
bfr[i] = ((unsigned int)(pel + bfr[i]))>>1;
}
bfr += ii;
ffr += ii;
}
}
else if (!xhalf && yhalf) {
for (j = ya; j < yb; j++) {
for (i = xa; i < xb; i++) {
pel = ((unsigned int)(ffr[i]+ffr[ii+i]+1))>>1;
bfr[i] = ((unsigned int)(pel + bfr[i]))>>1;
}
bfr += ii;
ffr += ii;
}
}
else { /* if (xhalf && yhalf) */
for (j = ya; j < yb; j++) {
for (i = xa; i < xb; i++) {
pel = ((unsigned int)(ffr[i]+ffr[i+1]+ffr[ii+i]+ffr[ii+i+1]+2))>>2;
bfr[i] = ((unsigned int)(pel + bfr[i]))>>1;
}
bfr += ii;
ffr += ii;
}
}
return;
}
static int motion_decode(SvH263DecompressInfo_t *H263Info, int vec, int pmv)
{
if (vec > 31) vec -= 64;
vec += pmv;
if (!H263Info->long_vectors) {
if (vec > 31)
vec -= 64;
if (vec < -32)
vec += 64;
}
else {
if (pmv < -31 && vec < -63)
vec += 64;
if (pmv > 32 && vec > 63)
vec -= 64;
}
return vec;
}
static int find_pmv(SvH263DecompressInfo_t *H263Info, int x, int y, int block, int comp)
{
int p1,p2,p3;
int xin1,xin2,xin3;
int yin1,yin2,yin3;
int vec1,vec2,vec3;
int l8,o8,or8;
x++;y++;
l8 = (H263Info->modemap[y][x-1] == H263_MODE_INTER4V ? 1 : 0);
o8 = (H263Info->modemap[y-1][x] == H263_MODE_INTER4V ? 1 : 0);
or8 = (H263Info->modemap[y-1][x+1] == H263_MODE_INTER4V ? 1 : 0);
switch (block) {
case 0:
vec1 = (l8 ? 2 : 0) ; yin1 = y ; xin1 = x-1;
vec2 = (o8 ? 3 : 0) ; yin2 = y-1; xin2 = x;
vec3 = (or8? 3 : 0) ; yin3 = y-1; xin3 = x+1;
break;
case 1:
vec1 = (l8 ? 2 : 0) ; yin1 = y ; xin1 = x-1;
vec2 = (o8 ? 3 : 0) ; yin2 = y-1; xin2 = x;
vec3 = (or8? 3 : 0) ; yin3 = y-1; xin3 = x+1;
break;
case 2:
vec1 = 1 ; yin1 = y ; xin1 = x;
vec2 = (o8 ? 4 : 0) ; yin2 = y-1; xin2 = x;
vec3 = (or8? 3 : 0) ; yin3 = y-1; xin3 = x+1;
break;
case 3:
vec1 = (l8 ? 4 : 0) ; yin1 = y ; xin1 = x-1;
vec2 = 1 ; yin2 = y ; xin2 = x;
vec3 = 2 ; yin3 = y ; xin3 = x;
break;
case 4:
vec1 = 3 ; yin1 = y ; xin1 = x;
vec2 = 1 ; yin2 = y ; xin2 = x;
vec3 = 2 ; yin3 = y ; xin3 = x;
break;
default:
fprintf(stderr,"Illegal block number in find_pmv (getpic.c)\n");
exit(1);
break;
}
p1 = H263Info->MV[comp][vec1][yin1][xin1];
p2 = H263Info->MV[comp][vec2][yin2][xin2];
p3 = H263Info->MV[comp][vec3][yin3][xin3];
if (H263Info->newgob && (block == 0 || block == 1 || block == 2))
p2 = H263_NO_VEC;
if (p2 == H263_NO_VEC) { p2 = p3 = p1; }
return p1+p2+p3 - mmax(p1,mmax(p2,p3)) - mmin(p1,mmin(p2,p3));
}
void find_bidir_limits(int vec, int *start, int *stop, int nhv)
{
/* limits taken from C loop in section G5 in H.263 */
*start = mmax(0,(-vec+1)/2 - nhv*8);
*stop = mmin(7,15-(vec+1)/2 - nhv*8);
(*stop)++; /* I use < and not <= in the loop */
}
void find_bidir_chroma_limits(int vec, int *start, int *stop)
{
/* limits taken from C loop in section G5 in H.263 */
*start = mmax(0,(-vec+1)/2);
*stop = mmin(7,7-(vec+1)/2);
(*stop)++; /* I use < and not <= in the loop */
return;
}
void make_edge_image(unsigned char *src, unsigned char *dst, int width, int height, int edge)
{
int i,j,incrp,incro;
register unsigned char *p1,*p2,*p3,*p4;
register unsigned char *o1,*o2,*o3,*o4;
register unsigned int *dp1, *do1 ;
/* center image */
/*
p1 = dst;
o1 = src;
for (j = 0; j < height;j++) {
for (i = 0; i < width; i++) {
*(p1 + i) = *(o1 + i);
}
p1 += width + (edge<<1);
o1 += width;
}
*/
dp1 = (unsigned int *)dst ;
do1 = (unsigned int *)src ;
incrp = (width + (edge<<1))/4 ;
incro = width/4 ;
for (j = 0; j < height;j++) {
for (i = 0; i < width/4; i++) {
*(dp1 + i) = *(do1 + i);
}
dp1 += incrp;
do1 += incro;
}
/* left and right edges */
p1 = dst-1;
o1 = src;
incrp = width + (edge<<1) ;
incro = width ;
for (j = 0; j < height;j++) {
for (i = 0; i < edge; i++) {
*(p1 - i) = *o1;
*(p1 + width + i + 1) = *(o1 + width - 1);
}
p1 += incrp;
o1 += incro;
}
/* top and bottom edges */
p1 = dst;
p2 = dst + (width + (edge<<1))*(height-1);
o1 = src;
o2 = src + width*(height-1);
incrp = (width + (edge<<1)) ;
for (j = 0; j < edge;j++) {
p1 -= incrp ;
p2 += incrp ;
for (i = 0; i < width; i++) {
*(p1 + i) = *(o1 + i);
*(p2 + i) = *(o2 + i);
}
}
/* corners */
p1 = dst - (width+(edge<<1)) - 1;
p2 = p1 + width + 1;
p3 = dst + (width+(edge<<1))*(height)-1;
p4 = p3 + width + 1;
o1 = src;
o2 = o1 + width - 1;
o3 = src + width*(height-1);
o4 = o3 + width - 1;
incrp = (width + (edge<<1)) ;
for (j = 0; j < edge; j++) {
for (i = 0; i < edge; i++) {
*(p1 - i) = *o1;
*(p2 + i) = *o2;
*(p3 - i) = *o3;
*(p4 + i) = *o4;
}
p1 -= incrp ;
p2 -= incrp ;
p3 += incrp ;
p4 += incrp ;
}
}
/* only used for displayed interpolated frames, not reconstructed ones */
void interpolate_image(unsigned char *in, unsigned char *out, int width, int height)
{
register int x,xx,y,w2;
register unsigned char *pp,*ii;
return ;
w2 = 2*width;
/* Horizontally */
pp = out;
ii = in;
for (y = 0; y < height-1; y++) {
for (x = 0,xx=0; x < width-1; x++,xx+=2) {
*(pp + xx) = *(ii + x);
*(pp + xx+1) = ((unsigned int)(*(ii + x) + *(ii + x + 1)))>>1;
*(pp + w2 + xx) = ((unsigned int)(*(ii + x) + *(ii + x + width)))>>1;
*(pp + w2 + xx+1) = ((unsigned int)(*(ii + x) + *(ii + x + 1) +
*(ii + x + width) + *(ii + x + width + 1)))>>2;
}
*(pp + w2 - 2) = *(ii + width - 1);
*(pp + w2 - 1) = *(ii + width - 1);
*(pp + w2 + w2 - 2) = *(ii + width + width - 1);
*(pp + w2 + w2 - 1) = *(ii + width + width - 1);
pp += w2<<1;
ii += width;
}
/* last lines */
for (x = 0,xx=0; x < width-1; x++,xx+=2) {
*(pp+ xx) = *(ii + x);
*(pp+ xx+1) = ((unsigned int)(*(ii + x) + *(ii + x + 1) + 1))>>1;
*(pp+ w2+ xx) = *(ii + x);
*(pp+ w2+ xx+1) = ((unsigned int)(*(ii + x) + *(ii + x + 1) + 1))>>1;
}
/* bottom right corner pels */
*(pp + (width<<1) - 2) = *(ii + width -1);
*(pp + (width<<1) - 1) = *(ii + width -1);
*(pp + (width<<2) - 2) = *(ii + width -1);
*(pp + (width<<2) - 1) = *(ii + width -1);
return;
}