/work/libde265/libde265/scan.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 "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 | 5 | { |
36 | 5 | int i=0; |
37 | 67 | for (int y=0;y<blkSize;y++) |
38 | 1.42k | for (int x=0;x<blkSize;x++) |
39 | 1.36k | { |
40 | 1.36k | scan[i].x = x; |
41 | 1.36k | scan[i].y = y; |
42 | 1.36k | i++; |
43 | 1.36k | } |
44 | 5 | } |
45 | | |
46 | | static void init_scan_v(position* scan, int blkSize) |
47 | 5 | { |
48 | 5 | int i=0; |
49 | 67 | for (int x=0;x<blkSize;x++) |
50 | 1.42k | for (int y=0;y<blkSize;y++) |
51 | 1.36k | { |
52 | 1.36k | scan[i].x = x; |
53 | 1.36k | scan[i].y = y; |
54 | 1.36k | i++; |
55 | 1.36k | } |
56 | 5 | } |
57 | | |
58 | | static void init_scan_d(position* scan, int blkSize) |
59 | 5 | { |
60 | 5 | int i=0; |
61 | 5 | int x=0,y=0; |
62 | | |
63 | 119 | do { |
64 | 2.78k | while (y>=0) { |
65 | 2.66k | if (x<blkSize && y<blkSize) { |
66 | 1.36k | scan[i].x = x; |
67 | 1.36k | scan[i].y = y; |
68 | 1.36k | i++; |
69 | 1.36k | } |
70 | 2.66k | y--; |
71 | 2.66k | x++; |
72 | 2.66k | } |
73 | | |
74 | 119 | y=x; |
75 | 119 | x=0; |
76 | 119 | } while (i < blkSize*blkSize); |
77 | 5 | } |
78 | | |
79 | | |
80 | | const position* get_scan_order(int log2BlockSize, int scanIdx) |
81 | 24 | { |
82 | 24 | switch (scanIdx) { |
83 | 8 | case 0: return scan_d[log2BlockSize]; |
84 | 8 | case 1: return scan_h[log2BlockSize]; |
85 | 8 | case 2: return scan_v[log2BlockSize]; |
86 | 0 | default: return 0; // should never happen |
87 | 24 | } |
88 | 24 | } |
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 | 0 | { |
105 | 0 | return scanpos[scanIdx][log2BlkSize][ y*(1<<log2BlkSize) + x ]; |
106 | 0 | } |
107 | | |
108 | | static void fill_scan_pos_table(scan_position* pos, int scanIdx, int log2TrafoSize) |
109 | 12 | { |
110 | 12 | int numSubBlocks = (1<<(log2TrafoSize-2)) * (1<<(log2TrafoSize-2)); |
111 | 12 | int blkSize = 1 << log2TrafoSize; |
112 | | |
113 | 12 | const position* ScanOrderSub = get_scan_order(log2TrafoSize-2, scanIdx); |
114 | 12 | const position* ScanOrderPos = get_scan_order(2, scanIdx); |
115 | | |
116 | 267 | for (int sb = 0; sb < numSubBlocks; sb++) |
117 | 255 | { |
118 | 255 | position S = ScanOrderSub[sb]; |
119 | 4.33k | for (int sp = 0; sp < 16; sp++) |
120 | 4.08k | { |
121 | 4.08k | int xC = (S.x<<2) + ScanOrderPos[sp].x; |
122 | 4.08k | int yC = (S.y<<2) + ScanOrderPos[sp].y; |
123 | 4.08k | pos[yC * blkSize + xC].subBlock = sb; |
124 | 4.08k | pos[yC * blkSize + xC].scanPos = sp; |
125 | 4.08k | } |
126 | 255 | } |
127 | 12 | } |
128 | | |
129 | | |
130 | | void init_scan_orders() |
131 | 1 | { |
132 | 6 | for (int log2size=1;log2size<=5;log2size++) |
133 | 5 | { |
134 | 5 | init_scan_h(scan_h[log2size], 1<<log2size); |
135 | 5 | init_scan_v(scan_v[log2size], 1<<log2size); |
136 | 5 | init_scan_d(scan_d[log2size], 1<<log2size); |
137 | 5 | } |
138 | | |
139 | 5 | for (int log2size=2;log2size<=5;log2size++) |
140 | 16 | for (int scanIdx=0;scanIdx<3;scanIdx++) |
141 | 12 | fill_scan_pos_table(scanpos[scanIdx][log2size], scanIdx, log2size); |
142 | 1 | } |