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