about summary refs log tree commit diff
path: root/converter/ppm/ppmtompeg/headers/frames.h
blob: 3fefaea777a3def855e00b449ac8aeb6bccafa1c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
/*===========================================================================*
 * frames.h                                  
 *                                       
 *  stuff dealing with frames                        
 *                                       
 *===========================================================================*/

#ifndef FRAMES_INCLUDED
#define FRAMES_INCLUDED

/*==============*
 * HEADER FILES *
 *==============*/

#include "ansi.h"
#include "mtypes.h"
#include "mheaders.h"
#include "frame.h"


/*===========*
 * CONSTANTS *
 *===========*/

#define I_FRAME 1
#define P_FRAME 2
#define B_FRAME 3

#define LUM_BLOCK   0
#define CHROM_BLOCK 1
#define CR_BLOCK    2
#define CB_BLOCK    3

#define MOTION_FORWARD      0
#define MOTION_BACKWARD     1
#define MOTION_INTERPOLATE  2


#define USE_HALF    0
#define USE_FULL    1

    /* motion vector stuff */
#define FORW_F_CODE fCode       /* from picture header */
#define BACK_F_CODE fCode
#define FORW_F  (1 << (FORW_F_CODE - 1))
#define BACK_F  (1 << (BACK_F_CODE - 1))
#define RANGE_NEG   (-(1 << (3 + FORW_F_CODE)))
#define RANGE_POS   ((1 << (3 + FORW_F_CODE))-1)
#define MODULUS     (1 << (4 + FORW_F_CODE))

#define ORIGINAL_FRAME  0
#define DECODED_FRAME   1


/*=======================*
 * STRUCTURE DEFINITIONS *
 *=======================*/

typedef struct FrameTableStruct {
    /* the following are all initted once and never changed */
    /* (they depend only on the pattern */
    char typ;
    struct FrameTableStruct *next;
    struct FrameTableStruct *prev;

    /* nextOutput is a pointer to next frame table entry to output */
    struct FrameTableStruct *nextOutput;

    boolean freeNow;    /* TRUE iff no frames point back to this */

    int number;

    int bFrameNumber;       /* actual frame number, if a b-frame */
    
} FrameTable;


/*==================*
 * TYPE DEFINITIONS *
 *==================*/

typedef struct dct_data_tye_struct {
  char useMotion;
  char pattern, mode;
  int fmotionX, fmotionY, bmotionX, bmotionY;
} dct_data_type;

void    EncodeYDC _ANSI_ARGS_((int32 dc_term, int32 *pred_term, BitBucket *bb));
void
EncodeCDC(int32       const dc_term,
          int32     * const pred_term,
          BitBucket * const bb);


/*========*
 * MACROS *
 *========*/

/* return ceiling(a/b) where a, b are ints, using temp value c */
#define int_ceil_div(a,b,c)     ((b*(c = a/b) < a) ? (c+1) : c)
#define int_floor_div(a,b,c)    ((b*(c = a/b) > a) ? (c-1) : c)

/* assumes many things:
 * block indices are (y,x)
 * variables y_dc_pred, cr_dc_pred, and cb_dc_pred
 * flat block fb exists
 */
