react-native-alpha-video 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +903 -2
- package/THIRD_PARTY_NOTICES.md +30 -0
- package/android/av1/build.gradle +67 -0
- package/android/av1/consumer-rules.pro +4 -0
- package/android/av1/src/main/cpp/Av1Codec_jni.cpp +8 -0
- package/android/av1/src/main/cpp/CMakeLists.txt +34 -0
- package/android/av1/src/main/java/dev/mediacache/alphavideo/av1/Av1Codec.java +21 -0
- package/android/build.gradle +85 -0
- package/android/consumer-rules.pro +2 -0
- package/android/gradle.properties +1 -0
- package/android/publish.gradle +82 -0
- package/android/settings.gradle +5 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/cpp/CMakeLists.txt +59 -0
- package/android/src/main/java/dev/mediacache/alphavideo/AlphaVideoCodecs.java +73 -0
- package/android/src/main/java/dev/mediacache/alphavideo/AlphaVideoView.java +1966 -0
- package/android/src/main/java/dev/mediacache/alphavideo/BufferedDualStreamPlayer.java +978 -0
- package/android/src/main/java/dev/mediacache/alphavideo/Fetcher.java +37 -0
- package/android/src/main/java/dev/mediacache/alphavideo/HttpFetcher.java +156 -0
- package/android/src/main/java/dev/mediacache/alphavideo/MediaCodecColor.java +47 -0
- package/android/src/main/java/dev/mediacache/alphavideo/MediaCodecDecoders.java +135 -0
- package/android/src/main/java/dev/mediacache/alphavideo/RangeSourceLink.java +54 -0
- package/android/src/main/java/dev/mediacache/alphavideo/SourceReader.java +174 -0
- package/android/src/main/java/dev/mediacache/alphavideo/SurfaceTextureVideoDecoder.java +802 -0
- package/android/src/main/java/dev/mediacache/alphavideo/WebMAlphaPlayerNative.java +95 -0
- package/android/src/main/java/dev/mediacache/alphavideo/WebMFrame.java +54 -0
- package/android/src/main/java/dev/mediacache/alphavideo/WebMSource.java +160 -0
- package/android/src/rangesource/java/dev/mediacache/alphavideo/AppDataSource.java +50 -0
- package/android/vpx/build.gradle +67 -0
- package/android/vpx/consumer-rules.pro +4 -0
- package/android/vpx/src/main/cpp/CMakeLists.txt +34 -0
- package/android/vpx/src/main/cpp/VpxCodec_jni.cpp +8 -0
- package/android/vpx/src/main/java/dev/mediacache/alphavideo/vpx/VpxCodec.java +21 -0
- package/codecs/av1/Dav1dDecoderPlugin.cpp +157 -0
- package/codecs/av1/Dav1dDecoderPlugin.h +17 -0
- package/codecs/vpx/VpxDecoderPlugin.cpp +103 -0
- package/codecs/vpx/VpxDecoderPlugin.h +17 -0
- package/cpp/AlphaDemuxer.cpp +984 -0
- package/cpp/AlphaDemuxer.h +123 -0
- package/cpp/AlphaVideoDecoderPlugin.h +84 -0
- package/cpp/Av1SequenceHeader.cpp +175 -0
- package/cpp/Av1SequenceHeader.h +25 -0
- package/cpp/ByteSource.cpp +116 -0
- package/cpp/ByteSource.h +59 -0
- package/cpp/RangeSourceClient.h +40 -0
- package/cpp/VideoDecoder.cpp +157 -0
- package/cpp/VideoDecoder.h +83 -0
- package/cpp/WebMAlphaPlayer.cpp +1666 -0
- package/cpp/WebMAlphaPlayer.h +389 -0
- package/cpp/WebMAlphaPlayer_jni.cpp +1380 -0
- package/cpp/YuvToRgb.cpp +39 -0
- package/cpp/YuvToRgb.h +40 -0
- package/ios/Sources/AlphaVideo/AlphaVideoCodecs.mm +63 -0
- package/ios/Sources/AlphaVideo/AlphaVideoInternal.h +70 -0
- package/ios/Sources/AlphaVideo/AlphaVideoPlayer.mm +994 -0
- package/ios/Sources/AlphaVideo/AlphaVideoSource.mm +476 -0
- package/ios/Sources/AlphaVideo/AlphaVideoView.mm +374 -0
- package/ios/Sources/AlphaVideo/include/AlphaVideo.h +303 -0
- package/ios/Sources/AlphaVideoAV1/AlphaVideoAV1Codec.mm +16 -0
- package/ios/Sources/AlphaVideoAV1/include/AlphaVideoAV1.h +18 -0
- package/ios/Sources/AlphaVideoVPX/AlphaVideoVPXCodec.mm +16 -0
- package/ios/Sources/AlphaVideoVPX/include/AlphaVideoVPX.h +17 -0
- package/lib/commonjs/AlphaVideoView.js +187 -0
- package/lib/commonjs/AlphaVideoView.js.map +1 -0
- package/lib/commonjs/AlphaVideoViewNativeComponent.js +47 -0
- package/lib/commonjs/AlphaVideoViewNativeComponent.js.map +1 -0
- package/lib/commonjs/AlphaVideoViewNativeComponent.web.js +11 -0
- package/lib/commonjs/AlphaVideoViewNativeComponent.web.js.map +1 -0
- package/lib/commonjs/NativeAlphaVideoModule.js +10 -0
- package/lib/commonjs/NativeAlphaVideoModule.js.map +1 -0
- package/lib/commonjs/NativeAlphaVideoModule.web.js +9 -0
- package/lib/commonjs/NativeAlphaVideoModule.web.js.map +1 -0
- package/lib/commonjs/WebPlayer.js +12 -0
- package/lib/commonjs/WebPlayer.js.map +1 -0
- package/lib/commonjs/WebPlayer.web.js +92 -0
- package/lib/commonjs/WebPlayer.web.js.map +1 -0
- package/lib/commonjs/index.js +124 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/module/AlphaVideoView.js +187 -0
- package/lib/module/AlphaVideoView.js.map +1 -0
- package/lib/module/AlphaVideoViewNativeComponent.js +47 -0
- package/lib/module/AlphaVideoViewNativeComponent.js.map +1 -0
- package/lib/module/AlphaVideoViewNativeComponent.web.js +11 -0
- package/lib/module/AlphaVideoViewNativeComponent.web.js.map +1 -0
- package/lib/module/NativeAlphaVideoModule.js +10 -0
- package/lib/module/NativeAlphaVideoModule.js.map +1 -0
- package/lib/module/NativeAlphaVideoModule.web.js +9 -0
- package/lib/module/NativeAlphaVideoModule.web.js.map +1 -0
- package/lib/module/WebPlayer.js +12 -0
- package/lib/module/WebPlayer.js.map +1 -0
- package/lib/module/WebPlayer.web.js +92 -0
- package/lib/module/WebPlayer.web.js.map +1 -0
- package/lib/module/index.js +124 -0
- package/lib/module/index.js.map +1 -0
- package/lib/typescript/react-native/src/AlphaVideoView.d.ts +189 -0
- package/lib/typescript/react-native/src/AlphaVideoView.d.ts.map +1 -0
- package/lib/typescript/react-native/src/AlphaVideoViewNativeComponent.d.ts +109 -0
- package/lib/typescript/react-native/src/AlphaVideoViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/react-native/src/AlphaVideoViewNativeComponent.web.d.ts +5 -0
- package/lib/typescript/react-native/src/AlphaVideoViewNativeComponent.web.d.ts.map +1 -0
- package/lib/typescript/react-native/src/NativeAlphaVideoModule.d.ts +21 -0
- package/lib/typescript/react-native/src/NativeAlphaVideoModule.d.ts.map +1 -0
- package/lib/typescript/react-native/src/NativeAlphaVideoModule.web.d.ts +3 -0
- package/lib/typescript/react-native/src/NativeAlphaVideoModule.web.d.ts.map +1 -0
- package/lib/typescript/react-native/src/WebPlayer.d.ts +3 -0
- package/lib/typescript/react-native/src/WebPlayer.d.ts.map +1 -0
- package/lib/typescript/react-native/src/WebPlayer.web.d.ts +9 -0
- package/lib/typescript/react-native/src/WebPlayer.web.d.ts.map +1 -0
- package/lib/typescript/react-native/src/index.d.ts +77 -0
- package/lib/typescript/react-native/src/index.d.ts.map +1 -0
- package/licenses/dav1d-COPYING.txt +23 -0
- package/licenses/libvpx-LICENSE.txt +31 -0
- package/licenses/libvpx-PATENTS.txt +23 -0
- package/licenses/libwebm-LICENSE.txt +30 -0
- package/licenses/libwebm-PATENTS.txt +23 -0
- package/package.json +150 -4
- package/prebuilt/android/arm64-v8a/lib/libdav1d.a +0 -0
- package/prebuilt/android/arm64-v8a/lib/libvpx.a +0 -0
- package/prebuilt/android/armeabi-v7a/lib/libdav1d.a +0 -0
- package/prebuilt/android/armeabi-v7a/lib/libvpx.a +0 -0
- package/prebuilt/android/x86_64/lib/libdav1d.a +0 -0
- package/prebuilt/android/x86_64/lib/libvpx.a +0 -0
- package/prebuilt/include/dav1d/common.h +94 -0
- package/prebuilt/include/dav1d/data.h +117 -0
- package/prebuilt/include/dav1d/dav1d.h +329 -0
- package/prebuilt/include/dav1d/headers.h +440 -0
- package/prebuilt/include/dav1d/picture.h +157 -0
- package/prebuilt/include/dav1d/version.h +50 -0
- package/prebuilt/include/vpx/vp8.h +136 -0
- package/prebuilt/include/vpx/vp8dx.h +228 -0
- package/prebuilt/include/vpx/vpx_codec.h +475 -0
- package/prebuilt/include/vpx/vpx_decoder.h +365 -0
- package/prebuilt/include/vpx/vpx_frame_buffer.h +83 -0
- package/prebuilt/include/vpx/vpx_image.h +209 -0
- package/prebuilt/include/vpx/vpx_integer.h +40 -0
- package/prebuilt/ios/lib/libdav1d.a +0 -0
- package/prebuilt/ios/lib/libvpx.a +0 -0
- package/prebuilt/ios-simulator/include/dav1d/common.h +94 -0
- package/prebuilt/ios-simulator/include/dav1d/data.h +117 -0
- package/prebuilt/ios-simulator/include/dav1d/dav1d.h +329 -0
- package/prebuilt/ios-simulator/include/dav1d/headers.h +440 -0
- package/prebuilt/ios-simulator/include/dav1d/picture.h +157 -0
- package/prebuilt/ios-simulator/include/dav1d/version.h +50 -0
- package/prebuilt/ios-simulator/include/vpx/vp8.h +136 -0
- package/prebuilt/ios-simulator/include/vpx/vp8dx.h +228 -0
- package/prebuilt/ios-simulator/include/vpx/vpx_codec.h +475 -0
- package/prebuilt/ios-simulator/include/vpx/vpx_decoder.h +365 -0
- package/prebuilt/ios-simulator/include/vpx/vpx_frame_buffer.h +83 -0
- package/prebuilt/ios-simulator/include/vpx/vpx_image.h +209 -0
- package/prebuilt/ios-simulator/include/vpx/vpx_integer.h +40 -0
- package/prebuilt/ios-simulator/lib/libdav1d.a +0 -0
- package/prebuilt/ios-simulator/lib/libvpx.a +0 -0
- package/react-native/android/CMakeLists.txt +14 -0
- package/react-native/android/build.gradle +110 -0
- package/react-native/android/src/main/AndroidManifest.xml +1 -0
- package/react-native/android/src/main/java/dev/mediacache/alphavideo/reactnative/AlphaVideoModule.java +102 -0
- package/react-native/android/src/main/java/dev/mediacache/alphavideo/reactnative/AlphaVideoPackage.java +50 -0
- package/react-native/android/src/main/java/dev/mediacache/alphavideo/reactnative/AlphaVideoViewManager.java +317 -0
- package/react-native/android/src/newarch/java/dev/mediacache/alphavideo/reactnative/AlphaVideoModuleSpec.java +10 -0
- package/react-native/android/src/newarch/java/dev/mediacache/alphavideo/reactnative/AlphaVideoViewManagerSpec.java +23 -0
- package/react-native/android/src/norangesource/java/dev/mediacache/alphavideo/AppDataSource.java +15 -0
- package/react-native/android/src/oldarch/java/dev/mediacache/alphavideo/reactnative/AlphaVideoModuleSpec.java +30 -0
- package/react-native/android/src/oldarch/java/dev/mediacache/alphavideo/reactnative/AlphaVideoViewManagerSpec.java +61 -0
- package/react-native/ios/RNAlphaVideoViewComponentView.mm +173 -0
- package/react-native/ios/RNAlphaVideoViewManager.mm +147 -0
- package/react-native/src/AlphaVideoView.tsx +329 -0
- package/react-native/src/AlphaVideoViewNativeComponent.ts +132 -0
- package/react-native/src/AlphaVideoViewNativeComponent.web.ts +5 -0
- package/react-native/src/NativeAlphaVideoModule.ts +22 -0
- package/react-native/src/NativeAlphaVideoModule.web.ts +2 -0
- package/react-native/src/WebPlayer.tsx +7 -0
- package/react-native/src/WebPlayer.web.tsx +60 -0
- package/react-native/src/index.tsx +144 -0
- package/react-native-alpha-video.podspec +99 -0
- package/react-native.config.js +12 -0
- package/scripts/build_codecs_android.sh +246 -0
- package/scripts/build_codecs_ios.sh +31 -0
- package/scripts/build_codecs_ios_device.sh +210 -0
- package/scripts/build_codecs_ios_simulator.sh +256 -0
- package/scripts/build_wasm.sh +230 -0
- package/scripts/build_xcframework.sh +49 -0
- package/scripts/fetch-prebuilt.sh +48 -0
- package/scripts/package_release.sh +107 -0
- package/scripts/publish-android.sh +85 -0
- package/scripts/vendor_range_source.sh +47 -0
- package/third_party/libwebm/AUTHORS.TXT +5 -0
- package/third_party/libwebm/LICENSE.TXT +30 -0
- package/third_party/libwebm/PATENTS.TXT +23 -0
- package/third_party/libwebm/README.md +7 -0
- package/third_party/libwebm/webm_parser/include/webm/buffer_reader.h +138 -0
- package/third_party/libwebm/webm_parser/include/webm/callback.h +363 -0
- package/third_party/libwebm/webm_parser/include/webm/dom_types.h +1781 -0
- package/third_party/libwebm/webm_parser/include/webm/element.h +208 -0
- package/third_party/libwebm/webm_parser/include/webm/file_reader.h +103 -0
- package/third_party/libwebm/webm_parser/include/webm/id.h +1085 -0
- package/third_party/libwebm/webm_parser/include/webm/istream_reader.h +99 -0
- package/third_party/libwebm/webm_parser/include/webm/reader.h +94 -0
- package/third_party/libwebm/webm_parser/include/webm/status.h +166 -0
- package/third_party/libwebm/webm_parser/include/webm/webm_parser.h +133 -0
- package/third_party/libwebm/webm_parser/src/ancestory.cc +334 -0
- package/third_party/libwebm/webm_parser/src/ancestory.h +83 -0
- package/third_party/libwebm/webm_parser/src/audio_parser.h +84 -0
- package/third_party/libwebm/webm_parser/src/bit_utils.cc +26 -0
- package/third_party/libwebm/webm_parser/src/bit_utils.h +24 -0
- package/third_party/libwebm/webm_parser/src/block_additions_parser.h +30 -0
- package/third_party/libwebm/webm_parser/src/block_group_parser.h +71 -0
- package/third_party/libwebm/webm_parser/src/block_header_parser.cc +76 -0
- package/third_party/libwebm/webm_parser/src/block_header_parser.h +65 -0
- package/third_party/libwebm/webm_parser/src/block_more_parser.h +32 -0
- package/third_party/libwebm/webm_parser/src/block_parser.cc +285 -0
- package/third_party/libwebm/webm_parser/src/block_parser.h +126 -0
- package/third_party/libwebm/webm_parser/src/bool_parser.h +95 -0
- package/third_party/libwebm/webm_parser/src/buffer_reader.cc +110 -0
- package/third_party/libwebm/webm_parser/src/byte_parser.h +144 -0
- package/third_party/libwebm/webm_parser/src/callback.cc +155 -0
- package/third_party/libwebm/webm_parser/src/chapter_atom_parser.h +42 -0
- package/third_party/libwebm/webm_parser/src/chapter_display_parser.h +34 -0
- package/third_party/libwebm/webm_parser/src/chapters_parser.h +28 -0
- package/third_party/libwebm/webm_parser/src/cluster_parser.h +48 -0
- package/third_party/libwebm/webm_parser/src/colour_parser.h +55 -0
- package/third_party/libwebm/webm_parser/src/content_enc_aes_settings_parser.h +32 -0
- package/third_party/libwebm/webm_parser/src/content_encoding_parser.h +38 -0
- package/third_party/libwebm/webm_parser/src/content_encodings_parser.h +30 -0
- package/third_party/libwebm/webm_parser/src/content_encryption_parser.h +37 -0
- package/third_party/libwebm/webm_parser/src/cue_point_parser.h +38 -0
- package/third_party/libwebm/webm_parser/src/cue_track_positions_parser.h +39 -0
- package/third_party/libwebm/webm_parser/src/cues_parser.h +27 -0
- package/third_party/libwebm/webm_parser/src/date_parser.cc +72 -0
- package/third_party/libwebm/webm_parser/src/date_parser.h +64 -0
- package/third_party/libwebm/webm_parser/src/ebml_parser.h +48 -0
- package/third_party/libwebm/webm_parser/src/edition_entry_parser.h +35 -0
- package/third_party/libwebm/webm_parser/src/element_parser.h +102 -0
- package/third_party/libwebm/webm_parser/src/file_reader.cc +142 -0
- package/third_party/libwebm/webm_parser/src/float_parser.cc +77 -0
- package/third_party/libwebm/webm_parser/src/float_parser.h +65 -0
- package/third_party/libwebm/webm_parser/src/id_element_parser.cc +49 -0
- package/third_party/libwebm/webm_parser/src/id_element_parser.h +56 -0
- package/third_party/libwebm/webm_parser/src/id_parser.cc +75 -0
- package/third_party/libwebm/webm_parser/src/id_parser.h +45 -0
- package/third_party/libwebm/webm_parser/src/info_parser.h +44 -0
- package/third_party/libwebm/webm_parser/src/int_parser.h +121 -0
- package/third_party/libwebm/webm_parser/src/istream_reader.cc +133 -0
- package/third_party/libwebm/webm_parser/src/master_parser.cc +298 -0
- package/third_party/libwebm/webm_parser/src/master_parser.h +230 -0
- package/third_party/libwebm/webm_parser/src/master_value_parser.h +533 -0
- package/third_party/libwebm/webm_parser/src/mastering_metadata_parser.h +57 -0
- package/third_party/libwebm/webm_parser/src/parser.h +34 -0
- package/third_party/libwebm/webm_parser/src/parser_utils.cc +34 -0
- package/third_party/libwebm/webm_parser/src/parser_utils.h +64 -0
- package/third_party/libwebm/webm_parser/src/projection_parser.h +40 -0
- package/third_party/libwebm/webm_parser/src/recursive_parser.h +93 -0
- package/third_party/libwebm/webm_parser/src/seek_head_parser.h +27 -0
- package/third_party/libwebm/webm_parser/src/seek_parser.h +37 -0
- package/third_party/libwebm/webm_parser/src/segment_parser.cc +86 -0
- package/third_party/libwebm/webm_parser/src/segment_parser.h +53 -0
- package/third_party/libwebm/webm_parser/src/simple_tag_parser.h +37 -0
- package/third_party/libwebm/webm_parser/src/size_parser.cc +56 -0
- package/third_party/libwebm/webm_parser/src/size_parser.h +43 -0
- package/third_party/libwebm/webm_parser/src/skip_callback.h +63 -0
- package/third_party/libwebm/webm_parser/src/skip_parser.cc +59 -0
- package/third_party/libwebm/webm_parser/src/skip_parser.h +35 -0
- package/third_party/libwebm/webm_parser/src/slices_parser.h +30 -0
- package/third_party/libwebm/webm_parser/src/tag_parser.h +37 -0
- package/third_party/libwebm/webm_parser/src/tags_parser.h +27 -0
- package/third_party/libwebm/webm_parser/src/targets_parser.h +35 -0
- package/third_party/libwebm/webm_parser/src/time_slice_parser.h +30 -0
- package/third_party/libwebm/webm_parser/src/track_entry_parser.h +65 -0
- package/third_party/libwebm/webm_parser/src/tracks_parser.h +27 -0
- package/third_party/libwebm/webm_parser/src/unknown_parser.cc +49 -0
- package/third_party/libwebm/webm_parser/src/unknown_parser.h +38 -0
- package/third_party/libwebm/webm_parser/src/var_int_parser.cc +71 -0
- package/third_party/libwebm/webm_parser/src/var_int_parser.h +56 -0
- package/third_party/libwebm/webm_parser/src/video_parser.h +122 -0
- package/third_party/libwebm/webm_parser/src/virtual_block_parser.cc +72 -0
- package/third_party/libwebm/webm_parser/src/virtual_block_parser.h +69 -0
- package/third_party/libwebm/webm_parser/src/void_parser.cc +49 -0
- package/third_party/libwebm/webm_parser/src/void_parser.h +41 -0
- package/third_party/libwebm/webm_parser/src/webm_parser.cc +282 -0
- package/third_party/range-source/LICENSE +21 -0
- package/third_party/range-source/README.md +8 -0
- package/third_party/range-source/include/range_source.h +395 -0
- package/third_party/range-source/include/range_source_download.h +309 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
|
|
2
|
+
//
|
|
3
|
+
// Use of this source code is governed by a BSD-style license
|
|
4
|
+
// that can be found in the LICENSE file in the root of the source
|
|
5
|
+
// tree. An additional intellectual property rights grant can be found
|
|
6
|
+
// in the file PATENTS. All contributing project authors may
|
|
7
|
+
// be found in the AUTHORS file in the root of the source tree.
|
|
8
|
+
#include "webm/istream_reader.h"
|
|
9
|
+
|
|
10
|
+
#include <cassert>
|
|
11
|
+
#include <cstdint>
|
|
12
|
+
#include <cstdio>
|
|
13
|
+
#include <cstdlib>
|
|
14
|
+
#include <limits>
|
|
15
|
+
#include <memory>
|
|
16
|
+
|
|
17
|
+
#include "webm/status.h"
|
|
18
|
+
|
|
19
|
+
namespace webm {
|
|
20
|
+
|
|
21
|
+
IstreamReader::IstreamReader(IstreamReader&& other)
|
|
22
|
+
: istream_(std::move(other.istream_)), position_(other.position_) {
|
|
23
|
+
other.position_ = 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
IstreamReader& IstreamReader::operator=(IstreamReader&& other) {
|
|
27
|
+
if (this != &other) {
|
|
28
|
+
istream_ = std::move(other.istream_);
|
|
29
|
+
position_ = other.position_;
|
|
30
|
+
other.position_ = 0;
|
|
31
|
+
}
|
|
32
|
+
return *this;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
Status IstreamReader::Read(std::size_t num_to_read, std::uint8_t* buffer,
|
|
36
|
+
std::uint64_t* num_actually_read) {
|
|
37
|
+
assert(num_to_read > 0);
|
|
38
|
+
assert(buffer != nullptr);
|
|
39
|
+
assert(num_actually_read != nullptr);
|
|
40
|
+
|
|
41
|
+
if (istream_ == nullptr) {
|
|
42
|
+
*num_actually_read = 0;
|
|
43
|
+
return Status(Status::kEndOfFile);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
|
|
47
|
+
constexpr std::streamsize streamsize_max =
|
|
48
|
+
std::numeric_limits<std::streamsize>::max();
|
|
49
|
+
std::streamsize limited_num_to_read;
|
|
50
|
+
if (num_to_read > static_cast<unsigned_streamsize>(streamsize_max)) {
|
|
51
|
+
limited_num_to_read = streamsize_max;
|
|
52
|
+
} else {
|
|
53
|
+
limited_num_to_read = static_cast<std::streamsize>(num_to_read);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
istream_->read(reinterpret_cast<char*>(buffer), limited_num_to_read);
|
|
57
|
+
std::streamsize actual = istream_->gcount();
|
|
58
|
+
*num_actually_read = static_cast<std::uint64_t>(actual);
|
|
59
|
+
position_ += *num_actually_read;
|
|
60
|
+
|
|
61
|
+
if (actual == 0) {
|
|
62
|
+
return Status(Status::kEndOfFile);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (static_cast<std::size_t>(actual) == num_to_read) {
|
|
66
|
+
return Status(Status::kOkCompleted);
|
|
67
|
+
} else {
|
|
68
|
+
return Status(Status::kOkPartial);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
Status IstreamReader::Skip(std::uint64_t num_to_skip,
|
|
73
|
+
std::uint64_t* num_actually_skipped) {
|
|
74
|
+
assert(num_to_skip > 0);
|
|
75
|
+
assert(num_actually_skipped != nullptr);
|
|
76
|
+
|
|
77
|
+
*num_actually_skipped = 0;
|
|
78
|
+
if (istream_ == nullptr || !istream_->good()) {
|
|
79
|
+
return Status(Status::kEndOfFile);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Try seeking forward first.
|
|
83
|
+
using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
|
|
84
|
+
constexpr std::streamsize streamsize_max =
|
|
85
|
+
std::numeric_limits<std::streamsize>::max();
|
|
86
|
+
std::streamsize seek_offset;
|
|
87
|
+
if (num_to_skip > static_cast<unsigned_streamsize>(streamsize_max)) {
|
|
88
|
+
seek_offset = streamsize_max;
|
|
89
|
+
} else {
|
|
90
|
+
seek_offset = static_cast<std::streamsize>(num_to_skip);
|
|
91
|
+
}
|
|
92
|
+
if (istream_->seekg(seek_offset, std::ios_base::cur)) {
|
|
93
|
+
*num_actually_skipped = static_cast<std::uint64_t>(seek_offset);
|
|
94
|
+
position_ += static_cast<std::uint64_t>(seek_offset);
|
|
95
|
+
if (static_cast<std::uint64_t>(seek_offset) == num_to_skip) {
|
|
96
|
+
return Status(Status::kOkCompleted);
|
|
97
|
+
} else {
|
|
98
|
+
return Status(Status::kOkPartial);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
istream_->clear();
|
|
102
|
+
|
|
103
|
+
// Seeking doesn't work on things like pipes, so if seeking failed then fall
|
|
104
|
+
// back to reading the data into a junk buffer.
|
|
105
|
+
std::size_t actual = 0;
|
|
106
|
+
do {
|
|
107
|
+
char junk[1024];
|
|
108
|
+
std::streamsize num_to_read = static_cast<std::streamsize>(sizeof(junk));
|
|
109
|
+
if (num_to_skip < static_cast<std::uint64_t>(num_to_read)) {
|
|
110
|
+
num_to_read = static_cast<std::streamsize>(num_to_skip);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
istream_->read(junk, num_to_read);
|
|
114
|
+
std::streamsize actual = istream_->gcount();
|
|
115
|
+
*num_actually_skipped += static_cast<std::uint64_t>(actual);
|
|
116
|
+
position_ += static_cast<std::uint64_t>(actual);
|
|
117
|
+
num_to_skip -= static_cast<std::uint64_t>(actual);
|
|
118
|
+
} while (actual > 0 && num_to_skip > 0);
|
|
119
|
+
|
|
120
|
+
if (*num_actually_skipped == 0) {
|
|
121
|
+
return Status(Status::kEndOfFile);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (num_to_skip == 0) {
|
|
125
|
+
return Status(Status::kOkCompleted);
|
|
126
|
+
} else {
|
|
127
|
+
return Status(Status::kOkPartial);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
std::uint64_t IstreamReader::Position() const { return position_; }
|
|
132
|
+
|
|
133
|
+
} // namespace webm
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
|
|
2
|
+
//
|
|
3
|
+
// Use of this source code is governed by a BSD-style license
|
|
4
|
+
// that can be found in the LICENSE file in the root of the source
|
|
5
|
+
// tree. An additional intellectual property rights grant can be found
|
|
6
|
+
// in the file PATENTS. All contributing project authors may
|
|
7
|
+
// be found in the AUTHORS file in the root of the source tree.
|
|
8
|
+
#include "src/master_parser.h"
|
|
9
|
+
|
|
10
|
+
#include <cassert>
|
|
11
|
+
#include <cstdint>
|
|
12
|
+
#include <limits>
|
|
13
|
+
|
|
14
|
+
#include "src/element_parser.h"
|
|
15
|
+
#include "src/skip_callback.h"
|
|
16
|
+
#include "webm/element.h"
|
|
17
|
+
#include "webm/id.h"
|
|
18
|
+
#include "webm/reader.h"
|
|
19
|
+
#include "webm/status.h"
|
|
20
|
+
|
|
21
|
+
namespace webm {
|
|
22
|
+
|
|
23
|
+
// Spec reference:
|
|
24
|
+
// http://matroska.org/technical/specs/index.html#EBML_ex
|
|
25
|
+
// https://github.com/Matroska-Org/ebml-specification/blob/master/specification.markdown
|
|
26
|
+
Status MasterParser::Init(const ElementMetadata& metadata,
|
|
27
|
+
std::uint64_t max_size) {
|
|
28
|
+
assert(metadata.size == kUnknownElementSize || metadata.size <= max_size);
|
|
29
|
+
|
|
30
|
+
InitSetup(metadata.header_size, metadata.size, metadata.position);
|
|
31
|
+
|
|
32
|
+
if (metadata.size != kUnknownElementSize) {
|
|
33
|
+
max_size_ = metadata.size;
|
|
34
|
+
} else {
|
|
35
|
+
max_size_ = max_size;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (metadata.size == 0) {
|
|
39
|
+
state_ = State::kEndReached;
|
|
40
|
+
} else {
|
|
41
|
+
state_ = State::kFirstReadOfChildId;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return Status(Status::kOkCompleted);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
void MasterParser::InitAfterSeek(const Ancestory& child_ancestory,
|
|
48
|
+
const ElementMetadata& child_metadata) {
|
|
49
|
+
InitSetup(kUnknownHeaderSize, kUnknownElementSize, kUnknownElementPosition);
|
|
50
|
+
max_size_ = std::numeric_limits<std::uint64_t>::max();
|
|
51
|
+
|
|
52
|
+
if (child_ancestory.empty()) {
|
|
53
|
+
child_metadata_ = child_metadata;
|
|
54
|
+
auto iter = parsers_.find(child_metadata_.id);
|
|
55
|
+
assert(iter != parsers_.end());
|
|
56
|
+
child_parser_ = iter->second.get();
|
|
57
|
+
state_ = State::kGettingAction;
|
|
58
|
+
} else {
|
|
59
|
+
child_metadata_.id = child_ancestory.id();
|
|
60
|
+
child_metadata_.header_size = kUnknownHeaderSize;
|
|
61
|
+
child_metadata_.size = kUnknownElementSize;
|
|
62
|
+
child_metadata_.position = kUnknownElementPosition;
|
|
63
|
+
|
|
64
|
+
auto iter = parsers_.find(child_metadata_.id);
|
|
65
|
+
assert(iter != parsers_.end());
|
|
66
|
+
child_parser_ = iter->second.get();
|
|
67
|
+
child_parser_->InitAfterSeek(child_ancestory.next(), child_metadata);
|
|
68
|
+
state_ = State::kReadingChildBody;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
Status MasterParser::Feed(Callback* callback, Reader* reader,
|
|
73
|
+
std::uint64_t* num_bytes_read) {
|
|
74
|
+
assert(callback != nullptr);
|
|
75
|
+
assert(reader != nullptr);
|
|
76
|
+
assert(num_bytes_read != nullptr);
|
|
77
|
+
|
|
78
|
+
*num_bytes_read = 0;
|
|
79
|
+
|
|
80
|
+
Callback* const original_callback = callback;
|
|
81
|
+
|
|
82
|
+
SkipCallback skip_callback;
|
|
83
|
+
if (action_ == Action::kSkip) {
|
|
84
|
+
callback = &skip_callback;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
Status status;
|
|
88
|
+
std::uint64_t local_num_bytes_read;
|
|
89
|
+
while (true) {
|
|
90
|
+
switch (state_) {
|
|
91
|
+
case State::kFirstReadOfChildId: {
|
|
92
|
+
// This separate case for the first read of the child ID is needed to
|
|
93
|
+
// avoid potential bugs where calling Feed() twice in a row on an
|
|
94
|
+
// unsized element at the end of the stream would return
|
|
95
|
+
// Status::kOkCompleted instead of Status::kEndOfFile (since we convert
|
|
96
|
+
// Status::kEndOfFile to Status::kOkCompleted when EOF is hit for an
|
|
97
|
+
// unsized element after its children have been fully parsed). Once
|
|
98
|
+
// the ID parser consumes > 0 bytes, this state must be exited.
|
|
99
|
+
assert(child_parser_ == nullptr);
|
|
100
|
+
assert(my_size_ == kUnknownElementSize || total_bytes_read_ < my_size_);
|
|
101
|
+
child_metadata_.position = reader->Position();
|
|
102
|
+
child_metadata_.header_size = 0;
|
|
103
|
+
status = id_parser_.Feed(callback, reader, &local_num_bytes_read);
|
|
104
|
+
*num_bytes_read += local_num_bytes_read;
|
|
105
|
+
total_bytes_read_ += local_num_bytes_read;
|
|
106
|
+
child_metadata_.header_size +=
|
|
107
|
+
static_cast<std::uint32_t>(local_num_bytes_read);
|
|
108
|
+
if (status.code == Status::kEndOfFile &&
|
|
109
|
+
my_size_ == kUnknownElementSize && local_num_bytes_read == 0) {
|
|
110
|
+
state_ = State::kEndReached;
|
|
111
|
+
} else if (!status.ok()) {
|
|
112
|
+
if (local_num_bytes_read > 0) {
|
|
113
|
+
state_ = State::kFinishingReadingChildId;
|
|
114
|
+
}
|
|
115
|
+
return status;
|
|
116
|
+
} else if (status.completed_ok()) {
|
|
117
|
+
state_ = State::kReadingChildSize;
|
|
118
|
+
} else {
|
|
119
|
+
state_ = State::kFinishingReadingChildId;
|
|
120
|
+
}
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
case State::kFinishingReadingChildId: {
|
|
125
|
+
assert(child_parser_ == nullptr);
|
|
126
|
+
assert(my_size_ == kUnknownElementSize || total_bytes_read_ < my_size_);
|
|
127
|
+
status = id_parser_.Feed(callback, reader, &local_num_bytes_read);
|
|
128
|
+
*num_bytes_read += local_num_bytes_read;
|
|
129
|
+
total_bytes_read_ += local_num_bytes_read;
|
|
130
|
+
child_metadata_.header_size +=
|
|
131
|
+
static_cast<std::uint32_t>(local_num_bytes_read);
|
|
132
|
+
if (!status.completed_ok()) {
|
|
133
|
+
return status;
|
|
134
|
+
}
|
|
135
|
+
state_ = State::kReadingChildSize;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
case State::kReadingChildSize: {
|
|
140
|
+
assert(child_parser_ == nullptr);
|
|
141
|
+
assert(total_bytes_read_ > 0);
|
|
142
|
+
status = size_parser_.Feed(callback, reader, &local_num_bytes_read);
|
|
143
|
+
*num_bytes_read += local_num_bytes_read;
|
|
144
|
+
total_bytes_read_ += local_num_bytes_read;
|
|
145
|
+
child_metadata_.header_size +=
|
|
146
|
+
static_cast<std::uint32_t>(local_num_bytes_read);
|
|
147
|
+
if (!status.completed_ok()) {
|
|
148
|
+
return status;
|
|
149
|
+
}
|
|
150
|
+
child_metadata_.id = id_parser_.id();
|
|
151
|
+
child_metadata_.size = size_parser_.size();
|
|
152
|
+
state_ = State::kValidatingChildSize;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
case State::kValidatingChildSize: {
|
|
157
|
+
assert(child_parser_ == nullptr);
|
|
158
|
+
|
|
159
|
+
std::uint64_t byte_count = total_bytes_read_;
|
|
160
|
+
if (child_metadata_.size != kUnknownElementSize) {
|
|
161
|
+
byte_count += child_metadata_.size;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
std::uint64_t byte_cap = max_size_;
|
|
165
|
+
// my_size_ is <= max_size_ if it's known, so pick the smaller value.
|
|
166
|
+
if (my_size_ != kUnknownElementSize) {
|
|
167
|
+
byte_cap = my_size_;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (byte_count > byte_cap) {
|
|
171
|
+
return Status(Status::kElementOverflow);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
auto iter = parsers_.find(child_metadata_.id);
|
|
175
|
+
bool unknown_child = iter == parsers_.end();
|
|
176
|
+
|
|
177
|
+
if (my_size_ == kUnknownElementSize && unknown_child) {
|
|
178
|
+
// The end of an unsized master element is considered to be the first
|
|
179
|
+
// instance of an element that isn't a known/valid child element.
|
|
180
|
+
has_cached_metadata_ = true;
|
|
181
|
+
state_ = State::kEndReached;
|
|
182
|
+
continue;
|
|
183
|
+
} else if (unknown_child &&
|
|
184
|
+
child_metadata_.size == kUnknownElementSize) {
|
|
185
|
+
// We can't skip or otherwise handle unknown elements with an unknown
|
|
186
|
+
// size.
|
|
187
|
+
return Status(Status::kIndefiniteUnknownElement);
|
|
188
|
+
}
|
|
189
|
+
if (unknown_child) {
|
|
190
|
+
child_parser_ = &unknown_parser_;
|
|
191
|
+
} else {
|
|
192
|
+
child_parser_ = iter->second.get();
|
|
193
|
+
}
|
|
194
|
+
state_ = State::kGettingAction;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
case State::kGettingAction: {
|
|
199
|
+
assert(child_parser_ != nullptr);
|
|
200
|
+
status = callback->OnElementBegin(child_metadata_, &action_);
|
|
201
|
+
if (!status.completed_ok()) {
|
|
202
|
+
return status;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (action_ == Action::kSkip) {
|
|
206
|
+
callback = &skip_callback;
|
|
207
|
+
if (child_metadata_.size != kUnknownElementSize) {
|
|
208
|
+
child_parser_ = &skip_parser_;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
state_ = State::kInitializingChildParser;
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
case State::kInitializingChildParser: {
|
|
216
|
+
assert(child_parser_ != nullptr);
|
|
217
|
+
status =
|
|
218
|
+
child_parser_->Init(child_metadata_, max_size_ - total_bytes_read_);
|
|
219
|
+
if (!status.completed_ok()) {
|
|
220
|
+
return status;
|
|
221
|
+
}
|
|
222
|
+
state_ = State::kReadingChildBody;
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
case State::kReadingChildBody: {
|
|
227
|
+
assert(child_parser_ != nullptr);
|
|
228
|
+
status = child_parser_->Feed(callback, reader, &local_num_bytes_read);
|
|
229
|
+
*num_bytes_read += local_num_bytes_read;
|
|
230
|
+
total_bytes_read_ += local_num_bytes_read;
|
|
231
|
+
if (!status.completed_ok()) {
|
|
232
|
+
return status;
|
|
233
|
+
}
|
|
234
|
+
state_ = State::kChildFullyParsed;
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
case State::kChildFullyParsed: {
|
|
239
|
+
assert(child_parser_ != nullptr);
|
|
240
|
+
std::uint64_t byte_cap = max_size_;
|
|
241
|
+
// my_size_ is <= max_size_ if it's known, so pick the smaller value.
|
|
242
|
+
if (my_size_ != kUnknownElementSize) {
|
|
243
|
+
byte_cap = my_size_;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (total_bytes_read_ > byte_cap) {
|
|
247
|
+
return Status(Status::kElementOverflow);
|
|
248
|
+
} else if (total_bytes_read_ == byte_cap) {
|
|
249
|
+
state_ = State::kEndReached;
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (child_parser_->GetCachedMetadata(&child_metadata_)) {
|
|
254
|
+
state_ = State::kValidatingChildSize;
|
|
255
|
+
} else {
|
|
256
|
+
state_ = State::kFirstReadOfChildId;
|
|
257
|
+
}
|
|
258
|
+
PrepareForNextChild();
|
|
259
|
+
callback = original_callback;
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
case State::kEndReached: {
|
|
264
|
+
return Status(Status::kOkCompleted);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
bool MasterParser::GetCachedMetadata(ElementMetadata* metadata) {
|
|
271
|
+
assert(metadata != nullptr);
|
|
272
|
+
|
|
273
|
+
if (has_cached_metadata_) {
|
|
274
|
+
*metadata = child_metadata_;
|
|
275
|
+
}
|
|
276
|
+
return has_cached_metadata_;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
void MasterParser::InitSetup(std::uint32_t header_size,
|
|
280
|
+
std::uint64_t size_in_bytes,
|
|
281
|
+
std::uint64_t position) {
|
|
282
|
+
PrepareForNextChild();
|
|
283
|
+
header_size_ = header_size;
|
|
284
|
+
my_size_ = size_in_bytes;
|
|
285
|
+
my_position_ = position;
|
|
286
|
+
total_bytes_read_ = 0;
|
|
287
|
+
has_cached_metadata_ = false;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
void MasterParser::PrepareForNextChild() {
|
|
291
|
+
// Do not reset child_metadata_ here.
|
|
292
|
+
id_parser_ = {};
|
|
293
|
+
size_parser_ = {};
|
|
294
|
+
child_parser_ = nullptr;
|
|
295
|
+
action_ = Action::kRead;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
} // namespace webm
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
|
|
2
|
+
//
|
|
3
|
+
// Use of this source code is governed by a BSD-style license
|
|
4
|
+
// that can be found in the LICENSE file in the root of the source
|
|
5
|
+
// tree. An additional intellectual property rights grant can be found
|
|
6
|
+
// in the file PATENTS. All contributing project authors may
|
|
7
|
+
// be found in the AUTHORS file in the root of the source tree.
|
|
8
|
+
#ifndef SRC_MASTER_PARSER_H_
|
|
9
|
+
#define SRC_MASTER_PARSER_H_
|
|
10
|
+
|
|
11
|
+
#include <cassert>
|
|
12
|
+
#include <cstdint>
|
|
13
|
+
#include <functional>
|
|
14
|
+
#include <memory>
|
|
15
|
+
#include <type_traits>
|
|
16
|
+
#include <unordered_map>
|
|
17
|
+
#include <utility>
|
|
18
|
+
|
|
19
|
+
#include "src/element_parser.h"
|
|
20
|
+
#include "src/id_parser.h"
|
|
21
|
+
#include "src/size_parser.h"
|
|
22
|
+
#include "src/skip_parser.h"
|
|
23
|
+
#include "src/unknown_parser.h"
|
|
24
|
+
#include "src/void_parser.h"
|
|
25
|
+
#include "webm/callback.h"
|
|
26
|
+
#include "webm/element.h"
|
|
27
|
+
#include "webm/id.h"
|
|
28
|
+
#include "webm/reader.h"
|
|
29
|
+
#include "webm/status.h"
|
|
30
|
+
|
|
31
|
+
namespace webm {
|
|
32
|
+
|
|
33
|
+
// A general purpose parser for EBML master elements.
|
|
34
|
+
//
|
|
35
|
+
// For example, if a document specification defines a Foo master element that
|
|
36
|
+
// has two boolean children (Bar and Baz), then a FooParser capable of parsing
|
|
37
|
+
// the Foo master element could be defined as follows:
|
|
38
|
+
//
|
|
39
|
+
// struct FooParser : public MasterParser {
|
|
40
|
+
// FooParser()
|
|
41
|
+
// : MasterParser(MakeChild<BoolParser>(Id::kBar),
|
|
42
|
+
// MakeChild<BoolParser>(Id::kBaz)) {}
|
|
43
|
+
// };
|
|
44
|
+
//
|
|
45
|
+
// See the MasterValueParser for an alternative class for parsing master
|
|
46
|
+
// elements into a data structure.
|
|
47
|
+
class MasterParser : public ElementParser {
|
|
48
|
+
public:
|
|
49
|
+
// Constructs a new MasterParser that uses the given
|
|
50
|
+
// {Id, std::unique_ptr<ElementParser>} pairs to map child IDs to the
|
|
51
|
+
// appropriate parser/handler. Each argument must be of type
|
|
52
|
+
// std::pair<Id, std::unique_ptr<ElementParser>>. If a parser is not
|
|
53
|
+
// explicitly provided for Id::kVoid, a VoidParser will automatically be used
|
|
54
|
+
// for it.
|
|
55
|
+
//
|
|
56
|
+
// Initializer lists don't support move-only types (i.e. std::unique_ptr), so
|
|
57
|
+
// instead a variadic template is used.
|
|
58
|
+
template <typename... T>
|
|
59
|
+
explicit MasterParser(T&&... parser_pairs) {
|
|
60
|
+
// Prefer an odd reserve size. This makes libc++ use a prime number for the
|
|
61
|
+
// bucket count. Otherwise, if it happens to be a power of 2, then libc++
|
|
62
|
+
// will use a power-of-2 bucket count (and since Matroska EBML IDs have low
|
|
63
|
+
// entropy in the low bits, there will be a lot of collisions). libstdc++
|
|
64
|
+
// always prefers a prime bucket count. I'm not sure how MSVC or others are
|
|
65
|
+
// implemented, but this shouldn't adversely affect them even if they are
|
|
66
|
+
// implemented differently. Add one to the count because we'll likely need
|
|
67
|
+
// to insert a parser for Id::kVoid.
|
|
68
|
+
parsers_.reserve((sizeof...(T) + 1) | 1);
|
|
69
|
+
|
|
70
|
+
// This dummy initializer list is just used to force the parameter pack to
|
|
71
|
+
// be expanded, which turns the expression into a for-each "loop" that
|
|
72
|
+
// inserts each argument into the map.
|
|
73
|
+
auto dummy = {0, (InsertParser(std::forward<T>(parser_pairs)), 0)...};
|
|
74
|
+
(void)dummy; // Silence unused variable warning.
|
|
75
|
+
|
|
76
|
+
if (parsers_.find(Id::kVoid) == parsers_.end()) {
|
|
77
|
+
InsertParser(MakeChild<VoidParser>(Id::kVoid));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
MasterParser(const MasterParser&) = delete;
|
|
82
|
+
MasterParser& operator=(const MasterParser&) = delete;
|
|
83
|
+
|
|
84
|
+
Status Init(const ElementMetadata& metadata, std::uint64_t max_size) override;
|
|
85
|
+
|
|
86
|
+
void InitAfterSeek(const Ancestory& child_ancestory,
|
|
87
|
+
const ElementMetadata& child_metadata) override;
|
|
88
|
+
|
|
89
|
+
Status Feed(Callback* callback, Reader* reader,
|
|
90
|
+
std::uint64_t* num_bytes_read) override;
|
|
91
|
+
|
|
92
|
+
bool GetCachedMetadata(ElementMetadata* metadata) override;
|
|
93
|
+
|
|
94
|
+
std::uint32_t header_size() const { return header_size_; }
|
|
95
|
+
|
|
96
|
+
// Gets the size of this element. May be called before the parse is fully
|
|
97
|
+
// complete (but only after Init() has already been called and successfully
|
|
98
|
+
// returned).
|
|
99
|
+
std::uint64_t size() const { return my_size_; }
|
|
100
|
+
|
|
101
|
+
// Gets absolute byte position of the start of the element in the byte stream.
|
|
102
|
+
// May be called before the parse is fully complete (but only after Init() has
|
|
103
|
+
// already been called and successfully returned).
|
|
104
|
+
std::uint64_t position() const { return my_position_; }
|
|
105
|
+
|
|
106
|
+
// Gets the metadata for the child that is currently being parsed. This may
|
|
107
|
+
// only be called while the child's body (not its header information like ID
|
|
108
|
+
// and size) is being parsed.
|
|
109
|
+
const ElementMetadata& child_metadata() const {
|
|
110
|
+
assert(state_ == State::kValidatingChildSize ||
|
|
111
|
+
state_ == State::kGettingAction ||
|
|
112
|
+
state_ == State::kInitializingChildParser ||
|
|
113
|
+
state_ == State::kReadingChildBody);
|
|
114
|
+
return child_metadata_;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
protected:
|
|
118
|
+
// Allocates a new parser of type T, forwarding args to the constructor, and
|
|
119
|
+
// creates a std::pair<Id, std::unique_ptr<ElementParser>> using the given id
|
|
120
|
+
// and the allocated parser.
|
|
121
|
+
template <typename T, typename... Args>
|
|
122
|
+
static std::pair<Id, std::unique_ptr<ElementParser>> MakeChild(
|
|
123
|
+
Id id, Args&&... args) {
|
|
124
|
+
std::unique_ptr<ElementParser> ptr(new T(std::forward<Args>(args)...));
|
|
125
|
+
return std::pair<Id, std::unique_ptr<ElementParser>>(id, std::move(ptr));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private:
|
|
129
|
+
// Parsing states for the finite-state machine.
|
|
130
|
+
enum class State {
|
|
131
|
+
/* clang-format off */
|
|
132
|
+
// State Transitions to state When
|
|
133
|
+
kFirstReadOfChildId, // kFinishingReadingChildId size(id) > 1
|
|
134
|
+
// kReadingChildSize size(id) == 1
|
|
135
|
+
// kEndReached EOF
|
|
136
|
+
kFinishingReadingChildId, // kReadingChildSize done
|
|
137
|
+
kReadingChildSize, // kValidatingChildSize done
|
|
138
|
+
kValidatingChildSize, // kGettingAction done
|
|
139
|
+
// kEndReached unknown id & unsized
|
|
140
|
+
kGettingAction, // kInitializingChildParser done
|
|
141
|
+
kInitializingChildParser, // kReadingChildBody done
|
|
142
|
+
kReadingChildBody, // kChildFullyParsed child parse done
|
|
143
|
+
kChildFullyParsed, // kValidatingChildSize cached metadata
|
|
144
|
+
// kFirstReadOfChildId read < my_size_
|
|
145
|
+
// kEndReached read == my_size_
|
|
146
|
+
kEndReached, // No transitions from here (must call Init)
|
|
147
|
+
/* clang-format on */
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
using StdHashIdKeyType = std::underlying_type<Id>::type;
|
|
151
|
+
using StdHashId = std::hash<StdHashIdKeyType>;
|
|
152
|
+
|
|
153
|
+
// Hash functor for hashing Id enums for storage in std::unordered_map.
|
|
154
|
+
struct IdHash : StdHashId {
|
|
155
|
+
#if __cpp_lib_is_invocable
|
|
156
|
+
using result_type = std::invoke_result<StdHashId, StdHashIdKeyType>::type;
|
|
157
|
+
#else
|
|
158
|
+
using result_type = StdHashId::result_type;
|
|
159
|
+
#endif // __cpp_lib_is_invocable
|
|
160
|
+
|
|
161
|
+
// Returns the hash of the given id.
|
|
162
|
+
result_type operator()(Id id) const {
|
|
163
|
+
return StdHashId::operator()(static_cast<StdHashIdKeyType>(id));
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
// The parser for parsing element Ids.
|
|
168
|
+
IdParser id_parser_;
|
|
169
|
+
|
|
170
|
+
// The parser for parsing element sizes.
|
|
171
|
+
SizeParser size_parser_;
|
|
172
|
+
|
|
173
|
+
// Metadata for the child element that is currently being parsed.
|
|
174
|
+
ElementMetadata child_metadata_;
|
|
175
|
+
|
|
176
|
+
// Maps child IDs to the appropriate parser that can handle that child.
|
|
177
|
+
std::unordered_map<Id, std::unique_ptr<ElementParser>, IdHash> parsers_;
|
|
178
|
+
|
|
179
|
+
// The parser that is used to parse unknown children.
|
|
180
|
+
UnknownParser unknown_parser_;
|
|
181
|
+
|
|
182
|
+
// The parser that is used to skip over children.
|
|
183
|
+
SkipParser skip_parser_;
|
|
184
|
+
|
|
185
|
+
// The parser that is being used to parse the current child. This must be null
|
|
186
|
+
// or a pointer in parsers_.
|
|
187
|
+
ElementParser* child_parser_;
|
|
188
|
+
|
|
189
|
+
// The current parsing action for the child that is currently being parsed.
|
|
190
|
+
Action action_ = Action::kRead;
|
|
191
|
+
|
|
192
|
+
// The current state of the parser.
|
|
193
|
+
State state_;
|
|
194
|
+
|
|
195
|
+
std::uint32_t header_size_;
|
|
196
|
+
|
|
197
|
+
// The size of this element.
|
|
198
|
+
std::uint64_t my_size_;
|
|
199
|
+
|
|
200
|
+
std::uint64_t my_position_;
|
|
201
|
+
|
|
202
|
+
std::uint64_t max_size_;
|
|
203
|
+
|
|
204
|
+
// The total number of bytes read by this parser.
|
|
205
|
+
std::uint64_t total_bytes_read_;
|
|
206
|
+
|
|
207
|
+
// Set to true if parsing has completed and this parser consumed an extra
|
|
208
|
+
// element header (ID and size) that wasn't from a child.
|
|
209
|
+
bool has_cached_metadata_ = false;
|
|
210
|
+
|
|
211
|
+
// Inserts the parser into the parsers_ map and asserts it is the only parser
|
|
212
|
+
// registers to parse the corresponding Id.
|
|
213
|
+
template <typename T>
|
|
214
|
+
void InsertParser(T&& parser) {
|
|
215
|
+
bool inserted = parsers_.insert(std::forward<T>(parser)).second;
|
|
216
|
+
(void)inserted; // Silence unused variable warning.
|
|
217
|
+
assert(inserted); // Make sure there aren't duplicates.
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Common initialization logic for Init/InitAfterseek.
|
|
221
|
+
void InitSetup(std::uint32_t header_size, std::uint64_t size_in_bytes,
|
|
222
|
+
std::uint64_t position);
|
|
223
|
+
|
|
224
|
+
// Resets the internal parsers in preparation for parsing the next child.
|
|
225
|
+
void PrepareForNextChild();
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
} // namespace webm
|
|
229
|
+
|
|
230
|
+
#endif // SRC_MASTER_PARSER_H_
|