From: malaterre Date: Sat, 21 May 2005 01:27:21 +0000 (+0000) Subject: ENH: For the long long long long term adding the part of lib that encode in mpeg X-Git-Tag: Version1.2.bp~706 X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=0ec502a63fffce3a48caef921a04c5b3eb917799;p=gdcm.git ENH: For the long long long long term adding the part of lib that encode in mpeg --- diff --git a/src/gdcmmpeg2/src/mpeg2enc/CHANGES b/src/gdcmmpeg2/src/mpeg2enc/CHANGES new file mode 100644 index 00000000..bf1467d0 --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/CHANGES @@ -0,0 +1,26 @@ +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 : + + - 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. + diff --git a/src/gdcmmpeg2/src/mpeg2enc/Makefile b/src/gdcmmpeg2/src/mpeg2enc/Makefile new file mode 100644 index 00000000..9f6dd70c --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/Makefile @@ -0,0 +1,70 @@ +# 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 diff --git a/src/gdcmmpeg2/src/mpeg2enc/Makefile.wat b/src/gdcmmpeg2/src/mpeg2enc/Makefile.wat new file mode 100644 index 00000000..57238dfb --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/Makefile.wat @@ -0,0 +1,85 @@ +# 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 + diff --git a/src/gdcmmpeg2/src/mpeg2enc/TODO b/src/gdcmmpeg2/src/mpeg2enc/TODO new file mode 100644 index 00000000..acd4fad1 --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/TODO @@ -0,0 +1,10 @@ +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) + + diff --git a/src/gdcmmpeg2/src/mpeg2enc/config.h b/src/gdcmmpeg2/src/mpeg2enc/config.h new file mode 100644 index 00000000..8548f879 --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/config.h @@ -0,0 +1,37 @@ +/* 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 diff --git a/src/gdcmmpeg2/src/mpeg2enc/conform.c b/src/gdcmmpeg2/src/mpeg2enc/conform.c new file mode 100644 index 00000000..1c1ce273 --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/conform.c @@ -0,0 +1,287 @@ +/* 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 +#include + +#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_formatCHROMA444) + 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; i9) + 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 (profileSP) + error("undefined Profile"); + + if (profile==SNR || profile==SPAT) + error("This encoder currently generates no scalable bitstreams"); + + if (levelLL || 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 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"); +} diff --git a/src/gdcmmpeg2/src/mpeg2enc/fdctref.c b/src/gdcmmpeg2/src/mpeg2enc/fdctref.c new file mode 100644 index 00000000..e04981a5 --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/fdctref.c @@ -0,0 +1,100 @@ +/* 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 + +#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) + */ + } +} diff --git a/src/gdcmmpeg2/src/mpeg2enc/global.h b/src/gdcmmpeg2/src/mpeg2enc/global.h new file mode 100644 index 00000000..b50a7b2a --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/global.h @@ -0,0 +1,334 @@ +/* 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 */ diff --git a/src/gdcmmpeg2/src/mpeg2enc/idct.c b/src/gdcmmpeg2/src/mpeg2enc/idct.c new file mode 100644 index 00000000..5602ad35 --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/idct.c @@ -0,0 +1,211 @@ +/* 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); +} diff --git a/src/gdcmmpeg2/src/mpeg2enc/motion.c b/src/gdcmmpeg2/src/mpeg2enc/motion.c new file mode 100644 index 00000000..30d0a307 --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/motion.c @@ -0,0 +1,1644 @@ +/* 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 +#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; jmb_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_dpmotion_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 (dmcimb_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 (dmcfieldimb_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 (dmcfmb_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 (dmcfieldfmb_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 (dmcrmb_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_dpmotion_type = MC_DMV; + dmc = dmc_dp; /* L1 metric */ + vmc = vmc_dp; /* we already calculated L2 error for Dual */ + + } + else if (dmc8motion_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 (dmcfieldimb_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 (dmc8imb_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 (dmcfieldfmb_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 (dmc8fmb_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 (dmcfieldrmb_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 (d0); + 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= distlim) + break; + + p1+= lx; + p2+= lx; + } + else if (hx && !hy) + for (j=0; j>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>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>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>1) - p2[i]; + s+= v*v; + } + p1+= lx; + p2+= lx; + } + else if (!hx && hy) + { + p1a = p1 + lx; + for (j=0; j>1) - p2[i]; + s+= v*v; + } + p1 = p1a; + p1a+= lx; + p2+= lx; + } + } + else /* if (hx && hy) */ + { + p1a = p1 + lx; + for (j=0; j>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>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>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; +} diff --git a/src/gdcmmpeg2/src/mpeg2enc/mpeg2enc.c b/src/gdcmmpeg2/src/mpeg2enc/mpeg2enc.c new file mode 100644 index 00000000..175b0f1a --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/mpeg2enc.c @@ -0,0 +1,558 @@ +/* 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 +#include + +#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 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; i4) + { + 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 (4< (4< (4< (4<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); + } +} diff --git a/src/gdcmmpeg2/src/mpeg2enc/mpeg2enc.h b/src/gdcmmpeg2/src/mpeg2enc/mpeg2enc.h new file mode 100644 index 00000000..d2402e8f --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/mpeg2enc.h @@ -0,0 +1,112 @@ +/* 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; +}; diff --git a/src/gdcmmpeg2/src/mpeg2enc/predict.c b/src/gdcmmpeg2/src/mpeg2enc/predict.c new file mode 100644 index 00000000..8faf8daa --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/predict.c @@ -0,0 +1,589 @@ +/* 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 +#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>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>1; + s+= lx; + d+= lx; + } + else + for (j=0; j>1)+1)>>1; + s+= lx; + d+= lx; + } + else + for (j=0; j>1; + s+= lx; + d+= lx; + } + else if (xh && !yh) + if (addflag) + for (j=0; j>1)+1)>>1; + s+= lx; + d+= lx; + } + else + for (j=0; j>1; + s+= lx; + d+= lx; + } + else /* if (xh && yh) */ + if (addflag) + for (j=0; j>2)+1)>>1; + s+= lx; + d+= lx; + } + else + for (j=0; j>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 +#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>= 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); +} diff --git a/src/gdcmmpeg2/src/mpeg2enc/puthdr.c b/src/gdcmmpeg2/src/mpeg2enc/puthdr.c new file mode 100644 index 00000000..2acd159c --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/puthdr.c @@ -0,0 +1,221 @@ +/* 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 +#include +#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); +} diff --git a/src/gdcmmpeg2/src/mpeg2enc/putmpg.c b/src/gdcmmpeg2/src/mpeg2enc/putmpg.c new file mode 100644 index 00000000..34889ac3 --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/putmpg.c @@ -0,0 +1,141 @@ +/* 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 +#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<vmax) + dmv-= dv; + else if (dmvvmax) + 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 */ +} diff --git a/src/gdcmmpeg2/src/mpeg2enc/putpic.c b/src/gdcmmpeg2/src/mpeg2enc/putpic.c new file mode 100644 index 00000000..8fb7d952 --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/putpic.c @@ -0,0 +1,376 @@ +/* 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 +#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>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 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>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]; + } + } +} diff --git a/src/gdcmmpeg2/src/mpeg2enc/putseq.c b/src/gdcmmpeg2/src/mpeg2enc/putseq.c new file mode 100644 index 00000000..d41387a7 --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/putseq.c @@ -0,0 +1,324 @@ +/* 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 +#include +#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) + 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< + +#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<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); +} diff --git a/src/gdcmmpeg2/src/mpeg2enc/quantize.c b/src/gdcmmpeg2/src/mpeg2enc/quantize.c new file mode 100644 index 00000000..4afeafbc --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/quantize.c @@ -0,0 +1,220 @@ +/* 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 +#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); + } +} diff --git a/src/gdcmmpeg2/src/mpeg2enc/ratectl.c b/src/gdcmmpeg2/src/mpeg2enc/ratectl.c new file mode 100644 index 00000000..28c3e53a --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/ratectl.c @@ -0,0 +1,519 @@ +/* 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 +#include + +#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 (T112) + 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; + } +} diff --git a/src/gdcmmpeg2/src/mpeg2enc/readpic.c b/src/gdcmmpeg2/src/mpeg2enc/readpic.c new file mode 100644 index 00000000..3247e670 --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/readpic.c @@ -0,0 +1,494 @@ +/* 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 +#include +#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>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; i8) + 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>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>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>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>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>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; +} diff --git a/src/gdcmmpeg2/src/mpeg2enc/stats.c b/src/gdcmmpeg2/src/mpeg2enc/stats.c new file mode 100644 index 00000000..00616555 --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/stats.c @@ -0,0 +1,446 @@ +/* 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 +#include +#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; jskipped) + n_skipped++; + else if (mbi->mb_type & MB_INTRA) + n_intra++; + else if (!(mbi->mb_type & MB_PATTERN)) + n_ncoded++; + + for (i=0; icbp & (1<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; jmb_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 +#include +#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>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>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; j00.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++; + } +} diff --git a/src/gdcmmpeg2/src/mpeg2enc/vlc.h b/src/gdcmmpeg2/src/mpeg2enc/vlc.h new file mode 100644 index 00000000..284bb155 --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/vlc.h @@ -0,0 +1,321 @@ +/* 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}} +}; diff --git a/src/gdcmmpeg2/src/mpeg2enc/writepic.c b/src/gdcmmpeg2/src/mpeg2enc/writepic.c new file mode 100644 index 00000000..59140341 --- /dev/null +++ b/src/gdcmmpeg2/src/mpeg2enc/writepic.c @@ -0,0 +1,81 @@ +/* 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 +#include +#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); +}