Coverage Report

Created: 2026-09-14 06:44

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
194M
#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
// Luma sample interpolation process (8.5.3.3.3.2).
49
// inter_t is the type of the intermediate prediction samples (see
50
// generate_inter_prediction_samples_plane below).
51
template <class pixel_t, class inter_t>
52
void mc_luma(const base_context* ctx,
53
             const seq_parameter_set* sps, int mv_x, int mv_y,
54
             int xP,int yP,
55
             inter_t* out, int out_stride,
56
             const pixel_t* ref, ptrdiff_t ref_stride,
57
             int nPbW, int nPbH, int bitDepth_L)
58
1.31M
{
59
1.31M
  int xFracL = mv_x & 3;
60
1.31M
  int yFracL = mv_y & 3;
61
62
1.31M
  int xIntOffsL = xP + (mv_x>>2);
63
1.31M
  int yIntOffsL = yP + (mv_y>>2);
64
65
  //const int shift1 = std::min(4, sps->BitDepth_Y-8);
66
  //const int shift2 = 6;
67
1.31M
  const int shift3 = std::max(2, 14 - sps->BitDepth_Y);
68
69
1.31M
  int w = sps->pic_width_in_luma_samples;
70
1.31M
  int h = sps->pic_height_in_luma_samples;
71
72
1.31M
  ALIGNED_16(inter_t) mcbuffer[MAX_CU_SIZE * (MAX_CU_SIZE+7)];
73
74
1.31M
  if (xFracL==0 && yFracL==0) {
75
76
698k
    if (xIntOffsL >= 0 && yIntOffsL >= 0 &&
77
690k
        nPbW+xIntOffsL <= w && nPbH+yIntOffsL <= h) {
78
79
666k
      ctx->acceleration.put_hevc_qpel(out, out_stride,
80
666k
                                      &ref[yIntOffsL*ref_stride + xIntOffsL],
81
666k
                                      ref_stride /* sizeof(pixel_t)*/,
82
666k
                                      nPbW,nPbH, mcbuffer, 0,0, bitDepth_L);
83
666k
    }
84
31.5k
    else {
85
350k
      for (int y=0;y<nPbH;y++)
86
4.83M
        for (int x=0;x<nPbW;x++) {
87
88
4.51M
          int xA = Clip3(0,w-1,x + xIntOffsL);
89
4.51M
          int yA = Clip3(0,h-1,y + yIntOffsL);
90
91
4.51M
          out[y*out_stride+x] = ref[ xA + yA*ref_stride ] << shift3;
92
4.51M
        }
93
31.5k
    }
94
95
#ifdef DE265_LOG_TRACE
96
    logtrace(LogMotion,"---MC luma %d %d = direct---\n",xFracL,yFracL);
97
98
    for (int y=0;y<nPbH;y++) {
99
      for (int x=0;x<nPbW;x++) {
100
101
        int xA = Clip3(0,w-1,x + xIntOffsL);
102
        int yA = Clip3(0,h-1,y + yIntOffsL);
103
104
        logtrace(LogMotion,"%02x ", ref[ xA + yA*ref_stride ]);
105
      }
106
      logtrace(LogMotion,"\n");
107
    }
108
109
    logtrace(LogMotion," -> \n");
110
111
    for (int y=0;y<nPbH;y++) {
112
      for (int x=0;x<nPbW;x++) {
113
114
        logtrace(LogMotion,"%02x ",out[y*out_stride+x] >> 6); // 6 will be used when summing predictions
115
      }
116
      logtrace(LogMotion,"\n");
117
    }
118
#endif
119
698k
  }
120
619k
  else {
121
619k
    int extra_left   = extra_before[xFracL];
122
619k
    int extra_right  = extra_after [xFracL];
123
619k
    int extra_top    = extra_before[yFracL];
124
619k
    int extra_bottom = extra_after [yFracL];
125
126
    //int nPbW_extra = extra_left + nPbW + extra_right;
127
    //int nPbH_extra = extra_top  + nPbH + extra_bottom;
128
129
130
619k
    pixel_t padbuf[(MAX_CU_SIZE+16)*(MAX_CU_SIZE+7)];
131
132
619k
    const pixel_t* src_ptr;
133
619k
    ptrdiff_t src_stride;
134
135
619k
    if (-extra_left + xIntOffsL >= 0 &&
136
600k
        -extra_top  + yIntOffsL >= 0 &&
137
546k
        nPbW+extra_right  + xIntOffsL < w &&
138
523k
        nPbH+extra_bottom + yIntOffsL < h) {
139
401k
      src_ptr = &ref[xIntOffsL + yIntOffsL*ref_stride];
140
401k
      src_stride = ref_stride;
141
401k
    }
142
218k
    else {
143
      // Extend fill width to a multiple of 16 so that SIMD over-reads
144
      // in qpel interpolation hit valid (edge-clamped) data.
145
218k
      int fill_width = ((extra_left + nPbW + extra_right + 15) & ~15);
146
218k
      if (fill_width > MAX_CU_SIZE+16) fill_width = MAX_CU_SIZE+16;
147
148
3.96M
      for (int y=-extra_top;y<nPbH+extra_bottom;y++) {
149
104M
        for (int x=-extra_left;x<fill_width - extra_left;x++) {
150
151
100M
          int xA = Clip3(0,w-1,x + xIntOffsL);
152
100M
          int yA = Clip3(0,h-1,y + yIntOffsL);
153
154
100M
          padbuf[x+extra_left + (y+extra_top)*(MAX_CU_SIZE+16)] = ref[ xA + yA*ref_stride ];
155
100M
        }
156
3.74M
      }
157
158
218k
      src_ptr = &padbuf[extra_top*(MAX_CU_SIZE+16) + extra_left];
159
218k
      src_stride = MAX_CU_SIZE+16;
160
218k
    }
161
162
619k
    ctx->acceleration.put_hevc_qpel(out, out_stride,
163
619k
                                    src_ptr, src_stride /* sizeof(pixel_t) */,
164
619k
                                    nPbW,nPbH, mcbuffer, xFracL,yFracL, bitDepth_L);
165
166
167
619k
    logtrace(LogMotion,"---V---\n");
168
6.71M
    for (int y=0;y<nPbH;y++) {
169
94.0M
      for (int x=0;x<nPbW;x++) {
170
88.0M
        logtrace(LogMotion,"%04x ",out[x+y*out_stride]);
171
88.0M
      }
172
6.09M
      logtrace(LogMotion,"\n");
173
6.09M
    }
174
619k
  }
175
1.31M
}
void mc_luma<unsigned short, short>(base_context const*, seq_parameter_set const*, int, int, int, int, short*, int, unsigned short const*, long, int, int, int)
Line
Count
Source
58
161k
{
59
161k
  int xFracL = mv_x & 3;
60
161k
  int yFracL = mv_y & 3;
61
62
161k
  int xIntOffsL = xP + (mv_x>>2);
63
161k
  int yIntOffsL = yP + (mv_y>>2);
64
65
  //const int shift1 = std::min(4, sps->BitDepth_Y-8);
66
  //const int shift2 = 6;
67
161k
  const int shift3 = std::max(2, 14 - sps->BitDepth_Y);
68
69
161k
  int w = sps->pic_width_in_luma_samples;
70
161k
  int h = sps->pic_height_in_luma_samples;
71
72
161k
  ALIGNED_16(inter_t) mcbuffer[MAX_CU_SIZE * (MAX_CU_SIZE+7)];
73
74
161k
  if (xFracL==0 && yFracL==0) {
75
76
78.3k
    if (xIntOffsL >= 0 && yIntOffsL >= 0 &&
77
77.1k
        nPbW+xIntOffsL <= w && nPbH+yIntOffsL <= h) {
78
79
71.5k
      ctx->acceleration.put_hevc_qpel(out, out_stride,
80
71.5k
                                      &ref[yIntOffsL*ref_stride + xIntOffsL],
81
71.5k
                                      ref_stride /* sizeof(pixel_t)*/,
82
71.5k
                                      nPbW,nPbH, mcbuffer, 0,0, bitDepth_L);
83
71.5k
    }
84
6.86k
    else {
85
66.0k
      for (int y=0;y<nPbH;y++)
86
787k
        for (int x=0;x<nPbW;x++) {
87
88
728k
          int xA = Clip3(0,w-1,x + xIntOffsL);
89
728k
          int yA = Clip3(0,h-1,y + yIntOffsL);
90
91
728k
          out[y*out_stride+x] = ref[ xA + yA*ref_stride ] << shift3;
92
728k
        }
93
6.86k
    }
94
95
#ifdef DE265_LOG_TRACE
96
    logtrace(LogMotion,"---MC luma %d %d = direct---\n",xFracL,yFracL);
97
98
    for (int y=0;y<nPbH;y++) {
99
      for (int x=0;x<nPbW;x++) {
100
101
        int xA = Clip3(0,w-1,x + xIntOffsL);
102
        int yA = Clip3(0,h-1,y + yIntOffsL);
103
104
        logtrace(LogMotion,"%02x ", ref[ xA + yA*ref_stride ]);
105
      }
106
      logtrace(LogMotion,"\n");
107
    }
108
109
    logtrace(LogMotion," -> \n");
110
111
    for (int y=0;y<nPbH;y++) {
112
      for (int x=0;x<nPbW;x++) {
113
114
        logtrace(LogMotion,"%02x ",out[y*out_stride+x] >> 6); // 6 will be used when summing predictions
115
      }
116
      logtrace(LogMotion,"\n");
117
    }
118
#endif
119
78.3k
  }
120
83.3k
  else {
121
83.3k
    int extra_left   = extra_before[xFracL];
122
83.3k
    int extra_right  = extra_after [xFracL];
123
83.3k
    int extra_top    = extra_before[yFracL];
124
83.3k
    int extra_bottom = extra_after [yFracL];
125
126
    //int nPbW_extra = extra_left + nPbW + extra_right;
127
    //int nPbH_extra = extra_top  + nPbH + extra_bottom;
128
129
130
83.3k
    pixel_t padbuf[(MAX_CU_SIZE+16)*(MAX_CU_SIZE+7)];
131
132
83.3k
    const pixel_t* src_ptr;
133
83.3k
    ptrdiff_t src_stride;
134
135
83.3k
    if (-extra_left + xIntOffsL >= 0 &&
136
80.3k
        -extra_top  + yIntOffsL >= 0 &&
137
74.9k
        nPbW+extra_right  + xIntOffsL < w &&
138
68.7k
        nPbH+extra_bottom + yIntOffsL < h) {
139
50.4k
      src_ptr = &ref[xIntOffsL + yIntOffsL*ref_stride];
140
50.4k
      src_stride = ref_stride;
141
50.4k
    }
142
32.8k
    else {
143
      // Extend fill width to a multiple of 16 so that SIMD over-reads
144
      // in qpel interpolation hit valid (edge-clamped) data.
145
32.8k
      int fill_width = ((extra_left + nPbW + extra_right + 15) & ~15);
146
32.8k
      if (fill_width > MAX_CU_SIZE+16) fill_width = MAX_CU_SIZE+16;
147
148
534k
      for (int y=-extra_top;y<nPbH+extra_bottom;y++) {
149
12.1M
        for (int x=-extra_left;x<fill_width - extra_left;x++) {
150
151
11.6M
          int xA = Clip3(0,w-1,x + xIntOffsL);
152
11.6M
          int yA = Clip3(0,h-1,y + yIntOffsL);
153
154
11.6M
          padbuf[x+extra_left + (y+extra_top)*(MAX_CU_SIZE+16)] = ref[ xA + yA*ref_stride ];
155
11.6M
        }
156
501k
      }
157
158
32.8k
      src_ptr = &padbuf[extra_top*(MAX_CU_SIZE+16) + extra_left];
159
32.8k
      src_stride = MAX_CU_SIZE+16;
160
32.8k
    }
161
162
83.3k
    ctx->acceleration.put_hevc_qpel(out, out_stride,
163
83.3k
                                    src_ptr, src_stride /* sizeof(pixel_t) */,
164
83.3k
                                    nPbW,nPbH, mcbuffer, xFracL,yFracL, bitDepth_L);
165
166
167
83.3k
    logtrace(LogMotion,"---V---\n");
168
852k
    for (int y=0;y<nPbH;y++) {
169
11.7M
      for (int x=0;x<nPbW;x++) {
170
11.0M
        logtrace(LogMotion,"%04x ",out[x+y*out_stride]);
171
11.0M
      }
172
769k
      logtrace(LogMotion,"\n");
173
769k
    }
174
83.3k
  }
175
161k
}
void mc_luma<unsigned char, short>(base_context const*, seq_parameter_set const*, int, int, int, int, short*, int, unsigned char const*, long, int, int, int)
Line
Count
Source
58
785k
{
59
785k
  int xFracL = mv_x & 3;
60
785k
  int yFracL = mv_y & 3;
61
62
785k
  int xIntOffsL = xP + (mv_x>>2);
63
785k
  int yIntOffsL = yP + (mv_y>>2);
64
65
  //const int shift1 = std::min(4, sps->BitDepth_Y-8);
66
  //const int shift2 = 6;
67
785k
  const int shift3 = std::max(2, 14 - sps->BitDepth_Y);
68
69
785k
  int w = sps->pic_width_in_luma_samples;
70
785k
  int h = sps->pic_height_in_luma_samples;
71
72
785k
  ALIGNED_16(inter_t) mcbuffer[MAX_CU_SIZE * (MAX_CU_SIZE+7)];
73
74
785k
  if (xFracL==0 && yFracL==0) {
75
76
393k
    if (xIntOffsL >= 0 && yIntOffsL >= 0 &&
77
388k
        nPbW+xIntOffsL <= w && nPbH+yIntOffsL <= h) {
78
79
377k
      ctx->acceleration.put_hevc_qpel(out, out_stride,
80
377k
                                      &ref[yIntOffsL*ref_stride + xIntOffsL],
81
377k
                                      ref_stride /* sizeof(pixel_t)*/,
82
377k
                                      nPbW,nPbH, mcbuffer, 0,0, bitDepth_L);
83
377k
    }
84
16.2k
    else {
85
203k
      for (int y=0;y<nPbH;y++)
86
3.24M
        for (int x=0;x<nPbW;x++) {
87
88
3.05M
          int xA = Clip3(0,w-1,x + xIntOffsL);
89
3.05M
          int yA = Clip3(0,h-1,y + yIntOffsL);
90
91
3.05M
          out[y*out_stride+x] = ref[ xA + yA*ref_stride ] << shift3;
92
3.05M
        }
93
16.2k
    }
94
95
#ifdef DE265_LOG_TRACE
96
    logtrace(LogMotion,"---MC luma %d %d = direct---\n",xFracL,yFracL);
97
98
    for (int y=0;y<nPbH;y++) {
99
      for (int x=0;x<nPbW;x++) {
100
101
        int xA = Clip3(0,w-1,x + xIntOffsL);
102
        int yA = Clip3(0,h-1,y + yIntOffsL);
103
104
        logtrace(LogMotion,"%02x ", ref[ xA + yA*ref_stride ]);
105
      }
106
      logtrace(LogMotion,"\n");
107
    }
108
109
    logtrace(LogMotion," -> \n");
110
111
    for (int y=0;y<nPbH;y++) {
112
      for (int x=0;x<nPbW;x++) {
113
114
        logtrace(LogMotion,"%02x ",out[y*out_stride+x] >> 6); // 6 will be used when summing predictions
115
      }
116
      logtrace(LogMotion,"\n");
117
    }
118
#endif
119
393k
  }
120
391k
  else {
121
391k
    int extra_left   = extra_before[xFracL];
122
391k
    int extra_right  = extra_after [xFracL];
123
391k
    int extra_top    = extra_before[yFracL];
124
391k
    int extra_bottom = extra_after [yFracL];
125
126
    //int nPbW_extra = extra_left + nPbW + extra_right;
127
    //int nPbH_extra = extra_top  + nPbH + extra_bottom;
128
129
130
391k
    pixel_t padbuf[(MAX_CU_SIZE+16)*(MAX_CU_SIZE+7)];
131
132
391k
    const pixel_t* src_ptr;
133
391k
    ptrdiff_t src_stride;
134
135
391k
    if (-extra_left + xIntOffsL >= 0 &&
136
376k
        -extra_top  + yIntOffsL >= 0 &&
137
339k
        nPbW+extra_right  + xIntOffsL < w &&
138
327k
        nPbH+extra_bottom + yIntOffsL < h) {
139
252k
      src_ptr = &ref[xIntOffsL + yIntOffsL*ref_stride];
140
252k
      src_stride = ref_stride;
141
252k
    }
142
139k
    else {
143
      // Extend fill width to a multiple of 16 so that SIMD over-reads
144
      // in qpel interpolation hit valid (edge-clamped) data.
145
139k
      int fill_width = ((extra_left + nPbW + extra_right + 15) & ~15);
146
139k
      if (fill_width > MAX_CU_SIZE+16) fill_width = MAX_CU_SIZE+16;
147
148
2.62M
      for (int y=-extra_top;y<nPbH+extra_bottom;y++) {
149
71.0M
        for (int x=-extra_left;x<fill_width - extra_left;x++) {
150
151
68.5M
          int xA = Clip3(0,w-1,x + xIntOffsL);
152
68.5M
          int yA = Clip3(0,h-1,y + yIntOffsL);
153
154
68.5M
          padbuf[x+extra_left + (y+extra_top)*(MAX_CU_SIZE+16)] = ref[ xA + yA*ref_stride ];
155
68.5M
        }
156
2.48M
      }
157
158
139k
      src_ptr = &padbuf[extra_top*(MAX_CU_SIZE+16) + extra_left];
159
139k
      src_stride = MAX_CU_SIZE+16;
160
139k
    }
161
162
391k
    ctx->acceleration.put_hevc_qpel(out, out_stride,
163
391k
                                    src_ptr, src_stride /* sizeof(pixel_t) */,
164
391k
                                    nPbW,nPbH, mcbuffer, xFracL,yFracL, bitDepth_L);
165
166
167
391k
    logtrace(LogMotion,"---V---\n");
168
4.34M
    for (int y=0;y<nPbH;y++) {
169
59.0M
      for (int x=0;x<nPbW;x++) {
170
55.0M
        logtrace(LogMotion,"%04x ",out[x+y*out_stride]);
171
55.0M
      }
172
3.95M
      logtrace(LogMotion,"\n");
173
3.95M
    }
174
391k
  }
175
785k
}
void mc_luma<unsigned short, int>(base_context const*, seq_parameter_set const*, int, int, int, int, int*, int, unsigned short const*, long, int, int, int)
Line
Count
Source
58
370k
{
59
370k
  int xFracL = mv_x & 3;
60
370k
  int yFracL = mv_y & 3;
61
62
370k
  int xIntOffsL = xP + (mv_x>>2);
63
370k
  int yIntOffsL = yP + (mv_y>>2);
64
65
  //const int shift1 = std::min(4, sps->BitDepth_Y-8);
66
  //const int shift2 = 6;
67
370k
  const int shift3 = std::max(2, 14 - sps->BitDepth_Y);
68
69
370k
  int w = sps->pic_width_in_luma_samples;
70
370k
  int h = sps->pic_height_in_luma_samples;
71
72
370k
  ALIGNED_16(inter_t) mcbuffer[MAX_CU_SIZE * (MAX_CU_SIZE+7)];
73
74
370k
  if (xFracL==0 && yFracL==0) {
75
76
226k
    if (xIntOffsL >= 0 && yIntOffsL >= 0 &&
77
225k
        nPbW+xIntOffsL <= w && nPbH+yIntOffsL <= h) {
78
79
217k
      ctx->acceleration.put_hevc_qpel(out, out_stride,
80
217k
                                      &ref[yIntOffsL*ref_stride + xIntOffsL],
81
217k
                                      ref_stride /* sizeof(pixel_t)*/,
82
217k
                                      nPbW,nPbH, mcbuffer, 0,0, bitDepth_L);
83
217k
    }
84
8.36k
    else {
85
80.4k
      for (int y=0;y<nPbH;y++)
86
801k
        for (int x=0;x<nPbW;x++) {
87
88
729k
          int xA = Clip3(0,w-1,x + xIntOffsL);
89
729k
          int yA = Clip3(0,h-1,y + yIntOffsL);
90
91
729k
          out[y*out_stride+x] = ref[ xA + yA*ref_stride ] << shift3;
92
729k
        }
93
8.36k
    }
94
95
#ifdef DE265_LOG_TRACE
96
    logtrace(LogMotion,"---MC luma %d %d = direct---\n",xFracL,yFracL);
97
98
    for (int y=0;y<nPbH;y++) {
99
      for (int x=0;x<nPbW;x++) {
100
101
        int xA = Clip3(0,w-1,x + xIntOffsL);
102
        int yA = Clip3(0,h-1,y + yIntOffsL);
103
104
        logtrace(LogMotion,"%02x ", ref[ xA + yA*ref_stride ]);
105
      }
106
      logtrace(LogMotion,"\n");
107
    }
108
109
    logtrace(LogMotion," -> \n");
110
111
    for (int y=0;y<nPbH;y++) {
112
      for (int x=0;x<nPbW;x++) {
113
114
        logtrace(LogMotion,"%02x ",out[y*out_stride+x] >> 6); // 6 will be used when summing predictions
115
      }
116
      logtrace(LogMotion,"\n");
117
    }
118
#endif
119
226k
  }
120
144k
  else {
121
144k
    int extra_left   = extra_before[xFracL];
122
144k
    int extra_right  = extra_after [xFracL];
123
144k
    int extra_top    = extra_before[yFracL];
124
144k
    int extra_bottom = extra_after [yFracL];
125
126
    //int nPbW_extra = extra_left + nPbW + extra_right;
127
    //int nPbH_extra = extra_top  + nPbH + extra_bottom;
128
129
130
144k
    pixel_t padbuf[(MAX_CU_SIZE+16)*(MAX_CU_SIZE+7)];
131
132
144k
    const pixel_t* src_ptr;
133
144k
    ptrdiff_t src_stride;
134
135
144k
    if (-extra_left + xIntOffsL >= 0 &&
136
143k
        -extra_top  + yIntOffsL >= 0 &&
137
131k
        nPbW+extra_right  + xIntOffsL < w &&
138
127k
        nPbH+extra_bottom + yIntOffsL < h) {
139
98.7k
      src_ptr = &ref[xIntOffsL + yIntOffsL*ref_stride];
140
98.7k
      src_stride = ref_stride;
141
98.7k
    }
142
45.4k
    else {
143
      // Extend fill width to a multiple of 16 so that SIMD over-reads
144
      // in qpel interpolation hit valid (edge-clamped) data.
145
45.4k
      int fill_width = ((extra_left + nPbW + extra_right + 15) & ~15);
146
45.4k
      if (fill_width > MAX_CU_SIZE+16) fill_width = MAX_CU_SIZE+16;
147
148
810k
      for (int y=-extra_top;y<nPbH+extra_bottom;y++) {
149
21.0M
        for (int x=-extra_left;x<fill_width - extra_left;x++) {
150
151
20.2M
          int xA = Clip3(0,w-1,x + xIntOffsL);
152
20.2M
          int yA = Clip3(0,h-1,y + yIntOffsL);
153
154
20.2M
          padbuf[x+extra_left + (y+extra_top)*(MAX_CU_SIZE+16)] = ref[ xA + yA*ref_stride ];
155
20.2M
        }
156
764k
      }
157
158
45.4k
      src_ptr = &padbuf[extra_top*(MAX_CU_SIZE+16) + extra_left];
159
45.4k
      src_stride = MAX_CU_SIZE+16;
160
45.4k
    }
161
162
144k
    ctx->acceleration.put_hevc_qpel(out, out_stride,
163
144k
                                    src_ptr, src_stride /* sizeof(pixel_t) */,
164
144k
                                    nPbW,nPbH, mcbuffer, xFracL,yFracL, bitDepth_L);
165
166
167
144k
    logtrace(LogMotion,"---V---\n");
168
1.51M
    for (int y=0;y<nPbH;y++) {
169
23.2M
      for (int x=0;x<nPbW;x++) {
170
21.8M
        logtrace(LogMotion,"%04x ",out[x+y*out_stride]);
171
21.8M
      }
172
1.37M
      logtrace(LogMotion,"\n");
173
1.37M
    }
174
144k
  }
175
370k
}
Unexecuted instantiation: void mc_luma<unsigned char, int>(base_context const*, seq_parameter_set const*, int, int, int, int, int*, int, unsigned char const*, long, int, int, int)
176
177
178
179
// Chroma sample interpolation process (8.5.3.3.3.3).
180
template <class pixel_t, class inter_t>
181
void mc_chroma(const base_context* ctx,
182
               const seq_parameter_set* sps,
183
               int mv_x, int mv_y,
184
               int xP,int yP,
185
               inter_t* out, int out_stride,
186
               const pixel_t* ref, ptrdiff_t ref_stride,
187
               int nPbWC, int nPbHC, int bit_depth_C)
