/*
*
* This file is part of libmpeg3
*
* LibMPEG3
* Author: Adam Williams <[email protected]>
* Page: heroine.linuxbox.com
* Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak)
*
LibMPEG3 was originally licenced under GPL. It was relicensed by
the author under the LGPL and the Squeak license on Nov 1st, 2000
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also licensed under the Squeak license.
http://www.squeak.org/license.html
*/
#include "mpeg3video.h"
#include "slice.h"
#include "vlc.h"
#include <stdio.h>
int mpeg3video_get_macroblock_address(mpeg3_slice_t *slice)
{
int code, val = 0;
mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
while((code = mpeg3slice_showbits(slice_buffer, 11)) < 24)
{
/* Is not macroblock_stuffing */
if(code != 15)
{
/* Is macroblock_escape */
if(code == 8)
{
val += 33;
}
else
{
/* fprintf(stderr, "mpeg3video_get_macroblock_address: invalid macroblock_address_increment code\n"); */
slice->fault = 1;
return 1;
}
}
mpeg3slice_flushbits(slice_buffer, 11);
}
if(code >= 1024)
{
mpeg3slice_flushbit(slice_buffer);
return val + 1;
}
if(code >= 128)
{
code >>= 6;
mpeg3slice_flushbits(slice_buffer, mpeg3_MBAtab1[code].len);
return val + mpeg3_MBAtab1[code].val;
}
code -= 24;
mpeg3slice_flushbits(slice_buffer, mpeg3_MBAtab2[code].len);
return val + mpeg3_MBAtab2[code].val;
}
/* macroblock_type for pictures with spatial scalability */
static inline int mpeg3video_getsp_imb_type(mpeg3_slice_t *slice)
{
mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
unsigned int code = mpeg3slice_showbits(slice_buffer, 4);
if(!code)
{
/* fprintf(stderr,"mpeg3video_getsp_imb_type: invalid macroblock_type code\n"); */
slice->fault = 1;
return 0;
}
mpeg3slice_flushbits(slice_buffer, mpeg3_spIMBtab[code].len);
return mpeg3_spIMBtab[code].val;
}
static inline int mpeg3video_getsp_pmb_type(mpeg3_slice_t *slice)
{
mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
int code = mpeg3slice_showbits(slice_buffer, 7);
if(code < 2)
{
/* fprintf(stderr,"mpeg3video_getsp_pmb_type: invalid macroblock_type code\n"); */
slice->fault = 1;
return 0;
}
if(code >= 16)
{
code >>= 3;
mpeg3slice_flushbits(slice_buffer, mpeg3_spPMBtab0[code].len);
return mpeg3_spPMBtab0[code].val;
}
mpeg3slice_flushbits(slice_buffer, mpeg3_spPMBtab1[code].len);
return mpeg3_spPMBtab1[code].val;
}
static inline int mpeg3video_getsp_bmb_type(mpeg3_slice_t *slice)
{
mpeg3_VLCtab_t *p;
mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
int code = mpeg3slice_showbits9(slice_buffer);
if(code >= 64)
p = &mpeg3_spBMBtab0[(code >> 5) - 2];
else
if(code >= 16)
p = &mpeg3_spBMBtab1[(code >> 2) - 4];
else
if(code >= 8)
p = &mpeg3_spBMBtab2[code - 8];
else
{
/* fprintf(stderr,"mpeg3video_getsp_bmb_type: invalid macroblock_type code\n"); */
slice->fault = 1;
return 0;
}
mpeg3slice_flushbits(slice_buffer, p->len);
return p->val;
}
static inline int mpeg3video_get_imb_type(mpeg3_slice_t *slice)
{
mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
if(mpeg3slice_getbit(slice_buffer))
{
return 1;
}
if(!mpeg3slice_getbit(slice_buffer))
{
/* fprintf(stderr,"mpeg3video_get_imb_type: invalid macroblock_type code\n"); */
slice->fault = 1;
}
return 17;
}
static inline int mpeg3video_get_pmb_type(mpeg3_slice_t *slice)
{
int code;
mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
if((code = mpeg3slice_showbits(slice_buffer, 6)) >= 8)
{
code >>= 3;
mpeg3slice_flushbits(slice_buffer, mpeg3_PMBtab0[code].len);
return mpeg3_PMBtab0[code].val;
}
if(code == 0)
{
/* fprintf(stderr,"mpeg3video_get_pmb_type: invalid macroblock_type code\n"); */
slice->fault = 1;
return 0;
}
mpeg3slice_flushbits(slice_buffer, mpeg3_PMBtab1[code].len);
return mpeg3_PMBtab1[code].val;
}
static inline int mpeg3video_get_bmb_type(mpeg3_slice_t *slice)
{
int code;
mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
if((code = mpeg3slice_showbits(slice_buffer, 6)) >= 8)
{
code >>= 2;
mpeg3slice_flushbits(slice_buffer, mpeg3_BMBtab0[code].len);
return mpeg3_BMBtab0[code].val;
}
if(code == 0)
{
/* fprintf(stderr,"mpeg3video_get_bmb_type: invalid macroblock_type code\n"); */
slice->fault = 1;
return 0;
}
mpeg3slice_flushbits(slice_buffer, mpeg3_BMBtab1[code].len);
return mpeg3_BMBtab1[code].val;
}
static inline int mpeg3video_get_dmb_type(mpeg3_slice_t *slice)
{
if(!mpeg3slice_getbit(slice->slice_buffer))
{
/* fprintf(stderr,"mpeg3video_get_dmb_type: invalid macroblock_type code\n"); */
slice->fault=1;
}
return 1;
}
static inline int mpeg3video_get_snrmb_type(mpeg3_slice_t *slice)
{
mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
int code = mpeg3slice_showbits(slice_buffer, 3);
if(code == 0)
{
/* fprintf(stderr,"mpeg3video_get_snrmb_type: invalid macroblock_type code\n"); */
slice->fault = 1;
return 0;
}
mpeg3slice_flushbits(slice_buffer, mpeg3_SNRMBtab[code].len);
return mpeg3_SNRMBtab[code].val;
}
int mpeg3video_get_mb_type(mpeg3_slice_t *slice, mpeg3video_t *video)
{
if(video->scalable_mode == SC_SNR)
{
return mpeg3video_get_snrmb_type(slice);
}
else
{
switch(video->pict_type)
{
case I_TYPE: return video->pict_scal ? mpeg3video_getsp_imb_type(slice) : mpeg3video_get_imb_type(slice);
case P_TYPE: return video->pict_scal ? mpeg3video_getsp_pmb_type(slice) : mpeg3video_get_pmb_type(slice);
case B_TYPE: return video->pict_scal ? mpeg3video_getsp_bmb_type(slice) : mpeg3video_get_bmb_type(slice);
case D_TYPE: return mpeg3video_get_dmb_type(slice);
default:
/*fprintf(stderr, "mpeg3video_getmbtype: unknown coding type\n"); */
break;
/* MPEG-1 only, not implemented */
}
}
return 0;
}
int mpeg3video_macroblock_modes(mpeg3_slice_t *slice,
mpeg3video_t *video,
int *pmb_type,
int *pstwtype,
int *pstwclass,
int *pmotion_type,
int *pmv_count,
int *pmv_format,
int *pdmv,
int *pmvscale,
int *pdct_type)
{
int mb_type;
int stwtype, stwcode, stwclass;
int motion_type = 0, mv_count, mv_format, dmv, mvscale;
int dct_type;
mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
static unsigned char stwc_table[3][4]
= { {6,3,7,4}, {2,1,5,4}, {2,5,7,4} };
static unsigned char stwclass_table[9]
= {0, 1, 2, 1, 1, 2, 3, 3, 4};
/* get macroblock_type */
mb_type = mpeg3video_get_mb_type(slice, video);
if(slice->fault) return 1;
/* get spatial_temporal_weight_code */
if(mb_type & MB_WEIGHT)
{
if(video->stwc_table_index == 0)
stwtype = 4;
else
{
stwcode = mpeg3slice_getbits2(slice_buffer);
stwtype = stwc_table[video->stwc_table_index - 1][stwcode];
}
}
else
stwtype = (mb_type & MB_CLASS4) ? 8 : 0;
/* derive spatial_temporal_weight_class (Table 7-18) */
stwclass = stwclass_table[stwtype];
/* get frame/field motion type */
if(mb_type & (MB_FORWARD | MB_BACKWARD))
{
if(video->pict_struct == FRAME_PICTURE)
{
/* frame_motion_type */
motion_type = video->frame_pred_dct ? MC_FRAME : mpeg3slice_getbits2(slice_buffer);
}
else
{
/* field_motion_type */
motion_type = mpeg3slice_getbits2(slice_buffer);
}
}
else
if((mb_type & MB_INTRA) && video->conceal_mv)
{
/* concealment motion vectors */
motion_type = (video->pict_struct == FRAME_PICTURE) ? MC_FRAME : MC_FIELD;
}
/* derive mv_count, mv_format and dmv, (table 6-17, 6-18) */
if(video->pict_struct == FRAME_PICTURE)
{
mv_count = (motion_type == MC_FIELD && stwclass < 2) ? 2 : 1;
mv_format = (motion_type == MC_FRAME) ? MV_FRAME : MV_FIELD;
}
else
{
mv_count = (motion_type == MC_16X8) ? 2 : 1;
mv_format = MV_FIELD;
}
dmv = (motion_type == MC_DMV); /* dual prime */
/* field mv predictions in frame pictures have to be scaled */
mvscale = ((mv_format == MV_FIELD) && (video->pict_struct == FRAME_PICTURE));
/* get dct_type (frame DCT / field DCT) */
dct_type = (video->pict_struct == FRAME_PICTURE) &&
(!video->frame_pred_dct) &&
(mb_type & (MB_PATTERN | MB_INTRA)) ?
mpeg3slice_getbit(slice_buffer) : 0;
/* return values */
*pmb_type = mb_type;
*pstwtype = stwtype;
*pstwclass = stwclass;
*pmotion_type = motion_type;
*pmv_count = mv_count;
*pmv_format = mv_format;
*pdmv = dmv;
*pmvscale = mvscale;
*pdct_type = dct_type;
return 0;
}
|