blob: e6e0f08efb6dff64761c4891ef31a655628042a5 [file] [log] [blame]
Ed Tanous93f987d2017-04-17 17:52:36 -07001#pragma once
2
Ed Tanous55c7b7a2018-05-22 15:27:24 -07003#include <aspeed/JTABLES.H>
Ed Tanous911ac312017-08-15 09:37:42 -07004#include <ast_video_types.hpp>
Ed Tanous93f987d2017-04-17 17:52:36 -07005#include <array>
Ed Tanous1ff48782017-04-18 12:45:08 -07006#include <cassert>
7#include <cstdint>
Ed Tanous911ac312017-08-15 09:37:42 -07008#include <cstring>
Ed Tanousb078cf32017-04-18 14:51:21 -07009#include <iostream>
10#include <vector>
Ed Tanous93f987d2017-04-17 17:52:36 -070011
Ed Tanous55c7b7a2018-05-22 15:27:24 -070012namespace ast_video {
Ed Tanous93f987d2017-04-17 17:52:36 -070013
Ed Tanous55c7b7a2018-05-22 15:27:24 -070014struct ColorCache {
15 ColorCache()
16 : color{0x008080, 0xFF8080, 0x808080, 0xC08080}, index{0, 1, 2, 3} {}
Ed Tanousd5f39992017-04-18 13:41:22 -070017
Ed Tanous55c7b7a2018-05-22 15:27:24 -070018 unsigned long color[4];
19 unsigned char index[4];
20 unsigned char bitMapBits{};
Ed Tanous93f987d2017-04-17 17:52:36 -070021};
22
23struct RGB {
Ed Tanous55c7b7a2018-05-22 15:27:24 -070024 unsigned char b;
25 unsigned char g;
26 unsigned char r;
27 unsigned char reserved;
Ed Tanous93f987d2017-04-17 17:52:36 -070028};
29
30enum class JpgBlock {
31 JPEG_NO_SKIP_CODE = 0x00,
32 JPEG_SKIP_CODE = 0x08,
33
34 JPEG_PASS2_CODE = 0x02,
35 JPEG_SKIP_PASS2_CODE = 0x0A,
36
37 LOW_JPEG_NO_SKIP_CODE = 0x04,
38 LOW_JPEG_SKIP_CODE = 0x0C,
39
40 VQ_NO_SKIP_1_COLOR_CODE = 0x05,
41 VQ_SKIP_1_COLOR_CODE = 0x0D,
42
43 VQ_NO_SKIP_2_COLOR_CODE = 0x06,
44 VQ_SKIP_2_COLOR_CODE = 0x0E,
45
46 VQ_NO_SKIP_4_COLOR_CODE = 0x07,
47 VQ_SKIP_4_COLOR_CODE = 0x0F,
48
49 FRAME_END_CODE = 0x09,
50
51};
52
53class AstJpegDecoder {
54 public:
55 AstJpegDecoder() {
56 // TODO(ed) figure out how to init this in the constructor
Ed Tanous55c7b7a2018-05-22 15:27:24 -070057 yuvBuffer.resize(1920 * 1200);
58 outBuffer.resize(1920 * 1200);
59 for (auto &r : outBuffer) {
60 r.r = 0x00;
61 r.g = 0x00;
62 r.b = 0x00;
63 r.reserved = 0xAA;
Ed Tanous93f987d2017-04-17 17:52:36 -070064 }
Ed Tanousd5f39992017-04-18 13:41:22 -070065
66 int qfactor = 16;
67
Ed Tanous55c7b7a2018-05-22 15:27:24 -070068 scalefactor = qfactor;
69 scalefactoruv = qfactor;
70 advancescalefactor = 16;
71 advancescalefactoruv = 16;
72 initJpgTable();
Ed Tanous93f987d2017-04-17 17:52:36 -070073 }
74
Ed Tanous55c7b7a2018-05-22 15:27:24 -070075 void loadQuantTable(std::array<long, 64> &quant_table) {
Ed Tanousd76323e2018-08-07 14:35:40 -070076 float scalefactorF[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f,
77 1.0f, 0.785694958f, 0.541196100f, 0.275899379f};
Ed Tanous93f987d2017-04-17 17:52:36 -070078 uint8_t j, row, col;
Ed Tanous911ac312017-08-15 09:37:42 -070079 std::array<uint8_t, 64> tempQT{};
Ed Tanous93f987d2017-04-17 17:52:36 -070080
81 // Load quantization coefficients from JPG file, scale them for DCT and
82 // reorder
83 // from zig-zag order
Ed Tanous55c7b7a2018-05-22 15:27:24 -070084 switch (ySelector) {
Ed Tanous93f987d2017-04-17 17:52:36 -070085 case 0:
Ed Tanous55c7b7a2018-05-22 15:27:24 -070086 stdLuminanceQt = tbl000Y;
Ed Tanous93f987d2017-04-17 17:52:36 -070087 break;
88 case 1:
Ed Tanous55c7b7a2018-05-22 15:27:24 -070089 stdLuminanceQt = tbl014Y;
Ed Tanous93f987d2017-04-17 17:52:36 -070090 break;
91 case 2:
Ed Tanous55c7b7a2018-05-22 15:27:24 -070092 stdLuminanceQt = tbl029Y;
Ed Tanous93f987d2017-04-17 17:52:36 -070093 break;
94 case 3:
Ed Tanous55c7b7a2018-05-22 15:27:24 -070095 stdLuminanceQt = tbl043Y;
Ed Tanous93f987d2017-04-17 17:52:36 -070096 break;
97 case 4:
Ed Tanous55c7b7a2018-05-22 15:27:24 -070098 stdLuminanceQt = tbl057Y;
Ed Tanous93f987d2017-04-17 17:52:36 -070099 break;
100 case 5:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700101 stdLuminanceQt = tbl071Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700102 break;
103 case 6:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700104 stdLuminanceQt = tbl086Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700105 break;
106 case 7:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700107 stdLuminanceQt = tbl100Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700108 break;
109 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700110 setQuantTable(stdLuminanceQt, static_cast<uint8_t>(scalefactor), tempQT);
Ed Tanous93f987d2017-04-17 17:52:36 -0700111
Ed Tanous911ac312017-08-15 09:37:42 -0700112 for (j = 0; j <= 63; j++) {
113 quant_table[j] = tempQT[zigzag[j]];
114 }
Ed Tanous93f987d2017-04-17 17:52:36 -0700115 j = 0;
Ed Tanous911ac312017-08-15 09:37:42 -0700116 for (row = 0; row <= 7; row++) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700117 for (col = 0; col <= 7; col++) {
Ed Tanous911ac312017-08-15 09:37:42 -0700118 quant_table[j] = static_cast<long>(
Ed Tanousd76323e2018-08-07 14:35:40 -0700119 (quant_table[j] * scalefactorF[row] * scalefactorF[col]) * 65536);
Ed Tanous93f987d2017-04-17 17:52:36 -0700120 j++;
121 }
Ed Tanous911ac312017-08-15 09:37:42 -0700122 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700123 bytePos += 64;
Ed Tanous93f987d2017-04-17 17:52:36 -0700124 }
125
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700126 void loadQuantTableCb(std::array<long, 64> &quant_table) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700127 float scalefactor[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f,
128 1.0f, 0.785694958f, 0.541196100f, 0.275899379f};
129 uint8_t j, row, col;
Ed Tanous911ac312017-08-15 09:37:42 -0700130 std::array<uint8_t, 64> tempQT{};
Ed Tanous93f987d2017-04-17 17:52:36 -0700131
132 // Load quantization coefficients from JPG file, scale them for DCT and
133 // reorder from zig-zag order
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700134 if (mapping == 0) {
135 switch (uvSelector) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700136 case 0:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700137 stdChrominanceQt = tbl000Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700138 break;
139 case 1:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700140 stdChrominanceQt = tbl014Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700141 break;
142 case 2:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700143 stdChrominanceQt = tbl029Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700144 break;
145 case 3:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700146 stdChrominanceQt = tbl043Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700147 break;
148 case 4:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700149 stdChrominanceQt = tbl057Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700150 break;
151 case 5:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700152 stdChrominanceQt = tbl071Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700153 break;
154 case 6:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700155 stdChrominanceQt = tbl086Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700156 break;
157 case 7:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700158 stdChrominanceQt = tbl100Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700159 break;
160 }
161 } else {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700162 switch (uvSelector) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700163 case 0:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700164 stdChrominanceQt = tbl000Uv;
Ed Tanous93f987d2017-04-17 17:52:36 -0700165 break;
166 case 1:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700167 stdChrominanceQt = tbl014Uv;
Ed Tanous93f987d2017-04-17 17:52:36 -0700168 break;
169 case 2:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700170 stdChrominanceQt = tbl029Uv;
Ed Tanous93f987d2017-04-17 17:52:36 -0700171 break;
172 case 3:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700173 stdChrominanceQt = tbl043Uv;
Ed Tanous93f987d2017-04-17 17:52:36 -0700174 break;
175 case 4:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700176 stdChrominanceQt = tbl057Uv;
Ed Tanous93f987d2017-04-17 17:52:36 -0700177 break;
178 case 5:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700179 stdChrominanceQt = tbl071Uv;
Ed Tanous93f987d2017-04-17 17:52:36 -0700180 break;
181 case 6:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700182 stdChrominanceQt = tbl086Uv;
Ed Tanous93f987d2017-04-17 17:52:36 -0700183 break;
184 case 7:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700185 stdChrominanceQt = tbl100Uv;
Ed Tanous93f987d2017-04-17 17:52:36 -0700186 break;
187 }
188 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700189 setQuantTable(stdChrominanceQt, static_cast<uint8_t>(scalefactoruv),
190 tempQT);
Ed Tanous93f987d2017-04-17 17:52:36 -0700191
192 for (j = 0; j <= 63; j++) {
193 quant_table[j] = tempQT[zigzag[j]];
194 }
195 j = 0;
196 for (row = 0; row <= 7; row++) {
197 for (col = 0; col <= 7; col++) {
Ed Tanous911ac312017-08-15 09:37:42 -0700198 quant_table[j] = static_cast<long>(
199 (quant_table[j] * scalefactor[row] * scalefactor[col]) * 65536);
Ed Tanous93f987d2017-04-17 17:52:36 -0700200 j++;
201 }
202 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700203 bytePos += 64;
Ed Tanous93f987d2017-04-17 17:52:36 -0700204 }
205 // Note: Added for Dual_JPEG
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700206 void loadAdvanceQuantTable(std::array<long, 64> &quant_table) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700207 float scalefactor[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f,
208 1.0f, 0.785694958f, 0.541196100f, 0.275899379f};
209 uint8_t j, row, col;
Ed Tanous911ac312017-08-15 09:37:42 -0700210 std::array<uint8_t, 64> tempQT{};
Ed Tanous93f987d2017-04-17 17:52:36 -0700211
212 // Load quantization coefficients from JPG file, scale them for DCT and
213 // reorder
214 // from zig-zag order
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700215 switch (advanceSelector) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700216 case 0:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700217 stdLuminanceQt = tbl000Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700218 break;
219 case 1:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700220 stdLuminanceQt = tbl014Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700221 break;
222 case 2:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700223 stdLuminanceQt = tbl029Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700224 break;
225 case 3:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700226 stdLuminanceQt = tbl043Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700227 break;
228 case 4:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700229 stdLuminanceQt = tbl057Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700230 break;
231 case 5:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700232 stdLuminanceQt = tbl071Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700233 break;
234 case 6:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700235 stdLuminanceQt = tbl086Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700236 break;
237 case 7:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700238 stdLuminanceQt = tbl100Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700239 break;
240 }
241 // Note: pass ADVANCE SCALE FACTOR to sub-function in Dual-JPEG
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700242 setQuantTable(stdLuminanceQt, static_cast<uint8_t>(advancescalefactor),
243 tempQT);
Ed Tanous93f987d2017-04-17 17:52:36 -0700244
Ed Tanous911ac312017-08-15 09:37:42 -0700245 for (j = 0; j <= 63; j++) {
246 quant_table[j] = tempQT[zigzag[j]];
247 }
Ed Tanous93f987d2017-04-17 17:52:36 -0700248 j = 0;
Ed Tanous911ac312017-08-15 09:37:42 -0700249 for (row = 0; row <= 7; row++) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700250 for (col = 0; col <= 7; col++) {
Ed Tanous911ac312017-08-15 09:37:42 -0700251 quant_table[j] = static_cast<long>(
252 (quant_table[j] * scalefactor[row] * scalefactor[col]) * 65536);
Ed Tanous93f987d2017-04-17 17:52:36 -0700253 j++;
254 }
Ed Tanous911ac312017-08-15 09:37:42 -0700255 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700256 bytePos += 64;
Ed Tanous93f987d2017-04-17 17:52:36 -0700257 }
258
259 // Note: Added for Dual-JPEG
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700260 void loadAdvanceQuantTableCb(std::array<long, 64> &quant_table) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700261 float scalefactor[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f,
262 1.0f, 0.785694958f, 0.541196100f, 0.275899379f};
263 uint8_t j, row, col;
Ed Tanous911ac312017-08-15 09:37:42 -0700264 std::array<uint8_t, 64> tempQT{};
Ed Tanous93f987d2017-04-17 17:52:36 -0700265
266 // Load quantization coefficients from JPG file, scale them for DCT and
267 // reorder
268 // from zig-zag order
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700269 if (mapping == 1) {
270 switch (advanceSelector) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700271 case 0:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700272 stdChrominanceQt = tbl000Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700273 break;
274 case 1:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700275 stdChrominanceQt = tbl014Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700276 break;
277 case 2:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700278 stdChrominanceQt = tbl029Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700279 break;
280 case 3:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700281 stdChrominanceQt = tbl043Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700282 break;
283 case 4:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700284 stdChrominanceQt = tbl057Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700285 break;
286 case 5:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700287 stdChrominanceQt = tbl071Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700288 break;
289 case 6:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700290 stdChrominanceQt = tbl086Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700291 break;
292 case 7:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700293 stdChrominanceQt = tbl100Y;
Ed Tanous93f987d2017-04-17 17:52:36 -0700294 break;
295 }
296 } else {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700297 switch (advanceSelector) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700298 case 0:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700299 stdChrominanceQt = tbl000Uv;
Ed Tanous93f987d2017-04-17 17:52:36 -0700300 break;
301 case 1:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700302 stdChrominanceQt = tbl014Uv;
Ed Tanous93f987d2017-04-17 17:52:36 -0700303 break;
304 case 2:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700305 stdChrominanceQt = tbl029Uv;
Ed Tanous93f987d2017-04-17 17:52:36 -0700306 break;
307 case 3:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700308 stdChrominanceQt = tbl043Uv;
Ed Tanous93f987d2017-04-17 17:52:36 -0700309 break;
310 case 4:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700311 stdChrominanceQt = tbl057Uv;
Ed Tanous93f987d2017-04-17 17:52:36 -0700312 break;
313 case 5:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700314 stdChrominanceQt = tbl071Uv;
Ed Tanous93f987d2017-04-17 17:52:36 -0700315 break;
316 case 6:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700317 stdChrominanceQt = tbl086Uv;
Ed Tanous93f987d2017-04-17 17:52:36 -0700318 break;
319 case 7:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700320 stdChrominanceQt = tbl100Uv;
Ed Tanous93f987d2017-04-17 17:52:36 -0700321 break;
322 }
323 }
324 // Note: pass ADVANCE SCALE FACTOR to sub-function in Dual-JPEG
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700325 setQuantTable(stdChrominanceQt, static_cast<uint8_t>(advancescalefactoruv),
326 tempQT);
Ed Tanous93f987d2017-04-17 17:52:36 -0700327
Ed Tanous911ac312017-08-15 09:37:42 -0700328 for (j = 0; j <= 63; j++) {
329 quant_table[j] = tempQT[zigzag[j]];
330 }
Ed Tanous93f987d2017-04-17 17:52:36 -0700331 j = 0;
Ed Tanous911ac312017-08-15 09:37:42 -0700332 for (row = 0; row <= 7; row++) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700333 for (col = 0; col <= 7; col++) {
Ed Tanous911ac312017-08-15 09:37:42 -0700334 quant_table[j] = static_cast<long>(
335 (quant_table[j] * scalefactor[row] * scalefactor[col]) * 65536);
Ed Tanous93f987d2017-04-17 17:52:36 -0700336 j++;
337 }
Ed Tanous911ac312017-08-15 09:37:42 -0700338 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700339 bytePos += 64;
Ed Tanous93f987d2017-04-17 17:52:36 -0700340 }
341
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700342 void idctTransform(short *coef, uint8_t *data, uint8_t nBlock) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700343#define FIX_1_082392200 ((int)277) /* FIX(1.082392200) */
344#define FIX_1_414213562 ((int)362) /* FIX(1.414213562) */
345#define FIX_1_847759065 ((int)473) /* FIX(1.847759065) */
346#define FIX_2_613125930 ((int)669) /* FIX(2.613125930) */
347
348#define MULTIPLY(var, cons) ((int)((var) * (cons)) >> 8)
349
350 int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
351 int tmp10, tmp11, tmp12, tmp13;
352 int z5, z10, z11, z12, z13;
353 int workspace[64]; /* buffers data between passes */
354
355 short *inptr = coef;
356 long *quantptr;
357 int *wsptr = workspace;
358 unsigned char *outptr;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700359 unsigned char *rLimit = rlimitTable + 128;
360 int ctr, dcval, dctsize = 8;
Ed Tanous93f987d2017-04-17 17:52:36 -0700361
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700362 quantptr = &qt[nBlock][0];
Ed Tanous93f987d2017-04-17 17:52:36 -0700363
364 // Pass 1: process columns from input (inptr), store into work array(wsptr)
365
366 for (ctr = 8; ctr > 0; ctr--) {
367 /* Due to quantization, we will usually find that many of the input
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700368 * coefficients are zero, especially the AC terms. We can exploit this
369 * by short-circuiting the IDCT calculation for any column in which all
370 * the AC terms are zero. In that case each output is equal to the
371 * DC coefficient (with scale factor as needed).
372 * With typical images and quantization tables, half or more of the
373 * column DCT calculations can be simplified this way.
374 */
Ed Tanous93f987d2017-04-17 17:52:36 -0700375
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700376 if ((inptr[dctsize * 1] | inptr[dctsize * 2] | inptr[dctsize * 3] |
377 inptr[dctsize * 4] | inptr[dctsize * 5] | inptr[dctsize * 6] |
378 inptr[dctsize * 7]) == 0) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700379 /* AC terms all zero */
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700380 dcval = static_cast<int>((inptr[dctsize * 0] * quantptr[dctsize * 0]) >>
Ed Tanous911ac312017-08-15 09:37:42 -0700381 16);
Ed Tanous93f987d2017-04-17 17:52:36 -0700382
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700383 wsptr[dctsize * 0] = dcval;
384 wsptr[dctsize * 1] = dcval;
385 wsptr[dctsize * 2] = dcval;
386 wsptr[dctsize * 3] = dcval;
387 wsptr[dctsize * 4] = dcval;
388 wsptr[dctsize * 5] = dcval;
389 wsptr[dctsize * 6] = dcval;
390 wsptr[dctsize * 7] = dcval;
Ed Tanous93f987d2017-04-17 17:52:36 -0700391
392 inptr++; /* advance pointers to next column */
393 quantptr++;
394 wsptr++;
395 continue;
396 }
397
398 /* Even part */
399
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700400 tmp0 = (inptr[dctsize * 0] * quantptr[dctsize * 0]) >> 16;
401 tmp1 = (inptr[dctsize * 2] * quantptr[dctsize * 2]) >> 16;
402 tmp2 = (inptr[dctsize * 4] * quantptr[dctsize * 4]) >> 16;
403 tmp3 = (inptr[dctsize * 6] * quantptr[dctsize * 6]) >> 16;
Ed Tanous93f987d2017-04-17 17:52:36 -0700404
405 tmp10 = tmp0 + tmp2; /* phase 3 */
406 tmp11 = tmp0 - tmp2;
407
408 tmp13 = tmp1 + tmp3; /* phases 5-3 */
409 tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */
410
411 tmp0 = tmp10 + tmp13; /* phase 2 */
412 tmp3 = tmp10 - tmp13;
413 tmp1 = tmp11 + tmp12;
414 tmp2 = tmp11 - tmp12;
415
416 /* Odd part */
417
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700418 tmp4 = (inptr[dctsize * 1] * quantptr[dctsize * 1]) >> 16;
419 tmp5 = (inptr[dctsize * 3] * quantptr[dctsize * 3]) >> 16;
420 tmp6 = (inptr[dctsize * 5] * quantptr[dctsize * 5]) >> 16;
421 tmp7 = (inptr[dctsize * 7] * quantptr[dctsize * 7]) >> 16;
Ed Tanous93f987d2017-04-17 17:52:36 -0700422
423 z13 = tmp6 + tmp5; /* phase 6 */
424 z10 = tmp6 - tmp5;
425 z11 = tmp4 + tmp7;
426 z12 = tmp4 - tmp7;
427
428 tmp7 = z11 + z13; /* phase 5 */
429 tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
430
431 z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
432 tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
433 tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */
434
435 tmp6 = tmp12 - tmp7; /* phase 2 */
436 tmp5 = tmp11 - tmp6;
437 tmp4 = tmp10 + tmp5;
438
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700439 wsptr[dctsize * 0] = (tmp0 + tmp7);
440 wsptr[dctsize * 7] = (tmp0 - tmp7);
441 wsptr[dctsize * 1] = (tmp1 + tmp6);
442 wsptr[dctsize * 6] = (tmp1 - tmp6);
443 wsptr[dctsize * 2] = (tmp2 + tmp5);
444 wsptr[dctsize * 5] = (tmp2 - tmp5);
445 wsptr[dctsize * 4] = (tmp3 + tmp4);
446 wsptr[dctsize * 3] = (tmp3 - tmp4);
Ed Tanous93f987d2017-04-17 17:52:36 -0700447
448 inptr++; /* advance pointers to next column */
449 quantptr++;
450 wsptr++;
451 }
452
453/* Pass 2: process rows from work array, store into output array. */
454/* Note that we must descale the results by a factor of 8 == 2**3, */
455/* and also undo the PASS1_BITS scaling. */
456
457//#define RANGE_MASK 1023; //2 bits wider than legal samples
458#define PASS1_BITS 0
Ed Tanous911ac312017-08-15 09:37:42 -0700459#define IDESCALE(x, n) ((int)((x) >> (n)))
Ed Tanous93f987d2017-04-17 17:52:36 -0700460
461 wsptr = workspace;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700462 for (ctr = 0; ctr < dctsize; ctr++) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700463 outptr = data + ctr * 8;
464
465 /* Rows of zeroes can be exploited in the same way as we did with columns.
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700466 * However, the column calculation has created many nonzero AC terms, so
467 * the simplification applies less often (typically 5% to 10% of the
468 * time). On machines with very fast multiplication, it's possible that
469 * the test takes more time than it's worth. In that case this section
470 * may be commented out.
471 */
Ed Tanous93f987d2017-04-17 17:52:36 -0700472 /* Even part */
473
Ed Tanous911ac312017-08-15 09:37:42 -0700474 tmp10 = (wsptr[0] + wsptr[4]);
475 tmp11 = (wsptr[0] - wsptr[4]);
Ed Tanous93f987d2017-04-17 17:52:36 -0700476
Ed Tanous911ac312017-08-15 09:37:42 -0700477 tmp13 = (wsptr[2] + wsptr[6]);
Ed Tanous93f987d2017-04-17 17:52:36 -0700478 tmp12 = MULTIPLY((int)wsptr[2] - (int)wsptr[6], FIX_1_414213562) - tmp13;
479
480 tmp0 = tmp10 + tmp13;
481 tmp3 = tmp10 - tmp13;
482 tmp1 = tmp11 + tmp12;
483 tmp2 = tmp11 - tmp12;
484
485 /* Odd part */
486
Ed Tanous911ac312017-08-15 09:37:42 -0700487 z13 = wsptr[5] + wsptr[3];
488 z10 = wsptr[5] - wsptr[3];
489 z11 = wsptr[1] + wsptr[7];
490 z12 = wsptr[1] - wsptr[7];
Ed Tanous93f987d2017-04-17 17:52:36 -0700491
492 tmp7 = z11 + z13; /* phase 5 */
493 tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
494
495 z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
496 tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
497 tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */
498
499 tmp6 = tmp12 - tmp7; /* phase 2 */
500 tmp5 = tmp11 - tmp6;
501 tmp4 = tmp10 + tmp5;
502
503 /* Final output stage: scale down by a factor of 8 and range-limit */
504
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700505 outptr[0] = rLimit[IDESCALE((tmp0 + tmp7), (PASS1_BITS + 3)) & 1023L];
506 outptr[7] = rLimit[IDESCALE((tmp0 - tmp7), (PASS1_BITS + 3)) & 1023L];
507 outptr[1] = rLimit[IDESCALE((tmp1 + tmp6), (PASS1_BITS + 3)) & 1023L];
508 outptr[6] = rLimit[IDESCALE((tmp1 - tmp6), (PASS1_BITS + 3)) & 1023L];
509 outptr[2] = rLimit[IDESCALE((tmp2 + tmp5), (PASS1_BITS + 3)) & 1023L];
510 outptr[5] = rLimit[IDESCALE((tmp2 - tmp5), (PASS1_BITS + 3)) & 1023L];
511 outptr[4] = rLimit[IDESCALE((tmp3 + tmp4), (PASS1_BITS + 3)) & 1023L];
512 outptr[3] = rLimit[IDESCALE((tmp3 - tmp4), (PASS1_BITS + 3)) & 1023L];
Ed Tanous93f987d2017-04-17 17:52:36 -0700513
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700514 wsptr += dctsize; /* advance pointer to next row */
Ed Tanous93f987d2017-04-17 17:52:36 -0700515 }
516 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700517 void yuvToRgb(
Ed Tanous93f987d2017-04-17 17:52:36 -0700518 int txb, int tyb,
519 unsigned char
520 *pYCbCr, // in, Y: 256 or 64 bytes; Cb: 64 bytes; Cr: 64 bytes
521 struct RGB *pYUV, // in, Y: 256 or 64 bytes; Cb: 64 bytes; Cr: 64 bytes
522 unsigned char
523 *pBgr // out, BGR format, 16*16*3 = 768 bytes; or 8*8*3=192 bytes
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700524 ) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700525 int i, j, pos, m, n;
526 unsigned char cb, cr, *py, *pcb, *pcr, *py420[4];
527 int y;
528 struct RGB *pByte;
529 int nBlocksInMcu = 6;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700530 unsigned int pixelX, pixelY;
Ed Tanous93f987d2017-04-17 17:52:36 -0700531
Ed Tanous911ac312017-08-15 09:37:42 -0700532 pByte = reinterpret_cast<struct RGB *>(pBgr);
Ed Tanous93f987d2017-04-17 17:52:36 -0700533 if (yuvmode == YuvMode::YUV444) {
534 py = pYCbCr;
535 pcb = pYCbCr + 64;
536 pcr = pcb + 64;
537
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700538 pixelX = txb * 8;
539 pixelY = tyb * 8;
540 pos = (pixelY * width) + pixelX;
Ed Tanous93f987d2017-04-17 17:52:36 -0700541
542 for (j = 0; j < 8; j++) {
543 for (i = 0; i < 8; i++) {
544 m = ((j << 3) + i);
545 y = py[m];
546 cb = pcb[m];
547 cr = pcr[m];
548 n = pos + i;
549 // For 2Pass. Save the YUV value
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700550 pYUV[n].b = cb;
551 pYUV[n].g = y;
552 pYUV[n].r = cr;
553 pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]];
554 pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]];
555 pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]];
Ed Tanous93f987d2017-04-17 17:52:36 -0700556 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700557 pos += width;
Ed Tanous93f987d2017-04-17 17:52:36 -0700558 }
559 } else {
Ed Tanous911ac312017-08-15 09:37:42 -0700560 for (i = 0; i < nBlocksInMcu - 2; i++) {
561 py420[i] = pYCbCr + i * 64;
562 }
Ed Tanous93f987d2017-04-17 17:52:36 -0700563 pcb = pYCbCr + (nBlocksInMcu - 2) * 64;
564 pcr = pcb + 64;
565
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700566 pixelX = txb * 16;
567 pixelY = tyb * 16;
568 pos = (pixelY * width) + pixelX;
Ed Tanous93f987d2017-04-17 17:52:36 -0700569
570 for (j = 0; j < 16; j++) {
571 for (i = 0; i < 16; i++) {
572 // block number is ((j/8) * 2 + i/8)={0, 1, 2, 3}
573 y = *(py420[(j >> 3) * 2 + (i >> 3)]++);
574 m = ((j >> 1) << 3) + (i >> 1);
575 cb = pcb[m];
576 cr = pcr[m];
577 n = pos + i;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700578 pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]];
579 pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]];
580 pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]];
Ed Tanous93f987d2017-04-17 17:52:36 -0700581 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700582 pos += width;
Ed Tanous93f987d2017-04-17 17:52:36 -0700583 }
584 }
585 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700586 void yuvToBuffer(
Ed Tanous93f987d2017-04-17 17:52:36 -0700587 int txb, int tyb,
588 unsigned char
589 *pYCbCr, // in, Y: 256 or 64 bytes; Cb: 64 bytes; Cr: 64 bytes
590 struct RGB
591 *pYUV, // out, BGR format, 16*16*3 = 768 bytes; or 8*8*3=192 bytes
592 unsigned char
593 *pBgr // out, BGR format, 16*16*3 = 768 bytes; or 8*8*3=192 bytes
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700594 ) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700595 int i, j, pos, m, n;
596 unsigned char cb, cr, *py, *pcb, *pcr, *py420[4];
597 int y;
598 struct RGB *pByte;
599 int nBlocksInMcu = 6;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700600 unsigned int pixelX, pixelY;
Ed Tanous93f987d2017-04-17 17:52:36 -0700601
Ed Tanous911ac312017-08-15 09:37:42 -0700602 pByte = reinterpret_cast<struct RGB *>(pBgr);
Ed Tanous93f987d2017-04-17 17:52:36 -0700603 if (yuvmode == YuvMode::YUV444) {
604 py = pYCbCr;
605 pcb = pYCbCr + 64;
606 pcr = pcb + 64;
607
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700608 pixelX = txb * 8;
609 pixelY = tyb * 8;
610 pos = (pixelY * width) + pixelX;
Ed Tanous93f987d2017-04-17 17:52:36 -0700611
612 for (j = 0; j < 8; j++) {
613 for (i = 0; i < 8; i++) {
614 m = ((j << 3) + i);
615 n = pos + i;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700616 y = pYUV[n].g + (py[m] - 128);
617 cb = pYUV[n].b + (pcb[m] - 128);
618 cr = pYUV[n].r + (pcr[m] - 128);
619 pYUV[n].b = cb;
620 pYUV[n].g = y;
621 pYUV[n].r = cr;
622 pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]];
623 pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]];
624 pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]];
Ed Tanous93f987d2017-04-17 17:52:36 -0700625 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700626 pos += width;
Ed Tanous93f987d2017-04-17 17:52:36 -0700627 }
628 } else {
Ed Tanous911ac312017-08-15 09:37:42 -0700629 for (i = 0; i < nBlocksInMcu - 2; i++) {
630 py420[i] = pYCbCr + i * 64;
631 }
Ed Tanous93f987d2017-04-17 17:52:36 -0700632 pcb = pYCbCr + (nBlocksInMcu - 2) * 64;
633 pcr = pcb + 64;
634
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700635 pixelX = txb * 16;
636 pixelY = tyb * 16;
637 pos = (pixelY * width) + pixelX;
Ed Tanous93f987d2017-04-17 17:52:36 -0700638
639 for (j = 0; j < 16; j++) {
640 for (i = 0; i < 16; i++) {
641 // block number is ((j/8) * 2 + i/8)={0, 1, 2, 3}
642 y = *(py420[(j >> 3) * 2 + (i >> 3)]++);
643 m = ((j >> 1) << 3) + (i >> 1);
644 cb = pcb[m];
645 cr = pcr[m];
646 n = pos + i;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700647 pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]];
648 pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]];
649 pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]];
Ed Tanous93f987d2017-04-17 17:52:36 -0700650 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700651 pos += width;
Ed Tanous93f987d2017-04-17 17:52:36 -0700652 }
653 }
654 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700655 void decompress(int txb, int tyb, char *outBuf, uint8_t QT_TableSelection) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700656 unsigned char *ptr;
657 unsigned char byTileYuv[768] = {};
658
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700659 memset(dctCoeff, 0, 384 * 2);
Ed Tanous93f987d2017-04-17 17:52:36 -0700660 ptr = byTileYuv;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700661 processHuffmanDataUnit(ydcNr, yacNr, &dcy, 0);
662 idctTransform(dctCoeff, ptr, QT_TableSelection);
Ed Tanous93f987d2017-04-17 17:52:36 -0700663 ptr += 64;
664
665 if (yuvmode == YuvMode::YUV420) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700666 processHuffmanDataUnit(ydcNr, yacNr, &dcy, 64);
667 idctTransform(dctCoeff + 64, ptr, QT_TableSelection);
Ed Tanous93f987d2017-04-17 17:52:36 -0700668 ptr += 64;
669
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700670 processHuffmanDataUnit(ydcNr, yacNr, &dcy, 128);
671 idctTransform(dctCoeff + 128, ptr, QT_TableSelection);
Ed Tanous93f987d2017-04-17 17:52:36 -0700672 ptr += 64;
673
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700674 processHuffmanDataUnit(ydcNr, yacNr, &dcy, 192);
675 idctTransform(dctCoeff + 192, ptr, QT_TableSelection);
Ed Tanous93f987d2017-04-17 17:52:36 -0700676 ptr += 64;
677
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700678 processHuffmanDataUnit(cbDcNr, cbAcNr, &dcCb, 256);
679 idctTransform(dctCoeff + 256, ptr, QT_TableSelection + 1);
Ed Tanous93f987d2017-04-17 17:52:36 -0700680 ptr += 64;
681
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700682 processHuffmanDataUnit(crDcNr, crAcNr, &dcCr, 320);
683 idctTransform(dctCoeff + 320, ptr, QT_TableSelection + 1);
Ed Tanous93f987d2017-04-17 17:52:36 -0700684 } else {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700685 processHuffmanDataUnit(cbDcNr, cbAcNr, &dcCb, 64);
686 idctTransform(dctCoeff + 64, ptr, QT_TableSelection + 1);
Ed Tanous93f987d2017-04-17 17:52:36 -0700687 ptr += 64;
688
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700689 processHuffmanDataUnit(crDcNr, crAcNr, &dcCr, 128);
690 idctTransform(dctCoeff + 128, ptr, QT_TableSelection + 1);
Ed Tanous93f987d2017-04-17 17:52:36 -0700691 }
692
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700693 // yuvToRgb (txb, tyb, byTileYuv, (unsigned char *)outBuf);
694 // yuvBuffer for YUV record
695 yuvToRgb(txb, tyb, byTileYuv, yuvBuffer.data(),
Ed Tanous911ac312017-08-15 09:37:42 -0700696 reinterpret_cast<unsigned char *>(outBuf));
Ed Tanous93f987d2017-04-17 17:52:36 -0700697 }
698
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700699 void decompress2Pass(int txb, int tyb, char *outBuf,
700 uint8_t QT_TableSelection) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700701 unsigned char *ptr;
702 unsigned char byTileYuv[768];
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700703 memset(dctCoeff, 0, 384 * 2);
Ed Tanous93f987d2017-04-17 17:52:36 -0700704
705 ptr = byTileYuv;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700706 processHuffmanDataUnit(ydcNr, yacNr, &dcy, 0);
707 idctTransform(dctCoeff, ptr, QT_TableSelection);
Ed Tanous93f987d2017-04-17 17:52:36 -0700708 ptr += 64;
709
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700710 processHuffmanDataUnit(cbDcNr, cbAcNr, &dcCb, 64);
711 idctTransform(dctCoeff + 64, ptr, QT_TableSelection + 1);
Ed Tanous93f987d2017-04-17 17:52:36 -0700712 ptr += 64;
713
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700714 processHuffmanDataUnit(crDcNr, crAcNr, &dcCr, 128);
715 idctTransform(dctCoeff + 128, ptr, QT_TableSelection + 1);
Ed Tanous93f987d2017-04-17 17:52:36 -0700716
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700717 yuvToBuffer(txb, tyb, byTileYuv, yuvBuffer.data(),
Ed Tanous911ac312017-08-15 09:37:42 -0700718 reinterpret_cast<unsigned char *>(outBuf));
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700719 // yuvToRgb (txb, tyb, byTileYuv, (unsigned char *)outBuf);
Ed Tanous93f987d2017-04-17 17:52:36 -0700720 }
721
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700722 void vqDecompress(int txb, int tyb, char *outBuf, uint8_t QT_TableSelection,
723 struct ColorCache *VQ) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700724 unsigned char *ptr, i;
725 unsigned char byTileYuv[192];
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700726 int data;
Ed Tanous93f987d2017-04-17 17:52:36 -0700727
728 ptr = byTileYuv;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700729 if (VQ->bitMapBits == 0) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700730 for (i = 0; i < 64; i++) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700731 ptr[0] = (VQ->color[VQ->index[0]] & 0xFF0000) >> 16;
732 ptr[64] = (VQ->color[VQ->index[0]] & 0x00FF00) >> 8;
733 ptr[128] = VQ->color[VQ->index[0]] & 0x0000FF;
Ed Tanous93f987d2017-04-17 17:52:36 -0700734 ptr += 1;
735 }
736 } else {
737 for (i = 0; i < 64; i++) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700738 data = static_cast<int>(lookKbits(VQ->bitMapBits));
739 ptr[0] = (VQ->color[VQ->index[data]] & 0xFF0000) >> 16;
740 ptr[64] = (VQ->color[VQ->index[data]] & 0x00FF00) >> 8;
741 ptr[128] = VQ->color[VQ->index[data]] & 0x0000FF;
Ed Tanous93f987d2017-04-17 17:52:36 -0700742 ptr += 1;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700743 skipKbits(VQ->bitMapBits);
Ed Tanous93f987d2017-04-17 17:52:36 -0700744 }
745 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700746 // yuvToRgb (txb, tyb, byTileYuv, (unsigned char *)outBuf);
747 yuvToRgb(txb, tyb, byTileYuv, yuvBuffer.data(),
Ed Tanous911ac312017-08-15 09:37:42 -0700748 reinterpret_cast<unsigned char *>(outBuf));
Ed Tanous93f987d2017-04-17 17:52:36 -0700749 }
750
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700751 void moveBlockIndex() {
Ed Tanous93f987d2017-04-17 17:52:36 -0700752 if (yuvmode == YuvMode::YUV444) {
753 txb++;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700754 if (txb >= static_cast<int>(width / 8)) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700755 tyb++;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700756 if (tyb >= static_cast<int>(height / 8)) {
Ed Tanous911ac312017-08-15 09:37:42 -0700757 tyb = 0;
758 }
Ed Tanous93f987d2017-04-17 17:52:36 -0700759 txb = 0;
760 }
761 } else {
762 txb++;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700763 if (txb >= static_cast<int>(width / 16)) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700764 tyb++;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700765 if (tyb >= static_cast<int>(height / 16)) {
Ed Tanous911ac312017-08-15 09:37:42 -0700766 tyb = 0;
767 }
Ed Tanous93f987d2017-04-17 17:52:36 -0700768 txb = 0;
769 }
770 }
771 }
772
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700773 void initColorTable() {
Ed Tanous93f987d2017-04-17 17:52:36 -0700774 int i, x;
775 int nScale = 1L << 16; // equal to power(2,16)
776 int nHalf = nScale >> 1;
777
778#define FIX(x) ((int)((x)*nScale + 0.5))
779
780 /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
781 /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700782 /* Cr=>r value is nearest int to 1.597656 * x */
783 /* Cb=>b value is nearest int to 2.015625 * x */
784 /* Cr=>g value is scaled-up -0.8125 * x */
785 /* Cb=>g value is scaled-up -0.390625 * x */
Ed Tanous93f987d2017-04-17 17:52:36 -0700786 for (i = 0, x = -128; i < 256; i++, x++) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700787 mCrToR[i] = (FIX(1.597656) * x + nHalf) >> 16;
788 mCbToB[i] = (FIX(2.015625) * x + nHalf) >> 16;
789 mCrToG[i] = (-FIX(0.8125) * x + nHalf) >> 16;
790 mCbToG[i] = (-FIX(0.390625) * x + nHalf) >> 16;
Ed Tanous93f987d2017-04-17 17:52:36 -0700791 }
792 for (i = 0, x = -16; i < 256; i++, x++) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700793 mY[i] = (FIX(1.164) * x + nHalf) >> 16;
Ed Tanous93f987d2017-04-17 17:52:36 -0700794 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700795 // For color Text Enchance Y Re-map. Recommend to disable in default
Ed Tanous93f987d2017-04-17 17:52:36 -0700796 /*
797 for (i = 0; i < (VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate);
798 i++) {
799 temp = (double)i /
800 VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate;
801 temp1 = 1.0 / VideoEngineInfo->INFData.Gamma1Parameter;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700802 mY[i] =
Ed Tanous93f987d2017-04-17 17:52:36 -0700803 (BYTE)(VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate * pow (temp,
804 temp1));
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700805 if (mY[i] > 255) mY[i] = 255;
Ed Tanous93f987d2017-04-17 17:52:36 -0700806 }
807 for (i = (VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate); i < 256;
808 i++) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700809 mY[i] =
Ed Tanous93f987d2017-04-17 17:52:36 -0700810 (BYTE)((VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate) + (256 -
811 VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate) * ( pow((double)((i -
812 VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate) / (256 -
813 (VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate))), (1.0 /
814 VideoEngineInfo->INFData.Gamma2Parameter)) ));
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700815 if (mY[i] > 255) mY[i] = 255;
Ed Tanous93f987d2017-04-17 17:52:36 -0700816 }
817 */
818 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700819 void loadHuffmanTable(HuffmanTable *HT, const unsigned char *nrcode,
820 const unsigned char *value,
821 const unsigned short int *Huff_code) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700822 unsigned char k, j, i;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700823 unsigned int code, codeIndex;
Ed Tanous93f987d2017-04-17 17:52:36 -0700824
825 for (j = 1; j <= 16; j++) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700826 HT->length[j] = nrcode[j];
Ed Tanous93f987d2017-04-17 17:52:36 -0700827 }
Ed Tanous911ac312017-08-15 09:37:42 -0700828 for (i = 0, k = 1; k <= 16; k++) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700829 for (j = 0; j < HT->length[k]; j++) {
830 HT->v[wordHiLo(k, j)] = value[i];
Ed Tanous93f987d2017-04-17 17:52:36 -0700831 i++;
832 }
Ed Tanous911ac312017-08-15 09:37:42 -0700833 }
Ed Tanous93f987d2017-04-17 17:52:36 -0700834
835 code = 0;
836 for (k = 1; k <= 16; k++) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700837 HT->minorCode[k] = static_cast<unsigned short int>(code);
838 for (j = 1; j <= HT->length[k]; j++) {
Ed Tanous911ac312017-08-15 09:37:42 -0700839 code++;
840 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700841 HT->majorCode[k] = static_cast<unsigned short int>(code - 1);
Ed Tanous93f987d2017-04-17 17:52:36 -0700842 code *= 2;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700843 if (HT->length[k] == 0) {
844 HT->minorCode[k] = 0xFFFF;
845 HT->majorCode[k] = 0;
Ed Tanous93f987d2017-04-17 17:52:36 -0700846 }
847 }
848
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700849 HT->len[0] = 2;
Ed Tanous93f987d2017-04-17 17:52:36 -0700850 i = 2;
851
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700852 for (codeIndex = 1; codeIndex < 65535; codeIndex++) {
853 if (codeIndex < Huff_code[i]) {
854 HT->len[codeIndex] = static_cast<unsigned char>(Huff_code[i + 1]);
Ed Tanous93f987d2017-04-17 17:52:36 -0700855 } else {
856 i = i + 2;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700857 HT->len[codeIndex] = static_cast<unsigned char>(Huff_code[i + 1]);
Ed Tanous93f987d2017-04-17 17:52:36 -0700858 }
859 }
860 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700861 void initJpgTable() {
862 initColorTable();
863 prepareRangeLimitTable();
864 loadHuffmanTable(&htdc[0], stdDcLuminanceNrcodes, stdDcLuminanceValues,
865 dcLuminanceHuffmancode);
866 loadHuffmanTable(&htac[0], stdAcLuminanceNrcodes, stdAcLuminanceValues,
867 acLuminanceHuffmancode);
868 loadHuffmanTable(&htdc[1], stdDcChrominanceNrcodes, stdDcChrominanceValues,
869 dcChrominanceHuffmancode);
870 loadHuffmanTable(&htac[1], stdAcChrominanceNrcodes, stdAcChrominanceValues,
871 acChrominanceHuffmancode);
Ed Tanous93f987d2017-04-17 17:52:36 -0700872 }
873
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700874 void prepareRangeLimitTable()
Ed Tanous93f987d2017-04-17 17:52:36 -0700875 /* Allocate and fill in the sample_range_limit table */
876 {
877 int j;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700878 rlimitTable = reinterpret_cast<unsigned char *>(malloc(5 * 256L + 128));
Ed Tanous93f987d2017-04-17 17:52:36 -0700879 /* First segment of "simple" table: limit[x] = 0 for x < 0 */
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700880 memset((void *)rlimitTable, 0, 256);
881 rlimitTable += 256; /* allow negative subscripts of simple table */
Ed Tanous93f987d2017-04-17 17:52:36 -0700882 /* Main part of "simple" table: limit[x] = x */
Ed Tanous911ac312017-08-15 09:37:42 -0700883 for (j = 0; j < 256; j++) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700884 rlimitTable[j] = j;
Ed Tanous911ac312017-08-15 09:37:42 -0700885 }
Ed Tanous93f987d2017-04-17 17:52:36 -0700886 /* End of simple table, rest of first half of post-IDCT table */
Ed Tanous911ac312017-08-15 09:37:42 -0700887 for (j = 256; j < 640; j++) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700888 rlimitTable[j] = 255;
Ed Tanous911ac312017-08-15 09:37:42 -0700889 }
Ed Tanous93f987d2017-04-17 17:52:36 -0700890
891 /* Second half of post-IDCT table */
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700892 memset((void *)(rlimitTable + 640), 0, 384);
Ed Tanous911ac312017-08-15 09:37:42 -0700893 for (j = 0; j < 128; j++) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700894 rlimitTable[j + 1024] = j;
Ed Tanous911ac312017-08-15 09:37:42 -0700895 }
Ed Tanous93f987d2017-04-17 17:52:36 -0700896 }
897
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700898 inline unsigned short int wordHiLo(uint8_t byte_high, uint8_t byte_low) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700899 return (byte_high << 8) + byte_low;
900 }
901
902 // river
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700903 void processHuffmanDataUnit(uint8_t DC_nr, uint8_t AC_nr,
904 signed short int *previous_DC,
905 unsigned short int position) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700906 uint8_t nr = 0;
907 uint8_t k;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700908 unsigned short int tmpHcode;
909 uint8_t sizeVal, count0;
910 unsigned short int *minCode;
911 uint8_t *huffValues;
912 uint8_t byteTemp;
Ed Tanous93f987d2017-04-17 17:52:36 -0700913
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700914 minCode = htdc[DC_nr].minorCode;
915 // maj_code=htdc[DC_nr].majorCode;
916 huffValues = htdc[DC_nr].v;
Ed Tanous93f987d2017-04-17 17:52:36 -0700917
918 // DC
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700919 k = htdc[DC_nr].len[static_cast<unsigned short int>(codebuf >> 16)];
Ed Tanous93f987d2017-04-17 17:52:36 -0700920 // river
921 // tmp_Hcode=lookKbits(k);
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700922 tmpHcode = static_cast<unsigned short int>(codebuf >> (32 - k));
Ed Tanous93f987d2017-04-17 17:52:36 -0700923 skipKbits(k);
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700924 sizeVal =
925 huffValues[wordHiLo(k, static_cast<uint8_t>(tmpHcode - minCode[k]))];
926 if (sizeVal == 0) {
927 dctCoeff[position + 0] = *previous_DC;
Ed Tanous911ac312017-08-15 09:37:42 -0700928 } else {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700929 dctCoeff[position + 0] = *previous_DC + getKbits(sizeVal);
930 *previous_DC = dctCoeff[position + 0];
Ed Tanous93f987d2017-04-17 17:52:36 -0700931 }
932
933 // Second, AC coefficient decoding
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700934 minCode = htac[AC_nr].minorCode;
935 // maj_code=htac[AC_nr].majorCode;
936 huffValues = htac[AC_nr].v;
Ed Tanous93f987d2017-04-17 17:52:36 -0700937
938 nr = 1; // AC coefficient
939 do {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700940 k = htac[AC_nr].len[static_cast<unsigned short int>(codebuf >> 16)];
941 tmpHcode = static_cast<unsigned short int>(codebuf >> (32 - k));
Ed Tanous93f987d2017-04-17 17:52:36 -0700942 skipKbits(k);
943
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700944 byteTemp =
945 huffValues[wordHiLo(k, static_cast<uint8_t>(tmpHcode - minCode[k]))];
946 sizeVal = byteTemp & 0xF;
947 count0 = byteTemp >> 4;
948 if (sizeVal == 0) {
949 if (count0 != 0xF) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700950 break;
951 }
952 nr += 16;
953 } else {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700954 nr += count0; // skip count_0 zeroes
955 dctCoeff[position + dezigzag[nr++]] = getKbits(sizeVal);
Ed Tanous93f987d2017-04-17 17:52:36 -0700956 }
957 } while (nr < 64);
958 }
959
960 unsigned short int lookKbits(uint8_t k) {
961 unsigned short int revcode;
962
Ed Tanous911ac312017-08-15 09:37:42 -0700963 revcode = static_cast<unsigned short int>(codebuf >> (32 - k));
Ed Tanous93f987d2017-04-17 17:52:36 -0700964
965 return (revcode);
966 }
967
968 void skipKbits(uint8_t k) {
969 unsigned long readbuf;
970
971 if ((newbits - k) <= 0) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700972 readbuf = buffer[bufferIndex];
973 bufferIndex++;
Ed Tanous93f987d2017-04-17 17:52:36 -0700974 codebuf =
975 (codebuf << k) | ((newbuf | (readbuf >> (newbits))) >> (32 - k));
976 newbuf = readbuf << (k - newbits);
977 newbits = 32 + newbits - k;
978 } else {
979 codebuf = (codebuf << k) | (newbuf >> (32 - k));
980 newbuf = newbuf << k;
981 newbits -= k;
982 }
983 }
984
985 signed short int getKbits(uint8_t k) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700986 signed short int signedWordvalue;
Ed Tanous93f987d2017-04-17 17:52:36 -0700987
988 // river
989 // signed_wordvalue=lookKbits(k);
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700990 signedWordvalue = static_cast<unsigned short int>(codebuf >> (32 - k));
991 if (((1L << (k - 1)) & signedWordvalue) == 0) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700992 // neg_pow2 was previously defined as the below. It seemed silly to keep
993 // a table of values around for something
994 // THat's relatively easy to compute, so it was replaced with the
995 // appropriate math
996 // signed_wordvalue = signed_wordvalue - (0xFFFF >> (16 - k));
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700997 std::array<signed short int, 17> negPow2 = {
Ed Tanous93f987d2017-04-17 17:52:36 -0700998 0, -1, -3, -7, -15, -31, -63, -127,
999 -255, -511, -1023, -2047, -4095, -8191, -16383, -32767};
1000
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001001 signedWordvalue = signedWordvalue + negPow2[k];
Ed Tanous93f987d2017-04-17 17:52:36 -07001002 }
1003 skipKbits(k);
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001004 return signedWordvalue;
Ed Tanous93f987d2017-04-17 17:52:36 -07001005 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001006 int initJpgDecoding() {
1007 bytePos = 0;
1008 loadQuantTable(qt[0]);
1009 loadQuantTableCb(qt[1]);
Ed Tanous93f987d2017-04-17 17:52:36 -07001010 // Note: Added for Dual-JPEG
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001011 loadAdvanceQuantTable(qt[2]);
1012 loadAdvanceQuantTableCb(qt[3]);
Ed Tanous93f987d2017-04-17 17:52:36 -07001013 return 1;
1014 }
1015
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001016 void setQuantTable(const uint8_t *basic_table, uint8_t scale_factor,
1017 std::array<uint8_t, 64> &newtable)
Ed Tanous93f987d2017-04-17 17:52:36 -07001018 // Set quantization table and zigzag reorder it
1019 {
1020 uint8_t i;
1021 long temp;
1022 for (i = 0; i < 64; i++) {
Ed Tanous911ac312017-08-15 09:37:42 -07001023 temp = (static_cast<long>(basic_table[i] * 16) / scale_factor);
Ed Tanous93f987d2017-04-17 17:52:36 -07001024 /* limit the values to the valid range */
Ed Tanous911ac312017-08-15 09:37:42 -07001025 if (temp <= 0L) {
1026 temp = 1L;
1027 }
1028 if (temp > 255L) {
1029 temp = 255L; /* limit to baseline range if requested */
1030 }
1031 newtable[zigzag[i]] = static_cast<uint8_t>(temp);
Ed Tanous93f987d2017-04-17 17:52:36 -07001032 }
1033 }
1034
1035 void updatereadbuf(uint32_t *codebuf, uint32_t *newbuf, int walks,
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001036 int *newbits, std::vector<uint32_t> &buffer) {
Ed Tanous93f987d2017-04-17 17:52:36 -07001037 unsigned long readbuf;
1038
1039 if ((*newbits - walks) <= 0) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001040 readbuf = buffer[bufferIndex];
1041 bufferIndex++;
Ed Tanous93f987d2017-04-17 17:52:36 -07001042 *codebuf = (*codebuf << walks) |
1043 ((*newbuf | (readbuf >> (*newbits))) >> (32 - walks));
1044 *newbuf = readbuf << (walks - *newbits);
1045 *newbits = 32 + *newbits - walks;
1046 } else {
1047 *codebuf = (*codebuf << walks) | (*newbuf >> (32 - walks));
1048 *newbuf = *newbuf << walks;
1049 *newbits -= walks;
1050 }
1051 }
1052
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001053 uint32_t decode(std::vector<uint32_t> &bufferVector, unsigned long width,
1054 unsigned long height, YuvMode yuvmode_in, int ySelector,
1055 int uvSelector) {
1056 ColorCache decodeColor;
1057 if (width != userWidth || height != userHeight || yuvmode_in != yuvmode ||
1058 ySelector != ySelector || uvSelector != uvSelector) {
Ed Tanousb078cf32017-04-18 14:51:21 -07001059 yuvmode = yuvmode_in;
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001060 ySelector = ySelector; // 0-7
1061 uvSelector = uvSelector; // 0-7
1062 userHeight = height;
1063 userWidth = width;
1064 width = width;
1065 height = height;
Ed Tanous93f987d2017-04-17 17:52:36 -07001066
Ed Tanousb078cf32017-04-18 14:51:21 -07001067 // TODO(ed) Magic number section. Document appropriately
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001068 advanceSelector = 0; // 0-7
1069 mapping = 0; // 0 or 1
Ed Tanous1ff48782017-04-18 12:45:08 -07001070
Ed Tanousb078cf32017-04-18 14:51:21 -07001071 if (yuvmode == YuvMode::YUV420) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001072 if ((width % 16) != 0u) {
1073 width = width + 16 - (width % 16);
Ed Tanousb078cf32017-04-18 14:51:21 -07001074 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001075 if ((height % 16) != 0u) {
1076 height = height + 16 - (height % 16);
Ed Tanousb078cf32017-04-18 14:51:21 -07001077 }
1078 } else {
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001079 if ((width % 8) != 0u) {
1080 width = width + 8 - (width % 8);
Ed Tanousb078cf32017-04-18 14:51:21 -07001081 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001082 if ((height % 8) != 0u) {
1083 height = height + 8 - (height % 8);
Ed Tanousb078cf32017-04-18 14:51:21 -07001084 }
1085 }
Ed Tanous93f987d2017-04-17 17:52:36 -07001086
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001087 initJpgDecoding();
Ed Tanouscc9e2c22017-04-18 14:32:02 -07001088 }
1089 // TODO(ed) cleanup cruft
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001090 buffer = bufferVector.data();
Ed Tanous93f987d2017-04-17 17:52:36 -07001091
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001092 codebuf = bufferVector[0];
1093 newbuf = bufferVector[1];
1094 bufferIndex = 2;
Ed Tanous93f987d2017-04-17 17:52:36 -07001095
1096 txb = tyb = 0;
1097 newbits = 32;
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001098 dcy = dcCb = dcCr = 0;
Ed Tanous93f987d2017-04-17 17:52:36 -07001099
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001100 static const uint32_t vqHeaderMask = 0x01;
1101 static const uint32_t vqNoUpdateHeader = 0x00;
1102 static const uint32_t vqUpdateHeader = 0x01;
1103 static const int vqNoUpdateLength = 0x03;
1104 static const int vqUpdateLength = 0x1B;
1105 static const uint32_t vqIndexMask = 0x03;
1106 static const uint32_t vqColorMask = 0xFFFFFF;
Ed Tanous1ff48782017-04-18 12:45:08 -07001107
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001108 static const int blockAsT2100StartLength = 0x04;
1109 static const int blockAsT2100SkipLength = 20; // S:1 H:3 X:8 Y:8
Ed Tanous1ff48782017-04-18 12:45:08 -07001110
Ed Tanous93f987d2017-04-17 17:52:36 -07001111 do {
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001112 auto blockHeader = static_cast<JpgBlock>((codebuf >> 28) & 0xFF);
1113 switch (blockHeader) {
Ed Tanous93f987d2017-04-17 17:52:36 -07001114 case JpgBlock::JPEG_NO_SKIP_CODE:
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001115 updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, &newbits,
1116 bufferVector);
1117 decompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0);
Ed Tanous93f987d2017-04-17 17:52:36 -07001118 break;
1119 case JpgBlock::FRAME_END_CODE:
1120 return 0;
1121 break;
1122 case JpgBlock::JPEG_SKIP_CODE:
1123
1124 txb = (codebuf & 0x0FF00000) >> 20;
1125 tyb = (codebuf & 0x0FF000) >> 12;
1126
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001127 updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, &newbits,
1128 bufferVector);
1129 decompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0);
Ed Tanous93f987d2017-04-17 17:52:36 -07001130 break;
1131 case JpgBlock::VQ_NO_SKIP_1_COLOR_CODE:
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001132 updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, &newbits,
1133 bufferVector);
1134 decodeColor.bitMapBits = 0;
Ed Tanous93f987d2017-04-17 17:52:36 -07001135
Ed Tanousd5f39992017-04-18 13:41:22 -07001136 for (int i = 0; i < 1; i++) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001137 decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask);
1138 if (((codebuf >> 31) & vqHeaderMask) == vqNoUpdateHeader) {
1139 updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, &newbits,
1140 bufferVector);
Ed Tanous93f987d2017-04-17 17:52:36 -07001141 } else {
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001142 decodeColor.color[decodeColor.index[i]] =
1143 ((codebuf >> 5) & vqColorMask);
1144 updatereadbuf(&codebuf, &newbuf, vqUpdateLength, &newbits,
1145 bufferVector);
Ed Tanous93f987d2017-04-17 17:52:36 -07001146 }
1147 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001148 vqDecompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0,
1149 &decodeColor);
Ed Tanous93f987d2017-04-17 17:52:36 -07001150 break;
1151 case JpgBlock::VQ_SKIP_1_COLOR_CODE:
1152 txb = (codebuf & 0x0FF00000) >> 20;
1153 tyb = (codebuf & 0x0FF000) >> 12;
1154
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001155 updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, &newbits,
1156 bufferVector);
1157 decodeColor.bitMapBits = 0;
Ed Tanous93f987d2017-04-17 17:52:36 -07001158
Ed Tanousd5f39992017-04-18 13:41:22 -07001159 for (int i = 0; i < 1; i++) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001160 decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask);
1161 if (((codebuf >> 31) & vqHeaderMask) == vqNoUpdateHeader) {
1162 updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, &newbits,
1163 bufferVector);
Ed Tanous93f987d2017-04-17 17:52:36 -07001164 } else {
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001165 decodeColor.color[decodeColor.index[i]] =
1166 ((codebuf >> 5) & vqColorMask);
1167 updatereadbuf(&codebuf, &newbuf, vqUpdateLength, &newbits,
1168 bufferVector);
Ed Tanous93f987d2017-04-17 17:52:36 -07001169 }
1170 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001171 vqDecompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0,
1172 &decodeColor);
Ed Tanous93f987d2017-04-17 17:52:36 -07001173 break;
1174
1175 case JpgBlock::VQ_NO_SKIP_2_COLOR_CODE:
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001176 updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, &newbits,
1177 bufferVector);
1178 decodeColor.bitMapBits = 1;
Ed Tanous93f987d2017-04-17 17:52:36 -07001179
Ed Tanousd5f39992017-04-18 13:41:22 -07001180 for (int i = 0; i < 2; i++) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001181 decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask);
1182 if (((codebuf >> 31) & vqHeaderMask) == vqNoUpdateHeader) {
1183 updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, &newbits,
1184 bufferVector);
Ed Tanous93f987d2017-04-17 17:52:36 -07001185 } else {
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001186 decodeColor.color[decodeColor.index[i]] =
1187 ((codebuf >> 5) & vqColorMask);
1188 updatereadbuf(&codebuf, &newbuf, vqUpdateLength, &newbits,
1189 bufferVector);
Ed Tanous93f987d2017-04-17 17:52:36 -07001190 }
1191 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001192 vqDecompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0,
1193 &decodeColor);
Ed Tanous93f987d2017-04-17 17:52:36 -07001194 break;
1195 case JpgBlock::VQ_SKIP_2_COLOR_CODE:
1196 txb = (codebuf & 0x0FF00000) >> 20;
1197 tyb = (codebuf & 0x0FF000) >> 12;
1198
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001199 updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, &newbits,
1200 bufferVector);
1201 decodeColor.bitMapBits = 1;
Ed Tanous93f987d2017-04-17 17:52:36 -07001202
Ed Tanousd5f39992017-04-18 13:41:22 -07001203 for (int i = 0; i < 2; i++) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001204 decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask);
1205 if (((codebuf >> 31) & vqHeaderMask) == vqNoUpdateHeader) {
1206 updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, &newbits,
1207 bufferVector);
Ed Tanous93f987d2017-04-17 17:52:36 -07001208 } else {
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001209 decodeColor.color[decodeColor.index[i]] =
1210 ((codebuf >> 5) & vqColorMask);
1211 updatereadbuf(&codebuf, &newbuf, vqUpdateLength, &newbits,
1212 bufferVector);
Ed Tanous93f987d2017-04-17 17:52:36 -07001213 }
1214 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001215 vqDecompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0,
1216 &decodeColor);
Ed Tanous93f987d2017-04-17 17:52:36 -07001217
1218 break;
1219 case JpgBlock::VQ_NO_SKIP_4_COLOR_CODE:
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001220 updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, &newbits,
1221 bufferVector);
1222 decodeColor.bitMapBits = 2;
Ed Tanous93f987d2017-04-17 17:52:36 -07001223
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001224 for (unsigned char &i : decodeColor.index) {
1225 i = ((codebuf >> 29) & vqIndexMask);
1226 if (((codebuf >> 31) & vqHeaderMask) == vqNoUpdateHeader) {
1227 updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, &newbits,
1228 bufferVector);
Ed Tanous93f987d2017-04-17 17:52:36 -07001229 } else {
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001230 decodeColor.color[i] = ((codebuf >> 5) & vqColorMask);
1231 updatereadbuf(&codebuf, &newbuf, vqUpdateLength, &newbits,
1232 bufferVector);
Ed Tanous93f987d2017-04-17 17:52:36 -07001233 }
1234 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001235 vqDecompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0,
1236 &decodeColor);
Ed Tanous93f987d2017-04-17 17:52:36 -07001237
1238 break;
1239
1240 case JpgBlock::VQ_SKIP_4_COLOR_CODE:
1241 txb = (codebuf & 0x0FF00000) >> 20;
1242 tyb = (codebuf & 0x0FF000) >> 12;
1243
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001244 updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, &newbits,
1245 bufferVector);
1246 decodeColor.bitMapBits = 2;
Ed Tanous93f987d2017-04-17 17:52:36 -07001247
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001248 for (unsigned char &i : decodeColor.index) {
1249 i = ((codebuf >> 29) & vqIndexMask);
1250 if (((codebuf >> 31) & vqHeaderMask) == vqNoUpdateHeader) {
1251 updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, &newbits,
1252 bufferVector);
Ed Tanous93f987d2017-04-17 17:52:36 -07001253 } else {
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001254 decodeColor.color[i] = ((codebuf >> 5) & vqColorMask);
1255 updatereadbuf(&codebuf, &newbuf, vqUpdateLength, &newbits,
1256 bufferVector);
Ed Tanous93f987d2017-04-17 17:52:36 -07001257 }
1258 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001259 vqDecompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0,
1260 &decodeColor);
Ed Tanous93f987d2017-04-17 17:52:36 -07001261
1262 break;
1263 case JpgBlock::JPEG_SKIP_PASS2_CODE:
1264 txb = (codebuf & 0x0FF00000) >> 20;
1265 tyb = (codebuf & 0x0FF000) >> 12;
1266
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001267 updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, &newbits,
1268 bufferVector);
1269 decompress2Pass(txb, tyb, reinterpret_cast<char *>(outBuffer.data()),
1270 2);
Ed Tanous93f987d2017-04-17 17:52:36 -07001271
1272 break;
1273 default:
1274 // TODO(ed) propogate errors upstream
1275 return -1;
1276 break;
1277 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001278 moveBlockIndex();
Ed Tanous93f987d2017-04-17 17:52:36 -07001279
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001280 } while (bufferIndex <= bufferVector.size());
Ed Tanous93f987d2017-04-17 17:52:36 -07001281
1282 return -1;
1283 }
1284
1285#ifdef cimg_version
1286 void dump_to_bitmap_file() {
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001287 cimg_library::CImg<unsigned char> image(width, height, 1, 3);
1288 for (int y = 0; y < width; y++) {
1289 for (int x = 0; x < height; x++) {
1290 auto pixel = outBuffer[x + (y * width)];
1291 image(x, y, 0) = pixel.r;
1292 image(x, y, 1) = pixel.g;
1293 image(x, y, 2) = pixel.b;
Ed Tanous93f987d2017-04-17 17:52:36 -07001294 }
1295 }
1296 image.save("/tmp/file2.bmp");
1297 }
1298#endif
1299
1300 private:
Ed Tanous911ac312017-08-15 09:37:42 -07001301 YuvMode yuvmode{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001302 // width and height are the modes your display used
1303 unsigned long width{};
1304 unsigned long height{};
1305 unsigned long userWidth{};
1306 unsigned long userHeight{};
1307 unsigned char ySelector{};
1308 int scalefactor;
1309 int scalefactoruv;
1310 int advancescalefactor;
1311 int advancescalefactoruv;
1312 int mapping{};
1313 unsigned char uvSelector{};
1314 unsigned char advanceSelector{};
1315 int bytePos{}; // current byte position
Ed Tanous93f987d2017-04-17 17:52:36 -07001316
1317 // quantization tables, no more than 4 quantization tables
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001318 std::array<std::array<long, 64>, 4> qt{};
Ed Tanous93f987d2017-04-17 17:52:36 -07001319
1320 // DC huffman tables , no more than 4 (0..3)
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001321 std::array<HuffmanTable, 4> htdc{};
Ed Tanous93f987d2017-04-17 17:52:36 -07001322 // AC huffman tables (0..3)
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001323 std::array<HuffmanTable, 4> htac{};
1324 std::array<int, 256> mCrToR{};
1325 std::array<int, 256> mCbToB{};
1326 std::array<int, 256> mCrToG{};
1327 std::array<int, 256> mCbToG{};
1328 std::array<int, 256> mY{};
1329 unsigned long bufferIndex{};
Ed Tanous911ac312017-08-15 09:37:42 -07001330 uint32_t codebuf{}, newbuf{}, readbuf{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001331 const unsigned char *stdLuminanceQt{};
1332 const uint8_t *stdChrominanceQt{};
Ed Tanous93f987d2017-04-17 17:52:36 -07001333
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001334 signed short int dcy{}, dcCb{}, dcCr{}; // Coeficientii DC pentru Y,Cb,Cr
1335 signed short int dctCoeff[384]{};
1336 // std::vector<signed short int> dctCoeff; // Current DCT_coefficients
Ed Tanous93f987d2017-04-17 17:52:36 -07001337 // quantization table number for Y, Cb, Cr
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001338 uint8_t yqNr = 0, cbQNr = 1, crQNr = 1;
Ed Tanous93f987d2017-04-17 17:52:36 -07001339 // DC Huffman table number for Y,Cb, Cr
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001340 uint8_t ydcNr = 0, cbDcNr = 1, crDcNr = 1;
Ed Tanous93f987d2017-04-17 17:52:36 -07001341 // AC Huffman table number for Y,Cb, Cr
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001342 uint8_t yacNr = 0, cbAcNr = 1, crAcNr = 1;
Ed Tanousd5f39992017-04-18 13:41:22 -07001343 int txb = 0;
1344 int tyb = 0;
Ed Tanous911ac312017-08-15 09:37:42 -07001345 int newbits{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001346 uint8_t *rlimitTable{};
1347 std::vector<RGB> yuvBuffer;
Ed Tanousd5f39992017-04-18 13:41:22 -07001348 // TODO(ed) this shouldn't exist. It is cruft that needs cleaning up
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001349 uint32_t *buffer{};
Ed Tanous93f987d2017-04-17 17:52:36 -07001350
1351 public:
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001352 std::vector<RGB> outBuffer;
Ed Tanous93f987d2017-04-17 17:52:36 -07001353};
Ed Tanous55c7b7a2018-05-22 15:27:24 -07001354} // namespace ast_video