~ubuntu-branches/ubuntu/hoary/kdemultimedia/hoary

« back to all changes in this revision

Viewing changes to mpeglib/lib/mpegplay/macroBlock.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Martin Schulze
  • Date: 2003-01-22 15:00:51 UTC
  • Revision ID: james.westby@ubuntu.com-20030122150051-uihwkdoxf15mi1tn
Tags: upstream-2.2.2
ImportĀ upstreamĀ versionĀ 2.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  stores macroblock infos
 
3
  Copyright (C) 2000  Martin Vogt
 
4
 
 
5
  This program is free software; you can redistribute it and/or modify
 
6
  it under the terms of the GNU Library General Public License as published by
 
7
  the Free Software Foundation.
 
8
 
 
9
  For more information look at the file COPYRIGHT in this package
 
10
 
 
11
 */
 
12
 
 
13
 
 
14
#include "macroBlock.h"
 
15
 
 
16
#define DEBUG_MACROBLOCK(x)
 
17
//#define DEBUG_MACROBLOCK(x) x
 
18
 
 
19
 
 
20
 
 
21
MacroBlock::MacroBlock(VideoDecoder* vid_stream) {
 
22
  this->vid_stream=vid_stream;
 
23
  copyFunctions=new CopyFunctions();
 
24
}
 
25
 
 
26
 
 
27
MacroBlock::~MacroBlock() {
 
28
  delete copyFunctions;
 
29
}
 
30
 
 
31
 
 
32
/*
 
33
 *--------------------------------------------------------------
 
34
 *
 
35
 * ParseMacroBlock --
 
36
 *
 
37
 *      Parseoff macroblock. Reconstructs DCT values. Applies
 
38
 *      inverse DCT, reconstructs motion vectors, calculates and
 
39
 *      set pixel values for macroblock in current pict image
 
40
 *      structure.
 
41
 *
 
42
 * Results:
 
43
 *      Here's where everything really happens. Welcome to the
 
44
 *      heart of darkness.
 
45
 *
 
46
 * Side effects:
 
47
 *      Bit stream irreversibly parsed off.
 
48
 *
 
49
 *--------------------------------------------------------------
 
50
 */
 
