h.264直接预测

直接预测是B帧上一种独有的预测方式,其中直接预测又分为两种模式: 时域直接模式(temporal direct)、空域直接模式(spatial direct)。

在分析这两种模式之前,有一个前提概念需要了解:共同位置4x4子宏块分割块(co-located 4x4 sub-macroblock partitions),下面简称为co-located。

共同位置4x4子宏块分割块,故名思义,该块大小为4x4。co-located的主要功能是得到出该4x4块的运动向量以及参考帧,以供后面的直接预测做后续处理,如果当前宏块进行的是直接预测,无论时域或空域,都会用到该co-located,因此需要先求出该4x4co-located的具体位置。

 

co-located的定位

1. 定位co-located所在图像

要求co-located的位置,首先需要知道co-located所在的图像colPic的位置,colPic可以确定在当前图像的第一个后向参考图像RefPicList1[ 0 ]内,但是colPic可以为帧或场,这取决于当期图像与参考图像,是以帧图像进行编码,还是以场图像进行编码,或者以互补场对(宏块级帧场自适应)方式进行编码。

  • 第一项:field_pic_flag表示当前图像是以帧还是场方式进行编码
  • 第二项:代表RefPicList1[0]的编码方式是帧、场、互补场对(两个场)
  • 第三项:mb_field_decoding_flag代表当前宏块对是以帧、场方式进行编码(前提条件是当前图像是以帧方式进行编码,也只有当前图像选择了帧编码,才能选择宏块对(宏块帧场自适应)的编码方式)
  • 第四项:

    topAbsDiffPOC=|DiffPicOrderCnt(firstRefPicL1Top,CurrPic)|bottomAbsDiffPOC=|DiffPicOrderCnt(firstRefPicL1Bottom,CurrPic)|

    添加这些条件是为了在采用宏块级帧场自适编码方式时,应选择距离当前图像最近的顶场或底场作为col_Pic

  • 第五项:col_Pic的取值,firstRefPicL1Top 和firstRefPicL1Bottom 分别为RefPicList1[ 0 ]中的顶场和底场

注:其实第二项RefPicList1[ 0 ]是一个被动选项,因为它是根据当前图像的编码方式是帧、场或宏块帧场自适应决定的,如果当前图像是场,那么RefPicList1[ 0 ]就有可能是已解码的场或者以解码帧中的一场;如果当前图像是帧(非MBAFF),那么RefPicList1[ 0 ]就是帧;如果当前宏块是帧并且为MBAFF,那么RefPicList1[ 0 ]就是一个互补场对(两个场可以组成一个帧)

 

2. 得到co-located在colPic内的位置

实际上,如果得到了colPic,就可以通过当前宏块的16个4x4块的绝对位置(以4x4块为单位相对于图像左上角(0,0)的绝对位置( opic_block_x,opic_block_y)),得到co-located在colPic的位置。

  • 如果当前图像为帧,colPic为场,则co-located为(opic_block_x,opic_block_y>>1)
  • 如果当前图像为场,colPic为帧,则co-located为(opic_block_x,opic_block_y<<1)
  • 如果当前图像与colPic同为帧或场,则co-located为(opic_block_x,opic_block_y)

(注:像在jm18.6中,实际计算时,不会出现当前图像为场,colPic为帧的情况,因为场的参考图像都会被分为场后加入参考图像队列,所以最终计算时也会先根据当前场的是顶场或底场挑出参考帧中对应的场作为colPic )

 

在标准中,先定位co-located所在宏块mbAddrCol,然后再定位co-located在该宏块内的地址(xcol,yM)。由于采用了不同于上述的4x4块定位方法,所以计算方式略复杂,但是得到的结果是一样的,最终会定位到同一个co-located

mbAddrCol1=2×PicWidthInMbs×(CurrMbAddr/PicWidthInMbs)+(CurrMbAddr % PicWidthInMbs)+PicWidthInMbs×(yCol/8)mbAddrCol2=2×CurrMbAddr+(yCol/8)mbAddrCol3=2×CurrMbAddr+bottom_field_flagmbAddrCol4=PicWidthInMbs×(CurrMbAddr/(2×PicWidthInMbs))+(CurrMbAddr % PicWidthInMbs)mbAddrCol5=CurrMbAddr/2mbAddrCol6=2×(CurrMbAddr/2)+((topAbsDiffPOC<bottomAbsDiffPOC)?0:1)mbAddrCol7=2×(CurrMbAddr/2)+(yCol/8)

 

(FAQ:为何表中没有FRM与AFRM配对?因为一个sps内只能定义为FRM或者AFRM(MBAFF),在一个序列内两者是不可能共存的;为何表中可以有FRM与FLD共存?因为sps可以定义PAFF(图像帧场自适应))

 

  • 第一项:PicCodingStruct( CurrPic ),当前图像的编码方式
  • 第二项:PicCodingStruct( colPic ),colPic的编码方式
  • 第三项:mbAddrX,当colPic为AFRM(宏块帧场自适应时),该项是用于定位colPic内地址为mbAddrX的宏块对,并用该宏块判断第五项fieldDecodingFlagX,即该宏块对是用场编码还是帧编码方式
  • 第四项:mb_field_decoding_flag,如果当前图像的编码方式是AFRM,该项用于判断当前宏块对是帧编码还是场编码方式
  • 第五项:fieldDecodingFlagX,如果colPic的编码方式是AFRM,该项用于判断mbAddrX所在的宏块对是帧编码还是场编码方式
  • 第六项:mbAddrCol,co-located所在的宏块在colPic内的地址,(注:涉及到AFRM的图像都会被当做互补场对来处理,即AFRM帧,而不是colPic)
  • 第七项:yM,co-located相对于其所在宏块的地址(xCol, yM),单位为像素,即第一个4x4块为(0,0),最后一个为(12,12),(注:当前4x4块相对于其所在宏块的地址为(xCol,yCol))
  • 第八项:VertMvScale,表明CurrPic与colPic的帧场对应关系

 

另外,为了减少计算量,还可以设定direct_8x8_inference_flag等于1,这样会导致8x8块共用一个4x4的co-located的运动向量,共用方式为一个宏块的4个8x8块分别只用该宏块4个角的4x4块作为co-located

 

获得co-located的运动向量与参考帧

  • 如果co-located是帧内预测方式编码,那么将无法获得运动向量与参考帧,mvCol = 0,refIdxCol = -1
  • 如果co-located是帧间预测编码方式,并且存在前向参考帧,那么mvCol将是co-located的前向运动向量,refIdxCol是co-located所在的8x8块中的前向参考索引
  • 如果co-located是帧间预测编码方式,并且只存在后向参考帧,那么mvCol将是co-located的后向运动向量,refIdxCol是co-located所在的8x8块中的后向参考索引

(注:标准规定参考图像选择的最小单位为8x8块,也就是说8x8块中的4个4x4块共享一个参考图像索引,请参考h.264语法结构分析中的ref_idx_l0以及ref_idx_l1关键字)

 

 

时域直接模式(temporal direct)

该模式是基于下图求出当前4x4块的前后向mvL0与mvL1,以及前向参考帧List0 reference的索引

已知的变量有:

  1. 后向参考图像List 1 reference (refPicList1[0])及其索引0
  2. 在计算co-located后得到的mvCol(mvCol需要根据VertMvScale进行调整,乘或除2),以及参考图像refColList0[refIdxCol](即List 0 reference)
  3. td与tb为图像之间的POC距离,既然List 0 reference、Current B、List 1 reference 已经知道,那么就容易得出td与tb的值

未知的变量有:

  1. List 0 reference的在当前参考图像列表中的索引
  2. 前后向运动向量mvL0与mvL1

求解方法:

  1. List 0 reference的索引,该索引是参考图像列表中图像List 0 reference所在的最小索引值(这部分由于jm18.6中对mbaff采用了独立互补场对参考列表,所以看起来更简单一点,而标准是从refPicList0参考列表开始,然后结合VertMvScale进行推导,看起来比较繁琐,但其实得到的结果是一样的)。
  2. mvL1 = mvCol/td*(td - tb)
  3. mvL0 = mvCol - mvL1    (忽略mv方向)

由于这些在标准(8.4.1.2.3)中讲的都非常细致,所以这里简要说明一下而已。

 

空域直接模式(spatial direct)

空域模式基于一种假设:当前编码宏块与其相邻宏块都向着同一个方向运动,大家有着类似的运动向量与参考帧(如下图)。在这种假设前提上,空域模式主要思想为采用相邻块来对当前宏块的参考索引以及运动向量进行预测。由于标准中8.4.1.3有非常详细的描述,所以在此略过。

但是上述假设也很有可能不成立,有可能当前宏块的相邻块都是运动的,但当前宏块是静止的(如下图)。比如说当前宏块是背景的一部分,而相邻块则是移动着的前景。这时候就需要判断当前宏块是否是运动的,以得到更准确的空域预测,co-located在这里就是用来判断当前宏块是否是运动宏块的。如果co-located的mvCol[0]与mvCol[1]能保证在某个范围之内,则表明当前宏块为静止宏块,那么将把当前宏块的mvL0与mvL1赋值为0,具体在标准8.4.1.2.2中描述得相当详细,不作细述。

 

jm18.6 mv_direct.c

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
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
/*!
 *************************************************************************************
 * \file mv_direct.c
 *
 * \brief
 *    Direct Motion Vector Generation
 *
 * \author
 *    Main contributors (see contributors.h for copyright, address and affiliation details)
 *      - Alexis Michael Tourapis         <alexismt@ieee.org>
 *
 *************************************************************************************
*/
 
#include "contributors.h"
 
#include <math.h>
#include <limits.h>
#include <time.h>
 
#include "global.h"
 
#include "image.h"
#include "mv_search.h"
#include "refbuf.h"
#include "memalloc.h"
#include "mb_access.h"
#include "macroblock.h"
#include "mc_prediction.h"
#include "conformance.h"
#include "mode_decision.h"
 
/*!
 ************************************************************************
 * \brief
 *    Calculate Temporal Direct Mode Motion Vectors
 ************************************************************************
 */
void Get_Direct_MV_Temporal (Macroblock *currMB)
{
  Slice *currSlice = currMB->p_Slice;
  int   block_x, block_y, pic_block_x, pic_block_y, opic_block_x, opic_block_y;
  MotionVector *****all_mvs;
  int   mv_scale;
  int refList;
  int ref_idx;
  VideoParameters *p_Vid = currMB->p_Vid;
  int list_offset = currMB->list_offset;//如果当前currSlice->mb_aff_frame_flag 且 currMB->mb_field ,list_offset>0
 
  StorablePicture **list1 = currSlice->listX[LIST_1 + list_offset];
 
  PicMotionParams colocated;
 
  //temporal direct mode copy from decoder
  for (block_y = 0; block_y < 4; block_y++)
  {
    pic_block_y  = currMB->block_y + block_y;
    opic_block_y = (currMB->opix_y >> 2) + block_y;
 
    for (block_x = 0; block_x < 4; block_x++)
    {
      pic_block_x  = currMB->block_x + block_x;
      opic_block_x = (currMB->pix_x>>2) + block_x;
 
      all_mvs = currSlice->all_mv;
      if (p_Vid->active_sps->direct_8x8_inference_flag)
      {
        if(currMB->p_Inp->separate_colour_plane_flag && currMB->p_Vid->yuv_format==YUV444)
          colocated = list1[0]->JVmv_info[currMB->p_Slice->colour_plane_id][RSD(opic_block_y)][RSD(opic_block_x)];
        else
          colocated = list1[0]->mv_info[RSD(opic_block_y)][RSD(opic_block_x)];
        if(currSlice->mb_aff_frame_flag && currMB->mb_field && currSlice->listX[LIST_1][0]->coded_frame)
        {//mbaff场宏块
          int iPosBlkY;
          if(currSlice->listX[LIST_1][0]->motion.mb_field[currMB->mbAddrX] )
              //当前宏块是mbaff且为场编码,参考帧宏块为场编码,不过因为此处计算ref_pic用的是frame,即一个场宏块对应两个帧宏块
              //场宏块>>2后*8,可以对比下面帧宏块>>3后再*8
              //>>2代表一个场宏块,
              //*8代表宏块对(两个帧宏块),
              //*4代表选择对应宏块(顶宏块或者底宏块其中之一(field重建回frame时,对于宏块的mv_info,是以宏块对方式组建的?)),
              //&3代表4x4子块
              //另外由于每一个8x8块对应一个参考帧所以最后也有RSD(opic_block_x)
            iPosBlkY = (opic_block_y>>2)*8+4*(currMB->mbAddrX&1)+(opic_block_y&0x03);
          else
              //因为当前是场(mb_field)?而下面参考帧采用的是帧,则代表field->frame,所以*2
            iPosBlkY = RSD(opic_block_y)*2;
 
          //由于标准规定(8.4.1.2.2最后一段)在colocated中应该在其所在的8x8分割块中选取参考帧,所以需要进行以下步骤
          if(colocated.ref_idx[LIST_0]>=0)//ref_idx>=0说明有前/后向参考帧,但是下面还需要根据当前宏块与colpic进行精确定位(在8x8分割块中选取某块的参考帧)
            colocated.ref_pic[LIST_0] = list1[0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[LIST_0];
          if(colocated.ref_idx[LIST_1]>=0)
            colocated.ref_pic[LIST_1] = list1[0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[LIST_1];
        }       
      }
      else
      {
        if(currMB->p_Inp->separate_colour_plane_flag && currMB->p_Vid->yuv_format==YUV444)
          colocated = list1[0]->JVmv_info[currMB->p_Slice->colour_plane_id][opic_block_y][opic_block_x];
        else
          colocated = list1[0]->mv_info[opic_block_y][opic_block_x];
      }
      if(currSlice->mb_aff_frame_flag)
      {
        if(!currMB->mb_field && ((currSlice->listX[LIST_1][0]->coded_frame && currSlice->listX[LIST_1][>motion.mb_field[currMB->mbAddrX]) ||
          (!currSlice->listX[LIST_1][0]->coded_frame)))
        {//mbaff帧宏块
          if (iabs(p_Vid->enc_picture->poc - currSlice->listX[LIST_1+4][0]->poc)> iabs(p_Vid->enc_picture->poc -rSlice->listX[LIST_1+2][0]->poc) )
          {
            if ( p_Vid->active_sps->direct_8x8_inference_flag)
            {
              if(currMB->p_Inp->separate_colour_plane_flag && currMB->p_Vid->yuv_format==YUV444)
                colocated = currSlice->listX[LIST_1+2][0]->JVmv_info[currMB->p_Slice->colour_plane_id][RSD(c_block_y)>>1][RSD(opic_block_x)];
              else
                colocated = currSlice->listX[LIST_1+2][0]->mv_info[RSD(opic_block_y)>>1][RSD(opic_block_x)];
            }
            else
            {
              if(currMB->p_Inp->separate_colour_plane_flag && currMB->p_Vid->yuv_format==YUV444)
                colocated = currSlice->listX[LIST_1+2][0]->JVmv_info[currMB->p_Slice->colour_plane_id][(c_block_y)>>1][(opic_block_x)];
              else
                colocated = currSlice->listX[LIST_1+2][0]->mv_info[(opic_block_y)>>1][opic_block_x];
            }
            if(currSlice->listX[LIST_1][0]->coded_frame)
            {//帧宏块,所以下面>>3后再*8,可以对比上面场宏块>>2后再*8
              int iPosBlkY = (RSD(opic_block_y)>>3)*8 + ((RSD(opic_block_y)>>1) & 0x03);
              if(colocated.ref_idx[LIST_0] >=0) // && !colocated.ref_pic[LIST_0])
                colocated.ref_pic[LIST_0] = currSlice->listX[LIST_1+2][0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[T_0];
              if(colocated.ref_idx[LIST_1] >=0) // && !colocated.ref_pic[LIST_1])
                colocated.ref_pic[LIST_1] = currSlice->listX[LIST_1+2][0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[T_1];
            }
          }
          else
          {
            if (p_Vid->active_sps->direct_8x8_inference_flag )
            {
              if(currMB->p_Inp->separate_colour_plane_flag && currMB->p_Vid->yuv_format==YUV444)
                colocated = currSlice->listX[LIST_1+4][0]->JVmv_info[currMB->p_Slice->colour_plane_id][RSD(c_block_y)>>1][RSD(opic_block_x)];
              else
                colocated = currSlice->listX[LIST_1+4][0]->mv_info[RSD(opic_block_y)>>1][RSD(opic_block_x)];
 
            }
            else
            {
              if(currMB->p_Inp->separate_colour_plane_flag && currMB->p_Vid->yuv_format==YUV444)
                colocated = currSlice->listX[LIST_1+4][0]->JVmv_info[currMB->p_Slice->colour_plane_id][(c_block_y)>>1][opic_block_x];
              else
                colocated = currSlice->listX[LIST_1+4][0]->mv_info[(opic_block_y)>>1][opic_block_x];
            }
            if(currSlice->listX[LIST_1][0]->coded_frame)
            {
              int iPosBlkY = (RSD(opic_block_y)>>3)*8 + ((RSD(opic_block_y)>>1) & 0x03)+4;
              if(colocated.ref_idx[LIST_0] >=0) // && !colocated.ref_pic[LIST_0])
                colocated.ref_pic[LIST_0] = currSlice->listX[LIST_1+4][0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[T_0];
              if(colocated.ref_idx[LIST_1] >=0)// && !colocated.ref_pic[LIST_1])
                colocated.ref_pic[LIST_1] = currSlice->listX[LIST_1+4][0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[T_1];
            }
          }
        }
      }
      else if(!p_Vid->active_sps->frame_mbs_only_flag && !currSlice->structure && !currSlice->listX[LIST_1][>coded_frame)
      {//图像级帧场自适应帧图像编码(即list1[0]有可能为场编码)
        if (iabs(p_Vid->enc_picture->poc - list1[0]->bottom_field->poc)> iabs(p_Vid->enc_picture->poc -list1[>top_field->poc) )
        {
          colocated = p_Vid->active_sps->direct_8x8_inference_flag ?
            list1[0]->top_field->mv_info[RSD(opic_block_y)>>1][RSD(opic_block_x)] : list1[0]->top_field->mv_info[(c_block_y)>>1][opic_block_x];
        }
        else
        {
          colocated = p_Vid->active_sps->direct_8x8_inference_flag ?
            list1[0]->bottom_field->mv_info[RSD(opic_block_y)>>1][RSD(opic_block_x)] : list1[0]->bottom_field->mv_info[(c_block_y)>>1][opic_block_x];
        }
      }
      else if(!p_Vid->active_sps->frame_mbs_only_flag && currSlice->structure && list1[0]->coded_frame)
      {//场图像编码
        int iPosBlkY;
        int currentmb = 2*(list1[0]->size_x>>4) * (opic_block_y >> 2)+ (opic_block_x>>2)*2 + ((c_block_y>>1) & 0x01);
        if(currSlice->structure!=list1[0]->structure)
        {
          if (currSlice->structure == TOP_FIELD)
          {
            colocated = p_Vid->active_sps->direct_8x8_inference_flag ?
              list1[0]->frame->top_field->mv_info[RSD(opic_block_y)][RSD(opic_block_x)] : list1[>frame->top_field->mv_info[opic_block_y][opic_block_x];
          }
          else
          {
            colocated = p_Vid->active_sps->direct_8x8_inference_flag ?
              list1[0]->frame->bottom_field->mv_info[RSD(opic_block_y)][RSD(opic_block_x)] : list1[>frame->bottom_field->mv_info[opic_block_y][opic_block_x];
          }
        }
 
        if(!currSlice->listX[LIST_1][0]->frame->mb_aff_frame_flag || !list1[0]->frame->motion.mb_field[currentmb])
          iPosBlkY = 2*(RSD(opic_block_y));
        else
          iPosBlkY = (RSD(opic_block_y)>>2)*8 + (RSD(opic_block_y) & 0x03)+4*(currSlice->structure == BOTTOM_FIELD);
        if(colocated.ref_idx[LIST_0] >=0) // && !colocated.ref_pic[LIST_0])
          colocated.ref_pic[LIST_0] = list1[0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[LIST_0];
        if(colocated.ref_idx[LIST_1] >=0)// && !colocated.ref_pic[LIST_1])
          colocated.ref_pic[LIST_1] = list1[0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[LIST_1];
      }
      //最后剩下的是全序列采用帧图像编码(frame_mbs_only_flag = 1),这样的话colocated._pic肯定是存在的,并且不用进行帧场转换,也就是采用原来的就可以,因此不用重新赋值
      //colocated在开头判断direct_8x8_inference_flag的两个分支处即可获得
 
      refList = ((colocated.ref_idx[LIST_0] == -1 || (p_Vid->view_id && colocated.ref_idx[LIST_0]==list1[0]->ref_pic_na[)? LIST_1 : LIST_0);
      ref_idx = colocated.ref_idx[refList];
 
      // next P is intra mode
      if (ref_idx == -1 || (p_Vid->view_id && ref_idx==list1[0]->ref_pic_na[refList]))
      {
        all_mvs[LIST_0][0][0][block_y][block_x] = zero_mv;
        all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv;
        currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = 0;
        currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = 0;
        currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
      }
      // next P is skip or inter mode
      else
      {
        int mapped_idx=INVALIDINDEX;
        int iref;
        if (colocated.ref_pic[refList] == NULL)
        {
           printf("invalid index found\n");
        }
        else
        {    //得到前向参考帧ref0,即下面的mapped_idx
        //Let refIdxL0Frm be the lowest valued reference index in the current reference picture list RefPicList0 that
        //references the frame or complementary field pair that contains the field refPicCol
          if( (currSlice->mb_aff_frame_flag && ( (currMB->mb_field && colocated.ref_pic[List]->structure==FRAME) ||          //currSlice :mbaff & mb_field, ref_pic :frame
            (!currMB->mb_field && colocated.ref_pic[refList]->structure!=FRAME)))                                             //currSlice :mb_frame        , ref_pic :field
            (!currSlice->mb_aff_frame_flag && ((currSlice->structure==FRAME && colocated.ref_pic[List]->structure!=FRAME)||   //currSlice :frame only       , ref_pic :field
            (currSlice->structure!=FRAME && colocated.ref_pic[refList]->structure==FRAME)))                                   //currSlice :field           , ref_pic :frame
          {//该判断条件表示currSlice与ref_pic用不同的帧场编码方式
            //! Frame with field co-located
            for (iref = 0; iref < imin(currSlice->num_ref_idx_active[LIST_0], currSlice->listXsize[LIST_0 + list_offset]); f++)
            {
              if (currSlice->listX[LIST_0 + list_offset][iref]->top_field == colocated.ref_pic[refList] ||
                currSlice->listX[LIST_0 + list_offset][iref]->bottom_field == colocated.ref_pic[refList] ||
                currSlice->listX[LIST_0 + list_offset][iref]->frame == colocated.ref_pic[refList] )
              {
                if ((p_Vid->field_picture==1) && (currSlice->listX[LIST_0 + list_offset][iref]->structure != rSlice->structure))
                {//currSlice :field       , ref_pic :frame  会进来这里?
                  mapped_idx=INVALIDINDEX;
                }
                else
                {
                  mapped_idx = iref;           
                  break;
                }
              }
              else //! invalid index. Default to zero even though this case should not happen
                mapped_idx=INVALIDINDEX;
            }
          }
          else
          {//currSlice 与 ref_pic 采用相同帧场编码方式
            for (iref = 0; iref < imin(currSlice->num_ref_idx_active[LIST_0], currSlice->listXsize[LIST_0 + list_offset]);iref++)
            {
              if(currSlice->listX[LIST_0 + list_offset][iref] == colocated.ref_pic[refList])
              {
                mapped_idx = iref;           
                break;
              }
              else //! invalid index. Default to zero even though this case should not happen
              {
                mapped_idx=INVALIDINDEX;
              }
            }
          }
        }
        if (mapped_idx != INVALIDINDEX)
        {
          MotionVector mv = colocated.mv[refList];
          mv_scale = currSlice->mvscale[LIST_0 + list_offset][mapped_idx];
 
          if((currSlice->mb_aff_frame_flag && !currMB->mb_field && colocated.ref_pic[refList]->structure!=FRAME)
            (!currSlice->mb_aff_frame_flag && currSlice->structure==FRAME && colocated.ref_pic[List]->structure!=FRAME))
            mv.mv_y *= 2;
          else if((currSlice->mb_aff_frame_flag && currMB->mb_field && colocated.ref_pic[List]->structure==FRAME) ||
            (!currSlice->mb_aff_frame_flag && currSlice->structure!=FRAME && colocated.ref_pic[List]->structure==FRAME))
            mv.mv_y /= 2;
 
          //mvL0,mvL1
          if (mv_scale==9999)
          {
            // forward
            all_mvs[LIST_0][0][0][block_y][block_x] = mv;
            // backward
            all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv;
          }
          else
          {
            //mv_scale = DistScaleFactor (in function compute_colocated)
            // forward
            all_mvs[LIST_0][mapped_idx][0][block_y][block_x].mv_x = (short) ((mv_scale * mv.mv_x + 128) >> 8);
            all_mvs[LIST_0][mapped_idx][0][block_y][block_x].mv_y = (short) ((mv_scale * mv.mv_y + 128) >> 8);
            // backward
            all_mvs[LIST_1][         0][0][block_y][block_x].mv_x = (short) (((mv_scale - 256) * mv.mv_x + 128) >> 8);
            all_mvs[LIST_1][         0][0][block_y][block_x].mv_y = (short) (((mv_scale - 256) * mv.mv_y + 128) >> 8);
 
          }
          //refIdx0,refIdx1
          // Test Level Limits if satisfied.
          if ( out_of_bounds_mvs(p_Vid, &all_mvs[LIST_0][mapped_idx][0][block_y][block_x])|| out_of_bounds_mvs(p_Vid, &all_mvs[T_1][0][0][block_y][block_x]))
          {
            currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = -1;
            currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = -1;
            currSlice->direct_pdir[pic_block_y][pic_block_x] = -1;
          }
          else
          {
            currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = (char) mapped_idx;
            currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = 0;
            currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
          }
        }
        else
        {
          currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = -1;
          currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = -1;
          currSlice->direct_pdir[pic_block_y][pic_block_x] = -1;
        }
      }
 
      if (p_Vid->active_pps->weighted_bipred_idc == 1 && currSlice->direct_pdir[pic_block_y][pic_block_x] == 2)
      {
        int weight_sum, i;
        short l0_refX = currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0];
        short l1_refX = currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1];
        for (i=0;i< (p_Vid->active_sps->chroma_format_idc == YUV400 ? 1 : 3); i++)
        {
          weight_sum = currSlice->wbp_weight[0][l0_refX][l1_refX][i] + currSlice->wbp_weight[1][l0_refX][l1_refX][i];
          if (weight_sum < -128 ||  weight_sum > 127)
          {
            currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = -1;
            currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = -1;
            currSlice->direct_pdir   [pic_block_y][pic_block_x]         = -1;
            break;
          }
        }
      }
    }
  }
}
 
static inline void set_direct_references(const PixelPos *mb, char *l0_rFrame, char *l1_rFrame, PicMotionParams **mv_info)
{
  if (mb->available)
  {
    char *ref_idx = mv_info[mb->pos_y][mb->pos_x].ref_idx;
    *l0_rFrame  = ref_idx[LIST_0];
    *l1_rFrame  = ref_idx[LIST_1];
  }
  else
  {
    *l0_rFrame  = -1;
    *l1_rFrame  = -1;
  }
}
 
static void set_direct_references_mb_field(const PixelPos *mb, char *l0_rFrame, char *l1_rFrame, PicMotionParams **mv_info, Macroblock _data)
{
  if (mb->available)
  {
    char *ref_idx = mv_info[mb->pos_y][mb->pos_x].ref_idx;
    if (mb_data[mb->mb_addr].mb_field)
    {
      *l0_rFrame  = ref_idx[LIST_0];
      *l1_rFrame  = ref_idx[LIST_1];
    }
    else
    {
      *l0_rFrame  = (ref_idx[LIST_0] < 0) ? ref_idx[LIST_0] : ref_idx[LIST_0] * 2;
      *l1_rFrame  = (ref_idx[LIST_1] < 0) ? ref_idx[LIST_1] : ref_idx[LIST_1] * 2;
    }
  }
  else
  {
    *l0_rFrame  = -1;
    *l1_rFrame  = -1;
  }
}
 
static void set_direct_references_mb_frame(const PixelPos *mb, char *l0_rFrame, char *l1_rFrame, PicMotionParams **mv_info, Macroblock _data)
{
  if (mb->available)
  {
    char *ref_idx = mv_info[mb->pos_y][mb->pos_x].ref_idx;
    if (mb_data[mb->mb_addr].mb_field)
    {
      *l0_rFrame  = (ref_idx[LIST_0] >> 1);
      *l1_rFrame  = (ref_idx[LIST_1] >> 1);
    }
    else
    {
      *l0_rFrame  = ref_idx[LIST_0];
      *l1_rFrame  = ref_idx[LIST_1];
    }
  }
  else
  {
    *l0_rFrame  = -1;
    *l1_rFrame  = -1;
  }
}
 
static void test_valid_direct(Slice *currSlice, seq_parameter_set_rbsp_t *active_sps, char  *direct_ref_idx, short l0_refX, short refX, int pic_block_y, int pic_block_x)
{
  int weight_sum, i;
  Boolean invalid_wp = FALSE;
  for (i=0;i< (active_sps->chroma_format_idc == YUV400 ? 1 : 3); i++)
  {
    weight_sum = currSlice->wbp_weight[0][l0_refX][l1_refX][i] + currSlice->wbp_weight[1][l0_refX][l1_refX][i];
    if (weight_sum < -128 ||  weight_sum > 127)
    {
      invalid_wp = TRUE;
      break;
    }
  }
  if (invalid_wp == FALSE)
    currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
  else
  {
    direct_ref_idx[LIST_0] = -1;
    direct_ref_idx[LIST_1] = -1;
    currSlice->direct_pdir[pic_block_y][pic_block_x] = -1;
  }
}
 
/*!
*************************************************************************************
* \brief
*    Temporary function for colocated info when direct_inference is enabled.
*
*************************************************************************************
*/
int get_colocated_info(Macroblock *currMB, StorablePicture *list1, int i, int j)
{
  if (list1->is_long_term)
    return 1;
  else
  {
    Slice *currSlice = currMB->p_Slice;
    VideoParameters *p_Vid = currMB->p_Vid;
    if( (currSlice->mb_aff_frame_flag) ||
      (!p_Vid->active_sps->frame_mbs_only_flag && ((!currSlice->structure && !list1->coded_frame) || (rSlice->structure!=list1->structure && list1->coded_frame))))
    {
      int jj = RSD(j);
      int ii = RSD(i);
      int jdiv = (jj>>1);
      int moving;
      PicMotionParams *fs = &list1->mv_info[jj][ii];
 
      if(currSlice->structure && currSlice->structure!=list1->structure && list1->coded_frame)
      {
         if(currSlice->structure == TOP_FIELD)
           fs = list1->top_field->mv_info[jj] + ii;
         else
           fs = list1->bottom_field->mv_info[jj] + ii;
      }
      else
      {
        if( (currSlice->mb_aff_frame_flag && ((!currMB->mb_field && list1->motion.mb_field[currMB->mbAddrX])
          (!currMB->mb_field && !list1->coded_frame)))
          || (!currSlice->mb_aff_frame_flag))
        {
          if (iabs(p_Vid->enc_picture->poc - list1->bottom_field->poc)> iabs(p_Vid->enc_picture->poc -t1->top_field->poc) )
          {
            fs = list1->top_field->mv_info[jdiv] + ii;
          }
          else
          {
            fs = list1->bottom_field->mv_info[jdiv] + ii;
          }
        }
      }
      moving = !((((fs->ref_idx[LIST_0] == 0)
        &&  (iabs(fs->mv[LIST_0].mv_x)>>1 == 0)
        &&  (iabs(fs->mv[LIST_0].mv_y)>>1 == 0)))
        || ((fs->ref_idx[LIST_0] == -1)
        &&  (fs->ref_idx[LIST_1] == 0)
        &&  (iabs(fs->mv[LIST_1].mv_x)>>1 == 0)
        &&  (iabs(fs->mv[LIST_1].mv_y)>>1 == 0)));
      return moving;
    }
    else
    {
      PicMotionParams *fs = &list1->mv_info[RSD(j)][RSD(i)];
      int moving;
      if(currMB->p_Vid->yuv_format == YUV444 && !currSlice->P444_joined)
        fs = &list1->JVmv_info[(int)(p_Vid->colour_plane_id)][RSD(j)][RSD(i)];
      moving= !((((fs->ref_idx[LIST_0] == 0)
        &&  (iabs(fs->mv[LIST_0].mv_x)>>1 == 0)
        &&  (iabs(fs->mv[LIST_0].mv_y)>>1 == 0)))
        || ((fs->ref_idx[LIST_0] == -1)
        &&  (fs->ref_idx[LIST_1] == 0)
        &&  (iabs(fs->mv[LIST_1].mv_x)>>1 == 0)
        &&  (iabs(fs->mv[LIST_1].mv_y)>>1 == 0)));
 
      return moving; 
    }
  }
}
 
/*!
*************************************************************************************
* \brief
*    Colocated info <= direct_inference is disabled.
*************************************************************************************
*/
int get_colocated_info_4x4(Macroblock *currMB, StorablePicture *list1, int i, int j)
{
  if (list1->is_long_term)
    return 1;
  else
  {
    PicMotionParams *fs = &list1->mv_info[j][i];
 
    int moving = !((((fs->ref_idx[LIST_0] == 0)
      &&  (iabs(fs->mv[LIST_0].mv_x)>>1 == 0)
      &&  (iabs(fs->mv[LIST_0].mv_y)>>1 == 0)))
      || ((fs->ref_idx[LIST_0] == -1)
      &&  (fs->ref_idx[LIST_1] == 0)
      &&  (iabs(fs->mv[LIST_1].mv_x)>>1 == 0)
      &&  (iabs(fs->mv[LIST_1].mv_y)>>1 == 0)));
 
    return moving; 
  }
}
 
/*!
************************************************************************
* \brief
*    Calculate Spatial Direct Mode Motion Vectors
************************************************************************
*/
void Get_Direct_MV_Spatial_Normal (Macroblock *currMB)
{
  Slice *currSlice = currMB->p_Slice;
  VideoParameters *p_Vid = currMB->p_Vid;
  PicMotionParams **mv_info = p_Vid->enc_picture->mv_info;
  char l0_refA, l0_refB, l0_refC;
  char l1_refA, l1_refB, l1_refC;
  char l0_refX,l1_refX;
  MotionVector pmvfw = zero_mv, pmvbw = zero_mv;
 
  int   block_x, block_y, pic_block_x, pic_block_y, opic_block_x, opic_block_y;
  MotionVector *****all_mvs;
  char  *direct_ref_idx;
  StorablePicture **list1 = currSlice->listX[LIST_1];
 
  PixelPos mb[4]; 
  get_neighbors(currMB, mb, 0, 0, 16);
 
  set_direct_references(&mb[0], &l0_refA,  &l1_refA,  mv_info);
  set_direct_references(&mb[1], &l0_refB,  &l1_refB,  mv_info);
  set_direct_references(&mb[2], &l0_refC,  &l1_refC,  mv_info);
 
  l0_refX = (char) imin(imin((unsigned char) l0_refA, (unsigned char) l0_refB), (unsigned char) l0_refC);
  l1_refX = (char) imin(imin((unsigned char) l1_refA, (unsigned char) l1_refB), (unsigned char) l1_refC);
 
  if (l0_refX >= 0)
    currMB->GetMVPredictor (currMB, mb, &pmvfw, l0_refX, mv_info, LIST_0, 0, 0, 16, 16);
 
  if (l1_refX >= 0)
    currMB->GetMVPredictor (currMB, mb, &pmvbw, l1_refX, mv_info, LIST_1, 0, 0, 16, 16);
 
  if (l0_refX == -1 && l1_refX == -1)
  {
    for (block_y=0; block_y<4; block_y++)
    {
      pic_block_y  = currMB->block_y + block_y;
      for (block_x=0; block_x<4; block_x++)
      {
        pic_block_x  = currMB->block_x + block_x;
        direct_ref_idx = currSlice->direct_ref_idx[pic_block_y][pic_block_x];
 
        currSlice->all_mv[LIST_0][0][0][block_y][block_x] = zero_mv;
        currSlice->all_mv[LIST_1][0][0][block_y][block_x] = zero_mv;
 
        direct_ref_idx[LIST_0] = direct_ref_idx[LIST_1] = 0;
 
        if (p_Vid->active_pps->weighted_bipred_idc == 1)
          test_valid_direct(currSlice, currSlice->active_sps, direct_ref_idx, 0, 0, pic_block_y, pic_block_x);
        else
          currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
      }
    }
  }
  else if (l0_refX == 0 || l1_refX == 0)
  {
    int (*get_colocated)(Macroblock *currMB, StorablePicture *list1, int i, int j) =
      p_Vid->active_sps->direct_8x8_inference_flag ? get_colocated_info : get_colocated_info_4x4;
 
    int is_moving_block;
    for (block_y = 0; block_y < 4; block_y++)
    {
      pic_block_y  = currMB->block_y + block_y;
      opic_block_y = (currMB->opix_y >> 2) + block_y;
 
      for (block_x=0; block_x<4; block_x++)
      {
        pic_block_x    = currMB->block_x + block_x;
        direct_ref_idx = currSlice->direct_ref_idx[pic_block_y][pic_block_x];
        opic_block_x   = (currMB->pix_x >> 2) + block_x;
 
        all_mvs = currSlice->all_mv;
        is_moving_block = (get_colocated(currMB, list1[0], opic_block_x, opic_block_y) == 0);
 
        if (l0_refX < 0)
        {
          all_mvs[LIST_0][0][0][block_y][block_x] = zero_mv;
          direct_ref_idx[LIST_0] = -1;
        }
        else if ((l0_refX == 0) && is_moving_block)
        {
          all_mvs[LIST_0][0][0][block_y][block_x] = zero_mv;
          direct_ref_idx[LIST_0] = 0;
        }
        else
        {
          all_mvs[LIST_0][(short) l0_refX][0][block_y][block_x] = pmvfw;
          direct_ref_idx[LIST_0] = (char)l0_refX;
        }
         
        if (l1_refX < 0)
        {
          all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv;
          direct_ref_idx[LIST_1] = -1;
        }
        else if((l1_refX == 0) && is_moving_block)
        {
          all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv;
          direct_ref_idx[LIST_1] = 0;
        }
        else
        {
          all_mvs[LIST_1][(short) l1_refX][0][block_y][block_x] = pmvbw;
          direct_ref_idx[LIST_1] = (char)l1_refX;
        }
 
        if      (direct_ref_idx[LIST_1] == -1)
          currSlice->direct_pdir[pic_block_y][pic_block_x] = 0;
        else if (direct_ref_idx[LIST_0] == -1)
          currSlice->direct_pdir[pic_block_y][pic_block_x] = 1;
        else if (p_Vid->active_pps->weighted_bipred_idc == 1)
          test_valid_direct(currSlice, currSlice->active_sps, direct_ref_idx, l0_refX, l1_refX, pic_block_y, pic_block_x);
        else
          currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
      }
    }
  }
  else
  {
    for (block_y=0; block_y<4; block_y++)
    {
      pic_block_y  = currMB->block_y + block_y;
 
      for (block_x=0; block_x<4; block_x++)
      {
        pic_block_x  = currMB->block_x + block_x;
        direct_ref_idx = currSlice->direct_ref_idx[pic_block_y][pic_block_x];
 
        all_mvs = currSlice->all_mv;
 
        if (l0_refX > 0)
        {
          all_mvs[LIST_0][(short) l0_refX][0][block_y][block_x] = pmvfw;
          direct_ref_idx[LIST_0]= (char)l0_refX;         
        }
        else
        {
          all_mvs[LIST_0][0][0][block_y][block_x] = zero_mv;
          direct_ref_idx[LIST_0]=-1;
        }
 
        if (l1_refX > 0)
        {
          all_mvs[LIST_1][(short) l1_refX][0][block_y][block_x] = pmvbw;
          direct_ref_idx[LIST_1] = (char)l1_refX;
        }
        else
        {
          all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv;
          direct_ref_idx[LIST_1] = -1;
        }
 
        if      (direct_ref_idx[LIST_1] == -1)
          currSlice->direct_pdir[pic_block_y][pic_block_x] = 0;
        else if (direct_ref_idx[LIST_0] == -1)
          currSlice->direct_pdir[pic_block_y][pic_block_x] = 1;
        else if (p_Vid->active_pps->weighted_bipred_idc == 1)
          test_valid_direct(currSlice, currSlice->active_sps, direct_ref_idx, l0_refX, l1_refX, pic_block_y, pic_block_x);
        else
          currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
      }
    }
  }
}
 
 
/*!
************************************************************************
* \brief
*    Calculate Spatial Direct Mode Motion Vectors
************************************************************************
*/
void Get_Direct_MV_Spatial_MBAFF (Macroblock *currMB)
{
  char l0_refA, l0_refB, l0_refC;
  char l1_refA, l1_refB, l1_refC;
  char l0_refX,l1_refX;
  MotionVector pmvfw = zero_mv, pmvbw = zero_mv;
 
  int   block_x, block_y, pic_block_x, pic_block_y, opic_block_x, opic_block_y;
  MotionVector *****all_mvs;
  char  *direct_ref_idx;
  int is_moving_block;
  Slice *currSlice = currMB->p_Slice;
  VideoParameters *p_Vid = currMB->p_Vid;
  PicMotionParams **mv_info = p_Vid->enc_picture->mv_info;
  StorablePicture **list1 = currSlice->listX[LIST_1 + currMB->list_offset];
 
  int (*get_colocated)(Macroblock *currMB, StorablePicture *list1, int i, int j) =
    p_Vid->active_sps->direct_8x8_inference_flag ? get_colocated_info : get_colocated_info_4x4;
 
  PixelPos mb[4]; 
  get_neighbors(currMB, mb, 0, 0, 16);
 
 
  if (currMB->mb_field)
  {
    set_direct_references_mb_field(&mb[0], &l0_refA, &l1_refA, mv_info, p_Vid->mb_data);
    set_direct_references_mb_field(&mb[1], &l0_refB, &l1_refB, mv_info, p_Vid->mb_data);
    set_direct_references_mb_field(&mb[2], &l0_refC, &l1_refC, mv_info, p_Vid->mb_data);
  }
  else
  {
    set_direct_references_mb_frame(&mb[0], &l0_refA, &l1_refA, mv_info, p_Vid->mb_data);
    set_direct_references_mb_frame(&mb[1], &l0_refB, &l1_refB, mv_info, p_Vid->mb_data);
    set_direct_references_mb_frame(&mb[2], &l0_refC, &l1_refC, mv_info, p_Vid->mb_data);
  }
 
  l0_refX = (char) imin(imin((unsigned char) l0_refA, (unsigned char) l0_refB), (unsigned char) l0_refC);
  l1_refX = (char) imin(imin((unsigned char) l1_refA, (unsigned char) l1_refB), (unsigned char) l1_refC);
 
  if (l0_refX >=0)
    currMB->GetMVPredictor (currMB, mb, &pmvfw, l0_refX, mv_info, LIST_0, 0, 0, 16, 16);
 
  if (l1_refX >=0)
    currMB->GetMVPredictor (currMB, mb, &pmvbw, l1_refX, mv_info, LIST_1, 0, 0, 16, 16);
 
  for (block_y=0; block_y<4; block_y++)
  {
    pic_block_y  = currMB->block_y + block_y;
    opic_block_y = (currMB->opix_y >> 2) + block_y;
 
    for (block_x=0; block_x<4; block_x++)
    {
      pic_block_x  = currMB->block_x + block_x;
      direct_ref_idx = currSlice->direct_ref_idx[pic_block_y][pic_block_x];
      opic_block_x = (currMB->pix_x >> 2) + block_x;
      is_moving_block = (get_colocated(currMB, list1[0], opic_block_x, opic_block_y) == 0);
 
      all_mvs = currSlice->all_mv;
 
      if (l0_refX >=0)
      {
        if (!l0_refX  && is_moving_block)
        {
          all_mvs[LIST_0][0][0][block_y][block_x] = zero_mv;
          direct_ref_idx[LIST_0] = 0;
        }
        else
        {
          all_mvs[LIST_0][(short) l0_refX][0][block_y][block_x] = pmvfw;
          direct_ref_idx[LIST_0] = (char)l0_refX;
        }
      }
      else
      {
        all_mvs[LIST_0][0][0][block_y][block_x] = zero_mv;
        direct_ref_idx[LIST_0] = -1;
      }
 
      if (l1_refX >=0)
      {
        if(l1_refX==0 && is_moving_block)
        {
          all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv;
          direct_ref_idx[LIST_1] = (char)l1_refX;
        }
        else
        {
          all_mvs[LIST_1][(short) l1_refX][0][block_y][block_x] = pmvbw;
          direct_ref_idx[LIST_1] = (char)l1_refX;
        }
      }
      else
      {
        all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv;
        direct_ref_idx[LIST_1] = -1;
      }
 
     // Test Level Limits if satisfied.
 
      // Test Level Limits if satisfied.
      if ((out_of_bounds_mvs(p_Vid, &all_mvs[LIST_0][l0_refX < 0? 0 : l0_refX][0][block_y][block_x])
        ||  out_of_bounds_mvs(p_Vid, &all_mvs[LIST_1][l1_refX < 0? 0 : l1_refX][0][block_y][block_x])))
      {
        direct_ref_idx[LIST_0] = -1;
        direct_ref_idx[LIST_1] = -1;
        currSlice->direct_pdir   [pic_block_y][pic_block_x]         = -1;
      }    
      else
      {
        if (l0_refX < 0 && l1_refX < 0)
        {
          direct_ref_idx[LIST_0] = direct_ref_idx[LIST_1] = 0;
          l0_refX = 0;
          l1_refX = 0;
        }
 
        if      (direct_ref_idx[LIST_1] == -1)
          currSlice->direct_pdir[pic_block_y][pic_block_x] = 0;
        else if (direct_ref_idx[LIST_0] == -1)
          currSlice->direct_pdir[pic_block_y][pic_block_x] = 1;
        else if (p_Vid->active_pps->weighted_bipred_idc == 1)
          test_valid_direct(currSlice, currSlice->active_sps, direct_ref_idx, l0_refX, l1_refX, pic_block_y, pic_block_x);
        else
          currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
      }
    }
  }
}
posted @   TaigaComplex  阅读(4342)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示