188
2.63M
{
189
  //const int shift1 = std::min(4, sps->BitDepth_C-8);
190
  //const int shift2 = 6;
191
2.63M
  const int shift3 = std::max(2, 14 - sps->BitDepth_C);
192
193
2.63M
  int wC = sps->pic_width_in_luma_samples /sps->SubWidthC;
194
2.63M
  int hC = sps->pic_height_in_luma_samples/sps->SubHeightC;
195
196
2.63M
  mv_x *= 2 / sps->SubWidthC;
197
2.63M
  mv_y *= 2 / sps->SubHeightC;
198
199
2.63M
  int xFracC = mv_x & 7;
200
2.63M
  int yFracC = mv_y & 7;
201
202
2.63M
  int xIntOffsC = xP/sps->SubWidthC  + (mv_x>>3);
203
2.63M
  int yIntOffsC = yP/sps->SubHeightC + (mv_y>>3);
204
205
2.63M
  ALIGNED_32(inter_t mcbuffer[MAX_CU_SIZE*(MAX_CU_SIZE+7)]);
206
207
2.63M
  if (xFracC == 0 && yFracC == 0) {
208
1.30M
    if (xIntOffsC>=0 && nPbWC+xIntOffsC<=wC &&
209
1.30M
        yIntOffsC>=0 && nPbHC+yIntOffsC<=hC) {
210
1.28M
      ctx->acceleration.put_hevc_epel(out, out_stride,
211
1.28M
                                      &ref[xIntOffsC + yIntOffsC*ref_stride], ref_stride,
212
1.28M
                                      nPbWC,nPbHC, 0,0, nullptr, bit_depth_C);
213
1.28M
    }
214
25.1k
    else
215
25.1k
      {
216
149k
        for (int y=0;y<nPbHC;y++)
217
960k
          for (int x=0;x<nPbWC;x++) {
218
219
836k
            int xB = Clip3(0,wC-1,x + xIntOffsC);
220
836k
            int yB = Clip3(0,hC-1,y + yIntOffsC);
221
222
836k
            out[y*out_stride+x] = ref[ xB + yB*ref_stride ] << shift3;
223
836k
          }
224
25.1k
      }
225
1.30M
  }
226
1.32M
  else {
227
1.32M
    pixel_t padbuf[(MAX_CU_SIZE+16)*(MAX_CU_SIZE+3)];
228
229
1.32M
    const pixel_t* src_ptr;
230
1.32M
    ptrdiff_t src_stride;
231
232
1.32M
    int extra_top  = 1;
233
1.32M
    int extra_left = 1;
234
1.32M
    int extra_right  = 2;
235
1.32M
    int extra_bottom = 2;
236
237
1.32M
    if (xIntOffsC>=1 && nPbWC+xIntOffsC<=wC-2 &&
238
1.22M
        yIntOffsC>=1 && nPbHC+yIntOffsC<=hC-2) {
239
830k
      src_ptr = &ref[xIntOffsC + yIntOffsC*ref_stride];
240
830k
      src_stride = ref_stride;
241
830k
    }
242
495k
    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
495k
      int fill_width = ((extra_left + nPbWC + extra_right + 15) & ~15);
246
495k
      if (fill_width > MAX_CU_SIZE+16) fill_width = MAX_CU_SIZE+16;
247
248
4.93M
      for (int y=-extra_top;y<nPbHC+extra_bottom;y++) {
249
95.8M
        for (int x=-extra_left;x<fill_width - extra_left;x++) {
250
251
91.3M
          int xA = Clip3(0,wC-1,x + xIntOffsC);
252
91.3M
          int yA = Clip3(0,hC-1,y + yIntOffsC);
253
254
91.3M
          padbuf[x+extra_left + (y+extra_top)*(MAX_CU_SIZE+16)] = ref[ xA + yA*ref_stride ];
255
91.3M
        }
256
4.44M
      }
257
258
495k
      src_ptr = &padbuf[extra_left + extra_top*(MAX_CU_SIZE+16)];
259
495k
      src_stride = MAX_CU_SIZE+16;
260
495k
    }
261
262
263
1.32M
    if (xFracC && yFracC) {
264
879k
      ctx->acceleration.put_hevc_epel_hv(out, out_stride,
265
879k
                                         src_ptr, src_stride,
266
879k
                                         nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
267
879k
    }
268
446k
    else if (xFracC) {
269
202k
      ctx->acceleration.put_hevc_epel_h(out, out_stride,
270
202k
                                        src_ptr, src_stride,
271
202k
                                        nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
272
202k
    }
273
244k
    else if (yFracC) {
274
244k
      ctx->acceleration.put_hevc_epel_v(out, out_stride,
275
244k
                                        src_ptr, src_stride,
276
244k
                                        nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
277
244k
    }
278
0
    else {
279
0
      assert(false); // full-pel shifts are handled above
280
0
    }
281
1.32M
  }
282
2.63M
}
void mc_chroma<unsigned short, short>(base_context const*, seq_parameter_set const*, int, int, int, int, short*, int, unsigned short const*, long, int, int, int)
Line
Count
Source
188
339k
{
189
  //const int shift1 = std::min(4, sps->BitDepth_C-8);
190
  //const int shift2 = 6;
191
339k
  const int shift3 = std::max(2, 14 - sps->BitDepth_C);
192
193
339k
  int wC = sps->pic_width_in_luma_samples /sps->SubWidthC;
194
339k
  int hC = sps->pic_height_in_luma_samples/sps->SubHeightC;
195
196
339k
  mv_x *= 2 / sps->SubWidthC;
197
339k
  mv_y *= 2 / sps->SubHeightC;
198
199
339k
  int xFracC = mv_x & 7;
200
339k
  int yFracC = mv_y & 7;
201
202
339k
  int xIntOffsC = xP/sps->SubWidthC  + (mv_x>>3);
203
339k
  int yIntOffsC = yP/sps->SubHeightC + (mv_y>>3);
204
205
339k
  ALIGNED_32(inter_t mcbuffer[MAX_CU_SIZE*(MAX_CU_SIZE+7)]);
206
207
339k
  if (xFracC == 0 && yFracC == 0) {
208
182k
    if (xIntOffsC>=0 && nPbWC+xIntOffsC<=wC &&
209
181k
        yIntOffsC>=0 && nPbHC+yIntOffsC<=hC) {
210
176k
      ctx->acceleration.put_hevc_epel(out, out_stride,
211
176k
                                      &ref[xIntOffsC + yIntOffsC*ref_stride], ref_stride,
212
176k
                                      nPbWC,nPbHC, 0,0, nullptr, bit_depth_C);
213
176k
    }
214
5.84k
    else
215
5.84k
      {
216
33.5k
        for (int y=0;y<nPbHC;y++)
217
207k
          for (int x=0;x<nPbWC;x++) {
218
219
180k
            int xB = Clip3(0,wC-1,x + xIntOffsC);
220
180k
            int yB = Clip3(0,hC-1,y + yIntOffsC);
221
222
180k
            out[y*out_stride+x] = ref[ xB + yB*ref_stride ] << shift3;
223
180k
          }
224
5.84k
      }
225
182k
  }
226
157k
  else {
227
157k
    pixel_t padbuf[(MAX_CU_SIZE+16)*(MAX_CU_SIZE+3)];
228
229
157k
    const pixel_t* src_ptr;
230
157k
    ptrdiff_t src_stride;
231
232
157k
    int extra_top  = 1;
233
157k
    int extra_left = 1;
234
157k
    int extra_right  = 2;
235
157k
    int extra_bottom = 2;
236
237
157k
    if (xIntOffsC>=1 && nPbWC+xIntOffsC<=wC-2 &&
238
145k
        yIntOffsC>=1 && nPbHC+yIntOffsC<=hC-2) {
239
91.6k
      src_ptr = &ref[xIntOffsC + yIntOffsC*ref_stride];
240
91.6k
      src_stride = ref_stride;
241
91.6k
    }
242
66.1k
    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
66.1k
      int fill_width = ((extra_left + nPbWC + extra_right + 15) & ~15);
246
66.1k
      if (fill_width > MAX_CU_SIZE+16) fill_width = MAX_CU_SIZE+16;
247
248
608k
      for (int y=-extra_top;y<nPbHC+extra_bottom;y++) {
249
10.6M
        for (int x=-extra_left;x<fill_width - extra_left;x++) {
250
251
10.1M
          int xA = Clip3(0,wC-1,x + xIntOffsC);
252
10.1M
          int yA = Clip3(0,hC-1,y + yIntOffsC);
253
254
10.1M
          padbuf[x+extra_left + (y+extra_top)*(MAX_CU_SIZE+16)] = ref[ xA + yA*ref_stride ];
255
10.1M
        }
256
542k
      }
257
258
66.1k
      src_ptr = &padbuf[extra_left + extra_top*(MAX_CU_SIZE+16)];
259
66.1k
      src_stride = MAX_CU_SIZE+16;
260
66.1k
    }
261
262
263
157k
    if (xFracC && yFracC) {
264
122k
      ctx->acceleration.put_hevc_epel_hv(out, out_stride,
265
122k
                                         src_ptr, src_stride,
266
122k
                                         nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
267
122k
    }
268
35.5k
    else if (xFracC) {
269
16.5k
      ctx->acceleration.put_hevc_epel_h(out, out_stride,
270
16.5k
                                        src_ptr, src_stride,
271
16.5k
                                        nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
272
16.5k
    }
273
19.0k
    else if (yFracC) {
274
19.0k
      ctx->acceleration.put_hevc_epel_v(out, out_stride,
275
19.0k
                                        src_ptr, src_stride,
276
19.0k
                                        nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
277
19.0k
    }
278
0
    else {
279
      assert(false); // full-pel shifts are handled above
280
0
    }
281
157k
  }
282
339k
}
void mc_chroma<unsigned char, short>(base_context const*, seq_parameter_set const*, int, int, int, int, short*, int, unsigned char const*, long, int, int, int)
Line
Count
Source
188
2.25M
{
189
  //const int shift1 = std::min(4, sps->BitDepth_C-8);
190
  //const int shift2 = 6;
191
2.25M
  const int shift3 = std::max(2, 14 - sps->BitDepth_C);
192
193
2.25M
  int wC = sps->pic_width_in_luma_samples /sps->SubWidthC;
194
2.25M
  int hC = sps->pic_height_in_luma_samples/sps->SubHeightC;
195
196
2.25M
  mv_x *= 2 / sps->SubWidthC;
197
2.25M
  mv_y *= 2 / sps->SubHeightC;
198
199
2.25M
  int xFracC = mv_x & 7;
200
2.25M
  int yFracC = mv_y & 7;
201
202
2.25M
  int xIntOffsC = xP/sps->SubWidthC  + (mv_x>>3);
203
2.25M
  int yIntOffsC = yP/sps->SubHeightC + (mv_y>>3);
204
205
2.25M
  ALIGNED_32(inter_t mcbuffer[MAX_CU_SIZE*(MAX_CU_SIZE+7)]);
206
207
2.25M
  if (xFracC == 0 && yFracC == 0) {
208
1.10M
    if (xIntOffsC>=0 && nPbWC+xIntOffsC<=wC &&
209
1.10M
        yIntOffsC>=0 && nPbHC+yIntOffsC<=hC) {
210
1.08M
      ctx->acceleration.put_hevc_epel(out, out_stride,
211
1.08M
                                      &ref[xIntOffsC + yIntOffsC*ref_stride], ref_stride,
212
1.08M
                                      nPbWC,nPbHC, 0,0, nullptr, bit_depth_C);
213
1.08M
    }
214
18.2k
    else
215
18.2k
      {
216
109k
        for (int y=0;y<nPbHC;y++)
217
714k
          for (int x=0;x<nPbWC;x++) {
218
219
623k
            int xB = Clip3(0,wC-1,x + xIntOffsC);
220
623k
            int yB = Clip3(0,hC-1,y + yIntOffsC);
221
222
623k
            out[y*out_stride+x] = ref[ xB + yB*ref_stride ] << shift3;
223
623k
          }
224
18.2k
      }
225
1.10M
  }
226
1.14M
  else {
227
1.14M
    pixel_t padbuf[(MAX_CU_SIZE+16)*(MAX_CU_SIZE+3)];
228
229
1.14M
    const pixel_t* src_ptr;
230
1.14M
    ptrdiff_t src_stride;
231
232
1.14M
    int extra_top  = 1;
233
1.14M
    int extra_left = 1;
234
1.14M
    int extra_right  = 2;
235
1.14M
    int extra_bottom = 2;
236
237
1.14M
    if (xIntOffsC>=1 && nPbWC+xIntOffsC<=wC-2 &&
238
1.06M
        yIntOffsC>=1 && nPbHC+yIntOffsC<=hC-2) {
239
727k
      src_ptr = &ref[xIntOffsC + yIntOffsC*ref_stride];
240
727k
      src_stride = ref_stride;
241
727k
    }
242
417k
    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
417k
      int fill_width = ((extra_left + nPbWC + extra_right + 15) & ~15);
246
417k
      if (fill_width > MAX_CU_SIZE+16) fill_width = MAX_CU_SIZE+16;
247
248
4.21M
      for (int y=-extra_top;y<nPbHC+extra_bottom;y++) {
249
83.3M
        for (int x=-extra_left;x<fill_width - extra_left;x++) {
250
251
79.5M
          int xA = Clip3(0,wC-1,x + xIntOffsC);
252
79.5M
          int yA = Clip3(0,hC-1,y + yIntOffsC);
253
254
79.5M
          padbuf[x+extra_left + (y+extra_top)*(MAX_CU_SIZE+16)] = ref[ xA + yA*ref_stride ];
255
79.5M
        }
256
3.80M
      }
257
258
417k
      src_ptr = &padbuf[extra_left + extra_top*(MAX_CU_SIZE+16)];
259
417k
      src_stride = MAX_CU_SIZE+16;
260
417k
    }
261
262
263
1.14M
    if (xFracC && yFracC) {
264
743k
      ctx->acceleration.put_hevc_epel_hv(out, out_stride,
265
743k
                                         src_ptr, src_stride,
266
743k
                                         nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
267
743k
    }
268
401k
    else if (xFracC) {
269
181k
      ctx->acceleration.put_hevc_epel_h(out, out_stride,
270
181k
                                        src_ptr, src_stride,
271
181k
                                        nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
272
181k
    }
273
219k
    else if (yFracC) {
274
219k
      ctx->acceleration.put_hevc_epel_v(out, out_stride,
275
219k
                                        src_ptr, src_stride,
276
219k
                                        nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
277
219k
    }
278
0
    else {
279
      assert(false); // full-pel shifts are handled above
280
0
    }
281
1.14M
  }
282
2.25M
}
void mc_chroma<unsigned short, int>(base_context const*, seq_parameter_set const*, int, int, int, int, int*, int, unsigned short const*, long, int, int, int)
Line
Count
Source
188
42.5k
{
189
  //const int shift1 = std::min(4, sps->BitDepth_C-8);
190
  //const int shift2 = 6;
191
42.5k
  const int shift3 = std::max(2, 14 - sps->BitDepth_C);
192
193
42.5k
  int wC = sps->pic_width_in_luma_samples /sps->SubWidthC;
194
42.5k
  int hC = sps->pic_height_in_luma_samples/sps->SubHeightC;
195
196
42.5k
  mv_x *= 2 / sps->SubWidthC;
197
42.5k
  mv_y *= 2 / sps->SubHeightC;
198
199
42.5k
  int xFracC = mv_x & 7;
200
42.5k
  int yFracC = mv_y & 7;
201
202
42.5k
  int xIntOffsC = xP/sps->SubWidthC  + (mv_x>>3);
203
42.5k
  int yIntOffsC = yP/sps->SubHeightC + (mv_y>>3);
204
205
42.5k
  ALIGNED_32(inter_t mcbuffer[MAX_CU_SIZE*(MAX_CU_SIZE+7)]);
206
207
42.5k
  if (xFracC == 0 && yFracC == 0) {
208
19.4k
    if (xIntOffsC>=0 && nPbWC+xIntOffsC<=wC &&
209
19.0k
        yIntOffsC>=0 && nPbHC+yIntOffsC<=hC) {
210
18.5k
      ctx->acceleration.put_hevc_epel(out, out_stride,
211
18.5k
                                      &ref[xIntOffsC + yIntOffsC*ref_stride], ref_stride,
212
18.5k
                                      nPbWC,nPbHC, 0,0, nullptr, bit_depth_C);
213
18.5k
    }
214
990
    else
215
990
      {
216
6.13k
        for (int y=0;y<nPbHC;y++)
217
37.8k
          for (int x=0;x<nPbWC;x++) {
218
219
32.7k
            int xB = Clip3(0,wC-1,x + xIntOffsC);
220
32.7k
            int yB = Clip3(0,hC-1,y + yIntOffsC);
221
222
32.7k
            out[y*out_stride+x] = ref[ xB + yB*ref_stride ] << shift3;
223
32.7k
          }
224
990
      }
225
19.4k
  }
226
23.0k
  else {
227
23.0k
    pixel_t padbuf[(MAX_CU_SIZE+16)*(MAX_CU_SIZE+3)];
228
229
23.0k
    const pixel_t* src_ptr;
230
23.0k
    ptrdiff_t src_stride;
231
232
23.0k
    int extra_top  = 1;
233
23.0k
    int extra_left = 1;
234
23.0k
    int extra_right  = 2;
235
23.0k
    int extra_bottom = 2;
236
237
23.0k
    if (xIntOffsC>=1 && nPbWC+xIntOffsC<=wC-2 &&
238
16.4k
        yIntOffsC>=1 && nPbHC+yIntOffsC<=hC-2) {
239
11.6k
      src_ptr = &ref[xIntOffsC + yIntOffsC*ref_stride];
240
11.6k
      src_stride = ref_stride;
241
11.6k
    }
242
11.3k
    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
11.3k
      int fill_width = ((extra_left + nPbWC + extra_right + 15) & ~15);
246
11.3k
      if (fill_width > MAX_CU_SIZE+16) fill_width = MAX_CU_SIZE+16;
247
248
108k
      for (int y=-extra_top;y<nPbHC+extra_bottom;y++) {
249
1.86M
        for (int x=-extra_left;x<fill_width - extra_left;x++) {
250
251
1.76M
          int xA = Clip3(0,wC-1,x + xIntOffsC);
252
1.76M
          int yA = Clip3(0,hC-1,y + yIntOffsC);
253
254
1.76M
          padbuf[x+extra_left + (y+extra_top)*(MAX_CU_SIZE+16)] = ref[ xA + yA*ref_stride ];
255
1.76M
        }
256
97.4k
      }
257
258
11.3k
      src_ptr = &padbuf[extra_left + extra_top*(MAX_CU_SIZE+16)];
259
11.3k
      src_stride = MAX_CU_SIZE+16;
260
11.3k
    }
261
262
263
23.0k
    if (xFracC && yFracC) {
264
13.8k
      ctx->acceleration.put_hevc_epel_hv(out, out_stride,
265
13.8k
                                         src_ptr, src_stride,
266
13.8k
                                         nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
267
13.8k
    }
268
9.23k
    else if (xFracC) {
269
3.77k
      ctx->acceleration.put_hevc_epel_h(out, out_stride,
270
3.77k
                                        src_ptr, src_stride,
271
3.77k
                                        nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
272
3.77k
    }
273
5.45k
    else if (yFracC) {
274
5.45k
      ctx->acceleration.put_hevc_epel_v(out, out_stride,
275
5.45k
                                        src_ptr, src_stride,
276
5.45k
                                        nPbWC,nPbHC, xFracC,yFracC, mcbuffer, bit_depth_C);
277
5.45k
    }
278
0
    else {
279
      assert(false); // full-pel shifts are handled above
280
0
    }
281
23.0k
  }
282
42.5k
}
Unexecuted instantiation: void mc_chroma<unsigned char, int>(base_context const*, seq_parameter_set const*, int, int, int, int, int*, int, unsigned char const*, long, int, int, int)
283
284
285
286
// Fractional sample interpolation (8.5.3.3.3) and weighted sample prediction
287
// (8.5.3.3.4) for one colour plane.
288
//
289
// inter_t is the type of the intermediate prediction samples predSamplesLX.
290
// The spec keeps them at max(14, BitDepth+2) bits plus the overshoot of the
291
// interpolation filters, which fits into int16_t only up to
292
// MC_MAX_BIT_DEPTH_INT16. Above that, int32_t is used (see acceleration.h).
293
//
294
// refPic[l] is NULL when list l is not used or when its reference picture is
295
// unusable. The caller has already reported the latter; the prediction is then
296
// filled with mid-grey.
297
//
298
// Forced inline: called once per colour plane from a hot loop, and inlining lets
299
// the compiler set up the prediction sample buffer once per PB instead of once
300
// per plane.
301
template <class inter_t>
302
static LIBDE265_ALWAYS_INLINE void generate_inter_prediction_samples_plane(base_context* ctx,
303
                                                    const slice_segment_header* shdr,
304
                                                    de265_image* img,
305
                                                    int cIdx,
306
                                                    int xP,int yP,
307
                                                    int nCS, int nPbW,int nPbH,
308
                                                    const PBMotion* vi,
309
                                                    const int predFlag[2],
310
                                                    const de265_image* const refPic[2])
311
3.27M
{
312
3.27M
  const pic_parameter_set* pps = shdr->pps.get();
313
3.27M
  const seq_parameter_set* sps = pps->sps.get();
314
315
3.27M
  const int bit_depth = sps->get_bit_depth(cIdx);
316
317
3.27M
  const int SubWidthC  = (cIdx==0 ? 1 : sps->SubWidthC);
318
3.27M
  const int SubHeightC = (cIdx==0 ? 1 : sps->SubHeightC);
319
3.27M
  const int w = nPbW / SubWidthC;
320
3.27M
  const int h = nPbH / SubHeightC;
321
322
3.27M
  void* pixels = img->get_image_plane_at_pos_any_depth(cIdx, xP/SubWidthC, yP/SubHeightC);
323
3.27M
  const ptrdiff_t stride = img->get_image_stride(cIdx);
324
325
  // TODO: must predSamples stride really be nCS or can it be something smaller like nPbW?
326
3.27M
  ALIGNED_16(inter_t) predSamples[2 /* LX */][MAX_CU_SIZE* MAX_CU_SIZE];
327
328
329
  // --- fractional sample interpolation (8.5.3.3.3) ---
330
331
9.82M
  for (int l=0;l<2;l++) {
332
6.54M
    if (!predFlag[l]) continue;
333
334
3.95M
    if (!refPic[l]) {
335
      // Fill with mid-grey in intermediate precision: (1 << (bit_depth-1)) << shift3.
336
0
      const inter_t fill = inter_t(1) << (bit_depth-1 + std::max(2, 14-bit_depth));
337
338
0
      for (int y=0;y<h;y++)
339
0
        for (int x=0;x<w;x++)
340
0
          predSamples[l][y*nCS+x] = fill;
341
342
0
      continue;
343
0
    }
344
345
3.95M
    if (cIdx==0) {
346
1.31M
      if (img->high_bit_depth(0)) {
347
532k
        mc_luma(ctx, sps, vi->mv[l].x, vi->mv[l].y, xP,yP,
348
532k
                predSamples[l],nCS,
349
532k
                (const uint16_t*)refPic[l]->get_image_plane(0),
350
532k
                refPic[l]->get_luma_stride(), nPbW,nPbH, bit_depth);
351
532k
      }
352
785k
      else {
353
785k
        mc_luma(ctx, sps, vi->mv[l].x, vi->mv[l].y, xP,yP,
354
785k
                predSamples[l],nCS,
355
785k
                (const uint8_t*)refPic[l]->get_image_plane(0),
356
785k
                refPic[l]->get_luma_stride(), nPbW,nPbH, bit_depth);
357
785k
      }
358
1.31M
    }
359
2.63M
    else {
360
2.63M
      if (img->high_bit_depth(cIdx)) {
361
382k
        mc_chroma(ctx, sps, vi->mv[l].x, vi->mv[l].y, xP,yP,
362
382k
                  predSamples[l],nCS,
363
382k
                  (const uint16_t*)refPic[l]->get_image_plane(cIdx),
364
382k
                  refPic[l]->get_chroma_stride(), w,h, bit_depth);
365
382k
      }
366
2.25M
      else {
367
2.25M
        mc_chroma(ctx, sps, vi->mv[l].x, vi->mv[l].y, xP,yP,
368
2.25M
                  predSamples[l],nCS,
369
2.25M
                  (const uint8_t*)refPic[l]->get_image_plane(cIdx),
370
2.25M
                  refPic[l]->get_chroma_stride(), w,h, bit_depth);
371
2.25M
      }
372
2.63M
    }
373
3.95M
  }
374
375
376
  // --- weighted sample prediction (8.5.3.3.4) ---
377
378
3.27M
  const bool weightedPredFlag = (shdr->slice_type == SLICE_TYPE_P ?
379
2.00M
                                 pps->weighted_pred_flag : pps->weighted_bipred_flag);
380
381
  // explicit weighted prediction parameters (8.5.3.3.4.3)
382
383
3.27M
  const int shift1 = std::max(2, 14-bit_depth);
384
3.27M
  const int log2WD = (cIdx==0 ? shdr->luma_log2_weight_denom : shdr->ChromaLog2WeightDenom) + shift1;
385
3.27M
  const int offsetShift = (cIdx==0 ? sps->WpOffsetBdShiftY : sps->WpOffsetBdShiftC);
386
387
3.27M
  auto weight = [&](int l) -> int {
388
2.38M
    const int refIdx = vi->refIdx[l];
389
2.38M
    return (cIdx==0 ? shdr->LumaWeight[l][refIdx] : shdr->ChromaWeight[l][refIdx][cIdx-1]);
390
2.38M
  };
motion.cc:generate_inter_prediction_samples_plane<short>(base_context*, slice_segment_header const*, de265_image*, int, int, int, int, int, int, PBMotion const*, int const*, de265_image const* const*)::{lambda(int)#1}::operator()(int) const
Line
Count
Source
387
2.19M
  auto weight = [&](int l) -> int {
388
2.19M
    const int refIdx = vi->refIdx[l];
389
2.19M
    return (cIdx==0 ? shdr->LumaWeight[l][refIdx] : shdr->ChromaWeight[l][refIdx][cIdx-1]);
390
2.19M
  };
motion.cc:generate_inter_prediction_samples_plane<int>(base_context*, slice_segment_header const*, de265_image*, int, int, int, int, int, int, PBMotion const*, int const*, de265_image const* const*)::{lambda(int)#1}::operator()(int) const
Line
Count
Source
387
182k
  auto weight = [&](int l) -> int {
388
182k
    const int refIdx = vi->refIdx[l];
389
182k
    return (cIdx==0 ? shdr->LumaWeight[l][refIdx] : shdr->ChromaWeight[l][refIdx][cIdx-1]);
390
182k
  };
391
392
3.27M
  auto offset = [&](int l) -> int {
393
2.38M
    const int refIdx = vi->refIdx[l];
394
2.38M
    const int o = (cIdx==0 ? shdr->luma_offset[l][refIdx] : shdr->ChromaOffset[l][refIdx][cIdx-1]);
395
2.38M
    return o * (1<<offsetShift);
396
2.38M
  };
motion.cc:generate_inter_prediction_samples_plane<short>(base_context*, slice_segment_header const*, de265_image*, int, int, int, int, int, int, PBMotion const*, int const*, de265_image const* const*)::{lambda(int)#2}::operator()(int) const
Line
Count
Source
392
2.19M
  auto offset = [&](int l) -> int {
393
2.19M
    const int refIdx = vi->refIdx[l];
394
2.19M
    const int o = (cIdx==0 ? shdr->luma_offset[l][refIdx] : shdr->ChromaOffset[l][refIdx][cIdx-1]);
395
2.19M
    return o * (1<<offsetShift);
396
2.19M
  };
motion.cc:generate_inter_prediction_samples_plane<int>(base_context*, slice_segment_header const*, de265_image*, int, int, int, int, int, int, PBMotion const*, int const*, de265_image const* const*)::{lambda(int)#2}::operator()(int) const
Line
Count
Source
392
182k
  auto offset = [&](int l) -> int {
393
182k
    const int refIdx = vi->refIdx[l];
394
182k
    const int o = (cIdx==0 ? shdr->luma_offset[l][refIdx] : shdr->ChromaOffset[l][refIdx][cIdx-1]);
395
182k
    return o * (1<<offsetShift);
396
182k
  };
397
398
399
3.27M
  if (predFlag[0] && predFlag[1]) {
400
678k
    if (!weightedPredFlag) {
401
127k
      ctx->acceleration.put_weighted_pred_avg(pixels, stride,
402
127k
                                              predSamples[0], predSamples[1], nCS,
403
127k
                                              w,h, bit_depth);
404
127k
    }
405
550k
    else {
406
550k
      logtrace(LogMotion,"weighted-BI-0 [%d] %d %d %d  %dx%d\n", vi->refIdx[0], log2WD-6,weight(0),offset(0),w,h);
407
550k
      logtrace(LogMotion,"weighted-BI-1 [%d] %d %d %d  %dx%d\n", vi->refIdx[1], log2WD-6,weight(1),offset(1),w,h);
408
409
550k
      ctx->acceleration.put_weighted_bipred(pixels, stride,
410
550k
                                            predSamples[0], predSamples[1], nCS,
411
550k
                                            w,h,
412
550k
                                            weight(0),offset(0),
413
550k
                                            weight(1),offset(1),
414
550k
                                            log2WD, bit_depth);
415
550k
    }
416
678k
  }
417
2.59M
  else {
418
2.59M
    const int l = (predFlag[0] ? 0 : 1); // the caller ensures that one list is used
419
420
2.59M
    if (!weightedPredFlag) {
421
1.31M
      ctx->acceleration.put_unweighted_pred(pixels, stride,
422
1.31M
                                            predSamples[l], nCS,
423
1.31M
                                            w,h, bit_depth);
424
1.31M
    }
425
1.28M
    else {
426
1.28M
      logtrace(LogMotion,"weighted-L%d [%d] %d %d %d  %dx%d\n", l, vi->refIdx[l], log2WD-6,weight(l),offset(l),w,h);
427
428
1.28M
      ctx->acceleration.put_weighted_pred(pixels, stride,
429
1.28M
                                          predSamples[l], nCS,
430
1.28M
                                          w,h,
431
1.28M
                                          weight(l),offset(l),
432
1.28M
                                          log2WD, bit_depth);
433
1.28M
    }
434
2.59M
  }
435
3.27M
}
motion.cc:void generate_inter_prediction_samples_plane<short>(base_context*, slice_segment_header const*, de265_image*, int, int, int, int, int, int, PBMotion const*, int const*, de265_image const* const*)
Line
Count
Source
311
2.89M
{
312
2.89M
  const pic_parameter_set* pps = shdr->pps.get();
313
2.89M
  const seq_parameter_set* sps = pps->sps.get();
314
315
2.89M
  const int bit_depth = sps->get_bit_depth(cIdx);
316
317
2.89M
  const int SubWidthC  = (cIdx==0 ? 1 : sps->SubWidthC);
318
2.89M
  const int SubHeightC = (cIdx==0 ? 1 : sps->SubHeightC);
319
2.89M
  const int w = nPbW / SubWidthC;
320
2.89M
  const int h = nPbH / SubHeightC;
321
322
2.89M
  void* pixels = img->get_image_plane_at_pos_any_depth(cIdx, xP/SubWidthC, yP/SubHeightC);
323
2.89M
  const ptrdiff_t stride = img->get_image_stride(cIdx);
324
325
  // TODO: must predSamples stride really be nCS or can it be something smaller like nPbW?
326
2.89M
  ALIGNED_16(inter_t) predSamples[2 /* LX */][MAX_CU_SIZE* MAX_CU_SIZE];
327
328
329
  // --- fractional sample interpolation (8.5.3.3.3) ---
330
331
8.67M
  for (int l=0;l<2;l++) {
332
5.78M
    if (!predFlag[l]) continue;
333
334
3.53M
    if (!refPic[l]) {
335
      // Fill with mid-grey in intermediate precision: (1 << (bit_depth-1)) << shift3.
336
0
      const inter_t fill = inter_t(1) << (bit_depth-1 + std::max(2, 14-bit_depth));
337
338
0
      for (int y=0;y<h;y++)
339
0
        for (int x=0;x<w;x++)
340
0
          predSamples[l][y*nCS+x] = fill;
341
342
0
      continue;
343
0
    }
344
345
3.53M
    if (cIdx==0) {
346
947k
      if (img->high_bit_depth(0)) {
347
161k
        mc_luma(ctx, sps, vi->mv[l].x, vi->mv[l].y, xP,yP,
348
161k
                predSamples[l],nCS,
349
161k
                (const uint16_t*)refPic[l]->get_image_plane(0),
350
161k
                refPic[l]->get_luma_stride(), nPbW,nPbH, bit_depth);
351
161k
      }
352
785k
      else {
353
785k
        mc_luma(ctx, sps, vi->mv[l].x, vi->mv[l].y, xP,yP,
354
785k
                predSamples[l],nCS,
355
785k
                (const uint8_t*)refPic[l]->get_image_plane(0),
356
785k
                refPic[l]->get_luma_stride(), nPbW,nPbH, bit_depth);
357
785k
      }
358
947k
    }
359
2.59M
    else {
360
2.59M
      if (img->high_bit_depth(cIdx)) {
361
339k
        mc_chroma(ctx, sps, vi->mv[l].x, vi->mv[l].y, xP,yP,
362
339k
                  predSamples[l],nCS,
363
339k
                  (const uint16_t*)refPic[l]->get_image_plane(cIdx),
364
339k
                  refPic[l]->get_chroma_stride(), w,h, bit_depth);
365
339k
      }
366
2.25M
      else {
367
2.25M
        mc_chroma(ctx, sps, vi->mv[l].x, vi->mv[l].y, xP,yP,
368
2.25M
                  predSamples[l],nCS,
369
2.25M
                  (const uint8_t*)refPic[l]->get_image_plane(cIdx),
370
2.25M
                  refPic[l]->get_chroma_stride(), w,h, bit_depth);
371
2.25M
      }
372
2.59M
    }
373
3.53M
  }
374
375
376
  // --- weighted sample prediction (8.5.3.3.4) ---
377
378
2.89M
  const bool weightedPredFlag = (shdr->slice_type == SLICE_TYPE_P ?
379
1.93M
                                 pps->weighted_pred_flag : pps->weighted_bipred_flag);
380
381
  // explicit weighted prediction parameters (8.5.3.3.4.3)
382
383
2.89M
  const int shift1 = std::max(2, 14-bit_depth);
384
2.89M
  const int log2WD = (cIdx==0 ? shdr->luma_log2_weight_denom : shdr->ChromaLog2WeightDenom) + shift1;
385
2.89M
  const int offsetShift = (cIdx==0 ? sps->WpOffsetBdShiftY : sps->WpOffsetBdShiftC);
386
387
2.89M
  auto weight = [&](int l) -> int {
388
2.89M
    const int refIdx = vi->refIdx[l];
389
2.89M
    return (cIdx==0 ? shdr->LumaWeight[l][refIdx] : shdr->ChromaWeight[l][refIdx][cIdx-1]);
390
2.89M
  };
391
392
2.89M
  auto offset = [&](int l) -> int {
393
2.89M
    const int refIdx = vi->refIdx[l];
394
2.89M
    const int o = (cIdx==0 ? shdr->luma_offset[l][refIdx] : shdr->ChromaOffset[l][refIdx][cIdx-1]);
395
2.89M
    return o * (1<<offsetShift);
396
2.89M
  };
397
398
399
2.89M
  if (predFlag[0] && predFlag[1]) {
400
647k
    if (!weightedPredFlag) {
401
125k
      ctx->acceleration.put_weighted_pred_avg(pixels, stride,
402
125k
                                              predSamples[0], predSamples[1], nCS,
403
125k
                                              w,h, bit_depth);
404
125k
    }
405
522k
    else {
406
522k
      logtrace(LogMotion,"weighted-BI-0 [%d] %d %d %d  %dx%d\n", vi->refIdx[0], log2WD-6,weight(0),offset(0),w,h);
407
522k
      logtrace(LogMotion,"weighted-BI-1 [%d] %d %d %d  %dx%d\n", vi->refIdx[1], log2WD-6,weight(1),offset(1),w,h);
408
409
522k
      ctx->acceleration.put_weighted_bipred(pixels, stride,
410
522k
                                            predSamples[0], predSamples[1], nCS,
411
522k
                                            w,h,
412
522k
                                            weight(0),offset(0),
413
522k
                                            weight(1),offset(1),
414
522k
                                            log2WD, bit_depth);
415
522k
    }
416
647k
  }
417
2.24M
  else {
418
2.24M
    const int l = (predFlag[0] ? 0 : 1); // the caller ensures that one list is used
419
420
2.24M
    if (!weightedPredFlag) {
421
1.08M
      ctx->acceleration.put_unweighted_pred(pixels, stride,
422
1.08M
                                            predSamples[l], nCS,
423
1.08M
                                            w,h, bit_depth);
424
1.08M
    }
425
1.15M
    else {
426
1.15M
      logtrace(LogMotion,"weighted-L%d [%d] %d %d %d  %dx%d\n", l, vi->refIdx[l], log2WD-6,weight(l),offset(l),w,h);
427
428
1.15M
      ctx->acceleration.put_weighted_pred(pixels, stride,
429
1.15M
                                          predSamples[l], nCS,
430
1.15M
                                          w,h,
431
1.15M
                                          weight(l),offset(l),
432
1.15M
                                          log2WD, bit_depth);
433
1.15M
    }
434
2.24M
  }
435
2.89M
}
motion.cc:void generate_inter_prediction_samples_plane<int>(base_context*, slice_segment_header const*, de265_image*, int, int, int, int, int, int, PBMotion const*, int const*, de265_image const* const*)
Line
Count
Source
311
382k
{
312
382k
  const pic_parameter_set* pps = shdr->pps.get();
313
382k
  const seq_parameter_set* sps = pps->sps.get();
314
315
382k
  const int bit_depth = sps->get_bit_depth(cIdx);
316
317
382k
  const int SubWidthC  = (cIdx==0 ? 1 : sps->SubWidthC);
318
382k
  const int SubHeightC = (cIdx==0 ? 1 : sps->SubHeightC);
319
382k
  const int w = nPbW / SubWidthC;
320
382k
  const int h = nPbH / SubHeightC;
321
322
382k
  void* pixels = img->get_image_plane_at_pos_any_depth(cIdx, xP/SubWidthC, yP/SubHeightC);
323
382k
  const ptrdiff_t stride = img->get_image_stride(cIdx);
324
325
  // TODO: must predSamples stride really be nCS or can it be something smaller like nPbW?
326
382k
  ALIGNED_16(inter_t) predSamples[2 /* LX */][MAX_CU_SIZE* MAX_CU_SIZE];
327
328
329
  // --- fractional sample interpolation (8.5.3.3.3) ---
330
331
1.14M
  for (int l=0;l<2;l++) {
332
764k
    if (!predFlag[l]) continue;
333
334
413k
    if (!refPic[l]) {
335
      // Fill with mid-grey in intermediate precision: (1 << (bit_depth-1)) << shift3.
336
0
      const inter_t fill = inter_t(1) << (bit_depth-1 + std::max(2, 14-bit_depth));
337
338
0
      for (int y=0;y<h;y++)
339
0
        for (int x=0;x<w;x++)
340
0
          predSamples[l][y*nCS+x] = fill;
341
342
0
      continue;
343
0
    }
344
345
413k
    if (cIdx==0) {
346
370k
      if (img->high_bit_depth(0)) {
347
370k
        mc_luma(ctx, sps, vi->mv[l].x, vi->mv[l].y, xP,yP,
348
370k
                predSamples[l],nCS,
349
370k
                (const uint16_t*)refPic[l]->get_image_plane(0),
350
370k
                refPic[l]->get_luma_stride(), nPbW,nPbH, bit_depth);
351
370k
      }
352
0
      else {
353
0
        mc_luma(ctx, sps, vi->mv[l].x, vi->mv[l].y, xP,yP,
354
0
                predSamples[l],nCS,
355
0
                (const uint8_t*)refPic[l]->get_image_plane(0),
356
0
                refPic[l]->get_luma_stride(), nPbW,nPbH, bit_depth);
357
0
      }
358
370k
    }
359
42.5k
    else {
360
42.5k
      if (img->high_bit_depth(cIdx)) {
361
42.5k
        mc_chroma(ctx, sps, vi->mv[l].x, vi->mv[l].y, xP,yP,
362
42.5k
                  predSamples[l],nCS,
363
42.5k
                  (const uint16_t*)refPic[l]->get_image_plane(cIdx),
364
42.5k
                  refPic[l]->get_chroma_stride(), w,h, bit_depth);
365
42.5k
      }
366
0
      else {
367
0
        mc_chroma(ctx, sps, vi->mv[l].x, vi->mv[l].y, xP,yP,
368
0
                  predSamples[l],nCS,
369
0
                  (const uint8_t*)refPic[l]->get_image_plane(cIdx),
370
0
                  refPic[l]->get_chroma_stride(), w,h, bit_depth);
371
0
      }
372
42.5k
    }
373
413k
  }
374
375
376
  // --- weighted sample prediction (8.5.3.3.4) ---
377
378
382k
  const bool weightedPredFlag = (shdr->slice_type == SLICE_TYPE_P ?
379
314k
                                 pps->weighted_pred_flag : pps->weighted_bipred_flag);
380
381
  // explicit weighted prediction parameters (8.5.3.3.4.3)
382
383
382k
  const int shift1 = std::max(2, 14-bit_depth);
384
382k
  const int log2WD = (cIdx==0 ? shdr->luma_log2_weight_denom : shdr->ChromaLog2WeightDenom) + shift1;
385
382k
  const int offsetShift = (cIdx==0 ? sps->WpOffsetBdShiftY : sps->WpOffsetBdShiftC);
386
387
382k
  auto weight = [&](int l) -> int {
388
382k
    const int refIdx = vi->refIdx[l];
389
382k
    return (cIdx==0 ? shdr->LumaWeight[l][refIdx] : shdr->ChromaWeight[l][refIdx][cIdx-1]);
390
382k
  };
391
392
382k
  auto offset = [&](int l) -> int {
393
382k
    const int refIdx = vi->refIdx[l];
394
382k
    const int o = (cIdx==0 ? shdr->luma_offset[l][refIdx] : shdr->ChromaOffset[l][refIdx][cIdx-1]);
395
382k
    return o * (1<<offsetShift);
396
382k
  };
397
398
399
382k
  if (predFlag[0] && predFlag[1]) {
400
30.8k
    if (!weightedPredFlag) {
401
2.52k
      ctx->acceleration.put_weighted_pred_avg(pixels, stride,
402
2.52k
                                              predSamples[0], predSamples[1], nCS,
403
2.52k
                                              w,h, bit_depth);
404
2.52k
    }
405
28.3k
    else {
406
28.3k
      logtrace(LogMotion,"weighted-BI-0 [%d] %d %d %d  %dx%d\n", vi->refIdx[0], log2WD-6,weight(0),offset(0),w,h);
407
28.3k
      logtrace(LogMotion,"weighted-BI-1 [%d] %d %d %d  %dx%d\n", vi->refIdx[1], log2WD-6,weight(1),offset(1),w,h);
408
409
28.3k
      ctx->acceleration.put_weighted_bipred(pixels, stride,
410
28.3k
                                            predSamples[0], predSamples[1], nCS,
411
28.3k
                                            w,h,
412
28.3k
                                            weight(0),offset(0),
413
28.3k
                                            weight(1),offset(1),
414
28.3k
                                            log2WD, bit_depth);
415
28.3k
    }
416
30.8k
  }
417
351k
  else {
418
351k
    const int l = (predFlag[0] ? 0 : 1); // the caller ensures that one list is used
419
420
351k
    if (!weightedPredFlag) {
421
225k
      ctx->acceleration.put_unweighted_pred(pixels, stride,
422
225k
                                            predSamples[l], nCS,
423
225k
                                            w,h, bit_depth);
424
225k
    }
425
126k
    else {
426
126k
      logtrace(LogMotion,"weighted-L%d [%d] %d %d %d  %dx%d\n", l, vi->refIdx[l], log2WD-6,weight(l),offset(l),w,h);
427
428
126k
      ctx->acceleration.put_weighted_pred(pixels, stride,
429
126k
                                          predSamples[l], nCS,
430
126k
                                          w,h,
431
126k
                                          weight(l),offset(l),
432
126k
                                          log2WD, bit_depth);
433
126k
    }
434
351k
  }
435
382k
}
436
437
438
439
// Decoding process for inter prediction samples (8.5.3.3).
440
// NOTE: for full-pel shifts, we can introduce a fast path, simply copying without shifts
441
void generate_inter_prediction_samples(base_context* ctx,
442
                                       const slice_segment_header* shdr,
443
                                       de265_image* img,
444
                                       int xC,int yC,
445
                                       int xB,int yB,
446
                                       int nCS, int nPbW,int nPbH,
447
                                       const PBMotion* vi)
448
1.09M
{
449
1.09M
  const int xP = xC+xB;
450
1.09M
  const int yP = yC+yB;
451
452
1.09M
  const pic_parameter_set* pps = shdr->pps.get();
453
1.09M
  const seq_parameter_set* sps = pps->sps.get();
454
455
1.09M
  if (sps->BitDepth_Y != img->get_bit_depth(0) ||
456
1.09M
      sps->BitDepth_C != img->get_bit_depth(1)) {
457
0
    img->integrity = INTEGRITY_DECODING_ERRORS;
458
0
    ctx->add_warning(DE265_WARNING_BIT_DEPTH_OF_CURRENT_IMAGE_DOES_NOT_MATCH_SPS, false);
459
0
    return;
460
0
  }
461
462
1.09M
  if (sps->chroma_format_idc != img->get_chroma_format()) {
463
0
    img->integrity = INTEGRITY_DECODING_ERRORS;
464
0
    ctx->add_warning(DE265_WARNING_CHROMA_OF_CURRENT_IMAGE_DOES_NOT_MATCH_SPS, false);
465
0
    return;
466
0
  }
467
468
469
1.09M
  int predFlag[2];
470
1.09M
  predFlag[0] = vi->predFlag[0];
471
1.09M
  predFlag[1] = vi->predFlag[1];
472
473
  // Some encoders use bi-prediction with two identical MVs onto the same picture.
474
  // Identify this case and use only one MV. This is not possible with explicit
475
  // weighted prediction, where the two lists may have different weights/offsets.
476
477
1.09M
  const bool weightedPredFlag = (shdr->slice_type == SLICE_TYPE_P ?
478
667k
                                 pps->weighted_pred_flag : pps->weighted_bipred_flag);
479
480
1.09M
  if (!weightedPredFlag) {
481
480k
    if (predFlag[0] && predFlag[1]) {
482
69.5k
      if (vi->mv[0].x == vi->mv[1].x &&
483
50.0k
          vi->mv[0].y == vi->mv[1].y &&
484
46.4k
          shdr->RefPicList[0][vi->refIdx[0]] ==
485
46.4k
          shdr->RefPicList[1][vi->refIdx[1]]) {
486
26.9k
        predFlag[1] = 0;
487
26.9k
      }
488
69.5k
    }
489
480k
  }
490
491
1.09M
  logtrace(LogMotion,"predFlags (modified): %d %d\n", predFlag[0], predFlag[1]);
492
493
1.09M
  if (!predFlag[0] && !predFlag[1]) {
494
    // TODO: check why it can actually happen that both predFlags[] are false.
495
    // For now, we ignore this and continue decoding.
496
497
0
    ctx->add_warning(DE265_WARNING_BOTH_PREDFLAGS_ZERO, false);
498
0
    img->integrity = INTEGRITY_DECODING_ERRORS;
499
0
    return;
500
0
  }
501
502
503
  // --- reference picture selection (8.5.3.3.2) ---
504
505
  // refPic[l] stays NULL when the reference picture cannot be used.
506
507
1.09M
  const de265_image* refPic[2] = { nullptr, nullptr };
508
509
3.27M
  for (int l=0;l<2;l++) {
510
2.18M
    if (!predFlag[l]) continue;
511
512
1.31M
    const de265_image* ref = ctx->get_image(shdr->RefPicList[l][vi->refIdx[l]]);
513
514
1.31M
    logtrace(LogMotion, "refIdx: %d -> dpb[%d]\n", vi->refIdx[l], shdr->RefPicList[l][vi->refIdx[l]]);
515
516
1.31M
    if (!ref || ref->PicState == UnusedForReference) {
517
0
      img->integrity = INTEGRITY_DECODING_ERRORS;
518
0
      ctx->add_warning(DE265_WARNING_NONEXISTING_REFERENCE_PICTURE_ACCESSED, false);
519
0
    }
520
1.31M
    else if (ref->get_width(0)  != sps->pic_width_in_luma_samples ||
521
1.31M
             ref->get_height(0) != sps->pic_height_in_luma_samples) {
522
0
      img->integrity = INTEGRITY_DECODING_ERRORS;
523
0
      ctx->add_warning(DE265_WARNING_REFERENCE_IMAGE_SIZE_DOES_NOT_MATCH_SPS, false);
524
0
    }
525
1.31M
    else if (img->get_bit_depth(0) != ref->get_bit_depth(0) ||
526
1.31M
             img->get_bit_depth(1) != ref->get_bit_depth(1)) {
527
0
      img->integrity = INTEGRITY_DECODING_ERRORS;
528
0
      ctx->add_warning(DE265_WARNING_REFERENCE_IMAGE_BIT_DEPTH_DOES_NOT_MATCH, false);
529
0
    }
530
1.31M
    else if (img->get_chroma_format() != ref->get_chroma_format()) {
531
0
      img->integrity = INTEGRITY_DECODING_ERRORS;
532
0
      ctx->add_warning(DE265_WARNING_REFERENCE_IMAGE_CHROMA_FORMAT_DOES_NOT_MATCH, false);
533
0
    }
534
1.31M
    else {
535
1.31M
      logtrace(LogMotion,"do MC: L%d,MV=%d;%d RefPOC=%d\n",
536
1.31M
               l,vi->mv[l].x,vi->mv[l].y,ref->PicOrderCntVal);
537
538
1.31M
      refPic[l] = ref;
539
1.31M
    }
540
1.31M
  }
541
542
543
  // --- prediction, per colour plane ---
544
545
  // Up to MC_MAX_BIT_DEPTH_INT16, the intermediate prediction samples fit
546
  // into int16_t. Above that, int32_t is needed.
547
548
1.09M
  const int nPlanes = (img->get_chroma_format() == de265_chroma_mono ? 1 : 3);
549
550
4.36M
  for (int cIdx=0;cIdx<nPlanes;cIdx++) {
551
3.27M
    if (sps->get_bit_depth(cIdx) <= MC_MAX_BIT_DEPTH_INT16) {
552
2.89M
      generate_inter_prediction_samples_plane<int16_t>(ctx,shdr,img, cIdx, xP,yP, nCS,nPbW,nPbH, vi, predFlag, refPic);
553
2.89M
    }
554
382k
    else {
555
382k
      generate_inter_prediction_samples_plane<int32_t>(ctx,shdr,img, cIdx, xP,yP, nCS,nPbW,nPbH, vi, predFlag, refPic);
556
382k
    }
557
3.27M
  }
558
1.09M
}
559
560
#ifdef DE265_LOG_TRACE
561
void logmvcand(const PBMotion& p)
562
{
563
  for (int v=0;v<2;v++) {
564
    if (p.predFlag[v]) {
565
      logtrace(LogMotion,"  %d: %s  %d;%d ref=%d\n", v, p.predFlag[v] ? "yes":"no ",
566
               p.mv[v].x,p.mv[v].y, p.refIdx[v]);
567
    } else {
568
      logtrace(LogMotion,"  %d: %s  --;-- ref=--\n", v, p.predFlag[v] ? "yes":"no ");
569
    }
570
  }
571
}
572
#else
573
#define logmvcand(p)
574
#endif
575
576
577
bool PBMotion::operator==(const PBMotion& b) const
578
277k
{
579
277k
  const PBMotion& a = *this;
580
581
  // TODO: is this really correct? no check for predFlag? Standard says so... (p.127)
582
583
704k
  for (int i=0;i<2;i++) {
584
502k
    if (a.predFlag[i] != b.predFlag[i]) return false;
585
586
478k
    if (a.predFlag[i]) {
587
316k
      if (a.mv[i].x != b.mv[i].x) return false;
588
286k
      if (a.mv[i].y != b.mv[i].y) return false;
589
270k
      if (a.refIdx[i] != b.refIdx[i]) return false;
590
270k
    }
591
478k
  }
592
593
201k
  return true;
594
277k
}
595
596
597
class MotionVectorAccess_de265_image : public MotionVectorAccess
598
{
599
public:
600
802k
  MotionVectorAccess_de265_image(const de265_image* i) : img(i) { }
601
602
802k
  enum PartMode get_PartMode(int x,int y) const override { return img->get_PartMode(x,y); }
603
758k
  const PBMotion& get_mv_info(int x,int y) const override { return img->get_mv_info(x,y); }
604
605
private:
606
  const de265_image* img;
607
};
608
609
610
611
/*
612
  +--+                +--+--+
613
  |B2|                |B1|B0|
614
  +--+----------------+--+--+
615
     |                   |
616
     |                   |
617
     |                   |
618
     |                   |
619
     |        PB         |
620
     |                   |
621
     |                   |
622
  +--+                   |
623
  |A1|                   |
624
  +--+-------------------+
625
  |A0|
626
  +--+
627
*/
628
629
630
// 8.5.3.1.2
631
// TODO: check: can we fill the candidate list directly in this function and omit to copy later
632
/*
633
  xC/yC:  CB position
634
  nCS:    CB size                 (probably modified because of singleMCLFlag)
635
  xP/yP:  PB position (absolute)  (probably modified because of singleMCLFlag)
636
  singleMCLFlag
637
  nPbW/nPbH: PB size
638
  partIdx
639
  out_cand: merging candidate vectors
640
641
  Add these candidates:
642
  - A1
643
  - B1  (if != A1)
644
  - B0  (if != B1)
645
  - A0  (if != A1)
646
  - B2  (if != A1 and != B1)
647
648
  A maximum of 4 candidates are generated.
649
650
  Note 1: For a CB split into two PBs, it does not make sense to merge the
651
  second part to the parameters of the first part, since then, we could use 2Nx2N
652
  right away. -> Exclude this candidate.
653
*/
654
int derive_spatial_merging_candidates(//const de265_image* img,
655
                                      const MotionVectorAccess& mvaccess,
656
                                      const de265_image* img,
657
                                      int xC, int yC, int nCS, int xP, int yP,
658
                                      uint8_t singleMCLFlag,
659
                                      int nPbW, int nPbH,
660
                                      int partIdx,
661
                                      PBMotion* out_cand,
662
                                      int maxCandidates)
663
802k
{
664
802k
  const pic_parameter_set* pps = &img->get_pps();
665
802k
  const int log2_parallel_merge_level = pps->log2_parallel_merge_level;
666
667
802k
  enum PartMode PartMode = mvaccess.get_PartMode(xC,yC);
668
669
  /*
670
  const int A0 = SpatialMergingCandidates::PRED_A0;
671
  const int A1 = SpatialMergingCandidates::PRED_A1;
672
  const int B0 = SpatialMergingCandidates::PRED_B0;
673
  const int B1 = SpatialMergingCandidates::PRED_B1;
674
  const int B2 = SpatialMergingCandidates::PRED_B2;
675
  */
676
677
  // --- A1 ---
678
679
  // a pixel within A1 (bottom right of A1)
680
802k
  int xA1 = xP-1;
681
802k
  int yA1 = yP+nPbH-1;
682
683
802k
  bool availableA1;
684
802k
  int idxA1;
685
686
802k
  int computed_candidates = 0;
687
688
  // check if candidate is in same motion-estimation region (MER) -> discard
689
802k
  if ((xP>>log2_parallel_merge_level) == (xA1>>log2_parallel_merge_level) &&
690
15.1k
      (yP>>log2_parallel_merge_level) == (yA1>>log2_parallel_merge_level)) {
691
12.0k
    availableA1 = false;
692
12.0k
    logtrace(LogMotion,"spatial merging candidate A1: below parallel merge level\n");
693
12.0k
  }
694
  // redundant candidate? (Note 1) -> discard
695
790k
  else if (// !singleMCLFlag &&    automatically true when partIdx==1
696
790k
           partIdx==1 &&
697
23.3k
           (PartMode==PART_Nx2N ||
698
16.8k
            PartMode==PART_nLx2N ||
699
13.0k
            PartMode==PART_nRx2N)) {
700
11.3k
    availableA1 = false;
701
11.3k
    logtrace(LogMotion,"spatial merging candidate A1: second part ignore\n");
702
11.3k
  }
703
  // MV available in A1
704
778k
  else {
705
778k
    availableA1 = img->available_pred_blk(xC,yC, nCS, xP,yP, nPbW,nPbH,partIdx, xA1,yA1);
706
778k
    if (!availableA1) logtrace(LogMotion,"spatial merging candidate A1: unavailable\n");
707
778k
  }
708
709
802k
  if (availableA1) {
710
758k
    idxA1 = computed_candidates++;
711
758k
    out_cand[idxA1] = mvaccess.get_mv_info(xA1,yA1);
712
713
758k
    logtrace(LogMotion,"spatial merging candidate A1:\n");
714
758k
    logmvcand(out_cand[idxA1]);
715
758k
  }
716
717
802k
  if (computed_candidates>=maxCandidates) return computed_candidates;
718
719
720
  // --- B1 ---
721
722
172k
  int xB1 = xP+nPbW-1;
723
172k
  int yB1 = yP-1;
724
725
172k
  bool availableB1;
726
172k
  int idxB1;
727
728
  // same MER -> discard
729
172k
  if ((xP>>log2_parallel_merge_level) == (xB1>>log2_parallel_merge_level) &&
730
135k
      (yP>>log2_parallel_merge_level) == (yB1>>log2_parallel_merge_level)) {
731
9.15k
    availableB1 = false;
732
9.15k
    logtrace(LogMotion,"spatial merging candidate B1: below parallel merge level\n");
733
9.15k
  }
734
  // redundant candidate (Note 1) -> discard
735
162k
  else if (// !singleMCLFlag &&    automatically true when partIdx==1
736
162k
           partIdx==1 &&
737
16.1k
           (PartMode==PART_2NxN ||
738
12.9k
            PartMode==PART_2NxnU ||
739
11.9k
            PartMode==PART_2NxnD)) {
740
4.52k
    availableB1 = false;
741
4.52k
    logtrace(LogMotion,"spatial merging candidate B1: second part ignore\n");
742
4.52k
  }
743
  // MV available in B1
744
158k
  else {
745
158k
    availableB1 = img->available_pred_blk(xC,yC, nCS, xP,yP, nPbW,nPbH,partIdx, xB1,yB1);
746
158k
    if (!availableB1) logtrace(LogMotion,"spatial merging candidate B1: unavailable\n");
747
158k
  }
748
749
172k
  if (availableB1) {
750
133k
    const PBMotion& b1 = img->get_mv_info(xB1,yB1);
751
752
    // B1 == A1 -> discard B1
753
133k
    if (availableA1 && out_cand[idxA1] == b1) {
754
73.5k
      idxB1 = idxA1;
755
73.5k
      logtrace(LogMotion,"spatial merging candidate B1: redundant to A1\n");
756
73.5k
    }
757
60.1k
    else {
758
60.1k
      idxB1 = computed_candidates++;
759
60.1k
      out_cand[idxB1] = b1;
760
761
60.1k
      logtrace(LogMotion,"spatial merging candidate B1:\n");
762
60.1k
      logmvcand(out_cand[idxB1]);
763
60.1k
    }
764
133k
  }
765
766
172k
  if (computed_candidates>=maxCandidates) return computed_candidates;
767
768
769
  // --- B0 ---
770
771
122k
  int xB0 = xP+nPbW;
772
122k
  int yB0 = yP-1;
773
774
122k
  bool availableB0;
775
122k
  int idxB0;
776
777
122k
  if ((xP>>log2_parallel_merge_level) == (xB0>>log2_parallel_merge_level) &&
778
7.93k
      (yP>>log2_parallel_merge_level) == (yB0>>log2_parallel_merge_level)) {
779
5.56k
    availableB0 = false;
780
5.56k
    logtrace(LogMotion,"spatial merging candidate B0: below parallel merge level\n");
781
5.56k
  }
782
117k
  else {
783
117k
    availableB0 = img->available_pred_blk(xC,yC, nCS, xP,yP, nPbW,nPbH,partIdx, xB0,yB0);
784
117k
    if (!availableB0) logtrace(LogMotion,"spatial merging candidate B0: unavailable\n");
785
117k
  }
786
787
122k
  if (availableB0) {
788
60.5k
    const PBMotion& b0 = img->get_mv_info(xB0,yB0);
789
790
    // B0 == B1 -> discard B0
791
60.5k
    if (availableB1 && out_cand[idxB1]==b0) {
792
45.3k
      idxB0 = idxB1;
793
45.3k
      logtrace(LogMotion,"spatial merging candidate B0: redundant to B1\n");
794
45.3k
    }
795
15.1k
    else {
796
15.1k
      idxB0 = computed_candidates++;
797
15.1k
      out_cand[idxB0] = b0;
798
15.1k
      logtrace(LogMotion,"spatial merging candidate B0:\n");
799
15.1k
      logmvcand(out_cand[idxB0]);
800
15.1k
    }
801
60.5k
  }
802
803
122k
  if (computed_candidates>=maxCandidates) return computed_candidates;
804
805
806
  // --- A0 ---
807
808
109k
  int xA0 = xP-1;
809
109k
  int yA0 = yP+nPbH;
810
811
109k
  bool availableA0;
812
109k
  int idxA0;
813
814
109k
  if ((xP>>log2_parallel_merge_level) == (xA0>>log2_parallel_merge_level) &&
815
10.3k
      (yP>>log2_parallel_merge_level) == (yA0>>log2_parallel_merge_level)) {
816
5.62k
    availableA0 = false;
817
5.62k
    logtrace(LogMotion,"spatial merging candidate A0: below parallel merge level\n");
818
5.62k
  }
819
103k
  else {
820
103k
    availableA0 = img->available_pred_blk(xC,yC, nCS, xP,yP, nPbW,nPbH,partIdx, xA0,yA0);
821
103k
    if (!availableA0) logtrace(LogMotion,"spatial merging candidate A0: unavailable\n");
822
103k
  }
823
824
109k
  if (availableA0) {
825
26.2k
    const PBMotion& a0 = img->get_mv_info(xA0,yA0);
826
827
    // A0 == A1 -> discard A0
828
26.2k
    if (availableA1 && out_cand[idxA1]==a0) {
829
20.4k
      idxA0 = idxA1;
830
20.4k
      logtrace(LogMotion,"spatial merging candidate A0: redundant to A1\n");
831
20.4k
    }
832
5.83k
    else {
833
5.83k
      idxA0 = computed_candidates++;
834
5.83k
      out_cand[idxA0] = a0;
835
5.83k
      logtrace(LogMotion,"spatial merging candidate A0:\n");
836
5.83k
      logmvcand(out_cand[idxA0]);
837
5.83k
    }
838
26.2k
  }
839
840
109k
  if (computed_candidates>=maxCandidates) return computed_candidates;
841
842
843
  // --- B2 ---
844
845
104k
  int xB2 = xP-1;
846
104k
  int yB2 = yP-1;
847
848
104k
  bool availableB2;
849
104k
  int idxB2;
850
851
  // if we already have four candidates, do not consider B2 anymore
852
104k
  if (computed_candidates==4) {
853
17
    availableB2 = false;
854
17
    logtrace(LogMotion,"spatial merging candidate B2: ignore\n");
855
17
  }
856
104k
  else if ((xP>>log2_parallel_merge_level) == (xB2>>log2_parallel_merge_level) &&
857
10.3k
           (yP>>log2_parallel_merge_level) == (yB2>>log2_parallel_merge_level)) {
858
7.27k
    availableB2 = false;
859
7.27k
    logtrace(LogMotion,"spatial merging candidate B2: below parallel merge level\n");
860
7.27k
  }
861
97.3k
  else {
862
97.3k
    availableB2 = img->available_pred_blk(xC,yC, nCS, xP,yP, nPbW,nPbH,partIdx, xB2,yB2);
863
97.3k
    if (!availableB2) logtrace(LogMotion,"spatial merging candidate B2: unavailable\n");
864
97.3k
  }
865
866
104k
  if (availableB2) {
867
73.3k
    const PBMotion& b2 = img->get_mv_info(xB2,yB2);
868
869
    // B2 == B1 -> discard B2
870
73.3k
    if (availableB1 && out_cand[idxB1]==b2) {
871
58.0k
      idxB2 = idxB1;
872
58.0k
      logtrace(LogMotion,"spatial merging candidate B2: redundant to B1\n");
873
58.0k
    }
874
    // B2 == A1 -> discard B2
875
15.3k
    else if (availableA1 && out_cand[idxA1]==b2) {
876
4.42k
      idxB2 = idxA1;
877
4.42k
      logtrace(LogMotion,"spatial merging candidate B2: redundant to A1\n");
878
4.42k
    }
879
10.8k
    else {
880
10.8k
      idxB2 = computed_candidates++;
881
10.8k
      out_cand[idxB2] = b2;
882
10.8k
      logtrace(LogMotion,"spatial merging candidate B2:\n");
883
10.8k
      logmvcand(out_cand[idxB2]);
884
10.8k
    }
885
73.3k
  }
886
887
104k
  return computed_candidates;
888
109k
}
889
890
891
// 8.5.3.1.4
892
void derive_zero_motion_vector_candidates(const slice_segment_header* shdr,
893
                                          PBMotion* out_mergeCandList,
894
                                          int* inout_numCurrMergeCand,
895
                                          int maxCandidates)
896
802k
{
897
802k
  logtrace(LogMotion,"derive_zero_motion_vector_candidates\n");
898
899
802k
  int numRefIdx;
900
901
802k
  if (shdr->slice_type==SLICE_TYPE_P) {
902
355k
    numRefIdx = shdr->num_ref_idx_l0_active;
903
355k
  }
904
446k
  else {
905
446k
    numRefIdx = std::min(shdr->num_ref_idx_l0_active,
906
446k
                             shdr->num_ref_idx_l1_active);
907
446k
  }
908
909
910
  //int numInputMergeCand = *inout_numMergeCand;
911
802k
  int zeroIdx = 0;
912
913
908k
  while (*inout_numCurrMergeCand < maxCandidates) {
914
    // 1.
915
916
106k
    logtrace(LogMotion,"zeroIdx:%d numRefIdx:%d\n", zeroIdx, numRefIdx);
917
918
106k
    PBMotion* newCand = &out_mergeCandList[*inout_numCurrMergeCand];
919
920
106k
    const int refIdx = (zeroIdx < numRefIdx) ? zeroIdx : 0;
921
922
106k
    if (shdr->slice_type==SLICE_TYPE_P) {
923
55.3k
      newCand->refIdx[0] = refIdx;
924
55.3k
      newCand->refIdx[1] = 0;
925
55.3k
      newCand->predFlag[0] = 1;
926
55.3k
      newCand->predFlag[1] = 0;
927
55.3k
    }
928
51.4k
    else {
929
51.4k
      newCand->refIdx[0] = refIdx;
930
51.4k
      newCand->refIdx[1] = refIdx;
931
51.4k
      newCand->predFlag[0] = 1;
932
51.4k
      newCand->predFlag[1] = 1;
933
51.4k
    }
934
935
106k
    newCand->mv[0].x = 0;
936
106k
    newCand->mv[0].y = 0;
937
106k
    newCand->mv[1].x = 0;
938
106k
    newCand->mv[1].y = 0;
939
940
106k
    (*inout_numCurrMergeCand)++;
941
942
    // 2.
943
944
106k
    zeroIdx++;
945
106k
  }
946
802k
}
947
948
949
bool scale_mv(MotionVector* out_mv, MotionVector mv, int colDist, int currDist)
950
5.07k
{
951
5.07k
  int td = Clip3(-128,127, colDist);
952
5.07k
  int tb = Clip3(-128,127, currDist);
953
954
5.07k
  if (td==0) {
955
0
    *out_mv = mv;
956
0
    return false;
957
0
  }
958
5.07k
  else {
959
5.07k
    int tx = (16384 + (std::abs(td)>>1)) / td;
960
5.07k
    int distScaleFactor = Clip3(-4096,4095, (tb*tx+32)>>6);
961
5.07k
    out_mv->x = Clip3(-32768,32767,
962
5.07k
                      Sign(distScaleFactor*mv.x)*((std::abs(distScaleFactor*mv.x)+127)>>8));
963
5.07k
    out_mv->y = Clip3(-32768,32767,
964
5.07k
                      Sign(distScaleFactor*mv.y)*((std::abs(distScaleFactor*mv.y)+127)>>8));
965
5.07k
    return true;
966
5.07k
  }
967
5.07k
}
968
969
970
// (L1003) 8.5.3.2.8
971
972
void derive_collocated_motion_vectors(base_context* ctx,
973
                                      de265_image* img,
974
                                      const slice_segment_header* shdr,
975
                                      int xP,int yP,
976
                                      int colPic,
977
                                      int xColPb,int yColPb,
978
                                      int refIdxLX,  // (always 0 for merge mode)
979
                                      int X,
980
                                      MotionVector* out_mvLXCol,
981
                                      uint8_t* out_availableFlagLXCol)
982
96.1k
{
983
96.1k
  logtrace(LogMotion,"derive_collocated_motion_vectors %d;%d\n",xP,yP);
984
985
986
  // get collocated image and the prediction mode at the collocated position
987
988
96.1k
  assert(ctx->has_image(colPic));
989
96.1k
  const de265_image* colImg = ctx->get_image(colPic);
990
991
  // check for access outside image area
992
993
96.1k
  if (xColPb >= colImg->get_width() ||
994
96.1k
      yColPb >= colImg->get_height()) {
995
0
    ctx->add_warning(DE265_WARNING_COLLOCATED_MOTION_VECTOR_OUTSIDE_IMAGE_AREA, false);
996
0
    *out_availableFlagLXCol = 0;
997
0
    return;
998
0
  }
999
1000
96.1k
  enum PredMode predMode = colImg->get_pred_mode(xColPb,yColPb);
1001
1002
1003
  // collocated block is Intra -> no collocated MV
1004
1005
96.1k
  if (predMode == MODE_INTRA) {
1006
77.2k
    out_mvLXCol->x = 0;
1007
77.2k
    out_mvLXCol->y = 0;
1008
77.2k
    *out_availableFlagLXCol = 0;
1009
77.2k
    return;
1010
77.2k
  }
1011
1012
1013
18.9k
  logtrace(LogMotion,"colPic:%d (POC=%d) X:%d refIdxLX:%d refpiclist:%d\n",
1014
18.9k
           colPic,
1015
18.9k
           colImg->PicOrderCntVal,
1016
18.9k
           X,refIdxLX,shdr->RefPicList[X][refIdxLX]);
1017
1018
1019
  // collocated reference image is unavailable -> no collocated MV
1020
1021
18.9k
  if (colImg->integrity == INTEGRITY_UNAVAILABLE_REFERENCE) {
1022
0
    out_mvLXCol->x = 0;
1023
0
    out_mvLXCol->y = 0;
1024
0
    *out_availableFlagLXCol = 0;
1025
0
    return;
1026
0
  }
1027
1028
1029
  // get the collocated MV
1030
1031
18.9k
  const PBMotion& mvi = colImg->get_mv_info(xColPb,yColPb);
1032
18.9k
  int listCol;
1033
18.9k
  int refIdxCol;
1034
18.9k
  MotionVector mvCol;
1035
1036
18.9k
  logtrace(LogMotion,"read MVI %d;%d:\n",xColPb,yColPb);
1037
18.9k
  logmvcand(mvi);
1038
1039
1040
  // collocated MV uses only L1 -> use L1
1041
18.9k
  if (mvi.predFlag[0]==0) {
1042
8.15k
    mvCol = mvi.mv[1];
1043
8.15k
    refIdxCol = mvi.refIdx[1];
1044
8.15k
    listCol = 1;
1045
8.15k
  }
1046
  // collocated MV uses only L0 -> use L0
1047
10.7k
  else if (mvi.predFlag[1]==0) {
1048
9.13k
    mvCol = mvi.mv[0];
1049
9.13k
    refIdxCol = mvi.refIdx[0];
1050
9.13k
    listCol = 0;
1051
9.13k
  }
1052
  // collocated MV uses L0 and L1
1053
1.63k
  else {
1054
1.63k
    bool allRefFramesBeforeCurrentFrame = true;
1055
1056
1.63k
    const int currentPOC = img->PicOrderCntVal;
1057
1058
    // all reference POCs earlier than current POC (list 1)
1059
    // Test L1 first, because there is a higher change to find a future reference frame.
1060
1061
7.56k
    for (int rIdx=0; rIdx<shdr->num_ref_idx_l1_active && allRefFramesBeforeCurrentFrame; rIdx++)
1062
5.93k
      {
1063
5.93k
        const de265_image* refimg = ctx->get_image(shdr->RefPicList[1][rIdx]);
1064
5.93k
        int refPOC = refimg->PicOrderCntVal;
1065
1066
5.93k
        if (refPOC > currentPOC) {
1067
555
          allRefFramesBeforeCurrentFrame = false;
1068
555
        }
1069
5.93k
      }
1070
1071
    // all reference POCs earlier than current POC (list 0)
1072
1073
4.04k
    for (int rIdx=0; rIdx<shdr->num_ref_idx_l0_active && allRefFramesBeforeCurrentFrame; rIdx++)
1074
2.41k
      {
1075
2.41k
        const de265_image* refimg = ctx->get_image(shdr->RefPicList[0][rIdx]);
1076
2.41k
        int refPOC = refimg->PicOrderCntVal;
1077
1078
2.41k
        if (refPOC > currentPOC) {
1079
124
          allRefFramesBeforeCurrentFrame = false;
1080
124
        }
1081
2.41k
      }
1082
1083
1084
    /* TODO: What is the rationale behind this ???
1085
1086
       My guess:
1087
       when there are images before the current frame (most probably in L0) and images after
1088
       the current frame (most probably in L1), we take the reference in the opposite
1089
       direction than where the collocated frame is positioned in the hope that the distance
1090
       to the current frame will be smaller and thus give a better prediction.
1091
1092
       If all references point into the past, we cannot say much about the temporal order or
1093
       L0,L1 and thus take over both parts.
1094
     */
1095
1096
1.63k
    if (allRefFramesBeforeCurrentFrame) {
1097
952
      mvCol = mvi.mv[X];
1098
952
      refIdxCol = mvi.refIdx[X];
1099
952
      listCol = X;
1100
952
    }
1101
679
    else {
1102
679
      int N = shdr->collocated_from_l0_flag;
1103
679
      mvCol = mvi.mv[N];
1104
679
      refIdxCol = mvi.refIdx[N];
1105
679
      listCol = N;
1106
679
    }
1107
1.63k
  }
1108
1109
1110
1111
18.9k
  uint16_t slice_hdr_idx = colImg->get_SliceHeaderIndex(xColPb,yColPb);
1112
18.9k
  if (slice_hdr_idx >= colImg->slices.size()) {
1113
0
    ctx->add_warning(DE265_WARNING_INVALID_SLICE_HEADER_INDEX_ACCESS, false);
1114
1115
0
    *out_availableFlagLXCol = 0;
1116
0
    out_mvLXCol->x = 0;
1117
0
    out_mvLXCol->y = 0;
1118
0
    return;
1119
0
  }
1120
1121
18.9k
  const slice_segment_header* colShdr = colImg->slices[ colImg->get_SliceHeaderIndex(xColPb,yColPb) ];
1122
1123
18.9k
  if (shdr->LongTermRefPic[X][refIdxLX] !=
1124
18.9k
      colShdr->LongTermRefPic[listCol][refIdxCol]) {
1125
5.85k
    *out_availableFlagLXCol = 0;
1126
5.85k
    out_mvLXCol->x = 0;
1127
5.85k
    out_mvLXCol->y = 0;
1128
5.85k
  }
1129
13.0k
  else {
1130
13.0k
    *out_availableFlagLXCol = 1;
1131
1132
13.0k
    const bool isLongTerm = shdr->LongTermRefPic[X][refIdxLX];
1133
1134
13.0k
    int colDist  = colImg->PicOrderCntVal - colShdr->RefPicList_POC[listCol][refIdxCol];
1135
13.0k
    int currDist = img->PicOrderCntVal - shdr->RefPicList_POC[X][refIdxLX];
1136
1137
13.0k
    logtrace(LogMotion,"COLPOCDIFF %d %d [%d %d / %d %d]\n",colDist, currDist,
1138
13.0k
             colImg->PicOrderCntVal, colShdr->RefPicList_POC[listCol][refIdxCol],
1139
13.0k
             img->PicOrderCntVal, shdr->RefPicList_POC[X][refIdxLX]
1140
13.0k
             );
1141
1142
13.0k
    if (isLongTerm || colDist == currDist) {
1143
12.5k
      *out_mvLXCol = mvCol;
1144
12.5k
    }
1145
536
    else {
1146
536
      if (!scale_mv(out_mvLXCol, mvCol, colDist, currDist)) {
1147
0
        ctx->add_warning(DE265_WARNING_INCORRECT_MOTION_VECTOR_SCALING, false);
1148
0
        img->integrity = INTEGRITY_DECODING_ERRORS;
1149
0
      }
1150
1151
536
      logtrace(LogMotion,"scale: %d;%d to %d;%d\n",
1152
536
               mvCol.x,mvCol.y, out_mvLXCol->x,out_mvLXCol->y);
1153
536
    }
1154
13.0k
  }
1155
18.9k
}
1156
1157
1158
// 8.5.3.1.7
1159
void derive_temporal_luma_vector_prediction(base_context* ctx,
1160
                                            de265_image* img,
1161
                                            const slice_segment_header* shdr,
1162
                                            int xP,int yP,
1163
                                            int nPbW,int nPbH,
1164
                                            int refIdxL,
1165
                                            int X, // which MV (L0/L1) to get
1166
                                            MotionVector* out_mvLXCol,
1167
                                            uint8_t*      out_availableFlagLXCol)
1168
299k
{
1169
  // --- no temporal MVP -> exit ---
1170
1171
299k
  if (shdr->slice_temporal_mvp_enabled_flag == 0) {
1172
243k
    out_mvLXCol->x = 0;
1173
243k
    out_mvLXCol->y = 0;
1174
243k
    *out_availableFlagLXCol = 0;
1175
243k
    return;
1176
243k
  }
1177
1178
1179
  // --- find collocated reference image ---
1180
1181
56.8k
  int Log2CtbSizeY = img->get_sps().Log2CtbSizeY;
1182
1183
56.8k
  int colPic; // TODO: this is the same for the whole slice. We can precompute it.
1184
1185
56.8k
  if (shdr->slice_type == SLICE_TYPE_B &&
1186
28.6k
      shdr->collocated_from_l0_flag == 0)
1187
8.49k
    {
1188
8.49k
      logtrace(LogMotion,"collocated L1 ref_idx=%d\n",shdr->collocated_ref_idx);
1189
1190
8.49k
      colPic = shdr->RefPicList[1][ shdr->collocated_ref_idx ];
1191
8.49k
    }
1192
48.3k
  else
1193
48.3k
    {
1194
48.3k
      logtrace(LogMotion,"collocated L0 ref_idx=%d\n",shdr->collocated_ref_idx);
1195
1196
48.3k
      colPic = shdr->RefPicList[0][ shdr->collocated_ref_idx ];
1197
48.3k
    }
1198
1199
1200
  // check whether collocated reference picture exists
1201
1202
56.8k
  if (!ctx->has_image(colPic)) {
1203
0
    out_mvLXCol->x = 0;
1204
0
    out_mvLXCol->y = 0;
1205
0
    *out_availableFlagLXCol = 0;
1206
1207
0
    ctx->add_warning(DE265_WARNING_NONEXISTING_REFERENCE_PICTURE_ACCESSED, false);
1208
0
    return;
1209
0
  }
1210
1211
1212
  // --- get collocated MV either at bottom-right corner or from center of PB ---
1213
1214
56.8k
  int xColPb,yColPb;
1215
56.8k
  int yColBr = yP + nPbH; // bottom right collocated motion vector position
1216
56.8k
  int xColBr = xP + nPbW;
1217
1218
  /* If neighboring pixel at bottom-right corner is in the same CTB-row and inside the image,
1219
     use this (reduced down to 16 pixels resolution) as collocated MV position.
1220
1221
     Note: see 2014, Sze, Sect. 5.2.1.2 why candidate C0 is excluded when on another CTB-row.
1222
     This is to reduce the memory bandwidth requirements.
1223
   */
1224
56.8k
  if ((yP>>Log2CtbSizeY) == (yColBr>>Log2CtbSizeY) &&
1225
47.6k
      xColBr < img->get_sps().pic_width_in_luma_samples &&
1226
45.9k
      yColBr < img->get_sps().pic_height_in_luma_samples)
1227
41.1k
    {
1228
41.1k
      xColPb = xColBr & ~0x0F; // reduce resolution of collocated motion-vectors to 16 pixels grid
1229
41.1k
      yColPb = yColBr & ~0x0F;
1230
1231
41.1k
      derive_collocated_motion_vectors(ctx,img,shdr, xP,yP, colPic, xColPb,yColPb, refIdxL, X,
1232
41.1k
                                       out_mvLXCol, out_availableFlagLXCol);
1233
41.1k
    }
1234
15.6k
  else
1235
15.6k
    {
1236
15.6k
      out_mvLXCol->x = 0;
1237
15.6k
      out_mvLXCol->y = 0;
1238
15.6k
      *out_availableFlagLXCol = 0;
1239
15.6k
    }
1240
1241
1242
56.8k
  if (*out_availableFlagLXCol==0) {
1243
1244
55.0k
    int xColCtr = xP+(nPbW>>1);
1245
55.0k
    int yColCtr = yP+(nPbH>>1);
1246
1247
55.0k
    xColPb = xColCtr & ~0x0F; // reduce resolution of collocated motion-vectors to 16 pixels grid
1248
55.0k
    yColPb = yColCtr & ~0x0F;
1249
1250
55.0k
    derive_collocated_motion_vectors(ctx,img,shdr, xP,yP, colPic, xColPb,yColPb, refIdxL, X,
1251
55.0k
                                     out_mvLXCol, out_availableFlagLXCol);
1252
55.0k
  }
1253
56.8k
}
1254
1255
1256
static int table_8_19[2][12] = {
1257
  { 0,1,0,2,1,2,0,3,1,3,2,3 },
1258
  { 1,0,2,0,2,1,3,0,3,1,3,2 }
1259
  };
1260
1261
// 8.5.3.1.3
1262
/* Note (TODO): during decoding, we know which of the candidates we will select.
1263
+   Hence, we do not really have to generate the other ones...
1264
+ */
1265
void derive_combined_bipredictive_merging_candidates(const base_context* ctx,
1266
                                                     const slice_segment_header* shdr,
1267
                                                     PBMotion* inout_mergeCandList,
1268
                                                     int* inout_numMergeCand,
1269
                                                     int maxCandidates)
1270
446k
{
1271
446k
  if (*inout_numMergeCand>1 && *inout_numMergeCand < maxCandidates) {
1272
4.84k
    int numOrigMergeCand = *inout_numMergeCand;
1273
1274
4.84k
    int numInputMergeCand = *inout_numMergeCand;
1275
4.84k
    int combIdx = 0;
1276
4.84k
    uint8_t combStop = false;
1277
1278
16.2k
    while (!combStop) {
1279
11.3k
      int l0CandIdx = table_8_19[0][combIdx];
1280
11.3k
      int l1CandIdx = table_8_19[1][combIdx];
1281
1282
11.3k
      if (l0CandIdx >= numInputMergeCand ||
1283
11.3k
          l1CandIdx >= numInputMergeCand) {
1284
0
        assert(false); // bitstream error -> TODO: conceal error
1285
0
      }
1286
1287
11.3k
      PBMotion& l0Cand = inout_mergeCandList[l0CandIdx];
1288
11.3k
      PBMotion& l1Cand = inout_mergeCandList[l1CandIdx];
1289
1290
11.3k
      logtrace(LogMotion,"add bipredictive merging candidate (combIdx:%d)\n",combIdx);
1291
11.3k
      logtrace(LogMotion,"l0Cand:\n"); logmvcand(l0Cand);
1292
11.3k
      logtrace(LogMotion,"l1Cand:\n"); logmvcand(l1Cand);
1293
1294
11.3k
      const de265_image* img0 = l0Cand.predFlag[0] ? ctx->get_image(shdr->RefPicList[0][l0Cand.refIdx[0]]) : nullptr;
1295
11.3k
      const de265_image* img1 = l1Cand.predFlag[1] ? ctx->get_image(shdr->RefPicList[1][l1Cand.refIdx[1]]) : nullptr;
1296
1297
11.3k
      if (l0Cand.predFlag[0] && !img0) {
1298
0
        return; // TODO error
1299
0
      }
1300
1301
11.3k
      if (l1Cand.predFlag[1] && !img1) {
1302
0
        return; // TODO error
1303
0
      }
1304
1305
11.3k
      if (l0Cand.predFlag[0] && l1Cand.predFlag[1] &&
1306
5.43k
          (img0->PicOrderCntVal != img1->PicOrderCntVal     ||
1307
4.46k
           l0Cand.mv[0].x != l1Cand.mv[1].x ||
1308
3.41k
           l0Cand.mv[0].y != l1Cand.mv[1].y)) {
1309
3.41k
        PBMotion& p = inout_mergeCandList[ *inout_numMergeCand ];
1310
3.41k
        p.refIdx[0] = l0Cand.refIdx[0];
1311
3.41k
        p.refIdx[1] = l1Cand.refIdx[1];
1312
3.41k
        p.predFlag[0] = l0Cand.predFlag[0];
1313
3.41k
        p.predFlag[1] = l1Cand.predFlag[1];
1314
3.41k
        p.mv[0] = l0Cand.mv[0];
1315
3.41k
        p.mv[1] = l1Cand.mv[1];
1316
3.41k
        (*inout_numMergeCand)++;
1317
1318
3.41k
        logtrace(LogMotion,"result:\n");
1319
3.41k
        logmvcand(p);
1320
3.41k
      }
1321
1322
11.3k
      combIdx++;
1323
11.3k
      if (combIdx == numOrigMergeCand*(numOrigMergeCand-1) ||
1324
7.80k
          *inout_numMergeCand == maxCandidates) {
1325
4.84k
        combStop = true;
1326
4.84k
      }
1327
11.3k
    }
1328
4.84k
  }
1329
446k
}
1330
1331
1332
// 8.5.3.1.1
1333
1334
void get_merge_candidate_list_without_step_9(base_context* ctx,
1335
                                             const slice_segment_header* shdr,
1336
                                             const MotionVectorAccess& mvaccess,
1337
                                             de265_image* img,
1338
                                             int xC,int yC, int xP,int yP,
1339
                                             int nCS, int nPbW,int nPbH, int partIdx,
1340
                                             int max_merge_idx,
1341
                                             PBMotion* mergeCandList)
1342
802k
{
1343
1344
  //int xOrigP = xP;
1345
  //int yOrigP = yP;
1346
  //int nOrigPbW = nPbW;
1347
  //int nOrigPbH = nPbH;
1348
1349
802k
  int singleMCLFlag; // single merge-candidate-list (MCL) flag
1350
1351
  /* Use single MCL for CBs of size 8x8, except when parallel-merge-level is at 4x4.
1352
     Without this flag, PBs smaller than 8x8 would not receive as much merging candidates.
1353
     Having additional candidates might have these advantages:
1354
     - coding MVs for these small PBs is expensive, and
1355
     - since the PBs are not far away from a proper (neighboring) merging candidate,
1356
     the quality of the candidates will still be good.
1357
  */
1358
802k
  singleMCLFlag = (img->get_pps().log2_parallel_merge_level > 2 && nCS==8);
1359
1360
802k
  if (singleMCLFlag) {
1361
639k
    xP=xC;
1362
639k
    yP=yC;
1363
639k
    nPbW=nCS;
1364
639k
    nPbH=nCS;
1365
639k
    partIdx=0;
1366
639k
  }
1367
1368
802k
  int maxCandidates = max_merge_idx+1;
1369
  //MotionVectorSpec mergeCandList[5];
1370
802k
  int numMergeCand=0;
1371
1372
  // --- spatial merge candidates
1373
1374
802k
  numMergeCand = derive_spatial_merging_candidates(mvaccess,
1375
802k
                                                   img, xC,yC, nCS, xP,yP, singleMCLFlag,
1376
802k
                                                   nPbW,nPbH,partIdx, mergeCandList,
1377
802k
                                                   maxCandidates);
1378
1379
  // --- collocated merge candidate
1380
802k
  if (numMergeCand < maxCandidates) {
1381
95.3k
    int refIdxCol[2] = { 0,0 };
1382
1383
95.3k
    MotionVector mvCol[2];
1384
95.3k
    uint8_t predFlagLCol[2];
1385
95.3k
    derive_temporal_luma_vector_prediction(ctx,img,shdr, xP,yP,nPbW,nPbH,
1386
95.3k
                                           refIdxCol[0],0, &mvCol[0],
1387
95.3k
                                           &predFlagLCol[0]);
1388
1389
95.3k
    uint8_t availableFlagCol = predFlagLCol[0];
1390
95.3k
    predFlagLCol[1] = 0;
1391
1392
95.3k
    if (shdr->slice_type == SLICE_TYPE_B) {
1393
40.7k
      derive_temporal_luma_vector_prediction(ctx,img,shdr,
1394
40.7k
                                             xP,yP,nPbW,nPbH, refIdxCol[1],1, &mvCol[1],
1395
40.7k
                                             &predFlagLCol[1]);
1396
40.7k
      availableFlagCol |= predFlagLCol[1];
1397
40.7k
    }
1398
1399
1400
95.3k
    if (availableFlagCol) {
1401
7.20k
      PBMotion* colVec = &mergeCandList[numMergeCand++];
1402
1403
7.20k
      colVec->mv[0] = mvCol[0];
1404
7.20k
      colVec->mv[1] = mvCol[1];
1405
7.20k
      colVec->predFlag[0] = predFlagLCol[0];
1406
7.20k
      colVec->predFlag[1] = predFlagLCol[1];
1407
7.20k
      colVec->refIdx[0] = refIdxCol[0];
1408
7.20k
      colVec->refIdx[1] = refIdxCol[1];
1409
7.20k
    }
1410
95.3k
  }
1411
1412
1413
  // --- bipredictive merge candidates ---
1414
1415
802k
  if (shdr->slice_type == SLICE_TYPE_B) {
1416
446k
    derive_combined_bipredictive_merging_candidates(ctx, shdr,
1417
446k
                                                    mergeCandList, &numMergeCand, maxCandidates);
1418
446k
  }
1419
1420
1421
  // --- zero-vector merge candidates ---
1422
1423
802k
  derive_zero_motion_vector_candidates(shdr, mergeCandList, &numMergeCand, maxCandidates);
1424
1425
1426
802k
  logtrace(LogMotion,"mergeCandList:\n");
1427
3.72M
  for (int i=0;i<shdr->MaxNumMergeCand;i++)
1428
2.92M
    {
1429
      //logtrace(LogMotion, " %d:%s\n", i, i==merge_idx ? " SELECTED":"");
1430
2.92M
      logmvcand(mergeCandList[i]);
1431
2.92M
    }
1432
802k
}
1433
1434
1435
1436
void get_merge_candidate_list(base_context* ctx,
1437
                              const slice_segment_header* shdr,
1438
                              de265_image* img,
1439
                              int xC,int yC, int xP,int yP,
1440
                              int nCS, int nPbW,int nPbH, int partIdx,
1441
                              PBMotion* mergeCandList)
1442
0
{
1443
0
  int max_merge_idx = 5-shdr->five_minus_max_num_merge_cand -1;
1444
1445
0
  get_merge_candidate_list_without_step_9(ctx, shdr,
1446
0
                                          MotionVectorAccess_de265_image(img), img,
1447
0
                                          xC,yC,xP,yP,nCS,nPbW,nPbH, partIdx,
1448
0
                                          max_merge_idx, mergeCandList);
1449
1450
  // 9. for encoder: modify all merge candidates
1451
1452
0
  for (int i=0;i<=max_merge_idx;i++) {
1453
0
    if (mergeCandList[i].predFlag[0] &&
1454
0
        mergeCandList[i].predFlag[1] &&
1455
0
        nPbW+nPbH==12)
1456
0
      {
1457
0
        mergeCandList[i].refIdx[1]   = 0;
1458
0
        mergeCandList[i].predFlag[1] = 0;
1459
0
      }
1460
0
  }
1461
0
}
1462
1463
1464
void derive_luma_motion_merge_mode(base_context* ctx,
1465
                                   const slice_segment_header* shdr,
1466
                                   de265_image* img,
1467
                                   int xC,int yC, int xP,int yP,
1468
                                   int nCS, int nPbW,int nPbH, int partIdx,
1469
                                   int merge_idx,
1470
                                   PBMotion* out_vi)
1471
802k
{
1472
802k
  PBMotion mergeCandList[5];
1473
1474
802k
  get_merge_candidate_list_without_step_9(ctx, shdr,
1475
802k
                                          MotionVectorAccess_de265_image(img), img,
1476
802k
                                          xC,yC,xP,yP,nCS,nPbW,nPbH, partIdx,
1477
802k
                                          merge_idx, mergeCandList);
1478
1479
1480
802k
  *out_vi = mergeCandList[merge_idx];
1481
1482
  // 8.5.3.1.1 / 9.
1483
1484
802k
  if (out_vi->predFlag[0] && out_vi->predFlag[1] && nPbW+nPbH==12) {
1485
20.9k
    out_vi->refIdx[1] = 0;
1486
20.9k
    out_vi->predFlag[1] = 0;
1487
20.9k
  }
1488
802k
}
1489
1490
1491
// 8.5.3.1.6
1492
void derive_spatial_luma_vector_prediction(base_context* ctx,
1493
                                           de265_image* img,
1494
                                           const slice_segment_header* shdr,
1495
                                           int xC,int yC,int nCS,int xP,int yP,
1496
                                           int nPbW,int nPbH, int X,
1497
                                           int refIdxLX, int partIdx,
1498
                                           uint8_t out_availableFlagLXN[2],
1499
                                           MotionVector out_mvLXN[2])
1500
331k
{
1501
331k
  if (refIdxLX >= MAX_NUM_REF_PICS) {
1502
0
    ctx->add_warning(DE265_WARNING_INCORRECT_MOTION_VECTOR_SCALING, false);
1503
0
    img->integrity = INTEGRITY_DECODING_ERRORS;
1504
1505
0
    out_availableFlagLXN[0] = false;
1506
0
    out_availableFlagLXN[1] = false;
1507
0
    out_mvLXN[0] = MotionVector();
1508
0
    out_mvLXN[1] = MotionVector();
1509
0
    return;
1510
0
  }
1511
1512
331k
  int isScaledFlagLX = 0;
1513
1514
331k
  const int A=0;
1515
331k
  const int B=1;
1516
1517
331k
  out_availableFlagLXN[A] = 0;
1518
331k
  out_availableFlagLXN[B] = 0;
1519
1520
1521
  // --- A ---
1522
1523
  // 1.
1524
1525
331k
  int xA[2], yA[2];
1526
331k
  xA[0] = xP-1;
1527
331k
  yA[0] = yP + nPbH;
1528
331k
  xA[1] = xA[0];
1529
331k
  yA[1] = yA[0]-1;
1530
1531
  // 2.
1532
1533
331k
  out_availableFlagLXN[A] = 0;
1534
331k
  out_mvLXN[A].x = 0;
1535
331k
  out_mvLXN[A].y = 0;
1536
1537
  // 3. / 4.
1538
1539
331k
  bool availableA[2];
1540
331k
  availableA[0] = img->available_pred_blk(xC,yC, nCS, xP,yP, nPbW,nPbH,partIdx, xA[0],yA[0]);
1541
331k
  availableA[1] = img->available_pred_blk(xC,yC, nCS, xP,yP, nPbW,nPbH,partIdx, xA[1],yA[1]);
1542
1543
  // 5.
1544
1545
331k
  if (availableA[0] || availableA[1]) {
1546
319k
    isScaledFlagLX = 1;
1547
319k
  }
1548
1549
  // 6.  test A0 and A1  (Ak)
1550
1551
331k
  int refIdxA=-1;
1552
1553
  // the POC we want to reference in this PB
1554
331k
  const de265_image* tmpimg = ctx->get_image(shdr->RefPicList[X][ refIdxLX ]);
1555
331k
  if (tmpimg==nullptr) { return; }
1556
331k
  const int referenced_POC = tmpimg->PicOrderCntVal;
1557
1558
993k
  for (int k=0;k<=1;k++) {
1559
1560
662k
    if (availableA[k] &&
1561
420k
        out_availableFlagLXN[A]==0 && // no A?-predictor so far
1562
321k
        img->get_pred_mode(xA[k],yA[k]) != MODE_INTRA) {
1563
1564
321k
      int Y=1-X;
1565
1566
321k
      const PBMotion& vi = img->get_mv_info(xA[k],yA[k]);
1567
321k
      logtrace(LogMotion,"MVP A%d=\n",k);
1568
321k
      logmvcand(vi);
1569
1570
321k
      const de265_image* imgX = nullptr;
1571
321k
      if (vi.predFlag[X]) {
1572
308k
        imgX = ctx->get_image(shdr->RefPicList[X][ vi.refIdx[X] ]);
1573
308k
      }
1574
1575
321k
      const de265_image* imgY = nullptr;
1576
321k
      if (vi.predFlag[Y]) {
1577
93.6k
        imgY = ctx->get_image(shdr->RefPicList[Y][ vi.refIdx[Y] ]);
1578
93.6k
      }
1579
1580
      // check whether the predictor X is available and references the same POC
1581
321k
      if (vi.predFlag[X] && imgX && imgX->PicOrderCntVal == referenced_POC) {
1582
1583
304k
        logtrace(LogMotion,"take A%d/L%d as A candidate with same POC\n",k,X);
1584
1585
304k
        out_availableFlagLXN[A]=1;
1586
304k
        out_mvLXN[A] = vi.mv[X];
1587
304k
        refIdxA = vi.refIdx[X];
1588
304k
      }
1589
      // check whether the other predictor (Y) is available and references the same POC
1590
16.5k
      else if (vi.predFlag[Y] && imgY && imgY->PicOrderCntVal == referenced_POC) {
1591
1592
8.72k
        logtrace(LogMotion,"take A%d/L%d as A candidate with same POC\n",k,Y);
1593
1594
8.72k
        out_availableFlagLXN[A]=1;
1595
8.72k
        out_mvLXN[A] = vi.mv[Y];
1596
8.72k
        refIdxA = vi.refIdx[Y];
1597
8.72k
      }
1598
321k
    }
1599
662k
  }
1600
1601
  // 7. If there is no predictor referencing the same POC, we take any other reference as
1602
  //    long as it is the same type of reference (long-term / short-term)
1603
1604
364k
  for (int k=0 ; k<=1 && out_availableFlagLXN[A]==0 ; k++) {
1605
33.6k
    int refPicList=-1;
1606
1607
33.6k
    if (availableA[k] &&
1608
        // TODO: we could remove this call by storing the result of the similar computation above
1609
5.56k
        img->get_pred_mode(xA[k],yA[k]) != MODE_INTRA) {
1610
1611
5.56k
      int Y=1-X;
1612
1613
5.56k
      const PBMotion& vi = img->get_mv_info(xA[k],yA[k]);
1614
5.56k
      if (vi.predFlag[X]==1 &&
1615
2.42k
          shdr->LongTermRefPic[X][refIdxLX] == shdr->LongTermRefPic[X][ vi.refIdx[X] ]) {
1616
1617
2.18k
        logtrace(LogMotion,"take A%D/L%d as A candidate with different POCs\n",k,X);
1618
1619
2.18k
        out_availableFlagLXN[A]=1;
1620
2.18k
        out_mvLXN[A] = vi.mv[X];
1621
2.18k
        refIdxA = vi.refIdx[X];
1622
2.18k
        refPicList = X;
1623
2.18k
      }
1624
3.38k
      else if (vi.predFlag[Y]==1 &&
1625
3.20k
               shdr->LongTermRefPic[X][refIdxLX] == shdr->LongTermRefPic[Y][ vi.refIdx[Y] ]) {
1626
1627
3.02k
        logtrace(LogMotion,"take A%d/L%d as A candidate with different POCs\n",k,Y);
1628
1629
3.02k
        out_availableFlagLXN[A]=1;
1630
3.02k
        out_mvLXN[A] = vi.mv[Y];
1631
3.02k
        refIdxA = vi.refIdx[Y];
1632
3.02k
        refPicList = Y;
1633
3.02k
      }
1634
5.56k
    }
1635
1636
33.6k
    if (out_availableFlagLXN[A]==1) {
1637
5.21k
      if (refIdxA<0) {
1638
0
        out_availableFlagLXN[0] = out_availableFlagLXN[1] = false;
1639
0
        return; // error
1640
0
      }
1641
1642
5.21k
      assert(refIdxA>=0);
1643
5.21k
      assert(refPicList>=0);
1644
1645
5.21k
      const de265_image* refPicA = ctx->get_image(shdr->RefPicList[refPicList][refIdxA ]);
1646
1647
#ifdef DE265_LOG_TRACE
1648
      const de265_image* refPicX = ctx->get_image(shdr->RefPicList[X][refIdxLX]);
1649
#endif
1650
1651
      //int picStateA = shdr->RefPicList_PicState[refPicList][refIdxA ];
1652
      //int picStateX = shdr->RefPicList_PicState[X         ][refIdxLX];
1653
1654
5.21k
      int isLongTermA = shdr->LongTermRefPic[refPicList][refIdxA ];
1655
5.21k
      int isLongTermX = shdr->LongTermRefPic[X         ][refIdxLX];
1656
1657
5.21k
      logtrace(LogMotion,"scale MVP A: A-POC:%d X-POC:%d\n",
1658
5.21k
               refPicA->PicOrderCntVal,refPicX->PicOrderCntVal);
1659
1660
5.21k
      if (!isLongTermA && !isLongTermX)
1661
      /*
1662
      if (picStateA == UsedForShortTermReference &&
1663
          picStateX == UsedForShortTermReference)
1664
      */
1665
4.06k
        {
1666
4.06k
          int distA = img->PicOrderCntVal - refPicA->PicOrderCntVal;
1667
4.06k
          int distX = img->PicOrderCntVal - referenced_POC;
1668
1669
4.06k
          if (!scale_mv(&out_mvLXN[A], out_mvLXN[A], distA, distX)) {
1670
0
            ctx->add_warning(DE265_WARNING_INCORRECT_MOTION_VECTOR_SCALING, false);
1671
0
            img->integrity = INTEGRITY_DECODING_ERRORS;
1672
0
          }
1673
4.06k
        }
1674
5.21k
    }
1675
33.6k
  }
1676
1677
  // --- B ---
1678
1679
  // 1.
1680
1681
331k
  int xB[3], yB[3];
1682
331k
  xB[0] = xP+nPbW;
1683
331k
  yB[0] = yP-1;
1684
331k
  xB[1] = xB[0]-1;
1685
331k
  yB[1] = yP-1;
1686
331k
  xB[2] = xP-1;
1687
331k
  yB[2] = yP-1;
1688
1689
  // 2.
1690
1691
331k
  out_availableFlagLXN[B] = 0;
1692
331k
  out_mvLXN[B].x = 0;
1693
331k
  out_mvLXN[B].y = 0;
1694
1695
  // 3. test B0,B1,B2 (Bk)
1696
1697
331k
  int refIdxB=-1;
1698
1699
331k
  bool availableB[3];
1700
1.32M
  for (int k=0;k<3;k++) {
1701
993k
    availableB[k] = img->available_pred_blk(xC,yC, nCS, xP,yP, nPbW,nPbH,partIdx, xB[k],yB[k]);
1702
1703
993k
    if (availableB[k] && out_availableFlagLXN[B]==0) {
1704
1705
264k
      int Y=1-X;
1706
1707
264k
      const PBMotion& vi = img->get_mv_info(xB[k],yB[k]);
1708
264k
      logtrace(LogMotion,"MVP B%d=\n",k);
1709
264k
      logmvcand(vi);
1710
1711
264k
      const de265_image* imgX = nullptr;
1712
264k
      if (vi.predFlag[X]) {
1713
254k
        imgX = ctx->get_image(shdr->RefPicList[X][ vi.refIdx[X] ]);
1714
254k
      }
1715
1716
264k
      const de265_image* imgY = nullptr;
1717
264k
      if (vi.predFlag[Y]) {
1718
71.0k
        imgY = ctx->get_image(shdr->RefPicList[Y][ vi.refIdx[Y] ]);
1719
71.0k
      }
1720
1721
264k
      if (vi.predFlag[X] && imgX && imgX->PicOrderCntVal == referenced_POC) {
1722
249k
        logtrace(LogMotion,"a) take B%d/L%d as B candidate with same POC\n",k,X);
1723
1724
249k
        out_availableFlagLXN[B]=1;
1725
249k
        out_mvLXN[B] = vi.mv[X];
1726
249k
        refIdxB = vi.refIdx[X];
1727
249k
      }
1728
14.9k
      else if (vi.predFlag[Y] && imgY && imgY->PicOrderCntVal == referenced_POC) {
1729
6.21k
        logtrace(LogMotion,"b) take B%d/L%d as B candidate with same POC\n",k,Y);
1730
1731
6.21k
        out_availableFlagLXN[B]=1;
1732
6.21k
        out_mvLXN[B] = vi.mv[Y];
1733
6.21k
        refIdxB = vi.refIdx[Y];
1734
6.21k
      }
1735
264k
    }
1736
993k
  }
1737
1738
  // 4.
1739
1740
331k
  if (isScaledFlagLX==0 &&      // no A predictor,
1741
12.0k
      out_availableFlagLXN[B])  // but an unscaled B predictor
1742
8.91k
    {
1743
      // use unscaled B predictor as A predictor
1744
1745
8.91k
      logtrace(LogMotion,"copy the same-POC B candidate as additional A candidate\n");
1746
1747
8.91k
      out_availableFlagLXN[A]=1;
1748
8.91k
      out_mvLXN[A] = out_mvLXN[B];
1749
8.91k
      refIdxA = refIdxB;
1750
8.91k
    }
1751
1752
  // 5.
1753
1754
  // If no A predictor, we output the unscaled B as the A predictor (above)
1755
  // and also add a scaled B predictor here.
1756
  // If there is (probably) an A predictor, no differing-POC B predictor is generated.
1757
331k
  if (isScaledFlagLX==0) {
1758
12.0k
    out_availableFlagLXN[B]=0;
1759
1760
32.8k
    for (int k=0 ; k<=2 && out_availableFlagLXN[B]==0 ; k++) {
1761
20.7k
      int refPicList=-1;
1762
1763
20.7k
      if (availableB[k]) {
1764
9.46k
        int Y=1-X;
1765
1766
9.46k
        const PBMotion& vi = img->get_mv_info(xB[k],yB[k]);
1767
1768
9.46k
        if (vi.predFlag[X]==1 &&
1769
8.34k
            shdr->LongTermRefPic[X][refIdxLX] == shdr->LongTermRefPic[X][ vi.refIdx[X] ]) {
1770
8.26k
          out_availableFlagLXN[B]=1;
1771
8.26k
          out_mvLXN[B] = vi.mv[X];
1772
8.26k
          refIdxB = vi.refIdx[X];
1773
8.26k
          refPicList = X;
1774
8.26k
        }
1775
1.20k
        else if (vi.predFlag[Y]==1 &&
1776
1.13k
                 shdr->LongTermRefPic[X][refIdxLX] == shdr->LongTermRefPic[Y][ vi.refIdx[Y] ]) {
1777
1.08k
          out_availableFlagLXN[B]=1;
1778
1.08k
          out_mvLXN[B] = vi.mv[Y];
1779
1.08k
          refIdxB = vi.refIdx[Y];
1780
1.08k
          refPicList = Y;
1781
1.08k
        }
1782
9.46k
      }
1783
1784
20.7k
      if (out_availableFlagLXN[B]==1) {
1785
9.35k
        if (refIdxB<0) {
1786
0
          out_availableFlagLXN[0] = out_availableFlagLXN[1] = false;
1787
0
          return; // error
1788
0
        }
1789
1790
9.35k
        assert(refPicList>=0);
1791
9.35k
        assert(refIdxB>=0);
1792
1793
9.35k
        const de265_image* refPicB=ctx->get_image(shdr->RefPicList[refPicList][refIdxB ]);
1794
9.35k
        const de265_image* refPicX=ctx->get_image(shdr->RefPicList[X         ][refIdxLX]);
1795
1796
9.35k
        int isLongTermB = shdr->LongTermRefPic[refPicList][refIdxB ];
1797
9.35k
        int isLongTermX = shdr->LongTermRefPic[X         ][refIdxLX];
1798
1799
9.35k
        if (refPicB==nullptr || refPicX==nullptr) {
1800
0
          img->decctx->add_warning(DE265_WARNING_NONEXISTING_REFERENCE_PICTURE_ACCESSED,false);
1801
0
          img->integrity = INTEGRITY_DECODING_ERRORS;
1802
0
        }
1803
9.35k
        else if (refPicB->PicOrderCntVal != refPicX->PicOrderCntVal &&
1804
567
                 !isLongTermB && !isLongTermX) {
1805
472
          int distB = img->PicOrderCntVal - refPicB->PicOrderCntVal;
1806
472
          int distX = img->PicOrderCntVal - referenced_POC;
1807
1808
472
          logtrace(LogMotion,"scale MVP B: B-POC:%d X-POC:%d\n",refPicB->PicOrderCntVal,refPicX->PicOrderCntVal);
1809
1810
472
          if (!scale_mv(&out_mvLXN[B], out_mvLXN[B], distB, distX)) {
1811
0
            ctx->add_warning(DE265_WARNING_INCORRECT_MOTION_VECTOR_SCALING, false);
1812
0
            img->integrity = INTEGRITY_DECODING_ERRORS;
1813
0
          }
1814
472
        }
1815
9.35k
      }
1816
20.7k
    }
1817
12.0k
  }
1818
331k
}
1819
1820
1821
// 8.5.3.1.5
1822
void fill_luma_motion_vector_predictors(base_context* ctx,
1823
                                        const slice_segment_header* shdr,
1824
                                        de265_image* img,
1825
                                        int xC,int yC,int nCS,int xP,int yP,
1826
                                        int nPbW,int nPbH, int l,
1827
                                        int refIdx, int partIdx,
1828
                                        MotionVector out_mvpList[2])
1829
331k
{
1830
  // 8.5.3.1.6: derive two spatial vector predictors A (0) and B (1)
1831
1832
331k
  uint8_t availableFlagLXN[2];
1833
331k
  MotionVector mvLXN[2];
1834
1835
331k
  derive_spatial_luma_vector_prediction(ctx, img, shdr, xC,yC, nCS, xP,yP,
1836
331k
                                        nPbW,nPbH, l, refIdx, partIdx,
1837
331k
                                        availableFlagLXN, mvLXN);
1838
1839
  // 8.5.3.1.7: if we only have one spatial vector or both spatial vectors are the same,
1840
  // derive a temporal predictor
1841
1842
331k
  uint8_t availableFlagLXCol;
1843
331k
  MotionVector mvLXCol;
1844
1845
1846
331k
  if (availableFlagLXN[0] &&
1847
327k
      availableFlagLXN[1] &&
1848
255k
      (mvLXN[0].x != mvLXN[1].x || mvLXN[0].y != mvLXN[1].y)) {
1849
167k
    availableFlagLXCol = 0;
1850
167k
  }
1851
163k
  else {
1852
163k
    derive_temporal_luma_vector_prediction(ctx, img, shdr,
1853
163k
                                           xP,yP, nPbW,nPbH, refIdx,l,
1854
163k
                                           &mvLXCol, &availableFlagLXCol);
1855
163k
  }
1856
1857
1858
  // --- build candidate vector list with exactly two entries ---
1859
1860
331k
  int numMVPCandLX=0;
1861
1862
  // spatial predictor A
1863
1864
331k
  if (availableFlagLXN[0])
1865
327k
    {
1866
327k
      out_mvpList[numMVPCandLX++] = mvLXN[0];
1867
327k
    }
1868
1869
  // spatial predictor B (if not same as A)
1870
1871
331k
  if (availableFlagLXN[1] &&
1872
255k
      (!availableFlagLXN[0] || // in case A in not available, but mvLXA initialized to same as mvLXB
1873
255k
       (mvLXN[0].x != mvLXN[1].x || mvLXN[0].y != mvLXN[1].y)))
1874
168k
    {
1875
168k
      out_mvpList[numMVPCandLX++] = mvLXN[1];
1876
168k
    }
1877
1878
  // temporal predictor
1879
1880
331k
  if (availableFlagLXCol)
1881
5.25k
    {
1882
5.25k
      out_mvpList[numMVPCandLX++] = mvLXCol;
1883
5.25k
    }
1884
1885
  // fill with zero predictors
1886
1887
492k
  while (numMVPCandLX<2) {
1888
161k
    out_mvpList[numMVPCandLX].x = 0;
1889
161k
    out_mvpList[numMVPCandLX].y = 0;
1890
161k
    numMVPCandLX++;
1891
161k
  }
1892
1893
1894
331k
  assert(numMVPCandLX==2);
1895
331k
}
1896
1897
1898
MotionVector luma_motion_vector_prediction(base_context* ctx,
1899
                                           const slice_segment_header* shdr,
1900
                                           de265_image* img,
1901
                                           const PBMotionCoding& motion,
1902
                                           int xC,int yC,int nCS,int xP,int yP,
1903
                                           int nPbW,int nPbH, int l,
1904
                                           int refIdx, int partIdx)
1905
331k
{
1906
331k
  MotionVector mvpList[2];
1907
1908
331k
  fill_luma_motion_vector_predictors(ctx, shdr, img,
1909
331k
                                     xC,yC,nCS,xP,yP,
1910
331k
                                     nPbW, nPbH, l, refIdx, partIdx,
1911
331k
                                     mvpList);
1912
1913
  // select predictor according to mvp_lX_flag
1914
1915
331k
  return mvpList[ l ? motion.mvp_l1_flag : motion.mvp_l0_flag ];
1916
331k
}
1917
1918
1919
#if DE265_LOG_TRACE
1920
void logMV(int x0,int y0,int nPbW,int nPbH, const char* mode,const PBMotion* mv)
1921
{
1922
  int pred0 = mv->predFlag[0];
1923
  int pred1 = mv->predFlag[1];
1924
1925
  logtrace(LogMotion,
1926
           "*MV %d;%d [%d;%d] %s: (%d) %d;%d @%d   (%d) %d;%d @%d\n", x0,y0,nPbW,nPbH,mode,
1927
           pred0,
1928
           pred0 ? mv->mv[0].x : 0,pred0 ? mv->mv[0].y : 0, pred0 ? mv->refIdx[0] : 0,
1929
           pred1,
1930
           pred1 ? mv->mv[1].x : 0,pred1 ? mv->mv[1].y : 0, pred1 ? mv->refIdx[1] : 0);
1931
}
1932
#else
1933
#define logMV(x0,y0,nPbW,nPbH,mode,mv)
1934
#endif
1935
1936
1937
1938
// 8.5.3.1
1939
void motion_vectors_and_ref_indices(base_context* ctx,
1940
                                    const slice_segment_header* shdr,
1941
                                    de265_image* img,
1942
                                    const PBMotionCoding& motion,
1943
                                    int xC,int yC, int xB,int yB, int nCS, int nPbW,int nPbH,
1944
                                    int partIdx,
1945
                                    PBMotion* out_vi)
1946
1.09M
{
1947
  //slice_segment_header* shdr = tctx->shdr;
1948
1949
1.09M
  int xP = xC+xB;
1950
1.09M
  int yP = yC+yB;
1951
1952
1.09M
  enum PredMode predMode = img->get_pred_mode(xC,yC);
1953
1954
1.09M
  if (predMode == MODE_SKIP ||
1955
568k
      (predMode == MODE_INTER && motion.merge_flag))
1956
802k
    {
1957
802k
      derive_luma_motion_merge_mode(ctx,shdr,img,
1958
802k
                                    xC,yC, xP,yP, nCS,nPbW,nPbH, partIdx,
1959
802k
                                    motion.merge_idx, out_vi);
1960
1961
802k
      logMV(xP,yP,nPbW,nPbH, "merge_mode", out_vi);
1962
802k
    }
1963
289k
  else {
1964
289k
    int mvdL[2][2];
1965
289k
    MotionVector mvpL[2];
1966
1967
867k
    for (int l=0;l<2;l++) {
1968
      // 1.
1969
1970
578k
      enum InterPredIdc inter_pred_idc = (enum InterPredIdc)motion.inter_pred_idc;
1971
1972
578k
      if (inter_pred_idc == PRED_BI ||
1973
494k
          (inter_pred_idc == PRED_L0 && l==0) ||
1974
331k
          (inter_pred_idc == PRED_L1 && l==1)) {
1975
331k
        out_vi->refIdx[l] = motion.refIdx[l];
1976
331k
        out_vi->predFlag[l] = 1;
1977
331k
      }
1978
247k
      else {
1979
247k
        out_vi->refIdx[l] = 0;
1980
247k
        out_vi->predFlag[l] = 0;
1981
247k
      }
1982
1983
      // 2.
1984
1985
578k
      mvdL[l][0] = motion.mvd[l][0];
1986
578k
      mvdL[l][1] = motion.mvd[l][1];
1987
1988
1989
578k
      if (out_vi->predFlag[l]) {
1990
        // 3.
1991
1992
331k
        mvpL[l] = luma_motion_vector_prediction(ctx,shdr,img,motion,
1993
331k
                                                xC,yC,nCS,xP,yP, nPbW,nPbH, l,
1994
331k
                                                out_vi->refIdx[l], partIdx);
1995
1996
        // 4.
1997
1998
331k
        int32_t x = (mvpL[l].x + mvdL[l][0] + 0x10000) & 0xFFFF;
1999
331k
        int32_t y = (mvpL[l].y + mvdL[l][1] + 0x10000) & 0xFFFF;
2000
2001
331k
        out_vi->mv[l].x = (x>=0x8000) ? x-0x10000 : x;
2002
331k
        out_vi->mv[l].y = (y>=0x8000) ? y-0x10000 : y;
2003
331k
      }
2004
578k
    }
2005
2006
289k
    logMV(xP,yP,nPbW,nPbH, "mvp", out_vi);
2007
289k
  }
2008
1.09M
}
2009
2010
2011
// 8.5.3
2012
2013
/* xC/yC : CB position
2014
   xB/yB : position offset of the PB
2015
   nPbW/nPbH : size of PB
2016
   nCS   : CB size
2017
 */
2018
void decode_prediction_unit(base_context* ctx,
2019
                            const slice_segment_header* shdr,
2020
                            de265_image* img,
2021
                            const PBMotionCoding& motion,
2022
                            int xC,int yC, int xB,int yB, int nCS, int nPbW,int nPbH, int partIdx)
2023
1.09M
{
2024
1.09M
  logtrace(LogMotion,"decode_prediction_unit POC=%d %d;%d %dx%d\n",
2025
1.09M
           img->PicOrderCntVal, xC+xB,yC+yB, nPbW,nPbH);
2026
2027
  //slice_segment_header* shdr = tctx->shdr;
2028
2029
  // 1.
2030
2031
1.09M
  PBMotion vi;
2032
1.09M
  motion_vectors_and_ref_indices(ctx, shdr, img, motion,
2033
1.09M
                                 xC,yC, xB,yB, nCS, nPbW,nPbH, partIdx, &vi);
2034
2035
  // 2.
2036
2037
1.09M
  generate_inter_prediction_samples(ctx,shdr, img, xC,yC, xB,yB, nCS, nPbW,nPbH, &vi);
2038
2039
2040
1.09M
  img->set_mv_info(xC+xB,yC+yB,nPbW,nPbH, vi);
2041
1.09M
}