diff options
-rw-r--r-- | AUTHORS.TXT | 1 | ||||
-rw-r--r-- | Android.mk | 23 | ||||
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | METADATA | 8 | ||||
-rw-r--r-- | common/vp9_level_stats.cc | 32 | ||||
-rw-r--r-- | common/vp9_level_stats.h | 9 | ||||
-rw-r--r-- | mkvmuxer/mkvmuxer.cc | 4 | ||||
-rw-r--r-- | mkvmuxer/mkvmuxer.h | 8 | ||||
-rw-r--r-- | mkvparser/mkvparser.cc | 2 | ||||
-rw-r--r-- | testing/mkvparser_fuzzer.cc | 51 | ||||
-rw-r--r-- | webm_parser/include/webm/file_reader.h | 13 | ||||
-rw-r--r-- | webm_parser/include/webm/status.h | 5 | ||||
-rw-r--r-- | webm_parser/src/file_reader.cc | 24 |
13 files changed, 145 insertions, 38 deletions
diff --git a/AUTHORS.TXT b/AUTHORS.TXT index 9686ac1..59b648c 100644 --- a/AUTHORS.TXT +++ b/AUTHORS.TXT @@ -2,3 +2,4 @@ # Name or Organization <email address> Google Inc. +Elijah Cirioli <eli.cirioli@gmail.com> diff --git a/Android.mk b/Android.mk new file mode 100644 index 0000000..e6c17df --- /dev/null +++ b/Android.mk @@ -0,0 +1,23 @@ +# Ignore this file during non-NDK builds. +ifdef NDK_ROOT +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE:= libwebm +LOCAL_CPPFLAGS:=-D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS +LOCAL_CPPFLAGS+=-D__STDC_LIMIT_MACROS -std=c++11 +LOCAL_C_INCLUDES:= $(LOCAL_PATH) +LOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH) + +LOCAL_SRC_FILES:= common/file_util.cc \ + common/hdr_util.cc \ + mkvparser/mkvparser.cc \ + mkvparser/mkvreader.cc \ + mkvmuxer/mkvmuxer.cc \ + mkvmuxer/mkvmuxerutil.cc \ + mkvmuxer/mkvwriter.cc +LOCAL_LICENSE_KINDS := SPDX-license-identifier-BSD +LOCAL_LICENSE_CONDITIONS := notice +LOCAL_NOTICE_FILE := $(LOCAL_PATH)/LICENSE.TXT $(LOCAL_PATH)/PATENTS.TXT +include $(BUILD_STATIC_LIBRARY) +endif # NDK_ROOT diff --git a/CMakeLists.txt b/CMakeLists.txt index a83d23b..99e904f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,9 @@ if (MSVC) endif () else () add_cxx_flag_if_supported("-Wall") + add_cxx_flag_if_supported("-Wc++14-compat") + add_cxx_flag_if_supported("-Wc++17-compat") + add_cxx_flag_if_supported("-Wc++20-compat") add_cxx_flag_if_supported("-Wextra") add_cxx_flag_if_supported("-Wnarrowing") add_cxx_flag_if_supported("-Wno-deprecated") @@ -9,11 +9,11 @@ third_party { type: GIT value: "https://chromium.googlesource.com/webm/libwebm" } - version: "libwebm-1.0.0.29" + version: "1930e3ca23b007f3ff11d98a570077be6201957e" license_type: NOTICE last_upgrade_date { - year: 2022 - month: 10 - day: 17 + year: 2023 + month: 3 + day: 20 } } diff --git a/common/vp9_level_stats.cc b/common/vp9_level_stats.cc index 76891e6..96a4bcc 100644 --- a/common/vp9_level_stats.cc +++ b/common/vp9_level_stats.cc @@ -17,21 +17,21 @@ namespace vp9_parser { const Vp9LevelRow Vp9LevelStats::Vp9LevelTable[kNumVp9Levels] = { - {LEVEL_1, 829440, 36864, 200, 400, 2, 1, 4, 8, 512}, - {LEVEL_1_1, 2764800, 73728, 800, 1000, 2, 1, 4, 8, 768}, - {LEVEL_2, 4608000, 122880, 1800, 1500, 2, 1, 4, 8, 960}, - {LEVEL_2_1, 9216000, 245760, 3600, 2800, 2, 2, 4, 8, 1344}, - {LEVEL_3, 20736000, 552960, 7200, 6000, 2, 4, 4, 8, 2048}, - {LEVEL_3_1, 36864000, 983040, 12000, 10000, 2, 4, 4, 8, 2752}, - {LEVEL_4, 83558400, 2228224, 18000, 16000, 4, 4, 4, 8, 4160}, - {LEVEL_4_1, 160432128, 2228224, 30000, 18000, 4, 4, 5, 6, 4160}, - {LEVEL_5, 311951360, 8912896, 60000, 36000, 6, 8, 6, 4, 8384}, - {LEVEL_5_1, 588251136, 8912896, 120000, 46000, 8, 8, 10, 4, 8384}, + {LEVEL_1, 829440, 36864, 512, 200, 400, 2, 1, 4, 8}, + {LEVEL_1_1, 2764800, 73728, 768, 800, 1000, 2, 1, 4, 8}, + {LEVEL_2, 4608000, 122880, 960, 1800, 1500, 2, 1, 4, 8}, + {LEVEL_2_1, 9216000, 245760, 1344, 3600, 2800, 2, 2, 4, 8}, + {LEVEL_3, 20736000, 552960, 2048, 7200, 6000, 2, 4, 4, 8}, + {LEVEL_3_1, 36864000, 983040, 2752, 12000, 10000, 2, 4, 4, 8}, + {LEVEL_4, 83558400, 2228224, 4160, 18000, 16000, 4, 4, 4, 8}, + {LEVEL_4_1, 160432128, 2228224, 4160, 30000, 18000, 4, 4, 5, 6}, + {LEVEL_5, 311951360, 8912896, 8384, 60000, 36000, 6, 8, 6, 4}, + {LEVEL_5_1, 588251136, 8912896, 8384, 120000, 46000, 8, 8, 10, 4}, // CPB Size = 0 for levels 5_2 to 6_2 - {LEVEL_5_2, 1176502272, 8912896, 180000, 0, 8, 8, 10, 4, 8384}, - {LEVEL_6, 1176502272, 35651584, 180000, 0, 8, 16, 10, 4, 16832}, - {LEVEL_6_1, 2353004544, 35651584, 240000, 0, 8, 16, 10, 4, 16832}, - {LEVEL_6_2, 4706009088, 35651584, 480000, 0, 8, 16, 10, 4, 16832}}; + {LEVEL_5_2, 1176502272, 8912896, 8384, 180000, 0, 8, 8, 10, 4}, + {LEVEL_6, 1176502272, 35651584, 16832, 180000, 0, 8, 16, 10, 4}, + {LEVEL_6_1, 2353004544, 35651584, 16832, 240000, 0, 8, 16, 10, 4}, + {LEVEL_6_2, 4706009088, 35651584, 16832, 480000, 0, 8, 16, 10, 4}}; void Vp9LevelStats::AddFrame(const Vp9HeaderParser& parser, int64_t time_ns) { ++frames; @@ -129,7 +129,7 @@ Vp9Level Vp9LevelStats::GetLevel() const { const int64_t max_luma_picture_breadth = GetMaxLumaPictureBreadth(); const double average_bitrate = GetAverageBitRate(); const double max_cpb_size = GetMaxCpbSize(); - const double compresion_ratio = GetCompressionRatio(); + const double compression_ratio = GetCompressionRatio(); const int max_column_tiles = GetMaxColumnTiles(); const int min_altref_distance = GetMinimumAltrefDistance(); const int max_ref_frames = GetMaxReferenceFrames(); @@ -215,7 +215,7 @@ Vp9Level Vp9LevelStats::GetLevel() const { // The minimum compression ratio has the same behavior as minimum altref // distance. - if (compresion_ratio < Vp9LevelTable[level_index].compresion_ratio) + if (compression_ratio < Vp9LevelTable[level_index].compression_ratio) max_level = LEVEL_UNKNOWN; return max_level; } diff --git a/common/vp9_level_stats.h b/common/vp9_level_stats.h index 45d6f5c..4230385 100644 --- a/common/vp9_level_stats.h +++ b/common/vp9_level_stats.h @@ -40,20 +40,13 @@ enum Vp9Level { }; struct Vp9LevelRow { - Vp9LevelRow() = default; - ~Vp9LevelRow() = default; - Vp9LevelRow(Vp9LevelRow&& other) = default; - Vp9LevelRow(const Vp9LevelRow& other) = default; - Vp9LevelRow& operator=(Vp9LevelRow&& other) = delete; - Vp9LevelRow& operator=(const Vp9LevelRow& other) = delete; - Vp9Level level; int64_t max_luma_sample_rate; int64_t max_luma_picture_size; int64_t max_luma_picture_breadth; double average_bitrate; double max_cpb_size; - double compresion_ratio; + double compression_ratio; int max_tiles; int min_altref_distance; int max_ref_frames; diff --git a/mkvmuxer/mkvmuxer.cc b/mkvmuxer/mkvmuxer.cc index ae36531..faaf016 100644 --- a/mkvmuxer/mkvmuxer.cc +++ b/mkvmuxer/mkvmuxer.cc @@ -607,10 +607,10 @@ bool ContentEncoding::Write(IMkvWriter* writer) const { return true; } -uint64_t ContentEncoding::EncodingSize(uint64_t compresion_size, +uint64_t ContentEncoding::EncodingSize(uint64_t compression_size, uint64_t encryption_size) const { // TODO(fgalligan): Add support for compression settings. - if (compresion_size != 0) + if (compression_size != 0) return 0; uint64_t encoding_size = 0; diff --git a/mkvmuxer/mkvmuxer.h b/mkvmuxer/mkvmuxer.h index f2db377..8602d82 100644 --- a/mkvmuxer/mkvmuxer.h +++ b/mkvmuxer/mkvmuxer.h @@ -330,7 +330,7 @@ class ContentEncoding { private: // Returns the size in bytes for the encoding elements. - uint64_t EncodingSize(uint64_t compresion_size, + uint64_t EncodingSize(uint64_t compression_size, uint64_t encryption_size) const; // Returns the size in bytes for the encryption elements. @@ -1425,7 +1425,7 @@ class SeekHead { bool Write(IMkvWriter* writer); // We are going to put a cap on the number of Seek Entries. - const static int32_t kSeekEntryCount = 5; + constexpr static int32_t kSeekEntryCount = 5; private: // Returns the maximum size in bytes of one seek entry. @@ -1505,8 +1505,8 @@ class Segment { kBeforeClusters = 0x1 // Position Cues before Clusters }; - static const uint32_t kDefaultDocTypeVersion = 4; - static const uint64_t kDefaultMaxClusterDuration = 30000000000ULL; + static constexpr uint32_t kDefaultDocTypeVersion = 4; + static constexpr uint64_t kDefaultMaxClusterDuration = 30000000000ULL; Segment(); ~Segment(); diff --git a/mkvparser/mkvparser.cc b/mkvparser/mkvparser.cc index 5d583dc..868afcb 100644 --- a/mkvparser/mkvparser.cc +++ b/mkvparser/mkvparser.cc @@ -2432,7 +2432,7 @@ bool CuePoint::TrackPosition::Parse(IMkvReader* pReader, long long start_, pos += size; // consume payload } - if ((m_pos < 0) || (m_track <= 0)) { + if ((m_pos < 0) || (m_track <= 0) || (m_block < 0) || (m_block > LONG_MAX)) { return false; } diff --git a/testing/mkvparser_fuzzer.cc b/testing/mkvparser_fuzzer.cc index a1a47b8..b3bb799 100644 --- a/testing/mkvparser_fuzzer.cc +++ b/testing/mkvparser_fuzzer.cc @@ -9,6 +9,7 @@ #include <cstdint> #include <cstdlib> #include <cstring> +#include <functional> #include <memory> #include <new> @@ -58,6 +59,51 @@ void ParseCues(const mkvparser::Segment& segment) { } } +const mkvparser::BlockEntry* GetBlockEntryFromCues( + const void* ctx, const mkvparser::CuePoint* cue, + const mkvparser::CuePoint::TrackPosition* track_pos) { + const auto* const cues = static_cast<const mkvparser::Cues*>(ctx); + return cues->GetBlock(cue, track_pos); +} + +const mkvparser::BlockEntry* GetBlockEntryFromCluster( + const void* ctx, const mkvparser::CuePoint* cue, + const mkvparser::CuePoint::TrackPosition* track_pos) { + if (track_pos == nullptr) { + return nullptr; + } + const auto* const cluster = static_cast<const mkvparser::Cluster*>(ctx); + const mkvparser::BlockEntry* block_entry = + cluster->GetEntry(*cue, *track_pos); + return block_entry; +} + +void WalkCues(const mkvparser::Segment& segment, + std::function<const mkvparser::BlockEntry*( + const void*, const mkvparser::CuePoint*, + const mkvparser::CuePoint::TrackPosition*)> + get_block_entry, + const void* ctx) { + const mkvparser::Cues* const cues = segment.GetCues(); + const mkvparser::Tracks* tracks = segment.GetTracks(); + if (cues == nullptr || tracks == nullptr) { + return; + } + const unsigned long num_tracks = tracks->GetTracksCount(); + + for (const mkvparser::CuePoint* cue = cues->GetFirst(); cue != nullptr; + cue = cues->GetNext(cue)) { + for (unsigned long track_num = 0; track_num < num_tracks; ++track_num) { + const mkvparser::Track* const track = tracks->GetTrackByIndex(track_num); + const mkvparser::CuePoint::TrackPosition* const track_pos = + cue->Find(track); + const mkvparser::BlockEntry* block_entry = + get_block_entry(ctx, cue, track_pos); + static_cast<void>(block_entry); + } + } +} + void ParseCluster(const mkvparser::Cluster& cluster) { const mkvparser::BlockEntry* block_entry; long status = cluster.GetFirst(block_entry); @@ -100,12 +146,15 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { return 0; } + ParseCues(*segment); + WalkCues(*segment, GetBlockEntryFromCues, segment->GetCues()); + const mkvparser::Cluster* cluster = segment->GetFirst(); while (cluster != nullptr && !cluster->EOS()) { ParseCluster(*cluster); + WalkCues(*segment, GetBlockEntryFromCluster, cluster); cluster = segment->GetNext(cluster); } - ParseCues(*segment); return 0; } diff --git a/webm_parser/include/webm/file_reader.h b/webm_parser/include/webm/file_reader.h index 6ccdc4d..69bec76 100644 --- a/webm_parser/include/webm/file_reader.h +++ b/webm_parser/include/webm/file_reader.h @@ -67,6 +67,19 @@ class FileReader : public Reader { Status Skip(std::uint64_t num_to_skip, std::uint64_t* num_actually_skipped) override; + /** + Moves the reader to a new absolute byte position in the file. + + It is required to call DidSeek() on the parser after successfully seeking. + Seeking will only work on actual files, not stdin or pipes. + + \param seek_position The new absolute byte position in the file. + \return `Status::kOkCompleted` if reader position is now `seek_position`. + `Status::kSeekFailed` if the reader was unable to seek to `seek_position` + such as when the file is stdin. + */ + Status Seek(std::uint64_t seek_position); + std::uint64_t Position() const override; private: diff --git a/webm_parser/include/webm/status.h b/webm_parser/include/webm/status.h index ff3f0c6..9577ef4 100644 --- a/webm_parser/include/webm/status.h +++ b/webm_parser/include/webm/status.h @@ -56,6 +56,11 @@ struct Status { */ kEndOfFile = -3, + /** + The reader was unable to seek to the requested location. + */ + kSeekFailed = -4, + // Parsing errors. Range: -1025 to -2048. /** An element's ID is malformed. diff --git a/webm_parser/src/file_reader.cc b/webm_parser/src/file_reader.cc index 0921abe..a2a397b 100644 --- a/webm_parser/src/file_reader.cc +++ b/webm_parser/src/file_reader.cc @@ -16,6 +16,19 @@ #include "webm/status.h" +#ifdef _MSC_VER +#define FSEEK_(stream, offset, whence) _fseeki64(stream, offset, whence) +#elif defined(_WIN32) +#define FSEEK_(stream, offset, whence) \ + fseeko64(stream, static_cast<off_t>(offset), whence) +#elif _POSIX_C_SOURCE >= 200112L +#define FSEEK_(stream, offset, whence) \ + fseeko(stream, static_cast<off_t>(offset), whence) +#else +#define FSEEK_(stream, offset, whence) \ + std::fseek(stream, static_cast<long>(offset), whence) +#endif + namespace webm { FileReader::FileReader(FILE* file) : file_(file) { assert(file); } @@ -77,8 +90,7 @@ Status FileReader::Skip(std::uint64_t num_to_skip, if (num_to_skip < static_cast<unsigned long>(seek_offset)) { // NOLINT seek_offset = static_cast<long>(num_to_skip); // NOLINT } - // TODO(mjbshaw): Use fseeko64/_fseeki64 if available. - if (!std::fseek(file_.get(), seek_offset, SEEK_CUR)) { + if (!FSEEK_(file_.get(), seek_offset, SEEK_CUR)) { *num_actually_skipped = static_cast<std::uint64_t>(seek_offset); position_ += static_cast<std::uint64_t>(seek_offset); if (static_cast<unsigned long>(seek_offset) == num_to_skip) { // NOLINT @@ -117,6 +129,14 @@ Status FileReader::Skip(std::uint64_t num_to_skip, } } +Status FileReader::Seek(std::uint64_t seek_position) { + if (FSEEK_(file_.get(), seek_position, SEEK_SET)) { + return Status(Status::kSeekFailed); + } + position_ = seek_position; + return Status(Status::kOkCompleted); +} + std::uint64_t FileReader::Position() const { return position_; } } // namespace webm |