--- /dev/null
+CHANGES
+=======
+
+Since July 4, 1994 edition:
+
+ Summary:
+ only very minor changes since version 1.1a, distributed two years
+ ago. A beta version of this program has significantly greater
+ number of changes (.par file syntax, restructured motion.c ,
+ zero-block test of Note 4.1.1, etc.)
+
+ 1. as per suggestion of Peter Loje Hansen <plh@tdr.dk>:
+
+ - corrected line 631 of motion.c so field_estimate uses
+ backward search range variables (sxb, syb) instead of
+ forward search range variables (sxf, syf).
+
+ - corrected line 250 in putseq.c, replacing .sxf with .syf
+
+
+ 2. many user suggestions:
+ - prevent divide by zero in SNR calculation in stat.c.
+
+ 3. general:
+ - eliminated support for non ANSI C compilers in makefile.
+
--- /dev/null
+# Makefile for mpeg2encode
+
+# Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+#
+# Disclaimer of Warranty
+#
+# These software programs are available to the user without any license fee or
+# royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+# any and all warranties, whether express, implied, or statuary, including any
+# implied warranties or merchantability or of fitness for a particular
+# purpose. In no event shall the copyright-holder be liable for any
+# incidental, punitive, or consequential damages of any kind whatsoever
+# arising from the use of these programs.
+#
+# This disclaimer of warranty extends to the user of these programs and user's
+# customers, employees, agents, transferees, successors, and assigns.
+#
+# The MPEG Software Simulation Group does not represent or warrant that the
+# programs furnished hereunder are free of infringement of any third-party
+# patents.
+#
+# Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+# are subject to royalty fees to patent holders. Many of these patents are
+# general enough such that they are unavoidable regardless of implementation
+# design.
+#
+#
+
+# select one of the following CC CFLAGS settings
+
+#
+# GNU gcc
+#
+CC = gcc
+CFLAGS = -O2 -Wall
+
+OBJ = mpeg2enc.o conform.o putseq.o putpic.o puthdr.o putmpg.o putvlc.o putbits.o motion.o predict.o readpic.o writepic.o transfrm.o fdctref.o idct.o quantize.o ratectl.o stats.o
+
+all: mpeg2encode
+
+pc: mpeg2enc.exe
+
+clean:
+ rm -f *.o *% core mpeg2encode
+
+mpeg2enc.exe: mpeg2encode
+ coff2exe mpeg2enc
+
+mpeg2encode: $(OBJ)
+ $(CC) $(CFLAGS) -o mpeg2encode $(OBJ) -lm
+
+conform.o : conform.c config.h global.h mpeg2enc.h
+fdctref.o : fdctref.c config.h
+idct.o : idct.c config.h
+motion.o : motion.c config.h global.h mpeg2enc.h
+mpeg2enc.o : mpeg2enc.c config.h global.h mpeg2enc.h
+predict.o : predict.c config.h global.h mpeg2enc.h
+putbits.o : putbits.c config.h
+puthdr.o : puthdr.c config.h global.h mpeg2enc.h
+putmpg.o : putmpg.c config.h global.h mpeg2enc.h
+putpic.o : putpic.c config.h global.h mpeg2enc.h
+putseq.o : putseq.c config.h global.h mpeg2enc.h
+putvlc.o : putvlc.c config.h global.h mpeg2enc.h vlc.h
+quantize.o : quantize.c config.h global.h mpeg2enc.h
+ratectl.o : ratectl.c config.h global.h mpeg2enc.h
+readpic.o : readpic.c config.h global.h mpeg2enc.h
+stats.o : stats.c config.h global.h mpeg2enc.h
+transfrm.o : transfrm.c config.h global.h mpeg2enc.h
+writepic.o : writepic.c config.h global.h mpeg2enc.h
--- /dev/null
+# Makefile for mpeg2encode (user contribution, untested)
+#
+# WATCOM C/386++
+#
+INC = C:\OR386\INCLUDE
+
+LINKFILE = temp.lnk
+CC = WCC386P
+LL = WLINKP system dos4g
+
+!ifdef DEBUG
+CFLAGS = -w4 -zq -4r -d2 -I$(INC)
+!else
+CFLAGS = -w4 -zq -4r -oaxt -I$(INC)
+!endif
+
+OBJ = mpeg2enc.obj conform.obj putseq.obj putpic.obj puthdr.obj putmpg.obj
+putvlc.obj putbits.obj motion.obj predict.obj readpic.obj
+writepic.obj transfrm.obj fdctref.obj idct.obj quantize.obj
+ratectl.obj stats.obj
+
+mpeg2enc.exe: $(OBJ)
+ %create $(LINKFILE)
+ %append $(LINKFILE) debug all
+ %append $(LINKFILE) opt stack=32000
+ %append $(LINKFILE) opt caseexact
+ %append $(LINKFILE) opt map=$^&.MAP
+ %append $(LINKFILE) NAME $^&
+ for %i in ($(OBJ)) do %append $(LINKFILE) FILE %i
+ $(LL) @$(LINKFILE)
+
+conform.obj: conform.c config.h mpeg2enc.h global.h
+ $(CC) $(CFLAGS) $*.c
+
+fdctref.obj: fdctref.c config.h
+ $(CC) $(CFLAGS) $*.c
+
+idct.obj: idct.c config.h
+ $(CC) $(CFLAGS) $*.c
+
+motion.obj: motion.c config.h mpeg2enc.h global.h
+ $(CC) $(CFLAGS) $*.c
+
+mpeg2enc.obj: mpeg2enc.c config.h mpeg2enc.h global.h
+ $(CC) $(CFLAGS) $*.c
+
+predict.obj: predict.c config.h mpeg2enc.h global.h
+ $(CC) $(CFLAGS) $*.c
+
+putbits.obj: putbits.c config.h
+ $(CC) $(CFLAGS) $*.c
+
+puthdr.obj: puthdr.c config.h mpeg2enc.h global.h
+ $(CC) $(CFLAGS) $*.c
+
+putmpg.obj: putmpg.c config.h mpeg2enc.h global.h
+ $(CC) $(CFLAGS) $*.c
+
+putpic.obj: putpic.c config.h mpeg2enc.h global.h
+ $(CC) $(CFLAGS) $*.c
+
+putseq.obj: putseq.c config.h mpeg2enc.h global.h
+ $(CC) $(CFLAGS) $*.c
+
+putvlc.obj: putvlc.c config.h mpeg2enc.h global.h vlc.h
+ $(CC) $(CFLAGS) $*.c
+
+quantize.obj: quantize.c config.h mpeg2enc.h global.h
+ $(CC) $(CFLAGS) $*.c
+
+ratectl.obj: ratectl.c config.h mpeg2enc.h global.h
+ $(CC) $(CFLAGS) $*.c
+
+readpic.obj: readpic.c config.h mpeg2enc.h global.h
+ $(CC) $(CFLAGS) $*.c
+
+stats.obj: stats.c config.h mpeg2enc.h global.h
+ $(CC) $(CFLAGS) $*.c
+
+transfrm.obj: transfrm.c config.h mpeg2enc.h global.h
+ $(CC) $(CFLAGS) $*.c
+
+writepic.obj: writepic.c config.h mpeg2enc.h global.h
+ $(CC) $(CFLAGS) $*.c
+
--- /dev/null
+TODO
+====
+
+ - update vbv_delay calculation to agree with November 1994
+ (WG11 approved IS draft of ISO/IEC 13818-2).
+
+ - allow intra only encoding of sequences (disable ipflag in
+ putseq.c)
+
+
--- /dev/null
+/* config.h, configuration defines */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+/* define NON_ANSI_COMPILER for compilers without function prototyping */
+/* #define NON_ANSI_COMPILER */
+
+#ifdef NON_ANSI_COMPILER
+#define _ANSI_ARGS_(x) ()
+#else
+#define _ANSI_ARGS_(x) x
+#endif
--- /dev/null
+/* conform.c, conformance checks */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "config.h"
+#include "global.h"
+
+/* check for (level independent) parameter limits */
+void range_checks()
+{
+ int i;
+
+ /* range and value checks */
+
+ if (horizontal_size<1 || horizontal_size>16383)
+ error("horizontal_size must be between 1 and 16383");
+ if (mpeg1 && horizontal_size>4095)
+ error("horizontal_size must be less than 4096 (MPEG-1)");
+ if ((horizontal_size&4095)==0)
+ error("horizontal_size must not be a multiple of 4096");
+ if (chroma_format!=CHROMA444 && horizontal_size%2 != 0)
+ error("horizontal_size must be a even (4:2:0 / 4:2:2)");
+
+ if (vertical_size<1 || vertical_size>16383)
+ error("vertical_size must be between 1 and 16383");
+ if (mpeg1 && vertical_size>4095)
+ error("vertical size must be less than 4096 (MPEG-1)");
+ if ((vertical_size&4095)==0)
+ error("vertical_size must not be a multiple of 4096");
+ if (chroma_format==CHROMA420 && vertical_size%2 != 0)
+ error("vertical_size must be a even (4:2:0)");
+ if(fieldpic)
+ {
+ if (vertical_size%2 != 0)
+ error("vertical_size must be a even (field pictures)");
+ if (chroma_format==CHROMA420 && vertical_size%4 != 0)
+ error("vertical_size must be a multiple of 4 (4:2:0 field pictures)");
+ }
+
+ if (mpeg1)
+ {
+ if (aspectratio<1 || aspectratio>14)
+ error("pel_aspect_ratio must be between 1 and 14 (MPEG-1)");
+ }
+ else
+ {
+ if (aspectratio<1 || aspectratio>4)
+ error("aspect_ratio_information must be 1, 2, 3 or 4");
+ }
+
+ if (frame_rate_code<1 || frame_rate_code>8)
+ error("frame_rate code must be between 1 and 8");
+
+ if (bit_rate<=0.0)
+ error("bit_rate must be positive");
+ if (bit_rate > ((1<<30)-1)*400.0)
+ error("bit_rate must be less than 429 Gbit/s");
+ if (mpeg1 && bit_rate > ((1<<18)-1)*400.0)
+ error("bit_rate must be less than 104 Mbit/s (MPEG-1)");
+
+ if (vbv_buffer_size<1 || vbv_buffer_size>0x3ffff)
+ error("vbv_buffer_size must be in range 1..(2^18-1)");
+ if (mpeg1 && vbv_buffer_size>=1024)
+ error("vbv_buffer_size must be less than 1024 (MPEG-1)");
+
+ if (chroma_format<CHROMA420 || chroma_format>CHROMA444)
+ error("chroma_format must be in range 1...3");
+
+ if (video_format<0 || video_format>4)
+ error("video_format must be in range 0...4");
+
+ if (color_primaries<1 || color_primaries>7 || color_primaries==3)
+ error("color_primaries must be in range 1...2 or 4...7");
+
+ if (transfer_characteristics<1 || transfer_characteristics>7
+ || transfer_characteristics==3)
+ error("transfer_characteristics must be in range 1...2 or 4...7");
+
+ if (matrix_coefficients<1 || matrix_coefficients>7 || matrix_coefficients==3)
+ error("matrix_coefficients must be in range 1...2 or 4...7");
+
+ if (display_horizontal_size<0 || display_horizontal_size>16383)
+ error("display_horizontal_size must be in range 0...16383");
+ if (display_vertical_size<0 || display_vertical_size>16383)
+ error("display_vertical_size must be in range 0...16383");
+
+ if (dc_prec<0 || dc_prec>3)
+ error("intra_dc_precision must be in range 0...3");
+
+ for (i=0; i<M; i++)
+ {
+ if (motion_data[i].forw_hor_f_code<1 || motion_data[i].forw_hor_f_code>9)
+ error("f_code must be between 1 and 9");
+ if (motion_data[i].forw_vert_f_code<1 || motion_data[i].forw_vert_f_code>9)
+ error("f_code must be between 1 and 9");
+ if (mpeg1 && motion_data[i].forw_hor_f_code>7)
+ error("f_code must be le less than 8");
+ if (mpeg1 && motion_data[i].forw_vert_f_code>7)
+ error("f_code must be le less than 8");
+ if (motion_data[i].sxf<=0)
+ error("search window must be positive"); /* doesn't belong here */
+ if (motion_data[i].syf<=0)
+ error("search window must be positive");
+ if (i!=0)
+ {
+ if (motion_data[i].back_hor_f_code<1 || motion_data[i].back_hor_f_code>9)
+ error("f_code must be between 1 and 9");
+ if (motion_data[i].back_vert_f_code<1 || motion_data[i].back_vert_f_code>9)
+ error("f_code must be between 1 and 9");
+ if (mpeg1 && motion_data[i].back_hor_f_code>7)
+ error("f_code must be le less than 8");
+ if (mpeg1 && motion_data[i].back_vert_f_code>7)
+ error("f_code must be le less than 8");
+ if (motion_data[i].sxb<=0)
+ error("search window must be positive");
+ if (motion_data[i].syb<=0)
+ error("search window must be positive");
+ }
+ }
+}
+
+/* identifies valid profile / level combinations */
+static char profile_level_defined[5][4] =
+{
+/* HL H-14 ML LL */
+ {1, 1, 1, 0}, /* HP */
+ {0, 1, 0, 0}, /* Spat */
+ {0, 0, 1, 1}, /* SNR */
+ {1, 1, 1, 1}, /* MP */
+ {0, 0, 1, 0} /* SP */
+};
+
+static struct level_limits {
+ int hor_f_code;
+ int vert_f_code;
+ int hor_size;
+ int vert_size;
+ int sample_rate;
+ int bit_rate; /* Mbit/s */
+ int vbv_buffer_size; /* 16384 bit steps */
+} maxval_tab[4] =
+{
+ {9, 5, 1920, 1152, 62668800, 80, 597}, /* HL */
+ {9, 5, 1440, 1152, 47001600, 60, 448}, /* H-14 */
+ {8, 5, 720, 576, 10368000, 15, 112}, /* ML */
+ {7, 4, 352, 288, 3041280, 4, 29} /* LL */
+};
+
+#define SP 5
+#define MP 4
+#define SNR 3
+#define SPAT 2
+#define HP 1
+
+#define LL 10
+#define ML 8
+#define H14 6
+#define HL 4
+
+void profile_and_level_checks()
+{
+ int i;
+ struct level_limits *maxval;
+
+ if (profile<0 || profile>15)
+ error("profile must be between 0 and 15");
+
+ if (level<0 || level>15)
+ error("level must be between 0 and 15");
+
+ if (profile>=8)
+ {
+ if (!quiet)
+ fprintf(stderr,"Warning: profile uses a reserved value, conformance checks skipped\n");
+ return;
+ }
+
+ if (profile<HP || profile>SP)
+ error("undefined Profile");
+
+ if (profile==SNR || profile==SPAT)
+ error("This encoder currently generates no scalable bitstreams");
+
+ if (level<HL || level>LL || level&1)
+ error("undefined Level");
+
+ maxval = &maxval_tab[(level-4) >> 1];
+
+ /* check profile@level combination */
+ if(!profile_level_defined[profile-1][(level-4) >> 1])
+ error("undefined profile@level combination");
+
+
+ /* profile (syntax) constraints */
+
+ if (profile==SP && M!=1)
+ error("Simple Profile does not allow B pictures");
+
+ if (profile!=HP && chroma_format!=CHROMA420)
+ error("chroma format must be 4:2:0 in specified Profile");
+
+ if (profile==HP && chroma_format==CHROMA444)
+ error("chroma format must be 4:2:0 or 4:2:2 in High Profile");
+
+ if (profile>=MP) /* SP, MP: constrained repeat_first_field */
+ {
+ if (frame_rate_code<=2 && repeatfirst)
+ error("repeat_first_first must be zero");
+ if (frame_rate_code<=6 && prog_seq && repeatfirst)
+ error("repeat_first_first must be zero");
+ }
+
+ if (profile!=HP && dc_prec==3)
+ error("11 bit DC precision only allowed in High Profile");
+
+
+ /* level (parameter value) constraints */
+
+ /* Table 8-8 */
+ if (frame_rate_code>5 && level>=ML)
+ error("Picture rate greater than permitted in specified Level");
+
+ for (i=0; i<M; i++)
+ {
+ if (motion_data[i].forw_hor_f_code > maxval->hor_f_code)
+ error("forward horizontal f_code greater than permitted in specified Level");
+
+ if (motion_data[i].forw_vert_f_code > maxval->vert_f_code)
+ error("forward vertical f_code greater than permitted in specified Level");
+
+ if (i!=0)
+ {
+ if (motion_data[i].back_hor_f_code > maxval->hor_f_code)
+ error("backward horizontal f_code greater than permitted in specified Level");
+
+ if (motion_data[i].back_vert_f_code > maxval->vert_f_code)
+ error("backward vertical f_code greater than permitted in specified Level");
+ }
+ }
+
+ /* Table 8-10 */
+ if (horizontal_size > maxval->hor_size)
+ error("Horizontal size is greater than permitted in specified Level");
+
+ if (vertical_size > maxval->vert_size)
+ error("Horizontal size is greater than permitted in specified Level");
+
+ /* Table 8-11 */
+ if (horizontal_size*vertical_size*frame_rate > maxval->sample_rate)
+ error("Sample rate is greater than permitted in specified Level");
+
+ /* Table 8-12 */
+ if (bit_rate> 1.0e6 * maxval->bit_rate)
+ error("Bit rate is greater than permitted in specified Level");
+
+ /* Table 8-13 */
+ if (vbv_buffer_size > maxval->vbv_buffer_size)
+ error("vbv_buffer_size exceeds High Level limit");
+}
--- /dev/null
+/* fdctref.c, forward discrete cosine transform, double precision */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include <math.h>
+
+#include "config.h"
+
+#ifndef PI
+# ifdef M_PI
+# define PI M_PI
+# else
+# define PI 3.14159265358979323846
+# endif
+#endif
+
+/* global declarations */
+void init_fdct _ANSI_ARGS_((void));
+void fdct _ANSI_ARGS_((short *block));
+
+/* private data */
+static double c[8][8]; /* transform coefficients */
+
+void init_fdct()
+{
+ int i, j;
+ double s;
+
+ for (i=0; i<8; i++)
+ {
+ s = (i==0) ? sqrt(0.125) : 0.5;
+
+ for (j=0; j<8; j++)
+ c[i][j] = s * cos((PI/8.0)*i*(j+0.5));
+ }
+}
+
+void fdct(block)
+short *block;
+{
+ int i, j, k;
+ double s;
+ double tmp[64];
+
+ for (i=0; i<8; i++)
+ for (j=0; j<8; j++)
+ {
+ s = 0.0;
+
+ for (k=0; k<8; k++)
+ s += c[j][k] * block[8*i+k];
+
+ tmp[8*i+j] = s;
+ }
+
+ for (j=0; j<8; j++)
+ for (i=0; i<8; i++)
+ {
+ s = 0.0;
+
+ for (k=0; k<8; k++)
+ s += c[i][k] * tmp[8*k+j];
+
+ block[8*i+j] = (int)floor(s+0.499999);
+ /*
+ * reason for adding 0.499999 instead of 0.5:
+ * s is quite often x.5 (at least for i and/or j = 0 or 4)
+ * and setting the rounding threshold exactly to 0.5 leads to an
+ * extremely high arithmetic implementation dependency of the result;
+ * s being between x.5 and x.500001 (which is now incorrectly rounded
+ * downwards instead of upwards) is assumed to occur less often
+ * (if at all)
+ */
+ }
+}
--- /dev/null
+/* global.h, global variables, function prototypes */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include "mpeg2enc.h"
+
+/* choose between declaration (GLOBAL undefined)
+ * and definition (GLOBAL defined)
+ * GLOBAL is defined in exactly one file (mpeg2enc.c)
+ */
+
+#ifndef GLOBAL
+#define EXTERN extern
+#else
+#define EXTERN
+#endif
+
+/* prototypes of global functions */
+
+/* conform.c */
+void range_checks _ANSI_ARGS_((void));
+void profile_and_level_checks _ANSI_ARGS_(());
+
+/* fdctref.c */
+void init_fdct _ANSI_ARGS_((void));
+void fdct _ANSI_ARGS_((short *block));
+
+/* idct.c */
+void idct _ANSI_ARGS_((short *block));
+void init_idct _ANSI_ARGS_((void));
+
+/* motion.c */
+void motion_estimation _ANSI_ARGS_((unsigned char *oldorg, unsigned char *neworg,
+ unsigned char *oldref, unsigned char *newref, unsigned char *cur,
+ unsigned char *curref, int sxf, int syf, int sxb, int syb,
+ struct mbinfo *mbi, int secondfield, int ipflag));
+
+/* mpeg2enc.c */
+void error _ANSI_ARGS_((char *text));
+
+/* predict.c */
+void predict _ANSI_ARGS_((unsigned char *reff[], unsigned char *refb[],
+ unsigned char *cur[3], int secondfield, struct mbinfo *mbi));
+
+/* putbits.c */
+void initbits _ANSI_ARGS_((void));
+void putbits _ANSI_ARGS_((int val, int n));
+void alignbits _ANSI_ARGS_((void));
+int bitcount _ANSI_ARGS_((void));
+
+/* puthdr.c */
+void putseqhdr _ANSI_ARGS_((void));
+void putseqext _ANSI_ARGS_((void));
+void putseqdispext _ANSI_ARGS_((void));
+void putuserdata _ANSI_ARGS_((char *userdata));
+void putgophdr _ANSI_ARGS_((int frame, int closed_gop));
+void putpicthdr _ANSI_ARGS_((void));
+void putpictcodext _ANSI_ARGS_((void));
+void putseqend _ANSI_ARGS_((void));
+
+/* putmpg.c */
+void putintrablk _ANSI_ARGS_((short *blk, int cc));
+void putnonintrablk _ANSI_ARGS_((short *blk));
+void putmv _ANSI_ARGS_((int dmv, int f_code));
+
+/* putpic.c */
+void putpict _ANSI_ARGS_((unsigned char *frame));
+
+/* putseq.c */
+void putseq _ANSI_ARGS_((void));
+
+/* putvlc.c */
+void putDClum _ANSI_ARGS_((int val));
+void putDCchrom _ANSI_ARGS_((int val));
+void putACfirst _ANSI_ARGS_((int run, int val));
+void putAC _ANSI_ARGS_((int run, int signed_level, int vlcformat));
+void putaddrinc _ANSI_ARGS_((int addrinc));
+void putmbtype _ANSI_ARGS_((int pict_type, int mb_type));
+void putmotioncode _ANSI_ARGS_((int motion_code));
+void putdmv _ANSI_ARGS_((int dmv));
+void putcbp _ANSI_ARGS_((int cbp));
+
+/* quantize.c */
+int quant_intra _ANSI_ARGS_((short *src, short *dst, int dc_prec,
+ unsigned char *quant_mat, int mquant));
+int quant_non_intra _ANSI_ARGS_((short *src, short *dst,
+ unsigned char *quant_mat, int mquant));
+void iquant_intra _ANSI_ARGS_((short *src, short *dst, int dc_prec,
+ unsigned char *quant_mat, int mquant));
+void iquant_non_intra _ANSI_ARGS_((short *src, short *dst,
+ unsigned char *quant_mat, int mquant));
+
+/* ratectl.c */
+void rc_init_seq _ANSI_ARGS_((void));
+void rc_init_GOP _ANSI_ARGS_((int np, int nb));
+void rc_init_pict _ANSI_ARGS_((unsigned char *frame));
+void rc_update_pict _ANSI_ARGS_((void));
+int rc_start_mb _ANSI_ARGS_((void));
+int rc_calc_mquant _ANSI_ARGS_((int j));
+void vbv_end_of_picture _ANSI_ARGS_((void));
+void calc_vbv_delay _ANSI_ARGS_((void));
+
+/* readpic.c */
+void readframe _ANSI_ARGS_((char *fname, unsigned char *frame[]));
+
+/* stats.c */
+void calcSNR _ANSI_ARGS_((unsigned char *org[3], unsigned char *rec[3]));
+void stats _ANSI_ARGS_((void));
+
+/* transfrm.c */
+void transform _ANSI_ARGS_((unsigned char *pred[], unsigned char *cur[],
+ struct mbinfo *mbi, short blocks[][64]));
+void itransform _ANSI_ARGS_((unsigned char *pred[], unsigned char *cur[],
+ struct mbinfo *mbi, short blocks[][64]));
+void dct_type_estimation _ANSI_ARGS_((unsigned char *pred, unsigned char *cur,
+ struct mbinfo *mbi));
+
+/* writepic.c */
+void writeframe _ANSI_ARGS_((char *fname, unsigned char *frame[]));
+
+
+/* global variables */
+
+EXTERN char version[]
+#ifdef GLOBAL
+ ="mpeg2encode V1.2, 96/07/19"
+#endif
+;
+
+EXTERN char author[]
+#ifdef GLOBAL
+ ="(C) 1996, MPEG Software Simulation Group"
+#endif
+;
+
+/* zig-zag scan */
+EXTERN unsigned char zig_zag_scan[64]
+#ifdef GLOBAL
+=
+{
+ 0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,
+ 12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28,
+ 35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,
+ 58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63
+}
+#endif
+;
+
+/* alternate scan */
+EXTERN unsigned char alternate_scan[64]
+#ifdef GLOBAL
+=
+{
+ 0,8,16,24,1,9,2,10,17,25,32,40,48,56,57,49,
+ 41,33,26,18,3,11,4,12,19,27,34,42,50,58,35,43,
+ 51,59,20,28,5,13,6,14,21,29,36,44,52,60,37,45,
+ 53,61,22,30,7,15,23,31,38,46,54,62,39,47,55,63
+}
+#endif
+;
+
+/* default intra quantization matrix */
+EXTERN unsigned char default_intra_quantizer_matrix[64]
+#ifdef GLOBAL
+=
+{
+ 8, 16, 19, 22, 26, 27, 29, 34,
+ 16, 16, 22, 24, 27, 29, 34, 37,
+ 19, 22, 26, 27, 29, 34, 34, 38,
+ 22, 22, 26, 27, 29, 34, 37, 40,
+ 22, 26, 27, 29, 32, 35, 40, 48,
+ 26, 27, 29, 32, 35, 40, 48, 58,
+ 26, 27, 29, 34, 38, 46, 56, 69,
+ 27, 29, 35, 38, 46, 56, 69, 83
+}
+#endif
+;
+
+/* non-linear quantization coefficient table */
+EXTERN unsigned char non_linear_mquant_table[32]
+#ifdef GLOBAL
+=
+{
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8,10,12,14,16,18,20,22,
+ 24,28,32,36,40,44,48,52,
+ 56,64,72,80,88,96,104,112
+}
+#endif
+;
+
+/* non-linear mquant table for mapping from scale to code
+ * since reconstruction levels are not bijective with the index map,
+ * it is up to the designer to determine most of the quantization levels
+ */
+
+EXTERN unsigned char map_non_linear_mquant[113]
+#ifdef GLOBAL
+=
+{
+0,1,2,3,4,5,6,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,
+16,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,22,22,
+22,22,23,23,23,23,24,24,24,24,24,24,24,25,25,25,25,25,25,25,26,26,
+26,26,26,26,26,26,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,29,
+29,29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,31,31,31,31,31
+}
+#endif
+;
+
+/* picture data arrays */
+
+/* reconstructed frames */
+EXTERN unsigned char *newrefframe[3], *oldrefframe[3], *auxframe[3];
+/* original frames */
+EXTERN unsigned char *neworgframe[3], *oldorgframe[3], *auxorgframe[3];
+/* prediction of current frame */
+EXTERN unsigned char *predframe[3];
+/* 8*8 block data */
+EXTERN short (*blocks)[64];
+/* intra / non_intra quantization matrices */
+EXTERN unsigned char intra_q[64], inter_q[64];
+EXTERN unsigned char chrom_intra_q[64],chrom_inter_q[64];
+/* prediction values for DCT coefficient (0,0) */
+EXTERN int dc_dct_pred[3];
+/* macroblock side information array */
+EXTERN struct mbinfo *mbinfo;
+/* motion estimation parameters */
+EXTERN struct motion_data *motion_data;
+/* clipping (=saturation) table */
+EXTERN unsigned char *clp;
+
+/* name strings */
+EXTERN char id_string[256], tplorg[256], tplref[256];
+EXTERN char iqname[256], niqname[256];
+EXTERN char statname[256];
+EXTERN char errortext[256];
+
+EXTERN FILE *outfile, *statfile; /* file descriptors */
+EXTERN int inputtype; /* format of input frames */
+
+EXTERN int quiet; /* suppress warnings */
+
+
+/* coding model parameters */
+
+EXTERN int N; /* number of frames in Group of Pictures */
+EXTERN int M; /* distance between I/P frames */
+EXTERN int P; /* intra slice refresh interval */
+EXTERN int nframes; /* total number of frames to encode */
+EXTERN int frame0, tc0; /* number and timecode of first frame */
+EXTERN int mpeg1; /* ISO/IEC IS 11172-2 sequence */
+EXTERN int fieldpic; /* use field pictures */
+
+/* sequence specific data (sequence header) */
+
+EXTERN int horizontal_size, vertical_size; /* frame size (pels) */
+EXTERN int width, height; /* encoded frame size (pels) multiples of 16 or 32 */
+EXTERN int chrom_width,chrom_height,block_count;
+EXTERN int mb_width, mb_height; /* frame size (macroblocks) */
+EXTERN int width2, height2, mb_height2, chrom_width2; /* picture size */
+EXTERN int aspectratio; /* aspect ratio information (pel or display) */
+EXTERN int frame_rate_code; /* coded value of frame rate */
+EXTERN double frame_rate; /* frames per second */
+EXTERN double bit_rate; /* bits per second */
+EXTERN int vbv_buffer_size; /* size of VBV buffer (* 16 kbit) */
+EXTERN int constrparms; /* constrained parameters flag (MPEG-1 only) */
+EXTERN int load_iquant, load_niquant; /* use non-default quant. matrices */
+EXTERN int load_ciquant,load_cniquant;
+
+
+/* sequence specific data (sequence extension) */
+
+EXTERN int profile, level; /* syntax / parameter constraints */
+EXTERN int prog_seq; /* progressive sequence */
+EXTERN int chroma_format;
+EXTERN int low_delay; /* no B pictures, skipped pictures */
+
+
+/* sequence specific data (sequence display extension) */
+
+EXTERN int video_format; /* component, PAL, NTSC, SECAM or MAC */
+EXTERN int color_primaries; /* source primary chromaticity coordinates */
+EXTERN int transfer_characteristics; /* opto-electronic transfer char. (gamma) */
+EXTERN int matrix_coefficients; /* Eg,Eb,Er / Y,Cb,Cr matrix coefficients */
+EXTERN int display_horizontal_size, display_vertical_size; /* display size */
+
+
+/* picture specific data (picture header) */
+
+EXTERN int temp_ref; /* temporal reference */
+EXTERN int pict_type; /* picture coding type (I, P or B) */
+EXTERN int vbv_delay; /* video buffering verifier delay (1/90000 seconds) */
+
+
+/* picture specific data (picture coding extension) */
+
+EXTERN int forw_hor_f_code, forw_vert_f_code;
+EXTERN int back_hor_f_code, back_vert_f_code; /* motion vector ranges */
+EXTERN int dc_prec; /* DC coefficient precision for intra coded blocks */
+EXTERN int pict_struct; /* picture structure (frame, top / bottom field) */
+EXTERN int topfirst; /* display top field first */
+/* use only frame prediction and frame DCT (I,P,B,current) */
+EXTERN int frame_pred_dct_tab[3], frame_pred_dct;
+EXTERN int conceal_tab[3]; /* use concealment motion vectors (I,P,B) */
+EXTERN int qscale_tab[3], q_scale_type; /* linear/non-linear quantizaton table */
+EXTERN int intravlc_tab[3], intravlc; /* intra vlc format (I,P,B,current) */
+EXTERN int altscan_tab[3], altscan; /* alternate scan (I,P,B,current) */
+EXTERN int repeatfirst; /* repeat first field after second field */
+EXTERN int prog_frame; /* progressive frame */
--- /dev/null
+/* idct.c, inverse fast discrete cosine transform */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+/**********************************************************/
+/* inverse two dimensional DCT, Chen-Wang algorithm */
+/* (cf. IEEE ASSP-32, pp. 803-816, Aug. 1984) */
+/* 32-bit integer arithmetic (8 bit coefficients) */
+/* 11 mults, 29 adds per DCT */
+/* sE, 18.8.91 */
+/**********************************************************/
+/* coefficients extended to 12 bit for IEEE1180-1990 */
+/* compliance sE, 2.1.94 */
+/**********************************************************/
+
+/* this code assumes >> to be a two's-complement arithmetic */
+/* right shift: (-2)>>1 == -1 , (-3)>>1 == -2 */
+
+#include "config.h"
+
+#define W1 2841 /* 2048*sqrt(2)*cos(1*pi/16) */
+#define W2 2676 /* 2048*sqrt(2)*cos(2*pi/16) */
+#define W3 2408 /* 2048*sqrt(2)*cos(3*pi/16) */
+#define W5 1609 /* 2048*sqrt(2)*cos(5*pi/16) */
+#define W6 1108 /* 2048*sqrt(2)*cos(6*pi/16) */
+#define W7 565 /* 2048*sqrt(2)*cos(7*pi/16) */
+
+/* global declarations */
+void init_idct _ANSI_ARGS_((void));
+void idct _ANSI_ARGS_((short *block));
+
+/* private data */
+static short iclip[1024]; /* clipping table */
+static short *iclp;
+
+/* private prototypes */
+static void idctrow _ANSI_ARGS_((short *blk));
+static void idctcol _ANSI_ARGS_((short *blk));
+
+/* row (horizontal) IDCT
+ *
+ * 7 pi 1
+ * dst[k] = sum c[l] * src[l] * cos( -- * ( k + - ) * l )
+ * l=0 8 2
+ *
+ * where: c[0] = 128
+ * c[1..7] = 128*sqrt(2)
+ */
+
+static void idctrow(blk)
+short *blk;
+{
+ int x0, x1, x2, x3, x4, x5, x6, x7, x8;
+
+ /* shortcut */
+ if (!((x1 = blk[4]<<11) | (x2 = blk[6]) | (x3 = blk[2]) |
+ (x4 = blk[1]) | (x5 = blk[7]) | (x6 = blk[5]) | (x7 = blk[3])))
+ {
+ blk[0]=blk[1]=blk[2]=blk[3]=blk[4]=blk[5]=blk[6]=blk[7]=blk[0]<<3;
+ return;
+ }
+
+ x0 = (blk[0]<<11) + 128; /* for proper rounding in the fourth stage */
+
+ /* first stage */
+ x8 = W7*(x4+x5);
+ x4 = x8 + (W1-W7)*x4;
+ x5 = x8 - (W1+W7)*x5;
+ x8 = W3*(x6+x7);
+ x6 = x8 - (W3-W5)*x6;
+ x7 = x8 - (W3+W5)*x7;
+
+ /* second stage */
+ x8 = x0 + x1;
+ x0 -= x1;
+ x1 = W6*(x3+x2);
+ x2 = x1 - (W2+W6)*x2;
+ x3 = x1 + (W2-W6)*x3;
+ x1 = x4 + x6;
+ x4 -= x6;
+ x6 = x5 + x7;
+ x5 -= x7;
+
+ /* third stage */
+ x7 = x8 + x3;
+ x8 -= x3;
+ x3 = x0 + x2;
+ x0 -= x2;
+ x2 = (181*(x4+x5)+128)>>8;
+ x4 = (181*(x4-x5)+128)>>8;
+
+ /* fourth stage */
+ blk[0] = (x7+x1)>>8;
+ blk[1] = (x3+x2)>>8;
+ blk[2] = (x0+x4)>>8;
+ blk[3] = (x8+x6)>>8;
+ blk[4] = (x8-x6)>>8;
+ blk[5] = (x0-x4)>>8;
+ blk[6] = (x3-x2)>>8;
+ blk[7] = (x7-x1)>>8;
+}
+
+/* column (vertical) IDCT
+ *
+ * 7 pi 1
+ * dst[8*k] = sum c[l] * src[8*l] * cos( -- * ( k + - ) * l )
+ * l=0 8 2
+ *
+ * where: c[0] = 1/1024
+ * c[1..7] = (1/1024)*sqrt(2)
+ */
+static void idctcol(blk)
+short *blk;
+{
+ int x0, x1, x2, x3, x4, x5, x6, x7, x8;
+
+ /* shortcut */
+ if (!((x1 = (blk[8*4]<<8)) | (x2 = blk[8*6]) | (x3 = blk[8*2]) |
+ (x4 = blk[8*1]) | (x5 = blk[8*7]) | (x6 = blk[8*5]) | (x7 = blk[8*3])))
+ {
+ blk[8*0]=blk[8*1]=blk[8*2]=blk[8*3]=blk[8*4]=blk[8*5]=blk[8*6]=blk[8*7]=
+ iclp[(blk[8*0]+32)>>6];
+ return;
+ }
+
+ x0 = (blk[8*0]<<8) + 8192;
+
+ /* first stage */
+ x8 = W7*(x4+x5) + 4;
+ x4 = (x8+(W1-W7)*x4)>>3;
+ x5 = (x8-(W1+W7)*x5)>>3;
+ x8 = W3*(x6+x7) + 4;
+ x6 = (x8-(W3-W5)*x6)>>3;
+ x7 = (x8-(W3+W5)*x7)>>3;
+
+ /* second stage */
+ x8 = x0 + x1;
+ x0 -= x1;
+ x1 = W6*(x3+x2) + 4;
+ x2 = (x1-(W2+W6)*x2)>>3;
+ x3 = (x1+(W2-W6)*x3)>>3;
+ x1 = x4 + x6;
+ x4 -= x6;
+ x6 = x5 + x7;
+ x5 -= x7;
+
+ /* third stage */
+ x7 = x8 + x3;
+ x8 -= x3;
+ x3 = x0 + x2;
+ x0 -= x2;
+ x2 = (181*(x4+x5)+128)>>8;
+ x4 = (181*(x4-x5)+128)>>8;
+
+ /* fourth stage */
+ blk[8*0] = iclp[(x7+x1)>>14];
+ blk[8*1] = iclp[(x3+x2)>>14];
+ blk[8*2] = iclp[(x0+x4)>>14];
+ blk[8*3] = iclp[(x8+x6)>>14];
+ blk[8*4] = iclp[(x8-x6)>>14];
+ blk[8*5] = iclp[(x0-x4)>>14];
+ blk[8*6] = iclp[(x3-x2)>>14];
+ blk[8*7] = iclp[(x7-x1)>>14];
+}
+
+/* two dimensional inverse discrete cosine transform */
+void idct(block)
+short *block;
+{
+ int i;
+
+ for (i=0; i<8; i++)
+ idctrow(block+8*i);
+
+ for (i=0; i<8; i++)
+ idctcol(block+i);
+}
+
+void init_idct()
+{
+ int i;
+
+ iclp = iclip+512;
+ for (i= -512; i<512; i++)
+ iclp[i] = (i<-256) ? -256 : ((i>255) ? 255 : i);
+}
--- /dev/null
+/* motion.c, motion estimation */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include <stdio.h>
+#include "config.h"
+#include "global.h"
+
+/* private prototypes */
+
+static void frame_ME _ANSI_ARGS_((unsigned char *oldorg, unsigned char *neworg,
+ unsigned char *oldref, unsigned char *newref, unsigned char *cur,
+ int i, int j, int sxf, int syf, int sxb, int syb, struct mbinfo *mbi));
+
+static void field_ME _ANSI_ARGS_((unsigned char *oldorg, unsigned char *neworg,
+ unsigned char *oldref, unsigned char *newref, unsigned char *cur,
+ unsigned char *curref, int i, int j, int sxf, int syf, int sxb, int syb,
+ struct mbinfo *mbi, int secondfield, int ipflag));
+
+static void frame_estimate _ANSI_ARGS_((unsigned char *org,
+ unsigned char *ref, unsigned char *mb,
+ int i, int j,
+ int sx, int sy, int *iminp, int *jminp, int *imintp, int *jmintp,
+ int *iminbp, int *jminbp, int *dframep, int *dfieldp,
+ int *tselp, int *bselp, int imins[2][2], int jmins[2][2]));
+
+static void field_estimate _ANSI_ARGS_((unsigned char *toporg,
+ unsigned char *topref, unsigned char *botorg, unsigned char *botref,
+ unsigned char *mb, int i, int j, int sx, int sy, int ipflag,
+ int *iminp, int *jminp, int *imin8up, int *jmin8up, int *imin8lp,
+ int *jmin8lp, int *dfieldp, int *d8p, int *selp, int *sel8up, int *sel8lp,
+ int *iminsp, int *jminsp, int *dsp));
+
+static void dpframe_estimate _ANSI_ARGS_((unsigned char *ref,
+ unsigned char *mb, int i, int j, int iminf[2][2], int jminf[2][2],
+ int *iminp, int *jminp, int *imindmvp, int *jmindmvp,
+ int *dmcp, int *vmcp));
+
+static void dpfield_estimate _ANSI_ARGS_((unsigned char *topref,
+ unsigned char *botref, unsigned char *mb,
+ int i, int j, int imins, int jmins, int *imindmvp, int *jmindmvp,
+ int *dmcp, int *vmcp));
+
+static int fullsearch _ANSI_ARGS_((unsigned char *org, unsigned char *ref,
+ unsigned char *blk,
+ int lx, int i0, int j0, int sx, int sy, int h, int xmax, int ymax,
+ int *iminp, int *jminp));
+
+static int dist1 _ANSI_ARGS_((unsigned char *blk1, unsigned char *blk2,
+ int lx, int hx, int hy, int h, int distlim));
+
+static int dist2 _ANSI_ARGS_((unsigned char *blk1, unsigned char *blk2,
+ int lx, int hx, int hy, int h));
+
+static int bdist1 _ANSI_ARGS_((unsigned char *pf, unsigned char *pb,
+ unsigned char *p2, int lx, int hxf, int hyf, int hxb, int hyb, int h));
+
+static int bdist2 _ANSI_ARGS_((unsigned char *pf, unsigned char *pb,
+ unsigned char *p2, int lx, int hxf, int hyf, int hxb, int hyb, int h));
+
+static int variance _ANSI_ARGS_((unsigned char *p, int lx));
+
+/*
+ * motion estimation for progressive and interlaced frame pictures
+ *
+ * oldorg: source frame for forward prediction (used for P and B frames)
+ * neworg: source frame for backward prediction (B frames only)
+ * oldref: reconstructed frame for forward prediction (P and B frames)
+ * newref: reconstructed frame for backward prediction (B frames only)
+ * cur: current frame (the one for which the prediction is formed)
+ * sxf,syf: forward search window (frame coordinates)
+ * sxb,syb: backward search window (frame coordinates)
+ * mbi: pointer to macroblock info structure
+ *
+ * results:
+ * mbi->
+ * mb_type: 0, MB_INTRA, MB_FORWARD, MB_BACKWARD, MB_FORWARD|MB_BACKWARD
+ * MV[][][]: motion vectors (frame format)
+ * mv_field_sel: top/bottom field (for field prediction)
+ * motion_type: MC_FRAME, MC_FIELD
+ *
+ * uses global vars: pict_type, frame_pred_dct
+ */
+void motion_estimation(oldorg,neworg,oldref,newref,cur,curref,
+ sxf,syf,sxb,syb,mbi,secondfield,ipflag)
+unsigned char *oldorg,*neworg,*oldref,*newref,*cur,*curref;
+int sxf,syf,sxb,syb;
+struct mbinfo *mbi;
+int secondfield,ipflag;
+{
+ int i, j;
+
+ /* loop through all macroblocks of the picture */
+ for (j=0; j<height2; j+=16)
+ {
+ for (i=0; i<width; i+=16)
+ {
+ if (pict_struct==FRAME_PICTURE)
+ frame_ME(oldorg,neworg,oldref,newref,cur,i,j,sxf,syf,sxb,syb,mbi);
+ else
+ field_ME(oldorg,neworg,oldref,newref,cur,curref,i,j,sxf,syf,sxb,syb,
+ mbi,secondfield,ipflag);
+ mbi++;
+ }
+
+ if (!quiet)
+ {
+ putc('.',stderr);
+ fflush(stderr);
+ }
+ }
+ if (!quiet)
+ putc('\n',stderr);
+}
+
+static void frame_ME(oldorg,neworg,oldref,newref,cur,i,j,sxf,syf,sxb,syb,mbi)
+unsigned char *oldorg,*neworg,*oldref,*newref,*cur;
+int i,j,sxf,syf,sxb,syb;
+struct mbinfo *mbi;
+{
+ int imin,jmin,iminf,jminf,iminr,jminr;
+ int imint,jmint,iminb,jminb;
+ int imintf,jmintf,iminbf,jminbf;
+ int imintr,jmintr,iminbr,jminbr;
+ int var,v0;
+ int dmc,dmcf,dmcr,dmci,vmc,vmcf,vmcr,vmci;
+ int dmcfield,dmcfieldf,dmcfieldr,dmcfieldi;
+ int tsel,bsel,tself,bself,tselr,bselr;
+ unsigned char *mb;
+ int imins[2][2],jmins[2][2];
+ int imindp,jmindp,imindmv,jmindmv,dmc_dp,vmc_dp;
+
+ mb = cur + i + width*j;
+
+ var = variance(mb,width);
+
+ if (pict_type==I_TYPE)
+ mbi->mb_type = MB_INTRA;
+ else if (pict_type==P_TYPE)
+ {
+ if (frame_pred_dct)
+ {
+ dmc = fullsearch(oldorg,oldref,mb,
+ width,i,j,sxf,syf,16,width,height,&imin,&jmin);
+ vmc = dist2(oldref+(imin>>1)+width*(jmin>>1),mb,
+ width,imin&1,jmin&1,16);
+ mbi->motion_type = MC_FRAME;
+ }
+ else
+ {
+ frame_estimate(oldorg,oldref,mb,i,j,sxf,syf,
+ &imin,&jmin,&imint,&jmint,&iminb,&jminb,
+ &dmc,&dmcfield,&tsel,&bsel,imins,jmins);
+
+ if (M==1)
+ dpframe_estimate(oldref,mb,i,j>>1,imins,jmins,
+ &imindp,&jmindp,&imindmv,&jmindmv,&dmc_dp,&vmc_dp);
+
+ /* select between dual prime, frame and field prediction */
+ if (M==1 && dmc_dp<dmc && dmc_dp<dmcfield)
+ {
+ mbi->motion_type = MC_DMV;
+ dmc = dmc_dp;
+ vmc = vmc_dp;
+ }
+ else if (dmc<=dmcfield)
+ {
+ mbi->motion_type = MC_FRAME;
+ vmc = dist2(oldref+(imin>>1)+width*(jmin>>1),mb,
+ width,imin&1,jmin&1,16);
+ }
+ else
+ {
+ mbi->motion_type = MC_FIELD;
+ dmc = dmcfield;
+ vmc = dist2(oldref+(tsel?width:0)+(imint>>1)+(width<<1)*(jmint>>1),
+ mb,width<<1,imint&1,jmint&1,8);
+ vmc+= dist2(oldref+(bsel?width:0)+(iminb>>1)+(width<<1)*(jminb>>1),
+ mb+width,width<<1,iminb&1,jminb&1,8);
+ }
+ }
+
+ /* select between intra or non-intra coding:
+ *
+ * selection is based on intra block variance (var) vs.
+ * prediction error variance (vmc)
+ *
+ * blocks with small prediction error are always coded non-intra
+ * even if variance is smaller (is this reasonable?)
+ */
+ if (vmc>var && vmc>=9*256)
+ mbi->mb_type = MB_INTRA;
+ else
+ {
+ /* select between MC / No-MC
+ *
+ * use No-MC if var(No-MC) <= 1.25*var(MC)
+ * (i.e slightly biased towards No-MC)
+ *
+ * blocks with small prediction error are always coded as No-MC
+ * (requires no motion vectors, allows skipping)
+ */
+ v0 = dist2(oldref+i+width*j,mb,width,0,0,16);
+ if (4*v0>5*vmc && v0>=9*256)
+ {
+ /* use MC */
+ var = vmc;
+ mbi->mb_type = MB_FORWARD;
+ if (mbi->motion_type==MC_FRAME)
+ {
+ mbi->MV[0][0][0] = imin - (i<<1);
+ mbi->MV[0][0][1] = jmin - (j<<1);
+ }
+ else if (mbi->motion_type==MC_DMV)
+ {
+ /* these are FRAME vectors */
+ /* same parity vector */
+ mbi->MV[0][0][0] = imindp - (i<<1);
+ mbi->MV[0][0][1] = (jmindp<<1) - (j<<1);
+
+ /* opposite parity vector */
+ mbi->dmvector[0] = imindmv;
+ mbi->dmvector[1] = jmindmv;
+ }
+ else
+ {
+ /* these are FRAME vectors */
+ mbi->MV[0][0][0] = imint - (i<<1);
+ mbi->MV[0][0][1] = (jmint<<1) - (j<<1);
+ mbi->MV[1][0][0] = iminb - (i<<1);
+ mbi->MV[1][0][1] = (jminb<<1) - (j<<1);
+ mbi->mv_field_sel[0][0] = tsel;
+ mbi->mv_field_sel[1][0] = bsel;
+ }
+ }
+ else
+ {
+ /* No-MC */
+ var = v0;
+ mbi->mb_type = 0;
+ mbi->motion_type = MC_FRAME;
+ mbi->MV[0][0][0] = 0;
+ mbi->MV[0][0][1] = 0;
+ }
+ }
+ }
+ else /* if (pict_type==B_TYPE) */
+ {
+ if (frame_pred_dct)
+ {
+ /* forward */
+ dmcf = fullsearch(oldorg,oldref,mb,
+ width,i,j,sxf,syf,16,width,height,&iminf,&jminf);
+ vmcf = dist2(oldref+(iminf>>1)+width*(jminf>>1),mb,
+ width,iminf&1,jminf&1,16);
+
+ /* backward */
+ dmcr = fullsearch(neworg,newref,mb,
+ width,i,j,sxb,syb,16,width,height,&iminr,&jminr);
+ vmcr = dist2(newref+(iminr>>1)+width*(jminr>>1),mb,
+ width,iminr&1,jminr&1,16);
+
+ /* interpolated (bidirectional) */
+ vmci = bdist2(oldref+(iminf>>1)+width*(jminf>>1),
+ newref+(iminr>>1)+width*(jminr>>1),
+ mb,width,iminf&1,jminf&1,iminr&1,jminr&1,16);
+
+ /* decisions */
+
+ /* select between forward/backward/interpolated prediction:
+ * use the one with smallest mean sqaured prediction error
+ */
+ if (vmcf<=vmcr && vmcf<=vmci)
+ {
+ vmc = vmcf;
+ mbi->mb_type = MB_FORWARD;
+ }
+ else if (vmcr<=vmci)
+ {
+ vmc = vmcr;
+ mbi->mb_type = MB_BACKWARD;
+ }
+ else
+ {
+ vmc = vmci;
+ mbi->mb_type = MB_FORWARD|MB_BACKWARD;
+ }
+
+ mbi->motion_type = MC_FRAME;
+ }
+ else
+ {
+ /* forward prediction */
+ frame_estimate(oldorg,oldref,mb,i,j,sxf,syf,
+ &iminf,&jminf,&imintf,&jmintf,&iminbf,&jminbf,
+ &dmcf,&dmcfieldf,&tself,&bself,imins,jmins);
+
+ /* backward prediction */
+ frame_estimate(neworg,newref,mb,i,j,sxb,syb,
+ &iminr,&jminr,&imintr,&jmintr,&iminbr,&jminbr,
+ &dmcr,&dmcfieldr,&tselr,&bselr,imins,jmins);
+
+ /* calculate interpolated distance */
+ /* frame */
+ dmci = bdist1(oldref+(iminf>>1)+width*(jminf>>1),
+ newref+(iminr>>1)+width*(jminr>>1),
+ mb,width,iminf&1,jminf&1,iminr&1,jminr&1,16);
+
+ /* top field */
+ dmcfieldi = bdist1(
+ oldref+(imintf>>1)+(tself?width:0)+(width<<1)*(jmintf>>1),
+ newref+(imintr>>1)+(tselr?width:0)+(width<<1)*(jmintr>>1),
+ mb,width<<1,imintf&1,jmintf&1,imintr&1,jmintr&1,8);
+
+ /* bottom field */
+ dmcfieldi+= bdist1(
+ oldref+(iminbf>>1)+(bself?width:0)+(width<<1)*(jminbf>>1),
+ newref+(iminbr>>1)+(bselr?width:0)+(width<<1)*(jminbr>>1),
+ mb+width,width<<1,iminbf&1,jminbf&1,iminbr&1,jminbr&1,8);
+
+ /* select prediction type of minimum distance from the
+ * six candidates (field/frame * forward/backward/interpolated)
+ */
+ if (dmci<dmcfieldi && dmci<dmcf && dmci<dmcfieldf
+ && dmci<dmcr && dmci<dmcfieldr)
+ {
+ /* frame, interpolated */
+ mbi->mb_type = MB_FORWARD|MB_BACKWARD;
+ mbi->motion_type = MC_FRAME;
+ vmc = bdist2(oldref+(iminf>>1)+width*(jminf>>1),
+ newref+(iminr>>1)+width*(jminr>>1),
+ mb,width,iminf&1,jminf&1,iminr&1,jminr&1,16);
+ }
+ else if (dmcfieldi<dmcf && dmcfieldi<dmcfieldf
+ && dmcfieldi<dmcr && dmcfieldi<dmcfieldr)
+ {
+ /* field, interpolated */
+ mbi->mb_type = MB_FORWARD|MB_BACKWARD;
+ mbi->motion_type = MC_FIELD;
+ vmc = bdist2(oldref+(imintf>>1)+(tself?width:0)+(width<<1)*(jmintf>>1),
+ newref+(imintr>>1)+(tselr?width:0)+(width<<1)*(jmintr>>1),
+ mb,width<<1,imintf&1,jmintf&1,imintr&1,jmintr&1,8);
+ vmc+= bdist2(oldref+(iminbf>>1)+(bself?width:0)+(width<<1)*(jminbf>>1),
+ newref+(iminbr>>1)+(bselr?width:0)+(width<<1)*(jminbr>>1),
+ mb+width,width<<1,iminbf&1,jminbf&1,iminbr&1,jminbr&1,8);
+ }
+ else if (dmcf<dmcfieldf && dmcf<dmcr && dmcf<dmcfieldr)
+ {
+ /* frame, forward */
+ mbi->mb_type = MB_FORWARD;
+ mbi->motion_type = MC_FRAME;
+ vmc = dist2(oldref+(iminf>>1)+width*(jminf>>1),mb,
+ width,iminf&1,jminf&1,16);
+ }
+ else if (dmcfieldf<dmcr && dmcfieldf<dmcfieldr)
+ {
+ /* field, forward */
+ mbi->mb_type = MB_FORWARD;
+ mbi->motion_type = MC_FIELD;
+ vmc = dist2(oldref+(tself?width:0)+(imintf>>1)+(width<<1)*(jmintf>>1),
+ mb,width<<1,imintf&1,jmintf&1,8);
+ vmc+= dist2(oldref+(bself?width:0)+(iminbf>>1)+(width<<1)*(jminbf>>1),
+ mb+width,width<<1,iminbf&1,jminbf&1,8);
+ }
+ else if (dmcr<dmcfieldr)
+ {
+ /* frame, backward */
+ mbi->mb_type = MB_BACKWARD;
+ mbi->motion_type = MC_FRAME;
+ vmc = dist2(newref+(iminr>>1)+width*(jminr>>1),mb,
+ width,iminr&1,jminr&1,16);
+ }
+ else
+ {
+ /* field, backward */
+ mbi->mb_type = MB_BACKWARD;
+ mbi->motion_type = MC_FIELD;
+ vmc = dist2(newref+(tselr?width:0)+(imintr>>1)+(width<<1)*(jmintr>>1),
+ mb,width<<1,imintr&1,jmintr&1,8);
+ vmc+= dist2(newref+(bselr?width:0)+(iminbr>>1)+(width<<1)*(jminbr>>1),
+ mb+width,width<<1,iminbr&1,jminbr&1,8);
+ }
+ }
+
+ /* select between intra or non-intra coding:
+ *
+ * selection is based on intra block variance (var) vs.
+ * prediction error variance (vmc)
+ *
+ * blocks with small prediction error are always coded non-intra
+ * even if variance is smaller (is this reasonable?)
+ */
+ if (vmc>var && vmc>=9*256)
+ mbi->mb_type = MB_INTRA;
+ else
+ {
+ var = vmc;
+ if (mbi->motion_type==MC_FRAME)
+ {
+ /* forward */
+ mbi->MV[0][0][0] = iminf - (i<<1);
+ mbi->MV[0][0][1] = jminf - (j<<1);
+ /* backward */
+ mbi->MV[0][1][0] = iminr - (i<<1);
+ mbi->MV[0][1][1] = jminr - (j<<1);
+ }
+ else
+ {
+ /* these are FRAME vectors */
+ /* forward */
+ mbi->MV[0][0][0] = imintf - (i<<1);
+ mbi->MV[0][0][1] = (jmintf<<1) - (j<<1);
+ mbi->MV[1][0][0] = iminbf - (i<<1);
+ mbi->MV[1][0][1] = (jminbf<<1) - (j<<1);
+ mbi->mv_field_sel[0][0] = tself;
+ mbi->mv_field_sel[1][0] = bself;
+ /* backward */
+ mbi->MV[0][1][0] = imintr - (i<<1);
+ mbi->MV[0][1][1] = (jmintr<<1) - (j<<1);
+ mbi->MV[1][1][0] = iminbr - (i<<1);
+ mbi->MV[1][1][1] = (jminbr<<1) - (j<<1);
+ mbi->mv_field_sel[0][1] = tselr;
+ mbi->mv_field_sel[1][1] = bselr;
+ }
+ }
+ }
+
+ mbi->var = var;
+}
+
+/*
+ * motion estimation for field pictures
+ *
+ * oldorg: original frame for forward prediction (P and B frames)
+ * neworg: original frame for backward prediction (B frames only)
+ * oldref: reconstructed frame for forward prediction (P and B frames)
+ * newref: reconstructed frame for backward prediction (B frames only)
+ * cur: current original frame (the one for which the prediction is formed)
+ * curref: current reconstructed frame (to predict second field from first)
+ * sxf,syf: forward search window (frame coordinates)
+ * sxb,syb: backward search window (frame coordinates)
+ * mbi: pointer to macroblock info structure
+ * secondfield: indicates second field of a frame (in P fields this means
+ * that reference field of opposite parity is in curref instead
+ * of oldref)
+ * ipflag: indicates a P type field which is the second field of a frame
+ * in which the first field is I type (this restricts predictions
+ * to be based only on the opposite parity (=I) field)
+ *
+ * results:
+ * mbi->
+ * mb_type: 0, MB_INTRA, MB_FORWARD, MB_BACKWARD, MB_FORWARD|MB_BACKWARD
+ * MV[][][]: motion vectors (field format)
+ * mv_field_sel: top/bottom field
+ * motion_type: MC_FIELD, MC_16X8
+ *
+ * uses global vars: pict_type, pict_struct
+ */
+static void field_ME(oldorg,neworg,oldref,newref,cur,curref,i,j,
+ sxf,syf,sxb,syb,mbi,secondfield,ipflag)
+unsigned char *oldorg,*neworg,*oldref,*newref,*cur,*curref;
+int i,j,sxf,syf,sxb,syb;
+struct mbinfo *mbi;
+int secondfield,ipflag;
+{
+ int w2;
+ unsigned char *mb, *toporg, *topref, *botorg, *botref;
+ int var,vmc,v0,dmc,dmcfieldi,dmc8i;
+ int imin,jmin,imin8u,jmin8u,imin8l,jmin8l,dmcfield,dmc8,sel,sel8u,sel8l;
+ int iminf,jminf,imin8uf,jmin8uf,imin8lf,jmin8lf,dmcfieldf,dmc8f,self,sel8uf,sel8lf;
+ int iminr,jminr,imin8ur,jmin8ur,imin8lr,jmin8lr,dmcfieldr,dmc8r,selr,sel8ur,sel8lr;
+ int imins,jmins,ds,imindmv,jmindmv,vmc_dp,dmc_dp;
+
+ w2 = width<<1;
+
+ mb = cur + i + w2*j;
+ if (pict_struct==BOTTOM_FIELD)
+ mb += width;
+
+ var = variance(mb,w2);
+
+ if (pict_type==I_TYPE)
+ mbi->mb_type = MB_INTRA;
+ else if (pict_type==P_TYPE)
+ {
+ toporg = oldorg;
+ topref = oldref;
+ botorg = oldorg + width;
+ botref = oldref + width;
+
+ if (secondfield)
+ {
+ /* opposite parity field is in same frame */
+ if (pict_struct==TOP_FIELD)
+ {
+ /* current is top field */
+ botorg = cur + width;
+ botref = curref + width;
+ }
+ else
+ {
+ /* current is bottom field */
+ toporg = cur;
+ topref = curref;
+ }
+ }
+
+ field_estimate(toporg,topref,botorg,botref,mb,i,j,sxf,syf,ipflag,
+ &imin,&jmin,&imin8u,&jmin8u,&imin8l,&jmin8l,
+ &dmcfield,&dmc8,&sel,&sel8u,&sel8l,&imins,&jmins,&ds);
+
+ if (M==1 && !ipflag) /* generic condition which permits Dual Prime */
+ dpfield_estimate(topref,botref,mb,i,j,imins,jmins,&imindmv,&jmindmv,
+ &dmc_dp,&vmc_dp);
+
+ /* select between dual prime, field and 16x8 prediction */
+ if (M==1 && !ipflag && dmc_dp<dmc8 && dmc_dp<dmcfield)
+ {
+ /* Dual Prime prediction */
+ mbi->motion_type = MC_DMV;
+ dmc = dmc_dp; /* L1 metric */
+ vmc = vmc_dp; /* we already calculated L2 error for Dual */
+
+ }
+ else if (dmc8<dmcfield)
+ {
+ /* 16x8 prediction */
+ mbi->motion_type = MC_16X8;
+ /* upper half block */
+ vmc = dist2((sel8u?botref:topref) + (imin8u>>1) + w2*(jmin8u>>1),
+ mb,w2,imin8u&1,jmin8u&1,8);
+ /* lower half block */
+ vmc+= dist2((sel8l?botref:topref) + (imin8l>>1) + w2*(jmin8l>>1),
+ mb+8*w2,w2,imin8l&1,jmin8l&1,8);
+ }
+ else
+ {
+ /* field prediction */
+ mbi->motion_type = MC_FIELD;
+ vmc = dist2((sel?botref:topref) + (imin>>1) + w2*(jmin>>1),
+ mb,w2,imin&1,jmin&1,16);
+ }
+
+ /* select between intra and non-intra coding */
+ if (vmc>var && vmc>=9*256)
+ mbi->mb_type = MB_INTRA;
+ else
+ {
+ /* zero MV field prediction from same parity ref. field
+ * (not allowed if ipflag is set)
+ */
+ if (!ipflag)
+ v0 = dist2(((pict_struct==BOTTOM_FIELD)?botref:topref) + i + w2*j,
+ mb,w2,0,0,16);
+ if (ipflag || (4*v0>5*vmc && v0>=9*256))
+ {
+ var = vmc;
+ mbi->mb_type = MB_FORWARD;
+ if (mbi->motion_type==MC_FIELD)
+ {
+ mbi->MV[0][0][0] = imin - (i<<1);
+ mbi->MV[0][0][1] = jmin - (j<<1);
+ mbi->mv_field_sel[0][0] = sel;
+ }
+ else if (mbi->motion_type==MC_DMV)
+ {
+ /* same parity vector */
+ mbi->MV[0][0][0] = imins - (i<<1);
+ mbi->MV[0][0][1] = jmins - (j<<1);
+
+ /* opposite parity vector */
+ mbi->dmvector[0] = imindmv;
+ mbi->dmvector[1] = jmindmv;
+ }
+ else
+ {
+ mbi->MV[0][0][0] = imin8u - (i<<1);
+ mbi->MV[0][0][1] = jmin8u - (j<<1);
+ mbi->MV[1][0][0] = imin8l - (i<<1);
+ mbi->MV[1][0][1] = jmin8l - ((j+8)<<1);
+ mbi->mv_field_sel[0][0] = sel8u;
+ mbi->mv_field_sel[1][0] = sel8l;
+ }
+ }
+ else
+ {
+ /* No MC */
+ var = v0;
+ mbi->mb_type = 0;
+ mbi->motion_type = MC_FIELD;
+ mbi->MV[0][0][0] = 0;
+ mbi->MV[0][0][1] = 0;
+ mbi->mv_field_sel[0][0] = (pict_struct==BOTTOM_FIELD);
+ }
+ }
+ }
+ else /* if (pict_type==B_TYPE) */
+ {
+ /* forward prediction */
+ field_estimate(oldorg,oldref,oldorg+width,oldref+width,mb,
+ i,j,sxf,syf,0,
+ &iminf,&jminf,&imin8uf,&jmin8uf,&imin8lf,&jmin8lf,
+ &dmcfieldf,&dmc8f,&self,&sel8uf,&sel8lf,&imins,&jmins,&ds);
+
+ /* backward prediction */
+ field_estimate(neworg,newref,neworg+width,newref+width,mb,
+ i,j,sxb,syb,0,
+ &iminr,&jminr,&imin8ur,&jmin8ur,&imin8lr,&jmin8lr,
+ &dmcfieldr,&dmc8r,&selr,&sel8ur,&sel8lr,&imins,&jmins,&ds);
+
+ /* calculate distances for bidirectional prediction */
+ /* field */
+ dmcfieldi = bdist1(oldref + (self?width:0) + (iminf>>1) + w2*(jminf>>1),
+ newref + (selr?width:0) + (iminr>>1) + w2*(jminr>>1),
+ mb,w2,iminf&1,jminf&1,iminr&1,jminr&1,16);
+
+ /* 16x8 upper half block */
+ dmc8i = bdist1(oldref + (sel8uf?width:0) + (imin8uf>>1) + w2*(jmin8uf>>1),
+ newref + (sel8ur?width:0) + (imin8ur>>1) + w2*(jmin8ur>>1),
+ mb,w2,imin8uf&1,jmin8uf&1,imin8ur&1,jmin8ur&1,8);
+
+ /* 16x8 lower half block */
+ dmc8i+= bdist1(oldref + (sel8lf?width:0) + (imin8lf>>1) + w2*(jmin8lf>>1),
+ newref + (sel8lr?width:0) + (imin8lr>>1) + w2*(jmin8lr>>1),
+ mb+8*w2,w2,imin8lf&1,jmin8lf&1,imin8lr&1,jmin8lr&1,8);
+
+ /* select prediction type of minimum distance */
+ if (dmcfieldi<dmc8i && dmcfieldi<dmcfieldf && dmcfieldi<dmc8f
+ && dmcfieldi<dmcfieldr && dmcfieldi<dmc8r)
+ {
+ /* field, interpolated */
+ mbi->mb_type = MB_FORWARD|MB_BACKWARD;
+ mbi->motion_type = MC_FIELD;
+ vmc = bdist2(oldref + (self?width:0) + (iminf>>1) + w2*(jminf>>1),
+ newref + (selr?width:0) + (iminr>>1) + w2*(jminr>>1),
+ mb,w2,iminf&1,jminf&1,iminr&1,jminr&1,16);
+ }
+ else if (dmc8i<dmcfieldf && dmc8i<dmc8f
+ && dmc8i<dmcfieldr && dmc8i<dmc8r)
+ {
+ /* 16x8, interpolated */
+ mbi->mb_type = MB_FORWARD|MB_BACKWARD;
+ mbi->motion_type = MC_16X8;
+
+ /* upper half block */
+ vmc = bdist2(oldref + (sel8uf?width:0) + (imin8uf>>1) + w2*(jmin8uf>>1),
+ newref + (sel8ur?width:0) + (imin8ur>>1) + w2*(jmin8ur>>1),
+ mb,w2,imin8uf&1,jmin8uf&1,imin8ur&1,jmin8ur&1,8);
+
+ /* lower half block */
+ vmc+= bdist2(oldref + (sel8lf?width:0) + (imin8lf>>1) + w2*(jmin8lf>>1),
+ newref + (sel8lr?width:0) + (imin8lr>>1) + w2*(jmin8lr>>1),
+ mb+8*w2,w2,imin8lf&1,jmin8lf&1,imin8lr&1,jmin8lr&1,8);
+ }
+ else if (dmcfieldf<dmc8f && dmcfieldf<dmcfieldr && dmcfieldf<dmc8r)
+ {
+ /* field, forward */
+ mbi->mb_type = MB_FORWARD;
+ mbi->motion_type = MC_FIELD;
+ vmc = dist2(oldref + (self?width:0) + (iminf>>1) + w2*(jminf>>1),
+ mb,w2,iminf&1,jminf&1,16);
+ }
+ else if (dmc8f<dmcfieldr && dmc8f<dmc8r)
+ {
+ /* 16x8, forward */
+ mbi->mb_type = MB_FORWARD;
+ mbi->motion_type = MC_16X8;
+
+ /* upper half block */
+ vmc = dist2(oldref + (sel8uf?width:0) + (imin8uf>>1) + w2*(jmin8uf>>1),
+ mb,w2,imin8uf&1,jmin8uf&1,8);
+
+ /* lower half block */
+ vmc+= dist2(oldref + (sel8lf?width:0) + (imin8lf>>1) + w2*(jmin8lf>>1),
+ mb+8*w2,w2,imin8lf&1,jmin8lf&1,8);
+ }
+ else if (dmcfieldr<dmc8r)
+ {
+ /* field, backward */
+ mbi->mb_type = MB_BACKWARD;
+ mbi->motion_type = MC_FIELD;
+ vmc = dist2(newref + (selr?width:0) + (iminr>>1) + w2*(jminr>>1),
+ mb,w2,iminr&1,jminr&1,16);
+ }
+ else
+ {
+ /* 16x8, backward */
+ mbi->mb_type = MB_BACKWARD;
+ mbi->motion_type = MC_16X8;
+
+ /* upper half block */
+ vmc = dist2(newref + (sel8ur?width:0) + (imin8ur>>1) + w2*(jmin8ur>>1),
+ mb,w2,imin8ur&1,jmin8ur&1,8);
+
+ /* lower half block */
+ vmc+= dist2(newref + (sel8lr?width:0) + (imin8lr>>1) + w2*(jmin8lr>>1),
+ mb+8*w2,w2,imin8lr&1,jmin8lr&1,8);
+ }
+
+ /* select between intra and non-intra coding */
+ if (vmc>var && vmc>=9*256)
+ mbi->mb_type = MB_INTRA;
+ else
+ {
+ var = vmc;
+ if (mbi->motion_type==MC_FIELD)
+ {
+ /* forward */
+ mbi->MV[0][0][0] = iminf - (i<<1);
+ mbi->MV[0][0][1] = jminf - (j<<1);
+ mbi->mv_field_sel[0][0] = self;
+ /* backward */
+ mbi->MV[0][1][0] = iminr - (i<<1);
+ mbi->MV[0][1][1] = jminr - (j<<1);
+ mbi->mv_field_sel[0][1] = selr;
+ }
+ else /* MC_16X8 */
+ {
+ /* forward */
+ mbi->MV[0][0][0] = imin8uf - (i<<1);
+ mbi->MV[0][0][1] = jmin8uf - (j<<1);
+ mbi->mv_field_sel[0][0] = sel8uf;
+ mbi->MV[1][0][0] = imin8lf - (i<<1);
+ mbi->MV[1][0][1] = jmin8lf - ((j+8)<<1);
+ mbi->mv_field_sel[1][0] = sel8lf;
+ /* backward */
+ mbi->MV[0][1][0] = imin8ur - (i<<1);
+ mbi->MV[0][1][1] = jmin8ur - (j<<1);
+ mbi->mv_field_sel[0][1] = sel8ur;
+ mbi->MV[1][1][0] = imin8lr - (i<<1);
+ mbi->MV[1][1][1] = jmin8lr - ((j+8)<<1);
+ mbi->mv_field_sel[1][1] = sel8lr;
+ }
+ }
+ }
+
+ mbi->var = var;
+}
+
+/*
+ * frame picture motion estimation
+ *
+ * org: top left pel of source reference frame
+ * ref: top left pel of reconstructed reference frame
+ * mb: macroblock to be matched
+ * i,j: location of mb relative to ref (=center of search window)
+ * sx,sy: half widths of search window
+ * iminp,jminp,dframep: location and value of best frame prediction
+ * imintp,jmintp,tselp: location of best field pred. for top field of mb
+ * iminbp,jminbp,bselp: location of best field pred. for bottom field of mb
+ * dfieldp: value of field prediction
+ */
+static void frame_estimate(org,ref,mb,i,j,sx,sy,
+ iminp,jminp,imintp,jmintp,iminbp,jminbp,dframep,dfieldp,tselp,bselp,
+ imins,jmins)
+unsigned char *org,*ref,*mb;
+int i,j,sx,sy;
+int *iminp,*jminp;
+int *imintp,*jmintp,*iminbp,*jminbp;
+int *dframep,*dfieldp;
+int *tselp,*bselp;
+int imins[2][2],jmins[2][2];
+{
+ int dt,db,dmint,dminb;
+ int imint,iminb,jmint,jminb;
+
+ /* frame prediction */
+ *dframep = fullsearch(org,ref,mb,width,i,j,sx,sy,16,width,height,
+ iminp,jminp);
+
+ /* predict top field from top field */
+ dt = fullsearch(org,ref,mb,width<<1,i,j>>1,sx,sy>>1,8,width,height>>1,
+ &imint,&jmint);
+
+ /* predict top field from bottom field */
+ db = fullsearch(org+width,ref+width,mb,width<<1,i,j>>1,sx,sy>>1,8,width,height>>1,
+ &iminb,&jminb);
+
+ imins[0][0] = imint;
+ jmins[0][0] = jmint;
+ imins[1][0] = iminb;
+ jmins[1][0] = jminb;
+
+ /* select prediction for top field */
+ if (dt<=db)
+ {
+ dmint=dt; *imintp=imint; *jmintp=jmint; *tselp=0;
+ }
+ else
+ {
+ dmint=db; *imintp=iminb; *jmintp=jminb; *tselp=1;
+ }
+
+ /* predict bottom field from top field */
+ dt = fullsearch(org,ref,mb+width,width<<1,i,j>>1,sx,sy>>1,8,width,height>>1,
+ &imint,&jmint);
+
+ /* predict bottom field from bottom field */
+ db = fullsearch(org+width,ref+width,mb+width,width<<1,i,j>>1,sx,sy>>1,8,width,height>>1,
+ &iminb,&jminb);
+
+ imins[0][1] = imint;
+ jmins[0][1] = jmint;
+ imins[1][1] = iminb;
+ jmins[1][1] = jminb;
+
+ /* select prediction for bottom field */
+ if (db<=dt)
+ {
+ dminb=db; *iminbp=iminb; *jminbp=jminb; *bselp=1;
+ }
+ else
+ {
+ dminb=dt; *iminbp=imint; *jminbp=jmint; *bselp=0;
+ }
+
+ *dfieldp=dmint+dminb;
+}
+
+/*
+ * field picture motion estimation subroutine
+ *
+ * toporg: address of original top reference field
+ * topref: address of reconstructed top reference field
+ * botorg: address of original bottom reference field
+ * botref: address of reconstructed bottom reference field
+ * mb: macroblock to be matched
+ * i,j: location of mb (=center of search window)
+ * sx,sy: half width/height of search window
+ *
+ * iminp,jminp,selp,dfieldp: location and distance of best field prediction
+ * imin8up,jmin8up,sel8up: location of best 16x8 pred. for upper half of mb
+ * imin8lp,jmin8lp,sel8lp: location of best 16x8 pred. for lower half of mb
+ * d8p: distance of best 16x8 prediction
+ * iminsp,jminsp,dsp: location and distance of best same parity field
+ * prediction (needed for dual prime, only valid if
+ * ipflag==0)
+ */
+static void field_estimate(toporg,topref,botorg,botref,mb,i,j,sx,sy,ipflag,
+ iminp,jminp,imin8up,jmin8up,imin8lp,jmin8lp,dfieldp,d8p,selp,sel8up,sel8lp,
+ iminsp,jminsp,dsp)
+unsigned char *toporg, *topref, *botorg, *botref, *mb;
+int i,j,sx,sy;
+int ipflag;
+int *iminp, *jminp;
+int *imin8up, *jmin8up, *imin8lp, *jmin8lp;
+int *dfieldp,*d8p;
+int *selp, *sel8up, *sel8lp;
+int *iminsp, *jminsp, *dsp;
+{
+ int dt, db, imint, jmint, iminb, jminb, notop, nobot;
+
+ /* if ipflag is set, predict from field of opposite parity only */
+ notop = ipflag && (pict_struct==TOP_FIELD);
+ nobot = ipflag && (pict_struct==BOTTOM_FIELD);
+
+ /* field prediction */
+
+ /* predict current field from top field */
+ if (notop)
+ dt = 65536; /* infinity */
+ else
+ dt = fullsearch(toporg,topref,mb,width<<1,
+ i,j,sx,sy>>1,16,width,height>>1,
+ &imint,&jmint);
+
+ /* predict current field from bottom field */
+ if (nobot)
+ db = 65536; /* infinity */
+ else
+ db = fullsearch(botorg,botref,mb,width<<1,
+ i,j,sx,sy>>1,16,width,height>>1,
+ &iminb,&jminb);
+
+ /* same parity prediction (only valid if ipflag==0) */
+ if (pict_struct==TOP_FIELD)
+ {
+ *iminsp = imint; *jminsp = jmint; *dsp = dt;
+ }
+ else
+ {
+ *iminsp = iminb; *jminsp = jminb; *dsp = db;
+ }
+
+ /* select field prediction */
+ if (dt<=db)
+ {
+ *dfieldp = dt; *iminp = imint; *jminp = jmint; *selp = 0;
+ }
+ else
+ {
+ *dfieldp = db; *iminp = iminb; *jminp = jminb; *selp = 1;
+ }
+
+
+ /* 16x8 motion compensation */
+
+ /* predict upper half field from top field */
+ if (notop)
+ dt = 65536;
+ else
+ dt = fullsearch(toporg,topref,mb,width<<1,
+ i,j,sx,sy>>1,8,width,height>>1,
+ &imint,&jmint);
+
+ /* predict upper half field from bottom field */
+ if (nobot)
+ db = 65536;
+ else
+ db = fullsearch(botorg,botref,mb,width<<1,
+ i,j,sx,sy>>1,8,width,height>>1,
+ &iminb,&jminb);
+
+ /* select prediction for upper half field */
+ if (dt<=db)
+ {
+ *d8p = dt; *imin8up = imint; *jmin8up = jmint; *sel8up = 0;
+ }
+ else
+ {
+ *d8p = db; *imin8up = iminb; *jmin8up = jminb; *sel8up = 1;
+ }
+
+ /* predict lower half field from top field */
+ if (notop)
+ dt = 65536;
+ else
+ dt = fullsearch(toporg,topref,mb+(width<<4),width<<1,
+ i,j+8,sx,sy>>1,8,width,height>>1,
+ &imint,&jmint);
+
+ /* predict lower half field from bottom field */
+ if (nobot)
+ db = 65536;
+ else
+ db = fullsearch(botorg,botref,mb+(width<<4),width<<1,
+ i,j+8,sx,sy>>1,8,width,height>>1,
+ &iminb,&jminb);
+
+ /* select prediction for lower half field */
+ if (dt<=db)
+ {
+ *d8p += dt; *imin8lp = imint; *jmin8lp = jmint; *sel8lp = 0;
+ }
+ else
+ {
+ *d8p += db; *imin8lp = iminb; *jmin8lp = jminb; *sel8lp = 1;
+ }
+}
+
+static void dpframe_estimate(ref,mb,i,j,iminf,jminf,
+ iminp,jminp,imindmvp, jmindmvp, dmcp, vmcp)
+unsigned char *ref, *mb;
+int i,j;
+int iminf[2][2], jminf[2][2];
+int *iminp, *jminp;
+int *imindmvp, *jmindmvp;
+int *dmcp,*vmcp;
+{
+ int pref,ppred,delta_x,delta_y;
+ int is,js,it,jt,ib,jb,it0,jt0,ib0,jb0;
+ int imins,jmins,imint,jmint,iminb,jminb,imindmv,jmindmv;
+ int vmc,local_dist;
+
+ /* Calculate Dual Prime distortions for 9 delta candidates
+ * for each of the four minimum field vectors
+ * Note: only for P pictures!
+ */
+
+ /* initialize minimum dual prime distortion to large value */
+ vmc = 1 << 30;
+
+ for (pref=0; pref<2; pref++)
+ {
+ for (ppred=0; ppred<2; ppred++)
+ {
+ /* convert Cartesian absolute to relative motion vector
+ * values (wrt current macroblock address (i,j)
+ */
+ is = iminf[pref][ppred] - (i<<1);
+ js = jminf[pref][ppred] - (j<<1);
+
+ if (pref!=ppred)
+ {
+ /* vertical field shift adjustment */
+ if (ppred==0)
+ js++;
+ else
+ js--;
+
+ /* mvxs and mvys scaling*/
+ is<<=1;
+ js<<=1;
+ if (topfirst == ppred)
+ {
+ /* second field: scale by 1/3 */
+ is = (is>=0) ? (is+1)/3 : -((-is+1)/3);
+ js = (js>=0) ? (js+1)/3 : -((-js+1)/3);
+ }
+ else
+ continue;
+ }
+
+ /* vector for prediction from field of opposite 'parity' */
+ if (topfirst)
+ {
+ /* vector for prediction of top field from bottom field */
+ it0 = ((is+(is>0))>>1);
+ jt0 = ((js+(js>0))>>1) - 1;
+
+ /* vector for prediction of bottom field from top field */
+ ib0 = ((3*is+(is>0))>>1);
+ jb0 = ((3*js+(js>0))>>1) + 1;
+ }
+ else
+ {
+ /* vector for prediction of top field from bottom field */
+ it0 = ((3*is+(is>0))>>1);
+ jt0 = ((3*js+(js>0))>>1) - 1;
+
+ /* vector for prediction of bottom field from top field */
+ ib0 = ((is+(is>0))>>1);
+ jb0 = ((js+(js>0))>>1) + 1;
+ }
+
+ /* convert back to absolute half-pel field picture coordinates */
+ is += i<<1;
+ js += j<<1;
+ it0 += i<<1;
+ jt0 += j<<1;
+ ib0 += i<<1;
+ jb0 += j<<1;
+
+ if (is >= 0 && is <= (width-16)<<1 &&
+ js >= 0 && js <= (height-16))
+ {
+ for (delta_y=-1; delta_y<=1; delta_y++)
+ {
+ for (delta_x=-1; delta_x<=1; delta_x++)
+ {
+ /* opposite field coordinates */
+ it = it0 + delta_x;
+ jt = jt0 + delta_y;
+ ib = ib0 + delta_x;
+ jb = jb0 + delta_y;
+
+ if (it >= 0 && it <= (width-16)<<1 &&
+ jt >= 0 && jt <= (height-16) &&
+ ib >= 0 && ib <= (width-16)<<1 &&
+ jb >= 0 && jb <= (height-16))
+ {
+ /* compute prediction error */
+ local_dist = bdist2(
+ ref + (is>>1) + (width<<1)*(js>>1),
+ ref + width + (it>>1) + (width<<1)*(jt>>1),
+ mb, /* current mb location */
+ width<<1, /* adjacent line distance */
+ is&1, js&1, it&1, jt&1, /* half-pel flags */
+ 8); /* block height */
+ local_dist += bdist2(
+ ref + width + (is>>1) + (width<<1)*(js>>1),
+ ref + (ib>>1) + (width<<1)*(jb>>1),
+ mb + width, /* current mb location */
+ width<<1, /* adjacent line distance */
+ is&1, js&1, ib&1, jb&1, /* half-pel flags */
+ 8); /* block height */
+
+ /* update delta with least distortion vector */
+ if (local_dist < vmc)
+ {
+ imins = is;
+ jmins = js;
+ imint = it;
+ jmint = jt;
+ iminb = ib;
+ jminb = jb;
+ imindmv = delta_x;
+ jmindmv = delta_y;
+ vmc = local_dist;
+ }
+ }
+ } /* end delta x loop */
+ } /* end delta y loop */
+ }
+ }
+ }
+
+ /* Compute L1 error for decision purposes */
+ local_dist = bdist1(
+ ref + (imins>>1) + (width<<1)*(jmins>>1),
+ ref + width + (imint>>1) + (width<<1)*(jmint>>1),
+ mb,
+ width<<1,
+ imins&1, jmins&1, imint&1, jmint&1,
+ 8);
+ local_dist += bdist1(
+ ref + width + (imins>>1) + (width<<1)*(jmins>>1),
+ ref + (iminb>>1) + (width<<1)*(jminb>>1),
+ mb + width,
+ width<<1,
+ imins&1, jmins&1, iminb&1, jminb&1,
+ 8);
+
+ *dmcp = local_dist;
+ *iminp = imins;
+ *jminp = jmins;
+ *imindmvp = imindmv;
+ *jmindmvp = jmindmv;
+ *vmcp = vmc;
+}
+
+static void dpfield_estimate(topref,botref,mb,i,j,imins,jmins,
+ imindmvp, jmindmvp, dmcp, vmcp)
+unsigned char *topref, *botref, *mb;
+int i,j;
+int imins, jmins;
+int *imindmvp, *jmindmvp;
+int *dmcp,*vmcp;
+{
+ unsigned char *sameref, *oppref;
+ int io0,jo0,io,jo,delta_x,delta_y,mvxs,mvys,mvxo0,mvyo0;
+ int imino,jmino,imindmv,jmindmv,vmc_dp,local_dist;
+
+ /* Calculate Dual Prime distortions for 9 delta candidates */
+ /* Note: only for P pictures! */
+
+ /* Assign opposite and same reference pointer */
+ if (pict_struct==TOP_FIELD)
+ {
+ sameref = topref;
+ oppref = botref;
+ }
+ else
+ {
+ sameref = botref;
+ oppref = topref;
+ }
+
+ /* convert Cartesian absolute to relative motion vector
+ * values (wrt current macroblock address (i,j)
+ */
+ mvxs = imins - (i<<1);
+ mvys = jmins - (j<<1);
+
+ /* vector for prediction from field of opposite 'parity' */
+ mvxo0 = (mvxs+(mvxs>0)) >> 1; /* mvxs // 2 */
+ mvyo0 = (mvys+(mvys>0)) >> 1; /* mvys // 2 */
+
+ /* vertical field shift correction */
+ if (pict_struct==TOP_FIELD)
+ mvyo0--;
+ else
+ mvyo0++;
+
+ /* convert back to absolute coordinates */
+ io0 = mvxo0 + (i<<1);
+ jo0 = mvyo0 + (j<<1);
+
+ /* initialize minimum dual prime distortion to large value */
+ vmc_dp = 1 << 30;
+
+ for (delta_y = -1; delta_y <= 1; delta_y++)
+ {
+ for (delta_x = -1; delta_x <=1; delta_x++)
+ {
+ /* opposite field coordinates */
+ io = io0 + delta_x;
+ jo = jo0 + delta_y;
+
+ if (io >= 0 && io <= (width-16)<<1 &&
+ jo >= 0 && jo <= (height2-16)<<1)
+ {
+ /* compute prediction error */
+ local_dist = bdist2(
+ sameref + (imins>>1) + width2*(jmins>>1),
+ oppref + (io>>1) + width2*(jo>>1),
+ mb, /* current mb location */
+ width2, /* adjacent line distance */
+ imins&1, jmins&1, io&1, jo&1, /* half-pel flags */
+ 16); /* block height */
+
+ /* update delta with least distortion vector */
+ if (local_dist < vmc_dp)
+ {
+ imino = io;
+ jmino = jo;
+ imindmv = delta_x;
+ jmindmv = delta_y;
+ vmc_dp = local_dist;
+ }
+ }
+ } /* end delta x loop */
+ } /* end delta y loop */
+
+ /* Compute L1 error for decision purposes */
+ *dmcp = bdist1(
+ sameref + (imins>>1) + width2*(jmins>>1),
+ oppref + (imino>>1) + width2*(jmino>>1),
+ mb, /* current mb location */
+ width2, /* adjacent line distance */
+ imins&1, jmins&1, imino&1, jmino&1, /* half-pel flags */
+ 16); /* block height */
+
+ *imindmvp = imindmv;
+ *jmindmvp = jmindmv;
+ *vmcp = vmc_dp;
+}
+
+/*
+ * full search block matching
+ *
+ * blk: top left pel of (16*h) block
+ * h: height of block
+ * lx: distance (in bytes) of vertically adjacent pels in ref,blk
+ * org: top left pel of source reference picture
+ * ref: top left pel of reconstructed reference picture
+ * i0,j0: center of search window
+ * sx,sy: half widths of search window
+ * xmax,ymax: right/bottom limits of search area
+ * iminp,jminp: pointers to where the result is stored
+ * result is given as half pel offset from ref(0,0)
+ * i.e. NOT relative to (i0,j0)
+ */
+static int fullsearch(org,ref,blk,lx,i0,j0,sx,sy,h,xmax,ymax,iminp,jminp)
+unsigned char *org,*ref,*blk;
+int lx,i0,j0,sx,sy,h,xmax,ymax;
+int *iminp,*jminp;
+{
+ int i,j,imin,jmin,ilow,ihigh,jlow,jhigh;
+ int d,dmin;
+ int k,l,sxy;
+
+ ilow = i0 - sx;
+ ihigh = i0 + sx;
+
+ if (ilow<0)
+ ilow = 0;
+
+ if (ihigh>xmax-16)
+ ihigh = xmax-16;
+
+ jlow = j0 - sy;
+ jhigh = j0 + sy;
+
+ if (jlow<0)
+ jlow = 0;
+
+ if (jhigh>ymax-h)
+ jhigh = ymax-h;
+
+ /* full pel search, spiraling outwards */
+
+ imin = i0;
+ jmin = j0;
+ dmin = dist1(org+imin+lx*jmin,blk,lx,0,0,h,65536);
+
+ sxy = (sx>sy) ? sx : sy;
+
+ for (l=1; l<=sxy; l++)
+ {
+ i = i0 - l;
+ j = j0 - l;
+ for (k=0; k<8*l; k++)
+ {
+ if (i>=ilow && i<=ihigh && j>=jlow && j<=jhigh)
+ {
+ d = dist1(org+i+lx*j,blk,lx,0,0,h,dmin);
+
+ if (d<dmin)
+ {
+ dmin = d;
+ imin = i;
+ jmin = j;
+ }
+ }
+
+ if (k<2*l) i++;
+ else if (k<4*l) j++;
+ else if (k<6*l) i--;
+ else j--;
+ }
+ }
+
+ /* half pel */
+ dmin = 65536;
+ imin <<= 1;
+ jmin <<= 1;
+ ilow = imin - (imin>0);
+ ihigh = imin + (imin<((xmax-16)<<1));
+ jlow = jmin - (jmin>0);
+ jhigh = jmin + (jmin<((ymax-h)<<1));
+
+ for (j=jlow; j<=jhigh; j++)
+ for (i=ilow; i<=ihigh; i++)
+ {
+ d = dist1(ref+(i>>1)+lx*(j>>1),blk,lx,i&1,j&1,h,dmin);
+
+ if (d<dmin)
+ {
+ dmin = d;
+ imin = i;
+ jmin = j;
+ }
+ }
+
+ *iminp = imin;
+ *jminp = jmin;
+
+ return dmin;
+}
+
+/*
+ * total absolute difference between two (16*h) blocks
+ * including optional half pel interpolation of blk1 (hx,hy)
+ * blk1,blk2: addresses of top left pels of both blocks
+ * lx: distance (in bytes) of vertically adjacent pels
+ * hx,hy: flags for horizontal and/or vertical interpolation
+ * h: height of block (usually 8 or 16)
+ * distlim: bail out if sum exceeds this value
+ */
+static int dist1(blk1,blk2,lx,hx,hy,h,distlim)
+unsigned char *blk1,*blk2;
+int lx,hx,hy,h;
+int distlim;
+{
+ unsigned char *p1,*p1a,*p2;
+ int i,j;
+ int s,v;
+
+ s = 0;
+ p1 = blk1;
+ p2 = blk2;
+
+ if (!hx && !hy)
+ for (j=0; j<h; j++)
+ {
+ if ((v = p1[0] - p2[0])<0) v = -v; s+= v;
+ if ((v = p1[1] - p2[1])<0) v = -v; s+= v;
+ if ((v = p1[2] - p2[2])<0) v = -v; s+= v;
+ if ((v = p1[3] - p2[3])<0) v = -v; s+= v;
+ if ((v = p1[4] - p2[4])<0) v = -v; s+= v;
+ if ((v = p1[5] - p2[5])<0) v = -v; s+= v;
+ if ((v = p1[6] - p2[6])<0) v = -v; s+= v;
+ if ((v = p1[7] - p2[7])<0) v = -v; s+= v;
+ if ((v = p1[8] - p2[8])<0) v = -v; s+= v;
+ if ((v = p1[9] - p2[9])<0) v = -v; s+= v;
+ if ((v = p1[10] - p2[10])<0) v = -v; s+= v;
+ if ((v = p1[11] - p2[11])<0) v = -v; s+= v;
+ if ((v = p1[12] - p2[12])<0) v = -v; s+= v;
+ if ((v = p1[13] - p2[13])<0) v = -v; s+= v;
+ if ((v = p1[14] - p2[14])<0) v = -v; s+= v;
+ if ((v = p1[15] - p2[15])<0) v = -v; s+= v;
+
+ if (s >= distlim)
+ break;
+
+ p1+= lx;
+ p2+= lx;
+ }
+ else if (hx && !hy)
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<16; i++)
+ {
+ v = ((unsigned int)(p1[i]+p1[i+1]+1)>>1) - p2[i];
+ if (v>=0)
+ s+= v;
+ else
+ s-= v;
+ }
+ p1+= lx;
+ p2+= lx;
+ }
+ else if (!hx && hy)
+ {
+ p1a = p1 + lx;
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<16; i++)
+ {
+ v = ((unsigned int)(p1[i]+p1a[i]+1)>>1) - p2[i];
+ if (v>=0)
+ s+= v;
+ else
+ s-= v;
+ }
+ p1 = p1a;
+ p1a+= lx;
+ p2+= lx;
+ }
+ }
+ else /* if (hx && hy) */
+ {
+ p1a = p1 + lx;
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<16; i++)
+ {
+ v = ((unsigned int)(p1[i]+p1[i+1]+p1a[i]+p1a[i+1]+2)>>2) - p2[i];
+ if (v>=0)
+ s+= v;
+ else
+ s-= v;
+ }
+ p1 = p1a;
+ p1a+= lx;
+ p2+= lx;
+ }
+ }
+
+ return s;
+}
+
+/*
+ * total squared difference between two (16*h) blocks
+ * including optional half pel interpolation of blk1 (hx,hy)
+ * blk1,blk2: addresses of top left pels of both blocks
+ * lx: distance (in bytes) of vertically adjacent pels
+ * hx,hy: flags for horizontal and/or vertical interpolation
+ * h: height of block (usually 8 or 16)
+ */
+static int dist2(blk1,blk2,lx,hx,hy,h)
+unsigned char *blk1,*blk2;
+int lx,hx,hy,h;
+{
+ unsigned char *p1,*p1a,*p2;
+ int i,j;
+ int s,v;
+
+ s = 0;
+ p1 = blk1;
+ p2 = blk2;
+ if (!hx && !hy)
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<16; i++)
+ {
+ v = p1[i] - p2[i];
+ s+= v*v;
+ }
+ p1+= lx;
+ p2+= lx;
+ }
+ else if (hx && !hy)
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<16; i++)
+ {
+ v = ((unsigned int)(p1[i]+p1[i+1]+1)>>1) - p2[i];
+ s+= v*v;
+ }
+ p1+= lx;
+ p2+= lx;
+ }
+ else if (!hx && hy)
+ {
+ p1a = p1 + lx;
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<16; i++)
+ {
+ v = ((unsigned int)(p1[i]+p1a[i]+1)>>1) - p2[i];
+ s+= v*v;
+ }
+ p1 = p1a;
+ p1a+= lx;
+ p2+= lx;
+ }
+ }
+ else /* if (hx && hy) */
+ {
+ p1a = p1 + lx;
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<16; i++)
+ {
+ v = ((unsigned int)(p1[i]+p1[i+1]+p1a[i]+p1a[i+1]+2)>>2) - p2[i];
+ s+= v*v;
+ }
+ p1 = p1a;
+ p1a+= lx;
+ p2+= lx;
+ }
+ }
+
+ return s;
+}
+
+/*
+ * absolute difference error between a (16*h) block and a bidirectional
+ * prediction
+ *
+ * p2: address of top left pel of block
+ * pf,hxf,hyf: address and half pel flags of forward ref. block
+ * pb,hxb,hyb: address and half pel flags of backward ref. block
+ * h: height of block
+ * lx: distance (in bytes) of vertically adjacent pels in p2,pf,pb
+ */
+static int bdist1(pf,pb,p2,lx,hxf,hyf,hxb,hyb,h)
+unsigned char *pf,*pb,*p2;
+int lx,hxf,hyf,hxb,hyb,h;
+{
+ unsigned char *pfa,*pfb,*pfc,*pba,*pbb,*pbc;
+ int i,j;
+ int s,v;
+
+ pfa = pf + hxf;
+ pfb = pf + lx*hyf;
+ pfc = pfb + hxf;
+
+ pba = pb + hxb;
+ pbb = pb + lx*hyb;
+ pbc = pbb + hxb;
+
+ s = 0;
+
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<16; i++)
+ {
+ v = ((((unsigned int)(*pf++ + *pfa++ + *pfb++ + *pfc++ + 2)>>2) +
+ ((unsigned int)(*pb++ + *pba++ + *pbb++ + *pbc++ + 2)>>2) + 1)>>1)
+ - *p2++;
+ if (v>=0)
+ s+= v;
+ else
+ s-= v;
+ }
+ p2+= lx-16;
+ pf+= lx-16;
+ pfa+= lx-16;
+ pfb+= lx-16;
+ pfc+= lx-16;
+ pb+= lx-16;
+ pba+= lx-16;
+ pbb+= lx-16;
+ pbc+= lx-16;
+ }
+
+ return s;
+}
+
+/*
+ * squared error between a (16*h) block and a bidirectional
+ * prediction
+ *
+ * p2: address of top left pel of block
+ * pf,hxf,hyf: address and half pel flags of forward ref. block
+ * pb,hxb,hyb: address and half pel flags of backward ref. block
+ * h: height of block
+ * lx: distance (in bytes) of vertically adjacent pels in p2,pf,pb
+ */
+static int bdist2(pf,pb,p2,lx,hxf,hyf,hxb,hyb,h)
+unsigned char *pf,*pb,*p2;
+int lx,hxf,hyf,hxb,hyb,h;
+{
+ unsigned char *pfa,*pfb,*pfc,*pba,*pbb,*pbc;
+ int i,j;
+ int s,v;
+
+ pfa = pf + hxf;
+ pfb = pf + lx*hyf;
+ pfc = pfb + hxf;
+
+ pba = pb + hxb;
+ pbb = pb + lx*hyb;
+ pbc = pbb + hxb;
+
+ s = 0;
+
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<16; i++)
+ {
+ v = ((((unsigned int)(*pf++ + *pfa++ + *pfb++ + *pfc++ + 2)>>2) +
+ ((unsigned int)(*pb++ + *pba++ + *pbb++ + *pbc++ + 2)>>2) + 1)>>1)
+ - *p2++;
+ s+=v*v;
+ }
+ p2+= lx-16;
+ pf+= lx-16;
+ pfa+= lx-16;
+ pfb+= lx-16;
+ pfc+= lx-16;
+ pb+= lx-16;
+ pba+= lx-16;
+ pbb+= lx-16;
+ pbc+= lx-16;
+ }
+
+ return s;
+}
+
+/*
+ * variance of a (16*16) block, multiplied by 256
+ * p: address of top left pel of block
+ * lx: distance (in bytes) of vertically adjacent pels
+ */
+static int variance(p,lx)
+unsigned char *p;
+int lx;
+{
+ int i,j;
+ unsigned int v,s,s2;
+
+ s = s2 = 0;
+
+ for (j=0; j<16; j++)
+ {
+ for (i=0; i<16; i++)
+ {
+ v = *p++;
+ s+= v;
+ s2+= v*v;
+ }
+ p+= lx-16;
+ }
+ return s2 - (s*s)/256;
+}
--- /dev/null
+/* mpeg2enc.c, main() and parameter file reading */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define GLOBAL /* used by global.h */
+#include "config.h"
+#include "global.h"
+
+/* private prototypes */
+static void init _ANSI_ARGS_((void));
+static void readparmfile _ANSI_ARGS_((char *fname));
+static void readquantmat _ANSI_ARGS_((void));
+
+
+int main(argc,argv)
+int argc;
+char *argv[];
+{
+ if (argc!=3)
+ {
+ printf("\n%s, %s\n",version,author);
+ printf("Usage: mpeg2encode in.par out.m2v\n");
+ exit(0);
+ }
+
+ /* read parameter file */
+ readparmfile(argv[1]);
+
+ /* read quantization matrices */
+ readquantmat();
+
+ /* open output file */
+ if (!(outfile=fopen(argv[2],"wb")))
+ {
+ sprintf(errortext,"Couldn't create output file %s",argv[2]);
+ error(errortext);
+ }
+
+ init();
+ putseq();
+
+ fclose(outfile);
+ fclose(statfile);
+
+ return 0;
+}
+
+static void init()
+{
+ int i, size;
+ static int block_count_tab[3] = {6,8,12};
+
+ initbits();
+ init_fdct();
+ init_idct();
+
+ /* round picture dimensions to nearest multiple of 16 or 32 */
+ mb_width = (horizontal_size+15)/16;
+ mb_height = prog_seq ? (vertical_size+15)/16 : 2*((vertical_size+31)/32);
+ mb_height2 = fieldpic ? mb_height>>1 : mb_height; /* for field pictures */
+ width = 16*mb_width;
+ height = 16*mb_height;
+
+ chrom_width = (chroma_format==CHROMA444) ? width : width>>1;
+ chrom_height = (chroma_format!=CHROMA420) ? height : height>>1;
+
+ height2 = fieldpic ? height>>1 : height;
+ width2 = fieldpic ? width<<1 : width;
+ chrom_width2 = fieldpic ? chrom_width<<1 : chrom_width;
+
+ block_count = block_count_tab[chroma_format-1];
+
+ /* clip table */
+ if (!(clp = (unsigned char *)malloc(1024)))
+ error("malloc failed\n");
+ clp+= 384;
+ for (i=-384; i<640; i++)
+ clp[i] = (i<0) ? 0 : ((i>255) ? 255 : i);
+
+ for (i=0; i<3; i++)
+ {
+ size = (i==0) ? width*height : chrom_width*chrom_height;
+
+ if (!(newrefframe[i] = (unsigned char *)malloc(size)))
+ error("malloc failed\n");
+ if (!(oldrefframe[i] = (unsigned char *)malloc(size)))
+ error("malloc failed\n");
+ if (!(auxframe[i] = (unsigned char *)malloc(size)))
+ error("malloc failed\n");
+ if (!(neworgframe[i] = (unsigned char *)malloc(size)))
+ error("malloc failed\n");
+ if (!(oldorgframe[i] = (unsigned char *)malloc(size)))
+ error("malloc failed\n");
+ if (!(auxorgframe[i] = (unsigned char *)malloc(size)))
+ error("malloc failed\n");
+ if (!(predframe[i] = (unsigned char *)malloc(size)))
+ error("malloc failed\n");
+ }
+
+ mbinfo = (struct mbinfo *)malloc(mb_width*mb_height2*sizeof(struct mbinfo));
+
+ if (!mbinfo)
+ error("malloc failed\n");
+
+ blocks =
+ (short (*)[64])malloc(mb_width*mb_height2*block_count*sizeof(short [64]));
+
+ if (!blocks)
+ error("malloc failed\n");
+
+ /* open statistics output file */
+ if (statname[0]=='-')
+ statfile = stdout;
+ else if (!(statfile = fopen(statname,"w")))
+ {
+ sprintf(errortext,"Couldn't create statistics output file %s",statname);
+ error(errortext);
+ }
+}
+
+void error(text)
+char *text;
+{
+ fprintf(stderr,text);
+ putc('\n',stderr);
+ exit(1);
+}
+
+static void readparmfile(fname)
+char *fname;
+{
+ int i;
+ int h,m,s,f;
+ FILE *fd;
+ char line[256];
+ static double ratetab[8]=
+ {24000.0/1001.0,24.0,25.0,30000.0/1001.0,30.0,50.0,60000.0/1001.0,60.0};
+ extern int r,Xi,Xb,Xp,d0i,d0p,d0b; /* rate control */
+ extern double avg_act; /* rate control */
+
+ if (!(fd = fopen(fname,"r")))
+ {
+ sprintf(errortext,"Couldn't open parameter file %s",fname);
+ error(errortext);
+ }
+
+ fgets(id_string,254,fd);
+ fgets(line,254,fd); sscanf(line,"%s",tplorg);
+ fgets(line,254,fd); sscanf(line,"%s",tplref);
+ fgets(line,254,fd); sscanf(line,"%s",iqname);
+ fgets(line,254,fd); sscanf(line,"%s",niqname);
+ fgets(line,254,fd); sscanf(line,"%s",statname);
+ fgets(line,254,fd); sscanf(line,"%d",&inputtype);
+ fgets(line,254,fd); sscanf(line,"%d",&nframes);
+ fgets(line,254,fd); sscanf(line,"%d",&frame0);
+ fgets(line,254,fd); sscanf(line,"%d:%d:%d:%d",&h,&m,&s,&f);
+ fgets(line,254,fd); sscanf(line,"%d",&N);
+ fgets(line,254,fd); sscanf(line,"%d",&M);
+ fgets(line,254,fd); sscanf(line,"%d",&mpeg1);
+ fgets(line,254,fd); sscanf(line,"%d",&fieldpic);
+ fgets(line,254,fd); sscanf(line,"%d",&horizontal_size);
+ fgets(line,254,fd); sscanf(line,"%d",&vertical_size);
+ fgets(line,254,fd); sscanf(line,"%d",&aspectratio);
+ fgets(line,254,fd); sscanf(line,"%d",&frame_rate_code);
+ fgets(line,254,fd); sscanf(line,"%lf",&bit_rate);
+ fgets(line,254,fd); sscanf(line,"%d",&vbv_buffer_size);
+ fgets(line,254,fd); sscanf(line,"%d",&low_delay);
+ fgets(line,254,fd); sscanf(line,"%d",&constrparms);
+ fgets(line,254,fd); sscanf(line,"%d",&profile);
+ fgets(line,254,fd); sscanf(line,"%d",&level);
+ fgets(line,254,fd); sscanf(line,"%d",&prog_seq);
+ fgets(line,254,fd); sscanf(line,"%d",&chroma_format);
+ fgets(line,254,fd); sscanf(line,"%d",&video_format);
+ fgets(line,254,fd); sscanf(line,"%d",&color_primaries);
+ fgets(line,254,fd); sscanf(line,"%d",&transfer_characteristics);
+ fgets(line,254,fd); sscanf(line,"%d",&matrix_coefficients);
+ fgets(line,254,fd); sscanf(line,"%d",&display_horizontal_size);
+ fgets(line,254,fd); sscanf(line,"%d",&display_vertical_size);
+ fgets(line,254,fd); sscanf(line,"%d",&dc_prec);
+ fgets(line,254,fd); sscanf(line,"%d",&topfirst);
+ fgets(line,254,fd); sscanf(line,"%d %d %d",
+ frame_pred_dct_tab,frame_pred_dct_tab+1,frame_pred_dct_tab+2);
+
+ fgets(line,254,fd); sscanf(line,"%d %d %d",
+ conceal_tab,conceal_tab+1,conceal_tab+2);
+
+ fgets(line,254,fd); sscanf(line,"%d %d %d",
+ qscale_tab,qscale_tab+1,qscale_tab+2);
+
+ fgets(line,254,fd); sscanf(line,"%d %d %d",
+ intravlc_tab,intravlc_tab+1,intravlc_tab+2);
+ fgets(line,254,fd); sscanf(line,"%d %d %d",
+ altscan_tab,altscan_tab+1,altscan_tab+2);
+ fgets(line,254,fd); sscanf(line,"%d",&repeatfirst);
+ fgets(line,254,fd); sscanf(line,"%d",&prog_frame);
+/* intra slice interval refresh period */
+ fgets(line,254,fd); sscanf(line,"%d",&P);
+ fgets(line,254,fd); sscanf(line,"%d",&r);
+ fgets(line,254,fd); sscanf(line,"%lf",&avg_act);
+ fgets(line,254,fd); sscanf(line,"%d",&Xi);
+ fgets(line,254,fd); sscanf(line,"%d",&Xp);
+ fgets(line,254,fd); sscanf(line,"%d",&Xb);
+ fgets(line,254,fd); sscanf(line,"%d",&d0i);
+ fgets(line,254,fd); sscanf(line,"%d",&d0p);
+ fgets(line,254,fd); sscanf(line,"%d",&d0b);
+
+ if (N<1)
+ error("N must be positive");
+ if (M<1)
+ error("M must be positive");
+ if (N%M != 0)
+ error("N must be an integer multiple of M");
+
+ motion_data = (struct motion_data *)malloc(M*sizeof(struct motion_data));
+ if (!motion_data)
+ error("malloc failed\n");
+
+ for (i=0; i<M; i++)
+ {
+ fgets(line,254,fd);
+ sscanf(line,"%d %d %d %d",
+ &motion_data[i].forw_hor_f_code, &motion_data[i].forw_vert_f_code,
+ &motion_data[i].sxf, &motion_data[i].syf);
+
+ if (i!=0)
+ {
+ fgets(line,254,fd);
+ sscanf(line,"%d %d %d %d",
+ &motion_data[i].back_hor_f_code, &motion_data[i].back_vert_f_code,
+ &motion_data[i].sxb, &motion_data[i].syb);
+ }
+ }
+
+ fclose(fd);
+
+ /* make flags boolean (x!=0 -> x=1) */
+ mpeg1 = !!mpeg1;
+ fieldpic = !!fieldpic;
+ low_delay = !!low_delay;
+ constrparms = !!constrparms;
+ prog_seq = !!prog_seq;
+ topfirst = !!topfirst;
+
+ for (i=0; i<3; i++)
+ {
+ frame_pred_dct_tab[i] = !!frame_pred_dct_tab[i];
+ conceal_tab[i] = !!conceal_tab[i];
+ qscale_tab[i] = !!qscale_tab[i];
+ intravlc_tab[i] = !!intravlc_tab[i];
+ altscan_tab[i] = !!altscan_tab[i];
+ }
+ repeatfirst = !!repeatfirst;
+ prog_frame = !!prog_frame;
+
+ /* make sure MPEG specific parameters are valid */
+ range_checks();
+
+ frame_rate = ratetab[frame_rate_code-1];
+
+ /* timecode -> frame number */
+ tc0 = h;
+ tc0 = 60*tc0 + m;
+ tc0 = 60*tc0 + s;
+ tc0 = (int)(frame_rate+0.5)*tc0 + f;
+
+ if (!mpeg1)
+ {
+ profile_and_level_checks();
+ }
+ else
+ {
+ /* MPEG-1 */
+ if (constrparms)
+ {
+ if (horizontal_size>768
+ || vertical_size>576
+ || ((horizontal_size+15)/16)*((vertical_size+15)/16)>396
+ || ((horizontal_size+15)/16)*((vertical_size+15)/16)*frame_rate>396*25.0
+ || frame_rate>30.0)
+ {
+ if (!quiet)
+ fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n");
+ constrparms = 0;
+ }
+ }
+
+ if (constrparms)
+ {
+ for (i=0; i<M; i++)
+ {
+ if (motion_data[i].forw_hor_f_code>4)
+ {
+ if (!quiet)
+ fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n");
+ constrparms = 0;
+ break;
+ }
+
+ if (motion_data[i].forw_vert_f_code>4)
+ {
+ if (!quiet)
+ fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n");
+ constrparms = 0;
+ break;
+ }
+
+ if (i!=0)
+ {
+ if (motion_data[i].back_hor_f_code>4)
+ {
+ if (!quiet)
+ fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n");
+ constrparms = 0;
+ break;
+ }
+
+ if (motion_data[i].back_vert_f_code>4)
+ {
+ if (!quiet)
+ fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n");
+ constrparms = 0;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* relational checks */
+
+ if (mpeg1)
+ {
+ if (!prog_seq)
+ {
+ if (!quiet)
+ fprintf(stderr,"Warning: setting progressive_sequence = 1\n");
+ prog_seq = 1;
+ }
+
+ if (chroma_format!=CHROMA420)
+ {
+ if (!quiet)
+ fprintf(stderr,"Warning: setting chroma_format = 1 (4:2:0)\n");
+ chroma_format = CHROMA420;
+ }
+
+ if (dc_prec!=0)
+ {
+ if (!quiet)
+ fprintf(stderr,"Warning: setting intra_dc_precision = 0\n");
+ dc_prec = 0;
+ }
+
+ for (i=0; i<3; i++)
+ if (qscale_tab[i])
+ {
+ if (!quiet)
+ fprintf(stderr,"Warning: setting qscale_tab[%d] = 0\n",i);
+ qscale_tab[i] = 0;
+ }
+
+ for (i=0; i<3; i++)
+ if (intravlc_tab[i])
+ {
+ if (!quiet)
+ fprintf(stderr,"Warning: setting intravlc_tab[%d] = 0\n",i);
+ intravlc_tab[i] = 0;
+ }
+
+ for (i=0; i<3; i++)
+ if (altscan_tab[i])
+ {
+ if (!quiet)
+ fprintf(stderr,"Warning: setting altscan_tab[%d] = 0\n",i);
+ altscan_tab[i] = 0;
+ }
+ }
+
+ if (!mpeg1 && constrparms)
+ {
+ if (!quiet)
+ fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n");
+ constrparms = 0;
+ }
+
+ if (prog_seq && !prog_frame)
+ {
+ if (!quiet)
+ fprintf(stderr,"Warning: setting progressive_frame = 1\n");
+ prog_frame = 1;
+ }
+
+ if (prog_frame && fieldpic)
+ {
+ if (!quiet)
+ fprintf(stderr,"Warning: setting field_pictures = 0\n");
+ fieldpic = 0;
+ }
+
+ if (!prog_frame && repeatfirst)
+ {
+ if (!quiet)
+ fprintf(stderr,"Warning: setting repeat_first_field = 0\n");
+ repeatfirst = 0;
+ }
+
+ if (prog_frame)
+ {
+ for (i=0; i<3; i++)
+ if (!frame_pred_dct_tab[i])
+ {
+ if (!quiet)
+ fprintf(stderr,"Warning: setting frame_pred_frame_dct[%d] = 1\n",i);
+ frame_pred_dct_tab[i] = 1;
+ }
+ }
+
+ if (prog_seq && !repeatfirst && topfirst)
+ {
+ if (!quiet)
+ fprintf(stderr,"Warning: setting top_field_first = 0\n");
+ topfirst = 0;
+ }
+
+ /* search windows */
+ for (i=0; i<M; i++)
+ {
+ if (motion_data[i].sxf > (4<<motion_data[i].forw_hor_f_code)-1)
+ {
+ if (!quiet)
+ fprintf(stderr,
+ "Warning: reducing forward horizontal search width to %d\n",
+ (4<<motion_data[i].forw_hor_f_code)-1);
+ motion_data[i].sxf = (4<<motion_data[i].forw_hor_f_code)-1;
+ }
+
+ if (motion_data[i].syf > (4<<motion_data[i].forw_vert_f_code)-1)
+ {
+ if (!quiet)
+ fprintf(stderr,
+ "Warning: reducing forward vertical search width to %d\n",
+ (4<<motion_data[i].forw_vert_f_code)-1);
+ motion_data[i].syf = (4<<motion_data[i].forw_vert_f_code)-1;
+ }
+
+ if (i!=0)
+ {
+ if (motion_data[i].sxb > (4<<motion_data[i].back_hor_f_code)-1)
+ {
+ if (!quiet)
+ fprintf(stderr,
+ "Warning: reducing backward horizontal search width to %d\n",
+ (4<<motion_data[i].back_hor_f_code)-1);
+ motion_data[i].sxb = (4<<motion_data[i].back_hor_f_code)-1;
+ }
+
+ if (motion_data[i].syb > (4<<motion_data[i].back_vert_f_code)-1)
+ {
+ if (!quiet)
+ fprintf(stderr,
+ "Warning: reducing backward vertical search width to %d\n",
+ (4<<motion_data[i].back_vert_f_code)-1);
+ motion_data[i].syb = (4<<motion_data[i].back_vert_f_code)-1;
+ }
+ }
+ }
+
+}
+
+static void readquantmat()
+{
+ int i,v;
+ FILE *fd;
+
+ if (iqname[0]=='-')
+ {
+ /* use default intra matrix */
+ load_iquant = 0;
+ for (i=0; i<64; i++)
+ intra_q[i] = default_intra_quantizer_matrix[i];
+ }
+ else
+ {
+ /* read customized intra matrix */
+ load_iquant = 1;
+ if (!(fd = fopen(iqname,"r")))
+ {
+ sprintf(errortext,"Couldn't open quant matrix file %s",iqname);
+ error(errortext);
+ }
+
+ for (i=0; i<64; i++)
+ {
+ fscanf(fd,"%d",&v);
+ if (v<1 || v>255)
+ error("invalid value in quant matrix");
+ intra_q[i] = v;
+ }
+
+ fclose(fd);
+ }
+
+ if (niqname[0]=='-')
+ {
+ /* use default non-intra matrix */
+ load_niquant = 0;
+ for (i=0; i<64; i++)
+ inter_q[i] = 16;
+ }
+ else
+ {
+ /* read customized non-intra matrix */
+ load_niquant = 1;
+ if (!(fd = fopen(niqname,"r")))
+ {
+ sprintf(errortext,"Couldn't open quant matrix file %s",niqname);
+ error(errortext);
+ }
+
+ for (i=0; i<64; i++)
+ {
+ fscanf(fd,"%d",&v);
+ if (v<1 || v>255)
+ error("invalid value in quant matrix");
+ inter_q[i] = v;
+ }
+
+ fclose(fd);
+ }
+}
--- /dev/null
+/* mpg2enc.h, defines and types */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#define PICTURE_START_CODE 0x100L
+#define SLICE_MIN_START 0x101L
+#define SLICE_MAX_START 0x1AFL
+#define USER_START_CODE 0x1B2L
+#define SEQ_START_CODE 0x1B3L
+#define EXT_START_CODE 0x1B5L
+#define SEQ_END_CODE 0x1B7L
+#define GOP_START_CODE 0x1B8L
+#define ISO_END_CODE 0x1B9L
+#define PACK_START_CODE 0x1BAL
+#define SYSTEM_START_CODE 0x1BBL
+
+/* picture coding type */
+#define I_TYPE 1
+#define P_TYPE 2
+#define B_TYPE 3
+#define D_TYPE 4
+
+/* picture structure */
+#define TOP_FIELD 1
+#define BOTTOM_FIELD 2
+#define FRAME_PICTURE 3
+
+/* macroblock type */
+#define MB_INTRA 1
+#define MB_PATTERN 2
+#define MB_BACKWARD 4
+#define MB_FORWARD 8
+#define MB_QUANT 16
+
+/* motion_type */
+#define MC_FIELD 1
+#define MC_FRAME 2
+#define MC_16X8 2
+#define MC_DMV 3
+
+/* mv_format */
+#define MV_FIELD 0
+#define MV_FRAME 1
+
+/* chroma_format */
+#define CHROMA420 1
+#define CHROMA422 2
+#define CHROMA444 3
+
+/* extension start code IDs */
+
+#define SEQ_ID 1
+#define DISP_ID 2
+#define QUANT_ID 3
+#define SEQSCAL_ID 5
+#define PANSCAN_ID 7
+#define CODING_ID 8
+#define SPATSCAL_ID 9
+#define TEMPSCAL_ID 10
+
+/* inputtype */
+#define T_Y_U_V 0
+#define T_YUV 1
+#define T_PPM 2
+
+/* macroblock information */
+struct mbinfo {
+ int mb_type; /* intra/forward/backward/interpolated */
+ int motion_type; /* frame/field/16x8/dual_prime */
+ int dct_type; /* field/frame DCT */
+ int mquant; /* quantization parameter */
+ int cbp; /* coded block pattern */
+ int skipped; /* skipped macroblock */
+ int MV[2][2][2]; /* motion vectors */
+ int mv_field_sel[2][2]; /* motion vertical field select */
+ int dmvector[2]; /* dual prime vectors */
+ double act; /* activity measure */
+ int var; /* for debugging */
+};
+
+/* motion data */
+struct motion_data {
+ int forw_hor_f_code,forw_vert_f_code; /* vector range */
+ int sxf,syf; /* search range */
+ int back_hor_f_code,back_vert_f_code;
+ int sxb,syb;
+};
--- /dev/null
+/* predict.c, motion compensated prediction */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include <stdio.h>
+#include "config.h"
+#include "global.h"
+
+/* private prototypes */
+static void predict_mb _ANSI_ARGS_((
+ unsigned char *oldref[], unsigned char *newref[], unsigned char *cur[],
+ int lx, int bx, int by, int pict_type, int pict_struct, int mb_type,
+ int motion_type, int secondfield,
+ int PMV[2][2][2], int mv_field_sel[2][2], int dmvector[2]));
+
+static void pred _ANSI_ARGS_((unsigned char *src[], int sfield,
+ unsigned char *dst[], int dfield,
+ int lx, int w, int h, int x, int y, int dx, int dy, int addflag));
+
+static void pred_comp _ANSI_ARGS_((unsigned char *src, unsigned char *dst,
+ int lx, int w, int h, int x, int y, int dx, int dy, int addflag));
+
+static void calc_DMV _ANSI_ARGS_((int DMV[][2], int *dmvector, int mvx,
+ int mvy));
+
+static void clearblock _ANSI_ARGS_((unsigned char *cur[], int i0, int j0));
+
+
+/* form prediction for a complete picture (frontend for predict_mb)
+ *
+ * reff: reference frame for forward prediction
+ * refb: reference frame for backward prediction
+ * cur: destination (current) frame
+ * secondfield: predict second field of a frame
+ * mbi: macroblock info
+ *
+ * Notes:
+ * - cf. predict_mb
+ */
+
+void predict(reff,refb,cur,secondfield,mbi)
+unsigned char *reff[],*refb[],*cur[3];
+int secondfield;
+struct mbinfo *mbi;
+{
+ int i, j, k;
+
+ k = 0;
+
+ /* loop through all macroblocks of the picture */
+ for (j=0; j<height2; j+=16)
+ for (i=0; i<width; i+=16)
+ {
+ predict_mb(reff,refb,cur,width,i,j,pict_type,pict_struct,
+ mbi[k].mb_type,mbi[k].motion_type,secondfield,
+ mbi[k].MV,mbi[k].mv_field_sel,mbi[k].dmvector);
+
+ k++;
+ }
+}
+
+/* form prediction for one macroblock
+ *
+ * oldref: reference frame for forward prediction
+ * newref: reference frame for backward prediction
+ * cur: destination (current) frame
+ * lx: frame width (identical to global var `width')
+ * bx,by: picture (field or frame) coordinates of macroblock to be predicted
+ * pict_type: I, P or B
+ * pict_struct: FRAME_PICTURE, TOP_FIELD, BOTTOM_FIELD
+ * mb_type: MB_FORWARD, MB_BACKWARD, MB_INTRA
+ * motion_type: MC_FRAME, MC_FIELD, MC_16X8, MC_DMV
+ * secondfield: predict second field of a frame
+ * PMV[2][2][2]: motion vectors (in half pel picture coordinates)
+ * mv_field_sel[2][2]: motion vertical field selects (for field predictions)
+ * dmvector: differential motion vectors (for dual prime)
+ *
+ * Notes:
+ * - when predicting a P type picture which is the second field of
+ * a frame, the same parity reference field is in oldref, while the
+ * opposite parity reference field is assumed to be in newref!
+ * - intra macroblocks are modelled to have a constant prediction of 128
+ * for all pels; this results in a DC DCT coefficient symmetric to 0
+ * - vectors for field prediction in frame pictures are in half pel frame
+ * coordinates (vertical component is twice the field value and always
+ * even)
+ *
+ * already covers dual prime (not yet used)
+ */
+
+static void predict_mb(oldref,newref,cur,lx,bx,by,pict_type,pict_struct,
+ mb_type,motion_type,secondfield,PMV,mv_field_sel,dmvector)
+unsigned char *oldref[],*newref[],*cur[];
+int lx;
+int bx,by;
+int pict_type;
+int pict_struct;
+int mb_type;
+int motion_type;
+int secondfield;
+int PMV[2][2][2], mv_field_sel[2][2], dmvector[2];
+{
+ int addflag, currentfield;
+ unsigned char **predframe;
+ int DMV[2][2];
+
+ if (mb_type&MB_INTRA)
+ {
+ clearblock(cur,bx,by);
+ return;
+ }
+
+ addflag = 0; /* first prediction is stored, second is added and averaged */
+
+ if ((mb_type & MB_FORWARD) || (pict_type==P_TYPE))
+ {
+ /* forward prediction, including zero MV in P pictures */
+
+ if (pict_struct==FRAME_PICTURE)
+ {
+ /* frame picture */
+
+ if ((motion_type==MC_FRAME) || !(mb_type & MB_FORWARD))
+ {
+ /* frame-based prediction in frame picture */
+ pred(oldref,0,cur,0,
+ lx,16,16,bx,by,PMV[0][0][0],PMV[0][0][1],0);
+ }
+ else if (motion_type==MC_FIELD)
+ {
+ /* field-based prediction in frame picture
+ *
+ * note scaling of the vertical coordinates (by, PMV[][0][1])
+ * from frame to field!
+ */
+
+ /* top field prediction */
+ pred(oldref,mv_field_sel[0][0],cur,0,
+ lx<<1,16,8,bx,by>>1,PMV[0][0][0],PMV[0][0][1]>>1,0);
+
+ /* bottom field prediction */
+ pred(oldref,mv_field_sel[1][0],cur,1,
+ lx<<1,16,8,bx,by>>1,PMV[1][0][0],PMV[1][0][1]>>1,0);
+ }
+ else if (motion_type==MC_DMV)
+ {
+ /* dual prime prediction */
+
+ /* calculate derived motion vectors */
+ calc_DMV(DMV,dmvector,PMV[0][0][0],PMV[0][0][1]>>1);
+
+ /* predict top field from top field */
+ pred(oldref,0,cur,0,
+ lx<<1,16,8,bx,by>>1,PMV[0][0][0],PMV[0][0][1]>>1,0);
+
+ /* predict bottom field from bottom field */
+ pred(oldref,1,cur,1,
+ lx<<1,16,8,bx,by>>1,PMV[0][0][0],PMV[0][0][1]>>1,0);
+
+ /* predict and add to top field from bottom field */
+ pred(oldref,1,cur,0,
+ lx<<1,16,8,bx,by>>1,DMV[0][0],DMV[0][1],1);
+
+ /* predict and add to bottom field from top field */
+ pred(oldref,0,cur,1,
+ lx<<1,16,8,bx,by>>1,DMV[1][0],DMV[1][1],1);
+ }
+ else
+ {
+ /* invalid motion_type in frame picture */
+ if (!quiet)
+ fprintf(stderr,"invalid motion_type\n");
+ }
+ }
+ else /* TOP_FIELD or BOTTOM_FIELD */
+ {
+ /* field picture */
+
+ currentfield = (pict_struct==BOTTOM_FIELD);
+
+ /* determine which frame to use for prediction */
+ if ((pict_type==P_TYPE) && secondfield
+ && (currentfield!=mv_field_sel[0][0]))
+ predframe = newref; /* same frame */
+ else
+ predframe = oldref; /* previous frame */
+
+ if ((motion_type==MC_FIELD) || !(mb_type & MB_FORWARD))
+ {
+ /* field-based prediction in field picture */
+ pred(predframe,mv_field_sel[0][0],cur,currentfield,
+ lx<<1,16,16,bx,by,PMV[0][0][0],PMV[0][0][1],0);
+ }
+ else if (motion_type==MC_16X8)
+ {
+ /* 16 x 8 motion compensation in field picture */
+
+ /* upper half */
+ pred(predframe,mv_field_sel[0][0],cur,currentfield,
+ lx<<1,16,8,bx,by,PMV[0][0][0],PMV[0][0][1],0);
+
+ /* determine which frame to use for lower half prediction */
+ if ((pict_type==P_TYPE) && secondfield
+ && (currentfield!=mv_field_sel[1][0]))
+ predframe = newref; /* same frame */
+ else
+ predframe = oldref; /* previous frame */
+
+ /* lower half */
+ pred(predframe,mv_field_sel[1][0],cur,currentfield,
+ lx<<1,16,8,bx,by+8,PMV[1][0][0],PMV[1][0][1],0);
+ }
+ else if (motion_type==MC_DMV)
+ {
+ /* dual prime prediction */
+
+ /* determine which frame to use for prediction */
+ if (secondfield)
+ predframe = newref; /* same frame */
+ else
+ predframe = oldref; /* previous frame */
+
+ /* calculate derived motion vectors */
+ calc_DMV(DMV,dmvector,PMV[0][0][0],PMV[0][0][1]);
+
+ /* predict from field of same parity */
+ pred(oldref,currentfield,cur,currentfield,
+ lx<<1,16,16,bx,by,PMV[0][0][0],PMV[0][0][1],0);
+
+ /* predict from field of opposite parity */
+ pred(predframe,!currentfield,cur,currentfield,
+ lx<<1,16,16,bx,by,DMV[0][0],DMV[0][1],1);
+ }
+ else
+ {
+ /* invalid motion_type in field picture */
+ if (!quiet)
+ fprintf(stderr,"invalid motion_type\n");
+ }
+ }
+ addflag = 1; /* next prediction (if any) will be averaged with this one */
+ }
+
+ if (mb_type & MB_BACKWARD)
+ {
+ /* backward prediction */
+
+ if (pict_struct==FRAME_PICTURE)
+ {
+ /* frame picture */
+
+ if (motion_type==MC_FRAME)
+ {
+ /* frame-based prediction in frame picture */
+ pred(newref,0,cur,0,
+ lx,16,16,bx,by,PMV[0][1][0],PMV[0][1][1],addflag);
+ }
+ else
+ {
+ /* field-based prediction in frame picture
+ *
+ * note scaling of the vertical coordinates (by, PMV[][1][1])
+ * from frame to field!
+ */
+
+ /* top field prediction */
+ pred(newref,mv_field_sel[0][1],cur,0,
+ lx<<1,16,8,bx,by>>1,PMV[0][1][0],PMV[0][1][1]>>1,addflag);
+
+ /* bottom field prediction */
+ pred(newref,mv_field_sel[1][1],cur,1,
+ lx<<1,16,8,bx,by>>1,PMV[1][1][0],PMV[1][1][1]>>1,addflag);
+ }
+ }
+ else /* TOP_FIELD or BOTTOM_FIELD */
+ {
+ /* field picture */
+
+ currentfield = (pict_struct==BOTTOM_FIELD);
+
+ if (motion_type==MC_FIELD)
+ {
+ /* field-based prediction in field picture */
+ pred(newref,mv_field_sel[0][1],cur,currentfield,
+ lx<<1,16,16,bx,by,PMV[0][1][0],PMV[0][1][1],addflag);
+ }
+ else if (motion_type==MC_16X8)
+ {
+ /* 16 x 8 motion compensation in field picture */
+
+ /* upper half */
+ pred(newref,mv_field_sel[0][1],cur,currentfield,
+ lx<<1,16,8,bx,by,PMV[0][1][0],PMV[0][1][1],addflag);
+
+ /* lower half */
+ pred(newref,mv_field_sel[1][1],cur,currentfield,
+ lx<<1,16,8,bx,by+8,PMV[1][1][0],PMV[1][1][1],addflag);
+ }
+ else
+ {
+ /* invalid motion_type in field picture */
+ if (!quiet)
+ fprintf(stderr,"invalid motion_type\n");
+ }
+ }
+ }
+}
+
+/* predict a rectangular block (all three components)
+ *
+ * src: source frame (Y,U,V)
+ * sfield: source field select (0: frame or top field, 1: bottom field)
+ * dst: destination frame (Y,U,V)
+ * dfield: destination field select (0: frame or top field, 1: bottom field)
+ *
+ * the following values are in luminance picture (frame or field) dimensions
+ * lx: distance of vertically adjacent pels (selects frame or field pred.)
+ * w,h: width and height of block (only 16x16 or 16x8 are used)
+ * x,y: coordinates of destination block
+ * dx,dy: half pel motion vector
+ * addflag: store or add (= average) prediction
+ */
+static void pred(src,sfield,dst,dfield,lx,w,h,x,y,dx,dy,addflag)
+unsigned char *src[];
+int sfield;
+unsigned char *dst[];
+int dfield;
+int lx;
+int w, h;
+int x, y;
+int dx, dy;
+int addflag;
+{
+ int cc;
+
+ for (cc=0; cc<3; cc++)
+ {
+ if (cc==1)
+ {
+ /* scale for color components */
+ if (chroma_format==CHROMA420)
+ {
+ /* vertical */
+ h >>= 1; y >>= 1; dy /= 2;
+ }
+ if (chroma_format!=CHROMA444)
+ {
+ /* horizontal */
+ w >>= 1; x >>= 1; dx /= 2;
+ lx >>= 1;
+ }
+ }
+ pred_comp(src[cc]+(sfield?lx>>1:0),dst[cc]+(dfield?lx>>1:0),
+ lx,w,h,x,y,dx,dy,addflag);
+ }
+}
+
+/* low level prediction routine
+ *
+ * src: prediction source
+ * dst: prediction destination
+ * lx: line width (for both src and dst)
+ * x,y: destination coordinates
+ * dx,dy: half pel motion vector
+ * w,h: size of prediction block
+ * addflag: store or add prediction
+ */
+
+static void pred_comp(src,dst,lx,w,h,x,y,dx,dy,addflag)
+unsigned char *src;
+unsigned char *dst;
+int lx;
+int w, h;
+int x, y;
+int dx, dy;
+int addflag;
+{
+ int xint, xh, yint, yh;
+ int i, j;
+ unsigned char *s, *d;
+
+ /* half pel scaling */
+ xint = dx>>1; /* integer part */
+ xh = dx & 1; /* half pel flag */
+ yint = dy>>1;
+ yh = dy & 1;
+
+ /* origins */
+ s = src + lx*(y+yint) + (x+xint); /* motion vector */
+ d = dst + lx*y + x;
+
+ if (!xh && !yh)
+ if (addflag)
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<w; i++)
+ d[i] = (unsigned int)(d[i]+s[i]+1)>>1;
+ s+= lx;
+ d+= lx;
+ }
+ else
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<w; i++)
+ d[i] = s[i];
+ s+= lx;
+ d+= lx;
+ }
+ else if (!xh && yh)
+ if (addflag)
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<w; i++)
+ d[i] = (d[i] + ((unsigned int)(s[i]+s[i+lx]+1)>>1)+1)>>1;
+ s+= lx;
+ d+= lx;
+ }
+ else
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<w; i++)
+ d[i] = (unsigned int)(s[i]+s[i+lx]+1)>>1;
+ s+= lx;
+ d+= lx;
+ }
+ else if (xh && !yh)
+ if (addflag)
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<w; i++)
+ d[i] = (d[i] + ((unsigned int)(s[i]+s[i+1]+1)>>1)+1)>>1;
+ s+= lx;
+ d+= lx;
+ }
+ else
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<w; i++)
+ d[i] = (unsigned int)(s[i]+s[i+1]+1)>>1;
+ s+= lx;
+ d+= lx;
+ }
+ else /* if (xh && yh) */
+ if (addflag)
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<w; i++)
+ d[i] = (d[i] + ((unsigned int)(s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2)>>2)+1)>>1;
+ s+= lx;
+ d+= lx;
+ }
+ else
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<w; i++)
+ d[i] = (unsigned int)(s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2)>>2;
+ s+= lx;
+ d+= lx;
+ }
+}
+
+
+/* calculate derived motion vectors (DMV) for dual prime prediction
+ * dmvector[2]: differential motion vectors (-1,0,+1)
+ * mvx,mvy: motion vector (for same parity)
+ *
+ * DMV[2][2]: derived motion vectors (for opposite parity)
+ *
+ * uses global variables pict_struct and topfirst
+ *
+ * Notes:
+ * - all vectors are in field coordinates (even for frame pictures)
+ */
+
+static void calc_DMV(DMV,dmvector,mvx,mvy)
+int DMV[][2];
+int *dmvector;
+int mvx, mvy;
+{
+ if (pict_struct==FRAME_PICTURE)
+ {
+ if (topfirst)
+ {
+ /* vector for prediction of top field from bottom field */
+ DMV[0][0] = ((mvx +(mvx>0))>>1) + dmvector[0];
+ DMV[0][1] = ((mvy +(mvy>0))>>1) + dmvector[1] - 1;
+
+ /* vector for prediction of bottom field from top field */
+ DMV[1][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0];
+ DMV[1][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] + 1;
+ }
+ else
+ {
+ /* vector for prediction of top field from bottom field */
+ DMV[0][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0];
+ DMV[0][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] - 1;
+
+ /* vector for prediction of bottom field from top field */
+ DMV[1][0] = ((mvx +(mvx>0))>>1) + dmvector[0];
+ DMV[1][1] = ((mvy +(mvy>0))>>1) + dmvector[1] + 1;
+ }
+ }
+ else
+ {
+ /* vector for prediction from field of opposite 'parity' */
+ DMV[0][0] = ((mvx+(mvx>0))>>1) + dmvector[0];
+ DMV[0][1] = ((mvy+(mvy>0))>>1) + dmvector[1];
+
+ /* correct for vertical field shift */
+ if (pict_struct==TOP_FIELD)
+ DMV[0][1]--;
+ else
+ DMV[0][1]++;
+ }
+}
+
+static void clearblock(cur,i0,j0)
+unsigned char *cur[];
+int i0, j0;
+{
+ int i, j, w, h;
+ unsigned char *p;
+
+ p = cur[0] + ((pict_struct==BOTTOM_FIELD) ? width : 0) + i0 + width2*j0;
+
+ for (j=0; j<16; j++)
+ {
+ for (i=0; i<16; i++)
+ p[i] = 128;
+ p+= width2;
+ }
+
+ w = h = 16;
+
+ if (chroma_format!=CHROMA444)
+ {
+ i0>>=1; w>>=1;
+ }
+
+ if (chroma_format==CHROMA420)
+ {
+ j0>>=1; h>>=1;
+ }
+
+ p = cur[1] + ((pict_struct==BOTTOM_FIELD) ? chrom_width : 0) + i0
+ + chrom_width2*j0;
+
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<w; i++)
+ p[i] = 128;
+ p+= chrom_width2;
+ }
+
+ p = cur[2] + ((pict_struct==BOTTOM_FIELD) ? chrom_width : 0) + i0
+ + chrom_width2*j0;
+
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<w; i++)
+ p[i] = 128;
+ p+= chrom_width2;
+ }
+}
--- /dev/null
+/* putbits.c, bit-level output */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include <stdio.h>
+#include "config.h"
+
+extern FILE *outfile; /* the only global var we need here */
+
+/* private data */
+static unsigned char outbfr;
+static int outcnt;
+static int bytecnt;
+
+/* initialize buffer, call once before first putbits or alignbits */
+void initbits()
+{
+ outcnt = 8;
+ bytecnt = 0;
+}
+
+/* write rightmost n (0<=n<=32) bits of val to outfile */
+void putbits(val,n)
+int val;
+int n;
+{
+ int i;
+ unsigned int mask;
+
+ mask = 1 << (n-1); /* selects first (leftmost) bit */
+
+ for (i=0; i<n; i++)
+ {
+ outbfr <<= 1;
+
+ if (val & mask)
+ outbfr|= 1;
+
+ mask >>= 1; /* select next bit */
+ outcnt--;
+
+ if (outcnt==0) /* 8 bit buffer full */
+ {
+ putc(outbfr,outfile);
+ outcnt = 8;
+ bytecnt++;
+ }
+ }
+}
+
+/* zero bit stuffing to next byte boundary (5.2.3, 6.2.1) */
+void alignbits()
+{
+ if (outcnt!=8)
+ putbits(0,outcnt);
+}
+
+/* return total number of generated bits */
+int bitcount()
+{
+ return 8*bytecnt + (8-outcnt);
+}
--- /dev/null
+/* puthdr.c, generation of headers */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include "config.h"
+#include "global.h"
+
+/* private prototypes */
+static int frametotc _ANSI_ARGS_((int frame));
+
+/* generate sequence header (6.2.2.1, 6.3.3)
+ *
+ * matrix download not implemented
+ */
+void putseqhdr()
+{
+ int i;
+
+ alignbits();
+ putbits(SEQ_START_CODE,32); /* sequence_header_code */
+ putbits(horizontal_size,12); /* horizontal_size_value */
+ putbits(vertical_size,12); /* vertical_size_value */
+ putbits(aspectratio,4); /* aspect_ratio_information */
+ putbits(frame_rate_code,4); /* frame_rate_code */
+ putbits((int)ceil(bit_rate/400.0),18); /* bit_rate_value */
+ putbits(1,1); /* marker_bit */
+ putbits(vbv_buffer_size,10); /* vbv_buffer_size_value */
+ putbits(constrparms,1); /* constrained_parameters_flag */
+
+ putbits(load_iquant,1); /* load_intra_quantizer_matrix */
+ if (load_iquant)
+ for (i=0; i<64; i++) /* matrices are always downloaded in zig-zag order */
+ putbits(intra_q[zig_zag_scan[i]],8); /* intra_quantizer_matrix */
+
+ putbits(load_niquant,1); /* load_non_intra_quantizer_matrix */
+ if (load_niquant)
+ for (i=0; i<64; i++)
+ putbits(inter_q[zig_zag_scan[i]],8); /* non_intra_quantizer_matrix */
+}
+
+/* generate sequence extension (6.2.2.3, 6.3.5) header (MPEG-2 only) */
+void putseqext()
+{
+ alignbits();
+ putbits(EXT_START_CODE,32); /* extension_start_code */
+ putbits(SEQ_ID,4); /* extension_start_code_identifier */
+ putbits((profile<<4)|level,8); /* profile_and_level_indication */
+ putbits(prog_seq,1); /* progressive sequence */
+ putbits(chroma_format,2); /* chroma_format */
+ putbits(horizontal_size>>12,2); /* horizontal_size_extension */
+ putbits(vertical_size>>12,2); /* vertical_size_extension */
+ putbits(((int)ceil(bit_rate/400.0))>>18,12); /* bit_rate_extension */
+ putbits(1,1); /* marker_bit */
+ putbits(vbv_buffer_size>>10,8); /* vbv_buffer_size_extension */
+ putbits(0,1); /* low_delay -- currently not implemented */
+ putbits(0,2); /* frame_rate_extension_n */
+ putbits(0,5); /* frame_rate_extension_d */
+}
+
+/* generate sequence display extension (6.2.2.4, 6.3.6)
+ *
+ * content not yet user setable
+ */
+void putseqdispext()
+{
+ alignbits();
+ putbits(EXT_START_CODE,32); /* extension_start_code */
+ putbits(DISP_ID,4); /* extension_start_code_identifier */
+ putbits(video_format,3); /* video_format */
+ putbits(1,1); /* colour_description */
+ putbits(color_primaries,8); /* colour_primaries */
+ putbits(transfer_characteristics,8); /* transfer_characteristics */
+ putbits(matrix_coefficients,8); /* matrix_coefficients */
+ putbits(display_horizontal_size,14); /* display_horizontal_size */
+ putbits(1,1); /* marker_bit */
+ putbits(display_vertical_size,14); /* display_vertical_size */
+}
+
+/* output a zero terminated string as user data (6.2.2.2.2, 6.3.4.1)
+ *
+ * string must not emulate start codes
+ */
+void putuserdata(userdata)
+char *userdata;
+{
+ alignbits();
+ putbits(USER_START_CODE,32); /* user_data_start_code */
+ while (*userdata)
+ putbits(*userdata++,8);
+}
+
+/* generate group of pictures header (6.2.2.6, 6.3.9)
+ *
+ * uses tc0 (timecode of first frame) and frame0 (number of first frame)
+ */
+void putgophdr(frame,closed_gop)
+int frame,closed_gop;
+{
+ int tc;
+
+ alignbits();
+ putbits(GOP_START_CODE,32); /* group_start_code */
+ tc = frametotc(tc0+frame);
+ putbits(tc,25); /* time_code */
+ putbits(closed_gop,1); /* closed_gop */
+ putbits(0,1); /* broken_link */
+}
+
+/* convert frame number to time_code
+ *
+ * drop_frame not implemented
+ */
+static int frametotc(frame)
+int frame;
+{
+ int fps, pict, sec, minute, hour, tc;
+
+ fps = (int)(frame_rate+0.5);
+ pict = frame%fps;
+ frame = (frame-pict)/fps;
+ sec = frame%60;
+ frame = (frame-sec)/60;
+ minute = frame%60;
+ frame = (frame-minute)/60;
+ hour = frame%24;
+ tc = (hour<<19) | (minute<<13) | (1<<12) | (sec<<6) | pict;
+
+ return tc;
+}
+
+/* generate picture header (6.2.3, 6.3.10) */
+void putpicthdr()
+{
+ alignbits();
+ putbits(PICTURE_START_CODE,32); /* picture_start_code */
+ calc_vbv_delay();
+ putbits(temp_ref,10); /* temporal_reference */
+ putbits(pict_type,3); /* picture_coding_type */
+ putbits(vbv_delay,16); /* vbv_delay */
+
+ if (pict_type==P_TYPE || pict_type==B_TYPE)
+ {
+ putbits(0,1); /* full_pel_forward_vector */
+ if (mpeg1)
+ putbits(forw_hor_f_code,3);
+ else
+ putbits(7,3); /* forward_f_code */
+ }
+
+ if (pict_type==B_TYPE)
+ {
+ putbits(0,1); /* full_pel_backward_vector */
+ if (mpeg1)
+ putbits(back_hor_f_code,3);
+ else
+ putbits(7,3); /* backward_f_code */
+ }
+
+ putbits(0,1); /* extra_bit_picture */
+}
+
+/* generate picture coding extension (6.2.3.1, 6.3.11)
+ *
+ * composite display information (v_axis etc.) not implemented
+ */
+void putpictcodext()
+{
+ alignbits();
+ putbits(EXT_START_CODE,32); /* extension_start_code */
+ putbits(CODING_ID,4); /* extension_start_code_identifier */
+ putbits(forw_hor_f_code,4); /* forward_horizontal_f_code */
+ putbits(forw_vert_f_code,4); /* forward_vertical_f_code */
+ putbits(back_hor_f_code,4); /* backward_horizontal_f_code */
+ putbits(back_vert_f_code,4); /* backward_vertical_f_code */
+ putbits(dc_prec,2); /* intra_dc_precision */
+ putbits(pict_struct,2); /* picture_structure */
+ putbits((pict_struct==FRAME_PICTURE)?topfirst:0,1); /* top_field_first */
+ putbits(frame_pred_dct,1); /* frame_pred_frame_dct */
+ putbits(0,1); /* concealment_motion_vectors -- currently not implemented */
+ putbits(q_scale_type,1); /* q_scale_type */
+ putbits(intravlc,1); /* intra_vlc_format */
+ putbits(altscan,1); /* alternate_scan */
+ putbits(repeatfirst,1); /* repeat_first_field */
+ putbits(prog_frame,1); /* chroma_420_type */
+ putbits(prog_frame,1); /* progressive_frame */
+ putbits(0,1); /* composite_display_flag */
+}
+
+/* generate sequence_end_code (6.2.2) */
+void putseqend()
+{
+ alignbits();
+ putbits(SEQ_END_CODE,32);
+}
--- /dev/null
+/* putmpg.c, block and motion vector encoding routines */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include <stdio.h>
+#include "config.h"
+#include "global.h"
+
+/* generate variable length codes for an intra-coded block (6.2.6, 6.3.17) */
+void putintrablk(blk,cc)
+short *blk;
+int cc;
+{
+ int n, dct_diff, run, signed_level;
+
+ /* DC coefficient (7.2.1) */
+ dct_diff = blk[0] - dc_dct_pred[cc]; /* difference to previous block */
+ dc_dct_pred[cc] = blk[0];
+
+ if (cc==0)
+ putDClum(dct_diff);
+ else
+ putDCchrom(dct_diff);
+
+ /* AC coefficients (7.2.2) */
+ run = 0;
+ for (n=1; n<64; n++)
+ {
+ /* use appropriate entropy scanning pattern */
+ signed_level = blk[(altscan ? alternate_scan : zig_zag_scan)[n]];
+ if (signed_level!=0)
+ {
+ putAC(run,signed_level,intravlc);
+ run = 0;
+ }
+ else
+ run++; /* count zero coefficients */
+ }
+
+ /* End of Block -- normative block punctuation */
+ if (intravlc)
+ putbits(6,4); /* 0110 (Table B-15) */
+ else
+ putbits(2,2); /* 10 (Table B-14) */
+}
+
+/* generate variable length codes for a non-intra-coded block (6.2.6, 6.3.17) */
+void putnonintrablk(blk)
+short *blk;
+{
+ int n, run, signed_level, first;
+
+ run = 0;
+ first = 1;
+
+ for (n=0; n<64; n++)
+ {
+ /* use appropriate entropy scanning pattern */
+ signed_level = blk[(altscan ? alternate_scan : zig_zag_scan)[n]];
+
+ if (signed_level!=0)
+ {
+ if (first)
+ {
+ /* first coefficient in non-intra block */
+ putACfirst(run,signed_level);
+ first = 0;
+ }
+ else
+ putAC(run,signed_level,0);
+
+ run = 0;
+ }
+ else
+ run++; /* count zero coefficients */
+ }
+
+ /* End of Block -- normative block punctuation */
+ putbits(2,2);
+}
+
+/* generate variable length code for a motion vector component (7.6.3.1) */
+void putmv(dmv,f_code)
+int dmv,f_code;
+{
+ int r_size, f, vmin, vmax, dv, temp, motion_code, motion_residual;
+
+ r_size = f_code - 1; /* number of fixed length code ('residual') bits */
+ f = 1<<r_size;
+ vmin = -16*f; /* lower range limit */
+ vmax = 16*f - 1; /* upper range limit */
+ dv = 32*f;
+
+ /* fold vector difference into [vmin...vmax] */
+ if (dmv>vmax)
+ dmv-= dv;
+ else if (dmv<vmin)
+ dmv+= dv;
+
+ /* check value */
+ if (dmv<vmin || dmv>vmax)
+ if (!quiet)
+ fprintf(stderr,"invalid motion vector\n");
+
+ /* split dmv into motion_code and motion_residual */
+ temp = ((dmv<0) ? -dmv : dmv) + f - 1;
+ motion_code = temp>>r_size;
+ if (dmv<0)
+ motion_code = -motion_code;
+ motion_residual = temp & (f-1);
+
+ putmotioncode(motion_code); /* variable length code */
+
+ if (r_size!=0 && motion_code!=0)
+ putbits(motion_residual,r_size); /* fixed length code */
+}
--- /dev/null
+/* putpic.c, block and motion vector encoding routines */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include <stdio.h>
+#include "config.h"
+#include "global.h"
+
+/* private prototypes */
+static void putmvs _ANSI_ARGS_((int MV[2][2][2], int PMV[2][2][2],
+ int mv_field_sel[2][2], int dmvector[2], int s, int motion_type,
+ int hor_f_code, int vert_f_code));
+
+/* quantization / variable length encoding of a complete picture */
+void putpict(frame)
+unsigned char *frame;
+{
+ int i, j, k, comp, cc;
+ int mb_type;
+ int PMV[2][2][2];
+ int prev_mquant;
+ int cbp, MBAinc;
+
+ rc_init_pict(frame); /* set up rate control */
+
+ /* picture header and picture coding extension */
+ putpicthdr();
+
+ if (!mpeg1)
+ putpictcodext();
+
+ prev_mquant = rc_start_mb(); /* initialize quantization parameter */
+
+ k = 0;
+
+ for (j=0; j<mb_height2; j++)
+ {
+ /* macroblock row loop */
+
+ for (i=0; i<mb_width; i++)
+ {
+ /* macroblock loop */
+ if (i==0)
+ {
+ /* slice header (6.2.4) */
+ alignbits();
+
+ if (mpeg1 || vertical_size<=2800)
+ putbits(SLICE_MIN_START+j,32); /* slice_start_code */
+ else
+ {
+ putbits(SLICE_MIN_START+(j&127),32); /* slice_start_code */
+ putbits(j>>7,3); /* slice_vertical_position_extension */
+ }
+
+ /* quantiser_scale_code */
+ putbits(q_scale_type ? map_non_linear_mquant[prev_mquant]
+ : prev_mquant >> 1, 5);
+
+ putbits(0,1); /* extra_bit_slice */
+
+ /* reset predictors */
+
+ for (cc=0; cc<3; cc++)
+ dc_dct_pred[cc] = 0;
+
+ PMV[0][0][0]=PMV[0][0][1]=PMV[1][0][0]=PMV[1][0][1]=0;
+ PMV[0][1][0]=PMV[0][1][1]=PMV[1][1][0]=PMV[1][1][1]=0;
+
+ MBAinc = i + 1; /* first MBAinc denotes absolute position */
+ }
+
+ mb_type = mbinfo[k].mb_type;
+
+ /* determine mquant (rate control) */
+ mbinfo[k].mquant = rc_calc_mquant(k);
+
+ /* quantize macroblock */
+ if (mb_type & MB_INTRA)
+ {
+ for (comp=0; comp<block_count; comp++)
+ quant_intra(blocks[k*block_count+comp],blocks[k*block_count+comp],
+ dc_prec,intra_q,mbinfo[k].mquant);
+ mbinfo[k].cbp = cbp = (1<<block_count) - 1;
+ }
+ else
+ {
+ cbp = 0;
+ for (comp=0;comp<block_count;comp++)
+ cbp = (cbp<<1) | quant_non_intra(blocks[k*block_count+comp],
+ blocks[k*block_count+comp],
+ inter_q,mbinfo[k].mquant);
+
+ mbinfo[k].cbp = cbp;
+
+ if (cbp)
+ mb_type|= MB_PATTERN;
+ }
+
+ /* output mquant if it has changed */
+ if (cbp && prev_mquant!=mbinfo[k].mquant)
+ mb_type|= MB_QUANT;
+
+ /* check if macroblock can be skipped */
+ if (i!=0 && i!=mb_width-1 && !cbp)
+ {
+ /* no DCT coefficients and neither first nor last macroblock of slice */
+
+ if (pict_type==P_TYPE && !(mb_type&MB_FORWARD))
+ {
+ /* P picture, no motion vectors -> skip */
+
+ /* reset predictors */
+
+ for (cc=0; cc<3; cc++)
+ dc_dct_pred[cc] = 0;
+
+ PMV[0][0][0]=PMV[0][0][1]=PMV[1][0][0]=PMV[1][0][1]=0;
+ PMV[0][1][0]=PMV[0][1][1]=PMV[1][1][0]=PMV[1][1][1]=0;
+
+ mbinfo[k].mb_type = mb_type;
+ mbinfo[k].skipped = 1;
+ MBAinc++;
+ k++;
+ continue;
+ }
+
+ if (pict_type==B_TYPE && pict_struct==FRAME_PICTURE
+ && mbinfo[k].motion_type==MC_FRAME
+ && ((mbinfo[k-1].mb_type^mb_type)&(MB_FORWARD|MB_BACKWARD))==0
+ && (!(mb_type&MB_FORWARD) ||
+ (PMV[0][0][0]==mbinfo[k].MV[0][0][0] &&
+ PMV[0][0][1]==mbinfo[k].MV[0][0][1]))
+ && (!(mb_type&MB_BACKWARD) ||
+ (PMV[0][1][0]==mbinfo[k].MV[0][1][0] &&
+ PMV[0][1][1]==mbinfo[k].MV[0][1][1])))
+ {
+ /* conditions for skipping in B frame pictures:
+ * - must be frame predicted
+ * - must be the same prediction type (forward/backward/interp.)
+ * as previous macroblock
+ * - relevant vectors (forward/backward/both) have to be the same
+ * as in previous macroblock
+ */
+
+ mbinfo[k].mb_type = mb_type;
+ mbinfo[k].skipped = 1;
+ MBAinc++;
+ k++;
+ continue;
+ }
+
+ if (pict_type==B_TYPE && pict_struct!=FRAME_PICTURE
+ && mbinfo[k].motion_type==MC_FIELD
+ && ((mbinfo[k-1].mb_type^mb_type)&(MB_FORWARD|MB_BACKWARD))==0
+ && (!(mb_type&MB_FORWARD) ||
+ (PMV[0][0][0]==mbinfo[k].MV[0][0][0] &&
+ PMV[0][0][1]==mbinfo[k].MV[0][0][1] &&
+ mbinfo[k].mv_field_sel[0][0]==(pict_struct==BOTTOM_FIELD)))
+ && (!(mb_type&MB_BACKWARD) ||
+ (PMV[0][1][0]==mbinfo[k].MV[0][1][0] &&
+ PMV[0][1][1]==mbinfo[k].MV[0][1][1] &&
+ mbinfo[k].mv_field_sel[0][1]==(pict_struct==BOTTOM_FIELD))))
+ {
+ /* conditions for skipping in B field pictures:
+ * - must be field predicted
+ * - must be the same prediction type (forward/backward/interp.)
+ * as previous macroblock
+ * - relevant vectors (forward/backward/both) have to be the same
+ * as in previous macroblock
+ * - relevant motion_vertical_field_selects have to be of same
+ * parity as current field
+ */
+
+ mbinfo[k].mb_type = mb_type;
+ mbinfo[k].skipped = 1;
+ MBAinc++;
+ k++;
+ continue;
+ }
+ }
+
+ /* macroblock cannot be skipped */
+ mbinfo[k].skipped = 0;
+
+ /* there's no VLC for 'No MC, Not Coded':
+ * we have to transmit (0,0) motion vectors
+ */
+ if (pict_type==P_TYPE && !cbp && !(mb_type&MB_FORWARD))
+ mb_type|= MB_FORWARD;
+
+ putaddrinc(MBAinc); /* macroblock_address_increment */
+ MBAinc = 1;
+
+ putmbtype(pict_type,mb_type); /* macroblock type */
+
+ if (mb_type & (MB_FORWARD|MB_BACKWARD) && !frame_pred_dct)
+ putbits(mbinfo[k].motion_type,2);
+
+ if (pict_struct==FRAME_PICTURE && cbp && !frame_pred_dct)
+ putbits(mbinfo[k].dct_type,1);
+
+ if (mb_type & MB_QUANT)
+ {
+ putbits(q_scale_type ? map_non_linear_mquant[mbinfo[k].mquant]
+ : mbinfo[k].mquant>>1,5);
+ prev_mquant = mbinfo[k].mquant;
+ }
+
+ if (mb_type & MB_FORWARD)
+ {
+ /* forward motion vectors, update predictors */
+ putmvs(mbinfo[k].MV,PMV,mbinfo[k].mv_field_sel,mbinfo[k].dmvector,0,
+ mbinfo[k].motion_type,forw_hor_f_code,forw_vert_f_code);
+ }
+
+ if (mb_type & MB_BACKWARD)
+ {
+ /* backward motion vectors, update predictors */
+ putmvs(mbinfo[k].MV,PMV,mbinfo[k].mv_field_sel,mbinfo[k].dmvector,1,
+ mbinfo[k].motion_type,back_hor_f_code,back_vert_f_code);
+ }
+
+ if (mb_type & MB_PATTERN)
+ {
+ putcbp((cbp >> (block_count-6)) & 63);
+ if (chroma_format!=CHROMA420)
+ putbits(cbp,block_count-6);
+ }
+
+ for (comp=0; comp<block_count; comp++)
+ {
+ /* block loop */
+ if (cbp & (1<<(block_count-1-comp)))
+ {
+ if (mb_type & MB_INTRA)
+ {
+ cc = (comp<4) ? 0 : (comp&1)+1;
+ putintrablk(blocks[k*block_count+comp],cc);
+ }
+ else
+ putnonintrablk(blocks[k*block_count+comp]);
+ }
+ }
+
+ /* reset predictors */
+ if (!(mb_type & MB_INTRA))
+ for (cc=0; cc<3; cc++)
+ dc_dct_pred[cc] = 0;
+
+ if (mb_type & MB_INTRA || (pict_type==P_TYPE && !(mb_type & MB_FORWARD)))
+ {
+ PMV[0][0][0]=PMV[0][0][1]=PMV[1][0][0]=PMV[1][0][1]=0;
+ PMV[0][1][0]=PMV[0][1][1]=PMV[1][1][0]=PMV[1][1][1]=0;
+ }
+
+ mbinfo[k].mb_type = mb_type;
+ k++;
+ }
+ }
+
+ rc_update_pict();
+ vbv_end_of_picture();
+}
+
+
+/* output motion vectors (6.2.5.2, 6.3.16.2)
+ *
+ * this routine also updates the predictions for motion vectors (PMV)
+ */
+
+static void putmvs(MV,PMV,mv_field_sel,dmvector,s,motion_type,
+ hor_f_code,vert_f_code)
+int MV[2][2][2],PMV[2][2][2];
+int mv_field_sel[2][2];
+int dmvector[2];
+int s,motion_type,hor_f_code,vert_f_code;
+{
+ if (pict_struct==FRAME_PICTURE)
+ {
+ if (motion_type==MC_FRAME)
+ {
+ /* frame prediction */
+ putmv(MV[0][s][0]-PMV[0][s][0],hor_f_code);
+ putmv(MV[0][s][1]-PMV[0][s][1],vert_f_code);
+ PMV[0][s][0]=PMV[1][s][0]=MV[0][s][0];
+ PMV[0][s][1]=PMV[1][s][1]=MV[0][s][1];
+ }
+ else if (motion_type==MC_FIELD)
+ {
+ /* field prediction */
+ putbits(mv_field_sel[0][s],1);
+ putmv(MV[0][s][0]-PMV[0][s][0],hor_f_code);
+ putmv((MV[0][s][1]>>1)-(PMV[0][s][1]>>1),vert_f_code);
+ putbits(mv_field_sel[1][s],1);
+ putmv(MV[1][s][0]-PMV[1][s][0],hor_f_code);
+ putmv((MV[1][s][1]>>1)-(PMV[1][s][1]>>1),vert_f_code);
+ PMV[0][s][0]=MV[0][s][0];
+ PMV[0][s][1]=MV[0][s][1];
+ PMV[1][s][0]=MV[1][s][0];
+ PMV[1][s][1]=MV[1][s][1];
+ }
+ else
+ {
+ /* dual prime prediction */
+ putmv(MV[0][s][0]-PMV[0][s][0],hor_f_code);
+ putdmv(dmvector[0]);
+ putmv((MV[0][s][1]>>1)-(PMV[0][s][1]>>1),vert_f_code);
+ putdmv(dmvector[1]);
+ PMV[0][s][0]=PMV[1][s][0]=MV[0][s][0];
+ PMV[0][s][1]=PMV[1][s][1]=MV[0][s][1];
+ }
+ }
+ else
+ {
+ /* field picture */
+ if (motion_type==MC_FIELD)
+ {
+ /* field prediction */
+ putbits(mv_field_sel[0][s],1);
+ putmv(MV[0][s][0]-PMV[0][s][0],hor_f_code);
+ putmv(MV[0][s][1]-PMV[0][s][1],vert_f_code);
+ PMV[0][s][0]=PMV[1][s][0]=MV[0][s][0];
+ PMV[0][s][1]=PMV[1][s][1]=MV[0][s][1];
+ }
+ else if (motion_type==MC_16X8)
+ {
+ /* 16x8 prediction */
+ putbits(mv_field_sel[0][s],1);
+ putmv(MV[0][s][0]-PMV[0][s][0],hor_f_code);
+ putmv(MV[0][s][1]-PMV[0][s][1],vert_f_code);
+ putbits(mv_field_sel[1][s],1);
+ putmv(MV[1][s][0]-PMV[1][s][0],hor_f_code);
+ putmv(MV[1][s][1]-PMV[1][s][1],vert_f_code);
+ PMV[0][s][0]=MV[0][s][0];
+ PMV[0][s][1]=MV[0][s][1];
+ PMV[1][s][0]=MV[1][s][0];
+ PMV[1][s][1]=MV[1][s][1];
+ }
+ else
+ {
+ /* dual prime prediction */
+ putmv(MV[0][s][0]-PMV[0][s][0],hor_f_code);
+ putdmv(dmvector[0]);
+ putmv(MV[0][s][1]-PMV[0][s][1],vert_f_code);
+ putdmv(dmvector[1]);
+ PMV[0][s][0]=PMV[1][s][0]=MV[0][s][0];
+ PMV[0][s][1]=PMV[1][s][1]=MV[0][s][1];
+ }
+ }
+}
--- /dev/null
+/* putseq.c, sequence level routines */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "config.h"
+#include "global.h"
+
+void putseq()
+{
+ /* this routine assumes (N % M) == 0 */
+ int i, j, k, f, f0, n, np, nb, sxf, syf, sxb, syb;
+ int ipflag;
+ FILE *fd;
+ char name[256];
+ unsigned char *neworg[3], *newref[3];
+ static char ipb[5] = {' ','I','P','B','D'};
+
+ rc_init_seq(); /* initialize rate control */
+
+ /* sequence header, sequence extension and sequence display extension */
+ putseqhdr();
+ if (!mpeg1)
+ {
+ putseqext();
+ putseqdispext();
+ }
+
+ /* optionally output some text data (description, copyright or whatever) */
+ if (strlen(id_string) > 1)
+ putuserdata(id_string);
+
+ /* loop through all frames in encoding/decoding order */
+ for (i=0; i<nframes; i++)
+ {
+ if (!quiet)
+ {
+ fprintf(stderr,"Encoding frame %d ",i);
+ fflush(stderr);
+ }
+
+ /* f0: lowest frame number in current GOP
+ *
+ * first GOP contains N-(M-1) frames,
+ * all other GOPs contain N frames
+ */
+ f0 = N*((i+(M-1))/N) - (M-1);
+
+ if (f0<0)
+ f0=0;
+
+ if (i==0 || (i-1)%M==0)
+ {
+ /* I or P frame */
+ for (j=0; j<3; j++)
+ {
+ /* shuffle reference frames */
+ neworg[j] = oldorgframe[j];
+ newref[j] = oldrefframe[j];
+ oldorgframe[j] = neworgframe[j];
+ oldrefframe[j] = newrefframe[j];
+ neworgframe[j] = neworg[j];
+ newrefframe[j] = newref[j];
+ }
+
+ /* f: frame number in display order */
+ f = (i==0) ? 0 : i+M-1;
+ if (f>=nframes)
+ f = nframes - 1;
+
+ if (i==f0) /* first displayed frame in GOP is I */
+ {
+ /* I frame */
+ pict_type = I_TYPE;
+ forw_hor_f_code = forw_vert_f_code = 15;
+ back_hor_f_code = back_vert_f_code = 15;
+
+ /* n: number of frames in current GOP
+ *
+ * first GOP contains (M-1) less (B) frames
+ */
+ n = (i==0) ? N-(M-1) : N;
+
+ /* last GOP may contain less frames */
+ if (n > nframes-f0)
+ n = nframes-f0;
+
+ /* number of P frames */
+ if (i==0)
+ np = (n + 2*(M-1))/M - 1; /* first GOP */
+ else
+ np = (n + (M-1))/M - 1;
+
+ /* number of B frames */
+ nb = n - np - 1;
+
+ rc_init_GOP(np,nb);
+
+ putgophdr(f0,i==0); /* set closed_GOP in first GOP only */
+ }
+ else
+ {
+ /* P frame */
+ pict_type = P_TYPE;
+ forw_hor_f_code = motion_data[0].forw_hor_f_code;
+ forw_vert_f_code = motion_data[0].forw_vert_f_code;
+ back_hor_f_code = back_vert_f_code = 15;
+ sxf = motion_data[0].sxf;
+ syf = motion_data[0].syf;
+ }
+ }
+ else
+ {
+ /* B frame */
+ for (j=0; j<3; j++)
+ {
+ neworg[j] = auxorgframe[j];
+ newref[j] = auxframe[j];
+ }
+
+ /* f: frame number in display order */
+ f = i - 1;
+ pict_type = B_TYPE;
+ n = (i-2)%M + 1; /* first B: n=1, second B: n=2, ... */
+ forw_hor_f_code = motion_data[n].forw_hor_f_code;
+ forw_vert_f_code = motion_data[n].forw_vert_f_code;
+ back_hor_f_code = motion_data[n].back_hor_f_code;
+ back_vert_f_code = motion_data[n].back_vert_f_code;
+ sxf = motion_data[n].sxf;
+ syf = motion_data[n].syf;
+ sxb = motion_data[n].sxb;
+ syb = motion_data[n].syb;
+ }
+
+ temp_ref = f - f0;
+ frame_pred_dct = frame_pred_dct_tab[pict_type-1];
+ q_scale_type = qscale_tab[pict_type-1];
+ intravlc = intravlc_tab[pict_type-1];
+ altscan = altscan_tab[pict_type-1];
+
+ fprintf(statfile,"\nFrame %d (#%d in display order):\n",i,f);
+ fprintf(statfile," picture_type=%c\n",ipb[pict_type]);
+ fprintf(statfile," temporal_reference=%d\n",temp_ref);
+ fprintf(statfile," frame_pred_frame_dct=%d\n",frame_pred_dct);
+ fprintf(statfile," q_scale_type=%d\n",q_scale_type);
+ fprintf(statfile," intra_vlc_format=%d\n",intravlc);
+ fprintf(statfile," alternate_scan=%d\n",altscan);
+
+ if (pict_type!=I_TYPE)
+ {
+ fprintf(statfile," forward search window: %d...%d / %d...%d\n",
+ -sxf,sxf,-syf,syf);
+ fprintf(statfile," forward vector range: %d...%d.5 / %d...%d.5\n",
+ -(4<<forw_hor_f_code),(4<<forw_hor_f_code)-1,
+ -(4<<forw_vert_f_code),(4<<forw_vert_f_code)-1);
+ }
+
+ if (pict_type==B_TYPE)
+ {
+ fprintf(statfile," backward search window: %d...%d / %d...%d\n",
+ -sxb,sxb,-syb,syb);
+ fprintf(statfile," backward vector range: %d...%d.5 / %d...%d.5\n",
+ -(4<<back_hor_f_code),(4<<back_hor_f_code)-1,
+ -(4<<back_vert_f_code),(4<<back_vert_f_code)-1);
+ }
+
+ sprintf(name,tplorg,f+frame0);
+ readframe(name,neworg);
+
+ if (fieldpic)
+ {
+ if (!quiet)
+ {
+ fprintf(stderr,"\nfirst field (%s) ",topfirst ? "top" : "bot");
+ fflush(stderr);
+ }
+
+ pict_struct = topfirst ? TOP_FIELD : BOTTOM_FIELD;
+
+ motion_estimation(oldorgframe[0],neworgframe[0],
+ oldrefframe[0],newrefframe[0],
+ neworg[0],newref[0],
+ sxf,syf,sxb,syb,mbinfo,0,0);
+
+ predict(oldrefframe,newrefframe,predframe,0,mbinfo);
+ dct_type_estimation(predframe[0],neworg[0],mbinfo);
+ transform(predframe,neworg,mbinfo,blocks);
+
+ putpict(neworg[0]);
+
+ for (k=0; k<mb_height2*mb_width; k++)
+ {
+ if (mbinfo[k].mb_type & MB_INTRA)
+ for (j=0; j<block_count; j++)
+ iquant_intra(blocks[k*block_count+j],blocks[k*block_count+j],
+ dc_prec,intra_q,mbinfo[k].mquant);
+ else
+ for (j=0;j<block_count;j++)
+ iquant_non_intra(blocks[k*block_count+j],blocks[k*block_count+j],
+ inter_q,mbinfo[k].mquant);
+ }
+
+ itransform(predframe,newref,mbinfo,blocks);
+ calcSNR(neworg,newref);
+ stats();
+
+ if (!quiet)
+ {
+ fprintf(stderr,"second field (%s) ",topfirst ? "bot" : "top");
+ fflush(stderr);
+ }
+
+ pict_struct = topfirst ? BOTTOM_FIELD : TOP_FIELD;
+
+ ipflag = (pict_type==I_TYPE);
+ if (ipflag)
+ {
+ /* first field = I, second field = P */
+ pict_type = P_TYPE;
+ forw_hor_f_code = motion_data[0].forw_hor_f_code;
+ forw_vert_f_code = motion_data[0].forw_vert_f_code;
+ back_hor_f_code = back_vert_f_code = 15;
+ sxf = motion_data[0].sxf;
+ syf = motion_data[0].syf;
+ }
+
+ motion_estimation(oldorgframe[0],neworgframe[0],
+ oldrefframe[0],newrefframe[0],
+ neworg[0],newref[0],
+ sxf,syf,sxb,syb,mbinfo,1,ipflag);
+
+ predict(oldrefframe,newrefframe,predframe,1,mbinfo);
+ dct_type_estimation(predframe[0],neworg[0],mbinfo);
+ transform(predframe,neworg,mbinfo,blocks);
+
+ putpict(neworg[0]);
+
+ for (k=0; k<mb_height2*mb_width; k++)
+ {
+ if (mbinfo[k].mb_type & MB_INTRA)
+ for (j=0; j<block_count; j++)
+ iquant_intra(blocks[k*block_count+j],blocks[k*block_count+j],
+ dc_prec,intra_q,mbinfo[k].mquant);
+ else
+ for (j=0;j<block_count;j++)
+ iquant_non_intra(blocks[k*block_count+j],blocks[k*block_count+j],
+ inter_q,mbinfo[k].mquant);
+ }
+
+ itransform(predframe,newref,mbinfo,blocks);
+ calcSNR(neworg,newref);
+ stats();
+ }
+ else
+ {
+ pict_struct = FRAME_PICTURE;
+
+ /* do motion_estimation
+ *
+ * uses source frames (...orgframe) for full pel search
+ * and reconstructed frames (...refframe) for half pel search
+ */
+
+ motion_estimation(oldorgframe[0],neworgframe[0],
+ oldrefframe[0],newrefframe[0],
+ neworg[0],newref[0],
+ sxf,syf,sxb,syb,mbinfo,0,0);
+
+ predict(oldrefframe,newrefframe,predframe,0,mbinfo);
+ dct_type_estimation(predframe[0],neworg[0],mbinfo);
+ transform(predframe,neworg,mbinfo,blocks);
+
+ putpict(neworg[0]);
+
+ for (k=0; k<mb_height*mb_width; k++)
+ {
+ if (mbinfo[k].mb_type & MB_INTRA)
+ for (j=0; j<block_count; j++)
+ iquant_intra(blocks[k*block_count+j],blocks[k*block_count+j],
+ dc_prec,intra_q,mbinfo[k].mquant);
+ else
+ for (j=0;j<block_count;j++)
+ iquant_non_intra(blocks[k*block_count+j],blocks[k*block_count+j],
+ inter_q,mbinfo[k].mquant);
+ }
+
+ itransform(predframe,newref,mbinfo,blocks);
+ calcSNR(neworg,newref);
+ stats();
+ }
+
+ sprintf(name,tplref,f+frame0);
+ writeframe(name,newref);
+
+ }
+
+ putseqend();
+}
--- /dev/null
+/* putvlc.c, generation of variable length codes */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include <stdio.h>
+
+#include "config.h"
+#include "global.h"
+#include "vlc.h"
+
+/* private prototypes */
+static void putDC _ANSI_ARGS_((sVLCtable *tab, int val));
+
+/* generate variable length code for luminance DC coefficient */
+void putDClum(val)
+int val;
+{
+ putDC(DClumtab,val);
+}
+
+/* generate variable length code for chrominance DC coefficient */
+void putDCchrom(val)
+int val;
+{
+ putDC(DCchromtab,val);
+}
+
+/* generate variable length code for DC coefficient (7.2.1) */
+static void putDC(tab,val)
+sVLCtable *tab;
+int val;
+{
+ int absval, size;
+
+ absval = (val<0) ? -val : val; /* abs(val) */
+
+ if (absval>2047 || (mpeg1 && absval>255))
+ {
+ /* should never happen */
+ sprintf(errortext,"DC value out of range (%d)\n",val);
+ error(errortext);
+ }
+
+ /* compute dct_dc_size */
+ size = 0;
+
+ while (absval)
+ {
+ absval >>= 1;
+ size++;
+ }
+
+ /* generate VLC for dct_dc_size (Table B-12 or B-13) */
+ putbits(tab[size].code,tab[size].len);
+
+ /* append fixed length code (dc_dct_differential) */
+ if (size!=0)
+ {
+ if (val>=0)
+ absval = val;
+ else
+ absval = val + (1<<size) - 1; /* val + (2 ^ size) - 1 */
+ putbits(absval,size);
+ }
+}
+
+/* generate variable length code for first coefficient
+ * of a non-intra block (7.2.2.2) */
+void putACfirst(run,val)
+int run,val;
+{
+ if (run==0 && (val==1 || val==-1)) /* these are treated differently */
+ putbits(2|(val<0),2); /* generate '1s' (s=sign), (Table B-14, line 2) */
+ else
+ putAC(run,val,0); /* no difference for all others */
+}
+
+/* generate variable length code for other DCT coefficients (7.2.2) */
+void putAC(run,signed_level,vlcformat)
+int run,signed_level,vlcformat;
+{
+ int level, len;
+ VLCtable *ptab;
+
+ level = (signed_level<0) ? -signed_level : signed_level; /* abs(signed_level) */
+
+ /* make sure run and level are valid */
+ if (run<0 || run>63 || level==0 || level>2047 || (mpeg1 && level>255))
+ {
+ sprintf(errortext,"AC value out of range (run=%d, signed_level=%d)\n",
+ run,signed_level);
+ error(errortext);
+ }
+
+ len = 0;
+
+ if (run<2 && level<41)
+ {
+ /* vlcformat selects either of Table B-14 / B-15 */
+ if (vlcformat)
+ ptab = &dct_code_tab1a[run][level-1];
+ else
+ ptab = &dct_code_tab1[run][level-1];
+
+ len = ptab->len;
+ }
+ else if (run<32 && level<6)
+ {
+ /* vlcformat selects either of Table B-14 / B-15 */
+ if (vlcformat)
+ ptab = &dct_code_tab2a[run-2][level-1];
+ else
+ ptab = &dct_code_tab2[run-2][level-1];
+
+ len = ptab->len;
+ }
+
+ if (len!=0) /* a VLC code exists */
+ {
+ putbits(ptab->code,len);
+ putbits(signed_level<0,1); /* sign */
+ }
+ else
+ {
+ /* no VLC for this (run, level) combination: use escape coding (7.2.2.3) */
+ putbits(1l,6); /* Escape */
+ putbits(run,6); /* 6 bit code for run */
+ if (mpeg1)
+ {
+ /* ISO/IEC 11172-2 uses a 8 or 16 bit code */
+ if (signed_level>127)
+ putbits(0,8);
+ if (signed_level<-127)
+ putbits(128,8);
+ putbits(signed_level,8);
+ }
+ else
+ {
+ /* ISO/IEC 13818-2 uses a 12 bit code, Table B-16 */
+ putbits(signed_level,12);
+ }
+ }
+}
+
+/* generate variable length code for macroblock_address_increment (6.3.16) */
+void putaddrinc(addrinc)
+int addrinc;
+{
+ while (addrinc>33)
+ {
+ putbits(0x08,11); /* macroblock_escape */
+ addrinc-= 33;
+ }
+
+ putbits(addrinctab[addrinc-1].code,addrinctab[addrinc-1].len);
+}
+
+/* generate variable length code for macroblock_type (6.3.16.1) */
+void putmbtype(pict_type,mb_type)
+int pict_type,mb_type;
+{
+ putbits(mbtypetab[pict_type-1][mb_type].code,
+ mbtypetab[pict_type-1][mb_type].len);
+}
+
+/* generate variable length code for motion_code (6.3.16.3) */
+void putmotioncode(motion_code)
+int motion_code;
+{
+ int abscode;
+
+ abscode = (motion_code>=0) ? motion_code : -motion_code; /* abs(motion_code) */
+ putbits(motionvectab[abscode].code,motionvectab[abscode].len);
+ if (motion_code!=0)
+ putbits(motion_code<0,1); /* sign, 0=positive, 1=negative */
+}
+
+/* generate variable length code for dmvector[t] (6.3.16.3), Table B-11 */
+void putdmv(dmv)
+int dmv;
+{
+ if (dmv==0)
+ putbits(0,1);
+ else if (dmv>0)
+ putbits(2,2);
+ else
+ putbits(3,2);
+}
+
+/* generate variable length code for coded_block_pattern (6.3.16.4)
+ *
+ * 4:2:2, 4:4:4 not implemented
+ */
+void putcbp(cbp)
+int cbp;
+{
+ putbits(cbptable[cbp].code,cbptable[cbp].len);
+}
--- /dev/null
+/* quantize.c, quantization / inverse quantization */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include <stdio.h>
+#include "config.h"
+#include "global.h"
+
+static void iquant1_intra _ANSI_ARGS_((short *src, short *dst,
+ int dc_prec, unsigned char *quant_mat, int mquant));
+static void iquant1_non_intra _ANSI_ARGS_((short *src, short *dst,
+ unsigned char *quant_mat, int mquant));
+
+/* Test Model 5 quantization
+ *
+ * this quantizer has a bias of 1/8 stepsize towards zero
+ * (except for the DC coefficient)
+ */
+int quant_intra(src,dst,dc_prec,quant_mat,mquant)
+short *src, *dst;
+int dc_prec;
+unsigned char *quant_mat;
+int mquant;
+{
+ int i;
+ int x, y, d;
+
+ x = src[0];
+ d = 8>>dc_prec; /* intra_dc_mult */
+ dst[0] = (x>=0) ? (x+(d>>1))/d : -((-x+(d>>1))/d); /* round(x/d) */
+
+ for (i=1; i<64; i++)
+ {
+ x = src[i];
+ d = quant_mat[i];
+ y = (32*(x>=0 ? x : -x) + (d>>1))/d; /* round(32*x/quant_mat) */
+ d = (3*mquant+2)>>2;
+ y = (y+d)/(2*mquant); /* (y+0.75*mquant) / (2*mquant) */
+
+ /* clip to syntax limits */
+ if (y > 255)
+ {
+ if (mpeg1)
+ y = 255;
+ else if (y > 2047)
+ y = 2047;
+ }
+
+ dst[i] = (x>=0) ? y : -y;
+
+#if 0
+ /* this quantizer is virtually identical to the above */
+ if (x<0)
+ x = -x;
+ d = mquant*quant_mat[i];
+ y = (16*x + ((3*d)>>3)) / d;
+ dst[i] = (src[i]<0) ? -y : y;
+#endif
+ }
+
+ return 1;
+}
+
+int quant_non_intra(src,dst,quant_mat,mquant)
+short *src, *dst;
+unsigned char *quant_mat;
+int mquant;
+{
+ int i;
+ int x, y, d;
+ int nzflag;
+
+ nzflag = 0;
+
+ for (i=0; i<64; i++)
+ {
+ x = src[i];
+ d = quant_mat[i];
+ y = (32*(x>=0 ? x : -x) + (d>>1))/d; /* round(32*x/quant_mat) */
+ y /= (2*mquant);
+
+ /* clip to syntax limits */
+ if (y > 255)
+ {
+ if (mpeg1)
+ y = 255;
+ else if (y > 2047)
+ y = 2047;
+ }
+
+ if ((dst[i] = (x>=0 ? y : -y)) != 0)
+ nzflag=1;
+ }
+
+ return nzflag;
+}
+
+/* MPEG-2 inverse quantization */
+void iquant_intra(src,dst,dc_prec,quant_mat,mquant)
+short *src, *dst;
+int dc_prec;
+unsigned char *quant_mat;
+int mquant;
+{
+ int i, val, sum;
+
+ if (mpeg1)
+ iquant1_intra(src,dst,dc_prec,quant_mat,mquant);
+ else
+ {
+ sum = dst[0] = src[0] << (3-dc_prec);
+ for (i=1; i<64; i++)
+ {
+ val = (int)(src[i]*quant_mat[i]*mquant)/16;
+ sum+= dst[i] = (val>2047) ? 2047 : ((val<-2048) ? -2048 : val);
+ }
+
+ /* mismatch control */
+ if ((sum&1)==0)
+ dst[63]^= 1;
+ }
+}
+
+void iquant_non_intra(src,dst,quant_mat,mquant)
+short *src, *dst;
+unsigned char *quant_mat;
+int mquant;
+{
+ int i, val, sum;
+
+ if (mpeg1)
+ iquant1_non_intra(src,dst,quant_mat,mquant);
+ else
+ {
+ sum = 0;
+ for (i=0; i<64; i++)
+ {
+ val = src[i];
+ if (val!=0)
+ val = (int)((2*val+(val>0 ? 1 : -1))*quant_mat[i]*mquant)/32;
+ sum+= dst[i] = (val>2047) ? 2047 : ((val<-2048) ? -2048 : val);
+ }
+
+ /* mismatch control */
+ if ((sum&1)==0)
+ dst[63]^= 1;
+ }
+}
+
+/* MPEG-1 inverse quantization */
+static void iquant1_intra(src,dst,dc_prec,quant_mat,mquant)
+short *src, *dst;
+int dc_prec;
+unsigned char *quant_mat;
+int mquant;
+{
+ int i, val;
+
+ dst[0] = src[0] << (3-dc_prec);
+ for (i=1; i<64; i++)
+ {
+ val = (int)(src[i]*quant_mat[i]*mquant)/16;
+
+ /* mismatch control */
+ if ((val&1)==0 && val!=0)
+ val+= (val>0) ? -1 : 1;
+
+ /* saturation */
+ dst[i] = (val>2047) ? 2047 : ((val<-2048) ? -2048 : val);
+ }
+}
+
+static void iquant1_non_intra(src,dst,quant_mat,mquant)
+short *src, *dst;
+unsigned char *quant_mat;
+int mquant;
+{
+ int i, val;
+
+ for (i=0; i<64; i++)
+ {
+ val = src[i];
+ if (val!=0)
+ {
+ val = (int)((2*val+(val>0 ? 1 : -1))*quant_mat[i]*mquant)/32;
+
+ /* mismatch control */
+ if ((val&1)==0 && val!=0)
+ val+= (val>0) ? -1 : 1;
+ }
+
+ /* saturation */
+ dst[i] = (val>2047) ? 2047 : ((val<-2048) ? -2048 : val);
+ }
+}
--- /dev/null
+/* ratectl.c, bitrate control routines (linear quantization only currently) */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include <stdio.h>
+#include <math.h>
+
+#include "config.h"
+#include "global.h"
+
+/* private prototypes */
+static void calc_actj _ANSI_ARGS_((unsigned char *frame));
+static double var_sblk _ANSI_ARGS_((unsigned char *p, int lx));
+
+/* rate control variables */
+int Xi, Xp, Xb, r, d0i, d0p, d0b;
+double avg_act;
+static int R, T, d;
+static double actsum;
+static int Np, Nb, S, Q;
+static int prev_mquant;
+
+void rc_init_seq()
+{
+ /* reaction parameter (constant) */
+ if (r==0) r = (int)floor(2.0*bit_rate/frame_rate + 0.5);
+
+ /* average activity */
+ if (avg_act==0.0) avg_act = 400.0;
+
+ /* remaining # of bits in GOP */
+ R = 0;
+
+ /* global complexity measure */
+ if (Xi==0) Xi = (int)floor(160.0*bit_rate/115.0 + 0.5);
+ if (Xp==0) Xp = (int)floor( 60.0*bit_rate/115.0 + 0.5);
+ if (Xb==0) Xb = (int)floor( 42.0*bit_rate/115.0 + 0.5);
+
+ /* virtual buffer fullness */
+ if (d0i==0) d0i = (int)floor(10.0*r/31.0 + 0.5);
+ if (d0p==0) d0p = (int)floor(10.0*r/31.0 + 0.5);
+ if (d0b==0) d0b = (int)floor(1.4*10.0*r/31.0 + 0.5);
+/*
+ if (d0i==0) d0i = (int)floor(10.0*r/(qscale_tab[0] ? 56.0 : 31.0) + 0.5);
+ if (d0p==0) d0p = (int)floor(10.0*r/(qscale_tab[1] ? 56.0 : 31.0) + 0.5);
+ if (d0b==0) d0b = (int)floor(1.4*10.0*r/(qscale_tab[2] ? 56.0 : 31.0) + 0.5);
+*/
+
+ fprintf(statfile,"\nrate control: sequence initialization\n");
+ fprintf(statfile,
+ " initial global complexity measures (I,P,B): Xi=%d, Xp=%d, Xb=%d\n",
+ Xi, Xp, Xb);
+ fprintf(statfile," reaction parameter: r=%d\n", r);
+ fprintf(statfile,
+ " initial virtual buffer fullness (I,P,B): d0i=%d, d0p=%d, d0b=%d\n",
+ d0i, d0p, d0b);
+ fprintf(statfile," initial average activity: avg_act=%.1f\n", avg_act);
+}
+
+void rc_init_GOP(np,nb)
+int np,nb;
+{
+ R += (int) floor((1 + np + nb) * bit_rate / frame_rate + 0.5);
+ Np = fieldpic ? 2*np+1 : np;
+ Nb = fieldpic ? 2*nb : nb;
+
+ fprintf(statfile,"\nrate control: new group of pictures (GOP)\n");
+ fprintf(statfile," target number of bits for GOP: R=%d\n",R);
+ fprintf(statfile," number of P pictures in GOP: Np=%d\n",Np);
+ fprintf(statfile," number of B pictures in GOP: Nb=%d\n",Nb);
+}
+
+/* Note: we need to substitute K for the 1.4 and 1.0 constants -- this can
+ be modified to fit image content */
+
+/* Step 1: compute target bits for current picture being coded */
+void rc_init_pict(frame)
+unsigned char *frame;
+{
+ double Tmin;
+
+ switch (pict_type)
+ {
+ case I_TYPE:
+ T = (int) floor(R/(1.0+Np*Xp/(Xi*1.0)+Nb*Xb/(Xi*1.4)) + 0.5);
+ d = d0i;
+ break;
+ case P_TYPE:
+ T = (int) floor(R/(Np+Nb*1.0*Xb/(1.4*Xp)) + 0.5);
+ d = d0p;
+ break;
+ case B_TYPE:
+ T = (int) floor(R/(Nb+Np*1.4*Xp/(1.0*Xb)) + 0.5);
+ d = d0b;
+ break;
+ }
+
+ Tmin = (int) floor(bit_rate/(8.0*frame_rate) + 0.5);
+
+ if (T<Tmin)
+ T = Tmin;
+
+ S = bitcount();
+ Q = 0;
+
+ calc_actj(frame);
+ actsum = 0.0;
+
+ fprintf(statfile,"\nrate control: start of picture\n");
+ fprintf(statfile," target number of bits: T=%d\n",T);
+}
+
+static void calc_actj(frame)
+unsigned char *frame;
+{
+ int i,j,k;
+ unsigned char *p;
+ double actj,var;
+
+ k = 0;
+
+ for (j=0; j<height2; j+=16)
+ for (i=0; i<width; i+=16)
+ {
+ p = frame + ((pict_struct==BOTTOM_FIELD)?width:0) + i + width2*j;
+
+ /* take minimum spatial activity measure of luminance blocks */
+
+ actj = var_sblk(p,width2);
+ var = var_sblk(p+8,width2);
+ if (var<actj) actj = var;
+ var = var_sblk(p+8*width2,width2);
+ if (var<actj) actj = var;
+ var = var_sblk(p+8*width2+8,width2);
+ if (var<actj) actj = var;
+
+ if (!fieldpic && !prog_seq)
+ {
+ /* field */
+ var = var_sblk(p,width<<1);
+ if (var<actj) actj = var;
+ var = var_sblk(p+8,width<<1);
+ if (var<actj) actj = var;
+ var = var_sblk(p+width,width<<1);
+ if (var<actj) actj = var;
+ var = var_sblk(p+width+8,width<<1);
+ if (var<actj) actj = var;
+ }
+
+ actj+= 1.0;
+
+ mbinfo[k++].act = actj;
+ }
+}
+
+void rc_update_pict()
+{
+ double X;
+
+ S = bitcount() - S; /* total # of bits in picture */
+ R-= S; /* remaining # of bits in GOP */
+ X = (int) floor(S*((0.5*(double)Q)/(mb_width*mb_height2)) + 0.5);
+ d+= S - T;
+ avg_act = actsum/(mb_width*mb_height2);
+
+ switch (pict_type)
+ {
+ case I_TYPE:
+ Xi = X;
+ d0i = d;
+ break;
+ case P_TYPE:
+ Xp = X;
+ d0p = d;
+ Np--;
+ break;
+ case B_TYPE:
+ Xb = X;
+ d0b = d;
+ Nb--;
+ break;
+ }
+
+ fprintf(statfile,"\nrate control: end of picture\n");
+ fprintf(statfile," actual number of bits: S=%d\n",S);
+ fprintf(statfile," average quantization parameter Q=%.1f\n",
+ (double)Q/(mb_width*mb_height2));
+ fprintf(statfile," remaining number of bits in GOP: R=%d\n",R);
+ fprintf(statfile,
+ " global complexity measures (I,P,B): Xi=%d, Xp=%d, Xb=%d\n",
+ Xi, Xp, Xb);
+ fprintf(statfile,
+ " virtual buffer fullness (I,P,B): d0i=%d, d0p=%d, d0b=%d\n",
+ d0i, d0p, d0b);
+ fprintf(statfile," remaining number of P pictures in GOP: Np=%d\n",Np);
+ fprintf(statfile," remaining number of B pictures in GOP: Nb=%d\n",Nb);
+ fprintf(statfile," average activity: avg_act=%.1f\n", avg_act);
+}
+
+/* compute initial quantization stepsize (at the beginning of picture) */
+int rc_start_mb()
+{
+ int mquant;
+
+ if (q_scale_type)
+ {
+ mquant = (int) floor(2.0*d*31.0/r + 0.5);
+
+ /* clip mquant to legal (linear) range */
+ if (mquant<1)
+ mquant = 1;
+ if (mquant>112)
+ mquant = 112;
+
+ /* map to legal quantization level */
+ mquant = non_linear_mquant_table[map_non_linear_mquant[mquant]];
+ }
+ else
+ {
+ mquant = (int) floor(d*31.0/r + 0.5);
+ mquant <<= 1;
+
+ /* clip mquant to legal (linear) range */
+ if (mquant<2)
+ mquant = 2;
+ if (mquant>62)
+ mquant = 62;
+
+ prev_mquant = mquant;
+ }
+
+/*
+ fprintf(statfile,"rc_start_mb:\n");
+ fprintf(statfile,"mquant=%d\n",mquant);
+*/
+
+ return mquant;
+}
+
+/* Step 2: measure virtual buffer - estimated buffer discrepancy */
+int rc_calc_mquant(j)
+int j;
+{
+ int mquant;
+ double dj, Qj, actj, N_actj;
+
+ /* measure virtual buffer discrepancy from uniform distribution model */
+ dj = d + (bitcount()-S) - j*(T/(mb_width*mb_height2));
+
+ /* scale against dynamic range of mquant and the bits/picture count */
+ Qj = dj*31.0/r;
+/*Qj = dj*(q_scale_type ? 56.0 : 31.0)/r; */
+
+ actj = mbinfo[j].act;
+ actsum+= actj;
+
+ /* compute normalized activity */
+ N_actj = (2.0*actj+avg_act)/(actj+2.0*avg_act);
+
+ if (q_scale_type)
+ {
+ /* modulate mquant with combined buffer and local activity measures */
+ mquant = (int) floor(2.0*Qj*N_actj + 0.5);
+
+ /* clip mquant to legal (linear) range */
+ if (mquant<1)
+ mquant = 1;
+ if (mquant>112)
+ mquant = 112;
+
+ /* map to legal quantization level */
+ mquant = non_linear_mquant_table[map_non_linear_mquant[mquant]];
+ }
+ else
+ {
+ /* modulate mquant with combined buffer and local activity measures */
+ mquant = (int) floor(Qj*N_actj + 0.5);
+ mquant <<= 1;
+
+ /* clip mquant to legal (linear) range */
+ if (mquant<2)
+ mquant = 2;
+ if (mquant>62)
+ mquant = 62;
+
+ /* ignore small changes in mquant */
+ if (mquant>=8 && (mquant-prev_mquant)>=-4 && (mquant-prev_mquant)<=4)
+ mquant = prev_mquant;
+
+ prev_mquant = mquant;
+ }
+
+ Q+= mquant; /* for calculation of average mquant */
+
+/*
+ fprintf(statfile,"rc_calc_mquant(%d): ",j);
+ fprintf(statfile,"bitcount=%d, dj=%f, Qj=%f, actj=%f, N_actj=%f, mquant=%d\n",
+ bitcount(),dj,Qj,actj,N_actj,mquant);
+*/
+
+ return mquant;
+}
+
+/* compute variance of 8x8 block */
+static double var_sblk(p,lx)
+unsigned char *p;
+int lx;
+{
+ int i, j;
+ unsigned int v, s, s2;
+
+ s = s2 = 0;
+
+ for (j=0; j<8; j++)
+ {
+ for (i=0; i<8; i++)
+ {
+ v = *p++;
+ s+= v;
+ s2+= v*v;
+ }
+ p+= lx - 8;
+ }
+
+ return s2/64.0 - (s/64.0)*(s/64.0);
+}
+
+/* VBV calculations
+ *
+ * generates warnings if underflow or overflow occurs
+ */
+
+/* vbv_end_of_picture
+ *
+ * - has to be called directly after writing picture_data()
+ * - needed for accurate VBV buffer overflow calculation
+ * - assumes there is no byte stuffing prior to the next start code
+ */
+
+static int bitcnt_EOP;
+
+void vbv_end_of_picture()
+{
+ bitcnt_EOP = bitcount();
+ bitcnt_EOP = (bitcnt_EOP + 7) & ~7; /* account for bit stuffing */
+}
+
+/* calc_vbv_delay
+ *
+ * has to be called directly after writing the picture start code, the
+ * reference point for vbv_delay
+ */
+
+void calc_vbv_delay()
+{
+ double picture_delay;
+ static double next_ip_delay; /* due to frame reordering delay */
+ static double decoding_time;
+
+ /* number of 1/90000 s ticks until next picture is to be decoded */
+ if (pict_type == B_TYPE)
+ {
+ if (prog_seq)
+ {
+ if (!repeatfirst)
+ picture_delay = 90000.0/frame_rate; /* 1 frame */
+ else
+ {
+ if (!topfirst)
+ picture_delay = 90000.0*2.0/frame_rate; /* 2 frames */
+ else
+ picture_delay = 90000.0*3.0/frame_rate; /* 3 frames */
+ }
+ }
+ else
+ {
+ /* interlaced */
+ if (fieldpic)
+ picture_delay = 90000.0/(2.0*frame_rate); /* 1 field */
+ else
+ {
+ if (!repeatfirst)
+ picture_delay = 90000.0*2.0/(2.0*frame_rate); /* 2 flds */
+ else
+ picture_delay = 90000.0*3.0/(2.0*frame_rate); /* 3 flds */
+ }
+ }
+ }
+ else
+ {
+ /* I or P picture */
+ if (fieldpic)
+ {
+ if(topfirst==(pict_struct==TOP_FIELD))
+ {
+ /* first field */
+ picture_delay = 90000.0/(2.0*frame_rate);
+ }
+ else
+ {
+ /* second field */
+ /* take frame reordering delay into account */
+ picture_delay = next_ip_delay - 90000.0/(2.0*frame_rate);
+ }
+ }
+ else
+ {
+ /* frame picture */
+ /* take frame reordering delay into account*/
+ picture_delay = next_ip_delay;
+ }
+
+ if (!fieldpic || topfirst!=(pict_struct==TOP_FIELD))
+ {
+ /* frame picture or second field */
+ if (prog_seq)
+ {
+ if (!repeatfirst)
+ next_ip_delay = 90000.0/frame_rate;
+ else
+ {
+ if (!topfirst)
+ next_ip_delay = 90000.0*2.0/frame_rate;
+ else
+ next_ip_delay = 90000.0*3.0/frame_rate;
+ }
+ }
+ else
+ {
+ if (fieldpic)
+ next_ip_delay = 90000.0/(2.0*frame_rate);
+ else
+ {
+ if (!repeatfirst)
+ next_ip_delay = 90000.0*2.0/(2.0*frame_rate);
+ else
+ next_ip_delay = 90000.0*3.0/(2.0*frame_rate);
+ }
+ }
+ }
+ }
+
+ if (decoding_time==0.0)
+ {
+ /* first call of calc_vbv_delay */
+ /* we start with a 7/8 filled VBV buffer (12.5% back-off) */
+ picture_delay = ((vbv_buffer_size*16384*7)/8)*90000.0/bit_rate;
+ if (fieldpic)
+ next_ip_delay = (int)(90000.0/frame_rate+0.5);
+ }
+
+ /* VBV checks */
+
+ /* check for underflow (previous picture) */
+ if (!low_delay && (decoding_time < bitcnt_EOP*90000.0/bit_rate))
+ {
+ /* picture not completely in buffer at intended decoding time */
+ if (!quiet)
+ fprintf(stderr,"vbv_delay underflow! (decoding_time=%.1f, t_EOP=%.1f\n)",
+ decoding_time, bitcnt_EOP*90000.0/bit_rate);
+ }
+
+ /* when to decode current frame */
+ decoding_time += picture_delay;
+
+ /* warning: bitcount() may overflow (e.g. after 9 min. at 8 Mbit/s */
+ vbv_delay = (int)(decoding_time - bitcount()*90000.0/bit_rate);
+
+ /* check for overflow (current picture) */
+ if ((decoding_time - bitcnt_EOP*90000.0/bit_rate)
+ > (vbv_buffer_size*16384)*90000.0/bit_rate)
+ {
+ if (!quiet)
+ fprintf(stderr,"vbv_delay overflow!\n");
+ }
+
+ fprintf(statfile,
+ "\nvbv_delay=%d (bitcount=%d, decoding_time=%.2f, bitcnt_EOP=%d)\n",
+ vbv_delay,bitcount(),decoding_time,bitcnt_EOP);
+
+ if (vbv_delay<0)
+ {
+ if (!quiet)
+ fprintf(stderr,"vbv_delay underflow: %d\n",vbv_delay);
+ vbv_delay = 0;
+ }
+
+ if (vbv_delay>65535)
+ {
+ if (!quiet)
+ fprintf(stderr,"vbv_delay overflow: %d\n",vbv_delay);
+ vbv_delay = 65535;
+ }
+}
--- /dev/null
+/* readpic.c, read source pictures */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "config.h"
+#include "global.h"
+
+/* private prototypes */
+static void read_y_u_v _ANSI_ARGS_((char *fname, unsigned char *frame[]));
+static void read_yuv _ANSI_ARGS_((char *fname, unsigned char *frame[]));
+static void read_ppm _ANSI_ARGS_((char *fname, unsigned char *frame[]));
+static void border_extend _ANSI_ARGS_((unsigned char *frame, int w1, int h1,
+ int w2, int h2));
+static void conv444to422 _ANSI_ARGS_((unsigned char *src, unsigned char *dst));
+static void conv422to420 _ANSI_ARGS_((unsigned char *src, unsigned char *dst));
+
+void readframe(fname,frame)
+char *fname;
+unsigned char *frame[];
+{
+ switch (inputtype)
+ {
+ case T_Y_U_V:
+ read_y_u_v(fname,frame);
+ break;
+ case T_YUV:
+ read_yuv(fname,frame);
+ break;
+ case T_PPM:
+ read_ppm(fname,frame);
+ break;
+ default:
+ break;
+ }
+}
+
+static void read_y_u_v(fname,frame)
+char *fname;
+unsigned char *frame[];
+{
+ int i;
+ int chrom_hsize, chrom_vsize;
+ char name[128];
+ FILE *fd;
+
+ chrom_hsize = (chroma_format==CHROMA444) ? horizontal_size
+ : horizontal_size>>1;
+ chrom_vsize = (chroma_format!=CHROMA420) ? vertical_size
+ : vertical_size>>1;
+
+ sprintf(name,"%s.Y",fname);
+ if (!(fd = fopen(name,"rb")))
+ {
+ sprintf(errortext,"Couldn't open %s\n",name);
+ error(errortext);
+ }
+ for (i=0; i<vertical_size; i++)
+ fread(frame[0]+i*width,1,horizontal_size,fd);
+ fclose(fd);
+ border_extend(frame[0],horizontal_size,vertical_size,width,height);
+
+ sprintf(name,"%s.U",fname);
+ if (!(fd = fopen(name,"rb")))
+ {
+ sprintf(errortext,"Couldn't open %s\n",name);
+ error(errortext);
+ }
+ for (i=0; i<chrom_vsize; i++)
+ fread(frame[1]+i*chrom_width,1,chrom_hsize,fd);
+ fclose(fd);
+ border_extend(frame[1],chrom_hsize,chrom_vsize,chrom_width,chrom_height);
+
+ sprintf(name,"%s.V",fname);
+ if (!(fd = fopen(name,"rb")))
+ {
+ sprintf(errortext,"Couldn't open %s\n",name);
+ error(errortext);
+ }
+ for (i=0; i<chrom_vsize; i++)
+ fread(frame[2]+i*chrom_width,1,chrom_hsize,fd);
+ fclose(fd);
+ border_extend(frame[2],chrom_hsize,chrom_vsize,chrom_width,chrom_height);
+}
+
+static void read_yuv(fname,frame)
+char *fname;
+unsigned char *frame[];
+{
+ int i;
+ int chrom_hsize, chrom_vsize;
+ char name[128];
+ FILE *fd;
+
+ chrom_hsize = (chroma_format==CHROMA444) ? horizontal_size
+ : horizontal_size>>1;
+ chrom_vsize = (chroma_format!=CHROMA420) ? vertical_size
+ : vertical_size>>1;
+
+ sprintf(name,"%s.yuv",fname);
+ if (!(fd = fopen(name,"rb")))
+ {
+ sprintf(errortext,"Couldn't open %s\n",name);
+ error(errortext);
+ }
+
+ /* Y */
+ for (i=0; i<vertical_size; i++)
+ fread(frame[0]+i*width,1,horizontal_size,fd);
+ border_extend(frame[0],horizontal_size,vertical_size,width,height);
+
+ /* Cb */
+ for (i=0; i<chrom_vsize; i++)
+ fread(frame[1]+i*chrom_width,1,chrom_hsize,fd);
+ border_extend(frame[1],chrom_hsize,chrom_vsize,chrom_width,chrom_height);
+
+ /* Cr */
+ for (i=0; i<chrom_vsize; i++)
+ fread(frame[2]+i*chrom_width,1,chrom_hsize,fd);
+ border_extend(frame[2],chrom_hsize,chrom_vsize,chrom_width,chrom_height);
+
+ fclose(fd);
+}
+
+static void read_ppm(fname,frame)
+char *fname;
+unsigned char *frame[];
+{
+ int i, j;
+ int r, g, b;
+ double y, u, v;
+ double cr, cg, cb, cu, cv;
+ char name[128];
+ FILE *fd;
+ unsigned char *yp, *up, *vp;
+ static unsigned char *u444, *v444, *u422, *v422;
+ static double coef[7][3] = {
+ {0.2125,0.7154,0.0721}, /* ITU-R Rec. 709 (1990) */
+ {0.299, 0.587, 0.114}, /* unspecified */
+ {0.299, 0.587, 0.114}, /* reserved */
+ {0.30, 0.59, 0.11}, /* FCC */
+ {0.299, 0.587, 0.114}, /* ITU-R Rec. 624-4 System B, G */
+ {0.299, 0.587, 0.114}, /* SMPTE 170M */
+ {0.212, 0.701, 0.087}}; /* SMPTE 240M (1987) */
+
+ i = matrix_coefficients;
+ if (i>8)
+ i = 3;
+
+ cr = coef[i-1][0];
+ cg = coef[i-1][1];
+ cb = coef[i-1][2];
+ cu = 0.5/(1.0-cb);
+ cv = 0.5/(1.0-cr);
+
+ if (chroma_format==CHROMA444)
+ {
+ u444 = frame[1];
+ v444 = frame[2];
+ }
+ else
+ {
+ if (!u444)
+ {
+ if (!(u444 = (unsigned char *)malloc(width*height)))
+ error("malloc failed");
+ if (!(v444 = (unsigned char *)malloc(width*height)))
+ error("malloc failed");
+ if (chroma_format==CHROMA420)
+ {
+ if (!(u422 = (unsigned char *)malloc((width>>1)*height)))
+ error("malloc failed");
+ if (!(v422 = (unsigned char *)malloc((width>>1)*height)))
+ error("malloc failed");
+ }
+ }
+ }
+
+ sprintf(name,"%s.ppm",fname);
+
+ if (!(fd = fopen(name,"rb")))
+ {
+ sprintf(errortext,"Couldn't open %s\n",name);
+ error(errortext);
+ }
+
+ /* skip header */
+ getc(fd); getc(fd); /* magic number (P6) */
+ pbm_getint(fd); pbm_getint(fd); pbm_getint(fd); /* width height maxcolors */
+
+ for (i=0; i<vertical_size; i++)
+ {
+ yp = frame[0] + i*width;
+ up = u444 + i*width;
+ vp = v444 + i*width;
+
+ for (j=0; j<horizontal_size; j++)
+ {
+ r=getc(fd); g=getc(fd); b=getc(fd);
+ /* convert to YUV */
+ y = cr*r + cg*g + cb*b;
+ u = cu*(b-y);
+ v = cv*(r-y);
+ yp[j] = (219.0/256.0)*y + 16.5; /* nominal range: 16..235 */
+ up[j] = (224.0/256.0)*u + 128.5; /* 16..240 */
+ vp[j] = (224.0/256.0)*v + 128.5; /* 16..240 */
+ }
+ }
+ fclose(fd);
+
+ border_extend(frame[0],horizontal_size,vertical_size,width,height);
+ border_extend(u444,horizontal_size,vertical_size,width,height);
+ border_extend(v444,horizontal_size,vertical_size,width,height);
+
+ if (chroma_format==CHROMA422)
+ {
+ conv444to422(u444,frame[1]);
+ conv444to422(v444,frame[2]);
+ }
+
+ if (chroma_format==CHROMA420)
+ {
+ conv444to422(u444,u422);
+ conv444to422(v444,v422);
+ conv422to420(u422,frame[1]);
+ conv422to420(v422,frame[2]);
+ }
+}
+
+static void border_extend(frame,w1,h1,w2,h2)
+unsigned char *frame;
+int w1,h1,w2,h2;
+{
+ int i, j;
+ unsigned char *fp;
+
+ /* horizontal pixel replication (right border) */
+
+ for (j=0; j<h1; j++)
+ {
+ fp = frame + j*w2;
+ for (i=w1; i<w2; i++)
+ fp[i] = fp[i-1];
+ }
+
+ /* vertical pixel replication (bottom border) */
+
+ for (j=h1; j<h2; j++)
+ {
+ fp = frame + j*w2;
+ for (i=0; i<w2; i++)
+ fp[i] = fp[i-w2];
+ }
+}
+
+/* horizontal filter and 2:1 subsampling */
+static void conv444to422(src,dst)
+unsigned char *src, *dst;
+{
+ int i, j, im5, im4, im3, im2, im1, ip1, ip2, ip3, ip4, ip5, ip6;
+
+ if (mpeg1)
+ {
+ for (j=0; j<height; j++)
+ {
+ for (i=0; i<width; i+=2)
+ {
+ im5 = (i<5) ? 0 : i-5;
+ im4 = (i<4) ? 0 : i-4;
+ im3 = (i<3) ? 0 : i-3;
+ im2 = (i<2) ? 0 : i-2;
+ im1 = (i<1) ? 0 : i-1;
+ ip1 = (i<width-1) ? i+1 : width-1;
+ ip2 = (i<width-2) ? i+2 : width-1;
+ ip3 = (i<width-3) ? i+3 : width-1;
+ ip4 = (i<width-4) ? i+4 : width-1;
+ ip5 = (i<width-5) ? i+5 : width-1;
+ ip6 = (i<width-5) ? i+6 : width-1;
+
+ /* FIR filter with 0.5 sample interval phase shift */
+ dst[i>>1] = clp[(int)(228*(src[i]+src[ip1])
+ +70*(src[im1]+src[ip2])
+ -37*(src[im2]+src[ip3])
+ -21*(src[im3]+src[ip4])
+ +11*(src[im4]+src[ip5])
+ + 5*(src[im5]+src[ip6])+256)>>9];
+ }
+ src+= width;
+ dst+= width>>1;
+ }
+ }
+ else
+ {
+ /* MPEG-2 */
+ for (j=0; j<height; j++)
+ {
+ for (i=0; i<width; i+=2)
+ {
+ im5 = (i<5) ? 0 : i-5;
+ im3 = (i<3) ? 0 : i-3;
+ im1 = (i<1) ? 0 : i-1;
+ ip1 = (i<width-1) ? i+1 : width-1;
+ ip3 = (i<width-3) ? i+3 : width-1;
+ ip5 = (i<width-5) ? i+5 : width-1;
+
+ /* FIR filter coefficients (*512): 22 0 -52 0 159 256 159 0 -52 0 22 */
+ dst[i>>1] = clp[(int)( 22*(src[im5]+src[ip5])-52*(src[im3]+src[ip3])
+ +159*(src[im1]+src[ip1])+256*src[i]+256)>>9];
+ }
+ src+= width;
+ dst+= width>>1;
+ }
+ }
+}
+
+/* vertical filter and 2:1 subsampling */
+static void conv422to420(src,dst)
+unsigned char *src, *dst;
+{
+ int w, i, j, jm6, jm5, jm4, jm3, jm2, jm1;
+ int jp1, jp2, jp3, jp4, jp5, jp6;
+
+ w = width>>1;
+
+ if (prog_frame)
+ {
+ /* intra frame */
+ for (i=0; i<w; i++)
+ {
+ for (j=0; j<height; j+=2)
+ {
+ jm5 = (j<5) ? 0 : j-5;
+ jm4 = (j<4) ? 0 : j-4;
+ jm3 = (j<3) ? 0 : j-3;
+ jm2 = (j<2) ? 0 : j-2;
+ jm1 = (j<1) ? 0 : j-1;
+ jp1 = (j<height-1) ? j+1 : height-1;
+ jp2 = (j<height-2) ? j+2 : height-1;
+ jp3 = (j<height-3) ? j+3 : height-1;
+ jp4 = (j<height-4) ? j+4 : height-1;
+ jp5 = (j<height-5) ? j+5 : height-1;
+ jp6 = (j<height-5) ? j+6 : height-1;
+
+ /* FIR filter with 0.5 sample interval phase shift */
+ dst[w*(j>>1)] = clp[(int)(228*(src[w*j]+src[w*jp1])
+ +70*(src[w*jm1]+src[w*jp2])
+ -37*(src[w*jm2]+src[w*jp3])
+ -21*(src[w*jm3]+src[w*jp4])
+ +11*(src[w*jm4]+src[w*jp5])
+ + 5*(src[w*jm5]+src[w*jp6])+256)>>9];
+ }
+ src++;
+ dst++;
+ }
+ }
+ else
+ {
+ /* intra field */
+ for (i=0; i<w; i++)
+ {
+ for (j=0; j<height; j+=4)
+ {
+ /* top field */
+ jm5 = (j<10) ? 0 : j-10;
+ jm4 = (j<8) ? 0 : j-8;
+ jm3 = (j<6) ? 0 : j-6;
+ jm2 = (j<4) ? 0 : j-4;
+ jm1 = (j<2) ? 0 : j-2;
+ jp1 = (j<height-2) ? j+2 : height-2;
+ jp2 = (j<height-4) ? j+4 : height-2;
+ jp3 = (j<height-6) ? j+6 : height-2;
+ jp4 = (j<height-8) ? j+8 : height-2;
+ jp5 = (j<height-10) ? j+10 : height-2;
+ jp6 = (j<height-12) ? j+12 : height-2;
+
+ /* FIR filter with 0.25 sample interval phase shift */
+ dst[w*(j>>1)] = clp[(int)(8*src[w*jm5]
+ +5*src[w*jm4]
+ -30*src[w*jm3]
+ -18*src[w*jm2]
+ +113*src[w*jm1]
+ +242*src[w*j]
+ +192*src[w*jp1]
+ +35*src[w*jp2]
+ -38*src[w*jp3]
+ -10*src[w*jp4]
+ +11*src[w*jp5]
+ +2*src[w*jp6]+256)>>9];
+
+ /* bottom field */
+ jm6 = (j<9) ? 1 : j-9;
+ jm5 = (j<7) ? 1 : j-7;
+ jm4 = (j<5) ? 1 : j-5;
+ jm3 = (j<3) ? 1 : j-3;
+ jm2 = (j<1) ? 1 : j-1;
+ jm1 = (j<height-1) ? j+1 : height-1;
+ jp1 = (j<height-3) ? j+3 : height-1;
+ jp2 = (j<height-5) ? j+5 : height-1;
+ jp3 = (j<height-7) ? j+7 : height-1;
+ jp4 = (j<height-9) ? j+9 : height-1;
+ jp5 = (j<height-11) ? j+11 : height-1;
+ jp6 = (j<height-13) ? j+13 : height-1;
+
+ /* FIR filter with 0.25 sample interval phase shift */
+ dst[w*((j>>1)+1)] = clp[(int)(8*src[w*jp6]
+ +5*src[w*jp5]
+ -30*src[w*jp4]
+ -18*src[w*jp3]
+ +113*src[w*jp2]
+ +242*src[w*jp1]
+ +192*src[w*jm1]
+ +35*src[w*jm2]
+ -38*src[w*jm3]
+ -10*src[w*jm4]
+ +11*src[w*jm5]
+ +2*src[w*jm6]+256)>>9];
+ }
+ src++;
+ dst++;
+ }
+ }
+}
+
+/* pbm_getc() and pbm_getint() are essentially taken from
+ * PBMPLUS (C) Jef Poskanzer
+ * but without error/EOF checking
+ */
+char pbm_getc(file)
+FILE* file;
+{
+ char ch;
+
+ ch = getc(file);
+
+ if (ch=='#')
+ {
+ do
+ {
+ ch = getc(file);
+ }
+ while (ch!='\n' && ch!='\r');
+ }
+
+ return ch;
+}
+
+int pbm_getint(file)
+FILE* file;
+{
+ char ch;
+ int i;
+
+ do
+ {
+ ch = pbm_getc(file);
+ }
+ while (ch==' ' || ch=='\t' || ch=='\n' || ch=='\r');
+
+ i = 0;
+ do
+ {
+ i = i*10 + ch-'0';
+ ch = pbm_getc(file);
+ }
+ while (ch>='0' && ch<='9');
+
+ return i;
+}
--- /dev/null
+/* stats.c, coding statistics */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include "config.h"
+#include "global.h"
+
+/* private prototypes */
+static void calcSNR1 _ANSI_ARGS_((unsigned char *org, unsigned char *rec,
+ int lx, int w, int h, double *pv, double *pe));
+
+
+void calcSNR(org,rec)
+unsigned char *org[3];
+unsigned char *rec[3];
+{
+ int w,h,offs;
+ double v,e;
+
+ w = horizontal_size;
+ h = (pict_struct==FRAME_PICTURE) ? vertical_size : (vertical_size>>1);
+ offs = (pict_struct==BOTTOM_FIELD) ? width : 0;
+
+ calcSNR1(org[0]+offs,rec[0]+offs,width2,w,h,&v,&e);
+ fprintf(statfile,"Y: variance=%4.4g, MSE=%3.3g (%3.3g dB), SNR=%3.3g dB\n",
+ v, e, 10.0*log10(255.0*255.0/e), 10.0*log10(v/e));
+
+ if (chroma_format!=CHROMA444)
+ {
+ w >>= 1;
+ offs >>= 1;
+ }
+
+ if (chroma_format==CHROMA420)
+ h >>= 1;
+
+ calcSNR1(org[1]+offs,rec[1]+offs,chrom_width2,w,h,&v,&e);
+ fprintf(statfile,"U: variance=%4.4g, MSE=%3.3g (%3.3g dB), SNR=%3.3g dB\n",
+ v, e, 10.0*log10(255.0*255.0/e), 10.0*log10(v/e));
+
+ calcSNR1(org[2]+offs,rec[2]+offs,chrom_width2,w,h,&v,&e);
+ fprintf(statfile,"V: variance=%4.4g, MSE=%3.3g (%3.3g dB), SNR=%3.3g dB\n",
+ v, e, 10.0*log10(255.0*255.0/e), 10.0*log10(v/e));
+}
+
+static void calcSNR1(org,rec,lx,w,h,pv,pe)
+unsigned char *org;
+unsigned char *rec;
+int lx,w,h;
+double *pv,*pe;
+{
+ int i, j;
+ double v1, s1, s2, e2;
+
+ s1 = s2 = e2 = 0.0;
+
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<w; i++)
+ {
+ v1 = org[i];
+ s1+= v1;
+ s2+= v1*v1;
+ v1-= rec[i];
+ e2+= v1*v1;
+ }
+ org += lx;
+ rec += lx;
+ }
+
+ s1 /= w*h;
+ s2 /= w*h;
+ e2 /= w*h;
+
+ /* prevent division by zero in calcSNR() */
+ if(e2==0.0)
+ e2 = 0.00001;
+
+ *pv = s2 - s1*s1; /* variance */
+ *pe = e2; /* MSE */
+}
+
+void stats()
+{
+ int i, j, k, nmb, mb_type;
+ int n_skipped, n_intra, n_ncoded, n_blocks, n_interp, n_forward, n_backward;
+ struct mbinfo *mbi;
+
+ nmb = mb_width*mb_height2;
+
+ n_skipped=n_intra=n_ncoded=n_blocks=n_interp=n_forward=n_backward=0;
+
+ for (k=0; k<nmb; k++)
+ {
+ mbi = mbinfo+k;
+ if (mbi->skipped)
+ n_skipped++;
+ else if (mbi->mb_type & MB_INTRA)
+ n_intra++;
+ else if (!(mbi->mb_type & MB_PATTERN))
+ n_ncoded++;
+
+ for (i=0; i<block_count; i++)
+ if (mbi->cbp & (1<<i))
+ n_blocks++;
+
+ if (mbi->mb_type & MB_FORWARD)
+ {
+ if (mbi->mb_type & MB_BACKWARD)
+ n_interp++;
+ else
+ n_forward++;
+ }
+ else if (mbi->mb_type & MB_BACKWARD)
+ n_backward++;
+ }
+
+ fprintf(statfile,"\npicture statistics:\n");
+ fprintf(statfile," # of intra coded macroblocks: %4d (%.1f%%)\n",
+ n_intra,100.0*(double)n_intra/nmb);
+ fprintf(statfile," # of coded blocks: %4d (%.1f%%)\n",
+ n_blocks,100.0*(double)n_blocks/(block_count*nmb));
+ fprintf(statfile," # of not coded macroblocks: %4d (%.1f%%)\n",
+ n_ncoded,100.0*(double)n_ncoded/nmb);
+ fprintf(statfile," # of skipped macroblocks: %4d (%.1f%%)\n",
+ n_skipped,100.0*(double)n_skipped/nmb);
+ fprintf(statfile," # of forw. pred. macroblocks: %4d (%.1f%%)\n",
+ n_forward,100.0*(double)n_forward/nmb);
+ fprintf(statfile," # of backw. pred. macroblocks: %4d (%.1f%%)\n",
+ n_backward,100.0*(double)n_backward/nmb);
+ fprintf(statfile," # of interpolated macroblocks: %4d (%.1f%%)\n",
+ n_interp,100.0*(double)n_interp/nmb);
+
+ fprintf(statfile,"\nmacroblock_type map:\n");
+
+ k = 0;
+
+ for (j=0; j<mb_height2; j++)
+ {
+ for (i=0; i<mb_width; i++)
+ {
+ mbi = mbinfo + k;
+ mb_type = mbi->mb_type;
+ if (mbi->skipped)
+ putc('S',statfile);
+ else if (mb_type & MB_INTRA)
+ putc('I',statfile);
+ else switch (mb_type & (MB_FORWARD|MB_BACKWARD))
+ {
+ case MB_FORWARD:
+ putc(mbi->motion_type==MC_FIELD ? 'f' :
+ mbi->motion_type==MC_DMV ? 'p' :
+ 'F',statfile); break;
+ case MB_BACKWARD:
+ putc(mbi->motion_type==MC_FIELD ? 'b' :
+ 'B',statfile); break;
+ case MB_FORWARD|MB_BACKWARD:
+ putc(mbi->motion_type==MC_FIELD ? 'd' :
+ 'D',statfile); break;
+ default:
+ putc('0',statfile); break;
+ }
+
+ if (mb_type & MB_QUANT)
+ putc('Q',statfile);
+ else if (mb_type & (MB_PATTERN|MB_INTRA))
+ putc(' ',statfile);
+ else
+ putc('N',statfile);
+
+ putc(' ',statfile);
+
+ k++;
+ }
+ putc('\n',statfile);
+ }
+
+ fprintf(statfile,"\nmquant map:\n");
+
+ k=0;
+ for (j=0; j<mb_height2; j++)
+ {
+ for (i=0; i<mb_width; i++)
+ {
+ if (i==0 || mbinfo[k].mquant!=mbinfo[k-1].mquant)
+ fprintf(statfile,"%3d",mbinfo[k].mquant);
+ else
+ fprintf(statfile," ");
+
+ k++;
+ }
+ putc('\n',statfile);
+ }
+
+#if 0
+ fprintf(statfile,"\ncbp map:\n");
+
+ k=0;
+ for (j=0; j<mb_height2; j++)
+ {
+ for (i=0; i<mb_width; i++)
+ {
+ fprintf(statfile,"%02x ",mbinfo[k].cbp);
+
+ k++;
+ }
+ putc('\n',statfile);
+ }
+
+ if (pict_struct==FRAME_PICTURE && !frame_pred_dct)
+ {
+ fprintf(statfile,"\ndct_type map:\n");
+
+ k=0;
+ for (j=0; j<mb_height2; j++)
+ {
+ for (i=0; i<mb_width; i++)
+ {
+ if (mbinfo[k].mb_type & (MB_PATTERN|MB_INTRA))
+ fprintf(statfile,"%d ",mbinfo[k].dct_type);
+ else
+ fprintf(statfile," ");
+
+ k++;
+ }
+ putc('\n',statfile);
+ }
+ }
+
+ if (pict_type!=I_TYPE)
+ {
+ fprintf(statfile,"\nforward motion vectors (first vector, horizontal):\n");
+
+ k=0;
+ for (j=0; j<mb_height2; j++)
+ {
+ for (i=0; i<mb_width; i++)
+ {
+ if (mbinfo[k].mb_type & MB_FORWARD)
+ fprintf(statfile,"%4d",mbinfo[k].MV[0][0][0]);
+ else
+ fprintf(statfile," .");
+
+ k++;
+ }
+ putc('\n',statfile);
+ }
+
+ fprintf(statfile,"\nforward motion vectors (first vector, vertical):\n");
+
+ k=0;
+ for (j=0; j<mb_height2; j++)
+ {
+ for (i=0; i<mb_width; i++)
+ {
+ if (mbinfo[k].mb_type & MB_FORWARD)
+ fprintf(statfile,"%4d",mbinfo[k].MV[0][0][1]);
+ else
+ fprintf(statfile," .");
+
+ k++;
+ }
+ putc('\n',statfile);
+ }
+
+ fprintf(statfile,"\nforward motion vectors (second vector, horizontal):\n");
+
+ k=0;
+ for (j=0; j<mb_height2; j++)
+ {
+ for (i=0; i<mb_width; i++)
+ {
+ if (mbinfo[k].mb_type & MB_FORWARD
+ && ((pict_struct==FRAME_PICTURE && mbinfo[k].motion_type==MC_FIELD) ||
+ (pict_struct!=FRAME_PICTURE && mbinfo[k].motion_type==MC_16X8)))
+ fprintf(statfile,"%4d",mbinfo[k].MV[1][0][0]);
+ else
+ fprintf(statfile," .");
+
+ k++;
+ }
+ putc('\n',statfile);
+ }
+
+ fprintf(statfile,"\nforward motion vectors (second vector, vertical):\n");
+
+ k=0;
+ for (j=0; j<mb_height2; j++)
+ {
+ for (i=0; i<mb_width; i++)
+ {
+ if (mbinfo[k].mb_type & MB_FORWARD
+ && ((pict_struct==FRAME_PICTURE && mbinfo[k].motion_type==MC_FIELD) ||
+ (pict_struct!=FRAME_PICTURE && mbinfo[k].motion_type==MC_16X8)))
+ fprintf(statfile,"%4d",mbinfo[k].MV[1][0][1]);
+ else
+ fprintf(statfile," .");
+
+ k++;
+ }
+ putc('\n',statfile);
+ }
+
+
+ }
+
+ if (pict_type==B_TYPE)
+ {
+ fprintf(statfile,"\nbackward motion vectors (first vector, horizontal):\n");
+
+ k=0;
+ for (j=0; j<mb_height2; j++)
+ {
+ for (i=0; i<mb_width; i++)
+ {
+ if (mbinfo[k].mb_type & MB_BACKWARD)
+ fprintf(statfile,"%4d",mbinfo[k].MV[0][1][0]);
+ else
+ fprintf(statfile," .");
+
+ k++;
+ }
+ putc('\n',statfile);
+ }
+
+ fprintf(statfile,"\nbackward motion vectors (first vector, vertical):\n");
+
+ k=0;
+ for (j=0; j<mb_height2; j++)
+ {
+ for (i=0; i<mb_width; i++)
+ {
+ if (mbinfo[k].mb_type & MB_BACKWARD)
+ fprintf(statfile,"%4d",mbinfo[k].MV[0][1][1]);
+ else
+ fprintf(statfile," .");
+
+ k++;
+ }
+ putc('\n',statfile);
+ }
+
+ fprintf(statfile,"\nbackward motion vectors (second vector, horizontal):\n");
+
+ k=0;
+ for (j=0; j<mb_height2; j++)
+ {
+ for (i=0; i<mb_width; i++)
+ {
+ if (mbinfo[k].mb_type & MB_BACKWARD
+ && ((pict_struct==FRAME_PICTURE && mbinfo[k].motion_type==MC_FIELD) ||
+ (pict_struct!=FRAME_PICTURE && mbinfo[k].motion_type==MC_16X8)))
+ fprintf(statfile,"%4d",mbinfo[k].MV[1][1][0]);
+ else
+ fprintf(statfile," .");
+
+ k++;
+ }
+ putc('\n',statfile);
+ }
+
+ fprintf(statfile,"\nbackward motion vectors (second vector, vertical):\n");
+
+ k=0;
+ for (j=0; j<mb_height2; j++)
+ {
+ for (i=0; i<mb_width; i++)
+ {
+ if (mbinfo[k].mb_type & MB_BACKWARD
+ && ((pict_struct==FRAME_PICTURE && mbinfo[k].motion_type==MC_FIELD) ||
+ (pict_struct!=FRAME_PICTURE && mbinfo[k].motion_type==MC_16X8)))
+ fprintf(statfile,"%4d",mbinfo[k].MV[1][1][1]);
+ else
+ fprintf(statfile," .");
+
+ k++;
+ }
+ putc('\n',statfile);
+ }
+
+
+ }
+#endif
+
+#if 0
+ /* useful for debugging */
+ fprintf(statfile,"\nmacroblock info dump:\n");
+
+ k=0;
+ for (j=0; j<mb_height2; j++)
+ {
+ for (i=0; i<mb_width; i++)
+ {
+ fprintf(statfile,"%d: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
+ k,
+ mbinfo[k].mb_type,
+ mbinfo[k].motion_type,
+ mbinfo[k].dct_type,
+ mbinfo[k].mquant,
+ mbinfo[k].cbp,
+ mbinfo[k].skipped,
+ mbinfo[k].MV[0][0][0],
+ mbinfo[k].MV[0][0][1],
+ mbinfo[k].MV[0][1][0],
+ mbinfo[k].MV[0][1][1],
+ mbinfo[k].MV[1][0][0],
+ mbinfo[k].MV[1][0][1],
+ mbinfo[k].MV[1][1][0],
+ mbinfo[k].MV[1][1][1],
+ mbinfo[k].mv_field_sel[0][0],
+ mbinfo[k].mv_field_sel[0][1],
+ mbinfo[k].mv_field_sel[1][0],
+ mbinfo[k].mv_field_sel[1][1]);
+
+ k++;
+ }
+ }
+#endif
+}
--- /dev/null
+/* transfrm.c, forward / inverse transformation */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include "config.h"
+#include "global.h"
+
+/* private prototypes*/
+static void add_pred _ANSI_ARGS_((unsigned char *pred, unsigned char *cur,
+ int lx, short *blk));
+static void sub_pred _ANSI_ARGS_((unsigned char *pred, unsigned char *cur,
+ int lx, short *blk));
+
+/* subtract prediction and transform prediction error */
+void transform(pred,cur,mbi,blocks)
+unsigned char *pred[], *cur[];
+struct mbinfo *mbi;
+short blocks[][64];
+{
+ int i, j, i1, j1, k, n, cc, offs, lx;
+
+ k = 0;
+
+ for (j=0; j<height2; j+=16)
+ for (i=0; i<width; i+=16)
+ {
+ for (n=0; n<block_count; n++)
+ {
+ cc = (n<4) ? 0 : (n&1)+1; /* color component index */
+ if (cc==0)
+ {
+ /* luminance */
+ if ((pict_struct==FRAME_PICTURE) && mbi[k].dct_type)
+ {
+ /* field DCT */
+ offs = i + ((n&1)<<3) + width*(j+((n&2)>>1));
+ lx = width<<1;
+ }
+ else
+ {
+ /* frame DCT */
+ offs = i + ((n&1)<<3) + width2*(j+((n&2)<<2));
+ lx = width2;
+ }
+
+ if (pict_struct==BOTTOM_FIELD)
+ offs += width;
+ }
+ else
+ {
+ /* chrominance */
+
+ /* scale coordinates */
+ i1 = (chroma_format==CHROMA444) ? i : i>>1;
+ j1 = (chroma_format!=CHROMA420) ? j : j>>1;
+
+ if ((pict_struct==FRAME_PICTURE) && mbi[k].dct_type
+ && (chroma_format!=CHROMA420))
+ {
+ /* field DCT */
+ offs = i1 + (n&8) + chrom_width*(j1+((n&2)>>1));
+ lx = chrom_width<<1;
+ }
+ else
+ {
+ /* frame DCT */
+ offs = i1 + (n&8) + chrom_width2*(j1+((n&2)<<2));
+ lx = chrom_width2;
+ }
+
+ if (pict_struct==BOTTOM_FIELD)
+ offs += chrom_width;
+ }
+
+ sub_pred(pred[cc]+offs,cur[cc]+offs,lx,blocks[k*block_count+n]);
+ fdct(blocks[k*block_count+n]);
+ }
+
+ k++;
+ }
+}
+
+/* inverse transform prediction error and add prediction */
+void itransform(pred,cur,mbi,blocks)
+unsigned char *pred[],*cur[];
+struct mbinfo *mbi;
+short blocks[][64];
+{
+ int i, j, i1, j1, k, n, cc, offs, lx;
+
+ k = 0;
+
+ for (j=0; j<height2; j+=16)
+ for (i=0; i<width; i+=16)
+ {
+ for (n=0; n<block_count; n++)
+ {
+ cc = (n<4) ? 0 : (n&1)+1; /* color component index */
+
+ if (cc==0)
+ {
+ /* luminance */
+ if ((pict_struct==FRAME_PICTURE) && mbi[k].dct_type)
+ {
+ /* field DCT */
+ offs = i + ((n&1)<<3) + width*(j+((n&2)>>1));
+ lx = width<<1;
+ }
+ else
+ {
+ /* frame DCT */
+ offs = i + ((n&1)<<3) + width2*(j+((n&2)<<2));
+ lx = width2;
+ }
+
+ if (pict_struct==BOTTOM_FIELD)
+ offs += width;
+ }
+ else
+ {
+ /* chrominance */
+
+ /* scale coordinates */
+ i1 = (chroma_format==CHROMA444) ? i : i>>1;
+ j1 = (chroma_format!=CHROMA420) ? j : j>>1;
+
+ if ((pict_struct==FRAME_PICTURE) && mbi[k].dct_type
+ && (chroma_format!=CHROMA420))
+ {
+ /* field DCT */
+ offs = i1 + (n&8) + chrom_width*(j1+((n&2)>>1));
+ lx = chrom_width<<1;
+ }
+ else
+ {
+ /* frame DCT */
+ offs = i1 + (n&8) + chrom_width2*(j1+((n&2)<<2));
+ lx = chrom_width2;
+ }
+
+ if (pict_struct==BOTTOM_FIELD)
+ offs += chrom_width;
+ }
+
+ idct(blocks[k*block_count+n]);
+ add_pred(pred[cc]+offs,cur[cc]+offs,lx,blocks[k*block_count+n]);
+ }
+
+ k++;
+ }
+}
+
+/* add prediction and prediction error, saturate to 0...255 */
+static void add_pred(pred,cur,lx,blk)
+unsigned char *pred, *cur;
+int lx;
+short *blk;
+{
+ int i, j;
+
+ for (j=0; j<8; j++)
+ {
+ for (i=0; i<8; i++)
+ cur[i] = clp[blk[i] + pred[i]];
+ blk+= 8;
+ cur+= lx;
+ pred+= lx;
+ }
+}
+
+/* subtract prediction from block data */
+static void sub_pred(pred,cur,lx,blk)
+unsigned char *pred, *cur;
+int lx;
+short *blk;
+{
+ int i, j;
+
+ for (j=0; j<8; j++)
+ {
+ for (i=0; i<8; i++)
+ blk[i] = cur[i] - pred[i];
+ blk+= 8;
+ cur+= lx;
+ pred+= lx;
+ }
+}
+
+/*
+ * select between frame and field DCT
+ *
+ * preliminary version: based on inter-field correlation
+ */
+void dct_type_estimation(pred,cur,mbi)
+unsigned char *pred,*cur;
+struct mbinfo *mbi;
+{
+ short blk0[128], blk1[128];
+ int i, j, i0, j0, k, offs, s0, s1, sq0, sq1, s01;
+ double d, r;
+
+ k = 0;
+
+ for (j0=0; j0<height2; j0+=16)
+ for (i0=0; i0<width; i0+=16)
+ {
+ if (frame_pred_dct || pict_struct!=FRAME_PICTURE)
+ mbi[k].dct_type = 0;
+ else
+ {
+ /* interlaced frame picture */
+ /*
+ * calculate prediction error (cur-pred) for top (blk0)
+ * and bottom field (blk1)
+ */
+ for (j=0; j<8; j++)
+ {
+ offs = width*((j<<1)+j0) + i0;
+ for (i=0; i<16; i++)
+ {
+ blk0[16*j+i] = cur[offs] - pred[offs];
+ blk1[16*j+i] = cur[offs+width] - pred[offs+width];
+ offs++;
+ }
+ }
+ /* correlate fields */
+ s0=s1=sq0=sq1=s01=0;
+
+ for (i=0; i<128; i++)
+ {
+ s0+= blk0[i];
+ sq0+= blk0[i]*blk0[i];
+ s1+= blk1[i];
+ sq1+= blk1[i]*blk1[i];
+ s01+= blk0[i]*blk1[i];
+ }
+
+ d = (sq0-(s0*s0)/128.0)*(sq1-(s1*s1)/128.0);
+
+ if (d>0.0)
+ {
+ r = (s01-(s0*s1)/128.0)/sqrt(d);
+ if (r>0.5)
+ mbi[k].dct_type = 0; /* frame DCT */
+ else
+ mbi[k].dct_type = 1; /* field DCT */
+ }
+ else
+ mbi[k].dct_type = 1; /* field DCT */
+ }
+ k++;
+ }
+}
--- /dev/null
+/* vlc.h, variable length code tables (used by routines in putvlc.c) */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+/* type definitions for variable length code table entries */
+
+typedef struct
+{
+ unsigned char code; /* right justified */
+ char len;
+} VLCtable;
+
+/* for codes longer than 8 bits (excluding leading zeroes) */
+typedef struct
+{
+ unsigned short code; /* right justified */
+ char len;
+} sVLCtable;
+
+
+/* data from ISO/IEC 13818-2 DIS, Annex B, variable length code tables */
+
+/* Table B-1, variable length codes for macroblock_address_increment
+ *
+ * indexed by [macroblock_address_increment-1]
+ * 'macroblock_escape' is treated elsewhere
+ */
+
+static VLCtable addrinctab[33]=
+{
+ {0x01,1}, {0x03,3}, {0x02,3}, {0x03,4},
+ {0x02,4}, {0x03,5}, {0x02,5}, {0x07,7},
+ {0x06,7}, {0x0b,8}, {0x0a,8}, {0x09,8},
+ {0x08,8}, {0x07,8}, {0x06,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}
+};
+
+
+/* Table B-2, B-3, B-4 variable length codes for macroblock_type
+ *
+ * indexed by [macroblock_type]
+ */
+
+static VLCtable mbtypetab[3][32]=
+{
+ /* I */
+ {
+ {0,0}, {1,1}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
+ {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
+ {0,0}, {1,2}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
+ {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}
+ },
+ /* P */
+ {
+ {0,0}, {3,5}, {1,2}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
+ {1,3}, {0,0}, {1,1}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
+ {0,0}, {1,6}, {1,5}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
+ {0,0}, {0,0}, {2,5}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}
+ },
+ /* B */
+ {
+ {0,0}, {3,5}, {0,0}, {0,0}, {2,3}, {0,0}, {3,3}, {0,0},
+ {2,4}, {0,0}, {3,4}, {0,0}, {2,2}, {0,0}, {3,2}, {0,0},
+ {0,0}, {1,6}, {0,0}, {0,0}, {0,0}, {0,0}, {2,6}, {0,0},
+ {0,0}, {0,0}, {3,6}, {0,0}, {0,0}, {0,0}, {2,5}, {0,0}
+ }
+};
+
+
+/* Table B-5 ... B-8 variable length codes for macroblock_type in
+ * scalable sequences
+ *
+ * not implemented
+ */
+
+/* Table B-9, variable length codes for coded_block_pattern
+ *
+ * indexed by [coded_block_pattern]
+ */
+
+static VLCtable cbptable[64]=
+{
+ {0x01,9}, {0x0b,5}, {0x09,5}, {0x0d,6},
+ {0x0d,4}, {0x17,7}, {0x13,7}, {0x1f,8},
+ {0x0c,4}, {0x16,7}, {0x12,7}, {0x1e,8},
+ {0x13,5}, {0x1b,8}, {0x17,8}, {0x13,8},
+ {0x0b,4}, {0x15,7}, {0x11,7}, {0x1d,8},
+ {0x11,5}, {0x19,8}, {0x15,8}, {0x11,8},
+ {0x0f,6}, {0x0f,8}, {0x0d,8}, {0x03,9},
+ {0x0f,5}, {0x0b,8}, {0x07,8}, {0x07,9},
+ {0x0a,4}, {0x14,7}, {0x10,7}, {0x1c,8},
+ {0x0e,6}, {0x0e,8}, {0x0c,8}, {0x02,9},
+ {0x10,5}, {0x18,8}, {0x14,8}, {0x10,8},
+ {0x0e,5}, {0x0a,8}, {0x06,8}, {0x06,9},
+ {0x12,5}, {0x1a,8}, {0x16,8}, {0x12,8},
+ {0x0d,5}, {0x09,8}, {0x05,8}, {0x05,9},
+ {0x0c,5}, {0x08,8}, {0x04,8}, {0x04,9},
+ {0x07,3}, {0x0a,5}, {0x08,5}, {0x0c,6}
+};
+
+
+/* Table B-10, variable length codes for motion_code
+ *
+ * indexed by [abs(motion_code)]
+ * sign of motion_code is treated elsewhere
+ */
+
+static VLCtable motionvectab[17]=
+{
+ {0x01,1}, {0x01,2}, {0x01,3}, {0x01,4},
+ {0x03,6}, {0x05,7}, {0x04,7}, {0x03,7},
+ {0x0b,9}, {0x0a,9}, {0x09,9}, {0x11,10},
+ {0x10,10}, {0x0f,10}, {0x0e,10}, {0x0d,10},
+ {0x0c,10}
+};
+
+
+/* Table B-11, variable length codes for dmvector
+ *
+ * treated elsewhere
+ */
+
+/* Table B-12, variable length codes for dct_dc_size_luminance
+ *
+ * indexed by [dct_dc_size_luminance]
+ */
+
+static sVLCtable DClumtab[12]=
+{
+ {0x0004,3}, {0x0000,2}, {0x0001,2}, {0x0005,3}, {0x0006,3}, {0x000e,4},
+ {0x001e,5}, {0x003e,6}, {0x007e,7}, {0x00fe,8}, {0x01fe,9}, {0x01ff,9}
+};
+
+
+/* Table B-13, variable length codes for dct_dc_size_chrominance
+ *
+ * indexed by [dct_dc_size_chrominance]
+ */
+
+static sVLCtable DCchromtab[12]=
+{
+ {0x0000,2}, {0x0001,2}, {0x0002,2}, {0x0006,3}, {0x000e,4}, {0x001e,5},
+ {0x003e,6}, {0x007e,7}, {0x00fe,8}, {0x01fe,9}, {0x03fe,10},{0x03ff,10}
+};
+
+
+/* Table B-14, DCT coefficients table zero
+ *
+ * indexed by [run][level-1]
+ * split into two tables (dct_code_tab1, dct_code_tab2) to reduce size
+ * 'first DCT coefficient' condition and 'End of Block' are treated elsewhere
+ * codes do not include s (sign bit)
+ */
+
+static VLCtable dct_code_tab1[2][40]=
+{
+ /* run = 0, level = 1...40 */
+ {
+ {0x03, 2}, {0x04, 4}, {0x05, 5}, {0x06, 7},
+ {0x26, 8}, {0x21, 8}, {0x0a,10}, {0x1d,12},
+ {0x18,12}, {0x13,12}, {0x10,12}, {0x1a,13},
+ {0x19,13}, {0x18,13}, {0x17,13}, {0x1f,14},
+ {0x1e,14}, {0x1d,14}, {0x1c,14}, {0x1b,14},
+ {0x1a,14}, {0x19,14}, {0x18,14}, {0x17,14},
+ {0x16,14}, {0x15,14}, {0x14,14}, {0x13,14},
+ {0x12,14}, {0x11,14}, {0x10,14}, {0x18,15},
+ {0x17,15}, {0x16,15}, {0x15,15}, {0x14,15},
+ {0x13,15}, {0x12,15}, {0x11,15}, {0x10,15}
+ },
+ /* run = 1, level = 1...18 */
+ {
+ {0x03, 3}, {0x06, 6}, {0x25, 8}, {0x0c,10},
+ {0x1b,12}, {0x16,13}, {0x15,13}, {0x1f,15},
+ {0x1e,15}, {0x1d,15}, {0x1c,15}, {0x1b,15},
+ {0x1a,15}, {0x19,15}, {0x13,16}, {0x12,16},
+ {0x11,16}, {0x10,16}, {0x00, 0}, {0x00, 0},
+ {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
+ {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
+ {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
+ {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
+ {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+ }
+};
+
+static VLCtable dct_code_tab2[30][5]=
+{
+ /* run = 2...31, level = 1...5 */
+ {{0x05, 4}, {0x04, 7}, {0x0b,10}, {0x14,12}, {0x14,13}},
+ {{0x07, 5}, {0x24, 8}, {0x1c,12}, {0x13,13}, {0x00, 0}},
+ {{0x06, 5}, {0x0f,10}, {0x12,12}, {0x00, 0}, {0x00, 0}},
+ {{0x07, 6}, {0x09,10}, {0x12,13}, {0x00, 0}, {0x00, 0}},
+ {{0x05, 6}, {0x1e,12}, {0x14,16}, {0x00, 0}, {0x00, 0}},
+ {{0x04, 6}, {0x15,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x07, 7}, {0x11,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x05, 7}, {0x11,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x27, 8}, {0x10,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x23, 8}, {0x1a,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x22, 8}, {0x19,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x20, 8}, {0x18,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x0e,10}, {0x17,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x0d,10}, {0x16,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x08,10}, {0x15,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1f,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1a,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x19,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x17,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x16,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1f,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1e,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1d,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1c,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1b,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1f,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1e,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1d,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1c,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1b,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}
+};
+
+
+/* Table B-15, DCT coefficients table one
+ *
+ * indexed by [run][level-1]
+ * split into two tables (dct_code_tab1a, dct_code_tab2a) to reduce size
+ * 'End of Block' is treated elsewhere
+ * codes do not include s (sign bit)
+ */
+
+static VLCtable dct_code_tab1a[2][40]=
+{
+ /* run = 0, level = 1...40 */
+ {
+ {0x02, 2}, {0x06, 3}, {0x07, 4}, {0x1c, 5},
+ {0x1d, 5}, {0x05, 6}, {0x04, 6}, {0x7b, 7},
+ {0x7c, 7}, {0x23, 8}, {0x22, 8}, {0xfa, 8},
+ {0xfb, 8}, {0xfe, 8}, {0xff, 8}, {0x1f,14},
+ {0x1e,14}, {0x1d,14}, {0x1c,14}, {0x1b,14},
+ {0x1a,14}, {0x19,14}, {0x18,14}, {0x17,14},
+ {0x16,14}, {0x15,14}, {0x14,14}, {0x13,14},
+ {0x12,14}, {0x11,14}, {0x10,14}, {0x18,15},
+ {0x17,15}, {0x16,15}, {0x15,15}, {0x14,15},
+ {0x13,15}, {0x12,15}, {0x11,15}, {0x10,15}
+ },
+ /* run = 1, level = 1...18 */
+ {
+ {0x02, 3}, {0x06, 5}, {0x79, 7}, {0x27, 8},
+ {0x20, 8}, {0x16,13}, {0x15,13}, {0x1f,15},
+ {0x1e,15}, {0x1d,15}, {0x1c,15}, {0x1b,15},
+ {0x1a,15}, {0x19,15}, {0x13,16}, {0x12,16},
+ {0x11,16}, {0x10,16}, {0x00, 0}, {0x00, 0},
+ {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
+ {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
+ {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
+ {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
+ {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+ }
+};
+
+static VLCtable dct_code_tab2a[30][5]=
+{
+ /* run = 2...31, level = 1...5 */
+ {{0x05, 5}, {0x07, 7}, {0xfc, 8}, {0x0c,10}, {0x14,13}},
+ {{0x07, 5}, {0x26, 8}, {0x1c,12}, {0x13,13}, {0x00, 0}},
+ {{0x06, 6}, {0xfd, 8}, {0x12,12}, {0x00, 0}, {0x00, 0}},
+ {{0x07, 6}, {0x04, 9}, {0x12,13}, {0x00, 0}, {0x00, 0}},
+ {{0x06, 7}, {0x1e,12}, {0x14,16}, {0x00, 0}, {0x00, 0}},
+ {{0x04, 7}, {0x15,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x05, 7}, {0x11,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x78, 7}, {0x11,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x7a, 7}, {0x10,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x21, 8}, {0x1a,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x25, 8}, {0x19,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x24, 8}, {0x18,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x05, 9}, {0x17,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x07, 9}, {0x16,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x0d,10}, {0x15,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1f,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1a,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x19,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x17,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x16,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1f,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1e,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1d,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1c,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1b,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1f,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1e,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1d,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1c,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
+ {{0x1b,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}
+};
--- /dev/null
+/* writepic.c, write reconstructed pictures */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "config.h"
+#include "global.h"
+
+void writeframe(fname,frame)
+char *fname;
+unsigned char *frame[];
+{
+ int chrom_hsize, chrom_vsize;
+ char name[128];
+ FILE *fd;
+
+ chrom_hsize = (chroma_format==CHROMA444) ? horizontal_size
+ : horizontal_size>>1;
+
+ chrom_vsize = (chroma_format!=CHROMA420) ? vertical_size
+ : vertical_size>>1;
+
+ if (fname[0]=='-')
+ return;
+
+ /* Y */
+ sprintf(name,"%s.Y",fname);
+ if (!(fd = fopen(name,"wb")))
+ {
+ sprintf(errortext,"Couldn't create %s\n",name);
+ error(errortext);
+ }
+ fwrite(frame[0],1,horizontal_size*vertical_size,fd);
+ fclose(fd);
+
+ /* Cb */
+ sprintf(name,"%s.U",fname);
+ if (!(fd = fopen(name,"wb")))
+ {
+ sprintf(errortext,"Couldn't create %s\n",name);
+ error(errortext);
+ }
+ fwrite(frame[1],1,chrom_hsize*chrom_vsize,fd);
+ fclose(fd);
+
+ /* Cr */
+ sprintf(name,"%s.V",fname);
+ if (!(fd = fopen(name,"wb")))
+ {
+ sprintf(errortext,"Couldn't create %s\n",name);
+ error(errortext);
+ }
+ fwrite(frame[2],1,chrom_hsize*chrom_vsize,fd);
+ fclose(fd);
+}