51
 
 
52
int MacroBlock::processMacroBlock(PictureArray* pictureArray) {
 
53
    unsigned int data;
 
54
  int recon_right_for, recon_down_for, recon_right_back,
 
55
      recon_down_back;
 
56
  int mb_quant = 0, mb_motion_forw = 0, mb_motion_back = 0, 
 
57
    mb_pattern = 0;
 
58
 
 
59
  int addr_incr;
 
60
  MpegVideoStream* mpegVideoStream=vid_stream->mpegVideoStream;
 
61
  DecoderClass* decoderClass=vid_stream->decoderClass;
 
62
 
 
63
  /*
 
64
   * Parse off macroblock address increment and add to macroblock address.
 
65
   */
 
66
  do {
 
67
    addr_incr=decoderClass->decodeMBAddrInc();
 
68
    if (addr_incr==MB_ESCAPE) {
 
69
      mb_address += 33;
 
70
      addr_incr=MB_STUFFING;
 
71
    }
 
72
 
 
73
  } while (addr_incr == MB_STUFFING);
 
74
  mb_address+=addr_incr;
 
75
    
 
76
      
 
77
  
 
78
  if (mb_address > (vid_stream->mpegVideoHeader)->getMB_Size()) {
 
79
 
 
80
    DEBUG_MACROBLOCK(cout <<"ParseMacroBlock: SKIP_TO_START_CODE"<<endl;)
 
81
    DEBUG_MACROBLOCK(cout <<"mb_address "<<mb_address<<endl;)
 
82
    
 
83
    int h=(vid_stream->mpegVideoHeader)->getMB_Height();
 
84
    int w=(vid_stream->mpegVideoHeader)->getMB_Width();
 
85
    
 
86
 
 
87
    DEBUG_MACROBLOCK(cout <<"mb_height*mb_width-1:"<<(h*w - 1)<<endl;)
 
88
    return false;
 
89
  }
 
90
  
 
91
  /*
 
92
   * If macroblocks have been skipped, process skipped macroblocks.
 
93
   */
 
94
 
 
95
  int code_type=(vid_stream->picture)->getCodeType();
 
96
 
 
97
  if (mb_address - past_mb_addr > 1) {
 
98
 
 
99
    processSkippedPictures(pictureArray,code_type,
 
100
                           (vid_stream->mpegVideoHeader)->getMB_Width());
 
101
 
 
102
  }
 
103
 
 
104
 
 
105
  /* Set past macroblock address to current macroblock address. */
 
106
  past_mb_addr = mb_address;
 
107
  /* Based on picture type decode macroblock type. */
 
108
 
 
109
 
 
110
  switch (code_type) {
 
111
  case I_TYPE:
 
112
    decoderClass->decodeMBTypeI(mb_quant, mb_motion_forw, 
 
113
                                 mb_motion_back, mb_pattern,
 
114
                                 mb_intra);
 
115
    break;
 
116
 
 
117
  case P_TYPE:
 
118
    decoderClass->decodeMBTypeP(mb_quant, mb_motion_forw, 
 
119
                                mb_motion_back, mb_pattern,
 
120
                                mb_intra);
 
121
    break;
 
122
 
 
123
  case B_TYPE:
 
124
    decoderClass->decodeMBTypeB(mb_quant, mb_motion_forw, 
 
125
                                mb_motion_back, mb_pattern,
 
126
                                mb_intra);
 
127
    break;
 
128
  case D_TYPE:
 
129
    DEBUG_MACROBLOCK(cout <<"ERROR:  MPEG-1 Streams with D-frames are not supported"<<endl;)
 
130
    return false;
 
131
 
 
132
  }
 
133
  /* If quantization flag set, parse off new quantization scale. */
 
134
  if (mb_quant == true) {
 
135
    data=mpegVideoStream->getBits(5);
 
136
    (vid_stream->slice)->setQuantScale(data);
 
137
  }
 
138
  /* If forward motion vectors exist... */
 
139
 
 
140
  if (mb_motion_forw == true) {
 
141
    // Parse off and decode horizontal forward motion vector. 
 
142
    motion_h_forw_code=decoderClass->decodeMotionVectors();
 
143
 
 
144
    // If horiz. forward r data exists, parse off. 
 
145
 
 
146
    if ((vid_stream->picture->getForw_f() != 1) &&
 
147
        (motion_h_forw_code != 0)) {
 
148
      data=vid_stream->picture->geth_forw_r(mpegVideoStream);
 
149
      motion_h_forw_r = data;
 
150
    }
 
151
    // Parse off and decode vertical forward motion vector. 
 
152
    
 
153
    motion_v_forw_code=decoderClass->decodeMotionVectors();
 
154
 
 
155
    // If vert. forw. r data exists, parse off. 
 
156
 
 
157
    if ((vid_stream->picture->getForw_f() != 1) &&
 
158
        (motion_v_forw_code != 0)) {
 
159
 
 
160
      data=vid_stream->picture->getv_forw_r(mpegVideoStream);
 
161
      motion_v_forw_r = data;
 
162
    }
 
163
  }
 
164
 
 
165
  /* If back motion vectors exist... */
 
166
 
 
167
  if (mb_motion_back == true) {
 
168
    // Parse off and decode horiz. back motion vector. 
 
169
    motion_h_back_code=decoderClass->decodeMotionVectors();
 
170
 
 
171
    // If horiz. back r data exists, parse off. 
 
172
 
 
173
    if ((vid_stream->picture->getBack_f() != 1) &&
 
174
        (motion_h_back_code != 0)) {
 
175
      data=vid_stream->picture->geth_back_r(mpegVideoStream);
 
176
      motion_h_back_r = data;
 
177
    }
 
178
    // Parse off and decode vert. back motion vector. 
 
179
    motion_v_back_code=decoderClass->decodeMotionVectors();
 
180
 
 
181
    // If vert. back r data exists, parse off. 
 
182
 
 
183
    if ((vid_stream->picture->getBack_f() != 1) &&
 
184
        (motion_v_back_code != 0)) {
 
185
      data=vid_stream->picture->getv_back_r(mpegVideoStream);
 
186
      motion_v_back_r = data;
 
187
    }
 
188
  }
 
189
 
 
190
  /* If mblock pattern flag set, parse and decode CBP (code block pattern). */
 
191
  if (mb_pattern == true) {
 
192
    cbp=decoderClass->decodeCBP();
 
193
  }
 
194
  /* Otherwise, set CBP to zero. */
 
195
  else
 
196
    cbp = 0;
 
197
 
 
198
 
 
199
 
 
200
  /* Reconstruct motion vectors depending on picture type. */
 
201
  if (code_type == P_TYPE) {
 
202
 
 
203
    /*
 
204
     * If no forw motion vectors, reset previous and current vectors to 0.
 
205
     */
 
206
    if (!mb_motion_forw) {
 
207
      recon_right_for = 0;
 
208
      recon_down_for = 0;
 
209
      recon_right_for_prev = 0;
 
210
      recon_down_for_prev = 0;
 
211
    }
 
212
    /*
 
213
     * Otherwise, compute new forw motion vectors. Reset previous vectors to
 
214
     * current vectors.
 
215
     */
 
216
 
 
217
    else {
 
218
      computeForwVector(&recon_right_for, &recon_down_for);
 
219
 
 
220
    }
 
221
  }
 
222
  if (code_type == B_TYPE) {
 
223
 
 
224
    /* Reset prev. and current vectors to zero if mblock is intracoded. */
 
225
    if (mb_intra) {
 
226
      recon_right_for_prev = 0;
 
227
      recon_down_for_prev = 0;
 
228
      recon_right_back_prev = 0;
 
229
      recon_down_back_prev = 0;
 
230
    } else {
 
231
      
 
232
     /* If no forw vectors, current vectors equal prev. vectors. */
 
233
      
 
234
      if (!mb_motion_forw) {
 
235
        recon_right_for = recon_right_for_prev;
 
236
        recon_down_for = recon_down_for_prev;
 
237
      }
 
238
      /*
 
239
       * Otherwise compute forw. vectors. Reset prev vectors to new values.
 
240
       */
 
241
      
 
242
      else {
 
243
        computeForwVector(&recon_right_for, &recon_down_for);
 
244
 
 
245
     }
 
246
      
 
247
      /* If no back vectors, set back vectors to prev back vectors. */
 
248
      
 
249
      if (!mb_motion_back) {
 
250
        recon_right_back = recon_right_back_prev;
 
251
        recon_down_back = recon_down_back_prev;
 
252
      }
 
253
      /* Otherwise compute new vectors and reset prev. back vectors. */
 
254
 
 
255
      else {
 
256
        computeBackVector(&recon_right_back,&recon_down_back);
 
257
 
 
258
      }
 
259
  
 
260
      /*
 
261
       * Store vector existence flags in structure for possible skipped
 
262
       * macroblocks to follow.
 
263
       */
 
264
 
 
265
      bpict_past_forw = mb_motion_forw;
 
266
      bpict_past_back = mb_motion_back;
 
267
    }
 
268
  }
 
269
  int back;
 
270
  back=reconstruct(recon_right_for,
 
271
                   recon_down_for,
 
272
                   recon_right_back,
 
273
                   recon_down_back,
 
274
                   mb_motion_forw,
 
275
                   mb_motion_back,
 
276
                   pictureArray);
 
277
  
 
278
 
 
279
  /* If D Type picture, flush marker bit. */
 
280
  if (code_type == D_TYPE) {
 
281
    mpegVideoStream->flushBits(1);
 
282
  }
 
283
 
 
284
  /* If macroblock was intracoded, set macroblock past intra address. */
 
285
  if (mb_intra) {
 
286
    past_intra_addr=mb_address;
 
287
  }
 
288
  if (back == false) {
 
289
    return false;
 
290
  }
 
291
  return true;
 
292
}
 
