/*===========================================================================*
* mheaders.c *
* *
* Procedures to generate MPEG headers *
* *
* EXPORTED PROCEDURES: *
* Mhead_GenPictureHeader *
* Mhead_GenSequenceHeader *
* Mhead_GenSequenceEnder *
* Mhead_GenGOPHeader *
* Mhead_GenSliceHeader *
* Mhead_GenSliceEnder *
* Mhead_GenMBHeader *
* *
*===========================================================================*/
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/*
* $Header: /share/cvs/AFNI/src/mpeg_encodedir/mheaders.c,v 1.4 2004/04/02 15:12:40 rwcox Exp $
* $Log: mheaders.c,v $
* Revision 1.4 2004/04/02 15:12:40 rwcox
* Cput
*
* Revision 1.3 2003/12/23 13:50:08 rwcox
* Cput
*
* Revision 1.2 2003/12/03 14:46:14 rwcox
* Cput
*
* Revision 1.1 2001/12/17 16:11:54 rwcox
* Cadd
*
* Revision 1.15 1995/08/07 21:45:19 smoot
* check for illegal MVs (shouldnt ever be called, but....)
* fix bug which made us not weite Iframe Qscale changes
* warns if writing a size=0 mpeg
*
* Revision 1.14 1995/05/22 20:53:35 smoot
* corrected bit_rate value in constrained params flag
*
* Revision 1.13 1995/05/02 01:50:38 eyhung
* made VidRateNum un-static
*
* Revision 1.12 1995/03/27 19:28:23 smoot
* auto-determines Qscale changes (was mb_quant)
*
* Revision 1.11 1995/02/16 09:12:39 eyhung
* fixed compile bug with HP7xx
*
* Revision 1.10 1995/01/25 22:53:50 smoot
* Better buf_size checking, and actually check constrained params
*
* Revision 1.9 1995/01/19 23:08:47 eyhung
* Changed copyrights
*
* Revision 1.8 1995/01/16 08:45:10 eyhung
* BLEAH'ed hsize and vsize
*
* Revision 1.7 1994/12/09 22:27:17 smoot
* Fixed buffer size in stream
*
* Revision 1.6 1994/11/12 02:11:54 keving
* nothing
*
* Revision 1.5 1994/03/15 00:27:11 keving
* nothing
*
* Revision 1.4 1993/12/22 19:19:01 keving
* nothing
*
* Revision 1.3 1993/07/22 22:23:43 keving
* nothing
*
* Revision 1.2 1993/06/30 20:06:09 keving
* nothing
*
* Revision 1.1 1993/06/03 21:08:08 keving
* nothing
*
* Revision 1.6 1993/03/01 23:03:40 keving
* nothing
*
* Revision 1.5 1993/02/17 23:18:20 dwallach
* checkin prior to keving's joining the project
*
* Revision 1.4 1993/01/18 10:20:02 dwallach
* *** empty log message ***
*
* Revision 1.3 1993/01/18 10:17:29 dwallach
* RCS headers installed, code indented uniformly
*
* Revision 1.3 1993/01/18 10:17:29 dwallach
* RCS headers installed, code indented uniformly
*
*/
/*==============*
* HEADER FILES *
*==============*/
#include "all.h"
#include "bitio.h"
#include "frames.h"
#include "mheaders.h"
/*==================*
* STATIC VARIABLES *
*==================*/
static int gopStartFrame = 0;
static int lastGOPStart = 0;
static int lastQSSet;
static uint32 mbAddrIncrTable[][2] = {
{0x0, 0},
{0x1, 1},
{0x3, 3},
{0x2, 3},
{0x3, 4},
{0x2, 4},
{0x3, 5},
{0x2, 5},
{0x7, 7},
{0x6, 7},
{0xb, 8},
{0xa, 8},
{0x9, 8},
{0x8, 8},
{0x7, 8},
{0x6, 8},
{0x17, 10},
{0x16, 10},
{0x15, 10},
{0x14, 10},
{0x13, 10},
{0x12, 10},
{0x23, 11},
{0x22, 11},
{0x21, 11},
{0x20, 11},
{0x1f, 11},
{0x1e, 11},
{0x1d, 11},
{0x1c, 11},
{0x1b, 11},
{0x1a, 11},
{0x19, 11},
{0x18, 11}};
static uint32 mbMotionVectorTable[][2] = {
{0x19, 11},
{0x1b, 11},
{0x1d, 11},
{0x1f, 11},
{0x21, 11},
{0x23, 11},
{0x13, 10},
{0x15, 10},
{0x17, 10},
{0x7, 8},
{0x9, 8},
{0xb, 8},
{0x7, 7},
{0x3, 5},
{0x3, 4},
{0x3, 3},
{0x1, 1},
{0x2, 3},
{0x2, 4},
{0x2, 5},
{0x6, 7},
{0xa, 8},
{0x8, 8},
{0x6, 8},
{0x16, 10},
{0x14, 10},
{0x12, 10},
{0x22, 11},
{0x20, 11},
{0x1e, 11},
{0x1c, 11},
{0x1a, 11},
{0x18, 11}};
static uint32 mbPatTable[][2] = {
{0x0, 0},
{0xb, 5},
{0x9, 5},
{0xd, 6},
{0xd, 4},
{0x17, 7},
{0x13, 7},
{0x1f, 8},
{0xc, 4},
{0x16, 7},
{0x12, 7},
{0x1e, 8},
{0x13, 5},
{0x1b, 8},
{0x17, 8},
{0x13, 8},
{0xb, 4},
{0x15, 7},
{0x11, 7},
{0x1d, 8},
{0x11, 5},
{0x19, 8},
{0x15, 8},
{0x11, 8},
{0xf, 6},
{0xf, 8},
{0xd, 8},
{0x3, 9},
{0xf, 5},
{0xb, 8},
{0x7, 8},
{0x7, 9},
{0xa, 4},
{0x14, 7},
{0x10, 7},
{0x1c, 8},
{0xe, 6},
{0xe, 8},
{0xc, 8},
{0x2, 9},
{0x10, 5},
{0x18, 8},
{0x14, 8},
{0x10, 8},
{0xe, 5},
{0xa, 8},
{0x6, 8},
{0x6, 9},
{0x12, 5},
{0x1a, 8},
{0x16, 8},
{0x12, 8},
{0xd, 5},
{0x9, 8},
{0x5, 8},
{0x5, 9},
{0xc, 5},
{0x8, 8},
{0x4, 8},
{0x4, 9},
{0x7, 3},
{0xa, 5}, /* grrr... 61, 62, 63 added - Kevin */
{0x8, 5},
{0xc, 6}
};
/*===========*
* CONSTANTS *
*===========*/
#define SEQ_HEAD_CODE 0x000001b3
#define EXT_START_CODE 0x000001b5
#define USER_START_CODE 0x000001b2
#define GOP_START_CODE 0x000001b8
#define PICT_START_CODE 0x00000100
#define SLICE_BASE_CODE 0x00000100
#define SEQ_END_CODE 0x000001b7
/* not static anymore because information is used for computing frame rate
* and for statistics */
const double VidRateNum[9]={1.0, 23.976, 24.0, 25.0, 29.97, 30.0,
50.0 ,59.94, 60.0};
/*===============================*
* INTERNAL PROCEDURE prototypes *
*===============================*/
static void GenMBAddrIncr _ANSI_ARGS_((BitBucket *bb, uint32 addr_incr));
static void GenPictHead _ANSI_ARGS_((BitBucket *bb, uint32 temp_ref,
uint32 code_type, uint32 vbv_delay,
int32 full_pel_forw_flag, uint32 forw_f_code,
int32 full_pel_back_flag, uint32 back_f_code,
uint8 *extra_info, uint32 extra_info_size,
uint8 *ext_data, uint32 ext_data_size,
uint8 *user_data, uint32 user_data_size));
static void GenMBType _ANSI_ARGS_((BitBucket *bb, uint32 pict_code_type,
uint32 mb_quant, uint32 motion_forw, uint32 motion_back,
uint32 mb_pattern, uint32 mb_intra));
static void GenMotionCode _ANSI_ARGS_((BitBucket *bb, int32 vector));
static void GenBlockPattern _ANSI_ARGS_((BitBucket *bb,
uint32 mb_pattern));
/*=====================*
* EXPORTED PROCEDURES *
*=====================*/
/*===========================================================================*
*
* SetGOPStartTime
*
* sets the start frame of the GOP; to be used with GenPictureHeader
*
* RETURNS: nothing
*
* SIDE EFFECTS: none
*
*===========================================================================*/
void
SetGOPStartTime(index)
int index;
{
lastGOPStart = gopStartFrame;
gopStartFrame = index;
}
/*===========================================================================*
*
* Mhead_GenPictureHeader
*
* generate picture header with given frame type and picture count
* append result to the specified bitstream
*
* RETURNS: nothing
*
* SIDE EFFECTS: none
*
*===========================================================================*/
void
Mhead_GenPictureHeader(bbPtr, frameType, pictCount, f_code)
BitBucket *bbPtr;
int frameType;
int pictCount;
int f_code;
{
int temporalRef;
if ( pictCount >= gopStartFrame ) {
temporalRef = (pictCount-gopStartFrame);
} else {
temporalRef = (pictCount-lastGOPStart);
}
temporalRef = (temporalRef % 1024);
DBG_PRINT(("Picture Header\n"));
GenPictHead(bbPtr, temporalRef, frameType,
0 /* vbv_delay */,
pixelFullSearch /* full_pel_forw_flag */,
f_code /* forw_f_code */,
pixelFullSearch /* full_pel_back_flag */,
f_code /* back_f_code */,
NULL, 0, NULL, 0, NULL, 0);
}
/*===========================================================================*
*
* Mhead_GenSequenceHeader
*
* generate sequence header with given attributes
* append result to the specified bitstream
*
* RETURNS: nothing
*
* SIDE EFFECTS: none
*
*===========================================================================*/
void
Mhead_GenSequenceHeader(bbPtr, hsize, vsize, pratio, pict_rate, bit_rate,
buf_size, c_param_flag, iq_matrix, niq_matrix,
ext_data, ext_data_size, user_data, user_data_size)
BitBucket *bbPtr;
uint32 hsize;
uint32 vsize;
int32 pratio;
int32 pict_rate;
int32 bit_rate;
int32 buf_size;
int32 c_param_flag;
int32 *iq_matrix;
int32 *niq_matrix;
uint8 *ext_data;
int32 ext_data_size;
uint8 *user_data;
int32 user_data_size;
{
extern int ZAG[];
int i;
/* Write seq start code. */
Bitio_Write(bbPtr, SEQ_HEAD_CODE, 32);
/* Write horiz. and vert. sizes. */
#ifdef BLEAH
fprintf(stdout, "hsize, vsize = %d, %d\n", hsize, vsize);
#endif
if (hsize==0 || vsize==0) {
fprintf(stderr, "Writing zero size to stream!\n");
}
Bitio_Write(bbPtr, hsize, 12);
Bitio_Write(bbPtr, vsize, 12);
/* Write pixel aspect ratio, negative values default to 1. */
if (pratio < 0) {
fprintf(stderr, "PROGRAMMER ERROR: pratio = %d\n", pratio);
exit(1);
}
Bitio_Write(bbPtr, pratio, 4);
/* Wrtie picture rate, negative values default to 30 fps. */
if (pict_rate < 0) {
fprintf(stderr, "PROGRAMMER ERROR: pict_rate = %d\n", pict_rate);
exit(1);
}
Bitio_Write(bbPtr, pict_rate, 4);
/* Write bit rate, negative values default to variable. */
if (bit_rate < 0) {
bit_rate = -1;
} else {
bit_rate = bit_rate / 400;
}
Bitio_Write(bbPtr, bit_rate, 18);
/* Marker bit. */
Bitio_Write(bbPtr, 0x1, 1);
/* Write VBV buffer size. Negative values default to zero. */
if (buf_size < 0) {
buf_size = 0;
}
buf_size = (buf_size + (16*1024 - 1)) / (16*1024);
if (buf_size>=0x400) buf_size=0x3ff;
Bitio_Write(bbPtr, buf_size, 10);
/* Write constrained parameter flag. */
{
int num_mb = ((hsize+15)/16) * ((vsize+15)/16);
/* At present we cheat on buffer size */
c_param_flag = ((bit_rate <= 4640) &&
(bit_rate >0) &&
(buf_size <= 20) &&
(pict_rate >= 1) &&
(pict_rate <= 5) &&
(hsize <= 768) &&
(vsize <= 576) &&
(num_mb <= 396) &&
(num_mb*VidRateNum[pict_rate] <= 9900) &&
(fCodeP<=4) &&
(fCodeB<=4));
}
if (c_param_flag) {
Bitio_Write(bbPtr, 0x01, 1);
} else {
Bitio_Write(bbPtr, 0x00, 1);
}
/* Write intra quant matrix if present. */
if (iq_matrix != NULL) {
Bitio_Write(bbPtr, 0x01, 1);
for (i = 0; i < 64; i++) {
Bitio_Write(bbPtr, iq_matrix[ZAG[i]], 8);
}
} else {
Bitio_Write(bbPtr, 0x00, 1);
}
/* Write non intra quant matrix if present. */
if (niq_matrix != NULL) {
Bitio_Write(bbPtr, 0x01, 1);
for (i = 0; i < 64; i++) {
Bitio_Write(bbPtr, niq_matrix[ZAG[i]], 8);
}
} else {
Bitio_Write(bbPtr, 0x00, 1);
}
/* next start code */
Bitio_BytePad(bbPtr);
/* Write ext data if present. */
if (ext_data != NULL) {
Bitio_Write(bbPtr, EXT_START_CODE, 32);
for (i = 0; i < ext_data_size; i++) {
Bitio_Write(bbPtr, ext_data[i], 8);
}
Bitio_BytePad(bbPtr);
}
/* Write user data if present. */
if ((user_data != NULL) && (user_data_size != 0)) {
Bitio_Write(bbPtr, USER_START_CODE, 32);
for (i = 0; i < user_data_size; i++) {
Bitio_Write(bbPtr, user_data[i], 8);
}
Bitio_BytePad(bbPtr);
}
}
/*===========================================================================*
*
* Mhead_GenSequenceEnder
*
* generate sequence ender
* append result to the specified bitstream
*
* RETURNS: nothing
*
* SIDE EFFECTS: none
*
*===========================================================================*/
void
Mhead_GenSequenceEnder(bbPtr)
BitBucket *bbPtr;
{
Bitio_Write(bbPtr, SEQ_END_CODE, 32);
}
/*===========================================================================*
*
* Mhead_GenGOPHeader
*
* generate GOP header with specified attributes
* append result to the specified bitstream
*
* RETURNS: nothing
*
* SIDE EFFECTS: none
*
*===========================================================================*/
void
Mhead_GenGOPHeader(bbPtr, drop_frame_flag, tc_hrs, tc_min, tc_sec, tc_pict,
closed_gop, broken_link, ext_data, ext_data_size,
user_data, user_data_size)
BitBucket *bbPtr;
int32 drop_frame_flag;
int32 tc_hrs;
int32 tc_min;
int32 tc_sec;
int32 tc_pict;
int32 closed_gop;
int32 broken_link;
uint8 *ext_data;
int32 ext_data_size;
uint8 *user_data;
int32 user_data_size;
{
int i;
/* Write gop start code. */
Bitio_Write(bbPtr, GOP_START_CODE, 32);
/* Construct and write timecode. */
/* Drop frame flag. */
if (drop_frame_flag) {
Bitio_Write(bbPtr, 0x01, 1);
} else {
Bitio_Write(bbPtr, 0x00, 1);
}
/* Time code hours. */
Bitio_Write(bbPtr, tc_hrs, 5);
/* Time code minutes. */
Bitio_Write(bbPtr, tc_min, 6);
/* Marker bit. */
Bitio_Write(bbPtr, 0x01, 1);
/* Time code seconds. */
Bitio_Write(bbPtr, tc_sec, 6);
/* Time code pictures. */
Bitio_Write(bbPtr, tc_pict, 6);
/* Closed gop flag. */
if (closed_gop) {
Bitio_Write(bbPtr, 0x01, 1);
} else {
Bitio_Write(bbPtr, 0x00, 1);
}
/* Broken link flag. */
if (broken_link) {
Bitio_Write(bbPtr, 0x01, 1);
} else {
Bitio_Write(bbPtr, 0x00, 1);
}
/* next start code */
Bitio_BytePad(bbPtr);
/* Write ext data if present. */
if (ext_data != NULL) {
Bitio_Write(bbPtr, EXT_START_CODE, 32);
for (i = 0; i < ext_data_size; i++) {
Bitio_Write(bbPtr, ext_data[i], 8);
}
Bitio_BytePad(bbPtr);
}
/* Write user data if present. */
if (user_data != NULL) {
Bitio_Write(bbPtr, USER_START_CODE, 32);
for (i = 0; i < user_data_size; i++) {
Bitio_Write(bbPtr, user_data[i], 8);
}
Bitio_BytePad(bbPtr);
}
}
/*===========================================================================*
*
* Mhead_GenSliceHeader
*
* generate slice header with specified attributes
* append result to the specified bitstream
*
* RETURNS: nothing
*
* SIDE EFFECTS: none
*
*===========================================================================*/
void
Mhead_GenSliceHeader(bbPtr, verticalPos, qscale, extra_info, extra_info_size)
BitBucket *bbPtr;
uint32 verticalPos;
uint32 qscale;
uint8 *extra_info;
uint32 extra_info_size;
{
int i;
/* Write slice start code. */
Bitio_Write(bbPtr, (SLICE_BASE_CODE + verticalPos), 32);
/* Quant. scale. */
Bitio_Write(bbPtr, qscale, 5);
lastQSSet = qscale;
/* Extra bit slice info. */
if (extra_info != NULL) {
for (i = 0; i < extra_info_size; i++) {
Bitio_Write(bbPtr, 0x01, 1);
Bitio_Write(bbPtr, extra_info[i], 8);
}
}
/* extra_bit_slice */
Bitio_Write(bbPtr, 0x00, 1);
}
/*===========================================================================*
*
* Mhead_GenSliceEnder
*
* generate slice ender
* append result to the specified bitstream
*
* RETURNS: nothing
*
* SIDE EFFECTS: none
*
*===========================================================================*/
void
Mhead_GenSliceEnder(bbPtr)
BitBucket *bbPtr;
{
Bitio_BytePad(bbPtr);
}
/*===========================================================================*
*
* Mhead_GenMBHeader
*
* generate macroblock header with given attributes
* append result to the specified bitstream
*
* RETURNS: nothing
*
* SIDE EFFECTS: none
*
*===========================================================================*/
void
Mhead_GenMBHeader(bbPtr, pict_code_type, addr_incr, q_scale,
forw_f_code, back_f_code, horiz_forw_r, vert_forw_r,
horiz_back_r, vert_back_r, motion_forw, m_horiz_forw,
m_vert_forw, motion_back, m_horiz_back, m_vert_back,
mb_pattern, mb_intra)
BitBucket *bbPtr;
uint32 pict_code_type;
uint32 addr_incr;
uint32 q_scale;
uint32 forw_f_code;
uint32 back_f_code;
uint32 horiz_forw_r;
uint32 vert_forw_r;
uint32 horiz_back_r;
uint32 vert_back_r;
int32 motion_forw;
int32 m_horiz_forw;
int32 m_vert_forw;
int32 motion_back;
int32 m_horiz_back;
int32 m_vert_back;
uint32 mb_pattern;
uint32 mb_intra;
{
uint32 mb_quant;
/* MB escape sequences if necessary. */
#ifdef BLEAH
if ( addr_incr != 1 )
fprintf(stdout, "Creating MB_INCR: %d\n", addr_incr);
#endif
while (addr_incr > 33) {
Bitio_Write(bbPtr, 0x008, 11);
addr_incr -= 33;
}
/* Generate addr incr code. */
GenMBAddrIncr(bbPtr, addr_incr);
/* Determine mb_quant (true if change in q scale) */
if ((q_scale != lastQSSet) && ((mb_pattern != 0) || (mb_intra == TRUE))) {
mb_quant = TRUE;
lastQSSet = q_scale;
} else {
mb_quant = FALSE;
}
/* Generate mb type code. */
GenMBType(bbPtr, pict_code_type, mb_quant, motion_forw, motion_back, mb_pattern, mb_intra);
/* MB quant. */
if (mb_quant) {
Bitio_Write(bbPtr, q_scale, 5);
}
/* Forward predictive vector stuff. */
if (motion_forw) {
int forw_f, forw_r_size;
forw_r_size = forw_f_code - 1;
forw_f = 1 << forw_r_size; /* 1 > 0 */
if ((m_horiz_forw > 16*forw_f-1) || (m_horiz_forw < -16*forw_f)) {
fprintf(stderr, "Illegal motion? %d %d\n", m_horiz_forw, 16*forw_f);
}
if ((m_vert_forw > 16*forw_f-1) || (m_vert_forw < -16*forw_f)) {
fprintf(stderr, "Illegal motion? %d %d\n", m_vert_forw, 16*forw_f);
}
GenMotionCode(bbPtr, m_horiz_forw);
if ((forw_f != 1) && (m_horiz_forw != 0)) {
Bitio_Write(bbPtr, horiz_forw_r, forw_r_size);
}
GenMotionCode(bbPtr, m_vert_forw);
if ((forw_f != 1) && (m_vert_forw != 0)) {
Bitio_Write(bbPtr, vert_forw_r, forw_r_size);
}
}
/* Back predicted vector stuff. */
if (motion_back) {
int back_f, back_r_size;
back_r_size = back_f_code - 1;
back_f = 1 << back_r_size; /* 1 > 0 */
if ((m_horiz_back > 16*back_f-1) || (m_horiz_back < -16*back_f)) {
fprintf(stderr, "Illegal motion? %d %d\n", m_horiz_back, 16*back_f);
}
if ((m_vert_back > 16*back_f-1) || (m_vert_back < -16*back_f)) {
fprintf(stderr, "Illegal motion? %d %d\n", m_vert_back, 16*back_f);
}
GenMotionCode(bbPtr, m_horiz_back);
if ((back_f != 1) && (m_horiz_back != 0)) {
Bitio_Write(bbPtr, horiz_back_r, back_r_size);
}
GenMotionCode(bbPtr, m_vert_back);
if ((back_f != 1) && (m_vert_back != 0)) {
Bitio_Write(bbPtr, vert_back_r, back_r_size);
}
}
/* MB pattern. */
if (mb_pattern) {
GenBlockPattern(bbPtr, mb_pattern);
}
}
/*=====================*
* INTERNAL PROCEDURES *
*=====================*/
/*===========================================================================*
*
* GenMBType
*
* generate macroblock type with given attributes
* append result to the specified bitstream
*
* RETURNS: nothing
*
* SIDE EFFECTS: none
*
*===========================================================================*/
static void
GenMBType(bbPtr, pict_code_type, mb_quant, motion_forw, motion_back,
mb_pattern, mb_intra)
BitBucket *bbPtr;
uint32 pict_code_type;
uint32 mb_quant;
uint32 motion_forw;
uint32 motion_back;
uint32 mb_pattern;
uint32 mb_intra;
{
int code;
switch (pict_code_type) {
case 1:
if ((motion_forw != 0) || (motion_back != 0) || (mb_pattern != 0) || (mb_intra != 1)) {
perror("Illegal parameters for macroblock type.");
exit(-1);
}
if (mb_quant) {
Bitio_Write(bbPtr, 0x1, 2);
} else {
Bitio_Write(bbPtr, 0x1, 1);
}
break;
case 2:
code = 0;
if (mb_quant) {
code += 16;
}
if (motion_forw) {
code += 8;
}
if (motion_back) {
code += 4;
}
if (mb_pattern) {
code += 2;
}
if (mb_intra) {
code += 1;
}
switch (code) {
case 1:
Bitio_Write(bbPtr, 0x3, 5);
break;
case 2:
Bitio_Write(bbPtr, 0x1, 2);
break;
case 8:
Bitio_Write(bbPtr, 0x1, 3);
break;
case 10:
Bitio_Write(bbPtr, 0x1, 1);
break;
case 17:
Bitio_Write(bbPtr, 0x1, 6);
break;
case 18:
Bitio_Write(bbPtr, 0x1, 5);
break;
case 26:
Bitio_Write(bbPtr, 0x2, 5);
break;
default:
perror("Illegal parameters for macroblock type.");
exit(-1);
break;
}
break;
case 3:
code = 0;
if (mb_quant) {
code += 16;
}
if (motion_forw) {
code += 8;
}
if (motion_back) {
code += 4;
}
if (mb_pattern) {
code += 2;
}
if (mb_intra) {
code += 1;
}
switch (code) {
case 12:
Bitio_Write(bbPtr, 0x2, 2);
break;
case 14:
Bitio_Write(bbPtr, 0x3, 2);
break;
case 4:
Bitio_Write(bbPtr, 0x2, 3);
break;
case 6:
Bitio_Write(bbPtr, 0x3, 3);
break;
case 8:
Bitio_Write(bbPtr, 0x2, 4);
break;
case 10:
Bitio_Write(bbPtr, 0x3, 4);
break;
case 1:
Bitio_Write(bbPtr, 0x3, 5);
break;
case 30:
Bitio_Write(bbPtr, 0x2, 5);
break;
case 26:
Bitio_Write(bbPtr, 0x3, 6);
break;
case 22:
Bitio_Write(bbPtr, 0x2, 6);
break;
case 17:
Bitio_Write(bbPtr, 0x1, 6);
break;
default:
perror("Illegal parameters for macroblock type.");
exit(-1);
break;
}
break;
}
}
/*===========================================================================*
*
* GenMotionCode
*
* generate motion vector output with given value
* append result to the specified bitstream
*
* RETURNS: nothing
*
* SIDE EFFECTS: none
*
*===========================================================================*/
static void
GenMotionCode(bbPtr, vector)
BitBucket *bbPtr;
int32 vector;
{
uint32 code, num;
if ((vector < -16) || (vector > 16)) {
perror("Motion vector out of range.");
fprintf(stderr, "Motion vector out of range: vector = %d\n", vector);
exit(-1);
}
code = mbMotionVectorTable[vector + 16][0];
num = mbMotionVectorTable[vector + 16][1];
Bitio_Write(bbPtr, code, num);
}
/*===========================================================================*
*
* GenBlockPattern
*
* generate macroblock pattern output
* append result to the specified bitstream
*
* RETURNS: nothing
*
* SIDE EFFECTS: none
*
*===========================================================================*/
static void
GenBlockPattern(bbPtr, mb_pattern)
BitBucket *bbPtr;
uint32 mb_pattern;
{
uint32 code, num;
code = mbPatTable[mb_pattern][0];
num = mbPatTable[mb_pattern][1];
Bitio_Write(bbPtr, code, num);
}
/*===========================================================================*
*
* GenMBAddrIncr
*
* generate macroblock address increment output
* append result to the specified bitstream
*
* RETURNS: nothing
*
* SIDE EFFECTS: none
*
*===========================================================================*/
static void
GenMBAddrIncr(bbPtr, addr_incr)
BitBucket *bbPtr;
uint32 addr_incr;
{
uint32 code;
uint32 num;
code = mbAddrIncrTable[addr_incr][0];
num = mbAddrIncrTable[addr_incr][1];
Bitio_Write(bbPtr, code, num);
}
/*===========================================================================*
*
* GenPictHead
*
* generate picture header with given attributes
* append result to the specified bitstream
*
* RETURNS: nothing
*
* SIDE EFFECTS: none
*
*===========================================================================*/
static void
GenPictHead(bbPtr, temp_ref, code_type, vbv_delay, full_pel_forw_flag,
forw_f_code, full_pel_back_flag, back_f_code, extra_info,
extra_info_size, ext_data, ext_data_size, user_data,
user_data_size)
BitBucket *bbPtr;
uint32 temp_ref;
uint32 code_type;
uint32 vbv_delay;
int32 full_pel_forw_flag;
uint32 forw_f_code;
int32 full_pel_back_flag;
uint32 back_f_code;
uint8 *extra_info;
uint32 extra_info_size;
uint8 *ext_data;
uint32 ext_data_size;
uint8 *user_data;
uint32 user_data_size;
{
int i;
/* Write picture start code. */
Bitio_Write(bbPtr, PICT_START_CODE, 32);
/* Temp reference. */
Bitio_Write(bbPtr, temp_ref, 10);
/* Code_type. */
if (code_type == 0) {
code_type = 1;
}
Bitio_Write(bbPtr, code_type, 3);
/* vbv_delay. */
vbv_delay = 0xffff; /* see page 36 (section 2.4.3.4) */
Bitio_Write(bbPtr, vbv_delay, 16);
if ((code_type == 2) || (code_type == 3)) {
/* Full pel forw flag. */
if (full_pel_forw_flag) {
Bitio_Write(bbPtr, 0x01, 1);
} else {
Bitio_Write(bbPtr, 0x00, 1);
}
/* Forw f code. */
Bitio_Write(bbPtr, forw_f_code, 3);
}
if (code_type == 3) {
/* Full pel back flag. */
if (full_pel_back_flag) {
Bitio_Write(bbPtr, 0x01, 1);
} else {
Bitio_Write(bbPtr, 0x00, 1);
}
/* Back f code. */
Bitio_Write(bbPtr, back_f_code, 3);
}
/* Extra bit picture info. */
if (extra_info != NULL) {
for (i = 0; i < extra_info_size; i++) {
Bitio_Write(bbPtr, 0x01, 1);
Bitio_Write(bbPtr, extra_info[i], 8);
}
}
Bitio_Write(bbPtr, 0x00, 1);
/* next start code */
Bitio_BytePad(bbPtr);
/* Write ext data if present. */
if (ext_data != NULL) {
Bitio_Write(bbPtr, EXT_START_CODE, 32);
for (i = 0; i < ext_data_size; i++) {
Bitio_Write(bbPtr, ext_data[i], 8);
}
Bitio_BytePad(bbPtr);
}
/* Write user data if present. */
if (user_data != NULL) {
Bitio_Write(bbPtr, USER_START_CODE, 32);
for (i = 0; i < user_data_size; i++) {
Bitio_Write(bbPtr, user_data[i], 8);
}
Bitio_BytePad(bbPtr);
}
}
#ifdef UNUSED_PROCEDURES
/* GenMBEnd only used for `D` pictures. Shouldn't really ever be called. */
/* - dwallach */
void
GenMBEnd(bbPtr)
BitBucket *bbPtr;
{
Bitio_Write(bbPtr, 0x01, 1);
}
#endif /* UNUSED_PROCEDURES */
syntax highlighted by Code2HTML, v. 0.9.1