Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(311)

Side by Side Diff: content/common/gpu/media/vaapi_jpeg_parser.cc

Issue 748023002: Add JPEG parser for JPEG decode acceleration (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/big_endian.h"
wuchengli 2014/12/08 09:25:10 vaapi_jpeg_parser.h already includes this. remove
kcwu 2014/12/16 06:23:53 Done.
6 #include "base/logging.h"
7 #include "content/common/gpu/media/vaapi_jpeg_parser.h"
8
9 using base::BigEndianReader;
10
11 namespace content {
12
13 VaapiJpegParser::VaapiJpegParser(const uint8_t* buffer, size_t length)
14 : buffer_(buffer), length_(length) {
15 }
16
17 VaapiJpegParser::~VaapiJpegParser() {
18 }
19
20 bool VaapiJpegParser::ParseSOF(BigEndianReader reader) {
21 // Spec B.2.2 Frame header syntax
22 uint8_t precision;
23
24 if (!reader.ReadU8(&precision))
25 return false;
26 if (!reader.ReadU16(&result_.visible_height))
27 return false;
28 if (!reader.ReadU16(&result_.visible_width))
29 return false;
30 if (!reader.ReadU8(&result_.num_component))
31 return false;
32
33 if (precision != 8) {
34 DLOG(ERROR) << "Only support 8 bit precision";
wuchengli 2014/12/08 09:25:11 print the actual precision
kcwu 2014/12/16 06:23:54 Done.
35 return false;
36 }
37 if (result_.num_component != 3 ||
38 result_.num_component >= arraysize(result_.components))
wuchengli 2014/12/08 09:25:10 add DLOG
kcwu 2014/12/16 06:23:53 Done.
39 return false;
40
41 // 64k*64k is max. in the JPEG standard. VAAPI doesn't support larger than
wuchengli 2014/12/08 09:25:10 s/max./the maximum/. s/64k*64k/Size 64k*64k/
kcwu 2014/12/16 06:23:53 Done.
42 // 16k*16k.
43 if (result_.visible_height > 16384 || result_.visible_width > 16384) {
wuchengli 2014/12/08 09:25:10 Should 16384 come from va.h or somewhere else?
kcwu 2014/12/16 06:23:53 There is no contant from va.h for this. It's heard
44 DLOG(ERROR) << "VAAPI don't support size larger than 16k*16k";
wuchengli 2014/12/08 09:25:10 print the actual size
kcwu 2014/12/16 06:23:54 Done.
45 return false;
46 }
47
48 for (int i = 0; i < result_.num_component; i++) {
49 JpegComponent* component = &result_.components[i];
wuchengli 2014/12/08 09:25:10 nit: use JpegComponent&?
kcwu 2014/12/16 06:23:53 Done.
50 if (!reader.ReadU8(&component->id))
51 return false;
52 if (component->id > result_.num_component) {
53 DLOG(ERROR) << "Only allow component id <= num_component: "
wuchengli 2014/12/08 09:25:11 Print both numbers at the end is not very clear. M
kcwu 2014/12/16 06:23:54 Done.
54 << static_cast<int>(component->id) << ","
55 << static_cast<int>(result_.num_component);
56 return false;
57 }
58 uint8_t hv;
wuchengli 2014/12/08 09:25:10 Is hv a common Jpeg terminology? If not, use more
kcwu 2014/12/16 06:23:54 It's not so meaningful to give a name for this. Th
59 if (!reader.ReadU8(&hv))
60 return false;
61 component->horizontal_sampling_factor = hv / 16;
62 component->vertical_sampling_factor = hv % 16;
63 if (!reader.ReadU8(&component->quantization_table_selector))
64 return false;
65 }
66
67 if (result_.components[0].horizontal_sampling_factor <
68 result_.components[1].horizontal_sampling_factor ||
69 result_.components[0].horizontal_sampling_factor <
70 result_.components[2].horizontal_sampling_factor) {
71 DLOG(ERROR) << "VAAPI don't supports horizontal sampling factor of Y"
72 << " smaller than Cb and Cr";
73 return false;
74 }
75 if (result_.components[0].vertical_sampling_factor <
76 result_.components[1].vertical_sampling_factor ||
77 result_.components[0].vertical_sampling_factor <
78 result_.components[2].vertical_sampling_factor) {
79 DLOG(ERROR) << "VAAPI don't supports vertical sampling factor of Y"
80 << " smaller than Cb and Cr";
81 return false;
82 }
83
84 return true;
85 }
86
87 bool VaapiJpegParser::ParseDQT(BigEndianReader reader) {
88 // Spec B.2.4.1 Quantization table-specification syntax
89 while (reader.remaining() > 0) {
90 uint8_t tmp;
91 if (!reader.ReadU8(&tmp))
92 return false;
93 uint8_t precision = tmp / 16;
94 uint8_t table_id = tmp % 16;
95 if (precision != 0) {
96 DLOG(ERROR) << "16 bits quantization table is not supported";
97 return false;
98 }
99 if (table_id >= kJpegQuantizationTableNum)
100 return false;
101
102 if (!reader.ReadBytes(&result_.q_table[table_id].value,
103 sizeof(result_.q_table[table_id].value)))
104 return false;
105 result_.q_table[table_id].valid = true;
106 }
107 return true;
108 }
109
110 bool VaapiJpegParser::ParseDHT(BigEndianReader reader) {
111 // Spec B.2.4.2 Huffman table-specification syntax
112 while (reader.remaining() > 0) {
113 uint8_t t;
114 if (!reader.ReadU8(&t))
115 return false;
116 int table_class = t / 16;
117 int table_id = t % 16;
118 if (table_class >= 2) // invalid
wuchengli 2014/12/08 09:25:10 Add DLOG. Add DLOG for all non reader.ReadU8 failu
kcwu 2014/12/16 06:23:54 Done.
119 return false;
120 if (table_id >= 2) // only support baseline
wuchengli 2014/12/08 09:25:10 Add DLOG
kcwu 2014/12/16 06:23:54 Done.
121 return false;
122
123 bool is_ac_table = (table_class == 1);
124 JpegHuffmanTable* table;
125 if (is_ac_table)
wuchengli 2014/12/08 09:25:10 just use table_class == 1 here?
kcwu 2014/12/16 06:23:54 Done.
126 table = &result_.ac_table[table_id];
127 else
128 table = &result_.dc_table[table_id];
129
130 size_t count = 0;
131 if (!reader.ReadBytes(&table->code_length, sizeof(table->code_length)))
132 return false;
133 for (unsigned i = 0; i < arraysize(table->code_length); i++)
wuchengli 2014/12/08 09:25:10 s/unsigned/size_t/
kcwu 2014/12/16 06:23:53 Done.
134 count += table->code_length[i];
135
136 if (count > sizeof(table->code_value))
wuchengli 2014/12/08 09:25:11 add DLOG
kcwu 2014/12/16 06:23:53 Done.
137 return false;
138 if (!reader.ReadBytes(&table->code_value, count))
139 return false;
140 table->valid = true;
141 }
142 return true;
143 }
144
145 bool VaapiJpegParser::ParseDRI(BigEndianReader reader) {
146 // Spec B.2.4.4 Restart interval definition syntax
147 return reader.ReadU16(&result_.restart_interval) && reader.remaining() == 0;
148 }
149
150 bool VaapiJpegParser::ParseSOS(BigEndianReader reader) {
151 // Spec B.2.3 Scan header syntax
152 if (!reader.ReadU8(&result_.scan.num_component))
153 return false;
154 if (result_.scan.num_component != result_.num_component)
wuchengli 2014/12/08 09:25:10 add DLOG
kcwu 2014/12/16 06:23:54 Done.
155 return false;
156
157 for (int i = 0; i < result_.scan.num_component; i++) {
158 JpegScan::Component* component = &result_.scan.components[i];
159 if (!reader.ReadU8(&component->component_selector))
160 return false;
161 uint8_t tmp;
162 if (!reader.ReadU8(&tmp))
163 return false;
164 component->dc_selector = tmp / 16;
165 component->ac_selector = tmp % 16;
166 if (component->component_selector != result_.components[i].id)
167 return false;
168 if (component->dc_selector >= kJpegHuffmanTableNum)
169 return false;
170 if (component->ac_selector >= kJpegHuffmanTableNum)
171 return false;
172 }
173
174 // unused fields, only for value checking
175 uint8_t spectral_selection_start;
176 uint8_t spectral_selection_end;
177 uint8_t point_transform;
178 if (!reader.ReadU8(&spectral_selection_start))
179 return false;
180 if (!reader.ReadU8(&spectral_selection_end))
181 return false;
182 if (!reader.ReadU8(&point_transform))
183 return false;
184 if (spectral_selection_start != 0 || spectral_selection_end != 63) {
185 DLOG(ERROR) << "Spectral selection should be 0,63 for baseline mode";
186 return false;
187 }
188 if (point_transform != 0) {
189 DLOG(ERROR) << "Point transform should be 0 for baseline mode";
190 return false;
191 }
192
193 return true;
194 }
195
196 bool VaapiJpegParser::ParseSOI(BigEndianReader reader) {
197 // Spec B.2.1 High-level syntax
198 uint8_t marker1;
199 uint8_t marker2;
200 bool has_marker_dqt = false;
201 bool has_marker_sos = false;
202
203 // Once reached SOS, all neccesary data are parsed.
204 while (!has_marker_sos) {
205 if (!reader.ReadU8(&marker1) || marker1 != MARKER1)
206 return false;
207
208 do {
209 if (!reader.ReadU8(&marker2))
210 return false;
211 } while (marker2 == MARKER1); // skip padding
212
213 uint16_t size;
214 if (!reader.ReadU16(&size))
215 return false;
216 if (reader.remaining() < size)
wuchengli 2014/12/08 09:25:10 add DLOG
kcwu 2014/12/16 06:23:54 Done.
217 return false;
218
219 // The size includes the size field itself.
220 if (size < sizeof(size))
wuchengli 2014/12/08 09:25:10 add DLOG
kcwu 2014/12/16 06:23:54 Done.
221 return false;
222 size -= sizeof(size);
223
224 switch (marker2) {
225 case SOF0:
226 if (!ParseSOF(BigEndianReader(reader.ptr(), size))) {
227 DLOG(ERROR) << "ParseSOF failed";
228 return false;
229 }
230 break;
231 case DQT:
232 if (!ParseDQT(BigEndianReader(reader.ptr(), size))) {
233 DLOG(ERROR) << "ParseDQT failed";
234 return false;
235 }
236 has_marker_dqt = true;
237 break;
238 case DHT:
239 if (!ParseDHT(BigEndianReader(reader.ptr(), size))) {
240 DLOG(ERROR) << "ParseDHT failed";
241 return false;
242 }
243 break;
244 case DRI:
245 if (!ParseDRI(BigEndianReader(reader.ptr(), size))) {
246 DLOG(ERROR) << "ParseDRI failed";
247 return false;
248 }
249 break;
250 case SOS:
251 if (!ParseSOS(BigEndianReader(reader.ptr(), size))) {
252 DLOG(ERROR) << "ParseSOS failed";
253 return false;
254 }
255 has_marker_sos = true;
256 break;
257 default:
258 DVLOG(4) << "unknown marker " << static_cast<int>(marker2);
wuchengli 2014/12/08 09:25:10 Why do we need this cast?
kcwu 2014/12/16 06:23:53 marker2 is char. It will print the character if no
259 break;
260 }
261 reader.Skip(size);
262 }
263
264 if (!has_marker_dqt) {
265 DLOG(ERROR) << "No DQT marker found";
266 return false;
267 }
268
269 // Scan data is following scan header immediately.
wuchengli 2014/12/08 09:25:11 s/is following/follows/
kcwu 2014/12/16 06:23:54 Done.
270 result_.scan.data = reader.ptr();
271 result_.scan.data_size = reader.remaining();
272
273 return true;
274 }
275
276 bool VaapiJpegParser::Parse() {
277 BigEndianReader reader(reinterpret_cast<const char*>(buffer_), length_);
278 memset(&result_, 0, sizeof(result_));
279
280 uint8_t marker1;
281 uint8_t marker2;
wuchengli 2014/12/08 09:25:10 nit: combine with the previous line
kcwu 2014/12/16 06:23:53 Done.
282 if (!reader.ReadU8(&marker1) || marker1 != MARKER1 ||
283 !reader.ReadU8(&marker2) || marker2 != SOI) {
284 LOG(ERROR) << "Not a JPEG";
285 return false;
286 }
287
288 return ParseSOI(BigEndianReader(reader.ptr(), reader.remaining()));
289 }
290
291 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698