293
  
 
294
 
 
295
int MacroBlock::resetMacroBlock() {
 
296
  /* Reset past intrablock address. */
 
297
  past_intra_addr = -2;
 
298
 
 
299
  /* Reset previous recon motion vectors. */
 
300
  
 
301
 
 
302
  recon_right_for_prev = 0;
 
303
  recon_down_for_prev = 0;
 
304
  recon_right_back_prev = 0;
 
305
  recon_down_back_prev = 0;
 
306
 
 
307
  /* Reset macroblock address. */
 
308
  mb_address = (((vid_stream->slice)->getVertPos()-1) *
 
309
                (vid_stream->mpegVideoHeader)->getMB_Width()) - 1;
 
310
  return true;
 
311
 
 
312
}
 
313
 
 
314
 
 
315
int MacroBlock::resetPastMacroBlock() {
 
316
  /* Reset past macroblock address field. */
 
317
 
 
318
  past_mb_addr = -1;
 
319
  return true;
 
320
}
 
321
 
 
322
 
 
323
 
 
324
 
 
325
int MacroBlock::reconstruct(int& recon_right_for,
 
326
                            int& recon_down_for,
 
327
                            int& recon_right_back,
 
328
                            int& recon_down_back,
 
329
                            int& mb_motion_forw,
 
330
                            int& mb_motion_back,
 
331
                            PictureArray* pictureArray) {
 
332
  int mask, i;
 
333
  int zero_block_flag;
 
334
  int mb_row;
 
335
  int mb_col;
 
336
  int mb_width=(vid_stream->mpegVideoHeader)->getMB_Width();
 
337
  int row_size=pictureArray->getWidth();
 
338
  short int* dct_start=(vid_stream->decoderClass)->getDCT();
 
339
  unsigned int qscale=(vid_stream->slice)->getQuantScale();
 
340
  int codeType=(vid_stream->picture)->getCodeType();
 
341
  DecoderClass* decoderClass=vid_stream->decoderClass;
 
342
  int lflag=false;
 
343
  Recon* recon=vid_stream->recon;
 
344
  unsigned int* iqmatrixptr=
 
345
    (vid_stream->mpegVideoHeader)->getIntra_quant_matrix();
 
346
  unsigned int* niqmatrixptr=
 
347
    (vid_stream->mpegVideoHeader)->getNon_intra_quant_matrix();
 
348
 
 
349
 
 
350
 
 
351
 
 
352
 
 
353
  if (mb_address-past_intra_addr > 1) {
 
354
    lflag=true;
 
355
  }
 
356
 
 
357
  if (mb_width <= 0) {
 
358
     DEBUG_MACROBLOCK(cout << "mb_width <= 0"<<endl;)
 
359
     return false;
 
360
  }
 
361
  /* Calculate macroblock row and column from address. */
 
362
  mb_row=mb_address / mb_width;
 
363
  mb_col=mb_address % mb_width;
 
364
 
 
365
  copyFunctions->startNOFloatSection();
 
366
 
 
367
  for (mask = 32, i = 0; i < 6; mask >>= 1, i++) {
 
368
 
 
369
     
 
370
    /* If block exists... */
 
371
    if ((mb_intra) || (cbp & mask)) {
 
372
      zero_block_flag = 0;
 
373
      //copyFunctions->endNOFloatSection();
 
374
      decoderClass->ParseReconBlock(i,mb_intra,
 
375
                                    qscale,lflag,iqmatrixptr,niqmatrixptr);
 
376
      //copyFunctions->endNOFloatSection();
 
377
    } else {
 
378
      zero_block_flag = 1;
 
379
    }
 
380
 
 
381
 
 
382
    // If macroblock is intra coded... 
 
383
 
 
384
 
 
385
    if (mb_intra) {
 
386
      recon->ReconIMBlock(i,mb_row,mb_col,row_size,
 
387
                          dct_start,pictureArray);
 
388
      //copyFunctions->endNOFloatSection();
 
389
    } else if (mb_motion_forw && mb_motion_back) {
 
390
      recon->ReconBiMBlock(i,recon_right_for,
 
391
                           recon_down_for,recon_right_back,
 
392
                           recon_down_back,zero_block_flag,
 
393
                           mb_row,mb_col,row_size,dct_start,
 
394
                           pictureArray);
 
395
      //copyFunctions->endNOFloatSection();
 
396
    } else if (mb_motion_forw || (codeType ==P_TYPE)){
 
397
      recon->ReconPMBlock(i,recon_right_for,
 
398
                          recon_down_for,zero_block_flag,
 
399
                          mb_row,mb_col,row_size,dct_start,
 
400
                          pictureArray, codeType);
 
401
      //copyFunctions->endNOFloatSection();
 
402
    } else if (mb_motion_back) {
 
403
      recon->ReconBMBlock(i,recon_right_back,
 
404
                          recon_down_back,zero_block_flag,
 
405
                          mb_row,mb_col,row_size,dct_start,
 
406
                          pictureArray);
 
407
      //copyFunctions->endNOFloatSection();
 
408
      
 
409
    } else {
 
410
      //DEBUG_MACROBLOCK(cout << "nothing"<<endl;)
 
411
    }
 
412
    
 
413
  }
 
414
  copyFunctions->endNOFloatSection();
 
415
  return true;
 
416
}
 
417
 
 
418
/*
 
419
 *--------------------------------------------------------------
 
420
 *
 
421
 * ComputeForwVector --
 
422
 *
 
423
 *      Computes forward motion vector by calling ComputeVector
 
424
 *      with appropriate parameters.
 
425
 *
 
426
 * Results:
 
427
 *      Reconstructed motion vector placed in recon_right_for_ptr and
 
428
 *      recon_down_for_ptr.
 
429
 *
 
430
 * Side effects:
 
431
 *      None.
 
432
 *
 
433
 *--------------------------------------------------------------
 
434
 */
 
435
 
 
436
void MacroBlock::computeForwVector(int* recon_right_for_ptr,
 
437
                                   int* recon_down_for_ptr) {
 
438
  
 
439
  Picture *picture;
 
440
 
 
441
 
 
442
  picture = vid_stream->picture;
 
443
 
 
444
 
 
445
  unsigned int forw_f=picture->getForw_f();
 
446
  unsigned int full_pel_forw_vector=picture->getFull_pel_forw_vector();
 
447
  vid_stream->motionVector->computeVector(recon_right_for_ptr, 
 
448
                                          recon_down_for_ptr,
 
449
                                          recon_right_for_prev, 
 
450
                                          recon_down_for_prev,
 
451
                                          forw_f,
 
452
                                          full_pel_forw_vector,
 
453
                                          motion_h_forw_code, 
 
454
                                          motion_v_forw_code,
 
455
                                          motion_h_forw_r,
 
456
                                          motion_v_forw_r); 
 
457
  picture->setForw_f(forw_f);
 
458
  picture->setFull_pel_forw_vector(full_pel_forw_vector);
 
459
}
 
460
 
 
461
 
 
462
/*
 
463
 *--------------------------------------------------------------
 
464
 *
 
465
 * ComputeBackVector --
 
466
 *
 
467
 *      Computes backward motion vector by calling ComputeVector
 
468
 *      with appropriate parameters.
 
469
 *
 
470
 * Results:
 
471
 *      Reconstructed motion vector placed in recon_right_back_ptr and
 
472
 *      recon_down_back_ptr.
 
473
 *
 
474
 * Side effects:
 
475
 *      None.
 
476
 *
 
477
 *--------------------------------------------------------------
 
478
 */
 
479
 
 
480
void MacroBlock::computeBackVector(int* recon_right_back_ptr,
 
481
                                   int* recon_down_back_ptr) {
 
482
 
 
483
  Picture *picture;
 
484
 
 
485
 
 
486
  picture = vid_stream->picture;
 
487
 
 
488
 
 
489
  unsigned int back_f=picture->getBack_f();
 
490
  unsigned int full_pel_back_vector=picture->getFull_pel_back_vector();
 
491
  
 
492
  vid_stream->motionVector->computeVector(recon_right_back_ptr, 
 
493
                                          recon_down_back_ptr,
 
494
                                          recon_right_back_prev, 
 
495
                                          recon_down_back_prev,
 
496
                                          back_f, 
 
497
                                          full_pel_back_vector,
 
498
                                          motion_h_back_code, 
 
499
                                          motion_v_back_code,
 
500
                                          motion_h_back_r,
 
501
                                          motion_v_back_r); 
 
502
  picture->setBack_f(back_f);
 
503
  picture->setFull_pel_back_vector(full_pel_back_vector);
 
504
}
 
505
 
 
506
 
 
507
 
 
508
 
 
509
 
 
510
int MacroBlock::processSkippedPictures(PictureArray* pictureArray,
 
511
                                       int code_type,
 
512
                                       int mb_width) {
 
513
  copyFunctions->startNOFloatSection();
 
514
 
 
515
  if (code_type == P_TYPE) {
 
516
    
 
517
    ProcessSkippedPFrameMBlocks(pictureArray->getCurrent(),
 
518
                                pictureArray->getFuture(),
 
519
                                mb_width);
 
520
    
 
521
  } else {
 
522
    if (code_type == B_TYPE) {
 
523
      ProcessSkippedBFrameMBlocks(vid_stream->picture,
 
524
                                  pictureArray->getPast(),
 
525
                                  pictureArray->getCurrent(),
 
526
                                  pictureArray->getFuture(),
 
527
                                  mb_width);
 
528
    }
 
529
  }
 
530
 
 
531
  copyFunctions->endNOFloatSection();
 
532
 
 
533
  return true;
 
534
}
 
535
 
 
536
/*
 
537
 *--------------------------------------------------------------
 
538
 *
 
539
 * ProcessSkippedPFrameMBlocks --
 
540
 *
 
541
 *      Processes skipped macroblocks in P frames.
 
542
 *
 
543
 * Results:
 
544
 *      Calculates pixel values for luminance, Cr, and Cb planes
 
545
 *      in current pict image for skipped macroblocks.
 
546
 *
 
547
 * Side effects:
 
548
 *      Pixel values in pict image changed.
 
549
 *
 
550
 *--------------------------------------------------------------
 
551
 */
 