#define GEN_I_BLOCK(frameType, frame, bb, mbAI, qscale) {                   \
    boolean overflow, overflowChange=FALSE;                             \
        int overflowValue = 0;                                              \
        do {                                                                \
      overflow =  Mpost_QuantZigBlock(dct[y][x], fb[0],                 \
             qscale, TRUE)==MPOST_OVERFLOW;                     \
          overflow |= Mpost_QuantZigBlock(dct[y][x+1], fb[1],               \
                 qscale, TRUE)==MPOST_OVERFLOW;                     \
      overflow |= Mpost_QuantZigBlock(dct[y+1][x], fb[2],               \
                         qscale, TRUE)==MPOST_OVERFLOW;                     \
      overflow |= Mpost_QuantZigBlock(dct[y+1][x+1], fb[3],             \
                         qscale, TRUE)==MPOST_OVERFLOW;                     \
      overflow |= Mpost_QuantZigBlock(dctb[y >> 1][x >> 1],             \
                         fb[4], qscale, TRUE)==MPOST_OVERFLOW;              \
      overflow |= Mpost_QuantZigBlock(dctr[y >> 1][x >> 1],             \
             fb[5], qscale, TRUE)==MPOST_OVERFLOW;              \
          if ((overflow) && (qscale!=31)) {                                 \
           overflowChange = TRUE; overflowValue++;                          \
       qscale++;                                                        \
       } else overflow = FALSE;                                         \
    } while (overflow);                                                 \
        Mhead_GenMBHeader(bb,                           \
            frameType /* pict_code_type */, mbAI /* addr_incr */,   \
            qscale /* q_scale */,                               \
            0 /* forw_f_code */, 0 /* back_f_code */,           \
            0 /* horiz_forw_r */, 0 /* vert_forw_r */,          \
            0 /* horiz_back_r */, 0 /* vert_back_r */,          \
            0 /* motion_forw */, 0 /* m_horiz_forw */,          \
            0 /* m_vert_forw */, 0 /* motion_back */,           \
            0 /* m_horiz_back */, 0 /* m_vert_back */,          \
            0 /* mb_pattern */, TRUE /* mb_intra */);           \
                                        \
    /* Y blocks */                              \
        EncodeYDC(fb[0][0], &y_dc_pred, bb);                            \
    Mpost_RLEHuffIBlock(fb[0], bb);                         \
    EncodeYDC(fb[1][0], &y_dc_pred, bb);                        \
        Mpost_RLEHuffIBlock(fb[1], bb);                             \
    EncodeYDC(fb[2][0], &y_dc_pred, bb);                        \
    Mpost_RLEHuffIBlock(fb[2], bb);                         \
    EncodeYDC(fb[3][0], &y_dc_pred, bb);                        \
    Mpost_RLEHuffIBlock(fb[3], bb);                         \
                                        \
    /* CB block */                              \
    EncodeCDC(fb[4][0], &cb_dc_pred, bb);                   \
    Mpost_RLEHuffIBlock(fb[4], bb);                     \
                                        \
    /* CR block */                              \
    EncodeCDC(fb[5][0], &cr_dc_pred, bb);                   \
    Mpost_RLEHuffIBlock(fb[5], bb);                     \
    if (overflowChange) qscale -= overflowValue;                        \
    }

#define BLOCK_TO_FRAME_COORD(bx1, bx2, x1, x2) {    \
    x1 = (bx1)*DCTSIZE;             \
    x2 = (bx2)*DCTSIZE;             \
    }

static __inline__ void
MotionToFrameCoord(int   const by,
                   int   const bx,
                   int   const my,
                   int   const mx,
                   int * const yP,
                   int * const xP) {
/*----------------------------------------------------------------------------
   Given a DCT block location and a motion vector, return the pixel
   coordinates to which the upper left corner of the block moves.

   Return negative coordinates if it moves out of frame.
-----------------------------------------------------------------------------*/
    *yP = by * DCTSIZE + my;
    *xP = bx * DCTSIZE + mx;
}

#define COORD_IN_FRAME(fy,fx, type)                 \
    ((type == LUM_BLOCK) ?                      \
     ((fy >= 0) && (fx >= 0) && (fy < Fsize_y) && (fx < Fsize_x)) : \
     ((fy >= 0) && (fx >= 0) && (fy < (Fsize_y>>1)) && (fx < (Fsize_x>>1))))


