/src/libde265/libde265/scan.cc
Line | Count | Source (jump to first uncovered line) |
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 "scan.h" |
22 | | |
23 | | static position scan0 = { 0,0 }; |
24 | | static position scan_h_1[ 2* 2], scan_v_1[ 2* 2], scan_d_1[ 2* 2]; |
25 | | static position scan_h_2[ 4* 4], scan_v_2[ 4* 4], scan_d_2[ 4* 4]; |
26 | | static position scan_h_3[ 8* 8], scan_v_3[ 8* 8], scan_d_3[ 8* 8]; |
27 | | static position scan_h_4[16*16], scan_v_4[16*16], scan_d_4[16*16]; |
28 | | static position scan_h_5[32*32], scan_v_5[32*32], scan_d_5[32*32]; |
29 | | |
30 | | static position* scan_h[7] = { &scan0,scan_h_1,scan_h_2,scan_h_3,scan_h_4,scan_h_5 }; |
31 | | static position* scan_v[7] = { &scan0,scan_v_1,scan_v_2,scan_v_3,scan_v_4,scan_v_5 }; |
32 | | static position* scan_d[7] = { &scan0,scan_d_1,scan_d_2,scan_d_3,scan_d_4,scan_d_5 }; |
33 | | |
34 | | static void init_scan_h(position* scan, int blkSize) |
35 | 1.46k | { |
36 | 1.46k | int i=0; |
37 | 19.5k | for (int y=0;y<blkSize;y++) |
38 | 416k | for (int x=0;x<blkSize;x++) |
39 | 398k | { |
40 | 398k | scan[i].x = x; |
41 | 398k | scan[i].y = y; |
42 | 398k | i++; |
43 | 398k | } |
44 | 1.46k | } |
45 | | |
46 | | static void init_scan_v(position* scan, int blkSize) |
47 | 1.46k | { |
48 | 1.46k | int i=0; |
49 | 19.5k | for (int x=0;x<blkSize;x++) |
50 | 416k | for (int y=0;y<blkSize;y++) |
51 | 398k | { |
52 | 398k | scan[i].x = x; |
53 | 398k | scan[i].y = y; |
54 | 398k | i++; |
55 | 398k | } |
56 | 1.46k | } |
57 | | |
58 | | static void init_scan_d(position* scan, int blkSize) |
59 | 1.46k | { |
60 | 1.46k | int i=0; |
61 | 1.46k | int x=0,y=0; |
62 | | |
63 | 34.7k | do { |
64 | 813k | while (y>=0) { |
65 | 778k | if (x<blkSize && y<blkSize) { |
66 | 398k | scan[i].x = x; |
67 | 398k | scan[i].y = y; |
68 | 398k | i++; |
69 | 398k | } |
70 | 778k | y--; |
71 | 778k | x++; |
72 | 778k | } |
73 | | |
74 | 34.7k | y=x; |
75 | 34.7k | x=0; |
76 | 34.7k | } while (i < blkSize*blkSize); |
77 | 1.46k | } |
78 | | |
79 | | |
80 | | const position* get_scan_order(int log2BlockSize, int scanIdx) |
81 | 11.3M | { |
82 | 11.3M | switch (scanIdx) { |
83 | 9.20M | case 0: return scan_d[log2BlockSize]; |
84 | 1.15M | case 1: return scan_h[log2BlockSize]; |
85 | 1.01M | case 2: return scan_v[log2BlockSize]; |
86 | 0 | default: return 0; // should never happen |
87 | 11.3M | } |
88 | 11.3M | } |
89 | | |
90 | | |
91 | | |
92 | | static scan_position scanpos_h_2[ 4* 4], scanpos_v_2[ 4* 4], scanpos_d_2[ 4* 4]; |
93 | | static scan_position scanpos_h_3[ 8* 8], scanpos_v_3[ 8* 8], scanpos_d_3[ 8* 8]; |
94 | | static scan_position scanpos_h_4[16*16], scanpos_v_4[16*16], scanpos_d_4[16*16]; |
95 | | static scan_position scanpos_h_5[32*32], scanpos_v_5[32*32], scanpos_d_5[32*32]; |
96 | | |
97 | | static scan_position* scanpos[3][6] = |
98 | | { { 0,0,scanpos_d_2,scanpos_d_3,scanpos_d_4,scanpos_d_5 }, |
99 | | { 0,0,scanpos_h_2,scanpos_h_3,scanpos_h_4,scanpos_h_5 }, |
100 | | { 0,0,scanpos_v_2,scanpos_v_3,scanpos_v_4,scanpos_v_5 } }; |
101 | | |
102 | | |
103 | | scan_position get_scan_position(int x,int y, int scanIdx, int log2BlkSize) |
104 | 4.48M | { |
105 | 4.48M | return scanpos[scanIdx][log2BlkSize][ y*(1<<log2BlkSize) + x ]; |
106 | 4.48M | } |
107 | | |
108 | | static void fill_scan_pos(scan_position* pos, int x,int y,int scanIdx, int log2TrafoSize) |
109 | 1.19M | { |
110 | 1.19M | int lastScanPos = 16; |
111 | 1.19M | int lastSubBlock = (1<<(log2TrafoSize-2)) * (1<<(log2TrafoSize-2)) -1; |
112 | | |
113 | 1.19M | const position* ScanOrderSub = get_scan_order(log2TrafoSize-2, scanIdx); |
114 | 1.19M | const position* ScanOrderPos = get_scan_order(2, scanIdx); |
115 | | |
116 | 1.19M | int xC,yC; |
117 | 490M | do { |
118 | 490M | if (lastScanPos==0) { |
119 | 30.0M | lastScanPos=16; |
120 | 30.0M | lastSubBlock--; |
121 | 30.0M | } |
122 | 490M | lastScanPos--; |
123 | | |
124 | 490M | position S = ScanOrderSub[lastSubBlock]; |
125 | 490M | xC = (S.x<<2) + ScanOrderPos[lastScanPos].x; |
126 | 490M | yC = (S.y<<2) + ScanOrderPos[lastScanPos].y; |
127 | | |
128 | 490M | } while ( (xC != x) || (yC != y)); |
129 | | |
130 | 1.19M | pos->subBlock = lastSubBlock; |
131 | 1.19M | pos->scanPos = lastScanPos; |
132 | 1.19M | } |
133 | | |
134 | | |
135 | | void init_scan_orders() |
136 | 292 | { |
137 | 1.75k | for (int log2size=1;log2size<=5;log2size++) |
138 | 1.46k | { |
139 | 1.46k | init_scan_h(scan_h[log2size], 1<<log2size); |
140 | 1.46k | init_scan_v(scan_v[log2size], 1<<log2size); |
141 | 1.46k | init_scan_d(scan_d[log2size], 1<<log2size); |
142 | 1.46k | } |
143 | | |
144 | | |
145 | 1.46k | for (int log2size=2;log2size<=5;log2size++) |
146 | 4.67k | for (int scanIdx=0;scanIdx<3;scanIdx++) |
147 | 56.0k | for (int y=0;y<(1<<log2size);y++) |
148 | 1.24M | for (int x=0;x<(1<<log2size);x++) |
149 | 1.19M | { |
150 | 1.19M | fill_scan_pos(&scanpos[scanIdx][log2size][ y*(1<<log2size) + x ],x,y,scanIdx,log2size); |
151 | 1.19M | } |
152 | 292 | } |