552
void MacroBlock::ProcessSkippedPFrameMBlocks(YUVPicture* current,
 
553
                                             YUVPicture* future,
 
554
                                             int mb_width) {
 
555
 
 
556
  int row_size, half_row, mb_row, mb_col, row, col, rr;
 
557
  int addr, row_incr, half_row_incr, crow, ccol;
 
558
  int *dest, *src, *dest1, *src1;
 
559
 
 
560
  /* For each row in macroblock luminance plane... */
 
561
  if (mb_width == 0) {
 
562
    DEBUG_MACROBLOCK(cout << "mb_width in skipped is 0"<<endl;)
 
563
    return;
 
564
  }
 
565
 
 
566
 
 
567
  /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
 
568
 
 
569
  row_size = mb_width << 4;
 
570
  half_row = (row_size >> 1);
 
571
  row_incr = row_size >> 2;
 
572
  half_row_incr = half_row >> 2;
 
573
 
 
574
  /* For each skipped macroblock, do... */
 
575
  int lumEnd=current->getLumLength();
 
576
  int colorEnd=current->getColorLength();
 
577
  
 
578
  unsigned char *picDest;
 
579
  unsigned char *picSrc;
 
580
 
 
581
  unsigned char *picDestStart;
 
582
  unsigned char *picSrcStart;
 
583
 
 
584
 
 
585
 
 
586
  for (addr = past_mb_addr + 1; addr < mb_address; addr++) {
 
587
 
 
588
    /* Calculate macroblock row and col. */
 
589
 
 
590
    mb_row = addr / mb_width;
 
591
    mb_col = addr % mb_width;
 
592
 
 
593
    /* Calculate upper left pixel row,col for luminance plane. */
 
594
 
 
595
    row = mb_row << 4;
 
596
    col = mb_col << 4;
 
597
    
 
598
    picDest=current->getLuminancePtr();
 
599
    picSrc=future->getLuminancePtr();
 
600
 
 
601
    picDestStart=(picDest+(row*row_size)+col);
 
602
    picSrcStart=(picSrc+(row*row_size)+col);
 
603
   
 
604
    if ((picDestStart+7*row_size+7 >= picDest+lumEnd) ||
 
605
        (picDestStart < picDest)) {
 
606
      DEBUG_MACROBLOCK(cout << "urg! last resort caught before sigsev skipped -1"<<endl;)
 
607
      break;
 
608
    }
 
609
    if ((picSrcStart+7*row_size+7 >= picSrc+lumEnd) ||
 
610
        (picSrcStart < picSrc)) {
 
611
      DEBUG_MACROBLOCK(cout << "urg! last resort caught before sigsev skipped -2"<<endl;)
 
612
      break;
 
613
    }
 
614
 
 
615
    dest=(int*)picDestStart;
 
616
    src=(int*)picSrcStart;
 
617
 
 
618
 
 
619
 
 
620
    for (rr = 0; rr < 8; rr++) {
 
621
 
 
622
      /* Copy pixel values from last I or P picture. */
 
623
      memcpy(dest,src,sizeof(int)*4);
 
624
 
 
625
      dest += row_incr;
 
626
      src += row_incr;
 
627
      memcpy(dest,src,sizeof(int)*4);
 
628
 
 
629
      dest += row_incr;
 
630
      src += row_incr;
 
631
    }
 
632
 
 
633
    /*
 
634
     * Divide row,col to get upper left pixel of macroblock in Cr and Cb
 
635
     * planes.
 
636
     */
 
637
 
 
638
    crow = row >> 1;
 
639
    ccol = col >> 1;
 
640
 
 
641
    /* For each row in Cr, and Cb planes... */
 
642
    picDest=current->getCrPtr();
 
643
    picDestStart=(picDest+(crow*half_row)+ccol);
 
644
    if ((picDestStart+7*half_row_incr+7 >= picDest+colorEnd) ||
 
645
        (picDestStart < picDest)) {
 
646
      DEBUG_MACROBLOCK(cout << "urg! last resort caught before sigsev skipped -3"<<endl;)
 
647
      break;
 
648
    }
 
649
 
 
650
 
 
651
    dest=(int*)(current->getCrPtr()+(crow*half_row)+ccol);
 
652
    src=(int*)(future->getCrPtr()+(crow*half_row)+ccol);
 
653
    dest1=(int*)(current->getCbPtr()+(crow*half_row)+ccol);
 
654
    src1=(int*)(future->getCbPtr()+(crow*half_row)+ccol);
 
655
 
 
656
    for (rr = 0; rr < 4; rr++) {
 
657
 
 
658
      /* Copy pixel values from last I or P picture. */
 
659
      memcpy(dest,src,sizeof(int)*2);
 
660
      memcpy(dest1,src1,sizeof(int)*2);
 
661
 
 
662
 
 
663
      dest += half_row_incr;
 
664
      src += half_row_incr;
 
665
      dest1 += half_row_incr;
 
666
      src1 += half_row_incr;
 
667
 
 
668
      memcpy(dest,src,sizeof(int)*2);
 
669
      memcpy(dest1,src1,sizeof(int)*2);
 
670
 
 
671
      dest += half_row_incr;
 
672
      src += half_row_incr;
 
673
      dest1 += half_row_incr;
 
674
      src1 += half_row_incr;
 
675
    }
 
676
 
 
677
  }
 
678
 
 
679
  recon_right_for_prev = 0;
 
680
  recon_down_for_prev = 0;
 
681
 
 
682
}
 
683
  
 
684
 
 
685
 
 
686
 
 
687
 
 
688
/*
 
689
 *--------------------------------------------------------------
 
690
 *
 
691
 * ProcessSkippedBFrameMBlocks --
 
692
 *
 
693
 *      Processes skipped macroblocks in B frames.
 
694
 *
 
695
 * Results:
 
696
 *      Calculates pixel values for luminance, Cr, and Cb planes
 
697
 *      in current pict image for skipped macroblocks.
 
698
 *
 
699
 * Side effects:
 
700
 *      Pixel values in pict image changed.
 
701
 *
 
702
 *--------------------------------------------------------------
 
703
 */
 
