Commit bf308637 authored by Gil Dekel's avatar Gil Dekel Committed by Commit Bot

media: Lightweight WebP parser to extract feature and size information.

A lightweight WebP parser that validates that a given data stream
encodes a lossy WebP image by following the WebP Container Specification
found at: https://devsite.googleplex.com/speed/webp/docs/riff_container
After format validation, the parser uses the Vp8Parser to parse the VP8
key frame and returns a Vp8FrameHeader when parsing succeeds.
Note: This parser only supports lossy WebP formats.

There are two reasons in favor of rolling out a new lightweight WebP
parser (instead of using libwebp):
1) It's going to be used both by the render and gpu processes. Avoiding
a third-party lib is preferable.
2) the Vp8Parser was written to fit the VA-API better, i.e. it produces
objects that can be fed into the VA-API with minimum processing.

This change also moves the VP8 parser from //media/filters to
//media/parser.

Bug: 877694
Test: WebpParserTest.*
Change-Id: Ia553bc320cf0c136a859d24a4422e2bcc6e9c2c1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1617637
Commit-Queue: Gil Dekel <gildekel@chromium.org>
Reviewed-by: default avatarMiguel Casas <mcasas@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Reviewed-by: default avatarAndres Calderon Jaramillo <andrescj@chromium.org>
Cr-Commit-Position: refs/heads/master@{#663975}
parent 5f2ed3c4
...@@ -315,18 +315,6 @@ if (proprietary_codecs) { ...@@ -315,18 +315,6 @@ if (proprietary_codecs) {
} }
} }
fuzzer_test("media_vp8_parser_fuzzer") {
sources = [
"filters/vp8_parser_fuzzertest.cc",
]
deps = [
":test_support",
"//base",
]
libfuzzer_options = [ "max_len = 400000" ]
dict = "test/vp8.dict"
}
fuzzer_test("media_vp9_parser_fuzzer") { fuzzer_test("media_vp9_parser_fuzzer") {
sources = [ sources = [
"filters/vp9_parser_fuzzertest.cc", "filters/vp9_parser_fuzzertest.cc",
......
...@@ -65,10 +65,6 @@ jumbo_source_set("filters") { ...@@ -65,10 +65,6 @@ jumbo_source_set("filters") {
"video_cadence_estimator.h", "video_cadence_estimator.h",
"video_renderer_algorithm.cc", "video_renderer_algorithm.cc",
"video_renderer_algorithm.h", "video_renderer_algorithm.h",
"vp8_bool_decoder.cc",
"vp8_bool_decoder.h",
"vp8_parser.cc",
"vp8_parser.h",
"vp9_bool_decoder.cc", "vp9_bool_decoder.cc",
"vp9_bool_decoder.h", "vp9_bool_decoder.h",
"vp9_compressed_header_parser.cc", "vp9_compressed_header_parser.cc",
...@@ -289,8 +285,6 @@ source_set("unit_tests") { ...@@ -289,8 +285,6 @@ source_set("unit_tests") {
"video_cadence_estimator_unittest.cc", "video_cadence_estimator_unittest.cc",
"video_decoder_stream_unittest.cc", "video_decoder_stream_unittest.cc",
"video_renderer_algorithm_unittest.cc", "video_renderer_algorithm_unittest.cc",
"vp8_bool_decoder_unittest.cc",
"vp8_parser_unittest.cc",
"vp9_parser_unittest.cc", "vp9_parser_unittest.cc",
"vp9_raw_bits_reader_unittest.cc", "vp9_raw_bits_reader_unittest.cc",
] ]
......
...@@ -276,6 +276,7 @@ source_set("common") { ...@@ -276,6 +276,7 @@ source_set("common") {
":buildflags", ":buildflags",
"//base", "//base",
"//media", "//media",
"//media/parsers",
"//ui/gfx:buffer_types", "//ui/gfx:buffer_types",
"//ui/gfx:memory_buffer", "//ui/gfx:memory_buffer",
"//ui/gfx/geometry", "//ui/gfx/geometry",
...@@ -482,6 +483,7 @@ if (use_v4l2_codec || use_vaapi || is_mac || is_win) { ...@@ -482,6 +483,7 @@ if (use_v4l2_codec || use_vaapi || is_mac || is_win) {
"//base/test:test_support", "//base/test:test_support",
"//media:test_support", "//media:test_support",
"//media/gpu", "//media/gpu",
"//media/parsers",
"//mojo/core/embedder", "//mojo/core/embedder",
"//testing/gtest", "//testing/gtest",
"//third_party/ffmpeg", "//third_party/ffmpeg",
......
...@@ -11,12 +11,12 @@ ...@@ -11,12 +11,12 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/numerics/safe_conversions.h" #include "base/numerics/safe_conversions.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "media/filters/vp8_parser.h"
#include "media/gpu/macros.h" #include "media/gpu/macros.h"
#include "media/gpu/v4l2/v4l2_decode_surface.h" #include "media/gpu/v4l2/v4l2_decode_surface.h"
#include "media/gpu/v4l2/v4l2_decode_surface_handler.h" #include "media/gpu/v4l2/v4l2_decode_surface_handler.h"
#include "media/gpu/v4l2/v4l2_device.h" #include "media/gpu/v4l2/v4l2_device.h"
#include "media/gpu/vp8_picture.h" #include "media/gpu/vp8_picture.h"
#include "media/parsers/vp8_parser.h"
namespace media { namespace media {
namespace { namespace {
......
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
#define MEDIA_GPU_VAAPI_VAAPI_VP8_ACCELERATOR_H_ #define MEDIA_GPU_VAAPI_VAAPI_VP8_ACCELERATOR_H_
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "media/filters/vp8_parser.h"
#include "media/gpu/vp8_decoder.h" #include "media/gpu/vp8_decoder.h"
#include "media/parsers/vp8_parser.h"
namespace media { namespace media {
......
...@@ -11,10 +11,10 @@ ...@@ -11,10 +11,10 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "media/base/video_bitrate_allocation.h" #include "media/base/video_bitrate_allocation.h"
#include "media/filters/vp8_parser.h"
#include "media/gpu/vaapi/accelerated_video_encoder.h" #include "media/gpu/vaapi/accelerated_video_encoder.h"
#include "media/gpu/vp8_picture.h" #include "media/gpu/vp8_picture.h"
#include "media/gpu/vp8_reference_frame_vector.h" #include "media/gpu/vp8_reference_frame_vector.h"
#include "media/parsers/vp8_parser.h"
namespace media { namespace media {
......
...@@ -54,7 +54,6 @@ ...@@ -54,7 +54,6 @@
#include "media/filters/ffmpeg_video_decoder.h" #include "media/filters/ffmpeg_video_decoder.h"
#include "media/filters/in_memory_url_protocol.h" #include "media/filters/in_memory_url_protocol.h"
#include "media/filters/ivf_parser.h" #include "media/filters/ivf_parser.h"
#include "media/filters/vp8_parser.h"
#include "media/filters/vp9_parser.h" #include "media/filters/vp9_parser.h"
#include "media/filters/vpx_video_decoder.h" #include "media/filters/vpx_video_decoder.h"
#include "media/gpu/buildflags.h" #include "media/gpu/buildflags.h"
...@@ -63,6 +62,7 @@ ...@@ -63,6 +62,7 @@
#include "media/gpu/h264_dpb.h" #include "media/gpu/h264_dpb.h"
#include "media/gpu/test/video_accelerator_unittest_helpers.h" #include "media/gpu/test/video_accelerator_unittest_helpers.h"
#include "media/gpu/test/video_frame_helpers.h" #include "media/gpu/test/video_frame_helpers.h"
#include "media/parsers/vp8_parser.h"
#include "media/video/fake_video_encode_accelerator.h" #include "media/video/fake_video_encode_accelerator.h"
#include "media/video/h264_level_limits.h" #include "media/video/h264_level_limits.h"
#include "media/video/h264_parser.h" #include "media/video/h264_parser.h"
......
...@@ -12,10 +12,10 @@ ...@@ -12,10 +12,10 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "media/filters/vp8_parser.h"
#include "media/gpu/accelerated_video_decoder.h" #include "media/gpu/accelerated_video_decoder.h"
#include "media/gpu/vp8_picture.h" #include "media/gpu/vp8_picture.h"
#include "media/gpu/vp8_reference_frame_vector.h" #include "media/gpu/vp8_reference_frame_vector.h"
#include "media/parsers/vp8_parser.h"
namespace media { namespace media {
......
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
#define MEDIA_GPU_VP8_PICTURE_H_ #define MEDIA_GPU_VP8_PICTURE_H_
#include "base/macros.h" #include "base/macros.h"
#include "media/filters/vp8_parser.h"
#include "media/gpu/codec_picture.h" #include "media/gpu/codec_picture.h"
#include "media/parsers/vp8_parser.h"
namespace media { namespace media {
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "media/filters/vp8_parser.h" #include "media/parsers/vp8_parser.h"
namespace media { namespace media {
......
...@@ -9,6 +9,12 @@ component("parsers") { ...@@ -9,6 +9,12 @@ component("parsers") {
"jpeg_parser.cc", "jpeg_parser.cc",
"jpeg_parser.h", "jpeg_parser.h",
"media_parsers_export.h", "media_parsers_export.h",
"vp8_bool_decoder.cc",
"vp8_bool_decoder.h",
"vp8_parser.cc",
"vp8_parser.h",
"webp_parser.cc",
"webp_parser.h",
] ]
defines = [ "IS_MEDIA_PARSER_IMPL" ] defines = [ "IS_MEDIA_PARSER_IMPL" ]
deps = [ deps = [
...@@ -26,6 +32,9 @@ source_set("unit_tests") { ...@@ -26,6 +32,9 @@ source_set("unit_tests") {
testonly = true testonly = true
sources = [ sources = [
"jpeg_parser_unittest.cc", "jpeg_parser_unittest.cc",
"vp8_bool_decoder_unittest.cc",
"vp8_parser_unittest.cc",
"webp_parser_unittest.cc",
] ]
deps = [ deps = [
":parsers", ":parsers",
...@@ -46,3 +55,16 @@ fuzzer_test("media_jpeg_parser_picture_fuzzer") { ...@@ -46,3 +55,16 @@ fuzzer_test("media_jpeg_parser_picture_fuzzer") {
seed_corpus = "//media/test/data" seed_corpus = "//media/test/data"
dict = "//media/test/jpeg.dict" dict = "//media/test/jpeg.dict"
} }
fuzzer_test("media_vp8_parser_fuzzer") {
sources = [
"vp8_parser_fuzzertest.cc",
]
deps = [
":parsers",
"//base",
"//media:test_support",
]
libfuzzer_options = [ "max_len = 400000" ]
dict = "//media/test/vp8.dict"
}
// Copyright 2015 The Chromium Authors. All rights reserved. // Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
//
#ifndef MEDIA_PARSERS_JPEG_PARSER_H_ #ifndef MEDIA_PARSERS_JPEG_PARSER_H_
#define MEDIA_PARSERS_JPEG_PARSER_H_ #define MEDIA_PARSERS_JPEG_PARSER_H_
......
...@@ -40,12 +40,13 @@ ...@@ -40,12 +40,13 @@
// project. (http://www.webmproject.org/code) // project. (http://www.webmproject.org/code)
// It is used to decode bits from a vp8 stream. // It is used to decode bits from a vp8 stream.
#include "media/parsers/vp8_bool_decoder.h"
#include <limits.h> #include <limits.h>
#include <algorithm> #include <algorithm>
#include "base/numerics/safe_conversions.h" #include "base/numerics/safe_conversions.h"
#include "media/filters/vp8_bool_decoder.h"
namespace media { namespace media {
......
...@@ -40,8 +40,8 @@ ...@@ -40,8 +40,8 @@
// project. (http://www.webmproject.org/code) // project. (http://www.webmproject.org/code)
// It is used to decode bits from a vp8 stream. // It is used to decode bits from a vp8 stream.
#ifndef MEDIA_FILTERS_VP8_BOOL_DECODER_H_ #ifndef MEDIA_PARSERS_VP8_BOOL_DECODER_H_
#define MEDIA_FILTERS_VP8_BOOL_DECODER_H_ #define MEDIA_PARSERS_VP8_BOOL_DECODER_H_
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
...@@ -49,13 +49,13 @@ ...@@ -49,13 +49,13 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "media/base/media_export.h" #include "media/parsers/media_parsers_export.h"
namespace media { namespace media {
// A class to decode the VP8's boolean entropy coded stream. It's a variant of // A class to decode the VP8's boolean entropy coded stream. It's a variant of
// arithmetic coding. See RFC 6386 - Chapter 7. Boolean Entropy Decoder. // arithmetic coding. See RFC 6386 - Chapter 7. Boolean Entropy Decoder.
class MEDIA_EXPORT Vp8BoolDecoder { class MEDIA_PARSERS_EXPORT Vp8BoolDecoder {
public: public:
Vp8BoolDecoder(); Vp8BoolDecoder();
...@@ -132,4 +132,4 @@ class MEDIA_EXPORT Vp8BoolDecoder { ...@@ -132,4 +132,4 @@ class MEDIA_EXPORT Vp8BoolDecoder {
} // namespace media } // namespace media
#endif // MEDIA_FILTERS_VP8_BOOL_DECODER_H_ #endif // MEDIA_PARSERS_VP8_BOOL_DECODER_H_
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "media/filters/vp8_bool_decoder.h" #include "media/parsers/vp8_bool_decoder.h"
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
......
...@@ -5,8 +5,9 @@ ...@@ -5,8 +5,9 @@
// This file contains an implementation of a VP8 raw stream parser, // This file contains an implementation of a VP8 raw stream parser,
// as defined in RFC 6386. // as defined in RFC 6386.
#include "media/parsers/vp8_parser.h"
#include "base/logging.h" #include "base/logging.h"
#include "media/filters/vp8_parser.h"
namespace media { namespace media {
......
...@@ -5,15 +5,15 @@ ...@@ -5,15 +5,15 @@
// This file contains an implementation of a VP8 raw stream parser, // This file contains an implementation of a VP8 raw stream parser,
// as defined in RFC 6386. // as defined in RFC 6386.
#ifndef MEDIA_FILTERS_VP8_PARSER_H_ #ifndef MEDIA_PARSERS_VP8_PARSER_H_
#define MEDIA_FILTERS_VP8_PARSER_H_ #define MEDIA_PARSERS_VP8_PARSER_H_
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "base/macros.h" #include "base/macros.h"
#include "media/base/media_export.h" #include "media/parsers/media_parsers_export.h"
#include "media/filters/vp8_bool_decoder.h" #include "media/parsers/vp8_bool_decoder.h"
namespace media { namespace media {
...@@ -23,7 +23,7 @@ const size_t kNumMBFeatureTreeProbs = 3; ...@@ -23,7 +23,7 @@ const size_t kNumMBFeatureTreeProbs = 3;
// Member of Vp8FrameHeader and will be 0-initialized // Member of Vp8FrameHeader and will be 0-initialized
// in Vp8FrameHeader's constructor. // in Vp8FrameHeader's constructor.
struct MEDIA_EXPORT Vp8SegmentationHeader { struct Vp8SegmentationHeader {
enum SegmentFeatureMode { FEATURE_MODE_DELTA = 0, FEATURE_MODE_ABSOLUTE = 1 }; enum SegmentFeatureMode { FEATURE_MODE_DELTA = 0, FEATURE_MODE_ABSOLUTE = 1 };
bool segmentation_enabled; bool segmentation_enabled;
...@@ -41,7 +41,7 @@ const size_t kNumBlockContexts = 4; ...@@ -41,7 +41,7 @@ const size_t kNumBlockContexts = 4;
// Member of Vp8FrameHeader and will be 0-initialized // Member of Vp8FrameHeader and will be 0-initialized
// in Vp8FrameHeader's constructor. // in Vp8FrameHeader's constructor.
struct MEDIA_EXPORT Vp8LoopFilterHeader { struct Vp8LoopFilterHeader {
enum Type { LOOP_FILTER_TYPE_NORMAL = 0, LOOP_FILTER_TYPE_SIMPLE = 1 }; enum Type { LOOP_FILTER_TYPE_NORMAL = 0, LOOP_FILTER_TYPE_SIMPLE = 1 };
Type type; Type type;
uint8_t level; uint8_t level;
...@@ -55,7 +55,7 @@ struct MEDIA_EXPORT Vp8LoopFilterHeader { ...@@ -55,7 +55,7 @@ struct MEDIA_EXPORT Vp8LoopFilterHeader {
// Member of Vp8FrameHeader and will be 0-initialized // Member of Vp8FrameHeader and will be 0-initialized
// in Vp8FrameHeader's constructor. // in Vp8FrameHeader's constructor.
struct MEDIA_EXPORT Vp8QuantizationHeader { struct Vp8QuantizationHeader {
uint8_t y_ac_qi; uint8_t y_ac_qi;
int8_t y_dc_delta; int8_t y_dc_delta;
int8_t y2_dc_delta; int8_t y2_dc_delta;
...@@ -96,7 +96,7 @@ enum Vp8RefType : size_t { ...@@ -96,7 +96,7 @@ enum Vp8RefType : size_t {
VP8_FRAME_ALTREF = 2, VP8_FRAME_ALTREF = 2,
}; };
struct MEDIA_EXPORT Vp8FrameHeader { struct MEDIA_PARSERS_EXPORT Vp8FrameHeader {
Vp8FrameHeader(); Vp8FrameHeader();
enum FrameType { KEYFRAME = 0, INTERFRAME = 1 }; enum FrameType { KEYFRAME = 0, INTERFRAME = 1 };
...@@ -164,7 +164,7 @@ struct MEDIA_EXPORT Vp8FrameHeader { ...@@ -164,7 +164,7 @@ struct MEDIA_EXPORT Vp8FrameHeader {
}; };
// A parser for raw VP8 streams as specified in RFC 6386. // A parser for raw VP8 streams as specified in RFC 6386.
class MEDIA_EXPORT Vp8Parser { class MEDIA_PARSERS_EXPORT Vp8Parser {
public: public:
Vp8Parser(); Vp8Parser();
~Vp8Parser(); ~Vp8Parser();
...@@ -205,4 +205,4 @@ class MEDIA_EXPORT Vp8Parser { ...@@ -205,4 +205,4 @@ class MEDIA_EXPORT Vp8Parser {
} // namespace media } // namespace media
#endif // MEDIA_FILTERS_VP8_PARSER_H_ #endif // MEDIA_PARSERS_VP8_PARSER_H_
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#include "base/numerics/safe_conversions.h" #include "base/numerics/safe_conversions.h"
#include "media/filters/ivf_parser.h" #include "media/filters/ivf_parser.h"
#include "media/filters/vp8_parser.h" #include "media/parsers/vp8_parser.h"
// Entry point for LibFuzzer. // Entry point for LibFuzzer.
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "media/base/test_data_util.h" #include "media/base/test_data_util.h"
#include "media/filters/ivf_parser.h" #include "media/filters/ivf_parser.h"
#include "media/filters/vp8_parser.h" #include "media/parsers/vp8_parser.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace media { namespace media {
......
// Copyright 2019 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 "media/parsers/webp_parser.h"
#include <limits.h>
#include <stddef.h>
#include <string.h>
#include "base/bits.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "build/build_config.h"
#include "media/parsers/vp8_parser.h"
#if !defined(ARCH_CPU_LITTLE_ENDIAN)
#error Big-Endian architecture not supported.
#endif
namespace media {
namespace {
// The byte position storing the size of the file.
constexpr size_t kFileSizeBytePosition = 4u;
// The byte position in which the WebP image data begins.
constexpr size_t kWebPFileBeginBytePosition = 8u;
// The byte position storing the size of the VP8 frame.
constexpr size_t kVp8FrameSizePosition = 16u;
// The 12 bytes that include the FourCC "WEBPVP8 " plus the VP8 chunk size info.
constexpr size_t kWebPFileHeaderByteSize = 12u;
// A valid WebP image header and VP8 chunk header require 20 bytes.
// The VP8 Key Frame's payload also begins at byte 20.
constexpr size_t kWebPFileAndVp8ChunkHeaderSizeInBytes = 20u;
// The max WebP file size is (2^32 - 10) per the WebP spec:
// https://developers.google.com/speed/webp/docs/riff_container#webp_file_header
constexpr uint32_t kMaxWebPFileSize = (1ull << 32) - 10u;
constexpr size_t kSizeOfUint32t = sizeof(uint32_t);
} // namespace
bool IsLossyWebPImage(base::span<const uint8_t> encoded_data) {
if (encoded_data.size() < kWebPFileAndVp8ChunkHeaderSizeInBytes)
return false;
DCHECK(encoded_data.data());
return !memcmp(encoded_data.data(), "RIFF", 4) &&
!memcmp(encoded_data.data() + kWebPFileBeginBytePosition, "WEBPVP8 ",
8);
}
std::unique_ptr<Vp8FrameHeader> ParseWebPImage(
base::span<const uint8_t> encoded_data) {
if (!IsLossyWebPImage(encoded_data))
return nullptr;
static_assert(CHAR_BIT == 8, "Size of a char is not 8 bits.");
static_assert(kSizeOfUint32t == 4u, "Size of uint32_t is not 4 bytes.");
// Try to acquire the WebP file size. IsLossyWebPImage() has ensured
// that we have enough data to read the file size.
DCHECK_GE(encoded_data.size(), kFileSizeBytePosition + kSizeOfUint32t);
// No need to worry about endianness because we assert little-endianness.
const uint32_t file_size = *reinterpret_cast<const uint32_t*>(
encoded_data.data() + kFileSizeBytePosition);
// Check that |file_size| is even, per the WebP spec:
// https://developers.google.com/speed/webp/docs/riff_container#webp_file_header
if (file_size % 2 != 0)
return nullptr;
// Check that |file_size| <= 2^32 - 10, per the WebP spec:
// https://developers.google.com/speed/webp/docs/riff_container#webp_file_header
if (file_size > kMaxWebPFileSize)
return nullptr;
// Check that the file size in the header matches the encoded data's size.
if (base::strict_cast<size_t>(file_size) !=
encoded_data.size() - kWebPFileBeginBytePosition) {
return nullptr;
}
// Try to acquire the VP8 key frame size and validate that it fits within the
// encoded data's size.
DCHECK_GE(encoded_data.size(), kVp8FrameSizePosition + kSizeOfUint32t);
const uint32_t vp8_frame_size = *reinterpret_cast<const uint32_t*>(
encoded_data.data() + kVp8FrameSizePosition);
// Check that the VP8 frame size is bounded by the WebP size.
if (base::strict_cast<size_t>(file_size) - kWebPFileHeaderByteSize <
base::strict_cast<size_t>(vp8_frame_size)) {
return nullptr;
}
// Check that the size of the encoded data is consistent.
const size_t vp8_padded_frame_size =
base::bits::Align(base::strict_cast<size_t>(vp8_frame_size), 2u);
if (encoded_data.size() - kWebPFileAndVp8ChunkHeaderSizeInBytes !=
vp8_padded_frame_size) {
return nullptr;
}
// Check that the last byte is 0 if |vp8_frame_size| is odd per WebP specs:
// https://developers.google.com/speed/webp/docs/riff_container#riff_file_format
if (vp8_frame_size % 2 &&
encoded_data.data()[encoded_data.size() - 1] != 0u) {
return nullptr;
}
// Attempt to parse the VP8 frame.
Vp8Parser vp8_parser;
auto result = std::make_unique<Vp8FrameHeader>();
if (vp8_parser.ParseFrame(
encoded_data.data() + kWebPFileAndVp8ChunkHeaderSizeInBytes,
base::strict_cast<size_t>(vp8_frame_size), result.get())) {
return result;
}
return nullptr;
}
} // namespace media
// Copyright 2019 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.
#ifndef MEDIA_PARSERS_WEBP_PARSER_H_
#define MEDIA_PARSERS_WEBP_PARSER_H_
#include <stdint.h>
#include <memory>
#include "base/containers/span.h"
#include "media/parsers/media_parsers_export.h"
namespace media {
struct Vp8FrameHeader;
// A lightweight WebP file header parser to extract feature and size
// information. It validates that a given data stream encodes a simple lossy
// WebP image and populates a Vp8FrameHeader upon successful parsing.
// For more information, see the WebP Container Specification:
// https://developers.google.com/speed/webp/docs/riff_container
// Returns true if |encoded_data| claims to encode a simple (non-extended) lossy
// WebP image. Returns false otherwise.
MEDIA_PARSERS_EXPORT
bool IsLossyWebPImage(base::span<const uint8_t> encoded_data);
// Parses a simple (non-extended) lossy WebP image and returns a Vp8FrameHeader
// containing the parsed VP8 frame contained by the image. Returns nullptr on
// failure.
MEDIA_PARSERS_EXPORT
std::unique_ptr<Vp8FrameHeader> ParseWebPImage(
base::span<const uint8_t> encoded_data);
} // namespace media
#endif // MEDIA_PARSERS_WEBP_PARSER_H_
This diff is collapsed.
...@@ -817,6 +817,17 @@ ffmpeg -i green.webm -i a300hz.webm -map 0 -map 1 green-a300hz.webm ...@@ -817,6 +817,17 @@ ffmpeg -i green.webm -i a300hz.webm -map 0 -map 1 green-a300hz.webm
ffmpeg -i red.webm -i a500hz.webm -map 0 -map 1 red-a500hz.webm ffmpeg -i red.webm -i a500hz.webm -map 0 -map 1 red-a500hz.webm
``` ```
### WebP Test Files
#### bouncy_ball.webp
An animated (extended) WebP encoded image of 450x450. Created by gildekel@ using Gimp.
#### red_green_gradient_lossy.webp
A lossy WebP encoded image of 3000x3000. Created by gildekel@ using Gimp.
#### yellow_pink_gradient_lossless.webp
A lossless WebP encoded image of 3000x3000. Created by gildekel@ using Gimp.
### JPEG Test Files ### JPEG Test Files
#### pixel-1280x720.jpg #### pixel-1280x720.jpg
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment