Coverage Report

Created: 2026-07-30 06:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/libde265/libde265/motion.cc
Line
Count
Source
1
/*
2
 * H.265 video codec.
3
 * Copyright (c) 2013-2014 struktur AG, Dirk Farin <farin@struktur.de>
4
 *
5
 * This file is part of libde265.
6
 *
7
 * libde265 is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Lesser General Public License as
9
 * published by the Free Software Foundation, either version 3 of
10
 * the License, or (at your option) any later version.
11
 *
12
 * libde265 is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public License
18
 * along with libde265.  If not, see <http://www.gnu.org/licenses/>.
19
 */
20
21
#include "motion.h"
22
#include "decctx.h"
23
#include "util.h"
24
#include "dpb.h"
25
26
#include <assert.h>
27
28
29
#include <sys/types.h>
30
#include <signal.h>
31
#include <string.h>
32
33
#if defined(_MSC_VER) || defined(__MINGW32__)
34
# include <malloc.h>
35
#elif defined(HAVE_ALLOCA_H)
36
# include <alloca.h>
37
#endif
38
39
40
1.04G
#define MAX_CU_SIZE 64
41
42
43
static int extra_before[4] = { 0,3,3,2 };
44
static int extra_after [4] = { 0,3,4,4 };
45
46
47
48
template <class pixel_t>
49
void mc_luma(const base_context* ctx,
50
             const seq_parameter_set* sps, int mv_x, int mv_y,
51
             int xP,int yP,
52
             int16_t* out, int out_stride,
53
             const pixel_t* ref, ptrdiff_t ref_stride,
54
             int nPbW, int nPbH, int bitDepth_L)
55
8.09M
{
56
8.09M
  int xFracL = mv_x & 3;
57
8.09M
  int yFracL = mv_y & 3;
58
59
8.09M
  int xIntOffsL = xP + (mv_x>>2);
60
8.09M
  int yIntOffsL = yP + (mv_y>>2);
61
62
  // luma sample interpolation process (8.5.3.2.2.1)
63
64
  //const int shift1 = sps->BitDepth_Y-8;
65
  //const int shift2 = 6;
66
8.09M
  const int shift3 = std::max(2, 14 - sps->BitDepth_Y);
67
68
8.09M
  int w = sps->pic_width_in_luma_samples;
69
8.09M
  int h = sps->pic_height_in_luma_samples;
70
71
8.09M
  ALIGNED_16(int16_t) mcbuffer[MAX_CU_SIZE * (MAX_CU_SIZE+7)];
72
73
8.09M
  if (xFracL==0 && yFracL==0) {
74
75
4.02M
    if (xIntOffsL >= 0 && yIntOffsL >= 0 &&
76
4.00M
        nPbW+xIntOffsL <= w && nPbH+yIntOffsL <= h) {
77
78
3.90M
      ctx->acceleration.put_hevc_qpel(out, out_stride,
79
3.90M
                                      &ref[yIntOffsL*ref_stride + xIntOffsL],
80
3.90M
                                      ref_stride /* sizeof(pixel_t)*/,
81
3.90M
                                      nPbW,nPbH, mcbuffer, 0,0, bitDepth_L);
82
3.90M
    }
83
120k
    else {
84
1.30M
      for (int y=0;y<nPbH;y++)
85
16.5M
        for (int x=0;x<nPbW;x++) {
86
87
15.3M
          int xA = Clip3(0,w-1,x + xIntOffsL);
88
15.3M
          int yA = Clip3(0,h-1,y + yIntOffsL);
89
90
15.3M
          out[y*out_stride+x] = ref[ xA + yA*ref_stride ] << shift3;
91
15.3M
        }
92
120k
    }
93
94
#ifdef DE265_LOG_TRACE
95
    logtrace(LogMotion,"---MC luma %d %d = direct---\n",xFracL,yFracL);
96
97
    for (int y=0;y<nPbH;y++) {
98
      for (int x=0;x<nPbW;x++) {
99
100
        int xA = Clip3(0,w-1,x + xIntOffsL);
101
        int yA = Clip3(0,h-1,y + yIntOffsL);
102
103
        logtrace(LogMotion,"%02x ", ref[ xA + yA*ref_stride ]);
104
      }
105
      logtrace(LogMotion,"\n");
106
    }
107
108
    logtrace(LogMotion," -> \n");
109
110
    for (int y=0;y<nPbH;y++) {
111
      for (int x=0;x<nPbW;x++) {
112
113
        logtrace(LogMotion,"%02x ",out[y*out_stride+x] >> 6); // 6 will be used when summing predictions
114
      }
115
      logtrace(LogMotion,"\n");
116
    }
117
#endif
118
4.02M
  }
119
4.07M
  else {
120
4.07M
    int extra_left   = extra_before[xFracL];
121
4.07M
    int extra_right  = extra_after [xFracL];
122
4.07M
    int extra_top    = extra_before[yFracL];
123
4.07M
    int extra_bottom = extra_after [yFracL];
124
125
    //int nPbW_extra = extra_left + nPbW + extra_right;
126
    //int nPbH_extra = extra_top  + nPbH + extra_bottom;
127
128
129
4.07M
    pixel_t padbuf[(MAX_CU_SIZE+16)*(MAX_CU_SIZE+7)];
130
131
4.07M
    const pixel_t* src_ptr;
132
4.07M
    ptrdiff_t src_stride;
133
134
4.07M
    if (-extra_left + xIntOffsL >= 0 &&
135
4.03M
        -extra_top  + yIntOffsL >= 0 &&
136
3.65M
        nPbW+extra_right  + xIntOffsL < w &&
137
3.57M
        nPbH+extra_bottom + yIntOffsL < h) {
138
2.78M
      src_ptr = &ref[xIntOffsL + yIntOffsL*ref_stride];
139
2.78M
      src_stride = ref_stride;
140
2.78M
    }
141
1.28M
    else {
142
      // Extend fill width to a multiple of 16 so that SIMD over-reads
143
      // in qpel interpolation hit valid (edge-clamped) data.
144
1.28M
      int fill_width = ((extra_left + nPbW + extra_right + 15) & ~15);
145
1.28M
      if (fill_width > MAX_CU_SIZE+16) fill_width = MAX_CU_SIZE+16;
146
147
22.9M
      for (int y=-extra_top;y<nPbH+extra_bottom;y++) {
148
537M
        for (int x=-extra_left;x<fill_width - extra_left;x++) {
149
150
515M
          int xA = Clip3(0,w-1,x + xIntOffsL);
151
515M
          int yA = Clip3(0,h-1,y + yIntOffsL);
152
153
515M
          padbuf[x+extra_left + (y+extra_top)*(MAX_CU_SIZE+16)] = ref[ xA + yA*ref_stride ];
154
515M
        }
155
21.6M
      }
156
157
1.28M
      src_ptr = &padbuf[extra_top*(MAX_CU_SIZE+16) + extra_left];
158
1.28M
      src_stride = MAX_CU_SIZE+16;
159
1.28M
    }
160
161
4.07M
    ctx->acceleration.put_hevc_qpel(out, out_stride,
162
4.07M
                                    src_ptr, src_stride /* sizeof(pixel_t) */,
163
4.07M
                                    nPbW,nPbH, mcbuffer, xFracL,yFracL, bitDepth_L);
164
165
166
4.07M
    logtrace(LogMotion,"---V---\n");
167
43.0M
    for (int y=0;y<nPbH;y++) {
168
510M
      for (int x=0;x<nPbW;x++) {
169
471M
        logtrace(LogMotion,"%04x ",out[x+y*out_stride]);
170
471M
      }
171
39.0M
      logtrace(LogMotion,"\n");
172
39.0M
    }
173
4.07M
  }
174
8.09M
}
void mc_luma<unsigned short>(base_context const*, seq_parameter_set const*, int, int, int, int, short*, int, unsigned short const*, long, int, int, int)
Line
Count
Source
55
1.54M
{
56
1.54M
  int xFracL = mv_x & 3;
57
1.54M
  int yFracL = mv_y & 3;
58
59
1.54M
  int xIntOffsL = xP + (mv_x>>2);
60
1.54M
  int yIntOffsL = yP + (mv_y>>2);
61
62
  // luma sample interpolation process (8.5.3.2.2.1)
63
64
  //const int shift1 = sps->BitDepth_Y-8;
65
  //const int shift2 = 6;
66
1.54M
  const int shift3 = std::max(2, 14 - sps->BitDepth_Y);
67
68
1.54M
  int w = sps->pic_width_in_luma_samples;
69
1.54M
  int h = sps->pic_height_in_luma_samples;
70
71
1.54M
  ALIGNED_16(int16_t) mcbuffer[MAX_CU_SIZE * (MAX_CU_SIZE+7)];
72
73
1.54M
  if (xFracL==0 && yFracL==0) {
74
75
688k
    if (xIntOffsL >= 0 && yIntOffsL >= 0 &&
76
683k
        nPbW+xIntOffsL <= w && nPbH+yIntOffsL <= h) {
77
78
665k
      ctx->acceleration.put_hevc_qpel(out, out_stride,
79
665k
                                      &ref[yIntOffsL*ref_stride + xIntOffsL],
80
665k
                                      ref_stride /* sizeof(pixel_t)*/,
81
665k
                                      nPbW,nPbH, mcbuffer, 0,0, bitDepth_L);
82
665k
    }
83
23.4k
    else {
84
271k
      for (int y=0;y<nPbH;y++)
85
3.84M
        for (int x=0;x<nPbW;x++) {
86
87
3.59M
          int xA = Clip3(0,w-1,x + xIntOffsL);
88
3.59M
          int yA = Clip3(0,h-1,y + yIntOffsL);
89
90
3.59M
          out[y*out_stride+x] = ref[ xA + yA*ref_stride ] << shift3;
91
3.59M
        }
92
23.4k
    }
93
94
#ifdef DE265_LOG_TRACE
95
    logtrace(LogMotion,"---MC luma %d %d = direct---\n",xFracL,yFracL);
96
97
    for (int y=0;y<nPbH;y++) {
98
      for (int x=0;x<nPbW;x++) {
99
100
        int xA = Clip3(0,w-1,x + xIntOffsL);
101
        int yA = Clip3(0,h-1,y + yIntOffsL);
102
103
        logtrace(LogMotion,"%02x ", ref[ xA + yA*ref_stride ]);
104
      }
105
      logtrace(LogMotion,"\n");
106
    }
107
108
    logtrace(LogMotion," -> \n");
109
110
    for (int y=0;y<nPbH;y++) {
111
      for (int x=0;x<nPbW;x++) {
112
113
        logtrace(LogMotion,"%02x ",out[y*out_stride+x] >> 6); // 6 will be used when summing predictions
114
      }
115
      logtrace(LogMotion,"\n");
116
    }
117
#endif
118
688k
  }
119
858k
  else {
120
858k
    int extra_left   = extra_before[xFracL];
121
858k
    int extra_right  = extra_after [xFracL];
122
858k
    int extra_top    = extra_before[yFracL];
123
858k
    int extra_bottom = extra_after [yFracL];
124
125
    //int nPbW_extra = extra_left + nPbW + extra_right;
126
    //int nPbH_extra = extra_top  + nPbH + extra_bottom;
127
128
129
858k
    pixel_t padbuf[(MAX_CU_SIZE+16)*(MAX_CU_SIZE+7)];
130
131
858k
    const pixel_t* src_ptr;
132
858k
    ptrdiff_t src_stride;
133
134
858k
    if (-extra_left + xIntOffsL >= 0 &&
135
850k
        -extra_top  + yIntOffsL >= 0 &&
136
780k
        nPbW+extra_right  + xIntOffsL < w &&
137
761k
        nPbH+extra_bottom + yIntOffsL < h) {
138
579k
      src_ptr = &ref[xIntOffsL + yIntOffsL*ref_stride];
139
579k
      src_stride = ref_stride;
140
579k
    }
141
279k
    else {
142
      // Extend fill width to a multiple of 16 so that SIMD over-reads
143
      // in qpel interpolation hit valid (edge-clamped) data.
144
279k
      int fill_width = ((extra_left + nPbW + extra_right + 15) & ~15);
145
279k
      if (fill_width > MAX_CU_SIZE+16) fill_width = MAX_CU_SIZE+16;
146
147
5.05M
      for (int y=-extra_top;y<nPbH+extra_bottom;y++) {
148
125M
        for (int x=-extra_left;x<fill_width - extra_left;x++) {
149
150
120M
          int xA = Clip3(0,w-1,x + xIntOffsL);
151
120M
          int yA = Clip3(0,h-1,y + yIntOffsL);
152
153
120M
          padbuf[x+extra_left + (y+extra_top)*(MAX_CU_SIZE+16)] = ref[ xA + yA*ref_stride ];
154
120M
        }
155
4.77M
      }
156
157
279k
      src_ptr = &padbuf[extra_top*(MAX_CU_SIZE+16) + extra_left];
158
279k
      src_stride = MAX_CU_SIZE+16;
159
279k
    }
160
161
858k
    ctx->acceleration.put_hevc_qpel(out, out_stride,
162
858k
                                    src_ptr, src_stride /* sizeof(pixel_t) */,
163
858k
                                    nPbW,nPbH, mcbuffer, xFracL,yFracL, bitDepth_L);
164
165
166
858k
    logtrace(LogMotion,"---V---\n");
167
9.20M
    for (int y=0;y<nPbH;y++) {
168
123M
      for (int x=0;x<nPbW;x++) {
169
115M
        logtrace(LogMotion,"%04x ",out[x+y*out_stride]);
170
115M
      }
171
8.34M
      logtrace(LogMotion,"\n");
172
8.34M
    }
173
858k
  }
174
1.54M
}
void mc_luma<unsigned char>(base_context const*, seq_parameter_set const*, int, int, int, int, short*, int, unsigned char const*, long, int, int, int)
Line
Count
Source
55
6.55M
{
56
6.55M
  int xFracL = mv_x & 3;
57
6.55M
  int yFracL = mv_y & 3;
58
59
6.55M
  int xIntOffsL = xP + (mv_x>>2);
60
6.55M
  int yIntOffsL = yP + (mv_y>>2);
61
62
  // luma sample interpolation process (8.5.3.2.2.1)
63
64
  //const int shift1 = sps->BitDepth_Y-8;
65
  //const int shift2 = 6;
66
6.55M
  const int shift3 = std::max(2, 14 - sps->BitDepth_Y);
67
68
6.55M
  int w = sps->pic_width_in_luma_samples;
69
6.55M
  int h = sps->pic_height_in_luma_samples;
70
71
6.55M
  ALIGNED_16(int16_t) mcbuffer[MAX_CU_SIZE * (MAX_CU_SIZE+7)];
72
73
6.55M
  if (xFracL==0 && yFracL==0) {
74
75
3.33M
    if (xIntOffsL >= 0 && yIntOffsL >= 0 &&
76
3.31M
        nPbW+xIntOffsL <= w && nPbH+yIntOffsL <= h) {
77
78
3.24M
      ctx->acceleration.put_hevc_qpel(out, out_stride,
79
3.24M
                                      &ref[yIntOffsL*ref_stride + xIntOffsL],
80
3.24M
                                      ref_stride /* sizeof(pixel_t)*/,
81
3.24M
                                      nPbW,nPbH, mcbuffer, 0,0, bitDepth_L);
82
3.24M
    }
83
97.1k
    else {
84
1.03M
      for (int y=0;y<nPbH;y++)
85
12.7M
        for (int x=0;x<nPbW;x++) {
86
87
11.7M
          int xA = Clip3(0,w-1,x + xIntOffsL);
88
11.7M
          int yA = Clip3(0,h-1,y + yIntOffsL);
89
90
11.7M
          out[y*out_stride+x] = ref[ xA + yA*ref_stride ] << shift3;
91
11.7M
        }
92
97.1k
    }
93
94
#ifdef DE265_LOG_TRACE
95
    logtrace(LogMotion,"---MC luma %d %d = direct---\n",xFracL,yFracL);
96
97
    for (int y=0;y<nPbH;y++) {
98
      for (int x=0;x<nPbW;x++) {
99
100
        int xA = Clip3(0,w-1,x + xIntOffsL);
101
        int yA = Clip3(0,h-1,y + yIntOffsL);
102
103
        logtrace(LogMotion,"%02x ", ref[ xA + yA*ref_stride ]);
104
      }
105
      logtrace(LogMotion,"\n");
106
    }
107
108
    logtrace(LogMotion," -> \n");
109
110
    for (int y=0;y<nPbH;y++) {
111
      for (int x=0;x<nPbW;x++) {
112
113
        logtrace(LogMotion,"%02x ",out[y*out_stride+x] >> 6); // 6 will be used when summing predictions
114
      }
115
      logtrace(LogMotion,"\n");
116
    }
117
#endif
118
3.33M
  }
119
3.21M
  else {
120
3.21M
    int extra_left   = extra_before[xFracL];
121
3.21M
    int extra_right  = extra_after [xFracL];
122
3.21M
    int extra_top    = extra_before[yFracL];
123
3.21M
    int extra_bottom = extra_after [yFracL];
124
125
    //int nPbW_extra = extra_left + nPbW + extra_right;
126
    //int nPbH_extra = extra_top  + nPbH + extra_bottom;
127
128
129
3.21M
    pixel_t padbuf[(MAX_CU_SIZE+16)*(MAX_CU_SIZE+7)];
130
131
3.21M
    const pixel_t* src_ptr;
132
3.21M
    ptrdiff_t src_stride;
133
134
3.21M
    if (-extra_left + xIntOffsL >= 0 &&
135
3.18M
        -extra_top  + yIntOffsL >= 0 &&
136
2.87M
        nPbW+extra_right  + xIntOffsL < w &&
137
2.81M
        nPbH+extra_bottom + yIntOffsL < h) {
138
2.20M
      src_ptr = &ref[xIntOffsL + yIntOffsL*ref_stride];
139
2.20M
      src_stride = ref_stride;
140
2.20M
    }
141
1.00M
    else {
142
      // Extend fill width to a multiple of 16 so that SIMD over-reads
143
      // in qpel interpolation hit valid (edge-clamped) data.
144
1.00M
      int fill_width = ((extra_left + nPbW + extra_right + 15) & ~15);
145
1.00M
      if (fill_width > MAX_CU_SIZE+16) fill_width = MAX_CU_SIZE+16;
146
147
17.8M
      for (int y=-extra_top;y<nPbH+extra_bottom;y++) {
148
411M
        for (int x=-extra_left;x<fill_width - extra_left;x++) {
149
150
394M
          int xA = Clip3(0,w-1,x + xIntOffsL);
151
394M
          int yA = Clip3(0,h-1,y + yIntOffsL);
152
153
394M
          padbuf[x+extra_left + (y+extra_top)*(MAX_CU_SIZE+16)] = ref[ xA + yA*ref_stride ];
154
394M
        }
155
16.8M
      }
156
157
1.00M
      src_ptr = &padbuf[extra_top*(MAX_CU_SIZE+16) + extra_left];
158
1.00M
      src_stride = MAX_CU_SIZE+16;
159
1.00M
    }
160
161
3.21M
    ctx->acceleration.put_hevc_qpel(out, out_stride,
162
3.21M
                                    src_ptr, src_stride /* sizeof(pixel_t) */,
163
3.21M
                                    nPbW,nPbH, mcbuffer, xFracL,yFracL, bitDepth_L);
164
165
166
3.21M
    logtrace(LogMotion,"---V---\n");
167
33.8M
    for (int y=0;y<nPbH;y++) {
168
387M
      for (int x=0;x<nPbW;x++) {
169
356M
        logtrace(LogMotion,"%04x ",out[x+y*out_stride]);
170
356M
      }
171
30.6M
      logtrace(LogMotion,"\n");
172
30.6M
    }
173
3.21M
  }
174
6.55M
}
175
176
177
178
template <class pixel_t>
179
void mc_chroma(const base_context* ctx,
180
               const seq_parameter_set* sps,
181
               int mv_x, int mv_y,
182
               int xP,int yP,
183
               int16_t* out, int out_stride,
184
               const pixel_t* ref, ptrdiff_t ref_stride,
185
               int nPbWC, int nPbHC, int bit_depth_C)