704
 
 
705
void MacroBlock::ProcessSkippedBFrameMBlocks(Picture* picture,
 
706
                                             YUVPicture* past,
 
707
                                             YUVPicture* current,
 
708
                                             YUVPicture* future,
 
709
                                             int mb_width) {
 
710
  int row_size, half_row, mb_row, mb_col, row, col, rr;
 
711
  int right_half_for = 0, down_half_for = 0;
 
712
  int c_right_half_for = 0, c_down_half_for = 0;
 
713
  int right_half_back = 0, down_half_back = 0;
 
714
  int c_right_half_back = 0, c_down_half_back = 0;
 
715
  int addr, right_for = 0, down_for = 0;
 
716
  int recon_right_for, recon_down_for;
 
717
  int recon_right_back, recon_down_back;
 
718
  int right_back = 0, down_back = 0;
 
719
  int c_right_for = 0, c_down_for = 0;
 
720
  int c_right_back = 0, c_down_back = 0;
 
721
  unsigned char forw_lum[256];
 
722
  unsigned char forw_cr[64], forw_cb[64];
 
723
  unsigned char back_lum[256], back_cr[64], back_cb[64];
 
724
  int row_incr, half_row_incr;
 
725
  int ccol, crow;
 
726
 
 
727
 
 
728
  /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
 
729
 
 
730
  if (mb_width == 0) {
 
731
    DEBUG_MACROBLOCK(cout << "mb_width in skipped is 0 (2)"<<endl;)
 
732
    return;
 
733
  }
 
734
 
 
735
  row_size = mb_width << 4;
 
736
  half_row = (row_size >> 1);
 
737
  row_incr = row_size >> 2;
 
738
  half_row_incr =  half_row >> 2;
 
739
 
 
740
  /* Establish motion vector codes based on full pixel flag. */
 
741
 
 
742
  if (picture->getFull_pel_forw_vector()) {
 
743
    recon_right_for = recon_right_for_prev << 1;
 
744
    recon_down_for = recon_down_for_prev << 1;
 
745
  } else {
 
746
    recon_right_for = recon_right_for_prev;
 
747
    recon_down_for = recon_down_for_prev;
 
748
  }
 
749
 
 
750
  if (picture->getFull_pel_back_vector()) {
 
751
    recon_right_back = recon_right_back_prev << 1;
 
752
    recon_down_back = recon_down_back_prev << 1;
 
753
  } else {
 
754
    recon_right_back = recon_right_back_prev;
 
755
    recon_down_back = recon_down_back_prev;
 
756
  }
 
757
 
 
758
 
 
759
  /* If only one motion vector, do display copy, else do full
 
760
     calculation. 
 
761
  */
 
762
 
 
763
  /* Calculate motion vectors. */
 
764
  
 
765
  if (bpict_past_forw) {
 
766
    right_for = recon_right_for >> 1;
 
767
    down_for = recon_down_for >> 1;
 
768
    right_half_for = recon_right_for & 0x1;
 
769
    down_half_for = recon_down_for & 0x1;
 
770
    
 
771
    recon_right_for /= 2;
 
772
    recon_down_for /= 2;
 
773
    c_right_for = recon_right_for >> 1;
 
774
    c_down_for = recon_down_for >> 1;
 
775
    c_right_half_for = recon_right_for & 0x1;
 
776
    c_down_half_for = recon_down_for & 0x1;
 
777
    
 
778
  }
 
779
  if (bpict_past_back) {
 
780
    right_back = recon_right_back >> 1;
 
781
    down_back = recon_down_back >> 1;
 
782
    right_half_back = recon_right_back & 0x1;
 
783
    down_half_back = recon_down_back & 0x1;
 
784
    
 
785
    recon_right_back /= 2;
 
786
    recon_down_back /= 2;
 
787
    c_right_back = recon_right_back >> 1;
 
788
    c_down_back = recon_down_back >> 1;
 
789
    c_right_half_back = recon_right_back & 0x1;
 
790
    c_down_half_back = recon_down_back & 0x1;
 
791
    
 
792
  }
 
793
  /* For each skipped macroblock, do... */
 
794
  
 
795
  for (addr = past_mb_addr + 1;
 
796
       addr < mb_address; addr++) {
 
797
    
 
798
    /* Calculate macroblock row and col. */
 
799
    
 
800
    mb_row = addr / mb_width;
 
801
    mb_col = addr % mb_width;
 
802
    
 
803
    /* Calculate upper left pixel row,col for luminance plane. */
 
804
    
 
805
    row = mb_row << 4;
 
806
    col = mb_col << 4;
 
807
    crow = row / 2;
 
808
    ccol = col / 2;
 
809
    
 
810
    /* If forward predicted, calculate prediction values. */
 
811
    if (bpict_past_forw) {
 
812
      int lumEnd=current->getLumLength();
 
813
      int colorEnd=current->getColorLength();
 
814
      ReconSkippedBlock(past->getLuminancePtr(),
 
815
                        forw_lum,row,col,row_size,
 
816
                        right_for,down_for,
 
817
                        right_half_for,
 
818
                        down_half_for,16,lumEnd);
 
819
      ReconSkippedBlock(past->getCrPtr(),
 
820
                        forw_cr,crow,ccol, half_row,
 
821
                        c_right_for,c_down_for,
 
822
                        c_right_half_for,
 
823
                        c_down_half_for,8,colorEnd);
 
824
      ReconSkippedBlock(past->getCbPtr(),
 
825
                        forw_cb,crow,ccol,half_row,
 
826
                        c_right_for,c_down_for,
 
827
                        c_right_half_for,
 
828
                        c_down_half_for,8,colorEnd);
 
829
    }
 
830
    /* If back predicted, calculate prediction values. */
 
831
    
 
832
    if (bpict_past_back) {
 
833
      int lumEnd=current->getLumLength();
 
834
      int colorEnd=current->getColorLength();
 
835
      ReconSkippedBlock(future->getLuminancePtr(),
 
836
                        back_lum,row,col,row_size,
 
837
                        right_back,down_back,
 
838
                        right_half_back,down_half_back,
 
839
                        16,lumEnd);
 
840
      ReconSkippedBlock(future->getCrPtr(),
 
841
                        back_cr,crow,ccol,
 
842
                        half_row,c_right_back,
 
843
                        c_down_back,c_right_half_back,
 
844
                        c_down_half_back,8,colorEnd);
 
845
      ReconSkippedBlock(future->getCbPtr(),
 
846
                        back_cb,crow,ccol,half_row,
 
847
                        c_right_back,c_down_back,
 
848
                        c_right_half_back,
 
849
                        c_down_half_back,8,colorEnd);
 
850
    }
 
851
    unsigned char* picDest=current->getLuminancePtr();
 
852
    int lumEnd=current->getLumLength();
 
853
    int colorEnd=current->getColorLength();
 
854
 
 
855
    unsigned char* picDestStart=(picDest+(row*row_size)+col);
 
856
 
 
857
   
 
858
    if ((picDestStart+7*row_size+7 >= picDest+lumEnd) ||
 
859
        (picDestStart < picDest)) {
 
860
      DEBUG_MACROBLOCK(cout << "urg! last resort caught before sigsev skipped -4"<<endl;)
 
861
      return;
 
862
    }
 
863
 
 
864
    picDest=current->getCrPtr();
 
865
    picDestStart=(picDest+(crow*half_row)+ccol);
 
866
    if ((picDestStart+7*half_row_incr+7 >= picDest+colorEnd) ||
 
867
        (picDestStart < picDest)) {
 
868
      DEBUG_MACROBLOCK(cout << "urg! last resort caught before sigsev skipped -5"<<endl;)
 
869
      exit(0);
 
870
    }
 
871
    
 
872
 
 
873
    if (bpict_past_forw && !bpict_past_back) {
 
874
      
 
875
      int *dest, *dest1;
 
876
      int *src, *src1;
 
877
      dest=(int*)(current->getLuminancePtr()+(row*row_size)+col);
 
878
      src=(int*)forw_lum;
 
879
      
 
880
      for (rr = 0; rr < 16; rr++) {
 
881
        
 
882
        /* memcpy(dest, forw_lum+(rr<<4), 16);  */
 
883
        
 
884
        dest[0] = src[0];
 
885
        dest[1] = src[1];
 
886
        dest[2] = src[2];
 
887
        dest[3] = src[3];
 
888
        dest += row_incr;
 
889
        src += 4;
 
890
      }
 
891
      
 
892
      dest = (int*)(current->getCrPtr()+(crow*half_row)+ccol);
 
893
      dest1 = (int*)(current->getCbPtr()+(crow*half_row)+ccol);
 
894
      src = (int*)forw_cr;
 
895
      src1 = (int*)forw_cb;
 
896
      
 
897
      for (rr = 0; rr < 8; rr++) {
 
898
        /*
 
899
         * memcpy(dest, forw_cr+(rr<<3), 8); memcpy(dest1, forw_cb+(rr<<3),
 
900
         * 8);
 
901
         */
 
902
        
 
903
        dest[0] = src[0];
 
904
        dest[1] = src[1];
 
905
        
 
906
        dest1[0] = src1[0];
 
907
        dest1[1] = src1[1];
 
908
        
 
909
        dest += half_row_incr;
 
910
        dest1 += half_row_incr;
 
911
        src += 2;
 
912
        src1 += 2;
 
913
      }
 
914
    } else if (bpict_past_back && !bpict_past_forw) {
 
915
      
 
916
      int *src, *src1;
 
917
      int *dest, *dest1;
 
918
      dest=(int*)(current->getLuminancePtr()+(row*row_size)+col);
 
919
      src = (int*)back_lum;
 
920
      
 
921
      for (rr = 0; rr < 16; rr++) {
 
922
        dest[0] = src[0];
 
923
        dest[1] = src[1];
 
924
        dest[2] = src[2];
 
925
        dest[3] = src[3];
 
926
        dest += row_incr;
 
927
        src += 4;
 
928
      }
 
929
      
 
930
      
 
931
      dest = (int *)(current->getCrPtr()+(crow*half_row)+ccol);
 
932
      dest1 = (int *)(current->getCbPtr()+(crow*half_row)+ccol);
 
933
      src = (int *)back_cr;
 
934
      src1 = (int *)back_cb;
 
935
      
 
936
      for (rr = 0; rr < 8; rr++) {
 
937
        /*
 
938
         * memcpy(dest, back_cr+(rr<<3), 8); memcpy(dest1, back_cb+(rr<<3),
 
939
         * 8);
 
940
         */
 
941
        
 
942
        dest[0] = src[0];
 
943
        dest[1] = src[1];
 
944
        
 
945
        dest1[0] = src1[0];
 
946
        dest1[1] = src1[1];
 
947
        
 
948
        dest += half_row_incr;
 
949
        dest1 += half_row_incr;
 
950
        src += 2;
 
951
        src1 += 2;
 
952
      }
 
953
    } else {
 
954
      
 
955
      unsigned char *src1, *src2, *src1a, *src2a;
 
956
      unsigned char *dest, *dest1;
 
957
      dest = current->getLuminancePtr()+(row*row_size)+col;
 
958
      src1 = forw_lum;
 
959
      src2 = back_lum;
 
960
      
 
961
      for (rr = 0; rr < 16; rr++) {
 
962
        dest[0] = (int) (src1[0] + src2[0]) >> 1;
 
963
        dest[1] = (int) (src1[1] + src2[1]) >> 1;
 
964
        dest[2] = (int) (src1[2] + src2[2]) >> 1;
 
965
        dest[3] = (int) (src1[3] + src2[3]) >> 1;
 
966
        dest[4] = (int) (src1[4] + src2[4]) >> 1;
 
967
        dest[5] = (int) (src1[5] + src2[5]) >> 1;
 
968
        dest[6] = (int) (src1[6] + src2[6]) >> 1;
 
969
        dest[7] = (int) (src1[7] + src2[7]) >> 1;
 
970
        dest[8] = (int) (src1[8] + src2[8]) >> 1;
 
971
        dest[9] = (int) (src1[9] + src2[9]) >> 1;
 
972
        dest[10] = (int) (src1[10] + src2[10]) >> 1;
 
973
        dest[11] = (int) (src1[11] + src2[11]) >> 1;
 
974
        dest[12] = (int) (src1[12] + src2[12]) >> 1;
 
975
        dest[13] = (int) (src1[13] + src2[13]) >> 1;
 
976
        dest[14] = (int) (src1[14] + src2[14]) >> 1;
 
977
        dest[15] = (int) (src1[15] + src2[15]) >> 1;
 
978
        dest += row_size;
 
979
        src1 += 16;
 
980
        src2 += 16;
 
981
      }
 
982
      
 
983
      
 
984
      dest = current->getCrPtr() + (crow * half_row) + ccol;
 
985
      dest1 = current->getCbPtr() + (crow * half_row) + ccol;
 
986
      src1 = forw_cr;
 
987
      src2 = back_cr;
 
988
      src1a = forw_cb;
 
989
      src2a = back_cb;
 
990
      
 
991
      for (rr = 0; rr < 8; rr++) {
 
992
        dest[0] = (int) (src1[0] + src2[0]) >> 1;
 
993
        dest[1] = (int) (src1[1] + src2[1]) >> 1;
 
994
        dest[2] = (int) (src1[2] + src2[2]) >> 1;
 
995
        dest[3] = (int) (src1[3] + src2[3]) >> 1;
 
996
        dest[4] = (int) (src1[4] + src2[4]) >> 1;
 
997
        dest[5] = (int) (src1[5] + src2[5]) >> 1;
 
998
        dest[6] = (int) (src1[6] + src2[6]) >> 1;
 
999
        dest[7] = (int) (src1[7] + src2[7]) >> 1;
 
1000
        dest += half_row;
 
1001
        src1 += 8;
 
1002
        src2 += 8;
 
1003
        
 
1004
        dest1[0] = (int) (src1a[0] + src2a[0]) >> 1;
 
1005
        dest1[1] = (int) (src1a[1] + src2a[1]) >> 1;
 
1006
        dest1[2] = (int) (src1a[2] + src2a[2]) >> 1;
 
1007
        dest1[3] = (int) (src1a[3] + src2a[3]) >> 1;
 
1008
        dest1[4] = (int) (src1a[4] + src2a[4]) >> 1;
 
1009
        dest1[5] = (int) (src1a[5] + src2a[5]) >> 1;
 
1010
        dest1[6] = (int) (src1a[6] + src2a[6]) >> 1;
 
1011
        dest1[7] = (int) (src1a[7] + src2a[7]) >> 1;
 
1012
        dest1 += half_row;
 
1013
        src1a += 8;
 
1014
        src2a += 8;
 
1015
      }
 
1016
    }
 
1017
    
 
1018
  }
 
1019
}
 
