diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2006-08-19 03:12:28 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2006-08-19 03:12:28 +0000 |
commit | 1fd361a1ea06e44286c213ca1f814f49306fdc43 (patch) | |
tree | 64c8c96cf54d8718847339a403e5e67b922e8c3f /converter/ppm/ppmtompeg/mheaders.c | |
download | netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.gz netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.xz netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.zip |
Create Subversion repository
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter/ppm/ppmtompeg/mheaders.c')
-rw-r--r-- | converter/ppm/ppmtompeg/mheaders.c | 1192 |
1 files changed, 1192 insertions, 0 deletions
diff --git a/converter/ppm/ppmtompeg/mheaders.c b/converter/ppm/ppmtompeg/mheaders.c new file mode 100644 index 00000000..2a5f2c63 --- /dev/null +++ b/converter/ppm/ppmtompeg/mheaders.c @@ -0,0 +1,1192 @@ +/*===========================================================================* + * 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: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/mheaders.c,v 1.15 1995/08/07 21:45:19 smoot Exp $ + * $Log: mheaders.c,v $ + * 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(BitBucket * const bbPtr, + uint32 const hsize, + uint32 const vsize, + int32 const pratio, + int32 const pict_rate, + int32 const bit_rate_arg, + int32 const buf_size_arg, + int32 const c_param_flag_arg, + const int32 * const iq_matrix, + const int32 * const niq_matrix, + uint8 * const ext_data, + int32 const ext_data_size, + uint8 * const user_data, + int32 const user_data_size) { + + extern int ZAG[]; + int i; + int32 bit_rate; + int32 buf_size; + int32 c_param_flag; + + /* 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_arg < 0) { + bit_rate = -1; + } else { + bit_rate = bit_rate_arg / 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_arg < 0) + buf_size = 0; + else + buf_size = buf_size_arg; + + 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(BitBucket * const bbPtr, + int32 const 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 */ |