static __inline__ void
encodeMotionVector(int      const x,
                   int      const y,
                   vector * const qP,
                   vector * const rP,
                   int      const f,
                   int      const fCode) {

    int tempX;
    int tempY;
    int tempC;

    if (x < RANGE_NEG)
        tempX = x + MODULUS;
    else if (x > RANGE_POS)
        tempX = x - MODULUS;
    else
        tempX = x;

    if (y < RANGE_NEG)
        tempY = y + MODULUS;
    else if (y > RANGE_POS)
        tempY = y - MODULUS;
    else
        tempY = y;

    if (tempX >= 0) {
        qP->x = int_ceil_div(tempX, f, tempC);
        rP->x = f - 1 + tempX - qP->x*f;
    } else {
        qP->x = int_floor_div(tempX, f, tempC);
        rP->x = f - 1 - tempX + qP->x*f;
    }

    if (tempY >= 0) {
        qP->y = int_ceil_div(tempY, f, tempC);
        rP->y = f - 1 + tempY - qP->y*f;
    } else {
        qP->y = int_floor_div(tempY, f, tempC);
        rP->y = f - 1 - tempY + qP->y*f;
    }
}


#define DoQuant(bit, src, dest)                                         \
  if (pattern & bit) {                                                  \
    switch (Mpost_QuantZigBlock(src, dest, QScale, FALSE)) {            \
    case MPOST_NON_ZERO:                                                \
      break;                                                            \
    case MPOST_ZERO:                                                    \
      pattern ^= bit;                                                   \
      break;                                                            \
    case MPOST_OVERFLOW:                                                \
      if (QScale != 31) {                                               \
    QScale++;                                                       \
    overflowChange = TRUE;                                          \
    overflowValue++;                                                \
    goto calc_blocks;                                               \
      }                                                                 \
      break;                                                            \
    }                                                                   \
  }

/*===============================*
 * EXTERNAL PROCEDURE prototypes *
 *===============================*/

void
ComputeBMotionLumBlock(MpegFrame * const prev,
                       MpegFrame * const next,
                       int         const by,
                       int         const bx,
                       int         const mode,
                       motion      const motion,
                       LumBlock *  const motionBlockP);

int
BMotionSearch(const LumBlock * const currentBlockP,
              MpegFrame *      const prev,
              MpegFrame *      const next,
              int              const by,
              int              const bx,
              motion *         const motionP,
              int              const oldMode);

void GenIFrame (BitBucket * const bb,
                MpegFrame * const mf);
void GenPFrame (BitBucket * const bb,
                MpegFrame * const current,
                MpegFrame * const prev);
void GenBFrame (BitBucket * const bb,
                MpegFrame * const curr,
                MpegFrame * const prev,
                MpegFrame * const next);
void    AllocDctBlocks _ANSI_ARGS_((void ));


float
IFrameTotalTime(void);

float
PFrameTotalTime(void);

float
BFrameTotalTime(void);

void
ShowIFrameSummary(unsigned int const inputFrameBits, 
                  unsigned int const totalBits, 
                  FILE *       const fpointer);

void
ShowPFrameSummary(unsigned int const inputFrameBits, 
                  unsigned int const totalBits, 
                  FILE *       const fpointer);

void
ShowBFrameSummary(unsigned int const inputFrameBits, 
                  unsigned int const totalBits, 
                  FILE *       const fpointer);

/* DIFFERENCE FUNCTIONS */

int32
LumBlockMAD(const LumBlock * const currentBlockP,
            const LumBlock * const motionBlockP,
            int32            const bestSoFar);

int32
LumBlockMSE(const LumBlock * const currentBlockP,
            const LumBlock * const motionBlockP,
            int32            const bestSoFar);

int32
LumMotionError(const LumBlock * const currentBlockP,
               MpegFrame *      const prev,
               int              const by,
               int              const bx,
               vector           const m,
               int32            const bestSoFar);

int32
LumAddMotionError(const LumBlock * const currentBlockP,
                  const LumBlock * const blockSoFarP,
                  MpegFrame *      const prev,
                  int              const by,
                  int              const bx,
                  vector           const m,
                  int32            const bestSoFar);

