r1019: Fix crash in Ogg file handling.
[cinelerra/simeon] / mpeg2enc / putmpg.c
1 /* putmpg.c, block and motion vector encoding routines                      */
2
3 /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
4
5 /*
6  * Disclaimer of Warranty
7  *
8  * These software programs are available to the user without any license fee or
9  * royalty on an "as is" basis.  The MPEG Software Simulation Group disclaims
10  * any and all warranties, whether express, implied, or statuary, including any
11  * implied warranties or merchantability or of fitness for a particular
12  * purpose.  In no event shall the copyright-holder be liable for any
13  * incidental, punitive, or consequential damages of any kind whatsoever
14  * arising from the use of these programs.
15  *
16  * This disclaimer of warranty extends to the user of these programs and user's
17  * customers, employees, agents, transferees, successors, and assigns.
18  *
19  * The MPEG Software Simulation Group does not represent or warrant that the
20  * programs furnished hereunder are free of infringement of any third-party
21  * patents.
22  *
23  * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
24  * are subject to royalty fees to patent holders.  Many of these patents are
25  * general enough such that they are unavoidable regardless of implementation
26  * design.
27  *
28  */
29
30 #include <stdio.h>
31 #include "config.h"
32 #include "global.h"
33
34 /* generate variable length codes for an intra-coded block (6.2.6, 6.3.17) */
35 void putintrablk(slice_engine_t *engine, 
36         pict_data_s *picture, 
37         short *blk, 
38         int cc)
39 {
40         int n, dct_diff, run, signed_level;
41
42 /* DC coefficient (7.2.1) */
43         dct_diff = blk[0] - engine->dc_dct_pred[cc]; /* difference to previous block */
44         engine->dc_dct_pred[cc] = blk[0];
45
46         if(cc == 0)
47         putDClum(engine, dct_diff);
48         else
49         putDCchrom(engine, dct_diff);
50
51 /* AC coefficients (7.2.2) */
52         run = 0;
53         for(n = 1; n < 64; n++)
54         {
55 /* use appropriate entropy scanning pattern */
56         signed_level = blk[(picture->altscan ? alternate_scan_hv : mpeg2_zig_zag_scan)[n]];
57         if (signed_level!=0)
58         {
59 //printf("putintrablk 1 %d\n", picture->altscan);slice_testbits(engine);
60                 putAC(engine, run, signed_level, picture->intravlc);
61 //printf("putintrablk 2\n");slice_testbits(engine);
62                 run = 0;
63         }
64         else
65                 run++; /* count zero coefficients */
66         }
67
68 /* End of Block -- normative block punctuation */
69         if (picture->intravlc)
70         slice_putbits(engine, 6, 4); /* 0110 (Table B-15) */
71         else
72         slice_putbits(engine, 2, 2); /* 10 (Table B-14) */
73 }
74
75 /* generate variable length codes for a non-intra-coded block (6.2.6, 6.3.17) */
76 void putnonintrablk(slice_engine_t *engine, 
77         pict_data_s *picture, 
78         short *blk)
79 {
80         int n, run, signed_level, first;
81
82         run = 0;
83         first = 1;
84
85         for(n = 0; n < 64; n++)
86         {
87 /* use appropriate entropy scanning pattern */
88       signed_level = blk[(picture->altscan ? alternate_scan_hv : mpeg2_zig_zag_scan)[n]];
89
90       if (signed_level!=0)
91       {
92           if (first)
93           {
94 /* first coefficient in non-intra block */
95                   putACfirst(engine, run, signed_level);
96                   first = 0;
97           }
98           else
99                 putAC(engine, run, signed_level, 0);
100
101           run = 0;
102       }
103       else
104           run++; /* count zero coefficients */
105         }
106
107 /* End of Block -- normative block punctuation  */
108         slice_putbits(engine, 2, 2);
109 }
110
111 /* generate variable length code for a motion vector component (7.6.3.1) */
112 void putmv(slice_engine_t *engine, int dmv, int f_code)
113 {
114         int r_size, f, vmin, vmax, dv, temp, motion_code, motion_residual;
115
116         r_size = f_code - 1; /* number of fixed length code ('residual') bits */
117         f = 1 << r_size;
118         vmin = -16 * f; /* lower range limit */
119         vmax = 16 * f - 1; /* upper range limit */
120         dv = 32 * f;
121
122 /* fold vector difference into [vmin...vmax] */
123         if(dmv > vmax)
124         dmv -= dv;
125         else 
126         if(dmv < vmin)
127         dmv += dv;
128
129 /* check value */
130         if(dmv < vmin || dmv > vmax)
131         if(!quiet)
132                 fprintf(stderr,"invalid motion vector\n");
133
134 /* split dmv into motion_code and motion_residual */
135         temp = ((dmv < 0) ? -dmv : dmv) + f - 1;
136         motion_code = temp >> r_size;
137         if(dmv < 0)
138         motion_code = -motion_code;
139         motion_residual = temp & (f - 1);
140
141         putmotioncode(engine, motion_code); /* variable length code */
142
143         if (r_size != 0 && motion_code != 0)
144         slice_putbits(engine, motion_residual, r_size); /* fixed length code */
145 }