1020
 
 
1021
 
 
1022
 
 
1023
 
 
1024
 
 
1025
 
 
1026
 
 
1027
/*
 
1028
 *--------------------------------------------------------------
 
1029
 *
 
1030
 * ReconSkippedBlock --
 
1031
 *
 
1032
 *      Reconstructs predictive block for skipped macroblocks
 
1033
 *      in B Frames.
 
1034
 *
 
1035
 * Results:
 
1036
 *      No return values.
 
1037
 *
 
1038
 * Side effects:
 
1039
 *      None.
 
1040
 *
 
1041
 *--------------------------------------------------------------
 
1042
 */
 
1043
void MacroBlock::ReconSkippedBlock(unsigned char* source,
 
1044
                                   unsigned char* dest,
 
1045
                                   int row,
 
1046
                                   int col,
 
1047
                                   int row_size,
 
1048
                                   int right,
 
1049
                                   int down,
 
1050
                                   int right_half,
 
1051
                                   int down_half,
 
1052
                                   int width,int maxLen) {
 
1053
  int rr;
 
1054
  unsigned char *source2;
 
1055
  unsigned char *tmp;
 
1056
 
 
1057
  tmp = source+((row + down) * row_size) + col + right;
 
1058
 
 
1059
 
 
1060
  if ((tmp+7*row_size+7 >= source+maxLen) ||
 
1061
      (tmp < source)) {
 
1062
    DEBUG_MACROBLOCK(cout << "urg! last resort caught before sigsev skipped -6"<<endl;)
 
1063
    return;
 
1064
  } 
 
1065
 
 
1066
  source=tmp;
 
1067
  if (width == 16) {
 
1068
    if ((!right_half) && (!down_half)) {
 
1069
        if (right & 0x1) {
 
1070
          /* No alignment, use bye copy */
 
1071
          for (rr = 0; rr < 16; rr++) {
 
1072
 
 
1073
            memcpy(dest,source,sizeof(char)*16);
 
1074
 
 
1075
            dest += 16;
 
1076
            source += row_size;
 
1077
          }
 
1078
        } else if (right & 0x2) {
 
1079
          /* Half-word bit aligned, use 16 bit copy */
 
1080
          short *src = (short *)source;
 
1081
          short *d = (short *)dest;
 
1082
          row_size >>= 1;
 
1083
          for (rr = 0; rr < 16; rr++) {
 
1084
 
 
1085
            memcpy(d,src,sizeof(short)*8);
 
1086
    
 
1087
            d += 8;
 
1088
            src += row_size;
 
1089
          }
 
1090
        } else {
 
1091
          /* Word aligned, use 32 bit copy */
 
1092
          int *src = (int *)source;
 
1093
          int *d = (int *)dest;
 
1094
          row_size >>= 2;
 
1095
          for (rr = 0; rr < 16; rr++) {
 
1096
            d[0] = src[0];
 
1097
            d[1] = src[1];
 
1098
            d[2] = src[2];
 
1099
            d[3] = src[3];
 
1100
            d += 4;
 
1101
            src += row_size;
 
1102
          }
 
1103
        }
 
1104
    } else {
 
1105
      source2 = source + right_half + (row_size * down_half);
 
1106
      copyFunctions->copy16_div2_destlinear_nocrop(source,source2,dest,
 
1107
                                                   row_size);
 
1108
 
 
1109
 
 
1110
    }
 
1111
  } else {                      /* (width == 8) */
 
1112
    assert(width == 8);
 
1113
    if ((!right_half) && (!down_half)) {
 
1114
      if (right & 0x1) {
 
1115
        for (rr = 0; rr < width; rr++) {
 
1116
 
 
1117
          memcpy(dest,source,sizeof(char)*8);
 
1118
 
 
1119
          dest += 8;
 
1120
          source += row_size;
 
1121
        }
 
1122
      } else if (right & 0x02) {
 
1123
        short *d = (short *)dest;
 
1124
        short *src = (short *)source;
 
1125
        row_size >>= 1;
 
1126
        for (rr = 0; rr < width; rr++) {
 
1127
          d[0] = src[0];
 
1128
          d[1] = src[1];
 
1129
          d[2] = src[2];
 
1130
          d[3] = src[3];
 
1131
          d += 4;
 
1132
          src += row_size;
 
1133
        }
 
1134
      } else {
 
1135
        int *d = (int *)dest;
 
1136
        int *src = (int *)source;
 
1137
        row_size >>= 2;
 
1138
        for (rr = 0; rr < width; rr++) {
 
1139
          d[0] = src[0];
 
1140
          d[1] = src[1];
 
1141
          d += 2;
 
1142
          src += row_size;
 
1143
        }
 
1144
      }
 
1145
    } else {
 
1146
      source2 = source + right_half + (row_size * down_half);
 
1147
      copyFunctions->copy8_div2_destlinear_nocrop(source,source2,
 
1148
                                                  dest,row_size);
 
1149
    }
 
1150
  }
 
1151
}
 
1152