int32
LumMotionErrorA(const LumBlock * const currentBlockP,
                MpegFrame *      const prevFrame,
                int              const by,
                int              const bx,
                vector           const m,
                int32            const bestSoFar);

int32
LumMotionErrorB(const LumBlock * const currentP,
                MpegFrame *      const prevFrame,
                int              const by,
                int              const bx,
                vector           const m,
                int32            const bestSoFar);

int32
LumMotionErrorC(const LumBlock * const currentP,
                MpegFrame *      const prevFrame,
                int              const by,
                int              const bx,
                vector           const m,
                int32            const bestSoFar);

int32
LumMotionErrorD(const LumBlock * const currentP,
                MpegFrame *      const prevFrame,
                int              const by,
                int              const bx,
                vector           const m,
                int32            const bestSoFar);

int32
LumMotionErrorSubSampled(const LumBlock * const currentBlockP,
                         MpegFrame *      const prevFrame,
                         int              const by,
                         int              const bx,
                         vector           const m,
                         int              const startY,
                         int              const startX);

void
BlockComputeSNR(MpegFrame * const current,
                float *     const snr,
                float *     const psnr);

int32
time_elapsed(void);

void
AllocDctBlocks(void);

/*==================*
 * GLOBAL VARIABLES *
 *==================*/

extern int pixelFullSearch;
extern int searchRangeP,searchRangeB;  /* defined in psearch.c */
extern int qscaleI;
extern int gopSize;
extern int slicesPerFrame;
extern int blocksPerSlice;
extern int referenceFrame;
extern int specificsOn;
extern int quietTime;       /* shut up for at least quietTime seconds;
                 * negative means shut up forever
                 */
extern boolean realQuiet;   /* TRUE = no messages to stdout */

extern boolean frameSummary;    /* TRUE = frame summaries should be printed */
extern boolean  printSNR;
extern boolean  printMSE;
extern boolean  decodeRefFrames;    /* TRUE = should decode I and P frames */
extern int  fCodeI,fCodeP,fCodeB;
extern boolean    forceEncodeLast;
extern int TIME_RATE;

#endif /* FRAMES_INCLUDED */


/*
 * Copyright (c) 1995 The Regents of the University of California.
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice and the following
 * two paragraphs appear in all copies of this software.
 *
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 */

/*  
 *  $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/headers/RCS/frames.h,v 1.13 1995/08/15 23:43:04 smoot Exp $
 *  $Log: frames.h,v $
 *  Revision 1.13  1995/08/15 23:43:04  smoot
 *  *** empty log message ***
 *
 * Revision 1.12  1995/04/14  23:13:18  smoot
 * Reorganized for better rate control.  Added overflow in DCT values
 * handling.
 *
 * Revision 1.11  1995/01/19  23:54:46  smoot
 * allow computediffdcts to un-assert parts of the pattern
 *
 * Revision 1.10  1995/01/16  07:43:10  eyhung
 * Added realQuiet
 *
 * Revision 1.9  1995/01/10  23:15:28  smoot
 * Fixed searchRange lack of def
 *
 * Revision 1.8  1994/11/15  00:55:36  smoot
 * added printMSE
 *
 * Revision 1.7  1994/11/14  22:51:02  smoot
 * added specifics flag.  Added BlockComputeSNR parameters
 *
 * Revision 1.6  1994/11/01  05:07:23  darryl
 *  with rate control changes added
 *
 * Revision 1.1  1994/09/27  01:02:55  darryl
 * Initial revision
 *
 * Revision 1.5  1993/07/22  22:24:23  keving
 * nothing
 *
 * Revision 1.4  1993/07/09  00:17:23  keving
 * nothing
 *
 * Revision 1.3  1993/06/03  21:08:53  keving
 * nothing
 *
 * Revision 1.2  1993/03/02  19:00:27  keving
 * nothing
 *
 * Revision 1.1  1993/02/19  20:15:51  keving
 * nothing
 *
 */