186
16.1M
{
187
  // chroma sample interpolation process (8.5.3.2.2.2)
188
189
  //const int shift1 = sps->BitDepth_C-8;
190
  //const int shift2 = 6;
191
16.1M
  const int shift3 = std::max(2, 14 - sps->BitDepth_C);
192
193
16.1M
  int wC = sps->pic_width_in_luma_samples /sps->SubWidthC;
194
16.1M
  int hC = sps->pic_height_in_luma_samples/sps->SubHeightC;
195
196
16.1M
  mv_x *= 2 / sps->SubWidthC;
197
16.1M
  mv_y *= 2 / sps->SubHeightC;
198
199
16.1M
  int xFracC = mv_x & 7;
200
16.1M
  int yFracC = mv_y & 7;
201
202
16.1M
  int xIntOffsC = xP/sps->SubWidthC  + (mv_x>>3);
203
16.1M
  int yIntOffsC = yP/sps->SubHeightC + (mv_y>>3);
204
205
16.1M
  ALIGNED_32(int16_t mcbuffer[MAX_CU_SIZE*(MAX_CU_SIZE+7)]);
206
207
16.1M
  if (xFracC == 0 && yFracC == 0) {
208
7.61M
    if (xIntOffsC>=0 && nPbWC+xIntOffsC<=wC &&
209
7.59M
        yIntOffsC>=0 && nPbHC+yIntOffsC<=hC) {
210
7.49M
      ctx->acceleration.put_hevc_epel(out, out_stride,
211
7.49M
                                      &ref[xIntOffsC + yIntOffsC*ref_stride], ref_stride,
212
7.49M
                                      nPbWC,nPbHC, 0,0, nullptr, bit_depth_C);
213
7.49M
    }
214
115k
    else
215
115k
      {
216
788k
        for (int y=0;y<nPbHC;y++)
217
4.63M
          for (int x=0;x<nPbWC;x++) {
218
219
3.95M
            int xB = Clip3(0,wC-1,x + xIntOffsC);
220
3.95M
            int yB = Clip3(0,hC-1,y + yIntOffsC);
221
222
3.95M
            out[y*out_stride+x] = ref[ xB + yB*ref_stride ] << shift3;
223
3.95M
          }
224
115k
      }
225
7.61M
  }
226
8.58M
  else {
227
8.58M
    pixel_t padbuf[(MAX_CU_SIZE+16)*(MAX_CU_SIZE+3)];
228
229
8.58M
    const pixel_t* src_ptr;
230
8.58M
    ptrdiff_t src_stride;
231
232
8.58M
    int extra_top  = 1;
233
8.58M
    int extra_left = 1;
234
8.58M
    int extra_right  = 2;
235
8.58M
    int extra_bottom = 2;
236
237
8.58M
    if (xIntOffsC>=1 && nPbWC+xIntOffsC<=wC-2 &&
238
8.30M
        yIntOffsC>=1 && nPbHC+yIntOffsC<=hC-2) {
239
5.78M
      src_ptr = &ref[xIntOffsC + yIntOffsC*ref_stride];
240
5.78M
      src_stride = ref_stride;
241
5.78M
    }
242
2.79M
    else {
243
      // Extend fill width to a multiple of 16 so that SIMD over-reads
244
      // in epel interpolation hit valid (edge-clamped) data.
245
2.79M
      int fill_width = ((extra_left + nPbWC + extra_right + 15) & ~15);
246
2.79M
      if (fill_width > MAX_CU_SIZE+16) fill_width = MAX_CU_SIZE+16;
247
248
30.2M
      for (int y=-extra_top;y<nPbHC+extra_bottom;y++) {
249
549M
        for (int x=-extra_left;x<fill_width - extra_left;x++) {
250
251
521M
          int xA = Clip3(0,wC-1,x + xIntOffsC);
252
521M
          int yA = Clip3(0,hC-1,y + yIntOffsC);
253
254
521M
          padbuf[x+extra_left + (y+extra_top)*(MAX_CU_SIZE+16)] = ref[ xA + yA*ref_stride ];
255
521M
        }
256
27.4M
      }
257
258
2.79M
      src_ptr = &padbuf[extra_left + extra_top*(MAX_CU_SIZE+16)];
259
2.79M
      src_stride = MAX_CU_SIZE+16;
260
2.79M
    }
261
262
263
8.58M
    if (xFracC && yFracC) {
264
5.35M
      ctx->acceleration.put_hevc_epel_hv(out, out_stride,
265
5.35M
                                         src_ptr, src_stride,
266
5.35M
                                         nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
267
5.35M
    }
268
3.22M
    else if (xFracC) {
269
1.52M
      ctx->acceleration.put_hevc_epel_h(out, out_stride,
270
1.52M
                                        src_ptr, src_stride,
271
1.52M
                                        nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
272
1.52M
    }
273
1.70M
    else if (yFracC) {
274
1.70M
      ctx->acceleration.put_hevc_epel_v(out, out_stride,
275
1.70M
                                        src_ptr, src_stride,
276
1.70M
                                        nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
277
1.70M
    }
278
0
    else {
279
0
      assert(false); // full-pel shifts are handled above
280
0
    }
281
8.58M
  }
282
16.1M
}
void mc_chroma<unsigned short>(base_context const*, seq_parameter_set const*, int, int, int, int, short*, int, unsigned short const*, long, int, int, int)
Line
Count
Source
186
3.23M
{
187
  // chroma sample interpolation process (8.5.3.2.2.2)
188
189
  //const int shift1 = sps->BitDepth_C-8;
190
  //const int shift2 = 6;
191
3.23M
  const int shift3 = std::max(2, 14 - sps->BitDepth_C);
192
193
3.23M
  int wC = sps->pic_width_in_luma_samples /sps->SubWidthC;
194
3.23M
  int hC = sps->pic_height_in_luma_samples/sps->SubHeightC;
195
196
3.23M
  mv_x *= 2 / sps->SubWidthC;
197
3.23M
  mv_y *= 2 / sps->SubHeightC;
198
199
3.23M
  int xFracC = mv_x & 7;
200
3.23M
  int yFracC = mv_y & 7;
201
202
3.23M
  int xIntOffsC = xP/sps->SubWidthC  + (mv_x>>3);
203
3.23M
  int yIntOffsC = yP/sps->SubHeightC + (mv_y>>3);
204
205
3.23M
  ALIGNED_32(int16_t mcbuffer[MAX_CU_SIZE*(MAX_CU_SIZE+7)]);
206
207
3.23M
  if (xFracC == 0 && yFracC == 0) {
208
1.93M
    if (xIntOffsC>=0 && nPbWC+xIntOffsC<=wC &&
209
1.92M
        yIntOffsC>=0 && nPbHC+yIntOffsC<=hC) {
210
1.90M
      ctx->acceleration.put_hevc_epel(out, out_stride,
211
1.90M
                                      &ref[xIntOffsC + yIntOffsC*ref_stride], ref_stride,
212
1.90M
                                      nPbWC,nPbHC, 0,0, nullptr, bit_depth_C);
213
1.90M
    }
214
28.7k
    else
215
28.7k
      {
216
197k
        for (int y=0;y<nPbHC;y++)
217
1.12M
          for (int x=0;x<nPbWC;x++) {
218
219
954k
            int xB = Clip3(0,wC-1,x + xIntOffsC);
220
954k
            int yB = Clip3(0,hC-1,y + yIntOffsC);
221
222
954k
            out[y*out_stride+x] = ref[ xB + yB*ref_stride ] << shift3;
223
954k
          }
224
28.7k
      }
225
1.93M
  }
226
1.30M
  else {
227
1.30M
    pixel_t padbuf[(MAX_CU_SIZE+16)*(MAX_CU_SIZE+3)];
228
229
1.30M
    const pixel_t* src_ptr;
230
1.30M
    ptrdiff_t src_stride;
231
232
1.30M
    int extra_top  = 1;
233
1.30M
    int extra_left = 1;
234
1.30M
    int extra_right  = 2;
235
1.30M
    int extra_bottom = 2;
236
237
1.30M
    if (xIntOffsC>=1 && nPbWC+xIntOffsC<=wC-2 &&
238
1.26M
        yIntOffsC>=1 && nPbHC+yIntOffsC<=hC-2) {
239
876k
      src_ptr = &ref[xIntOffsC + yIntOffsC*ref_stride];
240
876k
      src_stride = ref_stride;
241
876k
    }
242
425k
    else {
243
      // Extend fill width to a multiple of 16 so that SIMD over-reads
244
      // in epel interpolation hit valid (edge-clamped) data.
245
425k
      int fill_width = ((extra_left + nPbWC + extra_right + 15) & ~15);
246
425k
      if (fill_width > MAX_CU_SIZE+16) fill_width = MAX_CU_SIZE+16;
247
248
5.01M
      for (int y=-extra_top;y<nPbHC+extra_bottom;y++) {
249
101M
        for (int x=-extra_left;x<fill_width - extra_left;x++) {
250
251
96.6M
          int xA = Clip3(0,wC-1,x + xIntOffsC);
252
96.6M
          int yA = Clip3(0,hC-1,y + yIntOffsC);
253
254
96.6M
          padbuf[x+extra_left + (y+extra_top)*(MAX_CU_SIZE+16)] = ref[ xA + yA*ref_stride ];
255
96.6M
        }
256
4.59M
      }
257
258
425k
      src_ptr = &padbuf[extra_left + extra_top*(MAX_CU_SIZE+16)];
259
425k
      src_stride = MAX_CU_SIZE+16;
260
425k
    }
261
262
263
1.30M
    if (xFracC && yFracC) {
264
865k
      ctx->acceleration.put_hevc_epel_hv(out, out_stride,
265
865k
                                         src_ptr, src_stride,
266
865k
                                         nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
267
865k
    }
268
436k
    else if (xFracC) {
269
220k
      ctx->acceleration.put_hevc_epel_h(out, out_stride,
270
220k
                                        src_ptr, src_stride,
271
220k
                                        nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
272
220k
    }
273
215k
    else if (yFracC) {
274
215k
      ctx->acceleration.put_hevc_epel_v(out, out_stride,
275
215k
                                        src_ptr, src_stride,
276
215k
                                        nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
277
215k
    }
278
0
    else {
279
      assert(false); // full-pel shifts are handled above
280
0
    }
281
1.30M
  }
282
3.23M
}
void mc_chroma<unsigned char>(base_context const*, seq_parameter_set const*, int, int, int, int, short*, int, unsigned char const*, long, int, int, int)
Line
Count
Source
186
12.9M
{
187
  // chroma sample interpolation process (8.5.3.2.2.2)
188
189
  //const int shift1 = sps->BitDepth_C-8;
190
  //const int shift2 = 6;
191
12.9M
  const int shift3 = std::max(2, 14 - sps->BitDepth_C);
192
193
12.9M
  int wC = sps->pic_width_in_luma_samples /sps->SubWidthC;
194
12.9M
  int hC = sps->pic_height_in_luma_samples/sps->SubHeightC;
195
196
12.9M
  mv_x *= 2 / sps->SubWidthC;
197
12.9M
  mv_y *= 2 / sps->SubHeightC;
198
199
12.9M
  int xFracC = mv_x & 7;
200
12.9M
  int yFracC = mv_y & 7;
201
202
12.9M
  int xIntOffsC = xP/sps->SubWidthC  + (mv_x>>3);
203
12.9M
  int yIntOffsC = yP/sps->SubHeightC + (mv_y>>3);
204
205
12.9M
  ALIGNED_32(int16_t mcbuffer[MAX_CU_SIZE*(MAX_CU_SIZE+7)]);
206
207
12.9M
  if (xFracC == 0 && yFracC == 0) {
208
5.68M
    if (xIntOffsC>=0 && nPbWC+xIntOffsC<=wC &&
209
5.66M
        yIntOffsC>=0 && nPbHC+yIntOffsC<=hC) {
210
5.59M
      ctx->acceleration.put_hevc_epel(out, out_stride,
211
5.59M
                                      &ref[xIntOffsC + yIntOffsC*ref_stride], ref_stride,
212
5.59M
                                      nPbWC,nPbHC, 0,0, nullptr, bit_depth_C);
213
5.59M
    }
214
86.4k
    else
215
86.4k
      {
216
590k
        for (int y=0;y<nPbHC;y++)
217
3.50M
          for (int x=0;x<nPbWC;x++) {
218
219
3.00M
            int xB = Clip3(0,wC-1,x + xIntOffsC);
220
3.00M
            int yB = Clip3(0,hC-1,y + yIntOffsC);
221
222
3.00M
            out[y*out_stride+x] = ref[ xB + yB*ref_stride ] << shift3;
223
3.00M
          }
224
86.4k
      }
225
5.68M
  }
226
7.28M
  else {
227
7.28M
    pixel_t padbuf[(MAX_CU_SIZE+16)*(MAX_CU_SIZE+3)];
228
229
7.28M
    const pixel_t* src_ptr;
230
7.28M
    ptrdiff_t src_stride;
231
232
7.28M
    int extra_top  = 1;
233
7.28M
    int extra_left = 1;
234
7.28M
    int extra_right  = 2;
235
7.28M
    int extra_bottom = 2;
236
237
7.28M
    if (xIntOffsC>=1 && nPbWC+xIntOffsC<=wC-2 &&
238
7.04M
        yIntOffsC>=1 && nPbHC+yIntOffsC<=hC-2) {
239
4.90M
      src_ptr = &ref[xIntOffsC + yIntOffsC*ref_stride];
240
4.90M
      src_stride = ref_stride;
241
4.90M
    }
242
2.37M
    else {
243
      // Extend fill width to a multiple of 16 so that SIMD over-reads
244
      // in epel interpolation hit valid (edge-clamped) data.
245
2.37M
      int fill_width = ((extra_left + nPbWC + extra_right + 15) & ~15);
246
2.37M
      if (fill_width > MAX_CU_SIZE+16) fill_width = MAX_CU_SIZE+16;
247
248
25.2M
      for (int y=-extra_top;y<nPbHC+extra_bottom;y++) {
249
447M
        for (int x=-extra_left;x<fill_width - extra_left;x++) {
250
251
425M
          int xA = Clip3(0,wC-1,x + xIntOffsC);
252
425M
          int yA = Clip3(0,hC-1,y + yIntOffsC);
253
254
425M
          padbuf[x+extra_left + (y+extra_top)*(MAX_CU_SIZE+16)] = ref[ xA + yA*ref_stride ];
255
425M
        }
256
22.8M
      }
257
258
2.37M
      src_ptr = &padbuf[extra_left + extra_top*(MAX_CU_SIZE+16)];
259
2.37M
      src_stride = MAX_CU_SIZE+16;
260
2.37M
    }
261
262
263
7.28M
    if (xFracC && yFracC) {
264
4.48M
      ctx->acceleration.put_hevc_epel_hv(out, out_stride,
265
4.48M
                                         src_ptr, src_stride,
266
4.48M
                                         nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
267
4.48M
    }
268
2.79M
    else if (xFracC) {
269
1.29M
      ctx->acceleration.put_hevc_epel_h(out, out_stride,
270
1.29M
                                        src_ptr, src_stride,
271
1.29M
                                        nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
272
1.29M
    }
273
1.49M
    else if (yFracC) {
274
1.49M
      ctx->acceleration.put_hevc_epel_v(out, out_stride,
275
1.49M
                                        src_ptr, src_stride,
276
1.49M
                                        nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
277
1.49M
    }
278
0
    else {
279
      assert(false); // full-pel shifts are handled above
280
0
    }
281
7.28M
  }
282
12.9M
}
283
284
285
286
// 8.5.3.2
287
// NOTE: for full-pel shifts, we can introduce a fast path, simply copying without shifts
288
void generate_inter_prediction_samples(base_context* ctx,
289
                                       const slice_segment_header* shdr,
290
                                       de265_image* img,
291
                                       int xC,int yC,
292
                                       int xB,int yB,
293
                                       int nCS, int nPbW,int nPbH,
294
                                       const PBMotion* vi)
295
6.81M
{
296
6.81M
  int xP = xC+xB;
297
6.81M
  int yP = yC+yB;
298
299
6.81M
  void*  pixels[3];
300
6.81M
  int    stride[3];
301
302
6.81M
  const pic_parameter_set* pps = shdr->pps.get();
303
6.81M
  const seq_parameter_set* sps = pps->sps.get();
304
305
6.81M
  if (sps->BitDepth_Y != img->get_bit_depth(0) ||
306
6.81M
      sps->BitDepth_C != img->get_bit_depth(1)) {
307
0
    img->integrity = INTEGRITY_DECODING_ERRORS;
308
0
    ctx->add_warning(DE265_WARNING_BIT_DEPTH_OF_CURRENT_IMAGE_DOES_NOT_MATCH_SPS, false);
309
0
    return;
310
0
  }
311
312
6.81M
  if (sps->chroma_format_idc != img->get_chroma_format()) {
313
0
    img->integrity = INTEGRITY_DECODING_ERRORS;
314
0
    ctx->add_warning(DE265_WARNING_CHROMA_OF_CURRENT_IMAGE_DOES_NOT_MATCH_SPS, false);
315
0
    return;
316
0
  }
317
318
6.81M
  const int SubWidthC  = sps->SubWidthC;
319
6.81M
  const int SubHeightC = sps->SubHeightC;
320
321
6.81M
  pixels[0] = img->get_image_plane_at_pos_any_depth(0,xP,yP);
322
6.81M
  stride[0] = img->get_image_stride(0);
323
324
6.81M
  pixels[1] = img->get_image_plane_at_pos_any_depth(1,xP/SubWidthC,yP/SubHeightC);
325
6.81M
  stride[1] = img->get_image_stride(1);
326
327
6.81M
  pixels[2] = img->get_image_plane_at_pos_any_depth(2,xP/SubWidthC,yP/SubHeightC);
328
6.81M
  stride[2] = img->get_image_stride(2);
329
330
331
6.81M
  ALIGNED_16(int16_t) predSamplesL                 [2 /* LX */][MAX_CU_SIZE* MAX_CU_SIZE];
332
6.81M
  ALIGNED_16(int16_t) predSamplesC[2 /* chroma */ ][2 /* LX */][MAX_CU_SIZE* MAX_CU_SIZE];
333
334
  //int xP = xC+xB;
335
  //int yP = yC+yB;
336
337
6.81M
  int predFlag[2];
338
6.81M
  predFlag[0] = vi->predFlag[0];
339
6.81M
  predFlag[1] = vi->predFlag[1];
340
341
6.81M
  const int bit_depth_L = sps->BitDepth_Y;
342
6.81M
  const int bit_depth_C = sps->BitDepth_C;
343
344
  // Some encoders use bi-prediction with two similar MVs.
345
  // Identify this case and use only one MV.
346
347
  // do this only without weighted prediction, because the weights/offsets may be different
348
6.81M
  if (pps->weighted_pred_flag==0) {
349
6.03M
    if (predFlag[0] && predFlag[1]) {
350
2.24M
      if (vi->mv[0].x == vi->mv[1].x &&
351
1.50M
          vi->mv[0].y == vi->mv[1].y &&
352
1.34M
          shdr->RefPicList[0][vi->refIdx[0]] ==
353
1.34M
          shdr->RefPicList[1][vi->refIdx[1]]) {
354
1.25M
        predFlag[1] = 0;
355
1.25M
      }
356
2.24M
    }
357
6.03M
  }
358
359
360
  // Fill prediction samples with mid-grey in intermediate precision.
361
  // Used on error paths where the reference picture is unavailable or mismatched.
362
6.81M
  auto fill_pred_samples = [&](int l) {
363
0
    const int16_t fill = 1 << 13; // mid-grey: (1 << (bd-1)) << (14-bd) for any bd
364
0
    for (int y = 0; y < nPbH; y++)
365
0
      for (int x = 0; x < nPbW; x++)
366
0
        predSamplesL[l][y * nCS + x] = fill;
367
0
    if (img->get_chroma_format() != de265_chroma_mono) {
368
0
      int cW = nPbW / SubWidthC;
369
0
      int cH = nPbH / SubHeightC;
370
0
      for (int y = 0; y < cH; y++)
371
0
        for (int x = 0; x < cW; x++) {
372
0
          predSamplesC[0][l][y * nCS + x] = fill;
373
0
          predSamplesC[1][l][y * nCS + x] = fill;
374
0
        }
375
0
    }
376
0
  };
377
378
20.4M
  for (int l=0;l<2;l++) {
379
13.6M
    if (predFlag[l]) {
380
      // 8.5.3.2.1
381
382
8.09M
      const de265_image* refPic = ctx->get_image(shdr->RefPicList[l][vi->refIdx[l]]);
383
384
8.09M
      logtrace(LogMotion, "refIdx: %d -> dpb[%d]\n", vi->refIdx[l], shdr->RefPicList[l][vi->refIdx[l]]);
385
386
8.09M
      if (!refPic || refPic->PicState == UnusedForReference) {
387
0
        img->integrity = INTEGRITY_DECODING_ERRORS;
388
0
        ctx->add_warning(DE265_WARNING_NONEXISTING_REFERENCE_PICTURE_ACCESSED, false);
389
0
        fill_pred_samples(l);
390
0
      }
391
8.09M
      else if (refPic->get_width(0) != sps->pic_width_in_luma_samples ||
392
8.09M
               refPic->get_height(0) != sps->pic_height_in_luma_samples ||
393
8.09M
               img->get_chroma_format() != refPic->get_chroma_format()) {
394
0
        img->integrity = INTEGRITY_DECODING_ERRORS;
395
0
        ctx->add_warning(DE265_WARNING_REFERENCE_IMAGE_SIZE_DOES_NOT_MATCH_SPS, false);
396
0
        fill_pred_samples(l);
397
0
      }
398
8.09M
      else if (img->get_bit_depth(0) != refPic->get_bit_depth(0) ||
399
8.09M
               img->get_bit_depth(1) != refPic->get_bit_depth(1)) {
400
0
        img->integrity = INTEGRITY_DECODING_ERRORS;
401
0
        ctx->add_warning(DE265_WARNING_REFERENCE_IMAGE_BIT_DEPTH_DOES_NOT_MATCH, false);
402
0
        fill_pred_samples(l);
403
0
      }
404
8.09M
      else if (img->get_chroma_format() != refPic->get_chroma_format()) {
405
0
        img->integrity = INTEGRITY_DECODING_ERRORS;
406
0
        ctx->add_warning(DE265_WARNING_REFERENCE_IMAGE_CHROMA_FORMAT_DOES_NOT_MATCH, false);
407
0
        fill_pred_samples(l);
408
0
      }
409
8.09M
      else {
410
        // 8.5.3.2.2
411
412
8.09M
        logtrace(LogMotion,"do MC: L%d,MV=%d;%d RefPOC=%d\n",
413
8.09M
                 l,vi->mv[l].x,vi->mv[l].y,refPic->PicOrderCntVal);
414
415
416
        // TODO: must predSamples stride really be nCS or can it be something smaller like nPbW?
417
418
8.09M
        if (img->high_bit_depth(0)) {
419
1.54M
          mc_luma(ctx, sps, vi->mv[l].x, vi->mv[l].y, xP,yP,
420
1.54M
                  predSamplesL[l],nCS,
421
1.54M
                  (const uint16_t*)refPic->get_image_plane(0),
422
1.54M
                  refPic->get_luma_stride(), nPbW,nPbH, bit_depth_L);
423
1.54M
        }
424
6.55M
        else {
425
6.55M
          mc_luma(ctx, sps, vi->mv[l].x, vi->mv[l].y, xP,yP,
426
6.55M
                  predSamplesL[l],nCS,
427
6.55M
                  (const uint8_t*)refPic->get_image_plane(0),
428
6.55M
                  refPic->get_luma_stride(), nPbW,nPbH, bit_depth_L);
429
6.55M
        }
430
431
8.09M
        if (img->get_chroma_format() != de265_chroma_mono) {
432
8.09M
          if (img->high_bit_depth(1)) {
433
1.61M
            mc_chroma(ctx, sps, vi->mv[l].x, vi->mv[l].y, xP, yP,
434
1.61M
                      predSamplesC[0][l], nCS, (const uint16_t*) refPic->get_image_plane(1),
435
1.61M
                      refPic->get_chroma_stride(), nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C);
436
1.61M
            mc_chroma(ctx, sps, vi->mv[l].x, vi->mv[l].y, xP, yP,
437
1.61M
                      predSamplesC[1][l], nCS, (const uint16_t*) refPic->get_image_plane(2),
438
1.61M
                      refPic->get_chroma_stride(), nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C);
439
1.61M
          }
440
6.48M
          else {
441
6.48M
            mc_chroma(ctx, sps, vi->mv[l].x, vi->mv[l].y, xP, yP,
442
6.48M
                      predSamplesC[0][l], nCS, (const uint8_t*) refPic->get_image_plane(1),
443
6.48M
                      refPic->get_chroma_stride(), nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C);
444
6.48M
            mc_chroma(ctx, sps, vi->mv[l].x, vi->mv[l].y, xP, yP,
445
6.48M
                      predSamplesC[1][l], nCS, (const uint8_t*) refPic->get_image_plane(2),
446
6.48M
                      refPic->get_chroma_stride(), nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C);
447
6.48M
          }
448
8.09M
        }
449
8.09M
      }
450
8.09M
    }
451
13.6M
  }
452
453
454
  // weighted sample prediction  (8.5.3.2.3)
455
456
6.81M
  const int shift1_L = std::max(2,14-sps->BitDepth_Y);
457
6.81M
  const int offset_shift1_L = img->get_sps().WpOffsetBdShiftY;
458
6.81M
  const int shift1_C = std::max(2,14-sps->BitDepth_C);
459
6.81M
  const int offset_shift1_C = img->get_sps().WpOffsetBdShiftC;
460
461
  /*
462
  const int shift1_L = 14-img->sps.BitDepth_Y;
463
  const int offset_shift1_L = img->sps.BitDepth_Y-8;
464
  const int shift1_C = 14-img->sps.BitDepth_C;
465
  const int offset_shift1_C = img->sps.BitDepth_C-8;
466
  */
467
468
  /*
469
  if (0)
470
  printf("%d/%d %d/%d %d/%d %d/%d\n",
471
         shift1_L,
472
         Nshift1_L,
473
         offset_shift1_L,
474
         Noffset_shift1_L,
475
         shift1_C,
476
         Nshift1_C,
477
         offset_shift1_C,
478
         Noffset_shift1_C);
479
480
  assert(shift1_L==
481
         Nshift1_L);
482
  assert(offset_shift1_L==
483
         Noffset_shift1_L);
484
  assert(shift1_C==
485
         Nshift1_C);
486
  assert(offset_shift1_C==
487
         Noffset_shift1_C);
488
  */
489
490
491
6.81M
  logtrace(LogMotion,"predFlags (modified): %d %d\n", predFlag[0], predFlag[1]);
492
493
6.81M
  if (shdr->slice_type == SLICE_TYPE_P) {
494
609k
    if (pps->weighted_pred_flag==0) {
495
445k
      if (predFlag[0]==1 && predFlag[1]==0) {
496
445k
        ctx->acceleration.put_unweighted_pred(pixels[0], stride[0],
497
445k
                                              predSamplesL[0],nCS, nPbW,nPbH, bit_depth_L);
498
499
445k
        if (img->get_chroma_format() != de265_chroma_mono) {
500
445k
          ctx->acceleration.put_unweighted_pred(pixels[1], stride[1],
501
445k
                                                predSamplesC[0][0], nCS,
502
445k
                                                nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C);
503
445k
          ctx->acceleration.put_unweighted_pred(pixels[2], stride[2],
504
445k
                                                predSamplesC[1][0], nCS,
505
445k
                                                nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C);
506
445k
        }
507
445k
      }
508
0
      else {
509
0
        ctx->add_warning(DE265_WARNING_BOTH_PREDFLAGS_ZERO, false);
510
0
        img->integrity = INTEGRITY_DECODING_ERRORS;
511
0
      }
512
445k
    }
513
163k
    else {
514
      // weighted prediction
515
516
163k
      if (predFlag[0]==1 && predFlag[1]==0) {
517
518
163k
        int refIdx0 = vi->refIdx[0];
519
520
163k
        int luma_log2WD   = shdr->luma_log2_weight_denom + shift1_L;
521
163k
        int chroma_log2WD = shdr->ChromaLog2WeightDenom  + shift1_C;
522
523
163k
        int luma_w0 = shdr->LumaWeight[0][refIdx0];
524
163k
        int luma_o0 = shdr->luma_offset[0][refIdx0] * (1<<(offset_shift1_L));
525
526
163k
        int chroma0_w0 = shdr->ChromaWeight[0][refIdx0][0];
527
163k
        int chroma0_o0 = shdr->ChromaOffset[0][refIdx0][0] * (1<<(offset_shift1_C));
528
163k
        int chroma1_w0 = shdr->ChromaWeight[0][refIdx0][1];
529
163k
        int chroma1_o0 = shdr->ChromaOffset[0][refIdx0][1] * (1<<(offset_shift1_C));
530
531
163k
        logtrace(LogMotion,"weighted-0 [%d] %d %d %d  %dx%d\n", refIdx0, luma_log2WD-6,luma_w0,luma_o0,nPbW,nPbH);
532
533
163k
        ctx->acceleration.put_weighted_pred(pixels[0], stride[0],
534
163k
                                            predSamplesL[0],nCS, nPbW,nPbH,
535
163k
                                            luma_w0, luma_o0, luma_log2WD, bit_depth_L);
536
163k
        if (img->get_chroma_format() != de265_chroma_mono) {
537
163k
          ctx->acceleration.put_weighted_pred(pixels[1], stride[1],
538
163k
                                              predSamplesC[0][0], nCS, nPbW / SubWidthC, nPbH / SubHeightC,
539
163k
                                              chroma0_w0, chroma0_o0, chroma_log2WD, bit_depth_C);
540
163k
          ctx->acceleration.put_weighted_pred(pixels[2], stride[2],
541
163k
                                              predSamplesC[1][0], nCS, nPbW / SubWidthC, nPbH / SubHeightC,
542
163k
                                              chroma1_w0, chroma1_o0, chroma_log2WD, bit_depth_C);
543
163k
        }
544
163k
      }
545
0
      else {
546
0
        ctx->add_warning(DE265_WARNING_BOTH_PREDFLAGS_ZERO, false);
547
0
        img->integrity = INTEGRITY_DECODING_ERRORS;
548
0
      }
549
163k
    }
550
609k
  }
551
6.20M
  else {
552
6.20M
    assert(shdr->slice_type == SLICE_TYPE_B);
553
554
6.20M
    if (predFlag[0]==1 && predFlag[1]==1) {
555
1.28M
      if (pps->weighted_bipred_flag==0) {
556
        //const int shift2  = 15-8; // TODO: real bit depth
557
        //const int offset2 = 1<<(shift2-1);
558
559
928k
        int16_t* in0 = predSamplesL[0];
560
928k
        int16_t* in1 = predSamplesL[1];
561
562
928k
        ctx->acceleration.put_weighted_pred_avg(pixels[0], stride[0],
563
928k
                                                in0,in1, nCS, nPbW, nPbH, bit_depth_L);
564
565
928k
        int16_t* in00 = predSamplesC[0][0];
566
928k
        int16_t* in01 = predSamplesC[0][1];
567
928k
        int16_t* in10 = predSamplesC[1][0];
568
928k
        int16_t* in11 = predSamplesC[1][1];
569
570
928k
        if (img->get_chroma_format() != de265_chroma_mono) {
571
928k
          ctx->acceleration.put_weighted_pred_avg(pixels[1], stride[1],
572
928k
                                                  in00, in01, nCS,
573
928k
                                                  nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C);
574
928k
          ctx->acceleration.put_weighted_pred_avg(pixels[2], stride[2],
575
928k
                                                  in10, in11, nCS,
576
928k
                                                  nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C);
577
928k
        }
578
928k
      }
579
356k
      else {
580
        // weighted prediction
581
582
356k
        int refIdx0 = vi->refIdx[0];
583
356k
        int refIdx1 = vi->refIdx[1];
584
585
356k
        int luma_log2WD   = shdr->luma_log2_weight_denom + shift1_L;
586
356k
        int chroma_log2WD = shdr->ChromaLog2WeightDenom + shift1_C;
587
588
356k
        int luma_w0 = shdr->LumaWeight[0][refIdx0];
589
356k
        int luma_o0 = shdr->luma_offset[0][refIdx0] * (1<<(offset_shift1_L));
590
356k
        int luma_w1 = shdr->LumaWeight[1][refIdx1];
591
356k
        int luma_o1 = shdr->luma_offset[1][refIdx1] * (1<<(offset_shift1_L));
592
593
356k
        int chroma0_w0 = shdr->ChromaWeight[0][refIdx0][0];
594
356k
        int chroma0_o0 = shdr->ChromaOffset[0][refIdx0][0] * (1<<(offset_shift1_C));
595
356k
        int chroma1_w0 = shdr->ChromaWeight[0][refIdx0][1];
596
356k
        int chroma1_o0 = shdr->ChromaOffset[0][refIdx0][1] * (1<<(offset_shift1_C));
597
356k
        int chroma0_w1 = shdr->ChromaWeight[1][refIdx1][0];
598
356k
        int chroma0_o1 = shdr->ChromaOffset[1][refIdx1][0] * (1<<(offset_shift1_C));
599
356k
        int chroma1_w1 = shdr->ChromaWeight[1][refIdx1][1];
600
356k
        int chroma1_o1 = shdr->ChromaOffset[1][refIdx1][1] * (1<<(offset_shift1_C));
601
602
356k
        logtrace(LogMotion,"weighted-BI-0 [%d] %d %d %d  %dx%d\n", refIdx0, luma_log2WD-6,luma_w0,luma_o0,nPbW,nPbH);
603
356k
        logtrace(LogMotion,"weighted-BI-1 [%d] %d %d %d  %dx%d\n", refIdx1, luma_log2WD-6,luma_w1,luma_o1,nPbW,nPbH);
604
605
356k
        int16_t* in0 = predSamplesL[0];
606
356k
        int16_t* in1 = predSamplesL[1];
607
608
356k
        ctx->acceleration.put_weighted_bipred(pixels[0], stride[0],
609
356k
                                              in0,in1, nCS, nPbW, nPbH,
610
356k
                                              luma_w0,luma_o0,
611
356k
                                              luma_w1,luma_o1,
612
356k
                                              luma_log2WD, bit_depth_L);
613
614
356k
        int16_t* in00 = predSamplesC[0][0];
615
356k
        int16_t* in01 = predSamplesC[0][1];
616
356k
        int16_t* in10 = predSamplesC[1][0];
617
356k
        int16_t* in11 = predSamplesC[1][1];
618
619
356k
        if (img->get_chroma_format() != de265_chroma_mono) {
620
356k
          ctx->acceleration.put_weighted_bipred(pixels[1], stride[1],
621
356k
                                                in00, in01, nCS, nPbW / SubWidthC, nPbH / SubHeightC,
622
356k
                                                chroma0_w0, chroma0_o0,
623
356k
                                                chroma0_w1, chroma0_o1,
624
356k
                                                chroma_log2WD, bit_depth_C);
625
356k
          ctx->acceleration.put_weighted_bipred(pixels[2], stride[2],
626
356k
                                                in10, in11, nCS, nPbW / SubWidthC, nPbH / SubHeightC,
627
356k
                                                chroma1_w0, chroma1_o0,
628
356k
                                                chroma1_w1, chroma1_o1,
629
356k
                                                chroma_log2WD, bit_depth_C);
630
356k
        }
631
356k
      }
632
1.28M
    }
633
4.91M
    else if (predFlag[0]==1 || predFlag[1]==1) {
634
4.91M
      int l = predFlag[0] ? 0 : 1;
635
636
4.91M
      if (pps->weighted_bipred_flag==0) {
637
4.02M
        ctx->acceleration.put_unweighted_pred(pixels[0], stride[0],
638
4.02M
                                              predSamplesL[l],nCS, nPbW,nPbH, bit_depth_L);
639
640
4.02M
        if (img->get_chroma_format() != de265_chroma_mono) {
641
4.02M
          ctx->acceleration.put_unweighted_pred(pixels[1], stride[1],
642
4.02M
                                                predSamplesC[0][l], nCS,
643
4.02M
                                                nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C);
644
4.02M
          ctx->acceleration.put_unweighted_pred(pixels[2], stride[2],
645
4.02M
                                                predSamplesC[1][l], nCS,
646
4.02M
                                                nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C);
647
4.02M
        }
648
4.02M
      }
649
891k
      else {
650
891k
        int refIdx = vi->refIdx[l];
651
652
891k
        int luma_log2WD   = shdr->luma_log2_weight_denom + shift1_L;
653
891k
        int chroma_log2WD = shdr->ChromaLog2WeightDenom  + shift1_C;
654
655
891k
        int luma_w = shdr->LumaWeight[l][refIdx];
656
891k
        int luma_o = shdr->luma_offset[l][refIdx] * (1<<(offset_shift1_L));
657
658
891k
        int chroma0_w = shdr->ChromaWeight[l][refIdx][0];
659
891k
        int chroma0_o = shdr->ChromaOffset[l][refIdx][0] * (1<<(offset_shift1_C));
660
891k
        int chroma1_w = shdr->ChromaWeight[l][refIdx][1];
661
891k
        int chroma1_o = shdr->ChromaOffset[l][refIdx][1] * (1<<(offset_shift1_C));
662
663
891k
        logtrace(LogMotion,"weighted-B-L%d [%d] %d %d %d  %dx%d\n", l, refIdx, luma_log2WD-6,luma_w,luma_o,nPbW,nPbH);
664
665
891k
        ctx->acceleration.put_weighted_pred(pixels[0], stride[0],
666
891k
                                            predSamplesL[l],nCS, nPbW,nPbH,
667
891k
                                            luma_w, luma_o, luma_log2WD, bit_depth_L);
668
669
891k
        if (img->get_chroma_format() != de265_chroma_mono) {
670
891k
          ctx->acceleration.put_weighted_pred(pixels[1], stride[1],
671
891k
                                              predSamplesC[0][l], nCS,
672
891k
                                              nPbW / SubWidthC, nPbH / SubHeightC,
673
891k
                                              chroma0_w, chroma0_o, chroma_log2WD, bit_depth_C);
674
891k
          ctx->acceleration.put_weighted_pred(pixels[2], stride[2],
675
891k
                                              predSamplesC[1][l], nCS,
676
891k
                                              nPbW / SubWidthC, nPbH / SubHeightC,
677
891k
                                              chroma1_w, chroma1_o, chroma_log2WD, bit_depth_C);
678
891k
        }
679
891k
      }
680
4.91M
    }
681
0
    else {
682
      // TODO: check why it can actually happen that both predFlags[] are false.
683
      // For now, we ignore this and continue decoding.
684
685
0
      ctx->add_warning(DE265_WARNING_BOTH_PREDFLAGS_ZERO, false);
686
0
      img->integrity = INTEGRITY_DECODING_ERRORS;
687
0
    }
688
6.20M
  }
689
690
#if defined(DE265_LOG_TRACE) && 0
691
  logtrace(LogTransform,"MC pixels (luma), position %d %d:\n", xP,yP);
692
693
  for (int y=0;y<nPbH;y++) {
694
    logtrace(LogTransform,"MC-y-%d-%d ",xP,yP+y);
695
696
    for (int x=0;x<nPbW;x++) {
697
      logtrace(LogTransform,"*%02x ", pixels[0][x+y*stride[0]]);
698
    }
699
700
    logtrace(LogTransform,"*\n");
701
  }
702
703
704
  logtrace(LogTransform,"MC pixels (chroma cb), position %d %d:\n", xP/2,yP/2);
705
706
  for (int y=0;y<nPbH/2;y++) {
707
    logtrace(LogTransform,"MC-cb-%d-%d ",xP/2,yP/2+y);
708
709
    for (int x=0;x<nPbW/2;x++) {
710
      logtrace(LogTransform,"*%02x ", pixels[1][x+y*stride[1]]);
711
    }
712
713
    logtrace(LogTransform,"*\n");
714
  }
715
716
717
  logtrace(LogTransform,"MC pixels (chroma cr), position %d %d:\n", xP/2,yP/2);
718
719
  for (int y=0;y<nPbH/2;y++) {
720
    logtrace(LogTransform,"MC-cr-%d-%d ",xP/2,yP/2+y);
721
722
    for (int x=0;x<nPbW/2;x++) {
723
      logtrace(LogTransform,"*%02x ", pixels[2][x+y*stride[2]]);
724
    }
725
726
    logtrace(LogTransform,"*\n");
727
  }
728
#endif
729
6.81M
}
730
731
732
#ifdef DE265_LOG_TRACE
733
void logmvcand(const PBMotion& p)
734
{
735
  for (int v=0;v<2;v++) {
736
    if (p.predFlag[v]) {
737
      logtrace(LogMotion,"  %d: %s  %d;%d ref=%d\n", v, p.predFlag[v] ? "yes":"no ",
738
               p.mv[v].x,p.mv[v].y, p.refIdx[v]);
739
    } else {
740
      logtrace(LogMotion,"  %d: %s  --;-- ref=--\n", v, p.predFlag[v] ? "yes":"no ");
741
    }
742
  }
743
}
744
#else
745
#define logmvcand(p)
746
#endif
747
748
749
bool PBMotion::operator==(const PBMotion& b) const
750
1.78M
{
751
1.78M
  const PBMotion& a = *this;
752
753
  // TODO: is this really correct? no check for predFlag? Standard says so... (p.127)
754
755
4.01M
  for (int i=0;i<2;i++) {
756
2.99M
    if (a.predFlag[i] != b.predFlag[i]) return false;
757
758
2.77M
    if (a.predFlag[i]) {
759
2.21M
      if (a.mv[i].x != b.mv[i].x) return false;
760
1.83M
      if (a.mv[i].y != b.mv[i].y) return false;
761
1.74M
      if (a.refIdx[i] != b.refIdx[i]) return false;
762
1.74M
    }
763
2.77M
  }
764
765
1.02M
  return true;
766
1.78M
}
767
768
769
class MotionVectorAccess_de265_image : public MotionVectorAccess
770
{
771
public:
772
4.76M
  MotionVectorAccess_de265_image(const de265_image* i) : img(i) { }
773
774
4.76M
  enum PartMode get_PartMode(int x,int y) const override { return img->get_PartMode(x,y); }
775
4.35M
  const PBMotion& get_mv_info(int x,int y) const override { return img->get_mv_info(x,y); }
776
777
private:
778
  const de265_image* img;
779
};
780
781
782
783
/*
784
  +--+                +--+--+
785
  |B2|                |B1|B0|
786
  +--+----------------+--+--+
787
     |                   |
788
     |                   |
789
     |                   |
790
     |                   |
791
     |        PB         |
792
     |                   |
793
     |                   |
794
  +--+                   |
795
  |A1|                   |
796
  +--+-------------------+
797
  |A0|
798
  +--+
799
*/
800
801
802
// 8.5.3.1.2
803
// TODO: check: can we fill the candidate list directly in this function and omit to copy later
804
/*
805
  xC/yC:  CB position
806
  nCS:    CB size                 (probably modified because of singleMCLFlag)
807
  xP/yP:  PB position (absolute)  (probably modified because of singleMCLFlag)
808
  singleMCLFlag
809
  nPbW/nPbH: PB size
810
  partIdx
811
  out_cand: merging candidate vectors
812
813
  Add these candidates:
814
  - A1
815
  - B1  (if != A1)
816
  - B0  (if != B1)
817
  - A0  (if != A1)
818
  - B2  (if != A1 and != B1)
819
820
  A maximum of 4 candidates are generated.
821
822
  Note 1: For a CB split into two PBs, it does not make sense to merge the
823
  second part to the parameters of the first part, since then, we could use 2Nx2N
824
  right away. -> Exclude this candidate.
825
*/
826
int derive_spatial_merging_candidates(//const de265_image* img,
827
                                      const MotionVectorAccess& mvaccess,
828
                                      const de265_image* img,
829
                                      int xC, int yC, int nCS, int xP, int yP,
830
                                      uint8_t singleMCLFlag,
831
                                      int nPbW, int nPbH,
832
                                      int partIdx,
833
                                      PBMotion* out_cand,
834
                                      int maxCandidates)
835
4.76M
{
836
4.76M
  const pic_parameter_set* pps = &img->get_pps();
837
4.76M
  const int log2_parallel_merge_level = pps->log2_parallel_merge_level;
838
839
4.76M
  enum PartMode PartMode = mvaccess.get_PartMode(xC,yC);
840
841
  /*
842
  const int A0 = SpatialMergingCandidates::PRED_A0;
843
  const int A1 = SpatialMergingCandidates::PRED_A1;
844
  const int B0 = SpatialMergingCandidates::PRED_B0;
845
  const int B1 = SpatialMergingCandidates::PRED_B1;
846
  const int B2 = SpatialMergingCandidates::PRED_B2;
847
  */
848
849
  // --- A1 ---
850
851
  // a pixel within A1 (bottom right of A1)
852
4.76M
  int xA1 = xP-1;
853
4.76M
  int yA1 = yP+nPbH-1;
854
855
4.76M
  bool availableA1;
856
4.76M
  int idxA1;
857
858
4.76M
  int computed_candidates = 0;
859
860
  // check if candidate is in same motion-estimation region (MER) -> discard
861
4.76M
  if ((xP>>log2_parallel_merge_level) == (xA1>>log2_parallel_merge_level) &&
862
92.6k
      (yP>>log2_parallel_merge_level) == (yA1>>log2_parallel_merge_level)) {
863
82.4k
    availableA1 = false;
864
82.4k
    logtrace(LogMotion,"spatial merging candidate A1: below parallel merge level\n");
865
82.4k
  }
866
  // redundant candidate? (Note 1) -> discard
867
4.68M
  else if (// !singleMCLFlag &&    automatically true when partIdx==1
868
4.68M
           partIdx==1 &&
869
479k
           (PartMode==PART_Nx2N ||
870
277k
            PartMode==PART_nLx2N ||
871
254k
            PartMode==PART_nRx2N)) {
872
228k
    availableA1 = false;
873
228k
    logtrace(LogMotion,"spatial merging candidate A1: second part ignore\n");
874
228k
  }
875
  // MV available in A1
876
4.45M
  else {
877
4.45M
    availableA1 = img->available_pred_blk(xC,yC, nCS, xP,yP, nPbW,nPbH,partIdx, xA1,yA1);
878
4.45M
    if (!availableA1) logtrace(LogMotion,"spatial merging candidate A1: unavailable\n");
879
4.45M
  }
880
881
4.76M
  if (availableA1) {
882
4.35M
    idxA1 = computed_candidates++;
883
4.35M
    out_cand[idxA1] = mvaccess.get_mv_info(xA1,yA1);
884
885
4.35M
    logtrace(LogMotion,"spatial merging candidate A1:\n");
886
4.35M
    logmvcand(out_cand[idxA1]);
887
4.35M
  }
888
889
4.76M
  if (computed_candidates>=maxCandidates) return computed_candidates;
890
891
892
  // --- B1 ---
893
894
1.29M
  int xB1 = xP+nPbW-1;
895
1.29M
  int yB1 = yP-1;
896
897
1.29M
  bool availableB1;
898
1.29M
  int idxB1;
899
900
  // same MER -> discard
901
1.29M
  if ((xP>>log2_parallel_merge_level) == (xB1>>log2_parallel_merge_level) &&
902
452k
      (yP>>log2_parallel_merge_level) == (yB1>>log2_parallel_merge_level)) {
903
60.5k
    availableB1 = false;
904
60.5k
    logtrace(LogMotion,"spatial merging candidate B1: below parallel merge level\n");
905
60.5k
  }
906
  // redundant candidate (Note 1) -> discard
907
1.23M
  else if (// !singleMCLFlag &&    automatically true when partIdx==1
908
1.23M
           partIdx==1 &&
909
337k
           (PartMode==PART_2NxN ||
910
233k
            PartMode==PART_2NxnU ||
911
231k
            PartMode==PART_2NxnD)) {
912
107k
    availableB1 = false;
913
107k
    logtrace(LogMotion,"spatial merging candidate B1: second part ignore\n");
914
107k
  }
915
  // MV available in B1
916
1.13M
  else {
917
1.13M
    availableB1 = img->available_pred_blk(xC,yC, nCS, xP,yP, nPbW,nPbH,partIdx, xB1,yB1);
918
1.13M
    if (!availableB1) logtrace(LogMotion,"spatial merging candidate B1: unavailable\n");
919
1.13M
  }
920
921
1.29M
  if (availableB1) {
922
924k
    const PBMotion& b1 = img->get_mv_info(xB1,yB1);
923
924
    // B1 == A1 -> discard B1
925
924k
    if (availableA1 && out_cand[idxA1] == b1) {
926
352k
      idxB1 = idxA1;
927
352k
      logtrace(LogMotion,"spatial merging candidate B1: redundant to A1\n");
928
352k
    }
929
571k
    else {
930
571k
      idxB1 = computed_candidates++;
931
571k
      out_cand[idxB1] = b1;
932
933
571k
      logtrace(LogMotion,"spatial merging candidate B1:\n");
934
571k
      logmvcand(out_cand[idxB1]);
935
571k
    }
936
924k
  }
937
938
1.29M
  if (computed_candidates>=maxCandidates) return computed_candidates;
939
940
941
  // --- B0 ---
942
943
884k
  int xB0 = xP+nPbW;
944
884k
  int yB0 = yP-1;
945
946
884k
  bool availableB0;
947
884k
  int idxB0;
948
949
884k
  if ((xP>>log2_parallel_merge_level) == (xB0>>log2_parallel_merge_level) &&
950
44.8k
      (yP>>log2_parallel_merge_level) == (yB0>>log2_parallel_merge_level)) {
951
36.0k
    availableB0 = false;
952
36.0k
    logtrace(LogMotion,"spatial merging candidate B0: below parallel merge level\n");
953
36.0k
  }
954
848k
  else {
955
848k
    availableB0 = img->available_pred_blk(xC,yC, nCS, xP,yP, nPbW,nPbH,partIdx, xB0,yB0);
956
848k
    if (!availableB0) logtrace(LogMotion,"spatial merging candidate B0: unavailable\n");
957
848k
  }
958
959
884k
  if (availableB0) {
960
399k
    const PBMotion& b0 = img->get_mv_info(xB0,yB0);
961
962
    // B0 == B1 -> discard B0
963
399k
    if (availableB1 && out_cand[idxB1]==b0) {
964
218k
      idxB0 = idxB1;
965
218k
      logtrace(LogMotion,"spatial merging candidate B0: redundant to B1\n");
966
218k
    }
967
181k
    else {
968
181k
      idxB0 = computed_candidates++;
969
181k
      out_cand[idxB0] = b0;
970
181k
      logtrace(LogMotion,"spatial merging candidate B0:\n");
971
181k
      logmvcand(out_cand[idxB0]);
972
181k
    }
973
399k
  }
974
975
884k
  if (computed_candidates>=maxCandidates) return computed_candidates;
976
977
978
  // --- A0 ---
979
980
752k
  int xA0 = xP-1;
981
752k
  int yA0 = yP+nPbH;
982
983
752k
  bool availableA0;
984
752k
  int idxA0;
985
986
752k
  if ((xP>>log2_parallel_merge_level) == (xA0>>log2_parallel_merge_level) &&
987
77.0k
      (yP>>log2_parallel_merge_level) == (yA0>>log2_parallel_merge_level)) {
988
45.2k
    availableA0 = false;
989
45.2k
    logtrace(LogMotion,"spatial merging candidate A0: below parallel merge level\n");
990
45.2k
  }
991
706k
  else {
992
706k
    availableA0 = img->available_pred_blk(xC,yC, nCS, xP,yP, nPbW,nPbH,partIdx, xA0,yA0);
993
706k
    if (!availableA0) logtrace(LogMotion,"spatial merging candidate A0: unavailable\n");
994
706k
  }
995
996
752k
  if (availableA0) {
997
168k
    const PBMotion& a0 = img->get_mv_info(xA0,yA0);
998
999
    // A0 == A1 -> discard A0
1000
168k
    if (availableA1 && out_cand[idxA1]==a0) {
1001
118k
      idxA0 = idxA1;
1002
118k
      logtrace(LogMotion,"spatial merging candidate A0: redundant to A1\n");
1003
118k
    }
1004
49.7k
    else {
1005
49.7k
      idxA0 = computed_candidates++;
1006
49.7k
      out_cand[idxA0] = a0;
1007
49.7k
      logtrace(LogMotion,"spatial merging candidate A0:\n");
1008
49.7k
      logmvcand(out_cand[idxA0]);
1009
49.7k
    }
1010
168k
  }
1011
1012
752k
  if (computed_candidates>=maxCandidates) return computed_candidates;
1013
1014
1015
  // --- B2 ---
1016
1017
716k
  int xB2 = xP-1;
1018
716k
  int yB2 = yP-1;
1019
1020
716k
  bool availableB2;
1021
716k
  int idxB2;
1022
1023
  // if we already have four candidates, do not consider B2 anymore
1024
716k
  if (computed_candidates==4) {
1025
962
    availableB2 = false;
1026
962
    logtrace(LogMotion,"spatial merging candidate B2: ignore\n");
1027
962
  }
1028
715k
  else if ((xP>>log2_parallel_merge_level) == (xB2>>log2_parallel_merge_level) &&
1029
77.0k
           (yP>>log2_parallel_merge_level) == (yB2>>log2_parallel_merge_level)) {
1030
58.2k
    availableB2 = false;
1031
58.2k
    logtrace(LogMotion,"spatial merging candidate B2: below parallel merge level\n");
1032
58.2k
  }
1033
657k
  else {
1034
657k
    availableB2 = img->available_pred_blk(xC,yC, nCS, xP,yP, nPbW,nPbH,partIdx, xB2,yB2);
1035
657k
    if (!availableB2) logtrace(LogMotion,"spatial merging candidate B2: unavailable\n");
1036
657k
  }
1037
1038
716k
  if (availableB2) {
1039
459k
    const PBMotion& b2 = img->get_mv_info(xB2,yB2);
1040
1041
    // B2 == B1 -> discard B2
1042
459k
    if (availableB1 && out_cand[idxB1]==b2) {
1043
251k
      idxB2 = idxB1;
1044
251k
      logtrace(LogMotion,"spatial merging candidate B2: redundant to B1\n");
1045
251k
    }
1046
    // B2 == A1 -> discard B2
1047
207k
    else if (availableA1 && out_cand[idxA1]==b2) {
1048
81.3k
      idxB2 = idxA1;
1049
81.3k
      logtrace(LogMotion,"spatial merging candidate B2: redundant to A1\n");
1050
81.3k
    }
1051
125k
    else {
1052
125k
      idxB2 = computed_candidates++;
1053
125k
      out_cand[idxB2] = b2;
1054
125k
      logtrace(LogMotion,"spatial merging candidate B2:\n");
1055
125k
      logmvcand(out_cand[idxB2]);
1056
125k
    }
1057
459k
  }
1058
1059
716k
  return computed_candidates;
1060
752k
}
1061
1062
1063
// 8.5.3.1.4
1064
void derive_zero_motion_vector_candidates(const slice_segment_header* shdr,
1065
                                          PBMotion* out_mergeCandList,
1066
                                          int* inout_numCurrMergeCand,
1067
                                          int maxCandidates)
1068
4.76M
{
1069
4.76M
  logtrace(LogMotion,"derive_zero_motion_vector_candidates\n");
1070
1071
4.76M
  int numRefIdx;
1072
1073
4.76M
  if (shdr->slice_type==SLICE_TYPE_P) {
1074
492k
    numRefIdx = shdr->num_ref_idx_l0_active;
1075
492k
  }
1076
4.27M
  else {
1077
4.27M
    numRefIdx = std::min(shdr->num_ref_idx_l0_active,
1078
4.27M
                             shdr->num_ref_idx_l1_active);
1079
4.27M
  }
1080
1081
1082
  //int numInputMergeCand = *inout_numMergeCand;
1083
4.76M
  int zeroIdx = 0;
1084
1085
5.58M
  while (*inout_numCurrMergeCand < maxCandidates) {
1086
    // 1.
1087
1088
815k
    logtrace(LogMotion,"zeroIdx:%d numRefIdx:%d\n", zeroIdx, numRefIdx);
1089
1090
815k
    PBMotion* newCand = &out_mergeCandList[*inout_numCurrMergeCand];
1091
1092
815k
    const int refIdx = (zeroIdx < numRefIdx) ? zeroIdx : 0;
1093
1094
815k
    if (shdr->slice_type==SLICE_TYPE_P) {
1095
116k
      newCand->refIdx[0] = refIdx;
1096
116k
      newCand->refIdx[1] = 0;
1097
116k
      newCand->predFlag[0] = 1;
1098
116k
      newCand->predFlag[1] = 0;
1099
116k
    }
1100
698k
    else {
1101
698k
      newCand->refIdx[0] = refIdx;
1102
698k
      newCand->refIdx[1] = refIdx;
1103
698k
      newCand->predFlag[0] = 1;
1104
698k
      newCand->predFlag[1] = 1;
1105
698k
    }
1106
1107
815k
    newCand->mv[0].x = 0;
1108
815k
    newCand->mv[0].y = 0;
1109
815k
    newCand->mv[1].x = 0;
1110
815k
    newCand->mv[1].y = 0;
1111
1112
815k
    (*inout_numCurrMergeCand)++;
1113
1114
    // 2.
1115
1116
815k
    zeroIdx++;
1117
815k
  }
1118
4.76M
}
1119
1120
1121
bool scale_mv(MotionVector* out_mv, MotionVector mv, int colDist, int currDist)
1122
32.0k
{
1123
32.0k
  int td = Clip3(-128,127, colDist);
1124
32.0k
  int tb = Clip3(-128,127, currDist);
1125
1126
32.0k
  if (td==0) {
1127
0
    *out_mv = mv;
1128
0
    return false;
1129
0
  }
1130
32.0k
  else {
1131
32.0k
    int tx = (16384 + (std::abs(td)>>1)) / td;
1132
32.0k
    int distScaleFactor = Clip3(-4096,4095, (tb*tx+32)>>6);
1133
32.0k
    out_mv->x = Clip3(-32768,32767,
1134
32.0k
                      Sign(distScaleFactor*mv.x)*((std::abs(distScaleFactor*mv.x)+127)>>8));
1135
32.0k
    out_mv->y = Clip3(-32768,32767,
1136
32.0k
                      Sign(distScaleFactor*mv.y)*((std::abs(distScaleFactor*mv.y)+127)>>8));
1137
32.0k
    return true;
1138
32.0k
  }
1139
32.0k
}
1140
1141
1142
// (L1003) 8.5.3.2.8
1143
1144
void derive_collocated_motion_vectors(base_context* ctx,
1145
                                      de265_image* img,
1146
                                      const slice_segment_header* shdr,
1147
                                      int xP,int yP,
1148
                                      int colPic,
1149
                                      int xColPb,int yColPb,
1150
                                      int refIdxLX,  // (always 0 for merge mode)
1151
                                      int X,
1152
                                      MotionVector* out_mvLXCol,
1153
                                      uint8_t* out_availableFlagLXCol)
1154
1.30M
{
1155
1.30M
  logtrace(LogMotion,"derive_collocated_motion_vectors %d;%d\n",xP,yP);
1156
1157
1158
  // get collocated image and the prediction mode at the collocated position
1159
1160
1.30M
  assert(ctx->has_image(colPic));
1161
1.30M
  const de265_image* colImg = ctx->get_image(colPic);
1162
1163
  // check for access outside image area
1164
1165
1.30M
  if (xColPb >= colImg->get_width() ||
1166
1.30M
      yColPb >= colImg->get_height()) {
1167
0
    ctx->add_warning(DE265_WARNING_COLLOCATED_MOTION_VECTOR_OUTSIDE_IMAGE_AREA, false);
1168
0
    *out_availableFlagLXCol = 0;
1169
0
    return;
1170
0
  }
1171
1172
1.30M
  enum PredMode predMode = colImg->get_pred_mode(xColPb,yColPb);
1173
1174
1175
  // collocated block is Intra -> no collocated MV
1176
1177
1.30M
  if (predMode == MODE_INTRA) {
1178
1.23M
    out_mvLXCol->x = 0;
1179
1.23M
    out_mvLXCol->y = 0;
1180
1.23M
    *out_availableFlagLXCol = 0;
1181
1.23M
    return;
1182
1.23M
  }
1183
1184
1185
79.0k
  logtrace(LogMotion,"colPic:%d (POC=%d) X:%d refIdxLX:%d refpiclist:%d\n",
1186
79.0k
           colPic,
1187
79.0k
           colImg->PicOrderCntVal,
1188
79.0k
           X,refIdxLX,shdr->RefPicList[X][refIdxLX]);
1189
1190
1191
  // collocated reference image is unavailable -> no collocated MV
1192
1193
79.0k
  if (colImg->integrity == INTEGRITY_UNAVAILABLE_REFERENCE) {
1194
0
    out_mvLXCol->x = 0;
1195
0
    out_mvLXCol->y = 0;
1196
0
    *out_availableFlagLXCol = 0;
1197
0
    return;
1198
0
  }
1199
1200
1201
  // get the collocated MV
1202
1203
79.0k
  const PBMotion& mvi = colImg->get_mv_info(xColPb,yColPb);
1204
79.0k
  int listCol;
1205
79.0k
  int refIdxCol;
1206
79.0k
  MotionVector mvCol;
1207
1208
79.0k
  logtrace(LogMotion,"read MVI %d;%d:\n",xColPb,yColPb);
1209
79.0k
  logmvcand(mvi);
1210
1211
1212
  // collocated MV uses only L1 -> use L1
1213
79.0k
  if (mvi.predFlag[0]==0) {
1214
39.4k
    mvCol = mvi.mv[1];
1215
39.4k
    refIdxCol = mvi.refIdx[1];
1216
39.4k
    listCol = 1;
1217
39.4k
  }
1218
  // collocated MV uses only L0 -> use L0
1219
39.6k
  else if (mvi.predFlag[1]==0) {
1220
24.7k
    mvCol = mvi.mv[0];
1221
24.7k
    refIdxCol = mvi.refIdx[0];
1222
24.7k
    listCol = 0;
1223
24.7k
  }
1224
  // collocated MV uses L0 and L1
1225
14.8k
  else {
1226
14.8k
    bool allRefFramesBeforeCurrentFrame = true;
1227
1228
14.8k
    const int currentPOC = img->PicOrderCntVal;
1229
1230
    // all reference POCs earlier than current POC (list 1)
1231
    // Test L1 first, because there is a higher change to find a future reference frame.
1232
1233
31.4k
    for (int rIdx=0; rIdx<shdr->num_ref_idx_l1_active && allRefFramesBeforeCurrentFrame; rIdx++)
1234
16.6k
      {
1235
16.6k
        const de265_image* refimg = ctx->get_image(shdr->RefPicList[1][rIdx]);
1236
16.6k
        int refPOC = refimg->PicOrderCntVal;
1237
1238
16.6k
        if (refPOC > currentPOC) {
1239
565
          allRefFramesBeforeCurrentFrame = false;
1240
565
        }
1241
16.6k
      }
1242
1243
    // all reference POCs earlier than current POC (list 0)
1244
1245
30.1k
    for (int rIdx=0; rIdx<shdr->num_ref_idx_l0_active && allRefFramesBeforeCurrentFrame; rIdx++)
1246
15.3k
      {
1247
15.3k
        const de265_image* refimg = ctx->get_image(shdr->RefPicList[0][rIdx]);
1248
15.3k
        int refPOC = refimg->PicOrderCntVal;
1249
1250
15.3k
        if (refPOC > currentPOC) {
1251
40
          allRefFramesBeforeCurrentFrame = false;
1252
40
        }
1253
15.3k
      }
1254
1255
1256
    /* TODO: What is the rationale behind this ???
1257
1258
       My guess:
1259
       when there are images before the current frame (most probably in L0) and images after
1260
       the current frame (most probably in L1), we take the reference in the opposite
1261
       direction than where the collocated frame is positioned in the hope that the distance
1262
       to the current frame will be smaller and thus give a better prediction.
1263
1264
       If all references point into the past, we cannot say much about the temporal order or
1265
       L0,L1 and thus take over both parts.
1266
     */
1267
1268
14.8k
    if (allRefFramesBeforeCurrentFrame) {
1269
14.2k
      mvCol = mvi.mv[X];
1270
14.2k
      refIdxCol = mvi.refIdx[X];
1271
14.2k
      listCol = X;
1272
14.2k
    }
1273
605
    else {
1274
605
      int N = shdr->collocated_from_l0_flag;
1275
605
      mvCol = mvi.mv[N];
1276
605
      refIdxCol = mvi.refIdx[N];
1277
605
      listCol = N;
1278
605
    }
1279
14.8k
  }
1280
1281
1282
1283
79.0k
  uint16_t slice_hdr_idx = colImg->get_SliceHeaderIndex(xColPb,yColPb);
1284
79.0k
  if (slice_hdr_idx >= colImg->slices.size()) {
1285
0
    ctx->add_warning(DE265_WARNING_INVALID_SLICE_HEADER_INDEX_ACCESS, false);
1286
1287
0
    *out_availableFlagLXCol = 0;
1288
0
    out_mvLXCol->x = 0;
1289
0
    out_mvLXCol->y = 0;
1290
0
    return;
1291
0
  }
1292
1293
79.0k
  const slice_segment_header* colShdr = colImg->slices[ colImg->get_SliceHeaderIndex(xColPb,yColPb) ];
1294
1295
79.0k
  if (shdr->LongTermRefPic[X][refIdxLX] !=
1296
79.0k
      colShdr->LongTermRefPic[listCol][refIdxCol]) {
1297
6.17k
    *out_availableFlagLXCol = 0;
1298
6.17k
    out_mvLXCol->x = 0;
1299
6.17k
    out_mvLXCol->y = 0;
1300
6.17k
  }
1301
72.9k
  else {
1302
72.9k
    *out_availableFlagLXCol = 1;
1303
1304
72.9k
    const bool isLongTerm = shdr->LongTermRefPic[X][refIdxLX];
1305
1306
72.9k
    int colDist  = colImg->PicOrderCntVal - colShdr->RefPicList_POC[listCol][refIdxCol];
1307
72.9k
    int currDist = img->PicOrderCntVal - shdr->RefPicList_POC[X][refIdxLX];
1308
1309
72.9k
    logtrace(LogMotion,"COLPOCDIFF %d %d [%d %d / %d %d]\n",colDist, currDist,
1310
72.9k
             colImg->PicOrderCntVal, colShdr->RefPicList_POC[listCol][refIdxCol],
1311
72.9k
             img->PicOrderCntVal, shdr->RefPicList_POC[X][refIdxLX]
1312
72.9k
             );
1313
1314
72.9k
    if (isLongTerm || colDist == currDist) {
1315
72.3k
      *out_mvLXCol = mvCol;
1316
72.3k
    }
1317
603
    else {
1318
603
      if (!scale_mv(out_mvLXCol, mvCol, colDist, currDist)) {
1319
0
        ctx->add_warning(DE265_WARNING_INCORRECT_MOTION_VECTOR_SCALING, false);
1320
0
        img->integrity = INTEGRITY_DECODING_ERRORS;
1321
0
      }
1322
1323
603
      logtrace(LogMotion,"scale: %d;%d to %d;%d\n",
1324
603
               mvCol.x,mvCol.y, out_mvLXCol->x,out_mvLXCol->y);
1325
603
    }
1326
72.9k
  }
1327
79.0k
}
1328
1329
1330
// 8.5.3.1.7
1331
void derive_temporal_luma_vector_prediction(base_context* ctx,
1332
                                            de265_image* img,
1333
                                            const slice_segment_header* shdr,
1334
                                            int xP,int yP,
1335
                                            int nPbW,int nPbH,
1336
                                            int refIdxL,
1337
                                            int X, // which MV (L0/L1) to get
1338
                                            MotionVector* out_mvLXCol,
1339
                                            uint8_t*      out_availableFlagLXCol)
1340
2.49M
{
1341
  // --- no temporal MVP -> exit ---
1342
1343
2.49M
  if (shdr->slice_temporal_mvp_enabled_flag == 0) {
1344
1.65M
    out_mvLXCol->x = 0;
1345
1.65M
    out_mvLXCol->y = 0;
1346
1.65M
    *out_availableFlagLXCol = 0;
1347
1.65M
    return;
1348
1.65M
  }
1349
1350
1351
  // --- find collocated reference image ---
1352
1353
837k
  int Log2CtbSizeY = img->get_sps().Log2CtbSizeY;
1354
1355
837k
  int colPic; // TODO: this is the same for the whole slice. We can precompute it.
1356
1357
837k
  if (shdr->slice_type == SLICE_TYPE_B &&
1358
744k
      shdr->collocated_from_l0_flag == 0)
1359
117k
    {
1360
117k
      logtrace(LogMotion,"collocated L1 ref_idx=%d\n",shdr->collocated_ref_idx);
1361
1362
117k
      colPic = shdr->RefPicList[1][ shdr->collocated_ref_idx ];
1363
117k
    }
1364
719k
  else
1365
719k
    {
1366
719k
      logtrace(LogMotion,"collocated L0 ref_idx=%d\n",shdr->collocated_ref_idx);
1367
1368
719k
      colPic = shdr->RefPicList[0][ shdr->collocated_ref_idx ];
1369
719k
    }
1370
1371
1372
  // check whether collocated reference picture exists
1373
1374
837k
  if (!ctx->has_image(colPic)) {
1375
0
    out_mvLXCol->x = 0;
1376
0
    out_mvLXCol->y = 0;
1377
0
    *out_availableFlagLXCol = 0;
1378
1379
0
    ctx->add_warning(DE265_WARNING_NONEXISTING_REFERENCE_PICTURE_ACCESSED, false);
1380
0
    return;
1381
0
  }
1382
1383
1384
  // --- get collocated MV either at bottom-right corner or from center of PB ---
1385
1386
837k
  int xColPb,yColPb;
1387
837k
  int yColBr = yP + nPbH; // bottom right collocated motion vector position
1388
837k
  int xColBr = xP + nPbW;
1389
1390
  /* If neighboring pixel at bottom-right corner is in the same CTB-row and inside the image,
1391
     use this (reduced down to 16 pixels resolution) as collocated MV position.
1392
1393
     Note: see 2014, Sze, Sect. 5.2.1.2 why candidate C0 is excluded when on another CTB-row.
1394
     This is to reduce the memory bandwidth requirements.
1395
   */
1396
837k
  if ((yP>>Log2CtbSizeY) == (yColBr>>Log2CtbSizeY) &&
1397
500k
      xColBr < img->get_sps().pic_width_in_luma_samples &&
1398
494k
      yColBr < img->get_sps().pic_height_in_luma_samples)
1399
483k
    {
1400
483k
      xColPb = xColBr & ~0x0F; // reduce resolution of collocated motion-vectors to 16 pixels grid
1401
483k
      yColPb = yColBr & ~0x0F;
1402
1403
483k
      derive_collocated_motion_vectors(ctx,img,shdr, xP,yP, colPic, xColPb,yColPb, refIdxL, X,
1404
483k
                                       out_mvLXCol, out_availableFlagLXCol);
1405
483k
    }
1406
353k
  else
1407
353k
    {
1408
353k
      out_mvLXCol->x = 0;
1409
353k
      out_mvLXCol->y = 0;
1410
353k
      *out_availableFlagLXCol = 0;
1411
353k
    }
1412
1413
1414
837k
  if (*out_availableFlagLXCol==0) {
1415
1416
825k
    int xColCtr = xP+(nPbW>>1);
1417
825k
    int yColCtr = yP+(nPbH>>1);
1418
1419
825k
    xColPb = xColCtr & ~0x0F; // reduce resolution of collocated motion-vectors to 16 pixels grid
1420
825k
    yColPb = yColCtr & ~0x0F;
1421
1422
825k
    derive_collocated_motion_vectors(ctx,img,shdr, xP,yP, colPic, xColPb,yColPb, refIdxL, X,
1423
825k
                                     out_mvLXCol, out_availableFlagLXCol);
1424
825k
  }
1425
837k
}
1426
1427
1428
static int table_8_19[2][12] = {
1429
  { 0,1,0,2,1,2,0,3,1,3,2,3 },
1430
  { 1,0,2,0,2,1,3,0,3,1,3,2 }
1431
  };
1432
1433
// 8.5.3.1.3
1434
/* Note (TODO): during decoding, we know which of the candidates we will select.
1435
+   Hence, we do not really have to generate the other ones...
1436
+ */
1437
void derive_combined_bipredictive_merging_candidates(const base_context* ctx,
1438
                                                     const slice_segment_header* shdr,
1439
                                                     PBMotion* inout_mergeCandList,
1440
                                                     int* inout_numMergeCand,
1441
                                                     int maxCandidates)
1442
4.27M
{
1443
4.27M
  if (*inout_numMergeCand>1 && *inout_numMergeCand < maxCandidates) {
1444
96.1k
    int numOrigMergeCand = *inout_numMergeCand;
1445
1446
96.1k
    int numInputMergeCand = *inout_numMergeCand;
1447
96.1k
    int combIdx = 0;
1448
96.1k
    uint8_t combStop = false;
1449
1450
324k
    while (!combStop) {
1451
228k
      int l0CandIdx = table_8_19[0][combIdx];
1452
228k
      int l1CandIdx = table_8_19[1][combIdx];
1453
1454
228k
      if (l0CandIdx >= numInputMergeCand ||
1455
228k
          l1CandIdx >= numInputMergeCand) {
1456
0
        assert(false); // bitstream error -> TODO: conceal error
1457
0
      }
1458
1459
228k
      PBMotion& l0Cand = inout_mergeCandList[l0CandIdx];
1460
228k
      PBMotion& l1Cand = inout_mergeCandList[l1CandIdx];
1461
1462
228k
      logtrace(LogMotion,"add bipredictive merging candidate (combIdx:%d)\n",combIdx);
1463
228k
      logtrace(LogMotion,"l0Cand:\n"); logmvcand(l0Cand);
1464
228k
      logtrace(LogMotion,"l1Cand:\n"); logmvcand(l1Cand);
1465
1466
228k
      const de265_image* img0 = l0Cand.predFlag[0] ? ctx->get_image(shdr->RefPicList[0][l0Cand.refIdx[0]]) : nullptr;
1467
228k
      const de265_image* img1 = l1Cand.predFlag[1] ? ctx->get_image(shdr->RefPicList[1][l1Cand.refIdx[1]]) : nullptr;
1468
1469
228k
      if (l0Cand.predFlag[0] && !img0) {
1470
0
        return; // TODO error
1471
0
      }
1472
1473
228k
      if (l1Cand.predFlag[1] && !img1) {
1474
0
        return; // TODO error
1475
0
      }
1476
1477
228k
      if (l0Cand.predFlag[0] && l1Cand.predFlag[1] &&
1478
104k
          (img0->PicOrderCntVal != img1->PicOrderCntVal     ||
1479
80.5k
           l0Cand.mv[0].x != l1Cand.mv[1].x ||
1480
62.2k
           l0Cand.mv[0].y != l1Cand.mv[1].y)) {
1481
62.2k
        PBMotion& p = inout_mergeCandList[ *inout_numMergeCand ];
1482
62.2k
        p.refIdx[0] = l0Cand.refIdx[0];
1483
62.2k
        p.refIdx[1] = l1Cand.refIdx[1];
1484
62.2k
        p.predFlag[0] = l0Cand.predFlag[0];
1485
62.2k
        p.predFlag[1] = l1Cand.predFlag[1];
1486
62.2k
        p.mv[0] = l0Cand.mv[0];
1487
62.2k
        p.mv[1] = l1Cand.mv[1];
1488
62.2k
        (*inout_numMergeCand)++;
1489
1490
62.2k
        logtrace(LogMotion,"result:\n");
1491
62.2k
        logmvcand(p);
1492
62.2k
      }
1493
1494
228k
      combIdx++;
1495
228k
      if (combIdx == numOrigMergeCand*(numOrigMergeCand-1) ||
1496
161k
          *inout_numMergeCand == maxCandidates) {
1497
96.1k
        combStop = true;
1498
96.1k
      }
1499
228k
    }
1500
96.1k
  }
1501
4.27M
}
1502
1503
1504
// 8.5.3.1.1
1505
1506
void get_merge_candidate_list_without_step_9(base_context* ctx,
1507
                                             const slice_segment_header* shdr,
1508
                                             const MotionVectorAccess& mvaccess,
1509
                                             de265_image* img,
1510
                                             int xC,int yC, int xP,int yP,
1511
                                             int nCS, int nPbW,int nPbH, int partIdx,
1512
                                             int max_merge_idx,
1513
                                             PBMotion* mergeCandList)
1514
4.76M
{
1515
1516
  //int xOrigP = xP;
1517
  //int yOrigP = yP;
1518
  //int nOrigPbW = nPbW;
1519
  //int nOrigPbH = nPbH;
1520
1521
4.76M
  int singleMCLFlag; // single merge-candidate-list (MCL) flag
1522
1523
  /* Use single MCL for CBs of size 8x8, except when parallel-merge-level is at 4x4.
1524
     Without this flag, PBs smaller than 8x8 would not receive as much merging candidates.
1525
     Having additional candidates might have these advantages:
1526
     - coding MVs for these small PBs is expensive, and
1527
     - since the PBs are not far away from a proper (neighboring) merging candidate,
1528
     the quality of the candidates will still be good.
1529
  */
1530
4.76M
  singleMCLFlag = (img->get_pps().log2_parallel_merge_level > 2 && nCS==8);
1531
1532
4.76M
  if (singleMCLFlag) {
1533
1.15M
    xP=xC;
1534
1.15M
    yP=yC;
1535
1.15M
    nPbW=nCS;
1536
1.15M
    nPbH=nCS;
1537
1.15M
    partIdx=0;
1538
1.15M
  }
1539
1540
4.76M
  int maxCandidates = max_merge_idx+1;
1541
  //MotionVectorSpec mergeCandList[5];
1542
4.76M
  int numMergeCand=0;
1543
1544
  // --- spatial merge candidates
1545
1546
4.76M
  numMergeCand = derive_spatial_merging_candidates(mvaccess,
1547
4.76M
                                                   img, xC,yC, nCS, xP,yP, singleMCLFlag,
1548
4.76M
                                                   nPbW,nPbH,partIdx, mergeCandList,
1549
4.76M
                                                   maxCandidates);
1550
1551
  // --- collocated merge candidate
1552
4.76M
  if (numMergeCand < maxCandidates) {
1553
627k
    int refIdxCol[2] = { 0,0 };
1554
1555
627k
    MotionVector mvCol[2];
1556
627k
    uint8_t predFlagLCol[2];
1557
627k
    derive_temporal_luma_vector_prediction(ctx,img,shdr, xP,yP,nPbW,nPbH,
1558
627k
                                           refIdxCol[0],0, &mvCol[0],
1559
627k
                                           &predFlagLCol[0]);
1560
1561
627k
    uint8_t availableFlagCol = predFlagLCol[0];
1562
627k
    predFlagLCol[1] = 0;
1563
1564
627k
    if (shdr->slice_type == SLICE_TYPE_B) {
1565
530k
      derive_temporal_luma_vector_prediction(ctx,img,shdr,
1566
530k
                                             xP,yP,nPbW,nPbH, refIdxCol[1],1, &mvCol[1],
1567
530k
                                             &predFlagLCol[1]);
1568
530k
      availableFlagCol |= predFlagLCol[1];
1569
530k
    }
1570
1571
1572
627k
    if (availableFlagCol) {
1573
13.1k
      PBMotion* colVec = &mergeCandList[numMergeCand++];
1574
1575
13.1k
      colVec->mv[0] = mvCol[0];
1576
13.1k
      colVec->mv[1] = mvCol[1];
1577
13.1k
      colVec->predFlag[0] = predFlagLCol[0];
1578
13.1k
      colVec->predFlag[1] = predFlagLCol[1];
1579
13.1k
      colVec->refIdx[0] = refIdxCol[0];
1580
13.1k
      colVec->refIdx[1] = refIdxCol[1];
1581
13.1k
    }
1582
627k
  }
1583
1584
1585
  // --- bipredictive merge candidates ---
1586
1587
4.76M
  if (shdr->slice_type == SLICE_TYPE_B) {
1588
4.27M
    derive_combined_bipredictive_merging_candidates(ctx, shdr,
1589
4.27M
                                                    mergeCandList, &numMergeCand, maxCandidates);
1590
4.27M
  }
1591
1592
1593
  // --- zero-vector merge candidates ---
1594
1595
4.76M
  derive_zero_motion_vector_candidates(shdr, mergeCandList, &numMergeCand, maxCandidates);
1596
1597
1598
4.76M
  logtrace(LogMotion,"mergeCandList:\n");
1599
24.6M
  for (int i=0;i<shdr->MaxNumMergeCand;i++)
1600
19.9M
    {
1601
      //logtrace(LogMotion, " %d:%s\n", i, i==merge_idx ? " SELECTED":"");
1602
19.9M
      logmvcand(mergeCandList[i]);
1603
19.9M
    }
1604
4.76M
}
1605
1606
1607
1608
void get_merge_candidate_list(base_context* ctx,
1609
                              const slice_segment_header* shdr,
1610
                              de265_image* img,
1611
                              int xC,int yC, int xP,int yP,
1612
                              int nCS, int nPbW,int nPbH, int partIdx,
1613
                              PBMotion* mergeCandList)
1614
0
{
1615
0
  int max_merge_idx = 5-shdr->five_minus_max_num_merge_cand -1;
1616
1617
0
  get_merge_candidate_list_without_step_9(ctx, shdr,
1618
0
                                          MotionVectorAccess_de265_image(img), img,
1619
0
                                          xC,yC,xP,yP,nCS,nPbW,nPbH, partIdx,
1620
0
                                          max_merge_idx, mergeCandList);
1621
1622
  // 9. for encoder: modify all merge candidates
1623
1624
0
  for (int i=0;i<=max_merge_idx;i++) {
1625
0
    if (mergeCandList[i].predFlag[0] &&
1626
0
        mergeCandList[i].predFlag[1] &&
1627
0
        nPbW+nPbH==12)
1628
0
      {
1629
0
        mergeCandList[i].refIdx[1]   = 0;
1630
0
        mergeCandList[i].predFlag[1] = 0;
1631
0
      }
1632
0
  }
1633
0
}
1634
1635
1636
void derive_luma_motion_merge_mode(base_context* ctx,
1637
                                   const slice_segment_header* shdr,
1638
                                   de265_image* img,
1639
                                   int xC,int yC, int xP,int yP,
1640
                                   int nCS, int nPbW,int nPbH, int partIdx,
1641
                                   int merge_idx,
1642
                                   PBMotion* out_vi)
1643
4.76M
{
1644
4.76M
  PBMotion mergeCandList[5];
1645
1646
4.76M
  get_merge_candidate_list_without_step_9(ctx, shdr,
1647
4.76M
                                          MotionVectorAccess_de265_image(img), img,
1648
4.76M
                                          xC,yC,xP,yP,nCS,nPbW,nPbH, partIdx,
1649
4.76M
                                          merge_idx, mergeCandList);
1650
1651
1652
4.76M
  *out_vi = mergeCandList[merge_idx];
1653
1654
  // 8.5.3.1.1 / 9.
1655
1656
4.76M
  if (out_vi->predFlag[0] && out_vi->predFlag[1] && nPbW+nPbH==12) {
1657
271k
    out_vi->refIdx[1] = 0;
1658
271k
    out_vi->predFlag[1] = 0;
1659
271k
  }
1660
4.76M
}
1661
1662
1663
// 8.5.3.1.6
1664
void derive_spatial_luma_vector_prediction(base_context* ctx,
1665
                                           de265_image* img,
1666
                                           const slice_segment_header* shdr,
1667
                                           int xC,int yC,int nCS,int xP,int yP,
1668
                                           int nPbW,int nPbH, int X,
1669
                                           int refIdxLX, int partIdx,
1670
                                           uint8_t out_availableFlagLXN[2],
1671
                                           MotionVector out_mvLXN[2])
1672
2.49M
{
1673
2.49M
  if (refIdxLX >= MAX_NUM_REF_PICS) {
1674
0
    ctx->add_warning(DE265_WARNING_INCORRECT_MOTION_VECTOR_SCALING, false);
1675
0
    img->integrity = INTEGRITY_DECODING_ERRORS;
1676
1677
0
    out_availableFlagLXN[0] = false;
1678
0
    out_availableFlagLXN[1] = false;
1679
0
    out_mvLXN[0] = MotionVector();
1680
0
    out_mvLXN[1] = MotionVector();
1681
0
    return;
1682
0
  }
1683
1684
2.49M
  int isScaledFlagLX = 0;
1685
1686
2.49M
  const int A=0;
1687
2.49M
  const int B=1;
1688
1689
2.49M
  out_availableFlagLXN[A] = 0;
1690
2.49M
  out_availableFlagLXN[B] = 0;
1691
1692
1693
  // --- A ---
1694
1695
  // 1.
1696
1697
2.49M
  int xA[2], yA[2];
1698
2.49M
  xA[0] = xP-1;
1699
2.49M
  yA[0] = yP + nPbH;
1700
2.49M
  xA[1] = xA[0];
1701
2.49M
  yA[1] = yA[0]-1;
1702
1703
  // 2.
1704
1705
2.49M
  out_availableFlagLXN[A] = 0;
1706
2.49M
  out_mvLXN[A].x = 0;
1707
2.49M
  out_mvLXN[A].y = 0;
1708
1709
  // 3. / 4.
1710
1711
2.49M
  bool availableA[2];
1712
2.49M
  availableA[0] = img->available_pred_blk(xC,yC, nCS, xP,yP, nPbW,nPbH,partIdx, xA[0],yA[0]);
1713
2.49M
  availableA[1] = img->available_pred_blk(xC,yC, nCS, xP,yP, nPbW,nPbH,partIdx, xA[1],yA[1]);
1714
1715
  // 5.
1716
1717
2.49M
  if (availableA[0] || availableA[1]) {
1718
2.41M
    isScaledFlagLX = 1;
1719
2.41M
  }
1720
1721
  // 6.  test A0 and A1  (Ak)
1722
1723
2.49M
  int refIdxA=-1;
1724
1725
  // the POC we want to reference in this PB
1726
2.49M
  const de265_image* tmpimg = ctx->get_image(shdr->RefPicList[X][ refIdxLX ]);
1727
2.49M
  if (tmpimg==nullptr) { return; }
1728
2.49M
  const int referenced_POC = tmpimg->PicOrderCntVal;
1729
1730
7.47M
  for (int k=0;k<=1;k++) {
1731
1732
4.98M
    if (availableA[k] &&
1733
3.11M
        out_availableFlagLXN[A]==0 && // no A?-predictor so far
1734
2.45M
        img->get_pred_mode(xA[k],yA[k]) != MODE_INTRA) {
1735
1736
2.45M
      int Y=1-X;
1737
1738
2.45M
      const PBMotion& vi = img->get_mv_info(xA[k],yA[k]);
1739
2.45M
      logtrace(LogMotion,"MVP A%d=\n",k);
1740
2.45M
      logmvcand(vi);
1741
1742
2.45M
      const de265_image* imgX = nullptr;
1743
2.45M
      if (vi.predFlag[X]) {
1744
2.32M
        imgX = ctx->get_image(shdr->RefPicList[X][ vi.refIdx[X] ]);
1745
2.32M
      }
1746
1747
2.45M
      const de265_image* imgY = nullptr;
1748
2.45M
      if (vi.predFlag[Y]) {
1749
1.00M
        imgY = ctx->get_image(shdr->RefPicList[Y][ vi.refIdx[Y] ]);
1750
1.00M
      }
1751
1752
      // check whether the predictor X is available and references the same POC
1753
2.45M
      if (vi.predFlag[X] && imgX && imgX->PicOrderCntVal == referenced_POC) {
1754
1755
2.20M
        logtrace(LogMotion,"take A%d/L%d as A candidate with same POC\n",k,X);
1756
1757
2.20M
        out_availableFlagLXN[A]=1;
1758
2.20M
        out_mvLXN[A] = vi.mv[X];
1759
2.20M
        refIdxA = vi.refIdx[X];
1760
2.20M
      }
1761
      // check whether the other predictor (Y) is available and references the same POC
1762
248k
      else if (vi.predFlag[Y] && imgY && imgY->PicOrderCntVal == referenced_POC) {
1763
1764
100k
        logtrace(LogMotion,"take A%d/L%d as A candidate with same POC\n",k,Y);
1765
1766
100k
        out_availableFlagLXN[A]=1;
1767
100k
        out_mvLXN[A] = vi.mv[Y];
1768
100k
        refIdxA = vi.refIdx[Y];
1769
100k
      }
1770
2.45M
    }
1771
4.98M
  }
1772
1773
  // 7. If there is no predictor referencing the same POC, we take any other reference as
1774
  //    long as it is the same type of reference (long-term / short-term)
1775
1776
2.86M
  for (int k=0 ; k<=1 && out_availableFlagLXN[A]==0 ; k++) {
1777
366k
    int refPicList=-1;
1778
1779
366k
    if (availableA[k] &&
1780
        // TODO: we could remove this call by storing the result of the similar computation above
1781
130k
        img->get_pred_mode(xA[k],yA[k]) != MODE_INTRA) {
1782
1783
130k
      int Y=1-X;
1784
1785
130k
      const PBMotion& vi = img->get_mv_info(xA[k],yA[k]);
1786
130k
      if (vi.predFlag[X]==1 &&
1787
93.3k
          shdr->LongTermRefPic[X][refIdxLX] == shdr->LongTermRefPic[X][ vi.refIdx[X] ]) {
1788
1789
25.2k
        logtrace(LogMotion,"take A%D/L%d as A candidate with different POCs\n",k,X);
1790
1791
25.2k
        out_availableFlagLXN[A]=1;
1792
25.2k
        out_mvLXN[A] = vi.mv[X];
1793
25.2k
        refIdxA = vi.refIdx[X];
1794
25.2k
        refPicList = X;
1795
25.2k
      }
1796
104k
      else if (vi.predFlag[Y]==1 &&
1797
63.2k
               shdr->LongTermRefPic[X][refIdxLX] == shdr->LongTermRefPic[Y][ vi.refIdx[Y] ]) {
1798
1799
25.1k
        logtrace(LogMotion,"take A%d/L%d as A candidate with different POCs\n",k,Y);
1800
1801
25.1k
        out_availableFlagLXN[A]=1;
1802
25.1k
        out_mvLXN[A] = vi.mv[Y];
1803
25.1k
        refIdxA = vi.refIdx[Y];
1804
25.1k
        refPicList = Y;
1805
25.1k
      }
1806
130k
    }
1807
1808
366k
    if (out_availableFlagLXN[A]==1) {
1809
50.3k
      if (refIdxA<0) {
1810
0
        out_availableFlagLXN[0] = out_availableFlagLXN[1] = false;
1811
0
        return; // error
1812
0
      }
1813
1814
50.3k
      assert(refIdxA>=0);
1815
50.3k
      assert(refPicList>=0);
1816
1817
50.3k
      const de265_image* refPicA = ctx->get_image(shdr->RefPicList[refPicList][refIdxA ]);
1818
1819
#ifdef DE265_LOG_TRACE
1820
      const de265_image* refPicX = ctx->get_image(shdr->RefPicList[X][refIdxLX]);
1821
#endif
1822
1823
      //int picStateA = shdr->RefPicList_PicState[refPicList][refIdxA ];
1824
      //int picStateX = shdr->RefPicList_PicState[X         ][refIdxLX];
1825
1826
50.3k
      int isLongTermA = shdr->LongTermRefPic[refPicList][refIdxA ];
1827
50.3k
      int isLongTermX = shdr->LongTermRefPic[X         ][refIdxLX];
1828
1829
50.3k
      logtrace(LogMotion,"scale MVP A: A-POC:%d X-POC:%d\n",
1830
50.3k
               refPicA->PicOrderCntVal,refPicX->PicOrderCntVal);
1831
1832
50.3k
      if (!isLongTermA && !isLongTermX)
1833
      /*
1834
      if (picStateA == UsedForShortTermReference &&
1835
          picStateX == UsedForShortTermReference)
1836
      */
1837
29.3k
        {
1838
29.3k
          int distA = img->PicOrderCntVal - refPicA->PicOrderCntVal;
1839
29.3k
          int distX = img->PicOrderCntVal - referenced_POC;
1840
1841
29.3k
          if (!scale_mv(&out_mvLXN[A], out_mvLXN[A], distA, distX)) {
1842
0
            ctx->add_warning(DE265_WARNING_INCORRECT_MOTION_VECTOR_SCALING, false);
1843
0
            img->integrity = INTEGRITY_DECODING_ERRORS;
1844
0
          }
1845
29.3k
        }
1846
50.3k
    }
1847
366k
  }
1848
1849
  // --- B ---
1850
1851
  // 1.
1852
1853
2.49M
  int xB[3], yB[3];
1854
2.49M
  xB[0] = xP+nPbW;
1855
2.49M
  yB[0] = yP-1;
1856
2.49M
  xB[1] = xB[0]-1;
1857
2.49M
  yB[1] = yP-1;
1858
2.49M
  xB[2] = xP-1;
1859
2.49M
  yB[2] = yP-1;
1860
1861
  // 2.
1862
1863
2.49M
  out_availableFlagLXN[B] = 0;
1864
2.49M
  out_mvLXN[B].x = 0;
1865
2.49M
  out_mvLXN[B].y = 0;
1866
1867
  // 3. test B0,B1,B2 (Bk)
1868
1869
2.49M
  int refIdxB=-1;
1870
1871
2.49M
  bool availableB[3];
1872
9.97M
  for (int k=0;k<3;k++) {
1873
7.47M
    availableB[k] = img->available_pred_blk(xC,yC, nCS, xP,yP, nPbW,nPbH,partIdx, xB[k],yB[k]);
1874
1875
7.47M
    if (availableB[k] && out_availableFlagLXN[B]==0) {
1876
1877
2.08M
      int Y=1-X;
1878
1879
2.08M
      const PBMotion& vi = img->get_mv_info(xB[k],yB[k]);
1880
2.08M
      logtrace(LogMotion,"MVP B%d=\n",k);
1881
2.08M
      logmvcand(vi);
1882
1883
2.08M
      const de265_image* imgX = nullptr;
1884
2.08M
      if (vi.predFlag[X]) {
1885
1.93M
        imgX = ctx->get_image(shdr->RefPicList[X][ vi.refIdx[X] ]);
1886
1.93M
      }
1887
1888
2.08M
      const de265_image* imgY = nullptr;
1889
2.08M
      if (vi.predFlag[Y]) {
1890
832k
        imgY = ctx->get_image(shdr->RefPicList[Y][ vi.refIdx[Y] ]);
1891
832k
      }
1892
1893
2.08M
      if (vi.predFlag[X] && imgX && imgX->PicOrderCntVal == referenced_POC) {
1894
1.74M
        logtrace(LogMotion,"a) take B%d/L%d as B candidate with same POC\n",k,X);
1895
1896
1.74M
        out_availableFlagLXN[B]=1;
1897
1.74M
        out_mvLXN[B] = vi.mv[X];
1898
1.74M
        refIdxB = vi.refIdx[X];
1899
1.74M
      }
1900
335k
      else if (vi.predFlag[Y] && imgY && imgY->PicOrderCntVal == referenced_POC) {
1901
94.8k
        logtrace(LogMotion,"b) take B%d/L%d as B candidate with same POC\n",k,Y);
1902
1903
94.8k
        out_availableFlagLXN[B]=1;
1904
94.8k
        out_mvLXN[B] = vi.mv[Y];
1905
94.8k
        refIdxB = vi.refIdx[Y];
1906
94.8k
      }
1907
2.08M
    }
1908
7.47M
  }
1909
1910
  // 4.
1911
1912
2.49M
  if (isScaledFlagLX==0 &&      // no A predictor,
1913
75.2k
      out_availableFlagLXN[B])  // but an unscaled B predictor
1914
49.4k
    {
1915
      // use unscaled B predictor as A predictor
1916
1917
49.4k
      logtrace(LogMotion,"copy the same-POC B candidate as additional A candidate\n");
1918
1919
49.4k
      out_availableFlagLXN[A]=1;
1920
49.4k
      out_mvLXN[A] = out_mvLXN[B];
1921
49.4k
      refIdxA = refIdxB;
1922
49.4k
    }
1923
1924
  // 5.
1925
1926
  // If no A predictor, we output the unscaled B as the A predictor (above)
1927
  // and also add a scaled B predictor here.
1928
  // If there is (probably) an A predictor, no differing-POC B predictor is generated.
1929
2.49M
  if (isScaledFlagLX==0) {
1930
75.2k
    out_availableFlagLXN[B]=0;
1931
1932
219k
    for (int k=0 ; k<=2 && out_availableFlagLXN[B]==0 ; k++) {
1933
144k
      int refPicList=-1;
1934
1935
144k
      if (availableB[k]) {
1936
60.7k
        int Y=1-X;
1937
1938
60.7k
        const PBMotion& vi = img->get_mv_info(xB[k],yB[k]);
1939
1940
60.7k
        if (vi.predFlag[X]==1 &&
1941
52.4k
            shdr->LongTermRefPic[X][refIdxLX] == shdr->LongTermRefPic[X][ vi.refIdx[X] ]) {
1942
44.4k
          out_availableFlagLXN[B]=1;
1943
44.4k
          out_mvLXN[B] = vi.mv[X];
1944
44.4k
          refIdxB = vi.refIdx[X];
1945
44.4k
          refPicList = X;
1946
44.4k
        }
1947
16.2k
        else if (vi.predFlag[Y]==1 &&
1948
11.6k
                 shdr->LongTermRefPic[X][refIdxLX] == shdr->LongTermRefPic[Y][ vi.refIdx[Y] ]) {
1949
7.51k
          out_availableFlagLXN[B]=1;
1950
7.51k
          out_mvLXN[B] = vi.mv[Y];
1951
7.51k
          refIdxB = vi.refIdx[Y];
1952
7.51k
          refPicList = Y;
1953
7.51k
        }
1954
60.7k
      }
1955
1956
144k
      if (out_availableFlagLXN[B]==1) {
1957
52.0k
        if (refIdxB<0) {
1958
0
          out_availableFlagLXN[0] = out_availableFlagLXN[1] = false;
1959
0
          return; // error
1960
0
        }
1961
1962
52.0k
        assert(refPicList>=0);
1963
52.0k
        assert(refIdxB>=0);
1964
1965
52.0k
        const de265_image* refPicB=ctx->get_image(shdr->RefPicList[refPicList][refIdxB ]);
1966
52.0k
        const de265_image* refPicX=ctx->get_image(shdr->RefPicList[X         ][refIdxLX]);
1967
1968
52.0k
        int isLongTermB = shdr->LongTermRefPic[refPicList][refIdxB ];
1969
52.0k
        int isLongTermX = shdr->LongTermRefPic[X         ][refIdxLX];
1970
1971
52.0k
        if (refPicB==nullptr || refPicX==nullptr) {
1972
0
          img->decctx->add_warning(DE265_WARNING_NONEXISTING_REFERENCE_PICTURE_ACCESSED,false);
1973
0
          img->integrity = INTEGRITY_DECODING_ERRORS;
1974
0
        }
1975
52.0k
        else if (refPicB->PicOrderCntVal != refPicX->PicOrderCntVal &&
1976
3.86k
                 !isLongTermB && !isLongTermX) {
1977
2.09k
          int distB = img->PicOrderCntVal - refPicB->PicOrderCntVal;
1978
2.09k
          int distX = img->PicOrderCntVal - referenced_POC;
1979
1980
2.09k
          logtrace(LogMotion,"scale MVP B: B-POC:%d X-POC:%d\n",refPicB->PicOrderCntVal,refPicX->PicOrderCntVal);
1981
1982
2.09k
          if (!scale_mv(&out_mvLXN[B], out_mvLXN[B], distB, distX)) {
1983
0
            ctx->add_warning(DE265_WARNING_INCORRECT_MOTION_VECTOR_SCALING, false);
1984
0
            img->integrity = INTEGRITY_DECODING_ERRORS;
1985
0
          }
1986
2.09k
        }
1987
52.0k
      }
1988
144k
    }
1989
75.2k
  }
1990
2.49M
}
1991
1992
1993
// 8.5.3.1.5
1994
void fill_luma_motion_vector_predictors(base_context* ctx,
1995
                                        const slice_segment_header* shdr,
1996
                                        de265_image* img,
1997
                                        int xC,int yC,int nCS,int xP,int yP,
1998
                                        int nPbW,int nPbH, int l,
1999
                                        int refIdx, int partIdx,
2000
                                        MotionVector out_mvpList[2])
2001
2.49M
{
2002
  // 8.5.3.1.6: derive two spatial vector predictors A (0) and B (1)
2003
2004
2.49M
  uint8_t availableFlagLXN[2];
2005
2.49M
  MotionVector mvLXN[2];
2006
2007
2.49M
  derive_spatial_luma_vector_prediction(ctx, img, shdr, xC,yC, nCS, xP,yP,
2008
2.49M
                                        nPbW,nPbH, l, refIdx, partIdx,
2009
2.49M
                                        availableFlagLXN, mvLXN);
2010
2011
  // 8.5.3.1.7: if we only have one spatial vector or both spatial vectors are the same,
2012
  // derive a temporal predictor
2013
2014
2.49M
  uint8_t availableFlagLXCol;
2015
2.49M
  MotionVector mvLXCol;
2016
2017
2018
2.49M
  if (availableFlagLXN[0] &&
2019
2.40M
      availableFlagLXN[1] &&
2020
1.81M
      (mvLXN[0].x != mvLXN[1].x || mvLXN[0].y != mvLXN[1].y)) {
2021
1.15M
    availableFlagLXCol = 0;
2022
1.15M
  }
2023
1.33M
  else {
2024
1.33M
    derive_temporal_luma_vector_prediction(ctx, img, shdr,
2025
1.33M
                                           xP,yP, nPbW,nPbH, refIdx,l,
2026
1.33M
                                           &mvLXCol, &availableFlagLXCol);
2027
1.33M
  }
2028
2029
2030
  // --- build candidate vector list with exactly two entries ---
2031
2032
2.49M
  int numMVPCandLX=0;
2033
2034
  // spatial predictor A
2035
2036
2.49M
  if (availableFlagLXN[0])
2037
2.40M
    {
2038
2.40M
      out_mvpList[numMVPCandLX++] = mvLXN[0];
2039
2.40M
    }
2040
2041
  // spatial predictor B (if not same as A)
2042
2043
2.49M
  if (availableFlagLXN[1] &&
2044
1.84M
      (!availableFlagLXN[0] || // in case A in not available, but mvLXA initialized to same as mvLXB
2045
1.81M
       (mvLXN[0].x != mvLXN[1].x || mvLXN[0].y != mvLXN[1].y)))
2046
1.18M
    {
2047
1.18M
      out_mvpList[numMVPCandLX++] = mvLXN[1];
2048
1.18M
    }
2049
2050
  // temporal predictor
2051
2052
2.49M
  if (availableFlagLXCol)
2053
54.9k
    {
2054
54.9k
      out_mvpList[numMVPCandLX++] = mvLXCol;
2055
54.9k
    }
2056
2057
  // fill with zero predictors
2058
2059
3.83M
  while (numMVPCandLX<2) {
2060
1.33M
    out_mvpList[numMVPCandLX].x = 0;
2061
1.33M
    out_mvpList[numMVPCandLX].y = 0;
2062
1.33M
    numMVPCandLX++;
2063
1.33M
  }
2064
2065
2066
2.49M
  assert(numMVPCandLX==2);
2067
2.49M
}
2068
2069
2070
MotionVector luma_motion_vector_prediction(base_context* ctx,
2071
                                           const slice_segment_header* shdr,
2072
                                           de265_image* img,
2073
                                           const PBMotionCoding& motion,
2074
                                           int xC,int yC,int nCS,int xP,int yP,
2075
                                           int nPbW,int nPbH, int l,
2076
                                           int refIdx, int partIdx)
2077
2.49M
{
2078
2.49M
  MotionVector mvpList[2];
2079
2080
2.49M
  fill_luma_motion_vector_predictors(ctx, shdr, img,
2081
2.49M
                                     xC,yC,nCS,xP,yP,
2082
2.49M
                                     nPbW, nPbH, l, refIdx, partIdx,
2083
2.49M
                                     mvpList);
2084
2085
  // select predictor according to mvp_lX_flag
2086
2087
2.49M
  return mvpList[ l ? motion.mvp_l1_flag : motion.mvp_l0_flag ];
2088
2.49M
}
2089
2090
2091
#if DE265_LOG_TRACE
2092
void logMV(int x0,int y0,int nPbW,int nPbH, const char* mode,const PBMotion* mv)
2093
{
2094
  int pred0 = mv->predFlag[0];
2095
  int pred1 = mv->predFlag[1];
2096
2097
  logtrace(LogMotion,
2098
           "*MV %d;%d [%d;%d] %s: (%d) %d;%d @%d   (%d) %d;%d @%d\n", x0,y0,nPbW,nPbH,mode,
2099
           pred0,
2100
           pred0 ? mv->mv[0].x : 0,pred0 ? mv->mv[0].y : 0, pred0 ? mv->refIdx[0] : 0,
2101
           pred1,
2102
           pred1 ? mv->mv[1].x : 0,pred1 ? mv->mv[1].y : 0, pred1 ? mv->refIdx[1] : 0);
2103
}
2104
#else
2105
#define logMV(x0,y0,nPbW,nPbH,mode,mv)
2106
#endif
2107
2108
2109
2110
// 8.5.3.1
2111
void motion_vectors_and_ref_indices(base_context* ctx,
2112
                                    const slice_segment_header* shdr,
2113
                                    de265_image* img,
2114
                                    const PBMotionCoding& motion,
2115
                                    int xC,int yC, int xB,int yB, int nCS, int nPbW,int nPbH,
2116
                                    int partIdx,
2117
                                    PBMotion* out_vi)
2118
6.81M
{
2119
  //slice_segment_header* shdr = tctx->shdr;
2120
2121
6.81M
  int xP = xC+xB;
2122
6.81M
  int yP = yC+yB;
2123
2124
6.81M
  enum PredMode predMode = img->get_pred_mode(xC,yC);
2125
2126
6.81M
  if (predMode == MODE_SKIP ||
2127
3.65M
      (predMode == MODE_INTER && motion.merge_flag))
2128
4.76M
    {
2129
4.76M
      derive_luma_motion_merge_mode(ctx,shdr,img,
2130
4.76M
                                    xC,yC, xP,yP, nCS,nPbW,nPbH, partIdx,
2131
4.76M
                                    motion.merge_idx, out_vi);
2132
2133
4.76M
      logMV(xP,yP,nPbW,nPbH, "merge_mode", out_vi);
2134
4.76M
    }
2135
2.04M
  else {
2136
2.04M
    int mvdL[2][2];
2137
2.04M
    MotionVector mvpL[2];
2138
2139
6.13M
    for (int l=0;l<2;l++) {
2140
      // 1.
2141
2142
4.08M
      enum InterPredIdc inter_pred_idc = (enum InterPredIdc)motion.inter_pred_idc;
2143
2144
4.08M
      if (inter_pred_idc == PRED_BI ||
2145
3.19M
          (inter_pred_idc == PRED_L0 && l==0) ||
2146
2.49M
          (inter_pred_idc == PRED_L1 && l==1)) {
2147
2.49M
        out_vi->refIdx[l] = motion.refIdx[l];
2148
2.49M
        out_vi->predFlag[l] = 1;
2149
2.49M
      }
2150
1.59M
      else {
2151
1.59M
        out_vi->refIdx[l] = 0;
2152
1.59M
        out_vi->predFlag[l] = 0;
2153
1.59M
      }
2154
2155
      // 2.
2156
2157
4.08M
      mvdL[l][0] = motion.mvd[l][0];
2158
4.08M
      mvdL[l][1] = motion.mvd[l][1];
2159
2160
2161
4.08M
      if (out_vi->predFlag[l]) {
2162
        // 3.
2163
2164
2.49M
        mvpL[l] = luma_motion_vector_prediction(ctx,shdr,img,motion,
2165
2.49M
                                                xC,yC,nCS,xP,yP, nPbW,nPbH, l,
2166
2.49M
                                                out_vi->refIdx[l], partIdx);
2167
2168
        // 4.
2169
2170
2.49M
        int32_t x = (mvpL[l].x + mvdL[l][0] + 0x10000) & 0xFFFF;
2171
2.49M
        int32_t y = (mvpL[l].y + mvdL[l][1] + 0x10000) & 0xFFFF;
2172
2173
2.49M
        out_vi->mv[l].x = (x>=0x8000) ? x-0x10000 : x;
2174
2.49M
        out_vi->mv[l].y = (y>=0x8000) ? y-0x10000 : y;
2175
2.49M
      }
2176
4.08M
    }
2177
2178
2.04M
    logMV(xP,yP,nPbW,nPbH, "mvp", out_vi);
2179
2.04M
  }
2180
6.81M
}
2181
2182
2183
// 8.5.3
2184
2185
/* xC/yC : CB position
2186
   xB/yB : position offset of the PB
2187
   nPbW/nPbH : size of PB
2188
   nCS   : CB size
2189
 */
2190
void decode_prediction_unit(base_context* ctx,
2191
                            const slice_segment_header* shdr,
2192
                            de265_image* img,
2193
                            const PBMotionCoding& motion,
2194
                            int xC,int yC, int xB,int yB, int nCS, int nPbW,int nPbH, int partIdx)
2195
6.81M
{
2196
6.81M
  logtrace(LogMotion,"decode_prediction_unit POC=%d %d;%d %dx%d\n",
2197
6.81M
           img->PicOrderCntVal, xC+xB,yC+yB, nPbW,nPbH);
2198
2199
  //slice_segment_header* shdr = tctx->shdr;
2200
2201
  // 1.
2202
2203
6.81M
  PBMotion vi;
2204
6.81M
  motion_vectors_and_ref_indices(ctx, shdr, img, motion,
2205
6.81M
                                 xC,yC, xB,yB, nCS, nPbW,nPbH, partIdx, &vi);
2206
2207
  // 2.
2208
2209
6.81M
  generate_inter_prediction_samples(ctx,shdr, img, xC,yC, xB,yB, nCS, nPbW,nPbH, &vi);
2210
2211
2212
6.81M
  img->set_mv_info(xC+xB,yC+yB,nPbW,nPbH, vi);
2213
6.81M
}