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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: content/common/gpu/media/vaapi_jpeg_parser.cc
diff --git a/content/common/gpu/media/vaapi_jpeg_parser.cc b/content/common/gpu/media/vaapi_jpeg_parser.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4f86efad6ce4207379489647ee8472d099cb4e19
--- /dev/null
+++ b/content/common/gpu/media/vaapi_jpeg_parser.cc
@@ -0,0 +1,291 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#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.
+#include "base/logging.h"
+#include "content/common/gpu/media/vaapi_jpeg_parser.h"
+
+using base::BigEndianReader;
+
+namespace content {
+
+VaapiJpegParser::VaapiJpegParser(const uint8_t* buffer, size_t length)
+ : buffer_(buffer), length_(length) {
+}
+
+VaapiJpegParser::~VaapiJpegParser() {
+}
+
+bool VaapiJpegParser::ParseSOF(BigEndianReader reader) {
+ // Spec B.2.2 Frame header syntax
+ uint8_t precision;
+
+ if (!reader.ReadU8(&precision))
+ return false;
+ if (!reader.ReadU16(&result_.visible_height))
+ return false;
+ if (!reader.ReadU16(&result_.visible_width))
+ return false;
+ if (!reader.ReadU8(&result_.num_component))
+ return false;
+
+ if (precision != 8) {
+ 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.
+ return false;
+ }
+ if (result_.num_component != 3 ||
+ result_.num_component >= arraysize(result_.components))
wuchengli 2014/12/08 09:25:10 add DLOG
kcwu 2014/12/16 06:23:53 Done.
+ return false;
+
+ // 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.
+ // 16k*16k.
+ 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
+ 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.
+ return false;
+ }
+
+ for (int i = 0; i < result_.num_component; i++) {
+ JpegComponent* component = &result_.components[i];
wuchengli 2014/12/08 09:25:10 nit: use JpegComponent&?
kcwu 2014/12/16 06:23:53 Done.
+ if (!reader.ReadU8(&component->id))
+ return false;
+ if (component->id > result_.num_component) {
+ 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.
+ << static_cast<int>(component->id) << ","
+ << static_cast<int>(result_.num_component);
+ return false;
+ }
+ 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
+ if (!reader.ReadU8(&hv))
+ return false;
+ component->horizontal_sampling_factor = hv / 16;
+ component->vertical_sampling_factor = hv % 16;
+ if (!reader.ReadU8(&component->quantization_table_selector))
+ return false;
+ }
+
+ if (result_.components[0].horizontal_sampling_factor <
+ result_.components[1].horizontal_sampling_factor ||
+ result_.components[0].horizontal_sampling_factor <
+ result_.components[2].horizontal_sampling_factor) {
+ DLOG(ERROR) << "VAAPI don't supports horizontal sampling factor of Y"
+ << " smaller than Cb and Cr";
+ return false;
+ }
+ if (result_.components[0].vertical_sampling_factor <
+ result_.components[1].vertical_sampling_factor ||
+ result_.components[0].vertical_sampling_factor <
+ result_.components[2].vertical_sampling_factor) {
+ DLOG(ERROR) << "VAAPI don't supports vertical sampling factor of Y"
+ << " smaller than Cb and Cr";
+ return false;
+ }
+
+ return true;
+}
+
+bool VaapiJpegParser::ParseDQT(BigEndianReader reader) {
+ // Spec B.2.4.1 Quantization table-specification syntax
+ while (reader.remaining() > 0) {
+ uint8_t tmp;
+ if (!reader.ReadU8(&tmp))
+ return false;
+ uint8_t precision = tmp / 16;
+ uint8_t table_id = tmp % 16;
+ if (precision != 0) {
+ DLOG(ERROR) << "16 bits quantization table is not supported";
+ return false;
+ }
+ if (table_id >= kJpegQuantizationTableNum)
+ return false;
+
+ if (!reader.ReadBytes(&result_.q_table[table_id].value,
+ sizeof(result_.q_table[table_id].value)))
+ return false;
+ result_.q_table[table_id].valid = true;
+ }
+ return true;
+}
+
+bool VaapiJpegParser::ParseDHT(BigEndianReader reader) {
+ // Spec B.2.4.2 Huffman table-specification syntax
+ while (reader.remaining() > 0) {
+ uint8_t t;
+ if (!reader.ReadU8(&t))
+ return false;
+ int table_class = t / 16;
+ int table_id = t % 16;
+ 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.
+ return false;
+ if (table_id >= 2) // only support baseline
wuchengli 2014/12/08 09:25:10 Add DLOG
kcwu 2014/12/16 06:23:54 Done.
+ return false;
+
+ bool is_ac_table = (table_class == 1);
+ JpegHuffmanTable* table;
+ 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.
+ table = &result_.ac_table[table_id];
+ else
+ table = &result_.dc_table[table_id];
+
+ size_t count = 0;
+ if (!reader.ReadBytes(&table->code_length, sizeof(table->code_length)))
+ return false;
+ 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.
+ count += table->code_length[i];
+
+ if (count > sizeof(table->code_value))
wuchengli 2014/12/08 09:25:11 add DLOG
kcwu 2014/12/16 06:23:53 Done.
+ return false;
+ if (!reader.ReadBytes(&table->code_value, count))
+ return false;
+ table->valid = true;
+ }
+ return true;
+}
+
+bool VaapiJpegParser::ParseDRI(BigEndianReader reader) {
+ // Spec B.2.4.4 Restart interval definition syntax
+ return reader.ReadU16(&result_.restart_interval) && reader.remaining() == 0;
+}
+
+bool VaapiJpegParser::ParseSOS(BigEndianReader reader) {
+ // Spec B.2.3 Scan header syntax
+ if (!reader.ReadU8(&result_.scan.num_component))
+ return false;
+ 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.
+ return false;
+
+ for (int i = 0; i < result_.scan.num_component; i++) {
+ JpegScan::Component* component = &result_.scan.components[i];
+ if (!reader.ReadU8(&component->component_selector))
+ return false;
+ uint8_t tmp;
+ if (!reader.ReadU8(&tmp))
+ return false;
+ component->dc_selector = tmp / 16;
+ component->ac_selector = tmp % 16;
+ if (component->component_selector != result_.components[i].id)
+ return false;
+ if (component->dc_selector >= kJpegHuffmanTableNum)
+ return false;
+ if (component->ac_selector >= kJpegHuffmanTableNum)
+ return false;
+ }
+
+ // unused fields, only for value checking
+ uint8_t spectral_selection_start;
+ uint8_t spectral_selection_end;
+ uint8_t point_transform;
+ if (!reader.ReadU8(&spectral_selection_start))
+ return false;
+ if (!reader.ReadU8(&spectral_selection_end))
+ return false;
+ if (!reader.ReadU8(&point_transform))
+ return false;
+ if (spectral_selection_start != 0 || spectral_selection_end != 63) {
+ DLOG(ERROR) << "Spectral selection should be 0,63 for baseline mode";
+ return false;
+ }
+ if (point_transform != 0) {
+ DLOG(ERROR) << "Point transform should be 0 for baseline mode";
+ return false;
+ }
+
+ return true;
+}
+
+bool VaapiJpegParser::ParseSOI(BigEndianReader reader) {
+ // Spec B.2.1 High-level syntax
+ uint8_t marker1;
+ uint8_t marker2;
+ bool has_marker_dqt = false;
+ bool has_marker_sos = false;
+
+ // Once reached SOS, all neccesary data are parsed.
+ while (!has_marker_sos) {
+ if (!reader.ReadU8(&marker1) || marker1 != MARKER1)
+ return false;
+
+ do {
+ if (!reader.ReadU8(&marker2))
+ return false;
+ } while (marker2 == MARKER1); // skip padding
+
+ uint16_t size;
+ if (!reader.ReadU16(&size))
+ return false;
+ if (reader.remaining() < size)
wuchengli 2014/12/08 09:25:10 add DLOG
kcwu 2014/12/16 06:23:54 Done.
+ return false;
+
+ // The size includes the size field itself.
+ if (size < sizeof(size))
wuchengli 2014/12/08 09:25:10 add DLOG
kcwu 2014/12/16 06:23:54 Done.
+ return false;
+ size -= sizeof(size);
+
+ switch (marker2) {
+ case SOF0:
+ if (!ParseSOF(BigEndianReader(reader.ptr(), size))) {
+ DLOG(ERROR) << "ParseSOF failed";
+ return false;
+ }
+ break;
+ case DQT:
+ if (!ParseDQT(BigEndianReader(reader.ptr(), size))) {
+ DLOG(ERROR) << "ParseDQT failed";
+ return false;
+ }
+ has_marker_dqt = true;
+ break;
+ case DHT:
+ if (!ParseDHT(BigEndianReader(reader.ptr(), size))) {
+ DLOG(ERROR) << "ParseDHT failed";
+ return false;
+ }
+ break;
+ case DRI:
+ if (!ParseDRI(BigEndianReader(reader.ptr(), size))) {
+ DLOG(ERROR) << "ParseDRI failed";
+ return false;
+ }
+ break;
+ case SOS:
+ if (!ParseSOS(BigEndianReader(reader.ptr(), size))) {
+ DLOG(ERROR) << "ParseSOS failed";
+ return false;
+ }
+ has_marker_sos = true;
+ break;
+ default:
+ 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
+ break;
+ }
+ reader.Skip(size);
+ }
+
+ if (!has_marker_dqt) {
+ DLOG(ERROR) << "No DQT marker found";
+ return false;
+ }
+
+ // 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.
+ result_.scan.data = reader.ptr();
+ result_.scan.data_size = reader.remaining();
+
+ return true;
+}
+
+bool VaapiJpegParser::Parse() {
+ BigEndianReader reader(reinterpret_cast<const char*>(buffer_), length_);
+ memset(&result_, 0, sizeof(result_));
+
+ uint8_t marker1;
+ uint8_t marker2;
wuchengli 2014/12/08 09:25:10 nit: combine with the previous line
kcwu 2014/12/16 06:23:53 Done.
+ if (!reader.ReadU8(&marker1) || marker1 != MARKER1 ||
+ !reader.ReadU8(&marker2) || marker2 != SOI) {
+ LOG(ERROR) << "Not a JPEG";
+ return false;
+ }
+
+ return ParseSOI(BigEndianReader(reader.ptr(), reader.remaining()));
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698