Compare commits
212 Commits
libwebm-1.
...
libwebm-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82ac5fcdc8 | ||
|
|
852e1733a8 | ||
|
|
faf85c227d | ||
|
|
7c19266548 | ||
|
|
01fdee435c | ||
|
|
1ad314e297 | ||
|
|
476366249e | ||
|
|
267f71c76e | ||
|
|
f1a99d5f25 | ||
|
|
bff1aa512d | ||
|
|
a58c32339e | ||
|
|
714f3c4e4f | ||
|
|
cec98d4110 | ||
|
|
eb36ae4840 | ||
|
|
229f49347d | ||
|
|
287faf95f6 | ||
|
|
1a87b59032 | ||
|
|
d26ec6909d | ||
|
|
f2029be5f4 | ||
|
|
19f5694277 | ||
|
|
27a07c1fd1 | ||
|
|
d0313dd7ce | ||
|
|
b108695b9b | ||
|
|
4630f80f79 | ||
|
|
841a9b5fd9 | ||
|
|
8c4ca2ea04 | ||
|
|
49ae6f0dd9 | ||
|
|
0735bb5bdc | ||
|
|
93b24c4195 | ||
|
|
a57d6602b4 | ||
|
|
1c5bd949d0 | ||
|
|
7f77201dca | ||
|
|
795fd568b6 | ||
|
|
23bb18b76d | ||
|
|
7b57e37fde | ||
|
|
83a1f68944 | ||
|
|
507471457e | ||
|
|
b18110541a | ||
|
|
06b4337ed8 | ||
|
|
b366a98053 | ||
|
|
2857b2350c | ||
|
|
f1b2cfa03e | ||
|
|
ca8062959a | ||
|
|
6b4b297220 | ||
|
|
c0d2c9852b | ||
|
|
1a6dc4f210 | ||
|
|
275ac22cae | ||
|
|
064f2eed62 | ||
|
|
3778408b2a | ||
|
|
e86d046c07 | ||
|
|
f9885b5882 | ||
|
|
21ee398281 | ||
|
|
08fb6546e8 | ||
|
|
c8960955db | ||
|
|
680b4bfd3d | ||
|
|
5889e6c18b | ||
|
|
5135c4cd74 | ||
|
|
b0e4f32011 | ||
|
|
13ccc7f089 | ||
|
|
db3f9bbd79 | ||
|
|
8de3654fdb | ||
|
|
fa2aa7da2d | ||
|
|
d9bdadeff8 | ||
|
|
07a9cf7127 | ||
|
|
c56ee29254 | ||
|
|
d9013243ff | ||
|
|
7f7d898a27 | ||
|
|
42fe2cd755 | ||
|
|
8bccd9c306 | ||
|
|
7a2fa0daf3 | ||
|
|
44f5ce64b1 | ||
|
|
b521e3030e | ||
|
|
7680e2a76b | ||
|
|
39a315f8c1 | ||
|
|
f250aceeaa | ||
|
|
cd96a76985 | ||
|
|
8e8b3dbc6a | ||
|
|
82b7e5f487 | ||
|
|
04d7809375 | ||
|
|
986b64b8c0 | ||
|
|
2dec09426a | ||
|
|
b6de61a5c0 | ||
|
|
75a6d2da8b | ||
|
|
cec1f8521f | ||
|
|
8a61b4033e | ||
|
|
7affc5c3f8 | ||
|
|
d6d04acdcc | ||
|
|
4928b0bd5f | ||
|
|
c2e4a46244 | ||
|
|
e97f296855 | ||
|
|
d66ba4470a | ||
|
|
deb41c2ea1 | ||
|
|
42e5660e73 | ||
|
|
fe1e9bba6e | ||
|
|
2cb6a28b09 | ||
|
|
d04580fda5 | ||
|
|
c3550fdacf | ||
|
|
5dd0e40dbd | ||
|
|
8e96863b56 | ||
|
|
a9e4819e9f | ||
|
|
5a3be734f3 | ||
|
|
f99f3b20fb | ||
|
|
ff572b5399 | ||
|
|
b6311dc16f | ||
|
|
256cd02327 | ||
|
|
16c8e78265 | ||
|
|
c5e511c00a | ||
|
|
4baaa2c9a3 | ||
|
|
3d06eb1e2c | ||
|
|
d3849c2f7b | ||
|
|
f439e523b8 | ||
|
|
d3a44cd549 | ||
|
|
c6255af02a | ||
|
|
b5229c7bc8 | ||
|
|
e3616a6614 | ||
|
|
a4b68f825e | ||
|
|
bab0a002c5 | ||
|
|
feeb9b13ff | ||
|
|
b9a549b467 | ||
|
|
b386aa5c6b | ||
|
|
b0f8a81df9 | ||
|
|
f06e152abd | ||
|
|
27bb7476dd | ||
|
|
623d182613 | ||
|
|
1156da8d29 | ||
|
|
0d4cb404ea | ||
|
|
e12fff0ebb | ||
|
|
a321704b4c | ||
|
|
574045edd4 | ||
|
|
8be63972fd | ||
|
|
8f2d1b3cde | ||
|
|
1c36c24694 | ||
|
|
568504e64e | ||
|
|
acf788bedd | ||
|
|
418188b03e | ||
|
|
07688c92d7 | ||
|
|
2a63e473d8 | ||
|
|
d13c017744 | ||
|
|
249629d46c | ||
|
|
7f3cda494a | ||
|
|
5c0617852f | ||
|
|
4df111e60a | ||
|
|
7b2450131c | ||
|
|
c6767b94fd | ||
|
|
9097a0691b | ||
|
|
eddf9744cb | ||
|
|
def325c010 | ||
|
|
41f869cb0c | ||
|
|
fd0be37ba4 | ||
|
|
207d8a193a | ||
|
|
02429eb11b | ||
|
|
0cf7b1b7d3 | ||
|
|
2e80fedf8c | ||
|
|
3402e12d1a | ||
|
|
1a685db45b | ||
|
|
6634c7f87a | ||
|
|
7566004462 | ||
|
|
9915b8408e | ||
|
|
743725477c | ||
|
|
0d5a98cee5 | ||
|
|
e3485c9b9f | ||
|
|
46cc823994 | ||
|
|
5218bd291c | ||
|
|
1a0130d069 | ||
|
|
867f1894da | ||
|
|
4c7bec5743 | ||
|
|
9ead078aaf | ||
|
|
fb6b6e6444 | ||
|
|
ce775929a6 | ||
|
|
0a24fe44ae | ||
|
|
11d5b66eb4 | ||
|
|
a1a3b14538 | ||
|
|
0fcec38045 | ||
|
|
a7118d8ec5 | ||
|
|
abe9c2d0d1 | ||
|
|
630a0e3c33 | ||
|
|
e369bed319 | ||
|
|
a9d94ef2c5 | ||
|
|
3b66306126 | ||
|
|
acb7a2c8bc | ||
|
|
99f40649a7 | ||
|
|
c6634bca44 | ||
|
|
17cf7cc519 | ||
|
|
7f79df14a8 | ||
|
|
23cdb09fd2 | ||
|
|
8ae2137637 | ||
|
|
7952ce8f78 | ||
|
|
d58f55542f | ||
|
|
a0c85b1e46 | ||
|
|
4600f5b4a2 | ||
|
|
a142b15ada | ||
|
|
4a3f5c9f99 | ||
|
|
84f2156ca1 | ||
|
|
5440f20071 | ||
|
|
5c14a3f035 | ||
|
|
71a097fb12 | ||
|
|
cd6f7bff4b | ||
|
|
327e8ab617 | ||
|
|
796c90798a | ||
|
|
0f7815b036 | ||
|
|
ccb7fa9c73 | ||
|
|
4ec1e5cae5 | ||
|
|
849093f84f | ||
|
|
32e1556e68 | ||
|
|
5efd6e3c1d | ||
|
|
a6c71c1407 | ||
|
|
81c1d8415c | ||
|
|
d2f7478148 | ||
|
|
fd0a65af98 | ||
|
|
872cc57de4 | ||
|
|
ddfea3431f | ||
|
|
4134f6e04e |
53
.clang-format
Normal file
53
.clang-format
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
# BasedOnStyle: Google
|
||||||
|
AccessModifierOffset: -1
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
AlignEscapedNewlinesLeft: true
|
||||||
|
AlignTrailingComments: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: true
|
||||||
|
AlwaysBreakTemplateDeclarations: true
|
||||||
|
AlwaysBreakBeforeMultilineStrings: true
|
||||||
|
BreakBeforeBinaryOperators: false
|
||||||
|
BreakBeforeTernaryOperators: false
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BinPackParameters: true
|
||||||
|
ColumnLimit: 80
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
DerivePointerBinding: true
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
IndentCaseLabels: true
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: false
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 1
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 200
|
||||||
|
PointerBindsToType: true
|
||||||
|
SpacesBeforeTrailingComments: 2
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
Standard: Auto
|
||||||
|
IndentWidth: 2
|
||||||
|
TabWidth: 8
|
||||||
|
UseTab: Never
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
IndentFunctionDeclarationAfterType: true
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInContainerLiterals: true
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
...
|
||||||
|
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -19,5 +19,9 @@ Release
|
|||||||
ipch
|
ipch
|
||||||
dumpvtt
|
dumpvtt
|
||||||
sample
|
sample
|
||||||
samplemuxer
|
sample_muxer
|
||||||
vttdemux
|
vttdemux
|
||||||
|
Makefile
|
||||||
|
CMakeFiles
|
||||||
|
CMakeCache.txt
|
||||||
|
*.cmake
|
||||||
|
|||||||
64
CMakeLists.txt
Normal file
64
CMakeLists.txt
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
## Copyright (c) 2015 The WebM project authors. All Rights Reserved.
|
||||||
|
##
|
||||||
|
## Use of this source code is governed by a BSD-style license
|
||||||
|
## that can be found in the LICENSE file in the root of the source
|
||||||
|
## tree. An additional intellectual property rights grant can be found
|
||||||
|
## in the file PATENTS. All contributing project authors may
|
||||||
|
## be found in the AUTHORS file in the root of the source tree.
|
||||||
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
project(LIBWEBM)
|
||||||
|
include("${CMAKE_CURRENT_SOURCE_DIR}/build/msvc_runtime.cmake")
|
||||||
|
|
||||||
|
set(LIBWEBM_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
|
||||||
|
# Libwebm section.
|
||||||
|
add_library(webm STATIC
|
||||||
|
"${LIBWEBM_SRC_DIR}/mkvmuxer.cpp"
|
||||||
|
"${LIBWEBM_SRC_DIR}/mkvmuxer.hpp"
|
||||||
|
"${LIBWEBM_SRC_DIR}/mkvmuxertypes.hpp"
|
||||||
|
"${LIBWEBM_SRC_DIR}/mkvmuxerutil.cpp"
|
||||||
|
"${LIBWEBM_SRC_DIR}/mkvmuxerutil.hpp"
|
||||||
|
"${LIBWEBM_SRC_DIR}/mkvparser.cpp"
|
||||||
|
"${LIBWEBM_SRC_DIR}/mkvparser.hpp"
|
||||||
|
"${LIBWEBM_SRC_DIR}/mkvreader.cpp"
|
||||||
|
"${LIBWEBM_SRC_DIR}/mkvreader.hpp"
|
||||||
|
"${LIBWEBM_SRC_DIR}/mkvwriter.cpp"
|
||||||
|
"${LIBWEBM_SRC_DIR}/mkvwriter.hpp"
|
||||||
|
"${LIBWEBM_SRC_DIR}/webmids.hpp")
|
||||||
|
if(WIN32)
|
||||||
|
# Use libwebm and libwebm.lib for project and library name on Windows (instead
|
||||||
|
# webm and webm.lib).
|
||||||
|
set_target_properties(webm PROPERTIES PROJECT_LABEL libwebm)
|
||||||
|
set_target_properties(webm PROPERTIES PREFIX lib)
|
||||||
|
endif(WIN32)
|
||||||
|
|
||||||
|
include_directories("${LIBWEBM_SRC_DIR}")
|
||||||
|
|
||||||
|
# Sample section.
|
||||||
|
add_executable(sample
|
||||||
|
"${LIBWEBM_SRC_DIR}/sample.cpp")
|
||||||
|
target_link_libraries(sample LINK_PUBLIC webm)
|
||||||
|
|
||||||
|
# Sample muxer section.
|
||||||
|
add_executable(sample_muxer
|
||||||
|
"${LIBWEBM_SRC_DIR}/sample_muxer.cpp"
|
||||||
|
"${LIBWEBM_SRC_DIR}/sample_muxer_metadata.cc"
|
||||||
|
"${LIBWEBM_SRC_DIR}/sample_muxer_metadata.h"
|
||||||
|
"${LIBWEBM_SRC_DIR}/vttreader.cc"
|
||||||
|
"${LIBWEBM_SRC_DIR}/vttreader.h"
|
||||||
|
"${LIBWEBM_SRC_DIR}/webvttparser.cc"
|
||||||
|
"${LIBWEBM_SRC_DIR}/webvttparser.h")
|
||||||
|
target_link_libraries(sample_muxer LINK_PUBLIC webm)
|
||||||
|
|
||||||
|
# Vttdemux section.
|
||||||
|
add_executable(vttdemux
|
||||||
|
"${LIBWEBM_SRC_DIR}/vttdemux.cc"
|
||||||
|
"${LIBWEBM_SRC_DIR}/webvttparser.cc"
|
||||||
|
"${LIBWEBM_SRC_DIR}/webvttparser.h")
|
||||||
|
target_link_libraries(vttdemux LINK_PUBLIC webm)
|
||||||
|
|
||||||
|
# webm2pes section.
|
||||||
|
add_executable(webm2pes
|
||||||
|
"${LIBWEBM_SRC_DIR}/webm2pes.cc"
|
||||||
|
"${LIBWEBM_SRC_DIR}/webm2pes.h")
|
||||||
|
target_link_libraries(webm2pes LINK_PUBLIC webm)
|
||||||
@@ -12,14 +12,14 @@ OBJECTS4 := vttdemux.o webvttparser.o
|
|||||||
INCLUDES := -I.
|
INCLUDES := -I.
|
||||||
DEPS := $(WEBMOBJS:.o=.d) $(OBJECTS1:.o=.d) $(OBJECTS2:.o=.d)
|
DEPS := $(WEBMOBJS:.o=.d) $(OBJECTS1:.o=.d) $(OBJECTS2:.o=.d)
|
||||||
DEPS += $(OBJECTS3:.o=.d) $(OBJECTS4:.o=.d)
|
DEPS += $(OBJECTS3:.o=.d) $(OBJECTS4:.o=.d)
|
||||||
EXES := samplemuxer sample dumpvtt vttdemux
|
EXES := sample_muxer sample dumpvtt vttdemux
|
||||||
|
|
||||||
all: $(EXES)
|
all: $(EXES)
|
||||||
|
|
||||||
sample: sample.o $(LIBWEBMA)
|
sample: sample.o $(LIBWEBMA)
|
||||||
$(CXX) $^ -o $@
|
$(CXX) $^ -o $@
|
||||||
|
|
||||||
samplemuxer: $(OBJECTS2) $(LIBWEBMA)
|
sample_muxer: $(OBJECTS2) $(LIBWEBMA)
|
||||||
$(CXX) $^ -o $@
|
$(CXX) $^ -o $@
|
||||||
|
|
||||||
dumpvtt: $(OBJECTS3)
|
dumpvtt: $(OBJECTS3)
|
||||||
39
PATENTS.TXT
39
PATENTS.TXT
@@ -1,22 +1,23 @@
|
|||||||
Additional IP Rights Grant (Patents)
|
Additional IP Rights Grant (Patents)
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
"This implementation" means the copyrightable works distributed by
|
"These implementations" means the copyrightable works that implement the WebM
|
||||||
Google as part of the WebM Project.
|
codecs distributed by Google as part of the WebM Project.
|
||||||
|
|
||||||
Google hereby grants to you a perpetual, worldwide, non-exclusive,
|
Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge,
|
||||||
no-charge, royalty-free, irrevocable (except as stated in this section)
|
royalty-free, irrevocable (except as stated in this section) patent license to
|
||||||
patent license to make, have made, use, offer to sell, sell, import,
|
make, have made, use, offer to sell, sell, import, transfer, and otherwise
|
||||||
transfer, and otherwise run, modify and propagate the contents of this
|
run, modify and propagate the contents of these implementations of WebM, where
|
||||||
implementation of VP8, where such license applies only to those patent
|
such license applies only to those patent claims, both currently owned by
|
||||||
claims, both currently owned by Google and acquired in the future,
|
Google and acquired in the future, licensable by Google that are necessarily
|
||||||
licensable by Google that are necessarily infringed by this
|
infringed by these implementations of WebM. This grant does not include claims
|
||||||
implementation of VP8. This grant does not include claims that would be
|
that would be infringed only as a consequence of further modification of these
|
||||||
infringed only as a consequence of further modification of this
|
implementations. If you or your agent or exclusive licensee institute or order
|
||||||
implementation. If you or your agent or exclusive licensee institute or
|
or agree to the institution of patent litigation or any other patent
|
||||||
order or agree to the institution of patent litigation against any
|
enforcement activity against any entity (including a cross-claim or
|
||||||
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
counterclaim in a lawsuit) alleging that any of these implementations of WebM
|
||||||
that this implementation of VP8 or any code incorporated within this
|
or any code incorporated within any of these implementations of WebM
|
||||||
implementation of VP8 constitutes direct or contributory patent
|
constitute direct or contributory patent infringement, or inducement of
|
||||||
infringement, or inducement of patent infringement, then any patent
|
patent infringement, then any patent rights granted to you under this License
|
||||||
rights granted to you under this License for this implementation of VP8
|
for these implementations of WebM shall terminate as of the date such
|
||||||
shall terminate as of the date such litigation is filed.
|
litigation is filed.
|
||||||
|
|||||||
57
README.libwebm
Normal file
57
README.libwebm
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
Building Libwebm
|
||||||
|
|
||||||
|
To build libwebm you must first create project files. To do this run cmake
|
||||||
|
and pass it the path to your libwebm repo.
|
||||||
|
|
||||||
|
Makefile.unix can be used as a fallback on systems that cmake does not
|
||||||
|
support.
|
||||||
|
|
||||||
|
|
||||||
|
CMake Basics
|
||||||
|
|
||||||
|
To generate project/make files for the default toolchain on your system simply
|
||||||
|
run cmake with the path to the libwebm repo:
|
||||||
|
|
||||||
|
$ cmake path/to/libwebm
|
||||||
|
|
||||||
|
On Windows the above command will produce Visual Studio project files for the
|
||||||
|
newest Visual Studio detected on the system. On Mac OS X and Linux systems, the
|
||||||
|
above command will produce a makefile.
|
||||||
|
|
||||||
|
To control what types of projects are generated the -G parameter is added to
|
||||||
|
the cmake command line. This argument must be followed by the name of a
|
||||||
|
generator. Running cmake with the --help argument will list the available
|
||||||
|
generators for your system.
|
||||||
|
|
||||||
|
On Mac OS X you would run the following command to generate Xcode projects:
|
||||||
|
|
||||||
|
$ cmake path/to/libwebm -G Xcode
|
||||||
|
|
||||||
|
On a Windows box you would run the following command to generate Visual Studio
|
||||||
|
2013 projects:
|
||||||
|
|
||||||
|
$ cmake path/to/libwebm -G "Visual Studio 12"
|
||||||
|
|
||||||
|
To generate 64-bit Windows Visual Studio 2013 projects:
|
||||||
|
|
||||||
|
$ cmake path/to/libwebm "Visual Studio 12 Win64"
|
||||||
|
|
||||||
|
|
||||||
|
CMake Makefiles: Debugging and Optimization
|
||||||
|
|
||||||
|
Unlike Visual Studio and Xcode projects, the build configuration for make builds
|
||||||
|
is controlled when you run cmake. The following examples demonstrate various
|
||||||
|
build configurations.
|
||||||
|
|
||||||
|
Omitting the build type produces makefiles that use build flags containing
|
||||||
|
neither optimization nor debug flags:
|
||||||
|
$ cmake path/to/libwebm
|
||||||
|
|
||||||
|
A makefile using release (optimized) flags is produced like this:
|
||||||
|
$ cmake path/to/libwebm -DCMAKE_BUILD_TYPE=release
|
||||||
|
|
||||||
|
A release build with debug info can be produced as well:
|
||||||
|
$ cmake path/to/libwebm -DCMAKE_BUILD_TYPE=relwithdebinfo
|
||||||
|
|
||||||
|
And your standard debug build will be produced using:
|
||||||
|
$ cmake path/to/libwebm -DCMAKE_BUILD_TYPE=debug
|
||||||
34
RELEASE.TXT
34
RELEASE.TXT
@@ -1,34 +0,0 @@
|
|||||||
1.0.0.5
|
|
||||||
* Handled case when no duration
|
|
||||||
* Handled empty clusters
|
|
||||||
* Handled empty clusters when seeking
|
|
||||||
* Implemented check lacing bits
|
|
||||||
|
|
||||||
1.0.0.4
|
|
||||||
* Made Cues member variables mutables
|
|
||||||
* Defined against badly-formatted cue points
|
|
||||||
* Segment::GetCluster returns CuePoint too
|
|
||||||
* Separated cue-based searches
|
|
||||||
|
|
||||||
1.0.0.3
|
|
||||||
* Added Block::GetOffset() to get a frame's offset in a block
|
|
||||||
* Changed cluster count type from size_t to long
|
|
||||||
* Parsed SeekHead to find cues
|
|
||||||
* Allowed seeking beyond end of cluster cache
|
|
||||||
* Added not to attempt to reparse cues element
|
|
||||||
* Restructured Segment::LoadCluster
|
|
||||||
* Marked position of cues without parsing cues element
|
|
||||||
* Allowed cue points to be loaded incrementally
|
|
||||||
* Implemented to load lazily cue points as they're searched
|
|
||||||
* Merged Cues::LoadCuePoint into Cues::Find
|
|
||||||
* Lazy init cues
|
|
||||||
* Loaded cue point during find
|
|
||||||
|
|
||||||
1.0.0.2
|
|
||||||
* added support for Cues element
|
|
||||||
* seeking was improved
|
|
||||||
|
|
||||||
1.0.0.1
|
|
||||||
* fixed item 141
|
|
||||||
* added item 142
|
|
||||||
* added this file, RELEASE.TXT, to repository
|
|
||||||
24
build/msvc_runtime.cmake
Normal file
24
build/msvc_runtime.cmake
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
## Copyright (c) 2015 The WebM project authors. All Rights Reserved.
|
||||||
|
##
|
||||||
|
## Use of this source code is governed by a BSD-style license
|
||||||
|
## that can be found in the LICENSE file in the root of the source
|
||||||
|
## tree. An additional intellectual property rights grant can be found
|
||||||
|
## in the file PATENTS. All contributing project authors may
|
||||||
|
## be found in the AUTHORS file in the root of the source tree.
|
||||||
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
# CMake defaults to producing code linked to the DLL MSVC runtime. In libwebm
|
||||||
|
# static is typically desired. Force static code generation unless the user
|
||||||
|
# running CMake set MSVC_RUNTIME to dll.
|
||||||
|
if(NOT "${MSVC_RUNTIME}" STREQUAL "dll")
|
||||||
|
foreach(flag_var
|
||||||
|
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
||||||
|
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
||||||
|
if(${flag_var} MATCHES "/MD")
|
||||||
|
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
|
||||||
|
endif(${flag_var} MATCHES "/MD")
|
||||||
|
endforeach(flag_var)
|
||||||
|
endif(NOT "${MSVC_RUNTIME}" STREQUAL "dll")
|
||||||
|
endif(WIN32)
|
||||||
|
|
||||||
62
common/common.sh
Normal file
62
common/common.sh
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
##
|
||||||
|
## Copyright (c) 2015 The WebM project authors. All Rights Reserved.
|
||||||
|
##
|
||||||
|
## Use of this source code is governed by a BSD-style license
|
||||||
|
## that can be found in the LICENSE file in the root of the source
|
||||||
|
## tree. An additional intellectual property rights grant can be found
|
||||||
|
## in the file PATENTS. All contributing project authors may
|
||||||
|
## be found in the AUTHORS file in the root of the source tree.
|
||||||
|
##
|
||||||
|
set -e
|
||||||
|
devnull='> /dev/null 2>&1'
|
||||||
|
|
||||||
|
readonly ORIG_PWD="$(pwd)"
|
||||||
|
|
||||||
|
elog() {
|
||||||
|
echo "${0##*/} failed because: $@" 1>&2
|
||||||
|
}
|
||||||
|
|
||||||
|
vlog() {
|
||||||
|
if [ "${VERBOSE}" = "yes" ]; then
|
||||||
|
echo "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Terminates script when name of current directory does not match $1.
|
||||||
|
check_dir() {
|
||||||
|
current_dir="$(pwd)"
|
||||||
|
required_dir="$1"
|
||||||
|
if [ "${current_dir##*/}" != "${required_dir}" ]; then
|
||||||
|
elog "This script must be run from the ${required_dir} directory."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Terminates the script when $1 is not in $PATH. Any arguments required for
|
||||||
|
# the tool being tested to return a successful exit code can be passed as
|
||||||
|
# additional arguments.
|
||||||
|
check_tool() {
|
||||||
|
tool="$1"
|
||||||
|
shift
|
||||||
|
tool_args="$@"
|
||||||
|
if ! eval "${tool}" ${tool_args} > /dev/null 2>&1; then
|
||||||
|
elog "${tool} must be in your path."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Echoes git describe output for the directory specified by $1 to stdout.
|
||||||
|
git_describe() {
|
||||||
|
git_dir="$1"
|
||||||
|
check_git
|
||||||
|
echo $(git -C "${git_dir}" describe)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Echoes current git revision for the directory specifed by $1 to stdout.
|
||||||
|
git_revision() {
|
||||||
|
git_dir="$1"
|
||||||
|
check_git
|
||||||
|
echo $(git -C "${git_dir}" rev-parse HEAD)
|
||||||
|
}
|
||||||
|
|
||||||
17
dumpvtt.cc
17
dumpvtt.cc
@@ -48,18 +48,12 @@ int main(int argc, const char* argv[]) {
|
|||||||
fprintf(stdout, "cue identifier: \"%s\"\n", cue.identifier.c_str());
|
fprintf(stdout, "cue identifier: \"%s\"\n", cue.identifier.c_str());
|
||||||
|
|
||||||
const libwebvtt::Time& st = cue.start_time;
|
const libwebvtt::Time& st = cue.start_time;
|
||||||
fprintf(stdout, "cue start time: \"HH=%i MM=%i SS=%i SSS=%i\"\n",
|
fprintf(stdout, "cue start time: \"HH=%i MM=%i SS=%i SSS=%i\"\n", st.hours,
|
||||||
st.hours,
|
st.minutes, st.seconds, st.milliseconds);
|
||||||
st.minutes,
|
|
||||||
st.seconds,
|
|
||||||
st.milliseconds);
|
|
||||||
|
|
||||||
const libwebvtt::Time& sp = cue.stop_time;
|
const libwebvtt::Time& sp = cue.stop_time;
|
||||||
fprintf(stdout, "cue stop time: \"HH=%i MM=%i SS=%i SSS=%i\"\n",
|
fprintf(stdout, "cue stop time: \"HH=%i MM=%i SS=%i SSS=%i\"\n", sp.hours,
|
||||||
sp.hours,
|
sp.minutes, sp.seconds, sp.milliseconds);
|
||||||
sp.minutes,
|
|
||||||
sp.seconds,
|
|
||||||
sp.milliseconds);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
typedef libwebvtt::Cue::settings_t::const_iterator iter_t;
|
typedef libwebvtt::Cue::settings_t::const_iterator iter_t;
|
||||||
@@ -72,8 +66,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
while (i != j) {
|
while (i != j) {
|
||||||
const libwebvtt::Setting& setting = *i++;
|
const libwebvtt::Setting& setting = *i++;
|
||||||
fprintf(stdout, "cue setting: name=%s value=%s\n",
|
fprintf(stdout, "cue setting: name=%s value=%s\n",
|
||||||
setting.name.c_str(),
|
setting.name.c_str(), setting.value.c_str());
|
||||||
setting.value.c_str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
193
iosbuild.sh
Executable file
193
iosbuild.sh
Executable file
@@ -0,0 +1,193 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
##
|
||||||
|
## Copyright (c) 2015 The WebM project authors. All Rights Reserved.
|
||||||
|
##
|
||||||
|
## Use of this source code is governed by a BSD-style license
|
||||||
|
## that can be found in the LICENSE file in the root of the source
|
||||||
|
## tree. An additional intellectual property rights grant can be found
|
||||||
|
## in the file PATENTS. All contributing project authors may
|
||||||
|
## be found in the AUTHORS file in the root of the source tree.
|
||||||
|
##
|
||||||
|
## This script generates 'WebM.framework'. An iOS app can mux/demux WebM
|
||||||
|
## container files by including 'WebM.framework'.
|
||||||
|
##
|
||||||
|
## Run ./iosbuild.sh to generate 'WebM.framework'. By default the framework
|
||||||
|
## bundle will be created in a directory called framework. Use --out-dir to
|
||||||
|
## change the output directory.
|
||||||
|
##
|
||||||
|
## This script is based on iosbuild.sh from the libwebp project.
|
||||||
|
. $(dirname $0)/common/common.sh
|
||||||
|
|
||||||
|
# Trap function. Cleans up build output.
|
||||||
|
cleanup() {
|
||||||
|
local readonly res=$?
|
||||||
|
cd "${ORIG_PWD}"
|
||||||
|
|
||||||
|
for dir in ${LIBDIRS}; do
|
||||||
|
if [ -d "${dir}" ]; then
|
||||||
|
rm -rf "${dir}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $res -ne 0 ]; then
|
||||||
|
elog "build exited with error ($res)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
check_dir libwebm
|
||||||
|
|
||||||
|
iosbuild_usage() {
|
||||||
|
cat << EOF
|
||||||
|
Usage: ${0##*/} [arguments]
|
||||||
|
--help: Display this message and exit.
|
||||||
|
--out-dir: Override output directory (default is ${OUTDIR}).
|
||||||
|
--show-build-output: Show output from each library build.
|
||||||
|
--verbose: Output information about the environment and each stage of the
|
||||||
|
build.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# Extract the latest SDK version from the final field of the form: iphoneosX.Y
|
||||||
|
readonly SDK=$(xcodebuild -showsdks \
|
||||||
|
| grep iphoneos | sort | tail -n 1 | awk '{print substr($NF, 9)}'
|
||||||
|
)
|
||||||
|
|
||||||
|
# Extract Xcode version.
|
||||||
|
readonly XCODE=$(xcodebuild -version | grep Xcode | cut -d " " -f2)
|
||||||
|
if [ -z "${XCODE}" ]; then
|
||||||
|
echo "Xcode not available"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Add iPhoneOS-V6 to the list of platforms below if you need armv6 support.
|
||||||
|
# Note that iPhoneOS-V6 support is not available with the iOS6 SDK.
|
||||||
|
readonly INCLUDES="mkvmuxer.hpp
|
||||||
|
mkvmuxertypes.hpp
|
||||||
|
mkvmuxerutil.hpp
|
||||||
|
mkvparser.hpp
|
||||||
|
mkvreader.hpp
|
||||||
|
mkvwriter.hpp
|
||||||
|
webmids.hpp"
|
||||||
|
readonly PLATFORMS="iPhoneSimulator
|
||||||
|
iPhoneSimulator64
|
||||||
|
iPhoneOS-V7
|
||||||
|
iPhoneOS-V7s
|
||||||
|
iPhoneOS-V7-arm64"
|
||||||
|
readonly TARGETDIR="WebM.framework"
|
||||||
|
readonly DEVELOPER="$(xcode-select --print-path)"
|
||||||
|
readonly PLATFORMSROOT="${DEVELOPER}/Platforms"
|
||||||
|
readonly LIPO="$(xcrun -sdk iphoneos${SDK} -find lipo)"
|
||||||
|
LIBLIST=""
|
||||||
|
OPT_FLAGS="-DNDEBUG -O3"
|
||||||
|
readonly SDK_MAJOR_VERSION="$(echo ${SDK} | awk -F '.' '{ print $1 }')"
|
||||||
|
|
||||||
|
if [ -z "${SDK_MAJOR_VERSION}" ]; then
|
||||||
|
elog "iOS SDK not available"
|
||||||
|
exit 1
|
||||||
|
elif [ "${SDK_MAJOR_VERSION}" -lt "6" ]; then
|
||||||
|
elog "You need iOS SDK version 6 or above"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
vlog "iOS SDK Version ${SDK}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Parse the command line.
|
||||||
|
while [ -n "$1" ]; do
|
||||||
|
case "$1" in
|
||||||
|
--help)
|
||||||
|
iosbuild_usage
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
--out-dir)
|
||||||
|
OUTDIR="$2"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--enable-debug)
|
||||||
|
OPT_FLAGS="-g"
|
||||||
|
;;
|
||||||
|
--show-build-output)
|
||||||
|
devnull=
|
||||||
|
;;
|
||||||
|
--verbose)
|
||||||
|
VERBOSE=yes
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
iosbuild_usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
readonly OPT_FLAGS="${OPT_FLAGS}"
|
||||||
|
readonly OUTDIR="${OUTDIR:-framework}"
|
||||||
|
|
||||||
|
if [ "${VERBOSE}" = "yes" ]; then
|
||||||
|
cat << EOF
|
||||||
|
OUTDIR=${OUTDIR}
|
||||||
|
INCLUDES=${INCLUDES}
|
||||||
|
PLATFORMS=${PLATFORMS}
|
||||||
|
TARGETDIR=${TARGETDIR}
|
||||||
|
DEVELOPER=${DEVELOPER}
|
||||||
|
LIPO=${LIPO}
|
||||||
|
OPT_FLAGS=${OPT_FLAGS}
|
||||||
|
ORIG_PWD=${ORIG_PWD}
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf "${OUTDIR}/${TARGETDIR}"
|
||||||
|
mkdir -p "${OUTDIR}/${TARGETDIR}/Headers/"
|
||||||
|
|
||||||
|
for PLATFORM in ${PLATFORMS}; do
|
||||||
|
ARCH2=""
|
||||||
|
if [ "${PLATFORM}" = "iPhoneOS-V7-arm64" ]; then
|
||||||
|
PLATFORM="iPhoneOS"
|
||||||
|
ARCH="aarch64"
|
||||||
|
ARCH2="arm64"
|
||||||
|
elif [ "${PLATFORM}" = "iPhoneOS-V7s" ]; then
|
||||||
|
PLATFORM="iPhoneOS"
|
||||||
|
ARCH="armv7s"
|
||||||
|
elif [ "${PLATFORM}" = "iPhoneOS-V7" ]; then
|
||||||
|
PLATFORM="iPhoneOS"
|
||||||
|
ARCH="armv7"
|
||||||
|
elif [ "${PLATFORM}" = "iPhoneOS-V6" ]; then
|
||||||
|
PLATFORM="iPhoneOS"
|
||||||
|
ARCH="armv6"
|
||||||
|
elif [ "${PLATFORM}" = "iPhoneSimulator64" ]; then
|
||||||
|
PLATFORM="iPhoneSimulator"
|
||||||
|
ARCH="x86_64"
|
||||||
|
else
|
||||||
|
ARCH="i386"
|
||||||
|
fi
|
||||||
|
|
||||||
|
LIBDIR="${OUTDIR}/${PLATFORM}-${SDK}-${ARCH}"
|
||||||
|
LIBDIRS="${LIBDIRS} ${LIBDIR}"
|
||||||
|
LIBFILE="${LIBDIR}/libwebm.a"
|
||||||
|
eval mkdir -p "${LIBDIR}" ${devnull}
|
||||||
|
|
||||||
|
DEVROOT="${DEVELOPER}/Toolchains/XcodeDefault.xctoolchain"
|
||||||
|
SDKROOT="${PLATFORMSROOT}/"
|
||||||
|
SDKROOT="${SDKROOT}${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDK}.sdk/"
|
||||||
|
CXXFLAGS="-arch ${ARCH2:-${ARCH}} -isysroot ${SDKROOT} ${OPT_FLAGS}
|
||||||
|
-miphoneos-version-min=6.0"
|
||||||
|
|
||||||
|
# Build using the legacy makefile (instead of generating via cmake).
|
||||||
|
eval make -f Makefile.unix libwebm.a CXXFLAGS=\"${CXXFLAGS}\" ${devnull}
|
||||||
|
|
||||||
|
# copy lib and add it to LIBLIST.
|
||||||
|
eval cp libwebm.a "${LIBFILE}" ${devnull}
|
||||||
|
LIBLIST="${LIBLIST} ${LIBFILE}"
|
||||||
|
|
||||||
|
# clean build so we can go again.
|
||||||
|
eval make -f Makefile.unix clean ${devnull}
|
||||||
|
done
|
||||||
|
|
||||||
|
for include_file in ${INCLUDES}; do
|
||||||
|
eval cp -p ${include_file} "${OUTDIR}/${TARGETDIR}/Headers/" ${devnull}
|
||||||
|
done
|
||||||
|
|
||||||
|
eval ${LIPO} -create ${LIBLIST} -output "${OUTDIR}/${TARGETDIR}/WebM" ${devnull}
|
||||||
|
echo "Succesfully built ${TARGETDIR} in ${OUTDIR}."
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
|
||||||
# Visual Studio 2008
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample", "sample_2008.vcproj", "{0CB5681F-6065-490C-98C8-05531732ED7E}"
|
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
|
||||||
{7B1F12CA-0724-430B-B61A-1D357C912CBA} = {7B1F12CA-0724-430B-B61A-1D357C912CBA}
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwebm", "libwebm_2008.vcproj", "{7B1F12CA-0724-430B-B61A-1D357C912CBA}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_muxer", "sample_muxer_2008.vcproj", "{B407561F-1F5E-4798-B9C2-81AB09CFBC16}"
|
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
|
||||||
{7B1F12CA-0724-430B-B61A-1D357C912CBA} = {7B1F12CA-0724-430B-B61A-1D357C912CBA}
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Win32 = Debug|Win32
|
|
||||||
Release|Win32 = Release|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{0CB5681F-6065-490C-98C8-05531732ED7E}.Debug|Win32.ActiveCfg = Debug|Win32
|
|
||||||
{0CB5681F-6065-490C-98C8-05531732ED7E}.Debug|Win32.Build.0 = Debug|Win32
|
|
||||||
{0CB5681F-6065-490C-98C8-05531732ED7E}.Release|Win32.ActiveCfg = Release|Win32
|
|
||||||
{0CB5681F-6065-490C-98C8-05531732ED7E}.Release|Win32.Build.0 = Release|Win32
|
|
||||||
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Debug|Win32.ActiveCfg = Debug|Win32
|
|
||||||
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Debug|Win32.Build.0 = Debug|Win32
|
|
||||||
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Release|Win32.ActiveCfg = Release|Win32
|
|
||||||
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Release|Win32.Build.0 = Release|Win32
|
|
||||||
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Debug|Win32.ActiveCfg = Debug|Win32
|
|
||||||
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Debug|Win32.Build.0 = Debug|Win32
|
|
||||||
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Release|Win32.ActiveCfg = Release|Win32
|
|
||||||
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Release|Win32.Build.0 = Release|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
@@ -1,210 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="Windows-1252"?>
|
|
||||||
<VisualStudioProject
|
|
||||||
ProjectType="Visual C++"
|
|
||||||
Version="9.00"
|
|
||||||
Name="libwebm"
|
|
||||||
ProjectGUID="{7B1F12CA-0724-430B-B61A-1D357C912CBA}"
|
|
||||||
RootNamespace="libwebm"
|
|
||||||
Keyword="Win32Proj"
|
|
||||||
TargetFrameworkVersion="196613"
|
|
||||||
>
|
|
||||||
<Platforms>
|
|
||||||
<Platform
|
|
||||||
Name="Win32"
|
|
||||||
/>
|
|
||||||
</Platforms>
|
|
||||||
<ToolFiles>
|
|
||||||
</ToolFiles>
|
|
||||||
<Configurations>
|
|
||||||
<Configuration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
OutputDirectory="$(ProjectDir)..\lib\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ProjectDir)..\obj\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
|
|
||||||
ConfigurationType="4"
|
|
||||||
CharacterSet="1"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
Optimization="0"
|
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
|
|
||||||
MinimalRebuild="false"
|
|
||||||
BasicRuntimeChecks="3"
|
|
||||||
RuntimeLibrary="1"
|
|
||||||
UsePrecompiledHeader="0"
|
|
||||||
WarningLevel="4"
|
|
||||||
DebugInformationFormat="1"
|
|
||||||
DisableSpecificWarnings="4996"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLibrarianTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCALinkTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXDCMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCBscMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCFxCopTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"
|
|
||||||
/>
|
|
||||||
</Configuration>
|
|
||||||
<Configuration
|
|
||||||
Name="Release|Win32"
|
|
||||||
OutputDirectory="$(ProjectDir)..\lib\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ProjectDir)..\obj\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
|
|
||||||
ConfigurationType="4"
|
|
||||||
CharacterSet="1"
|
|
||||||
WholeProgramOptimization="1"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
Optimization="2"
|
|
||||||
EnableIntrinsicFunctions="true"
|
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
|
|
||||||
RuntimeLibrary="0"
|
|
||||||
EnableFunctionLevelLinking="true"
|
|
||||||
UsePrecompiledHeader="0"
|
|
||||||
WarningLevel="4"
|
|
||||||
DebugInformationFormat="1"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLibrarianTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCALinkTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXDCMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCBscMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCFxCopTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"
|
|
||||||
/>
|
|
||||||
</Configuration>
|
|
||||||
</Configurations>
|
|
||||||
<References>
|
|
||||||
</References>
|
|
||||||
<Files>
|
|
||||||
<Filter
|
|
||||||
Name="Source Files"
|
|
||||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
|
||||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
|
||||||
>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mkvmuxer.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mkvmuxerutil.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mkvparser.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mkvreader.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mkvwriter.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
<Filter
|
|
||||||
Name="Header Files"
|
|
||||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
|
||||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
|
||||||
>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mkvmuxer.hpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mkvmuxertypes.hpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mkvmuxerutil.hpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mkvparser.hpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mkvreader.hpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mkvwriter.hpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\webmids.hpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
</Files>
|
|
||||||
<Globals>
|
|
||||||
</Globals>
|
|
||||||
</VisualStudioProject>
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
|
||||||
# Visual Studio 2010
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample", "sample_2010.vcxproj", "{0CB5681F-6065-490C-98C8-05531732ED7E}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwebm", "libwebm_2010.vcxproj", "{7B1F12CA-0724-430B-B61A-1D357C912CBA}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_muxer", "sample_muxer_2010.vcxproj", "{B407561F-1F5E-4798-B9C2-81AB09CFBC16}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug DLL|Win32 = Debug DLL|Win32
|
|
||||||
Debug|Win32 = Debug|Win32
|
|
||||||
Release DLL|Win32 = Release DLL|Win32
|
|
||||||
Release|Win32 = Release|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{0CB5681F-6065-490C-98C8-05531732ED7E}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32
|
|
||||||
{0CB5681F-6065-490C-98C8-05531732ED7E}.Debug DLL|Win32.Build.0 = Debug DLL|Win32
|
|
||||||
{0CB5681F-6065-490C-98C8-05531732ED7E}.Debug|Win32.ActiveCfg = Debug|Win32
|
|
||||||
{0CB5681F-6065-490C-98C8-05531732ED7E}.Debug|Win32.Build.0 = Debug|Win32
|
|
||||||
{0CB5681F-6065-490C-98C8-05531732ED7E}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
|
|
||||||
{0CB5681F-6065-490C-98C8-05531732ED7E}.Release DLL|Win32.Build.0 = Release DLL|Win32
|
|
||||||
{0CB5681F-6065-490C-98C8-05531732ED7E}.Release|Win32.ActiveCfg = Release|Win32
|
|
||||||
{0CB5681F-6065-490C-98C8-05531732ED7E}.Release|Win32.Build.0 = Release|Win32
|
|
||||||
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32
|
|
||||||
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Debug DLL|Win32.Build.0 = Debug DLL|Win32
|
|
||||||
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Debug|Win32.ActiveCfg = Debug|Win32
|
|
||||||
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Debug|Win32.Build.0 = Debug|Win32
|
|
||||||
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
|
|
||||||
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Release DLL|Win32.Build.0 = Release DLL|Win32
|
|
||||||
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Release|Win32.ActiveCfg = Release|Win32
|
|
||||||
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Release|Win32.Build.0 = Release|Win32
|
|
||||||
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32
|
|
||||||
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Debug DLL|Win32.Build.0 = Debug DLL|Win32
|
|
||||||
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Debug|Win32.ActiveCfg = Debug|Win32
|
|
||||||
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Debug|Win32.Build.0 = Debug|Win32
|
|
||||||
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
|
|
||||||
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Release DLL|Win32.Build.0 = Release DLL|Win32
|
|
||||||
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Release|Win32.ActiveCfg = Release|Win32
|
|
||||||
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Release|Win32.Build.0 = Release|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
|
||||||
<ProjectConfiguration Include="Debug DLL|Win32">
|
|
||||||
<Configuration>Debug DLL</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release DLL|Win32">
|
|
||||||
<Configuration>Release DLL</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|Win32">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<ProjectName>libwebm</ProjectName>
|
|
||||||
<ProjectGuid>{7B1F12CA-0724-430B-B61A-1D357C912CBA}</ProjectGuid>
|
|
||||||
<RootNamespace>libwebm</RootNamespace>
|
|
||||||
<Keyword>Win32Proj</Keyword>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<PlatformToolset>Windows7.1SDK</PlatformToolset>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<PlatformToolset>Windows7.1SDK</PlatformToolset>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
<PlatformToolset>Windows7.1SDK</PlatformToolset>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
<PlatformToolset>Windows7.1SDK</PlatformToolset>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
|
||||||
<ImportGroup Label="ExtensionSettings">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<PropertyGroup Label="UserMacros" />
|
|
||||||
<PropertyGroup>
|
|
||||||
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
|
|
||||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\lib\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">$(ProjectDir)..\lib\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\lib\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">$(ProjectDir)..\lib\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<MinimalRebuild>false</MinimalRebuild>
|
|
||||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level4</WarningLevel>
|
|
||||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
|
||||||
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<MinimalRebuild>false</MinimalRebuild>
|
|
||||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
|
||||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level4</WarningLevel>
|
|
||||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
|
||||||
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<Optimization>MaxSpeed</Optimization>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level4</WarningLevel>
|
|
||||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<Optimization>MaxSpeed</Optimization>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level4</WarningLevel>
|
|
||||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="mkvmuxer.cpp" />
|
|
||||||
<ClCompile Include="mkvmuxerutil.cpp" />
|
|
||||||
<ClCompile Include="mkvparser.cpp" />
|
|
||||||
<ClCompile Include="mkvreader.cpp" />
|
|
||||||
<ClCompile Include="mkvwriter.cpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="mkvmuxer.hpp" />
|
|
||||||
<ClInclude Include="mkvmuxertypes.hpp" />
|
|
||||||
<ClInclude Include="mkvmuxerutil.hpp" />
|
|
||||||
<ClInclude Include="mkvparser.hpp" />
|
|
||||||
<ClInclude Include="mkvreader.hpp" />
|
|
||||||
<ClInclude Include="mkvwriter.hpp" />
|
|
||||||
<ClInclude Include="webmids.hpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup>
|
|
||||||
<Filter Include="Source Files">
|
|
||||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
|
||||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Header Files">
|
|
||||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
|
||||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
|
||||||
</Filter>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="mkvmuxer.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="mkvmuxerutil.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="mkvparser.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="mkvreader.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="mkvwriter.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="mkvmuxer.hpp">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="mkvmuxertypes.hpp">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="mkvmuxerutil.hpp">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="mkvparser.hpp">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="mkvreader.hpp">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="mkvwriter.hpp">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="webmids.hpp">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
1369
mkvmuxer.cpp
1369
mkvmuxer.cpp
File diff suppressed because it is too large
Load Diff
472
mkvmuxer.hpp
472
mkvmuxer.hpp
@@ -15,7 +15,7 @@
|
|||||||
// http://www.webmproject.org/code/specs/container/.
|
// http://www.webmproject.org/code/specs/container/.
|
||||||
|
|
||||||
namespace mkvparser {
|
namespace mkvparser {
|
||||||
class IMkvReader;
|
class IMkvReader;
|
||||||
} // end namespace
|
} // end namespace
|
||||||
|
|
||||||
namespace mkvmuxer {
|
namespace mkvmuxer {
|
||||||
@@ -23,6 +23,8 @@ namespace mkvmuxer {
|
|||||||
class MkvWriter;
|
class MkvWriter;
|
||||||
class Segment;
|
class Segment;
|
||||||
|
|
||||||
|
const uint64 kMaxTrackNumber = 126;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////
|
||||||
// Interface used by the mkvmuxer to write out the Mkv data.
|
// Interface used by the mkvmuxer to write out the Mkv data.
|
||||||
class IMkvWriter {
|
class IMkvWriter {
|
||||||
@@ -57,11 +59,15 @@ class IMkvWriter {
|
|||||||
|
|
||||||
// Writes out the EBML header for a WebM file. This function must be called
|
// Writes out the EBML header for a WebM file. This function must be called
|
||||||
// before any other libwebm writing functions are called.
|
// before any other libwebm writing functions are called.
|
||||||
|
bool WriteEbmlHeader(IMkvWriter* writer, uint64 doc_type_version);
|
||||||
|
|
||||||
|
// Deprecated. Writes out EBML header with doc_type_version as
|
||||||
|
// kDefaultDocTypeVersion. Exists for backward compatibility.
|
||||||
bool WriteEbmlHeader(IMkvWriter* writer);
|
bool WriteEbmlHeader(IMkvWriter* writer);
|
||||||
|
|
||||||
// Copies in Chunk from source to destination between the given byte positions
|
// Copies in Chunk from source to destination between the given byte positions
|
||||||
bool ChunkedCopy(mkvparser::IMkvReader* source, IMkvWriter* dst,
|
bool ChunkedCopy(mkvparser::IMkvReader* source, IMkvWriter* dst, int64 start,
|
||||||
int64 start, int64 size);
|
int64 size);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////
|
||||||
// Class to hold data the will be written to a block.
|
// Class to hold data the will be written to a block.
|
||||||
@@ -70,22 +76,65 @@ class Frame {
|
|||||||
Frame();
|
Frame();
|
||||||
~Frame();
|
~Frame();
|
||||||
|
|
||||||
|
// Sets this frame's contents based on |frame|. Returns true on success. On
|
||||||
|
// failure, this frame's existing contents may be lost.
|
||||||
|
bool CopyFrom(const Frame& frame);
|
||||||
|
|
||||||
// Copies |frame| data into |frame_|. Returns true on success.
|
// Copies |frame| data into |frame_|. Returns true on success.
|
||||||
bool Init(const uint8* frame, uint64 length);
|
bool Init(const uint8* frame, uint64 length);
|
||||||
|
|
||||||
|
// Copies |additional| data into |additional_|. Returns true on success.
|
||||||
|
bool AddAdditionalData(const uint8* additional, uint64 length, uint64 add_id);
|
||||||
|
|
||||||
|
// Returns true if the frame has valid parameters.
|
||||||
|
bool IsValid() const;
|
||||||
|
|
||||||
|
// Returns true if the frame can be written as a SimpleBlock based on current
|
||||||
|
// parameters.
|
||||||
|
bool CanBeSimpleBlock() const;
|
||||||
|
|
||||||
|
uint64 add_id() const { return add_id_; }
|
||||||
|
const uint8* additional() const { return additional_; }
|
||||||
|
uint64 additional_length() const { return additional_length_; }
|
||||||
|
void set_duration(uint64 duration) { duration_ = duration; }
|
||||||
|
uint64 duration() const { return duration_; }
|
||||||
const uint8* frame() const { return frame_; }
|
const uint8* frame() const { return frame_; }
|
||||||
|
void set_is_key(bool key) { is_key_ = key; }
|
||||||
|
bool is_key() const { return is_key_; }
|
||||||
uint64 length() const { return length_; }
|
uint64 length() const { return length_; }
|
||||||
void set_track_number(uint64 track_number) { track_number_ = track_number; }
|
void set_track_number(uint64 track_number) { track_number_ = track_number; }
|
||||||
uint64 track_number() const { return track_number_; }
|
uint64 track_number() const { return track_number_; }
|
||||||
void set_timestamp(uint64 timestamp) { timestamp_ = timestamp; }
|
void set_timestamp(uint64 timestamp) { timestamp_ = timestamp; }
|
||||||
uint64 timestamp() const { return timestamp_; }
|
uint64 timestamp() const { return timestamp_; }
|
||||||
void set_is_key(bool key) { is_key_ = key; }
|
void set_discard_padding(int64 discard_padding) {
|
||||||
bool is_key() const { return is_key_; }
|
discard_padding_ = discard_padding;
|
||||||
|
}
|
||||||
|
int64 discard_padding() const { return discard_padding_; }
|
||||||
|
void set_reference_block_timestamp(int64 reference_block_timestamp);
|
||||||
|
int64 reference_block_timestamp() const { return reference_block_timestamp_; }
|
||||||
|
bool reference_block_timestamp_set() const {
|
||||||
|
return reference_block_timestamp_set_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Id of the Additional data.
|
||||||
|
uint64 add_id_;
|
||||||
|
|
||||||
|
// Pointer to additional data. Owned by this class.
|
||||||
|
uint8* additional_;
|
||||||
|
|
||||||
|
// Length of the additional data.
|
||||||
|
uint64 additional_length_;
|
||||||
|
|
||||||
|
// Duration of the frame in nanoseconds.
|
||||||
|
uint64 duration_;
|
||||||
|
|
||||||
// Pointer to the data. Owned by this class.
|
// Pointer to the data. Owned by this class.
|
||||||
uint8* frame_;
|
uint8* frame_;
|
||||||
|
|
||||||
|
// Flag telling if the data should set the key flag of a block.
|
||||||
|
bool is_key_;
|
||||||
|
|
||||||
// Length of the data.
|
// Length of the data.
|
||||||
uint64 length_;
|
uint64 length_;
|
||||||
|
|
||||||
@@ -95,8 +144,16 @@ class Frame {
|
|||||||
// Timestamp of the data in nanoseconds.
|
// Timestamp of the data in nanoseconds.
|
||||||
uint64 timestamp_;
|
uint64 timestamp_;
|
||||||
|
|
||||||
// Flag telling if the data should set the key flag of a block.
|
// Discard padding for the frame.
|
||||||
bool is_key_;
|
int64 discard_padding_;
|
||||||
|
|
||||||
|
// Reference block timestamp.
|
||||||
|
int64 reference_block_timestamp_;
|
||||||
|
|
||||||
|
// Flag indicating if |reference_block_timestamp_| has been set.
|
||||||
|
bool reference_block_timestamp_set_;
|
||||||
|
|
||||||
|
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Frame);
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////
|
||||||
@@ -195,9 +252,7 @@ class Cues {
|
|||||||
// ContentEncAESSettings element
|
// ContentEncAESSettings element
|
||||||
class ContentEncAESSettings {
|
class ContentEncAESSettings {
|
||||||
public:
|
public:
|
||||||
enum {
|
enum { kCTR = 1 };
|
||||||
kCTR = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
ContentEncAESSettings();
|
ContentEncAESSettings();
|
||||||
~ContentEncAESSettings() {}
|
~ContentEncAESSettings() {}
|
||||||
@@ -319,6 +374,16 @@ class Track {
|
|||||||
uint64 type() const { return type_; }
|
uint64 type() const { return type_; }
|
||||||
void set_uid(uint64 uid) { uid_ = uid; }
|
void set_uid(uint64 uid) { uid_ = uid; }
|
||||||
uint64 uid() const { return uid_; }
|
uint64 uid() const { return uid_; }
|
||||||
|
void set_codec_delay(uint64 codec_delay) { codec_delay_ = codec_delay; }
|
||||||
|
uint64 codec_delay() const { return codec_delay_; }
|
||||||
|
void set_seek_pre_roll(uint64 seek_pre_roll) {
|
||||||
|
seek_pre_roll_ = seek_pre_roll;
|
||||||
|
}
|
||||||
|
uint64 seek_pre_roll() const { return seek_pre_roll_; }
|
||||||
|
void set_default_duration(uint64 default_duration) {
|
||||||
|
default_duration_ = default_duration;
|
||||||
|
}
|
||||||
|
uint64 default_duration() const { return default_duration_; }
|
||||||
|
|
||||||
uint64 codec_private_length() const { return codec_private_length_; }
|
uint64 codec_private_length() const { return codec_private_length_; }
|
||||||
uint32 content_encoding_entries_size() const {
|
uint32 content_encoding_entries_size() const {
|
||||||
@@ -326,7 +391,7 @@ class Track {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Track element names
|
// Track element names.
|
||||||
char* codec_id_;
|
char* codec_id_;
|
||||||
uint8* codec_private_;
|
uint8* codec_private_;
|
||||||
char* language_;
|
char* language_;
|
||||||
@@ -335,6 +400,9 @@ class Track {
|
|||||||
uint64 number_;
|
uint64 number_;
|
||||||
uint64 type_;
|
uint64 type_;
|
||||||
uint64 uid_;
|
uint64 uid_;
|
||||||
|
uint64 codec_delay_;
|
||||||
|
uint64 seek_pre_roll_;
|
||||||
|
uint64 default_duration_;
|
||||||
|
|
||||||
// Size of the CodecPrivate data in bytes.
|
// Size of the CodecPrivate data in bytes.
|
||||||
uint64 codec_private_length_;
|
uint64 codec_private_length_;
|
||||||
@@ -355,16 +423,13 @@ class VideoTrack : public Track {
|
|||||||
// Supported modes for stereo 3D.
|
// Supported modes for stereo 3D.
|
||||||
enum StereoMode {
|
enum StereoMode {
|
||||||
kMono = 0,
|
kMono = 0,
|
||||||
kSideBySideLeftIsFirst = 1,
|
kSideBySideLeftIsFirst = 1,
|
||||||
kTopBottomRightIsFirst = 2,
|
kTopBottomRightIsFirst = 2,
|
||||||
kTopBottomLeftIsFirst = 3,
|
kTopBottomLeftIsFirst = 3,
|
||||||
kSideBySideRightIsFirst = 11
|
kSideBySideRightIsFirst = 11
|
||||||
};
|
};
|
||||||
|
|
||||||
enum AlphaMode {
|
enum AlphaMode { kNoAlpha = 0, kAlpha = 1 };
|
||||||
kNoAlpha = 0,
|
|
||||||
kAlpha = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
// The |seed| parameter is used to synthesize a UID for the track.
|
// The |seed| parameter is used to synthesize a UID for the track.
|
||||||
explicit VideoTrack(unsigned int* seed);
|
explicit VideoTrack(unsigned int* seed);
|
||||||
@@ -387,6 +452,16 @@ class VideoTrack : public Track {
|
|||||||
uint64 display_height() const { return display_height_; }
|
uint64 display_height() const { return display_height_; }
|
||||||
void set_display_width(uint64 width) { display_width_ = width; }
|
void set_display_width(uint64 width) { display_width_ = width; }
|
||||||
uint64 display_width() const { return display_width_; }
|
uint64 display_width() const { return display_width_; }
|
||||||
|
|
||||||
|
void set_crop_left(uint64 crop_left) { crop_left_ = crop_left; }
|
||||||
|
uint64 crop_left() const { return crop_left_; }
|
||||||
|
void set_crop_right(uint64 crop_right) { crop_right_ = crop_right; }
|
||||||
|
uint64 crop_right() const { return crop_right_; }
|
||||||
|
void set_crop_top(uint64 crop_top) { crop_top_ = crop_top; }
|
||||||
|
uint64 crop_top() const { return crop_top_; }
|
||||||
|
void set_crop_bottom(uint64 crop_bottom) { crop_bottom_ = crop_bottom; }
|
||||||
|
uint64 crop_bottom() const { return crop_bottom_; }
|
||||||
|
|
||||||
void set_frame_rate(double frame_rate) { frame_rate_ = frame_rate; }
|
void set_frame_rate(double frame_rate) { frame_rate_ = frame_rate; }
|
||||||
double frame_rate() const { return frame_rate_; }
|
double frame_rate() const { return frame_rate_; }
|
||||||
void set_height(uint64 height) { height_ = height; }
|
void set_height(uint64 height) { height_ = height; }
|
||||||
@@ -403,6 +478,10 @@ class VideoTrack : public Track {
|
|||||||
// Video track element names.
|
// Video track element names.
|
||||||
uint64 display_height_;
|
uint64 display_height_;
|
||||||
uint64 display_width_;
|
uint64 display_width_;
|
||||||
|
uint64 crop_left_;
|
||||||
|
uint64 crop_right_;
|
||||||
|
uint64 crop_top_;
|
||||||
|
uint64 crop_bottom_;
|
||||||
double frame_rate_;
|
double frame_rate_;
|
||||||
uint64 height_;
|
uint64 height_;
|
||||||
uint64 stereo_mode_;
|
uint64 stereo_mode_;
|
||||||
@@ -448,13 +527,13 @@ class AudioTrack : public Track {
|
|||||||
class Tracks {
|
class Tracks {
|
||||||
public:
|
public:
|
||||||
// Audio and video type defined by the Matroska specs.
|
// Audio and video type defined by the Matroska specs.
|
||||||
enum {
|
enum { kVideo = 0x1, kAudio = 0x2 };
|
||||||
kVideo = 0x1,
|
|
||||||
kAudio = 0x2
|
static const char kOpusCodecId[];
|
||||||
};
|
static const char kVorbisCodecId[];
|
||||||
// Vorbis and VP8 coded id defined by the Matroska specs.
|
static const char kVp8CodecId[];
|
||||||
static const char* const kVorbisCodecId;
|
static const char kVp9CodecId[];
|
||||||
static const char* const kVp8CodecId;
|
static const char kVp10CodecId[];
|
||||||
|
|
||||||
Tracks();
|
Tracks();
|
||||||
~Tracks();
|
~Tracks();
|
||||||
@@ -490,6 +569,9 @@ class Tracks {
|
|||||||
// Number of Track elements added.
|
// Number of Track elements added.
|
||||||
uint32 track_entries_size_;
|
uint32 track_entries_size_;
|
||||||
|
|
||||||
|
// Whether or not Tracks element has already been written via IMkvWriter.
|
||||||
|
mutable bool wrote_tracks_;
|
||||||
|
|
||||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tracks);
|
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tracks);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -506,10 +588,13 @@ class Chapter {
|
|||||||
|
|
||||||
// Converts the nanosecond start and stop times of this chapter to
|
// Converts the nanosecond start and stop times of this chapter to
|
||||||
// their corresponding timecode values, and stores them that way.
|
// their corresponding timecode values, and stores them that way.
|
||||||
void set_time(const Segment& segment,
|
void set_time(const Segment& segment, uint64 start_time_ns,
|
||||||
uint64 start_time_ns,
|
|
||||||
uint64 end_time_ns);
|
uint64 end_time_ns);
|
||||||
|
|
||||||
|
// Sets the uid for this chapter. Primarily used to enable
|
||||||
|
// deterministic output from the muxer.
|
||||||
|
void set_uid(const uint64 uid) { uid_ = uid; }
|
||||||
|
|
||||||
// Add a title string to this chapter, per the semantics described
|
// Add a title string to this chapter, per the semantics described
|
||||||
// here:
|
// here:
|
||||||
// http://www.matroska.org/technical/specs/index.html
|
// http://www.matroska.org/technical/specs/index.html
|
||||||
@@ -526,9 +611,7 @@ class Chapter {
|
|||||||
// http://www.iana.org/domains/root/db/
|
// http://www.iana.org/domains/root/db/
|
||||||
//
|
//
|
||||||
// The function returns false if the string could not be allocated.
|
// The function returns false if the string could not be allocated.
|
||||||
bool add_string(const char* title,
|
bool add_string(const char* title, const char* language, const char* country);
|
||||||
const char* language,
|
|
||||||
const char* country);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class Chapters;
|
friend class Chapters;
|
||||||
@@ -657,6 +740,112 @@ class Chapters {
|
|||||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Chapters);
|
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Chapters);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
|
// Tag element
|
||||||
|
//
|
||||||
|
class Tag {
|
||||||
|
public:
|
||||||
|
bool add_simple_tag(const char* tag_name, const char* tag_string);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Tags calls Clear and the destructor of Tag
|
||||||
|
friend class Tags;
|
||||||
|
|
||||||
|
// For storage of simple tags
|
||||||
|
class SimpleTag {
|
||||||
|
public:
|
||||||
|
// Establish representation invariant for new SimpleTag object.
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
// Reclaim resources, in anticipation of destruction.
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
// Copies the title to the |tag_name_| member. Returns false on
|
||||||
|
// error.
|
||||||
|
bool set_tag_name(const char* tag_name);
|
||||||
|
|
||||||
|
// Copies the language to the |tag_string_| member. Returns false
|
||||||
|
// on error.
|
||||||
|
bool set_tag_string(const char* tag_string);
|
||||||
|
|
||||||
|
// If |writer| is non-NULL, serialize the SimpleTag sub-element of
|
||||||
|
// the Atom into the stream. Returns the SimpleTag element size on
|
||||||
|
// success, 0 if error.
|
||||||
|
uint64 Write(IMkvWriter* writer) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
char* tag_name_;
|
||||||
|
char* tag_string_;
|
||||||
|
};
|
||||||
|
|
||||||
|
Tag();
|
||||||
|
~Tag();
|
||||||
|
|
||||||
|
// Copies this Tag object to a different one. This is used when
|
||||||
|
// expanding a plain array of Tag objects (see Tags).
|
||||||
|
void ShallowCopy(Tag* dst) const;
|
||||||
|
|
||||||
|
// Reclaim resources used by this Tag object, pending its
|
||||||
|
// destruction.
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
// If there is no storage remaining on the |simple_tags_| array for a
|
||||||
|
// new display object, creates a new, longer array and copies the
|
||||||
|
// existing SimpleTag objects to the new array. Returns false if the
|
||||||
|
// array cannot be expanded.
|
||||||
|
bool ExpandSimpleTagsArray();
|
||||||
|
|
||||||
|
// If |writer| is non-NULL, serialize the Tag sub-element into the
|
||||||
|
// stream. Returns the total size of the element on success, 0 if
|
||||||
|
// error.
|
||||||
|
uint64 Write(IMkvWriter* writer) const;
|
||||||
|
|
||||||
|
// The Atom element can contain multiple SimpleTag sub-elements
|
||||||
|
SimpleTag* simple_tags_;
|
||||||
|
|
||||||
|
// The physical length (total size) of the |simple_tags_| array.
|
||||||
|
int simple_tags_size_;
|
||||||
|
|
||||||
|
// The logical length (number of active elements) on the |simple_tags_|
|
||||||
|
// array.
|
||||||
|
int simple_tags_count_;
|
||||||
|
|
||||||
|
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tag);
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
|
// Tags element
|
||||||
|
//
|
||||||
|
class Tags {
|
||||||
|
public:
|
||||||
|
Tags();
|
||||||
|
~Tags();
|
||||||
|
|
||||||
|
Tag* AddTag();
|
||||||
|
|
||||||
|
// Returns the number of tags that have been added.
|
||||||
|
int Count() const;
|
||||||
|
|
||||||
|
// Output the Tags element to the writer. Returns true on success.
|
||||||
|
bool Write(IMkvWriter* writer) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Expands the tags_ array if there is not enough space to contain
|
||||||
|
// another tag object. Returns true on success.
|
||||||
|
bool ExpandTagsArray();
|
||||||
|
|
||||||
|
// Total length of the tags_ array.
|
||||||
|
int tags_size_;
|
||||||
|
|
||||||
|
// Number of active tags on the tags_ array.
|
||||||
|
int tags_count_;
|
||||||
|
|
||||||
|
// Array for storage of tag objects.
|
||||||
|
Tag* tags_;
|
||||||
|
|
||||||
|
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tags);
|
||||||
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////
|
||||||
// Cluster element
|
// Cluster element
|
||||||
//
|
//
|
||||||
@@ -664,34 +853,36 @@ class Chapters {
|
|||||||
// |Init| must be called before any other method in this class.
|
// |Init| must be called before any other method in this class.
|
||||||
class Cluster {
|
class Cluster {
|
||||||
public:
|
public:
|
||||||
Cluster(uint64 timecode, int64 cues_pos);
|
|
||||||
~Cluster();
|
|
||||||
|
|
||||||
// |timecode| is the absolute timecode of the cluster. |cues_pos| is the
|
// |timecode| is the absolute timecode of the cluster. |cues_pos| is the
|
||||||
// position for the cluster within the segment that should be written in
|
// position for the cluster within the segment that should be written in
|
||||||
// the cues element.
|
// the cues element. |timecode_scale| is the timecode scale of the segment.
|
||||||
|
Cluster(uint64 timecode, int64 cues_pos, uint64 timecode_scale);
|
||||||
|
~Cluster();
|
||||||
|
|
||||||
bool Init(IMkvWriter* ptr_writer);
|
bool Init(IMkvWriter* ptr_writer);
|
||||||
|
|
||||||
|
// Adds a frame to be output in the file. The frame is written out through
|
||||||
|
// |writer_| if successful. Returns true on success.
|
||||||
|
bool AddFrame(const Frame* frame);
|
||||||
|
|
||||||
// Adds a frame to be output in the file. The frame is written out through
|
// Adds a frame to be output in the file. The frame is written out through
|
||||||
// |writer_| if successful. Returns true on success.
|
// |writer_| if successful. Returns true on success.
|
||||||
// Inputs:
|
// Inputs:
|
||||||
// frame: Pointer to the data
|
// data: Pointer to the data
|
||||||
// length: Length of the data
|
// length: Length of the data
|
||||||
// track_number: Track to add the data to. Value returned by Add track
|
// track_number: Track to add the data to. Value returned by Add track
|
||||||
// functions. The range of allowed values is [1, 126].
|
// functions. The range of allowed values is [1, 126].
|
||||||
// timecode: Absolute (not relative to cluster) timestamp of the
|
// timecode: Absolute (not relative to cluster) timestamp of the
|
||||||
// frame, expressed in timecode units.
|
// frame, expressed in timecode units.
|
||||||
// is_key: Flag telling whether or not this frame is a key frame.
|
// is_key: Flag telling whether or not this frame is a key frame.
|
||||||
bool AddFrame(const uint8* frame,
|
bool AddFrame(const uint8* data, uint64 length, uint64 track_number,
|
||||||
uint64 length,
|
|
||||||
uint64 track_number,
|
|
||||||
uint64 timecode, // timecode units (absolute)
|
uint64 timecode, // timecode units (absolute)
|
||||||
bool is_key);
|
bool is_key);
|
||||||
|
|
||||||
// Adds a frame to be output in the file. The frame is written out through
|
// Adds a frame to be output in the file. The frame is written out through
|
||||||
// |writer_| if successful. Returns true on success.
|
// |writer_| if successful. Returns true on success.
|
||||||
// Inputs:
|
// Inputs:
|
||||||
// frame: Pointer to the data
|
// data: Pointer to the data
|
||||||
// length: Length of the data
|
// length: Length of the data
|
||||||
// additional: Pointer to the additional data
|
// additional: Pointer to the additional data
|
||||||
// additional_length: Length of the additional data
|
// additional_length: Length of the additional data
|
||||||
@@ -701,19 +892,30 @@ class Cluster {
|
|||||||
// abs_timecode: Absolute (not relative to cluster) timestamp of the
|
// abs_timecode: Absolute (not relative to cluster) timestamp of the
|
||||||
// frame, expressed in timecode units.
|
// frame, expressed in timecode units.
|
||||||
// is_key: Flag telling whether or not this frame is a key frame.
|
// is_key: Flag telling whether or not this frame is a key frame.
|
||||||
bool AddFrameWithAdditional(const uint8* frame,
|
bool AddFrameWithAdditional(const uint8* data, uint64 length,
|
||||||
uint64 length,
|
const uint8* additional, uint64 additional_length,
|
||||||
const uint8* additional,
|
uint64 add_id, uint64 track_number,
|
||||||
uint64 additional_length,
|
uint64 abs_timecode, bool is_key);
|
||||||
uint64 add_id,
|
|
||||||
uint64 track_number,
|
// Adds a frame to be output in the file. The frame is written out through
|
||||||
uint64 abs_timecode,
|
// |writer_| if successful. Returns true on success.
|
||||||
bool is_key);
|
// Inputs:
|
||||||
|
// data: Pointer to the data.
|
||||||
|
// length: Length of the data.
|
||||||
|
// discard_padding: DiscardPadding element value.
|
||||||
|
// track_number: Track to add the data to. Value returned by Add track
|
||||||
|
// functions. The range of allowed values is [1, 126].
|
||||||
|
// abs_timecode: Absolute (not relative to cluster) timestamp of the
|
||||||
|
// frame, expressed in timecode units.
|
||||||
|
// is_key: Flag telling whether or not this frame is a key frame.
|
||||||
|
bool AddFrameWithDiscardPadding(const uint8* data, uint64 length,
|
||||||
|
int64 discard_padding, uint64 track_number,
|
||||||
|
uint64 abs_timecode, bool is_key);
|
||||||
|
|
||||||
// Writes a frame of metadata to the output medium; returns true on
|
// Writes a frame of metadata to the output medium; returns true on
|
||||||
// success.
|
// success.
|
||||||
// Inputs:
|
// Inputs:
|
||||||
// frame: Pointer to the data
|
// data: Pointer to the data
|
||||||
// length: Length of the data
|
// length: Length of the data
|
||||||
// track_number: Track to add the data to. Value returned by Add track
|
// track_number: Track to add the data to. Value returned by Add track
|
||||||
// functions. The range of allowed values is [1, 126].
|
// functions. The range of allowed values is [1, 126].
|
||||||
@@ -724,11 +926,8 @@ class Cluster {
|
|||||||
// The metadata frame is written as a block group, with a duration
|
// The metadata frame is written as a block group, with a duration
|
||||||
// sub-element but no reference time sub-elements (indicating that
|
// sub-element but no reference time sub-elements (indicating that
|
||||||
// it is considered a keyframe, per Matroska semantics).
|
// it is considered a keyframe, per Matroska semantics).
|
||||||
bool AddMetadata(const uint8* frame,
|
bool AddMetadata(const uint8* data, uint64 length, uint64 track_number,
|
||||||
uint64 length,
|
uint64 timecode, uint64 duration);
|
||||||
uint64 track_number,
|
|
||||||
uint64 timecode, // timecode units (absolute)
|
|
||||||
uint64 duration); // timecode units
|
|
||||||
|
|
||||||
// Increments the size of the cluster's data in bytes.
|
// Increments the size of the cluster's data in bytes.
|
||||||
void AddPayloadSize(uint64 size);
|
void AddPayloadSize(uint64 size);
|
||||||
@@ -740,52 +939,29 @@ class Cluster {
|
|||||||
// Returns the size in bytes for the entire Cluster element.
|
// Returns the size in bytes for the entire Cluster element.
|
||||||
uint64 Size() const;
|
uint64 Size() const;
|
||||||
|
|
||||||
|
// Given |abs_timecode|, calculates timecode relative to most recent timecode.
|
||||||
|
// Returns -1 on failure, or a relative timecode.
|
||||||
|
int64 GetRelativeTimecode(int64 abs_timecode) const;
|
||||||
|
|
||||||
int64 size_position() const { return size_position_; }
|
int64 size_position() const { return size_position_; }
|
||||||
int32 blocks_added() const { return blocks_added_; }
|
int32 blocks_added() const { return blocks_added_; }
|
||||||
uint64 payload_size() const { return payload_size_; }
|
uint64 payload_size() const { return payload_size_; }
|
||||||
int64 position_for_cues() const { return position_for_cues_; }
|
int64 position_for_cues() const { return position_for_cues_; }
|
||||||
uint64 timecode() const { return timecode_; }
|
uint64 timecode() const { return timecode_; }
|
||||||
|
uint64 timecode_scale() const { return timecode_scale_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Signature that matches either of WriteSimpleBlock or WriteMetadataBlock
|
// Utility method that confirms that blocks can still be added, and that the
|
||||||
// in the muxer utilities package.
|
// cluster header has been written. Used by |DoWriteFrame*|. Returns true
|
||||||
typedef uint64 (*WriteBlock)(IMkvWriter* writer,
|
// when successful.
|
||||||
const uint8* data,
|
bool PreWriteBlock();
|
||||||
uint64 length,
|
|
||||||
uint64 track_number,
|
|
||||||
int64 timecode,
|
|
||||||
uint64 generic_arg);
|
|
||||||
|
|
||||||
// Signature that matches WriteBlockWithAdditional
|
// Utility method used by the |DoWriteFrame*| methods that handles the book
|
||||||
// in the muxer utilities package.
|
// keeping required after each block is written.
|
||||||
typedef uint64 (*WriteBlockAdditional)(IMkvWriter* writer,
|
void PostWriteBlock(uint64 element_size);
|
||||||
const uint8* data,
|
|
||||||
uint64 length,
|
|
||||||
const uint8* additional,
|
|
||||||
uint64 add_id,
|
|
||||||
uint64 additional_length,
|
|
||||||
uint64 track_number,
|
|
||||||
int64 timecode,
|
|
||||||
uint64 is_key);
|
|
||||||
|
|
||||||
// Used to implement AddFrame and AddMetadata.
|
// Does some verification and calls WriteFrame.
|
||||||
bool DoWriteBlock(const uint8* frame,
|
bool DoWriteFrame(const Frame* const frame);
|
||||||
uint64 length,
|
|
||||||
uint64 track_number,
|
|
||||||
uint64 absolute_timecode,
|
|
||||||
uint64 generic_arg,
|
|
||||||
WriteBlock write_block);
|
|
||||||
|
|
||||||
// Used to implement AddFrameWithAdditional
|
|
||||||
bool DoWriteBlockWithAdditional(const uint8* frame,
|
|
||||||
uint64 length,
|
|
||||||
const uint8* additional,
|
|
||||||
uint64 additional_length,
|
|
||||||
uint64 add_id,
|
|
||||||
uint64 track_number,
|
|
||||||
uint64 absolute_timecode,
|
|
||||||
uint64 generic_arg,
|
|
||||||
WriteBlockAdditional write_block);
|
|
||||||
|
|
||||||
// Outputs the Cluster header to |writer_|. Returns true on success.
|
// Outputs the Cluster header to |writer_|. Returns true on success.
|
||||||
bool WriteClusterHeader();
|
bool WriteClusterHeader();
|
||||||
@@ -811,6 +987,9 @@ class Cluster {
|
|||||||
// The absolute timecode of the cluster.
|
// The absolute timecode of the cluster.
|
||||||
const uint64 timecode_;
|
const uint64 timecode_;
|
||||||
|
|
||||||
|
// The timecode scale of the Segment containing the cluster.
|
||||||
|
const uint64 timecode_scale_;
|
||||||
|
|
||||||
// Pointer to the writer object. Not owned by this class.
|
// Pointer to the writer object. Not owned by this class.
|
||||||
IMkvWriter* writer_;
|
IMkvWriter* writer_;
|
||||||
|
|
||||||
@@ -895,6 +1074,8 @@ class SegmentInfo {
|
|||||||
uint64 timecode_scale() const { return timecode_scale_; }
|
uint64 timecode_scale() const { return timecode_scale_; }
|
||||||
void set_writing_app(const char* app);
|
void set_writing_app(const char* app);
|
||||||
const char* writing_app() const { return writing_app_; }
|
const char* writing_app() const { return writing_app_; }
|
||||||
|
void set_date_utc(int64 date_utc) { date_utc_ = date_utc; }
|
||||||
|
int64 date_utc() const { return date_utc_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Segment Information element names.
|
// Segment Information element names.
|
||||||
@@ -906,6 +1087,8 @@ class SegmentInfo {
|
|||||||
uint64 timecode_scale_;
|
uint64 timecode_scale_;
|
||||||
// Initially set to libwebm-%d.%d.%d.%d, major, minor, build, revision.
|
// Initially set to libwebm-%d.%d.%d.%d, major, minor, build, revision.
|
||||||
char* writing_app_;
|
char* writing_app_;
|
||||||
|
// LLONG_MIN when DateUTC is not set.
|
||||||
|
int64 date_utc_;
|
||||||
|
|
||||||
// The file position of the duration element.
|
// The file position of the duration element.
|
||||||
int64 duration_pos_;
|
int64 duration_pos_;
|
||||||
@@ -921,16 +1104,14 @@ class SegmentInfo {
|
|||||||
// |Init| must be called before any other method in this class.
|
// |Init| must be called before any other method in this class.
|
||||||
class Segment {
|
class Segment {
|
||||||
public:
|
public:
|
||||||
enum Mode {
|
enum Mode { kLive = 0x1, kFile = 0x2 };
|
||||||
kLive = 0x1,
|
|
||||||
kFile = 0x2
|
|
||||||
};
|
|
||||||
|
|
||||||
enum CuesPosition {
|
enum CuesPosition {
|
||||||
kAfterClusters = 0x0, // Position Cues after Clusters - Default
|
kAfterClusters = 0x0, // Position Cues after Clusters - Default
|
||||||
kBeforeClusters = 0x1 // Position Cues before Clusters
|
kBeforeClusters = 0x1 // Position Cues before Clusters
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const static uint32 kDefaultDocTypeVersion = 2;
|
||||||
const static uint64 kDefaultMaxClusterDuration = 30000000000ULL;
|
const static uint64 kDefaultMaxClusterDuration = 30000000000ULL;
|
||||||
|
|
||||||
Segment();
|
Segment();
|
||||||
@@ -947,8 +1128,8 @@ class Segment {
|
|||||||
// track number.
|
// track number.
|
||||||
Track* AddTrack(int32 number);
|
Track* AddTrack(int32 number);
|
||||||
|
|
||||||
// Adds an audio track to the segment. Returns the number of the track on
|
// Adds a Vorbis audio track to the segment. Returns the number of the track
|
||||||
// success, 0 on error. |number| is the number to use for the audio track.
|
// on success, 0 on error. |number| is the number to use for the audio track.
|
||||||
// |number| must be >= 0. If |number| == 0 then the muxer will decide on
|
// |number| must be >= 0. If |number| == 0 then the muxer will decide on
|
||||||
// the track number.
|
// the track number.
|
||||||
uint64 AddAudioTrack(int32 sample_rate, int32 channels, int32 number);
|
uint64 AddAudioTrack(int32 sample_rate, int32 channels, int32 number);
|
||||||
@@ -958,6 +1139,11 @@ class Segment {
|
|||||||
// populate its fields via the Chapter member functions.
|
// populate its fields via the Chapter member functions.
|
||||||
Chapter* AddChapter();
|
Chapter* AddChapter();
|
||||||
|
|
||||||
|
// Adds an empty tag to the tags of this segment. Returns
|
||||||
|
// non-NULL on success. After adding the tag, the caller should
|
||||||
|
// populate its fields via the Tag member functions.
|
||||||
|
Tag* AddTag();
|
||||||
|
|
||||||
// Adds a cue point to the Cues element. |timestamp| is the time in
|
// Adds a cue point to the Cues element. |timestamp| is the time in
|
||||||
// nanoseconds of the cue's time. |track| is the Track of the Cue. This
|
// nanoseconds of the cue's time. |track| is the Track of the Cue. This
|
||||||
// function must be called after AddFrame to calculate the correct
|
// function must be called after AddFrame to calculate the correct
|
||||||
@@ -966,22 +1152,19 @@ class Segment {
|
|||||||
|
|
||||||
// Adds a frame to be output in the file. Returns true on success.
|
// Adds a frame to be output in the file. Returns true on success.
|
||||||
// Inputs:
|
// Inputs:
|
||||||
// frame: Pointer to the data
|
// data: Pointer to the data
|
||||||
// length: Length of the data
|
// length: Length of the data
|
||||||
// track_number: Track to add the data to. Value returned by Add track
|
// track_number: Track to add the data to. Value returned by Add track
|
||||||
// functions.
|
// functions.
|
||||||
// timestamp: Timestamp of the frame in nanoseconds from 0.
|
// timestamp: Timestamp of the frame in nanoseconds from 0.
|
||||||
// is_key: Flag telling whether or not this frame is a key frame.
|
// is_key: Flag telling whether or not this frame is a key frame.
|
||||||
bool AddFrame(const uint8* frame,
|
bool AddFrame(const uint8* data, uint64 length, uint64 track_number,
|
||||||
uint64 length,
|
uint64 timestamp_ns, bool is_key);
|
||||||
uint64 track_number,
|
|
||||||
uint64 timestamp_ns,
|
|
||||||
bool is_key);
|
|
||||||
|
|
||||||
// Writes a frame of metadata to the output medium; returns true on
|
// Writes a frame of metadata to the output medium; returns true on
|
||||||
// success.
|
// success.
|
||||||
// Inputs:
|
// Inputs:
|
||||||
// frame: Pointer to the data
|
// data: Pointer to the data
|
||||||
// length: Length of the data
|
// length: Length of the data
|
||||||
// track_number: Track to add the data to. Value returned by Add track
|
// track_number: Track to add the data to. Value returned by Add track
|
||||||
// functions.
|
// functions.
|
||||||
@@ -992,22 +1175,49 @@ class Segment {
|
|||||||
// The metadata frame is written as a block group, with a duration
|
// The metadata frame is written as a block group, with a duration
|
||||||
// sub-element but no reference time sub-elements (indicating that
|
// sub-element but no reference time sub-elements (indicating that
|
||||||
// it is considered a keyframe, per Matroska semantics).
|
// it is considered a keyframe, per Matroska semantics).
|
||||||
bool AddMetadata(const uint8* frame,
|
bool AddMetadata(const uint8* data, uint64 length, uint64 track_number,
|
||||||
uint64 length,
|
uint64 timestamp_ns, uint64 duration_ns);
|
||||||
uint64 track_number,
|
|
||||||
uint64 timestamp_ns,
|
|
||||||
uint64 duration_ns);
|
|
||||||
|
|
||||||
bool AddFrameWithAdditional(const uint8* frame,
|
// Writes a frame with additional data to the output medium; returns true on
|
||||||
uint64 length,
|
// success.
|
||||||
const uint8* additional,
|
// Inputs:
|
||||||
uint64 additional_length,
|
// data: Pointer to the data.
|
||||||
uint64 add_id,
|
// length: Length of the data.
|
||||||
uint64 track_number,
|
// additional: Pointer to additional data.
|
||||||
uint64 timestamp,
|
// additional_length: Length of additional data.
|
||||||
bool is_key);
|
// add_id: Additional ID which identifies the type of additional data.
|
||||||
|
// track_number: Track to add the data to. Value returned by Add track
|
||||||
|
// functions.
|
||||||
|
// timestamp: Absolute timestamp of the frame, expressed in nanosecond
|
||||||
|
// units.
|
||||||
|
// is_key: Flag telling whether or not this frame is a key frame.
|
||||||
|
bool AddFrameWithAdditional(const uint8* data, uint64 length,
|
||||||
|
const uint8* additional, uint64 additional_length,
|
||||||
|
uint64 add_id, uint64 track_number,
|
||||||
|
uint64 timestamp, bool is_key);
|
||||||
|
|
||||||
// Adds a video track to the segment. Returns the number of the track on
|
// Writes a frame with DiscardPadding to the output medium; returns true on
|
||||||
|
// success.
|
||||||
|
// Inputs:
|
||||||
|
// data: Pointer to the data.
|
||||||
|
// length: Length of the data.
|
||||||
|
// discard_padding: DiscardPadding element value.
|
||||||
|
// track_number: Track to add the data to. Value returned by Add track
|
||||||
|
// functions.
|
||||||
|
// timestamp: Absolute timestamp of the frame, expressed in nanosecond
|
||||||
|
// units.
|
||||||
|
// is_key: Flag telling whether or not this frame is a key frame.
|
||||||
|
bool AddFrameWithDiscardPadding(const uint8* data, uint64 length,
|
||||||
|
int64 discard_padding, uint64 track_number,
|
||||||
|
uint64 timestamp, bool is_key);
|
||||||
|
|
||||||
|
// Writes a Frame to the output medium. Chooses the correct way of writing
|
||||||
|
// the frame (Block vs SimpleBlock) based on the parameters passed.
|
||||||
|
// Inputs:
|
||||||
|
// frame: frame object
|
||||||
|
bool AddGenericFrame(const Frame* frame);
|
||||||
|
|
||||||
|
// Adds a VP8 video track to the segment. Returns the number of the track on
|
||||||
// success, 0 on error. |number| is the number to use for the video track.
|
// success, 0 on error. |number| is the number to use for the video track.
|
||||||
// |number| must be >= 0. If |number| == 0 then the muxer will decide on
|
// |number| must be >= 0. If |number| == 0 then the muxer will decide on
|
||||||
// the track number.
|
// the track number.
|
||||||
@@ -1088,6 +1298,9 @@ class Segment {
|
|||||||
// Cues elements.
|
// Cues elements.
|
||||||
bool CheckHeaderInfo();
|
bool CheckHeaderInfo();
|
||||||
|
|
||||||
|
// Sets |doc_type_version_| based on the current element requirements.
|
||||||
|
void UpdateDocTypeVersion();
|
||||||
|
|
||||||
// Sets |name| according to how many chunks have been written. |ext| is the
|
// Sets |name| according to how many chunks have been written. |ext| is the
|
||||||
// file extension. |name| must be deleted by the calling app. Returns true
|
// file extension. |name| must be deleted by the calling app. Returns true
|
||||||
// on success.
|
// on success.
|
||||||
@@ -1133,7 +1346,6 @@ class Segment {
|
|||||||
// was necessary but creation was not successful.
|
// was necessary but creation was not successful.
|
||||||
bool DoNewClusterProcessing(uint64 track_num, uint64 timestamp_ns, bool key);
|
bool DoNewClusterProcessing(uint64 track_num, uint64 timestamp_ns, bool key);
|
||||||
|
|
||||||
|
|
||||||
// Adjusts Cue Point values (to place Cues before Clusters) so that they
|
// Adjusts Cue Point values (to place Cues before Clusters) so that they
|
||||||
// reflect the correct offsets.
|
// reflect the correct offsets.
|
||||||
void MoveCuesBeforeClusters();
|
void MoveCuesBeforeClusters();
|
||||||
@@ -1145,7 +1357,7 @@ class Segment {
|
|||||||
// diff - indicates the difference in size of the Cues element that needs to
|
// diff - indicates the difference in size of the Cues element that needs to
|
||||||
// accounted for.
|
// accounted for.
|
||||||
// index - index in the list of Cues which is currently being adjusted.
|
// index - index in the list of Cues which is currently being adjusted.
|
||||||
// cue_size - size of the Cues element.
|
// cue_size - sum of size of all the CuePoint elements.
|
||||||
void MoveCuesBeforeClustersHelper(uint64 diff, int index, uint64* cue_size);
|
void MoveCuesBeforeClustersHelper(uint64 diff, int index, uint64* cue_size);
|
||||||
|
|
||||||
// Seeds the random number generator used to make UIDs.
|
// Seeds the random number generator used to make UIDs.
|
||||||
@@ -1157,6 +1369,7 @@ class Segment {
|
|||||||
SegmentInfo segment_info_;
|
SegmentInfo segment_info_;
|
||||||
Tracks tracks_;
|
Tracks tracks_;
|
||||||
Chapters chapters_;
|
Chapters chapters_;
|
||||||
|
Tags tags_;
|
||||||
|
|
||||||
// Number of chunks written.
|
// Number of chunks written.
|
||||||
int chunk_count_;
|
int chunk_count_;
|
||||||
@@ -1222,9 +1435,15 @@ class Segment {
|
|||||||
// Flag telling if the segment's header has been written.
|
// Flag telling if the segment's header has been written.
|
||||||
bool header_written_;
|
bool header_written_;
|
||||||
|
|
||||||
|
// Duration of the last block in nanoseconds.
|
||||||
|
uint64 last_block_duration_;
|
||||||
|
|
||||||
// Last timestamp in nanoseconds added to a cluster.
|
// Last timestamp in nanoseconds added to a cluster.
|
||||||
uint64 last_timestamp_;
|
uint64 last_timestamp_;
|
||||||
|
|
||||||
|
// Last timestamp in nanoseconds by track number added to a cluster.
|
||||||
|
uint64 last_track_timestamp_[kMaxTrackNumber];
|
||||||
|
|
||||||
// Maximum time in nanoseconds for a cluster duration. This variable is a
|
// Maximum time in nanoseconds for a cluster duration. This variable is a
|
||||||
// guideline and some clusters may have a longer duration. Default is 30
|
// guideline and some clusters may have a longer duration. Default is 30
|
||||||
// seconds.
|
// seconds.
|
||||||
@@ -1246,12 +1465,23 @@ class Segment {
|
|||||||
// Flag whether or not the muxer should output a Cues element.
|
// Flag whether or not the muxer should output a Cues element.
|
||||||
bool output_cues_;
|
bool output_cues_;
|
||||||
|
|
||||||
|
// The size of the EBML header, used to validate the header if
|
||||||
|
// WriteEbmlHeader() is called more than once.
|
||||||
|
int32 ebml_header_size_;
|
||||||
|
|
||||||
// The file position of the segment's payload.
|
// The file position of the segment's payload.
|
||||||
int64 payload_pos_;
|
int64 payload_pos_;
|
||||||
|
|
||||||
// The file position of the element's size.
|
// The file position of the element's size.
|
||||||
int64 size_position_;
|
int64 size_position_;
|
||||||
|
|
||||||
|
// Current DocTypeVersion (|doc_type_version_|) and that written in
|
||||||
|
// WriteSegmentHeader().
|
||||||
|
// WriteEbmlHeader() will be called from Finalize() if |doc_type_version_|
|
||||||
|
// differs from |doc_type_version_written_|.
|
||||||
|
uint32 doc_type_version_;
|
||||||
|
uint32 doc_type_version_written_;
|
||||||
|
|
||||||
// Pointer to the writer objects. Not owned by this class.
|
// Pointer to the writer objects. Not owned by this class.
|
||||||
IMkvWriter* writer_cluster_;
|
IMkvWriter* writer_cluster_;
|
||||||
IMkvWriter* writer_cues_;
|
IMkvWriter* writer_cues_;
|
||||||
@@ -1260,6 +1490,6 @@ class Segment {
|
|||||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Segment);
|
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Segment);
|
||||||
};
|
};
|
||||||
|
|
||||||
} //end namespace mkvmuxer
|
} // end namespace mkvmuxer
|
||||||
|
|
||||||
#endif //MKVMUXER_HPP
|
#endif // MKVMUXER_HPP
|
||||||
|
|||||||
@@ -13,18 +13,18 @@
|
|||||||
// A macro to disallow the copy constructor and operator= functions
|
// A macro to disallow the copy constructor and operator= functions
|
||||||
// This should be used in the private: declarations for a class
|
// This should be used in the private: declarations for a class
|
||||||
#define LIBWEBM_DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
#define LIBWEBM_DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||||
TypeName(const TypeName&); \
|
TypeName(const TypeName&); \
|
||||||
void operator=(const TypeName&)
|
void operator=(const TypeName&)
|
||||||
|
|
||||||
namespace mkvmuxer {
|
namespace mkvmuxer {
|
||||||
|
|
||||||
typedef unsigned char uint8;
|
typedef unsigned char uint8;
|
||||||
typedef short int16;
|
typedef short int16;
|
||||||
typedef int int32;
|
typedef int int32;
|
||||||
typedef unsigned int uint32;
|
typedef unsigned int uint32;
|
||||||
typedef long long int64;
|
typedef long long int64;
|
||||||
typedef unsigned long long uint64;
|
typedef unsigned long long uint64;
|
||||||
|
|
||||||
} //end namespace mkvmuxer
|
} // end namespace mkvmuxer
|
||||||
|
|
||||||
#endif // MKVMUXERTYPES_HPP
|
#endif // MKVMUXERTYPES_HPP
|
||||||
|
|||||||
507
mkvmuxerutil.cpp
507
mkvmuxerutil.cpp
@@ -12,22 +12,169 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#ifdef _WIN32
|
|
||||||
#define _CRT_RAND_S
|
|
||||||
#endif
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
#include "mkvwriter.hpp"
|
#include "mkvwriter.hpp"
|
||||||
#include "webmids.hpp"
|
#include "webmids.hpp"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
// Disable MSVC warnings that suggest making code non-portable.
|
||||||
|
#pragma warning(disable : 4996)
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mkvmuxer {
|
namespace mkvmuxer {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Date elements are always 8 octets in size.
|
||||||
|
const int kDateElementSize = 8;
|
||||||
|
|
||||||
|
uint64 WriteBlock(IMkvWriter* writer, const Frame* const frame, int64 timecode,
|
||||||
|
uint64 timecode_scale) {
|
||||||
|
uint64 block_additional_elem_size = 0;
|
||||||
|
uint64 block_addid_elem_size = 0;
|
||||||
|
uint64 block_more_payload_size = 0;
|
||||||
|
uint64 block_more_elem_size = 0;
|
||||||
|
uint64 block_additions_payload_size = 0;
|
||||||
|
uint64 block_additions_elem_size = 0;
|
||||||
|
if (frame->additional()) {
|
||||||
|
block_additional_elem_size = EbmlElementSize(
|
||||||
|
kMkvBlockAdditional, frame->additional(), frame->additional_length());
|
||||||
|
block_addid_elem_size = EbmlElementSize(kMkvBlockAddID, frame->add_id());
|
||||||
|
|
||||||
|
block_more_payload_size =
|
||||||
|
block_addid_elem_size + block_additional_elem_size;
|
||||||
|
block_more_elem_size =
|
||||||
|
EbmlMasterElementSize(kMkvBlockMore, block_more_payload_size) +
|
||||||
|
block_more_payload_size;
|
||||||
|
block_additions_payload_size = block_more_elem_size;
|
||||||
|
block_additions_elem_size =
|
||||||
|
EbmlMasterElementSize(kMkvBlockAdditions,
|
||||||
|
block_additions_payload_size) +
|
||||||
|
block_additions_payload_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 discard_padding_elem_size = 0;
|
||||||
|
if (frame->discard_padding() != 0) {
|
||||||
|
discard_padding_elem_size =
|
||||||
|
EbmlElementSize(kMkvDiscardPadding, frame->discard_padding());
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint64 reference_block_timestamp =
|
||||||
|
frame->reference_block_timestamp() / timecode_scale;
|
||||||
|
uint64 reference_block_elem_size = 0;
|
||||||
|
if (!frame->is_key()) {
|
||||||
|
reference_block_elem_size =
|
||||||
|
EbmlElementSize(kMkvReferenceBlock, reference_block_timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint64 duration = frame->duration() / timecode_scale;
|
||||||
|
uint64 block_duration_elem_size = 0;
|
||||||
|
if (duration > 0)
|
||||||
|
block_duration_elem_size = EbmlElementSize(kMkvBlockDuration, duration);
|
||||||
|
|
||||||
|
const uint64 block_payload_size = 4 + frame->length();
|
||||||
|
const uint64 block_elem_size =
|
||||||
|
EbmlMasterElementSize(kMkvBlock, block_payload_size) + block_payload_size;
|
||||||
|
|
||||||
|
const uint64 block_group_payload_size =
|
||||||
|
block_elem_size + block_additions_elem_size + block_duration_elem_size +
|
||||||
|
discard_padding_elem_size + reference_block_elem_size;
|
||||||
|
|
||||||
|
if (!WriteEbmlMasterElement(writer, kMkvBlockGroup,
|
||||||
|
block_group_payload_size)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WriteEbmlMasterElement(writer, kMkvBlock, block_payload_size))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (WriteUInt(writer, frame->track_number()))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (SerializeInt(writer, timecode, 2))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// For a Block, flags is always 0.
|
||||||
|
if (SerializeInt(writer, 0, 1))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (writer->Write(frame->frame(), static_cast<uint32>(frame->length())))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (frame->additional()) {
|
||||||
|
if (!WriteEbmlMasterElement(writer, kMkvBlockAdditions,
|
||||||
|
block_additions_payload_size)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WriteEbmlMasterElement(writer, kMkvBlockMore, block_more_payload_size))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!WriteEbmlElement(writer, kMkvBlockAddID, frame->add_id()))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!WriteEbmlElement(writer, kMkvBlockAdditional, frame->additional(),
|
||||||
|
frame->additional_length())) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame->discard_padding() != 0 &&
|
||||||
|
!WriteEbmlElement(writer, kMkvDiscardPadding, frame->discard_padding())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!frame->is_key() &&
|
||||||
|
!WriteEbmlElement(writer, kMkvReferenceBlock,
|
||||||
|
reference_block_timestamp)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (duration > 0 && !WriteEbmlElement(writer, kMkvBlockDuration, duration)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return EbmlMasterElementSize(kMkvBlockGroup, block_group_payload_size) +
|
||||||
|
block_group_payload_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 WriteSimpleBlock(IMkvWriter* writer, const Frame* const frame,
|
||||||
|
int64 timecode) {
|
||||||
|
if (WriteID(writer, kMkvSimpleBlock))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const int32 size = static_cast<int32>(frame->length()) + 4;
|
||||||
|
if (WriteUInt(writer, size))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (WriteUInt(writer, static_cast<uint64>(frame->track_number())))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (SerializeInt(writer, timecode, 2))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
uint64 flags = 0;
|
||||||
|
if (frame->is_key())
|
||||||
|
flags |= 0x80;
|
||||||
|
|
||||||
|
if (SerializeInt(writer, flags, 1))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (writer->Write(frame->frame(), static_cast<uint32>(frame->length())))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return GetUIntSize(kMkvSimpleBlock) + GetCodedUIntSize(size) + 4 +
|
||||||
|
frame->length();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
int32 GetCodedUIntSize(uint64 value) {
|
int32 GetCodedUIntSize(uint64 value) {
|
||||||
if (value < 0x000000000000007FULL)
|
if (value < 0x000000000000007FULL)
|
||||||
return 1;
|
return 1;
|
||||||
@@ -64,6 +211,13 @@ int32 GetUIntSize(uint64 value) {
|
|||||||
return 8;
|
return 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 GetIntSize(int64 value) {
|
||||||
|
// Doubling the requested value ensures positive values with their high bit
|
||||||
|
// set are written with 0-padding to avoid flipping the signedness.
|
||||||
|
const uint64 v = (value < 0) ? value ^ -1LL : value;
|
||||||
|
return GetUIntSize(2 * v);
|
||||||
|
}
|
||||||
|
|
||||||
uint64 EbmlMasterElementSize(uint64 type, uint64 value) {
|
uint64 EbmlMasterElementSize(uint64 type, uint64 value) {
|
||||||
// Size of EBML ID
|
// Size of EBML ID
|
||||||
int32 ebml_size = GetUIntSize(type);
|
int32 ebml_size = GetUIntSize(type);
|
||||||
@@ -74,6 +228,19 @@ uint64 EbmlMasterElementSize(uint64 type, uint64 value) {
|
|||||||
return ebml_size;
|
return ebml_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64 EbmlElementSize(uint64 type, int64 value) {
|
||||||
|
// Size of EBML ID
|
||||||
|
int32 ebml_size = GetUIntSize(type);
|
||||||
|
|
||||||
|
// Datasize
|
||||||
|
ebml_size += GetIntSize(value);
|
||||||
|
|
||||||
|
// Size of Datasize
|
||||||
|
ebml_size++;
|
||||||
|
|
||||||
|
return ebml_size;
|
||||||
|
}
|
||||||
|
|
||||||
uint64 EbmlElementSize(uint64 type, uint64 value) {
|
uint64 EbmlElementSize(uint64 type, uint64 value) {
|
||||||
// Size of EBML ID
|
// Size of EBML ID
|
||||||
int32 ebml_size = GetUIntSize(type);
|
int32 ebml_size = GetUIntSize(type);
|
||||||
@@ -87,7 +254,7 @@ uint64 EbmlElementSize(uint64 type, uint64 value) {
|
|||||||
return ebml_size;
|
return ebml_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 EbmlElementSize(uint64 type, float /* value */ ) {
|
uint64 EbmlElementSize(uint64 type, float /* value */) {
|
||||||
// Size of EBML ID
|
// Size of EBML ID
|
||||||
uint64 ebml_size = GetUIntSize(type);
|
uint64 ebml_size = GetUIntSize(type);
|
||||||
|
|
||||||
@@ -132,6 +299,19 @@ uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size) {
|
|||||||
return ebml_size;
|
return ebml_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64 EbmlDateElementSize(uint64 type) {
|
||||||
|
// Size of EBML ID
|
||||||
|
uint64 ebml_size = GetUIntSize(type);
|
||||||
|
|
||||||
|
// Datasize
|
||||||
|
ebml_size += kDateElementSize;
|
||||||
|
|
||||||
|
// Size of Datasize
|
||||||
|
ebml_size++;
|
||||||
|
|
||||||
|
return ebml_size;
|
||||||
|
}
|
||||||
|
|
||||||
int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size) {
|
int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size) {
|
||||||
if (!writer || size < 1 || size > 8)
|
if (!writer || size < 1 || size > 8)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -156,16 +336,22 @@ int32 SerializeFloat(IMkvWriter* writer, float f) {
|
|||||||
if (!writer)
|
if (!writer)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
const uint32& val = reinterpret_cast<const uint32&>(f);
|
assert(sizeof(uint32) == sizeof(float));
|
||||||
|
// This union is merely used to avoid a reinterpret_cast from float& to
|
||||||
|
// uint32& which will result in violation of strict aliasing.
|
||||||
|
union U32 {
|
||||||
|
uint32 u32;
|
||||||
|
float f;
|
||||||
|
} value;
|
||||||
|
value.f = f;
|
||||||
|
|
||||||
for (int32 i = 1; i <= 4; ++i) {
|
for (int32 i = 1; i <= 4; ++i) {
|
||||||
const int32 byte_count = 4 - i;
|
const int32 byte_count = 4 - i;
|
||||||
const int32 bit_count = byte_count * 8;
|
const int32 bit_count = byte_count * 8;
|
||||||
|
|
||||||
const uint32 bb = val >> bit_count;
|
const uint8 byte = static_cast<uint8>(value.u32 >> bit_count);
|
||||||
const uint8 b = static_cast<uint8>(bb);
|
|
||||||
|
|
||||||
const int32 status = writer->Write(&b, 1);
|
const int32 status = writer->Write(&byte, 1);
|
||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
@@ -258,6 +444,23 @@ bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, int64 value) {
|
||||||
|
if (!writer)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (WriteID(writer, type))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const uint64 size = GetIntSize(value);
|
||||||
|
if (WriteUInt(writer, size))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (SerializeInt(writer, value, static_cast<int32>(size)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value) {
|
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value) {
|
||||||
if (!writer)
|
if (!writer)
|
||||||
return false;
|
return false;
|
||||||
@@ -281,19 +484,17 @@ bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value) {
|
|||||||
if (WriteID(writer, type))
|
if (WriteID(writer, type))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const int32 length = strlen(value);
|
const uint64 length = strlen(value);
|
||||||
if (WriteUInt(writer, length))
|
if (WriteUInt(writer, length))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (writer->Write(value, length))
|
if (writer->Write(value, static_cast<const uint32>(length)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteEbmlElement(IMkvWriter* writer,
|
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const uint8* value,
|
||||||
uint64 type,
|
|
||||||
const uint8* value,
|
|
||||||
uint64 size) {
|
uint64 size) {
|
||||||
if (!writer || !value || size < 1)
|
if (!writer || !value || size < 1)
|
||||||
return false;
|
return false;
|
||||||
@@ -310,247 +511,41 @@ bool WriteEbmlElement(IMkvWriter* writer,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 WriteSimpleBlock(IMkvWriter* writer,
|
bool WriteEbmlDateElement(IMkvWriter* writer, uint64 type, int64 value) {
|
||||||
const uint8* data,
|
|
||||||
uint64 length,
|
|
||||||
uint64 track_number,
|
|
||||||
int64 timecode,
|
|
||||||
uint64 is_key) {
|
|
||||||
if (!writer)
|
if (!writer)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!data || length < 1)
|
if (WriteID(writer, type))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Here we only permit track number values to be no greater than
|
if (WriteUInt(writer, kDateElementSize))
|
||||||
// 126, which the largest value we can store having a Matroska
|
|
||||||
// integer representation of only 1 byte.
|
|
||||||
|
|
||||||
if (track_number < 1 || track_number > 126)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Technically the timestamp for a block can be less than the
|
if (SerializeInt(writer, value, kDateElementSize))
|
||||||
// timestamp for the cluster itself (remember that block timestamp
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 WriteFrame(IMkvWriter* writer, const Frame* const frame,
|
||||||
|
Cluster* cluster) {
|
||||||
|
if (!writer || !frame || !frame->IsValid() || !cluster ||
|
||||||
|
!cluster->timecode_scale())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Technically the timecode for a block can be less than the
|
||||||
|
// timecode for the cluster itself (remember that block timecode
|
||||||
// is a signed, 16-bit integer). However, as a simplification we
|
// is a signed, 16-bit integer). However, as a simplification we
|
||||||
// only permit non-negative cluster-relative timestamps for blocks.
|
// only permit non-negative cluster-relative timecodes for blocks.
|
||||||
|
const int64 relative_timecode = cluster->GetRelativeTimecode(
|
||||||
if (timecode < 0 || timecode > kMaxBlockTimecode)
|
frame->timestamp() / cluster->timecode_scale());
|
||||||
return false;
|
if (relative_timecode < 0 || relative_timecode > kMaxBlockTimecode)
|
||||||
|
|
||||||
if (WriteID(writer, kMkvSimpleBlock))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const int32 size = static_cast<int32>(length) + 4;
|
return frame->CanBeSimpleBlock() ?
|
||||||
if (WriteUInt(writer, size))
|
WriteSimpleBlock(writer, frame, relative_timecode) :
|
||||||
return 0;
|
WriteBlock(writer, frame, relative_timecode,
|
||||||
|
cluster->timecode_scale());
|
||||||
if (WriteUInt(writer, static_cast<uint64>(track_number)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (SerializeInt(writer, timecode, 2))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
uint64 flags = 0;
|
|
||||||
if (is_key)
|
|
||||||
flags |= 0x80;
|
|
||||||
|
|
||||||
if (SerializeInt(writer, flags, 1))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (writer->Write(data, static_cast<uint32>(length)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
const uint64 element_size =
|
|
||||||
GetUIntSize(kMkvSimpleBlock) + GetCodedUIntSize(size) + 4 + length;
|
|
||||||
|
|
||||||
return element_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We must write the metadata (key)frame as a BlockGroup element,
|
|
||||||
// because we need to specify a duration for the frame. The
|
|
||||||
// BlockGroup element comprises the frame itself and its duration,
|
|
||||||
// and is laid out as follows:
|
|
||||||
//
|
|
||||||
// BlockGroup tag
|
|
||||||
// BlockGroup size
|
|
||||||
// Block tag
|
|
||||||
// Block size
|
|
||||||
// (the frame is the block payload)
|
|
||||||
// Duration tag
|
|
||||||
// Duration size
|
|
||||||
// (duration payload)
|
|
||||||
//
|
|
||||||
uint64 WriteMetadataBlock(IMkvWriter* writer,
|
|
||||||
const uint8* data,
|
|
||||||
uint64 length,
|
|
||||||
uint64 track_number,
|
|
||||||
int64 timecode,
|
|
||||||
uint64 duration) {
|
|
||||||
// We don't backtrack when writing to the stream, so we must
|
|
||||||
// pre-compute the BlockGroup size, by summing the sizes of each
|
|
||||||
// sub-element (the block and the duration).
|
|
||||||
|
|
||||||
// We use a single byte for the track number of the block, which
|
|
||||||
// means the block header is exactly 4 bytes.
|
|
||||||
|
|
||||||
// TODO(matthewjheaney): use EbmlMasterElementSize and WriteEbmlMasterElement
|
|
||||||
|
|
||||||
const uint64 block_payload_size = 4 + length;
|
|
||||||
const int32 block_size = GetCodedUIntSize(block_payload_size);
|
|
||||||
const uint64 block_elem_size = 1 + block_size + block_payload_size;
|
|
||||||
|
|
||||||
const int32 duration_payload_size = GetUIntSize(duration);
|
|
||||||
const int32 duration_size = GetCodedUIntSize(duration_payload_size);
|
|
||||||
const uint64 duration_elem_size = 1 + duration_size + duration_payload_size;
|
|
||||||
|
|
||||||
const uint64 blockg_payload_size = block_elem_size + duration_elem_size;
|
|
||||||
const int32 blockg_size = GetCodedUIntSize(blockg_payload_size);
|
|
||||||
const uint64 blockg_elem_size = 1 + blockg_size + blockg_payload_size;
|
|
||||||
|
|
||||||
if (WriteID(writer, kMkvBlockGroup)) // 1-byte ID size
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (WriteUInt(writer, blockg_payload_size))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Write Block element
|
|
||||||
|
|
||||||
if (WriteID(writer, kMkvBlock)) // 1-byte ID size
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (WriteUInt(writer, block_payload_size))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Byte 1 of 4
|
|
||||||
|
|
||||||
if (WriteUInt(writer, track_number))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Bytes 2 & 3 of 4
|
|
||||||
|
|
||||||
if (SerializeInt(writer, timecode, 2))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Byte 4 of 4
|
|
||||||
|
|
||||||
const uint64 flags = 0;
|
|
||||||
|
|
||||||
if (SerializeInt(writer, flags, 1))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Now write the actual frame (of metadata)
|
|
||||||
|
|
||||||
if (writer->Write(data, static_cast<uint32>(length)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Write Duration element
|
|
||||||
|
|
||||||
if (WriteID(writer, kMkvBlockDuration)) // 1-byte ID size
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (WriteUInt(writer, duration_payload_size))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (SerializeInt(writer, duration, duration_payload_size))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Note that we don't write a reference time as part of the block
|
|
||||||
// group; no reference time(s) indicates that this block is a
|
|
||||||
// keyframe. (Unlike the case for a SimpleBlock element, the header
|
|
||||||
// bits of the Block sub-element of a BlockGroup element do not
|
|
||||||
// indicate keyframe status. The keyframe status is inferred from
|
|
||||||
// the absence of reference time sub-elements.)
|
|
||||||
|
|
||||||
return blockg_elem_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes a WebM Block with Additional. The structure is as follows
|
|
||||||
// Indentation shows sub-levels
|
|
||||||
// BlockGroup
|
|
||||||
// Block
|
|
||||||
// Data
|
|
||||||
// BlockAdditions
|
|
||||||
// BlockMore
|
|
||||||
// BlockAddID
|
|
||||||
// 1 (Denotes Alpha)
|
|
||||||
// BlockAdditional
|
|
||||||
// Data
|
|
||||||
uint64 WriteBlockWithAdditional(IMkvWriter* writer,
|
|
||||||
const uint8* data,
|
|
||||||
uint64 length,
|
|
||||||
const uint8* additional,
|
|
||||||
uint64 additional_length,
|
|
||||||
uint64 add_id,
|
|
||||||
uint64 track_number,
|
|
||||||
int64 timecode,
|
|
||||||
uint64 is_key) {
|
|
||||||
if (!data || !additional || length < 1 || additional_length < 1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
const uint64 block_payload_size = 4 + length;
|
|
||||||
const uint64 block_elem_size = EbmlMasterElementSize(kMkvBlock,
|
|
||||||
block_payload_size) +
|
|
||||||
block_payload_size;
|
|
||||||
const uint64 block_additional_elem_size = EbmlElementSize(kMkvBlockAdditional,
|
|
||||||
additional,
|
|
||||||
additional_length);
|
|
||||||
const uint64 block_addid_elem_size = EbmlElementSize(kMkvBlockAddID, add_id);
|
|
||||||
|
|
||||||
const uint64 block_more_payload_size = block_addid_elem_size +
|
|
||||||
block_additional_elem_size;
|
|
||||||
const uint64 block_more_elem_size = EbmlMasterElementSize(
|
|
||||||
kMkvBlockMore,
|
|
||||||
block_more_payload_size) +
|
|
||||||
block_more_payload_size;
|
|
||||||
const uint64 block_additions_payload_size = block_more_elem_size;
|
|
||||||
const uint64 block_additions_elem_size = EbmlMasterElementSize(
|
|
||||||
kMkvBlockAdditions,
|
|
||||||
block_additions_payload_size) +
|
|
||||||
block_additions_payload_size;
|
|
||||||
const uint64 block_group_payload_size = block_elem_size +
|
|
||||||
block_additions_elem_size;
|
|
||||||
const uint64 block_group_elem_size = EbmlMasterElementSize(
|
|
||||||
kMkvBlockGroup,
|
|
||||||
block_group_payload_size) +
|
|
||||||
block_group_payload_size;
|
|
||||||
|
|
||||||
if (!WriteEbmlMasterElement(writer, kMkvBlockGroup,
|
|
||||||
block_group_payload_size))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!WriteEbmlMasterElement(writer, kMkvBlock, block_payload_size))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (WriteUInt(writer, track_number))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (SerializeInt(writer, timecode, 2))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
uint64 flags = 0;
|
|
||||||
if (is_key)
|
|
||||||
flags |= 0x80;
|
|
||||||
if (SerializeInt(writer, flags, 1))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (writer->Write(data, static_cast<uint32>(length)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!WriteEbmlMasterElement(writer, kMkvBlockAdditions,
|
|
||||||
block_additions_payload_size))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!WriteEbmlMasterElement(writer, kMkvBlockMore, block_more_payload_size))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!WriteEbmlElement(writer, kMkvBlockAddID, add_id))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!WriteEbmlElement(writer, kMkvBlockAdditional,
|
|
||||||
additional, additional_length))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return block_group_elem_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
|
uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
|
||||||
@@ -558,9 +553,9 @@ uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Subtract one for the void ID and the coded size.
|
// Subtract one for the void ID and the coded size.
|
||||||
uint64 void_entry_size = size - 1 - GetCodedUIntSize(size-1);
|
uint64 void_entry_size = size - 1 - GetCodedUIntSize(size - 1);
|
||||||
uint64 void_size = EbmlMasterElementSize(kMkvVoid, void_entry_size) +
|
uint64 void_size =
|
||||||
void_entry_size;
|
EbmlMasterElementSize(kMkvVoid, void_entry_size) + void_entry_size;
|
||||||
|
|
||||||
if (void_size != size)
|
if (void_size != size)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -600,16 +595,18 @@ void GetVersion(int32* major, int32* minor, int32* build, int32* revision) {
|
|||||||
|
|
||||||
mkvmuxer::uint64 mkvmuxer::MakeUID(unsigned int* seed) {
|
mkvmuxer::uint64 mkvmuxer::MakeUID(unsigned int* seed) {
|
||||||
uint64 uid = 0;
|
uint64 uid = 0;
|
||||||
|
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
srand(*seed);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (int i = 0; i < 7; ++i) { // avoid problems with 8-byte values
|
for (int i = 0; i < 7; ++i) { // avoid problems with 8-byte values
|
||||||
uid <<= 8;
|
uid <<= 8;
|
||||||
|
|
||||||
// TODO(fgalligan): Move random number generation to platform specific code.
|
// TODO(fgalligan): Move random number generation to platform specific code.
|
||||||
#ifdef _WIN32
|
#ifdef _MSC_VER
|
||||||
(void)seed;
|
(void)seed;
|
||||||
unsigned int random_value;
|
const int32 nn = rand();
|
||||||
const errno_t e = rand_s(&random_value);
|
|
||||||
(void)e;
|
|
||||||
const int32 nn = random_value;
|
|
||||||
#elif __ANDROID__
|
#elif __ANDROID__
|
||||||
int32 temp_num = 1;
|
int32 temp_num = 1;
|
||||||
int fd = open("/dev/urandom", O_RDONLY);
|
int fd = open("/dev/urandom", O_RDONLY);
|
||||||
@@ -618,6 +615,8 @@ mkvmuxer::uint64 mkvmuxer::MakeUID(unsigned int* seed) {
|
|||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
const int32 nn = temp_num;
|
const int32 nn = temp_num;
|
||||||
|
#elif defined __MINGW32__
|
||||||
|
const int32 nn = rand();
|
||||||
#else
|
#else
|
||||||
const int32 nn = rand_r(seed);
|
const int32 nn = rand_r(seed);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#ifndef MKVMUXERUTIL_HPP
|
#ifndef MKVMUXERUTIL_HPP
|
||||||
#define MKVMUXERUTIL_HPP
|
#define MKVMUXERUTIL_HPP
|
||||||
|
|
||||||
|
#include "mkvmuxer.hpp"
|
||||||
#include "mkvmuxertypes.hpp"
|
#include "mkvmuxertypes.hpp"
|
||||||
|
|
||||||
namespace mkvmuxer {
|
namespace mkvmuxer {
|
||||||
@@ -23,12 +24,15 @@ int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size);
|
|||||||
|
|
||||||
// Returns the size in bytes of the element.
|
// Returns the size in bytes of the element.
|
||||||
int32 GetUIntSize(uint64 value);
|
int32 GetUIntSize(uint64 value);
|
||||||
|
int32 GetIntSize(int64 value);
|
||||||
int32 GetCodedUIntSize(uint64 value);
|
int32 GetCodedUIntSize(uint64 value);
|
||||||
uint64 EbmlMasterElementSize(uint64 type, uint64 value);
|
uint64 EbmlMasterElementSize(uint64 type, uint64 value);
|
||||||
|
uint64 EbmlElementSize(uint64 type, int64 value);
|
||||||
uint64 EbmlElementSize(uint64 type, uint64 value);
|
uint64 EbmlElementSize(uint64 type, uint64 value);
|
||||||
uint64 EbmlElementSize(uint64 type, float value);
|
uint64 EbmlElementSize(uint64 type, float value);
|
||||||
uint64 EbmlElementSize(uint64 type, const char* value);
|
uint64 EbmlElementSize(uint64 type, const char* value);
|
||||||
uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size);
|
uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size);
|
||||||
|
uint64 EbmlDateElementSize(uint64 type);
|
||||||
|
|
||||||
// Creates an EBML coded number from |value| and writes it out. The size of
|
// Creates an EBML coded number from |value| and writes it out. The size of
|
||||||
// the coded number is determined by the value of |value|. |value| must not
|
// the coded number is determined by the value of |value|. |value| must not
|
||||||
@@ -49,69 +53,17 @@ int32 WriteID(IMkvWriter* writer, uint64 type);
|
|||||||
|
|
||||||
// Output an Mkv non-master element. Returns true if the element was written.
|
// Output an Mkv non-master element. Returns true if the element was written.
|
||||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value);
|
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value);
|
||||||
|
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, int64 value);
|
||||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value);
|
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value);
|
||||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value);
|
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value);
|
||||||
bool WriteEbmlElement(IMkvWriter* writer,
|
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const uint8* value,
|
||||||
uint64 type,
|
|
||||||
const uint8* value,
|
|
||||||
uint64 size);
|
uint64 size);
|
||||||
|
bool WriteEbmlDateElement(IMkvWriter* writer, uint64 type, int64 value);
|
||||||
|
|
||||||
// Output an Mkv Simple Block.
|
// Output a Mkv Frame. It decides the correct element to write (Block vs
|
||||||
// Inputs:
|
// SimpleBlock) based on the parameters of the Frame.
|
||||||
// data: Pointer to the data.
|
uint64 WriteFrame(IMkvWriter* writer, const Frame* const frame,
|
||||||
// length: Length of the data.
|
Cluster* cluster);
|
||||||
// track_number: Track to add the data to. Value returned by Add track
|
|
||||||
// functions. Only values in the range [1, 126] are
|
|
||||||
// permitted.
|
|
||||||
// timecode: Relative timecode of the Block. Only values in the
|
|
||||||
// range [0, 2^15) are permitted.
|
|
||||||
// is_key: Non-zero value specifies that frame is a key frame.
|
|
||||||
uint64 WriteSimpleBlock(IMkvWriter* writer,
|
|
||||||
const uint8* data,
|
|
||||||
uint64 length,
|
|
||||||
uint64 track_number,
|
|
||||||
int64 timecode,
|
|
||||||
uint64 is_key);
|
|
||||||
|
|
||||||
// Output a metadata keyframe, using a Block Group element.
|
|
||||||
// Inputs:
|
|
||||||
// data: Pointer to the (meta)data.
|
|
||||||
// length: Length of the (meta)data.
|
|
||||||
// track_number: Track to add the data to. Value returned by Add track
|
|
||||||
// functions. Only values in the range [1, 126] are
|
|
||||||
// permitted.
|
|
||||||
// timecode Timecode of frame, relative to cluster timecode. Only
|
|
||||||
// values in the range [0, 2^15) are permitted.
|
|
||||||
// duration_timecode Duration of frame, using timecode units.
|
|
||||||
uint64 WriteMetadataBlock(IMkvWriter* writer,
|
|
||||||
const uint8* data,
|
|
||||||
uint64 length,
|
|
||||||
uint64 track_number,
|
|
||||||
int64 timecode,
|
|
||||||
uint64 duration_timecode);
|
|
||||||
|
|
||||||
// Output an Mkv Block with BlockAdditional data.
|
|
||||||
// Inputs:
|
|
||||||
// data: Pointer to the data.
|
|
||||||
// length: Length of the data.
|
|
||||||
// additional: Pointer to the additional data
|
|
||||||
// additional_length: Length of the additional data.
|
|
||||||
// add_id: Value of BlockAddID element.
|
|
||||||
// track_number: Track to add the data to. Value returned by Add track
|
|
||||||
// functions. Only values in the range [1, 126] are
|
|
||||||
// permitted.
|
|
||||||
// timecode: Relative timecode of the Block. Only values in the
|
|
||||||
// range [0, 2^15) are permitted.
|
|
||||||
// is_key: Non-zero value specifies that frame is a key frame.
|
|
||||||
uint64 WriteBlockWithAdditional(IMkvWriter* writer,
|
|
||||||
const uint8* data,
|
|
||||||
uint64 length,
|
|
||||||
const uint8* additional,
|
|
||||||
uint64 additional_length,
|
|
||||||
uint64 add_id,
|
|
||||||
uint64 track_number,
|
|
||||||
int64 timecode,
|
|
||||||
uint64 is_key);
|
|
||||||
|
|
||||||
// Output a void element. |size| must be the entire size in bytes that will be
|
// Output a void element. |size| must be the entire size in bytes that will be
|
||||||
// void. The function will calculate the size of the void header and subtract
|
// void. The function will calculate the size of the void header and subtract
|
||||||
@@ -126,6 +78,6 @@ void GetVersion(int32* major, int32* minor, int32* build, int32* revision);
|
|||||||
// the random-number generator (see POSIX rand_r() for semantics).
|
// the random-number generator (see POSIX rand_r() for semantics).
|
||||||
uint64 MakeUID(unsigned int* seed);
|
uint64 MakeUID(unsigned int* seed);
|
||||||
|
|
||||||
} //end namespace mkvmuxer
|
} // end namespace mkvmuxer
|
||||||
|
|
||||||
#endif // MKVMUXERUTIL_HPP
|
#endif // MKVMUXERUTIL_HPP
|
||||||
|
|||||||
14936
mkvparser.cpp
14936
mkvparser.cpp
File diff suppressed because it is too large
Load Diff
1655
mkvparser.hpp
1655
mkvparser.hpp
File diff suppressed because it is too large
Load Diff
178
mkvreader.cpp
178
mkvreader.cpp
@@ -10,119 +10,123 @@
|
|||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
namespace mkvparser
|
namespace mkvparser {
|
||||||
{
|
|
||||||
|
|
||||||
MkvReader::MkvReader() :
|
MkvReader::MkvReader() : m_file(NULL), reader_owns_file_(true) {}
|
||||||
m_file(NULL)
|
|
||||||
{
|
MkvReader::MkvReader(FILE* fp) : m_file(fp), reader_owns_file_(false) {
|
||||||
|
GetFileSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
MkvReader::~MkvReader()
|
MkvReader::~MkvReader() {
|
||||||
{
|
if (reader_owns_file_)
|
||||||
Close();
|
Close();
|
||||||
|
m_file = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MkvReader::Open(const char* fileName)
|
int MkvReader::Open(const char* fileName) {
|
||||||
{
|
if (fileName == NULL)
|
||||||
if (fileName == NULL)
|
return -1;
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (m_file)
|
if (m_file)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef _MSC_VER
|
||||||
const errno_t e = fopen_s(&m_file, fileName, "rb");
|
const errno_t e = fopen_s(&m_file, fileName, "rb");
|
||||||
|
|
||||||
if (e)
|
if (e)
|
||||||
return -1; //error
|
return -1; // error
|
||||||
#else
|
#else
|
||||||
m_file = fopen(fileName, "rb");
|
m_file = fopen(fileName, "rb");
|
||||||
|
|
||||||
if (m_file == NULL)
|
if (m_file == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
#endif
|
||||||
|
return !GetFileSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MkvReader::GetFileSize() {
|
||||||
|
if (m_file == NULL)
|
||||||
|
return false;
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
int status = _fseeki64(m_file, 0L, SEEK_END);
|
||||||
|
|
||||||
|
if (status)
|
||||||
|
return false; // error
|
||||||
|
|
||||||
|
m_length = _ftelli64(m_file);
|
||||||
|
#else
|
||||||
|
fseek(m_file, 0L, SEEK_END);
|
||||||
|
m_length = ftell(m_file);
|
||||||
|
#endif
|
||||||
|
assert(m_length >= 0);
|
||||||
|
|
||||||
|
if (m_length < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
status = _fseeki64(m_file, 0L, SEEK_SET);
|
||||||
|
|
||||||
|
if (status)
|
||||||
|
return false; // error
|
||||||
|
#else
|
||||||
|
fseek(m_file, 0L, SEEK_SET);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WIN32
|
return true;
|
||||||
int status = _fseeki64(m_file, 0L, SEEK_END);
|
}
|
||||||
|
|
||||||
if (status)
|
void MkvReader::Close() {
|
||||||
return -1; //error
|
if (m_file != NULL) {
|
||||||
|
fclose(m_file);
|
||||||
|
m_file = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_length = _ftelli64(m_file);
|
int MkvReader::Length(long long* total, long long* available) {
|
||||||
#else
|
if (m_file == NULL)
|
||||||
fseek(m_file, 0L, SEEK_END);
|
return -1;
|
||||||
m_length = ftell(m_file);
|
|
||||||
#endif
|
|
||||||
assert(m_length >= 0);
|
|
||||||
|
|
||||||
#ifdef WIN32
|
if (total)
|
||||||
status = _fseeki64(m_file, 0L, SEEK_SET);
|
*total = m_length;
|
||||||
|
|
||||||
if (status)
|
if (available)
|
||||||
return -1; //error
|
*available = m_length;
|
||||||
#else
|
|
||||||
fseek(m_file, 0L, SEEK_SET);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MkvReader::Read(long long offset, long len, unsigned char* buffer) {
|
||||||
|
if (m_file == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (offset < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (len < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
void MkvReader::Close()
|
if (offset >= m_length)
|
||||||
{
|
return -1;
|
||||||
if (m_file != NULL)
|
|
||||||
{
|
|
||||||
fclose(m_file);
|
|
||||||
m_file = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int MkvReader::Length(long long* total, long long* available)
|
#ifdef _MSC_VER
|
||||||
{
|
const int status = _fseeki64(m_file, offset, SEEK_SET);
|
||||||
if (m_file == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (total)
|
if (status)
|
||||||
*total = m_length;
|
return -1; // error
|
||||||
|
|
||||||
if (available)
|
|
||||||
*available = m_length;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MkvReader::Read(long long offset, long len, unsigned char* buffer)
|
|
||||||
{
|
|
||||||
if (m_file == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (offset < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (len < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (len == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (offset >= m_length)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
const int status = _fseeki64(m_file, offset, SEEK_SET);
|
|
||||||
|
|
||||||
if (status)
|
|
||||||
return -1; //error
|
|
||||||
#else
|
#else
|
||||||
fseek(m_file, offset, SEEK_SET);
|
fseek(m_file, offset, SEEK_SET);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const size_t size = fread(buffer, 1, len, m_file);
|
const size_t size = fread(buffer, 1, len, m_file);
|
||||||
|
|
||||||
if (size < size_t(len))
|
if (size < size_t(len))
|
||||||
return -1; //error
|
return -1; // error
|
||||||
|
|
||||||
return 0; //success
|
return 0; // success
|
||||||
}
|
}
|
||||||
|
|
||||||
} //end namespace mkvparser
|
} // end namespace mkvparser
|
||||||
|
|||||||
@@ -12,27 +12,34 @@
|
|||||||
#include "mkvparser.hpp"
|
#include "mkvparser.hpp"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
namespace mkvparser
|
namespace mkvparser {
|
||||||
{
|
|
||||||
|
|
||||||
class MkvReader : public IMkvReader
|
class MkvReader : public IMkvReader {
|
||||||
{
|
public:
|
||||||
MkvReader(const MkvReader&);
|
MkvReader();
|
||||||
MkvReader& operator=(const MkvReader&);
|
explicit MkvReader(FILE* fp);
|
||||||
public:
|
virtual ~MkvReader();
|
||||||
MkvReader();
|
|
||||||
virtual ~MkvReader();
|
|
||||||
|
|
||||||
int Open(const char*);
|
int Open(const char*);
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
virtual int Read(long long position, long length, unsigned char* buffer);
|
virtual int Read(long long position, long length, unsigned char* buffer);
|
||||||
virtual int Length(long long* total, long long* available);
|
virtual int Length(long long* total, long long* available);
|
||||||
private:
|
|
||||||
long long m_length;
|
private:
|
||||||
FILE* m_file;
|
MkvReader(const MkvReader&);
|
||||||
|
MkvReader& operator=(const MkvReader&);
|
||||||
|
|
||||||
|
// Determines the size of the file. This is called either by the constructor
|
||||||
|
// or by the Open function depending on file ownership. Returns true on
|
||||||
|
// success.
|
||||||
|
bool GetFileSize();
|
||||||
|
|
||||||
|
long long m_length;
|
||||||
|
FILE* m_file;
|
||||||
|
bool reader_owns_file_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} //end namespace mkvparser
|
} // end namespace mkvparser
|
||||||
|
|
||||||
#endif //MKVREADER_HPP
|
#endif // MKVREADER_HPP
|
||||||
|
|||||||
@@ -16,12 +16,11 @@
|
|||||||
|
|
||||||
namespace mkvmuxer {
|
namespace mkvmuxer {
|
||||||
|
|
||||||
MkvWriter::MkvWriter() : file_(NULL) {
|
MkvWriter::MkvWriter() : file_(NULL), writer_owns_file_(true) {}
|
||||||
}
|
|
||||||
|
|
||||||
MkvWriter::~MkvWriter() {
|
MkvWriter::MkvWriter(FILE* fp) : file_(fp), writer_owns_file_(false) {}
|
||||||
Close();
|
|
||||||
}
|
MkvWriter::~MkvWriter() { Close(); }
|
||||||
|
|
||||||
int32 MkvWriter::Write(const void* buffer, uint32 length) {
|
int32 MkvWriter::Write(const void* buffer, uint32 length) {
|
||||||
if (!file_)
|
if (!file_)
|
||||||
@@ -56,10 +55,10 @@ bool MkvWriter::Open(const char* filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MkvWriter::Close() {
|
void MkvWriter::Close() {
|
||||||
if (file_) {
|
if (file_ && writer_owns_file_) {
|
||||||
fclose(file_);
|
fclose(file_);
|
||||||
file_ = NULL;
|
|
||||||
}
|
}
|
||||||
|
file_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64 MkvWriter::Position() const {
|
int64 MkvWriter::Position() const {
|
||||||
@@ -67,9 +66,9 @@ int64 MkvWriter::Position() const {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
return _ftelli64(file_);
|
return _ftelli64(file_);
|
||||||
#else
|
#else
|
||||||
return ftell(file_);
|
return ftell(file_);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,17 +77,14 @@ int32 MkvWriter::Position(int64 position) {
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
return _fseeki64(file_, position, SEEK_SET);
|
return _fseeki64(file_, position, SEEK_SET);
|
||||||
#else
|
#else
|
||||||
return fseek(file_, position, SEEK_SET);
|
return fseek(file_, position, SEEK_SET);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MkvWriter::Seekable() const {
|
bool MkvWriter::Seekable() const { return true; }
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MkvWriter::ElementStartNotify(uint64, int64) {
|
void MkvWriter::ElementStartNotify(uint64, int64) {}
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace mkvmuxer
|
} // namespace mkvmuxer
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ namespace mkvmuxer {
|
|||||||
class MkvWriter : public IMkvWriter {
|
class MkvWriter : public IMkvWriter {
|
||||||
public:
|
public:
|
||||||
MkvWriter();
|
MkvWriter();
|
||||||
|
explicit MkvWriter(FILE* fp);
|
||||||
virtual ~MkvWriter();
|
virtual ~MkvWriter();
|
||||||
|
|
||||||
// IMkvWriter interface
|
// IMkvWriter interface
|
||||||
@@ -40,10 +41,11 @@ class MkvWriter : public IMkvWriter {
|
|||||||
private:
|
private:
|
||||||
// File handle to output file.
|
// File handle to output file.
|
||||||
FILE* file_;
|
FILE* file_;
|
||||||
|
bool writer_owns_file_;
|
||||||
|
|
||||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(MkvWriter);
|
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(MkvWriter);
|
||||||
};
|
};
|
||||||
|
|
||||||
} //end namespace mkvmuxer
|
} // end namespace mkvmuxer
|
||||||
|
|
||||||
#endif // MKVWRITER_HPP
|
#endif // MKVWRITER_HPP
|
||||||
|
|||||||
627
sample.cpp
627
sample.cpp
@@ -6,310 +6,361 @@
|
|||||||
// in the file PATENTS. All contributing project authors may
|
// in the file PATENTS. All contributing project authors may
|
||||||
// be found in the AUTHORS file in the root of the source tree.
|
// be found in the AUTHORS file in the root of the source tree.
|
||||||
//
|
//
|
||||||
// This sample application demonstrates how to use the matroska parser
|
// This sample application demonstrates how to use the Matroska parser
|
||||||
// library, which allows clients to handle a matroska format file.
|
// library, which allows clients to handle a Matroska format file.
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "mkvreader.hpp"
|
#include "mkvreader.hpp"
|
||||||
#include "mkvparser.hpp"
|
#include "mkvparser.hpp"
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
// Silences these warnings:
|
// Disable MSVC warnings that suggest making code non-portable.
|
||||||
// warning C4996: 'mbstowcs': This function or variable may be unsafe. Consider
|
#pragma warning(disable : 4996)
|
||||||
// using mbstowcs_s instead. To disable deprecation, use
|
|
||||||
// _CRT_SECURE_NO_WARNINGS. See online help for details.
|
|
||||||
// Fixing this warning requires use of a function available only on Windows,
|
|
||||||
// and this sample code must support non-windows platforms.
|
|
||||||
#pragma warning(disable:4996)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const wchar_t* utf8towcs(const char* str)
|
static const wchar_t* utf8towcs(const char* str) {
|
||||||
{
|
if (str == NULL)
|
||||||
if (str == NULL)
|
return NULL;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
//TODO: this probably requires that the locale be
|
// TODO: this probably requires that the locale be
|
||||||
//configured somehow:
|
// configured somehow:
|
||||||
|
|
||||||
const size_t size = mbstowcs(NULL, str, 0);
|
const size_t size = mbstowcs(NULL, str, 0);
|
||||||
|
|
||||||
if (size == 0)
|
if (size == 0 || size == static_cast<size_t>(-1))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
wchar_t* const val = new wchar_t[size+1];
|
wchar_t* const val = new (std::nothrow) wchar_t[size + 1];
|
||||||
|
if (val == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
mbstowcs(val, str, size);
|
mbstowcs(val, str, size);
|
||||||
val[size] = L'\0';
|
val[size] = L'\0';
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InputHasCues(const mkvparser::Segment* const segment) {
|
||||||
|
const mkvparser::Cues* const cues = segment->GetCues();
|
||||||
|
if (cues == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
while (!cues->DoneParsing())
|
||||||
{
|
cues->LoadCuePoint();
|
||||||
if (argc == 1)
|
|
||||||
{
|
|
||||||
printf("\t\t\tMkv Parser Sample Application\n");
|
|
||||||
printf("\t\t\tUsage: \n");
|
|
||||||
printf("\t\t\t ./sample [input file] \n");
|
|
||||||
printf("\t\t\t ./sample sample.mkv \n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace mkvparser;
|
const mkvparser::CuePoint* const cue_point = cues->GetFirst();
|
||||||
|
if (cue_point == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
MkvReader reader;
|
return true;
|
||||||
|
}
|
||||||
if (reader.Open(argv[1]))
|
|
||||||
{
|
int main(int argc, char* argv[]) {
|
||||||
printf("\n Filename is invalid or error while opening.\n");
|
if (argc == 1) {
|
||||||
return -1;
|
printf("\t\t\tMkv Parser Sample Application\n");
|
||||||
}
|
printf("\t\t\tUsage: \n");
|
||||||
|
printf("\t\t\t ./sample [input file] \n");
|
||||||
int maj, min, build, rev;
|
printf("\t\t\t ./sample sample.mkv \n");
|
||||||
|
return -1;
|
||||||
GetVersion(maj, min, build, rev);
|
}
|
||||||
printf("\t\t libmkv verison: %d.%d.%d.%d\n", maj, min, build, rev);
|
|
||||||
|
using namespace mkvparser;
|
||||||
long long pos = 0;
|
|
||||||
|
MkvReader reader;
|
||||||
EBMLHeader ebmlHeader;
|
|
||||||
|
if (reader.Open(argv[1])) {
|
||||||
ebmlHeader.Parse(&reader, pos);
|
printf("\n Filename is invalid or error while opening.\n");
|
||||||
|
return -1;
|
||||||
printf("\t\t\t EBML Header\n");
|
}
|
||||||
printf("\t\tEBML Version\t\t: %lld\n", ebmlHeader.m_version);
|
|
||||||
printf("\t\tEBML MaxIDLength\t: %lld\n", ebmlHeader.m_maxIdLength);
|
int maj, min, build, rev;
|
||||||
printf("\t\tEBML MaxSizeLength\t: %lld\n", ebmlHeader.m_maxSizeLength);
|
|
||||||
printf("\t\tDoc Type\t\t: %s\n", ebmlHeader.m_docType);
|
GetVersion(maj, min, build, rev);
|
||||||
printf("\t\tPos\t\t\t: %lld\n", pos);
|
printf("\t\t libmkv verison: %d.%d.%d.%d\n", maj, min, build, rev);
|
||||||
|
|
||||||
typedef mkvparser::Segment seg_t;
|
long long pos = 0;
|
||||||
seg_t* pSegment_;
|
|
||||||
|
EBMLHeader ebmlHeader;
|
||||||
long long ret = seg_t::CreateInstance(&reader, pos, pSegment_);
|
|
||||||
if (ret)
|
long long ret = ebmlHeader.Parse(&reader, pos);
|
||||||
{
|
if (ret < 0) {
|
||||||
printf("\n Segment::CreateInstance() failed.");
|
printf("\n EBMLHeader::Parse() failed.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::auto_ptr<seg_t> pSegment(pSegment_);
|
printf("\t\t\t EBML Header\n");
|
||||||
|
printf("\t\tEBML Version\t\t: %lld\n", ebmlHeader.m_version);
|
||||||
ret = pSegment->Load();
|
printf("\t\tEBML MaxIDLength\t: %lld\n", ebmlHeader.m_maxIdLength);
|
||||||
if (ret < 0)
|
printf("\t\tEBML MaxSizeLength\t: %lld\n", ebmlHeader.m_maxSizeLength);
|
||||||
{
|
printf("\t\tDoc Type\t\t: %s\n", ebmlHeader.m_docType);
|
||||||
printf("\n Segment::Load() failed.");
|
printf("\t\tPos\t\t\t: %lld\n", pos);
|
||||||
return -1;
|
|
||||||
}
|
typedef mkvparser::Segment seg_t;
|
||||||
|
seg_t* pSegment_;
|
||||||
const SegmentInfo* const pSegmentInfo = pSegment->GetInfo();
|
|
||||||
|
ret = seg_t::CreateInstance(&reader, pos, pSegment_);
|
||||||
const long long timeCodeScale = pSegmentInfo->GetTimeCodeScale();
|
if (ret) {
|
||||||
const long long duration_ns = pSegmentInfo->GetDuration();
|
printf("\n Segment::CreateInstance() failed.");
|
||||||
|
return -1;
|
||||||
const char* const pTitle_ = pSegmentInfo->GetTitleAsUTF8();
|
}
|
||||||
const wchar_t* const pTitle = utf8towcs(pTitle_);
|
|
||||||
|
const std::auto_ptr<seg_t> pSegment(pSegment_);
|
||||||
const char* const pMuxingApp_ = pSegmentInfo->GetMuxingAppAsUTF8();
|
|
||||||
const wchar_t* const pMuxingApp = utf8towcs(pMuxingApp_);
|
ret = pSegment->Load();
|
||||||
|
if (ret < 0) {
|
||||||
const char* const pWritingApp_ = pSegmentInfo->GetWritingAppAsUTF8();
|
printf("\n Segment::Load() failed.");
|
||||||
const wchar_t* const pWritingApp = utf8towcs(pWritingApp_);
|
return -1;
|
||||||
|
}
|
||||||
printf("\n");
|
|
||||||
printf("\t\t\t Segment Info\n");
|
const SegmentInfo* const pSegmentInfo = pSegment->GetInfo();
|
||||||
printf("\t\tTimeCodeScale\t\t: %lld \n", timeCodeScale);
|
if (pSegmentInfo == NULL) {
|
||||||
printf("\t\tDuration\t\t: %lld\n", duration_ns);
|
printf("\n Segment::GetInfo() failed.");
|
||||||
|
return -1;
|
||||||
const double duration_sec = double(duration_ns) / 1000000000;
|
}
|
||||||
printf("\t\tDuration(secs)\t\t: %7.3lf\n", duration_sec);
|
|
||||||
|
const long long timeCodeScale = pSegmentInfo->GetTimeCodeScale();
|
||||||
if (pTitle == NULL)
|
const long long duration_ns = pSegmentInfo->GetDuration();
|
||||||
printf("\t\tTrack Name\t\t: NULL\n");
|
|
||||||
else
|
const char* const pTitle_ = pSegmentInfo->GetTitleAsUTF8();
|
||||||
{
|
const wchar_t* const pTitle = utf8towcs(pTitle_);
|
||||||
printf("\t\tTrack Name\t\t: %ls\n", pTitle);
|
|
||||||
delete [] pTitle;
|
const char* const pMuxingApp_ = pSegmentInfo->GetMuxingAppAsUTF8();
|
||||||
}
|
const wchar_t* const pMuxingApp = utf8towcs(pMuxingApp_);
|
||||||
|
|
||||||
|
const char* const pWritingApp_ = pSegmentInfo->GetWritingAppAsUTF8();
|
||||||
if (pMuxingApp == NULL)
|
const wchar_t* const pWritingApp = utf8towcs(pWritingApp_);
|
||||||
printf("\t\tMuxing App\t\t: NULL\n");
|
|
||||||
else
|
printf("\n");
|
||||||
{
|
printf("\t\t\t Segment Info\n");
|
||||||
printf("\t\tMuxing App\t\t: %ls\n", pMuxingApp);
|
printf("\t\tTimeCodeScale\t\t: %lld \n", timeCodeScale);
|
||||||
delete [] pMuxingApp;
|
printf("\t\tDuration\t\t: %lld\n", duration_ns);
|
||||||
}
|
|
||||||
|
const double duration_sec = double(duration_ns) / 1000000000;
|
||||||
if (pWritingApp == NULL)
|
printf("\t\tDuration(secs)\t\t: %7.3lf\n", duration_sec);
|
||||||
printf("\t\tWriting App\t\t: NULL\n");
|
|
||||||
else
|
if (pTitle == NULL)
|
||||||
{
|
printf("\t\tTrack Name\t\t: NULL\n");
|
||||||
printf("\t\tWriting App\t\t: %ls\n", pWritingApp);
|
else {
|
||||||
delete [] pWritingApp;
|
printf("\t\tTrack Name\t\t: %ls\n", pTitle);
|
||||||
}
|
delete[] pTitle;
|
||||||
|
}
|
||||||
// pos of segment payload
|
|
||||||
printf("\t\tPosition(Segment)\t: %lld\n", pSegment->m_start);
|
if (pMuxingApp == NULL)
|
||||||
|
printf("\t\tMuxing App\t\t: NULL\n");
|
||||||
// size of segment payload
|
else {
|
||||||
printf("\t\tSize(Segment)\t\t: %lld\n", pSegment->m_size);
|
printf("\t\tMuxing App\t\t: %ls\n", pMuxingApp);
|
||||||
|
delete[] pMuxingApp;
|
||||||
const mkvparser::Tracks* pTracks = pSegment->GetTracks();
|
}
|
||||||
|
|
||||||
unsigned long i = 0;
|
if (pWritingApp == NULL)
|
||||||
const unsigned long j = pTracks->GetTracksCount();
|
printf("\t\tWriting App\t\t: NULL\n");
|
||||||
|
else {
|
||||||
printf("\n\t\t\t Track Info\n");
|
printf("\t\tWriting App\t\t: %ls\n", pWritingApp);
|
||||||
|
delete[] pWritingApp;
|
||||||
while (i != j)
|
}
|
||||||
{
|
|
||||||
const Track* const pTrack = pTracks->GetTrackByIndex(i++);
|
// pos of segment payload
|
||||||
|
printf("\t\tPosition(Segment)\t: %lld\n", pSegment->m_start);
|
||||||
if (pTrack == NULL)
|
|
||||||
continue;
|
// size of segment payload
|
||||||
|
printf("\t\tSize(Segment)\t\t: %lld\n", pSegment->m_size);
|
||||||
const long trackType = pTrack->GetType();
|
|
||||||
const long trackNumber = pTrack->GetNumber();
|
const mkvparser::Tracks* pTracks = pSegment->GetTracks();
|
||||||
const unsigned long long trackUid = pTrack->GetUid();
|
|
||||||
const wchar_t* const pTrackName = utf8towcs(pTrack->GetNameAsUTF8());
|
unsigned long track_num = 0;
|
||||||
|
const unsigned long num_tracks = pTracks->GetTracksCount();
|
||||||
printf("\t\tTrack Type\t\t: %ld\n", trackType);
|
|
||||||
printf("\t\tTrack Number\t\t: %ld\n", trackNumber);
|
printf("\n\t\t\t Track Info\n");
|
||||||
printf("\t\tTrack Uid\t\t: %lld\n", trackUid);
|
|
||||||
|
while (track_num != num_tracks) {
|
||||||
if (pTrackName == NULL)
|
const Track* const pTrack = pTracks->GetTrackByIndex(track_num++);
|
||||||
printf("\t\tTrack Name\t\t: NULL\n");
|
|
||||||
else
|
if (pTrack == NULL)
|
||||||
{
|
continue;
|
||||||
printf("\t\tTrack Name\t\t: %ls \n", pTrackName);
|
|
||||||
delete [] pTrackName;
|
const long trackType = pTrack->GetType();
|
||||||
}
|
const long trackNumber = pTrack->GetNumber();
|
||||||
|
const unsigned long long trackUid = pTrack->GetUid();
|
||||||
const char* const pCodecId = pTrack->GetCodecId();
|
const wchar_t* const pTrackName = utf8towcs(pTrack->GetNameAsUTF8());
|
||||||
|
|
||||||
if (pCodecId == NULL)
|
printf("\t\tTrack Type\t\t: %ld\n", trackType);
|
||||||
printf("\t\tCodec Id\t\t: NULL\n");
|
printf("\t\tTrack Number\t\t: %ld\n", trackNumber);
|
||||||
else
|
printf("\t\tTrack Uid\t\t: %lld\n", trackUid);
|
||||||
printf("\t\tCodec Id\t\t: %s\n", pCodecId);
|
|
||||||
|
if (pTrackName == NULL)
|
||||||
const char* const pCodecName_ = pTrack->GetCodecNameAsUTF8();
|
printf("\t\tTrack Name\t\t: NULL\n");
|
||||||
const wchar_t* const pCodecName = utf8towcs(pCodecName_);
|
else {
|
||||||
|
printf("\t\tTrack Name\t\t: %ls \n", pTrackName);
|
||||||
if (pCodecName == NULL)
|
delete[] pTrackName;
|
||||||
printf("\t\tCodec Name\t\t: NULL\n");
|
}
|
||||||
else
|
|
||||||
{
|
const char* const pCodecId = pTrack->GetCodecId();
|
||||||
printf("\t\tCodec Name\t\t: %ls\n", pCodecName);
|
|
||||||
delete [] pCodecName;
|
if (pCodecId == NULL)
|
||||||
}
|
printf("\t\tCodec Id\t\t: NULL\n");
|
||||||
|
else
|
||||||
if (trackType == mkvparser::Track::kVideo)
|
printf("\t\tCodec Id\t\t: %s\n", pCodecId);
|
||||||
{
|
|
||||||
const VideoTrack* const pVideoTrack =
|
const char* const pCodecName_ = pTrack->GetCodecNameAsUTF8();
|
||||||
static_cast<const VideoTrack*>(pTrack);
|
const wchar_t* const pCodecName = utf8towcs(pCodecName_);
|
||||||
|
|
||||||
const long long width = pVideoTrack->GetWidth();
|
if (pCodecName == NULL)
|
||||||
printf("\t\tVideo Width\t\t: %lld\n", width);
|
printf("\t\tCodec Name\t\t: NULL\n");
|
||||||
|
else {
|
||||||
const long long height = pVideoTrack->GetHeight();
|
printf("\t\tCodec Name\t\t: %ls\n", pCodecName);
|
||||||
printf("\t\tVideo Height\t\t: %lld\n", height);
|
delete[] pCodecName;
|
||||||
|
}
|
||||||
const double rate = pVideoTrack->GetFrameRate();
|
|
||||||
printf("\t\tVideo Rate\t\t: %f\n",rate);
|
if (trackType == mkvparser::Track::kVideo) {
|
||||||
}
|
const VideoTrack* const pVideoTrack =
|
||||||
|
static_cast<const VideoTrack*>(pTrack);
|
||||||
if (trackType == mkvparser::Track::kAudio)
|
|
||||||
{
|
const long long width = pVideoTrack->GetWidth();
|
||||||
const AudioTrack* const pAudioTrack =
|
printf("\t\tVideo Width\t\t: %lld\n", width);
|
||||||
static_cast<const AudioTrack*>(pTrack);
|
|
||||||
|
const long long height = pVideoTrack->GetHeight();
|
||||||
const long long channels = pAudioTrack->GetChannels();
|
printf("\t\tVideo Height\t\t: %lld\n", height);
|
||||||
printf("\t\tAudio Channels\t\t: %lld\n", channels);
|
|
||||||
|
const double rate = pVideoTrack->GetFrameRate();
|
||||||
const long long bitDepth = pAudioTrack->GetBitDepth();
|
printf("\t\tVideo Rate\t\t: %f\n", rate);
|
||||||
printf("\t\tAudio BitDepth\t\t: %lld\n", bitDepth);
|
}
|
||||||
|
|
||||||
const double sampleRate = pAudioTrack->GetSamplingRate();
|
if (trackType == mkvparser::Track::kAudio) {
|
||||||
printf("\t\tAddio Sample Rate\t: %.3f\n", sampleRate);
|
const AudioTrack* const pAudioTrack =
|
||||||
}
|
static_cast<const AudioTrack*>(pTrack);
|
||||||
}
|
|
||||||
|
const long long channels = pAudioTrack->GetChannels();
|
||||||
printf("\n\n\t\t\t Cluster Info\n");
|
printf("\t\tAudio Channels\t\t: %lld\n", channels);
|
||||||
const unsigned long clusterCount = pSegment->GetCount();
|
|
||||||
|
const long long bitDepth = pAudioTrack->GetBitDepth();
|
||||||
printf("\t\tCluster Count\t: %ld\n\n", clusterCount);
|
printf("\t\tAudio BitDepth\t\t: %lld\n", bitDepth);
|
||||||
|
|
||||||
if (clusterCount == 0)
|
const double sampleRate = pAudioTrack->GetSamplingRate();
|
||||||
{
|
printf("\t\tAddio Sample Rate\t: %.3f\n", sampleRate);
|
||||||
printf("\t\tSegment has no clusters.\n");
|
|
||||||
return -1;
|
const long long codecDelay = pAudioTrack->GetCodecDelay();
|
||||||
}
|
printf("\t\tAudio Codec Delay\t\t: %lld\n", codecDelay);
|
||||||
|
|
||||||
const mkvparser::Cluster* pCluster = pSegment->GetFirst();
|
const long long seekPreRoll = pAudioTrack->GetSeekPreRoll();
|
||||||
|
printf("\t\tAudio Seek Pre Roll\t\t: %lld\n", seekPreRoll);
|
||||||
while ((pCluster != NULL) && !pCluster->EOS())
|
}
|
||||||
{
|
}
|
||||||
const long long timeCode = pCluster->GetTimeCode();
|
|
||||||
printf("\t\tCluster Time Code\t: %lld\n", timeCode);
|
printf("\n\n\t\t\t Cluster Info\n");
|
||||||
|
const unsigned long clusterCount = pSegment->GetCount();
|
||||||
const long long time_ns = pCluster->GetTime();
|
|
||||||
printf("\t\tCluster Time (ns)\t: %lld\n", time_ns);
|
printf("\t\tCluster Count\t: %ld\n\n", clusterCount);
|
||||||
|
|
||||||
const BlockEntry* pBlockEntry;
|
if (clusterCount == 0) {
|
||||||
|
printf("\t\tSegment has no clusters.\n");
|
||||||
long status = pCluster->GetFirst(pBlockEntry);
|
return -1;
|
||||||
|
}
|
||||||
if (status < 0) //error
|
|
||||||
{
|
const mkvparser::Cluster* pCluster = pSegment->GetFirst();
|
||||||
printf("\t\tError parsing first block of cluster\n");
|
|
||||||
fflush(stdout);
|
while ((pCluster != NULL) && !pCluster->EOS()) {
|
||||||
return -1;
|
const long long timeCode = pCluster->GetTimeCode();
|
||||||
}
|
printf("\t\tCluster Time Code\t: %lld\n", timeCode);
|
||||||
|
|
||||||
while ((pBlockEntry != NULL) && !pBlockEntry->EOS())
|
const long long time_ns = pCluster->GetTime();
|
||||||
{
|
printf("\t\tCluster Time (ns)\t: %lld\n", time_ns);
|
||||||
const Block* const pBlock = pBlockEntry->GetBlock();
|
|
||||||
const long long trackNum = pBlock->GetTrackNumber();
|
const BlockEntry* pBlockEntry;
|
||||||
const unsigned long tn = static_cast<unsigned long>(trackNum);
|
|
||||||
const Track* const pTrack = pTracks->GetTrackByNumber(tn);
|
long status = pCluster->GetFirst(pBlockEntry);
|
||||||
|
|
||||||
if (pTrack == NULL)
|
if (status < 0) // error
|
||||||
printf("\t\t\tBlock\t\t:UNKNOWN TRACK TYPE\n");
|
{
|
||||||
else
|
printf("\t\tError parsing first block of cluster\n");
|
||||||
{
|
fflush(stdout);
|
||||||
const long long trackType = pTrack->GetType();
|
return -1;
|
||||||
const int frameCount = pBlock->GetFrameCount();
|
}
|
||||||
const long long time_ns = pBlock->GetTime(pCluster);
|
|
||||||
|
while ((pBlockEntry != NULL) && !pBlockEntry->EOS()) {
|
||||||
printf("\t\t\tBlock\t\t:%s,%s,%15lld\n",
|
const Block* const pBlock = pBlockEntry->GetBlock();
|
||||||
(trackType == mkvparser::Track::kVideo) ? "V" : "A",
|
const long long trackNum = pBlock->GetTrackNumber();
|
||||||
pBlock->IsKey() ? "I" : "P",
|
const unsigned long tn = static_cast<unsigned long>(trackNum);
|
||||||
time_ns);
|
const Track* const pTrack = pTracks->GetTrackByNumber(tn);
|
||||||
|
|
||||||
for (int i = 0; i < frameCount; ++i)
|
if (pTrack == NULL)
|
||||||
{
|
printf("\t\t\tBlock\t\t:UNKNOWN TRACK TYPE\n");
|
||||||
const Block::Frame& theFrame = pBlock->GetFrame(i);
|
else {
|
||||||
const long size = theFrame.len;
|
const long long trackType = pTrack->GetType();
|
||||||
const long long offset = theFrame.pos;
|
const int frameCount = pBlock->GetFrameCount();
|
||||||
printf("\t\t\t %15ld,%15llx\n", size, offset);
|
const long long time_ns = pBlock->GetTime(pCluster);
|
||||||
}
|
const long long discard_padding = pBlock->GetDiscardPadding();
|
||||||
}
|
|
||||||
|
printf("\t\t\tBlock\t\t:%s,%s,%15lld,%lld\n",
|
||||||
status = pCluster->GetNext(pBlockEntry, pBlockEntry);
|
(trackType == mkvparser::Track::kVideo) ? "V" : "A",
|
||||||
|
pBlock->IsKey() ? "I" : "P", time_ns, discard_padding);
|
||||||
if (status < 0)
|
|
||||||
{
|
for (int i = 0; i < frameCount; ++i) {
|
||||||
printf("\t\t\tError parsing next block of cluster\n");
|
const Block::Frame& theFrame = pBlock->GetFrame(i);
|
||||||
fflush(stdout);
|
const long size = theFrame.len;
|
||||||
return -1;
|
const long long offset = theFrame.pos;
|
||||||
}
|
printf("\t\t\t %15ld,%15llx\n", size, offset);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
pCluster = pSegment->GetNext(pCluster);
|
|
||||||
}
|
status = pCluster->GetNext(pBlockEntry, pBlockEntry);
|
||||||
|
|
||||||
fflush(stdout);
|
if (status < 0) {
|
||||||
return 0;
|
printf("\t\t\tError parsing next block of cluster\n");
|
||||||
|
fflush(stdout);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pCluster = pSegment->GetNext(pCluster);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InputHasCues(pSegment.get())) {
|
||||||
|
// Walk them.
|
||||||
|
const mkvparser::Cues* const cues = pSegment->GetCues();
|
||||||
|
const mkvparser::CuePoint* cue = cues->GetFirst();
|
||||||
|
int cue_point_num = 1;
|
||||||
|
|
||||||
|
printf("\t\tCues\n");
|
||||||
|
do {
|
||||||
|
for (track_num = 0; track_num < num_tracks; ++track_num) {
|
||||||
|
const mkvparser::Track* const track =
|
||||||
|
pTracks->GetTrackByIndex(track_num);
|
||||||
|
const mkvparser::CuePoint::TrackPosition* const track_pos =
|
||||||
|
cue->Find(track);
|
||||||
|
|
||||||
|
if (track_pos != NULL) {
|
||||||
|
const char track_type =
|
||||||
|
(track->GetType() == mkvparser::Track::kVideo) ? 'V' : 'A';
|
||||||
|
printf(
|
||||||
|
"\t\t\tCue Point %4d Track %3lu(%c) Time %14lld "
|
||||||
|
"Block %4lld Pos %8llx\n",
|
||||||
|
cue_point_num, track->GetNumber(), track_type,
|
||||||
|
cue->GetTime(pSegment.get()), track_pos->m_block,
|
||||||
|
track_pos->m_pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cue = cues->GetNext(cue);
|
||||||
|
++cue_point_num;
|
||||||
|
} while (cue != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
const mkvparser::Tags* const tags = pSegment->GetTags();
|
||||||
|
if (tags && tags->GetTagCount() > 0) {
|
||||||
|
printf("\t\tTags\n");
|
||||||
|
for (int i = 0; i < tags->GetTagCount(); ++i) {
|
||||||
|
const mkvparser::Tags::Tag* const tag = tags->GetTag(i);
|
||||||
|
printf("\t\t\tTag\n");
|
||||||
|
for (int j = 0; j < tag->GetSimpleTagCount(); j++) {
|
||||||
|
const mkvparser::Tags::SimpleTag* const simple_tag =
|
||||||
|
tag->GetSimpleTag(j);
|
||||||
|
printf("\t\t\t\tSimple Tag \"%s\" Value \"%s\"\n",
|
||||||
|
simple_tag->GetTagName(), simple_tag->GetTagString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fflush(stdout);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,181 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="Windows-1252"?>
|
|
||||||
<VisualStudioProject
|
|
||||||
ProjectType="Visual C++"
|
|
||||||
Version="9.00"
|
|
||||||
Name="sample"
|
|
||||||
ProjectGUID="{0CB5681F-6065-490C-98C8-05531732ED7E}"
|
|
||||||
RootNamespace="sample"
|
|
||||||
Keyword="Win32Proj"
|
|
||||||
TargetFrameworkVersion="131072"
|
|
||||||
>
|
|
||||||
<Platforms>
|
|
||||||
<Platform
|
|
||||||
Name="Win32"
|
|
||||||
/>
|
|
||||||
</Platforms>
|
|
||||||
<ToolFiles>
|
|
||||||
</ToolFiles>
|
|
||||||
<Configurations>
|
|
||||||
<Configuration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
OutputDirectory="$(ProjectDir)..\exe\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ProjectDir)..\obj\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
|
|
||||||
ConfigurationType="1"
|
|
||||||
CharacterSet="1"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
Optimization="0"
|
|
||||||
AdditionalIncludeDirectories="..\"
|
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
|
||||||
MinimalRebuild="false"
|
|
||||||
BasicRuntimeChecks="3"
|
|
||||||
RuntimeLibrary="1"
|
|
||||||
UsePrecompiledHeader="0"
|
|
||||||
WarningLevel="4"
|
|
||||||
Detect64BitPortabilityProblems="false"
|
|
||||||
DebugInformationFormat="1"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLinkerTool"
|
|
||||||
AdditionalDependencies="$(ProjectDir)..\lib\libwebm_2008\libwebm\$(PlatformName)\$(ConfigurationName)\libwebm.lib"
|
|
||||||
LinkIncremental="2"
|
|
||||||
GenerateDebugInformation="true"
|
|
||||||
SubSystem="1"
|
|
||||||
RandomizedBaseAddress="1"
|
|
||||||
DataExecutionPrevention="0"
|
|
||||||
TargetMachine="1"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCALinkTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManifestTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXDCMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCBscMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCFxCopTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCAppVerifierTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"
|
|
||||||
/>
|
|
||||||
</Configuration>
|
|
||||||
<Configuration
|
|
||||||
Name="Release|Win32"
|
|
||||||
OutputDirectory="$(ProjectDir)..\exe\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ProjectDir)..\obj\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
|
|
||||||
ConfigurationType="1"
|
|
||||||
CharacterSet="1"
|
|
||||||
WholeProgramOptimization="1"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
|
||||||
RuntimeLibrary="0"
|
|
||||||
UsePrecompiledHeader="0"
|
|
||||||
WarningLevel="3"
|
|
||||||
Detect64BitPortabilityProblems="false"
|
|
||||||
DebugInformationFormat="3"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLinkerTool"
|
|
||||||
AdditionalDependencies="$(ProjectDir)..\lib\libwebm_2008\libwebm\$(PlatformName)\$(ConfigurationName)\libwebm.lib"
|
|
||||||
LinkIncremental="1"
|
|
||||||
GenerateDebugInformation="true"
|
|
||||||
SubSystem="1"
|
|
||||||
OptimizeReferences="2"
|
|
||||||
EnableCOMDATFolding="2"
|
|
||||||
RandomizedBaseAddress="1"
|
|
||||||
DataExecutionPrevention="0"
|
|
||||||
TargetMachine="1"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCALinkTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManifestTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXDCMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCBscMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCFxCopTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCAppVerifierTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"
|
|
||||||
/>
|
|
||||||
</Configuration>
|
|
||||||
</Configurations>
|
|
||||||
<References>
|
|
||||||
</References>
|
|
||||||
<Files>
|
|
||||||
<File
|
|
||||||
RelativePath=".\sample.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Files>
|
|
||||||
<Globals>
|
|
||||||
</Globals>
|
|
||||||
</VisualStudioProject>
|
|
||||||
@@ -1,181 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
|
||||||
<ProjectConfiguration Include="Debug DLL|Win32">
|
|
||||||
<Configuration>Debug DLL</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release DLL|Win32">
|
|
||||||
<Configuration>Release DLL</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|Win32">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<ProjectName>sample</ProjectName>
|
|
||||||
<ProjectGuid>{0CB5681F-6065-490C-98C8-05531732ED7E}</ProjectGuid>
|
|
||||||
<RootNamespace>sample</RootNamespace>
|
|
||||||
<Keyword>Win32Proj</Keyword>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<PlatformToolset>Windows7.1SDK</PlatformToolset>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<PlatformToolset>Windows7.1SDK</PlatformToolset>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
<PlatformToolset>Windows7.1SDK</PlatformToolset>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
<PlatformToolset>Windows7.1SDK</PlatformToolset>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
|
||||||
<ImportGroup Label="ExtensionSettings">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<PropertyGroup Label="UserMacros" />
|
|
||||||
<PropertyGroup>
|
|
||||||
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
|
|
||||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
|
|
||||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">true</LinkIncremental>
|
|
||||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
|
|
||||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">false</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<AdditionalIncludeDirectories>..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<MinimalRebuild>false</MinimalRebuild>
|
|
||||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level4</WarningLevel>
|
|
||||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
|
||||||
<DataExecutionPrevention>
|
|
||||||
</DataExecutionPrevention>
|
|
||||||
<TargetMachine>MachineX86</TargetMachine>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<AdditionalIncludeDirectories>..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<MinimalRebuild>false</MinimalRebuild>
|
|
||||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
|
||||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level4</WarningLevel>
|
|
||||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
|
||||||
<DataExecutionPrevention>
|
|
||||||
</DataExecutionPrevention>
|
|
||||||
<TargetMachine>MachineX86</TargetMachine>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
|
||||||
<DataExecutionPrevention>
|
|
||||||
</DataExecutionPrevention>
|
|
||||||
<TargetMachine>MachineX86</TargetMachine>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
|
||||||
<DataExecutionPrevention>
|
|
||||||
</DataExecutionPrevention>
|
|
||||||
<TargetMachine>MachineX86</TargetMachine>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="sample.cpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="libwebm_2010.vcxproj">
|
|
||||||
<Project>{7b1f12ca-0724-430b-b61a-1d357c912cba}</Project>
|
|
||||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="sample.cpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
161
sample_muxer.cpp
161
sample_muxer.cpp
@@ -9,6 +9,7 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -23,8 +24,14 @@
|
|||||||
|
|
||||||
#include "sample_muxer_metadata.h"
|
#include "sample_muxer_metadata.h"
|
||||||
|
|
||||||
|
using mkvmuxer::int64;
|
||||||
using mkvmuxer::uint64;
|
using mkvmuxer::uint64;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
// Disable MSVC warnings that suggest making code non-portable.
|
||||||
|
#pragma warning(disable : 4996)
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void Usage() {
|
void Usage() {
|
||||||
@@ -45,6 +52,7 @@ void Usage() {
|
|||||||
printf(" -audio_track_number <int> >0 Changes the audio track number\n");
|
printf(" -audio_track_number <int> >0 Changes the audio track number\n");
|
||||||
printf(" -video_track_number <int> >0 Changes the video track number\n");
|
printf(" -video_track_number <int> >0 Changes the video track number\n");
|
||||||
printf(" -chunking <string> Chunk output\n");
|
printf(" -chunking <string> Chunk output\n");
|
||||||
|
printf(" -copy_tags <int> >0 Copies the tags\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("Video options:\n");
|
printf("Video options:\n");
|
||||||
printf(" -display_width <int> Display width in pixels\n");
|
printf(" -display_width <int> Display width in pixels\n");
|
||||||
@@ -56,16 +64,16 @@ void Usage() {
|
|||||||
printf(" -cues_before_clusters <int> >0 puts Cues before Clusters\n");
|
printf(" -cues_before_clusters <int> >0 puts Cues before Clusters\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("Metadata options:\n");
|
printf("Metadata options:\n");
|
||||||
printf(" -webvtt-subtitles <vttfile> "
|
printf(" -webvtt-subtitles <vttfile> ");
|
||||||
"add WebVTT subtitles as metadata track\n");
|
printf("add WebVTT subtitles as metadata track\n");
|
||||||
printf(" -webvtt-captions <vttfile> "
|
printf(" -webvtt-captions <vttfile> ");
|
||||||
"add WebVTT captions as metadata track\n");
|
printf("add WebVTT captions as metadata track\n");
|
||||||
printf(" -webvtt-descriptions <vttfile> "
|
printf(" -webvtt-descriptions <vttfile> ");
|
||||||
"add WebVTT descriptions as metadata track\n");
|
printf("add WebVTT descriptions as metadata track\n");
|
||||||
printf(" -webvtt-metadata <vttfile> "
|
printf(" -webvtt-metadata <vttfile> ");
|
||||||
"add WebVTT subtitles as metadata track\n");
|
printf("add WebVTT subtitles as metadata track\n");
|
||||||
printf(" -webvtt-chapters <vttfile> "
|
printf(" -webvtt-chapters <vttfile> ");
|
||||||
"add WebVTT chapters as MKV chapters element\n");
|
printf("add WebVTT chapters as MKV chapters element\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MetadataFile {
|
struct MetadataFile {
|
||||||
@@ -76,9 +84,8 @@ struct MetadataFile {
|
|||||||
typedef std::list<MetadataFile> metadata_files_t;
|
typedef std::list<MetadataFile> metadata_files_t;
|
||||||
|
|
||||||
// Cache the WebVTT filenames specified as command-line args.
|
// Cache the WebVTT filenames specified as command-line args.
|
||||||
bool LoadMetadataFiles(
|
bool LoadMetadataFiles(const metadata_files_t& files,
|
||||||
const metadata_files_t& files,
|
SampleMuxerMetadata* metadata) {
|
||||||
SampleMuxerMetadata* metadata) {
|
|
||||||
typedef metadata_files_t::const_iterator iter_t;
|
typedef metadata_files_t::const_iterator iter_t;
|
||||||
|
|
||||||
iter_t i = files.begin();
|
iter_t i = files.begin();
|
||||||
@@ -94,22 +101,21 @@ bool LoadMetadataFiles(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ParseArgWebVTT(
|
int ParseArgWebVTT(char* argv[], int* argv_index, int argc_check,
|
||||||
char* argv[],
|
metadata_files_t* metadata_files) {
|
||||||
int* argv_index,
|
|
||||||
int argc_check,
|
|
||||||
metadata_files_t* metadata_files) {
|
|
||||||
int& i = *argv_index;
|
int& i = *argv_index;
|
||||||
|
|
||||||
enum { kCount = 5 };
|
enum { kCount = 5 };
|
||||||
struct Arg { const char* name; SampleMuxerMetadata::Kind kind; };
|
struct Arg {
|
||||||
const Arg args[kCount] = {
|
const char* name;
|
||||||
{ "-webvtt-subtitles", SampleMuxerMetadata::kSubtitles },
|
SampleMuxerMetadata::Kind kind;
|
||||||
{ "-webvtt-captions", SampleMuxerMetadata::kCaptions },
|
|
||||||
{ "-webvtt-descriptions", SampleMuxerMetadata::kDescriptions },
|
|
||||||
{ "-webvtt-metadata", SampleMuxerMetadata::kMetadata },
|
|
||||||
{ "-webvtt-chapters", SampleMuxerMetadata::kChapters }
|
|
||||||
};
|
};
|
||||||
|
const Arg args[kCount] = {
|
||||||
|
{"-webvtt-subtitles", SampleMuxerMetadata::kSubtitles},
|
||||||
|
{"-webvtt-captions", SampleMuxerMetadata::kCaptions},
|
||||||
|
{"-webvtt-descriptions", SampleMuxerMetadata::kDescriptions},
|
||||||
|
{"-webvtt-metadata", SampleMuxerMetadata::kMetadata},
|
||||||
|
{"-webvtt-chapters", SampleMuxerMetadata::kChapters}};
|
||||||
|
|
||||||
for (int idx = 0; idx < kCount; ++idx) {
|
for (int idx = 0; idx < kCount; ++idx) {
|
||||||
const Arg& arg = args[idx];
|
const Arg& arg = args[idx];
|
||||||
@@ -155,6 +161,7 @@ int main(int argc, char* argv[]) {
|
|||||||
int audio_track_number = 0; // 0 tells muxer to decide.
|
int audio_track_number = 0; // 0 tells muxer to decide.
|
||||||
int video_track_number = 0; // 0 tells muxer to decide.
|
int video_track_number = 0; // 0 tells muxer to decide.
|
||||||
bool chunking = false;
|
bool chunking = false;
|
||||||
|
bool copy_tags = false;
|
||||||
const char* chunk_name = NULL;
|
const char* chunk_name = NULL;
|
||||||
|
|
||||||
bool output_cues_block_number = true;
|
bool output_cues_block_number = true;
|
||||||
@@ -196,8 +203,7 @@ int main(int argc, char* argv[]) {
|
|||||||
cues_on_video_track = false;
|
cues_on_video_track = false;
|
||||||
} else if (!strcmp("-max_cluster_duration", argv[i]) && i < argc_check) {
|
} else if (!strcmp("-max_cluster_duration", argv[i]) && i < argc_check) {
|
||||||
const double seconds = strtod(argv[++i], &end);
|
const double seconds = strtod(argv[++i], &end);
|
||||||
max_cluster_duration =
|
max_cluster_duration = static_cast<uint64>(seconds * 1000000000.0);
|
||||||
static_cast<uint64>(seconds * 1000000000.0);
|
|
||||||
} else if (!strcmp("-max_cluster_size", argv[i]) && i < argc_check) {
|
} else if (!strcmp("-max_cluster_size", argv[i]) && i < argc_check) {
|
||||||
max_cluster_size = strtol(argv[++i], &end, 10);
|
max_cluster_size = strtol(argv[++i], &end, 10);
|
||||||
} else if (!strcmp("-switch_tracks", argv[i]) && i < argc_check) {
|
} else if (!strcmp("-switch_tracks", argv[i]) && i < argc_check) {
|
||||||
@@ -209,6 +215,8 @@ int main(int argc, char* argv[]) {
|
|||||||
} else if (!strcmp("-chunking", argv[i]) && i < argc_check) {
|
} else if (!strcmp("-chunking", argv[i]) && i < argc_check) {
|
||||||
chunking = true;
|
chunking = true;
|
||||||
chunk_name = argv[++i];
|
chunk_name = argv[++i];
|
||||||
|
} else if (!strcmp("-copy_tags", argv[i]) && i < argc_check) {
|
||||||
|
copy_tags = strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||||
} else if (!strcmp("-display_width", argv[i]) && i < argc_check) {
|
} else if (!strcmp("-display_width", argv[i]) && i < argc_check) {
|
||||||
display_width = strtol(argv[++i], &end, 10);
|
display_width = strtol(argv[++i], &end, 10);
|
||||||
} else if (!strcmp("-display_height", argv[i]) && i < argc_check) {
|
} else if (!strcmp("-display_height", argv[i]) && i < argc_check) {
|
||||||
@@ -240,17 +248,20 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
long long pos = 0;
|
long long pos = 0;
|
||||||
mkvparser::EBMLHeader ebml_header;
|
mkvparser::EBMLHeader ebml_header;
|
||||||
ebml_header.Parse(&reader, pos);
|
long long ret = ebml_header.Parse(&reader, pos);
|
||||||
|
if (ret) {
|
||||||
|
printf("\n EBMLHeader::Parse() failed.");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
mkvparser::Segment* parser_segment;
|
mkvparser::Segment* parser_segment_;
|
||||||
long long ret = mkvparser::Segment::CreateInstance(&reader,
|
ret = mkvparser::Segment::CreateInstance(&reader, pos, parser_segment_);
|
||||||
pos,
|
|
||||||
parser_segment);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printf("\n Segment::CreateInstance() failed.");
|
printf("\n Segment::CreateInstance() failed.");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::auto_ptr<mkvparser::Segment> parser_segment(parser_segment_);
|
||||||
ret = parser_segment->Load();
|
ret = parser_segment->Load();
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printf("\n Segment::Load() failed.");
|
printf("\n Segment::Load() failed.");
|
||||||
@@ -258,6 +269,10 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const mkvparser::SegmentInfo* const segment_info = parser_segment->GetInfo();
|
const mkvparser::SegmentInfo* const segment_info = parser_segment->GetInfo();
|
||||||
|
if (segment_info == NULL) {
|
||||||
|
printf("\n Segment::GetInfo() failed.");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
const long long timeCodeScale = segment_info->GetTimeCodeScale();
|
const long long timeCodeScale = segment_info->GetTimeCodeScale();
|
||||||
|
|
||||||
// Set muxer header info
|
// Set muxer header info
|
||||||
@@ -296,6 +311,21 @@ int main(int argc, char* argv[]) {
|
|||||||
info->set_timecode_scale(timeCodeScale);
|
info->set_timecode_scale(timeCodeScale);
|
||||||
info->set_writing_app("sample_muxer");
|
info->set_writing_app("sample_muxer");
|
||||||
|
|
||||||
|
const mkvparser::Tags* const tags = parser_segment->GetTags();
|
||||||
|
if (copy_tags && tags) {
|
||||||
|
for (int i = 0; i < tags->GetTagCount(); i++) {
|
||||||
|
const mkvparser::Tags::Tag* const tag = tags->GetTag(i);
|
||||||
|
mkvmuxer::Tag* muxer_tag = muxer_segment.AddTag();
|
||||||
|
|
||||||
|
for (int j = 0; j < tag->GetSimpleTagCount(); j++) {
|
||||||
|
const mkvparser::Tags::SimpleTag* const simple_tag =
|
||||||
|
tag->GetSimpleTag(j);
|
||||||
|
muxer_tag->add_simple_tag(simple_tag->GetTagName(),
|
||||||
|
simple_tag->GetTagString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set Tracks element attributes
|
// Set Tracks element attributes
|
||||||
const mkvparser::Tracks* const parser_tracks = parser_segment->GetTracks();
|
const mkvparser::Tracks* const parser_tracks = parser_segment->GetTracks();
|
||||||
unsigned long i = 0;
|
unsigned long i = 0;
|
||||||
@@ -324,7 +354,7 @@ int main(int argc, char* argv[]) {
|
|||||||
// Get the video track from the parser
|
// Get the video track from the parser
|
||||||
const mkvparser::VideoTrack* const pVideoTrack =
|
const mkvparser::VideoTrack* const pVideoTrack =
|
||||||
static_cast<const mkvparser::VideoTrack*>(parser_track);
|
static_cast<const mkvparser::VideoTrack*>(parser_track);
|
||||||
const long long width = pVideoTrack->GetWidth();
|
const long long width = pVideoTrack->GetWidth();
|
||||||
const long long height = pVideoTrack->GetHeight();
|
const long long height = pVideoTrack->GetHeight();
|
||||||
|
|
||||||
// Add the video track to the muxer
|
// Add the video track to the muxer
|
||||||
@@ -336,9 +366,8 @@ int main(int argc, char* argv[]) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
mkvmuxer::VideoTrack* const video =
|
mkvmuxer::VideoTrack* const video = static_cast<mkvmuxer::VideoTrack*>(
|
||||||
static_cast<mkvmuxer::VideoTrack*>(
|
muxer_segment.GetTrackByNumber(vid_track));
|
||||||
muxer_segment.GetTrackByNumber(vid_track));
|
|
||||||
if (!video) {
|
if (!video) {
|
||||||
printf("\n Could not get video track.\n");
|
printf("\n Could not get video track.\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
@@ -347,6 +376,8 @@ int main(int argc, char* argv[]) {
|
|||||||
if (track_name)
|
if (track_name)
|
||||||
video->set_name(track_name);
|
video->set_name(track_name);
|
||||||
|
|
||||||
|
video->set_codec_id(pVideoTrack->GetCodecId());
|
||||||
|
|
||||||
if (display_width > 0)
|
if (display_width > 0)
|
||||||
video->set_display_width(display_width);
|
video->set_display_width(display_width);
|
||||||
if (display_height > 0)
|
if (display_height > 0)
|
||||||
@@ -362,7 +393,7 @@ int main(int argc, char* argv[]) {
|
|||||||
// Get the audio track from the parser
|
// Get the audio track from the parser
|
||||||
const mkvparser::AudioTrack* const pAudioTrack =
|
const mkvparser::AudioTrack* const pAudioTrack =
|
||||||
static_cast<const mkvparser::AudioTrack*>(parser_track);
|
static_cast<const mkvparser::AudioTrack*>(parser_track);
|
||||||
const long long channels = pAudioTrack->GetChannels();
|
const long long channels = pAudioTrack->GetChannels();
|
||||||
const double sample_rate = pAudioTrack->GetSamplingRate();
|
const double sample_rate = pAudioTrack->GetSamplingRate();
|
||||||
|
|
||||||
// Add the audio track to the muxer
|
// Add the audio track to the muxer
|
||||||
@@ -374,9 +405,8 @@ int main(int argc, char* argv[]) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
mkvmuxer::AudioTrack* const audio =
|
mkvmuxer::AudioTrack* const audio = static_cast<mkvmuxer::AudioTrack*>(
|
||||||
static_cast<mkvmuxer::AudioTrack*>(
|
muxer_segment.GetTrackByNumber(aud_track));
|
||||||
muxer_segment.GetTrackByNumber(aud_track));
|
|
||||||
if (!audio) {
|
if (!audio) {
|
||||||
printf("\n Could not get audio track.\n");
|
printf("\n Could not get audio track.\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
@@ -385,6 +415,8 @@ int main(int argc, char* argv[]) {
|
|||||||
if (track_name)
|
if (track_name)
|
||||||
audio->set_name(track_name);
|
audio->set_name(track_name);
|
||||||
|
|
||||||
|
audio->set_codec_id(pAudioTrack->GetCodecId());
|
||||||
|
|
||||||
size_t private_size;
|
size_t private_size;
|
||||||
const unsigned char* const private_data =
|
const unsigned char* const private_data =
|
||||||
pAudioTrack->GetCodecPrivate(private_size);
|
pAudioTrack->GetCodecPrivate(private_size);
|
||||||
@@ -398,6 +430,11 @@ int main(int argc, char* argv[]) {
|
|||||||
const long long bit_depth = pAudioTrack->GetBitDepth();
|
const long long bit_depth = pAudioTrack->GetBitDepth();
|
||||||
if (bit_depth > 0)
|
if (bit_depth > 0)
|
||||||
audio->set_bit_depth(bit_depth);
|
audio->set_bit_depth(bit_depth);
|
||||||
|
|
||||||
|
if (pAudioTrack->GetCodecDelay())
|
||||||
|
audio->set_codec_delay(pAudioTrack->GetCodecDelay());
|
||||||
|
if (pAudioTrack->GetSeekPreRoll())
|
||||||
|
audio->set_seek_pre_roll(pAudioTrack->GetSeekPreRoll());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,16 +476,23 @@ int main(int argc, char* argv[]) {
|
|||||||
long status = cluster->GetFirst(block_entry);
|
long status = cluster->GetFirst(block_entry);
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
printf("\n Could not get first block of cluster.\n");
|
printf("\n Could not get first block of cluster.\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((block_entry != NULL) && !block_entry->EOS()) {
|
while ((block_entry != NULL) && !block_entry->EOS()) {
|
||||||
const mkvparser::Block* const block = block_entry->GetBlock();
|
const mkvparser::Block* const block = block_entry->GetBlock();
|
||||||
const long long trackNum = block->GetTrackNumber();
|
const long long trackNum = block->GetTrackNumber();
|
||||||
const mkvparser::Track* const parser_track =
|
const mkvparser::Track* const parser_track =
|
||||||
parser_tracks->GetTrackByNumber(
|
parser_tracks->GetTrackByNumber(static_cast<unsigned long>(trackNum));
|
||||||
static_cast<unsigned long>(trackNum));
|
|
||||||
|
// When |parser_track| is NULL, it means that the track number in the
|
||||||
|
// Block is invalid (i.e.) the was no TrackEntry corresponding to the
|
||||||
|
// track number. So we reject the file.
|
||||||
|
if (!parser_track) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
const long long track_type = parser_track->GetType();
|
const long long track_type = parser_track->GetType();
|
||||||
const long long time_ns = block->GetTime(cluster);
|
const long long time_ns = block->GetTime(cluster);
|
||||||
|
|
||||||
@@ -460,13 +504,12 @@ int main(int argc, char* argv[]) {
|
|||||||
if ((track_type == Track::kAudio && output_audio) ||
|
if ((track_type == Track::kAudio && output_audio) ||
|
||||||
(track_type == Track::kVideo && output_video)) {
|
(track_type == Track::kVideo && output_video)) {
|
||||||
const int frame_count = block->GetFrameCount();
|
const int frame_count = block->GetFrameCount();
|
||||||
const bool is_key = block->IsKey();
|
|
||||||
|
|
||||||
for (int i = 0; i < frame_count; ++i) {
|
for (int i = 0; i < frame_count; ++i) {
|
||||||
const mkvparser::Block::Frame& frame = block->GetFrame(i);
|
const mkvparser::Block::Frame& frame = block->GetFrame(i);
|
||||||
|
|
||||||
if (frame.len > data_len) {
|
if (frame.len > data_len) {
|
||||||
delete [] data;
|
delete[] data;
|
||||||
data = new unsigned char[frame.len];
|
data = new unsigned char[frame.len];
|
||||||
if (!data)
|
if (!data)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
@@ -476,15 +519,16 @@ int main(int argc, char* argv[]) {
|
|||||||
if (frame.Read(&reader, data))
|
if (frame.Read(&reader, data))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
uint64 track_num = vid_track;
|
mkvmuxer::Frame muxer_frame;
|
||||||
if (track_type == Track::kAudio)
|
if (!muxer_frame.Init(data, frame.len))
|
||||||
track_num = aud_track;
|
return EXIT_FAILURE;
|
||||||
|
muxer_frame.set_track_number(track_type == Track::kAudio ? aud_track :
|
||||||
if (!muxer_segment.AddFrame(data,
|
vid_track);
|
||||||
frame.len,
|
if (block->GetDiscardPadding())
|
||||||
track_num,
|
muxer_frame.set_discard_padding(block->GetDiscardPadding());
|
||||||
time_ns,
|
muxer_frame.set_timestamp(time_ns);
|
||||||
is_key)) {
|
muxer_frame.set_is_key(block->IsKey());
|
||||||
|
if (!muxer_segment.AddGenericFrame(&muxer_frame)) {
|
||||||
printf("\n Could not add frame.\n");
|
printf("\n Could not add frame.\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
@@ -494,8 +538,8 @@ int main(int argc, char* argv[]) {
|
|||||||
status = cluster->GetNext(block_entry, block_entry);
|
status = cluster->GetNext(block_entry, block_entry);
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
printf("\n Could not get next block of cluster.\n");
|
printf("\n Could not get next block of cluster.\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,8 +577,7 @@ int main(int argc, char* argv[]) {
|
|||||||
remove(temp_file);
|
remove(temp_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete [] data;
|
delete[] data;
|
||||||
delete parser_segment;
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,179 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="Windows-1252"?>
|
|
||||||
<VisualStudioProject
|
|
||||||
ProjectType="Visual C++"
|
|
||||||
Version="9.00"
|
|
||||||
Name="sample_muxer"
|
|
||||||
ProjectGUID="{B407561F-1F5E-4798-B9C2-81AB09CFBC16}"
|
|
||||||
RootNamespace="sample_muxer"
|
|
||||||
Keyword="Win32Proj"
|
|
||||||
TargetFrameworkVersion="196613"
|
|
||||||
>
|
|
||||||
<Platforms>
|
|
||||||
<Platform
|
|
||||||
Name="Win32"
|
|
||||||
/>
|
|
||||||
</Platforms>
|
|
||||||
<ToolFiles>
|
|
||||||
</ToolFiles>
|
|
||||||
<Configurations>
|
|
||||||
<Configuration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
OutputDirectory="$(ProjectDir)..\exe\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ProjectDir)..\obj\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
|
|
||||||
ConfigurationType="1"
|
|
||||||
CharacterSet="1"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
Optimization="0"
|
|
||||||
AdditionalIncludeDirectories="../"
|
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
|
||||||
MinimalRebuild="true"
|
|
||||||
BasicRuntimeChecks="3"
|
|
||||||
RuntimeLibrary="1"
|
|
||||||
UsePrecompiledHeader="0"
|
|
||||||
WarningLevel="4"
|
|
||||||
DebugInformationFormat="4"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLinkerTool"
|
|
||||||
AdditionalDependencies="$(ProjectDir)..\lib\libwebm_2008\libwebm\$(PlatformName)\$(ConfigurationName)\libwebm.lib"
|
|
||||||
LinkIncremental="2"
|
|
||||||
GenerateDebugInformation="true"
|
|
||||||
SubSystem="1"
|
|
||||||
TargetMachine="1"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCALinkTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManifestTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXDCMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCBscMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCFxCopTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCAppVerifierTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"
|
|
||||||
/>
|
|
||||||
</Configuration>
|
|
||||||
<Configuration
|
|
||||||
Name="Release|Win32"
|
|
||||||
OutputDirectory="$(ProjectDir)..\exe\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ProjectDir)..\obj\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
|
|
||||||
ConfigurationType="1"
|
|
||||||
CharacterSet="1"
|
|
||||||
WholeProgramOptimization="1"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
Optimization="2"
|
|
||||||
EnableIntrinsicFunctions="true"
|
|
||||||
AdditionalIncludeDirectories="../"
|
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
|
||||||
RuntimeLibrary="0"
|
|
||||||
EnableFunctionLevelLinking="true"
|
|
||||||
UsePrecompiledHeader="0"
|
|
||||||
WarningLevel="4"
|
|
||||||
DebugInformationFormat="3"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLinkerTool"
|
|
||||||
AdditionalDependencies="$(ProjectDir)..\lib\libwebm_2008\libwebm\$(PlatformName)\$(ConfigurationName)\libwebm.lib"
|
|
||||||
LinkIncremental="1"
|
|
||||||
GenerateDebugInformation="true"
|
|
||||||
SubSystem="1"
|
|
||||||
OptimizeReferences="2"
|
|
||||||
EnableCOMDATFolding="2"
|
|
||||||
TargetMachine="1"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCALinkTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManifestTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXDCMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCBscMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCFxCopTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCAppVerifierTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"
|
|
||||||
/>
|
|
||||||
</Configuration>
|
|
||||||
</Configurations>
|
|
||||||
<References>
|
|
||||||
</References>
|
|
||||||
<Files>
|
|
||||||
<File
|
|
||||||
RelativePath=".\sample_muxer.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Files>
|
|
||||||
<Globals>
|
|
||||||
</Globals>
|
|
||||||
</VisualStudioProject>
|
|
||||||
@@ -1,185 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
|
||||||
<ProjectConfiguration Include="Debug DLL|Win32">
|
|
||||||
<Configuration>Debug DLL</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release DLL|Win32">
|
|
||||||
<Configuration>Release DLL</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|Win32">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<ProjectName>sample_muxer</ProjectName>
|
|
||||||
<ProjectGuid>{B407561F-1F5E-4798-B9C2-81AB09CFBC16}</ProjectGuid>
|
|
||||||
<RootNamespace>sample_muxer</RootNamespace>
|
|
||||||
<Keyword>Win32Proj</Keyword>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<PlatformToolset>Windows7.1SDK</PlatformToolset>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<PlatformToolset>Windows7.1SDK</PlatformToolset>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
<PlatformToolset>Windows7.1SDK</PlatformToolset>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
<PlatformToolset>Windows7.1SDK</PlatformToolset>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
|
||||||
<ImportGroup Label="ExtensionSettings">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<PropertyGroup Label="UserMacros" />
|
|
||||||
<PropertyGroup>
|
|
||||||
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
|
|
||||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
|
|
||||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">true</LinkIncremental>
|
|
||||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
|
|
||||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">false</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<MinimalRebuild>true</MinimalRebuild>
|
|
||||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level4</WarningLevel>
|
|
||||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<TargetMachine>MachineX86</TargetMachine>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<MinimalRebuild>true</MinimalRebuild>
|
|
||||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
|
||||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level4</WarningLevel>
|
|
||||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<TargetMachine>MachineX86</TargetMachine>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<Optimization>MaxSpeed</Optimization>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level4</WarningLevel>
|
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<TargetMachine>MachineX86</TargetMachine>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<Optimization>MaxSpeed</Optimization>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level4</WarningLevel>
|
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<TargetMachine>MachineX86</TargetMachine>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="sample_muxer.cpp" />
|
|
||||||
<ClCompile Include="sample_muxer_metadata.cc" />
|
|
||||||
<ClCompile Include="vttreader.cc" />
|
|
||||||
<ClCompile Include="webvttparser.cc" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="libwebm_2010.vcxproj">
|
|
||||||
<Project>{7b1f12ca-0724-430b-b61a-1d357c912cba}</Project>
|
|
||||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="sample_muxer_metadata.h" />
|
|
||||||
<ClInclude Include="vttreader.h" />
|
|
||||||
<ClInclude Include="webvttparser.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="sample_muxer.cpp" />
|
|
||||||
<ClCompile Include="sample_muxer_metadata.cc" />
|
|
||||||
<ClCompile Include="vttreader.cc" />
|
|
||||||
<ClCompile Include="webvttparser.cc" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="sample_muxer_metadata.h" />
|
|
||||||
<ClInclude Include="vttreader.h" />
|
|
||||||
<ClInclude Include="webvttparser.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,9 +1,19 @@
|
|||||||
|
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style license
|
||||||
|
// that can be found in the LICENSE file in the root of the source
|
||||||
|
// tree. An additional intellectual property rights grant can be found
|
||||||
|
// in the file PATENTS. All contributing project authors may
|
||||||
|
// be found in the AUTHORS file in the root of the source tree.
|
||||||
|
//
|
||||||
|
// This sample application demonstrates how to use the matroska parser
|
||||||
|
// library, which allows clients to handle a matroska format file.
|
||||||
|
|
||||||
#include "sample_muxer_metadata.h"
|
#include "sample_muxer_metadata.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "vttreader.h"
|
#include "vttreader.h"
|
||||||
|
|
||||||
SampleMuxerMetadata::SampleMuxerMetadata() : segment_(NULL) {
|
SampleMuxerMetadata::SampleMuxerMetadata() : segment_(NULL) {}
|
||||||
}
|
|
||||||
|
|
||||||
bool SampleMuxerMetadata::Init(mkvmuxer::Segment* segment) {
|
bool SampleMuxerMetadata::Init(mkvmuxer::Segment* segment) {
|
||||||
if (segment == NULL || segment_ != NULL)
|
if (segment == NULL || segment_ != NULL)
|
||||||
@@ -82,9 +92,8 @@ bool SampleMuxerMetadata::LoadChapters(const char* file) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SampleMuxerMetadata::ParseChapters(
|
bool SampleMuxerMetadata::ParseChapters(const char* file,
|
||||||
const char* file,
|
cue_list_t* cues_ptr) {
|
||||||
cue_list_t* cues_ptr) {
|
|
||||||
cue_list_t& cues = *cues_ptr;
|
cue_list_t& cues = *cues_ptr;
|
||||||
cues.clear();
|
cues.clear();
|
||||||
|
|
||||||
@@ -188,9 +197,7 @@ bool SampleMuxerMetadata::AddChapter(const cue_t& cue) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SampleMuxerMetadata::AddTrack(
|
bool SampleMuxerMetadata::AddTrack(Kind kind, mkvmuxer::uint64* track_num) {
|
||||||
Kind kind,
|
|
||||||
mkvmuxer::uint64* track_num) {
|
|
||||||
*track_num = 0;
|
*track_num = 0;
|
||||||
|
|
||||||
// Track number value 0 means "let muxer choose track number"
|
// Track number value 0 means "let muxer choose track number"
|
||||||
@@ -238,10 +245,8 @@ bool SampleMuxerMetadata::AddTrack(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SampleMuxerMetadata::Parse(
|
bool SampleMuxerMetadata::Parse(const char* file, Kind /* kind */,
|
||||||
const char* file,
|
mkvmuxer::uint64 track_num) {
|
||||||
Kind /* kind */,
|
|
||||||
mkvmuxer::uint64 track_num) {
|
|
||||||
libwebvtt::VttReader r;
|
libwebvtt::VttReader r;
|
||||||
int e = r.Open(file);
|
int e = r.Open(file);
|
||||||
|
|
||||||
@@ -300,16 +305,14 @@ void SampleMuxerMetadata::MakeFrame(const cue_t& c, std::string* pf) {
|
|||||||
WriteCuePayload(c.payload, pf);
|
WriteCuePayload(c.payload, pf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SampleMuxerMetadata::WriteCueIdentifier(
|
void SampleMuxerMetadata::WriteCueIdentifier(const std::string& identifier,
|
||||||
const std::string& identifier,
|
std::string* pf) {
|
||||||
std::string* pf) {
|
|
||||||
pf->append(identifier);
|
pf->append(identifier);
|
||||||
pf->push_back('\x0A'); // LF
|
pf->push_back('\x0A'); // LF
|
||||||
}
|
}
|
||||||
|
|
||||||
void SampleMuxerMetadata::WriteCueSettings(
|
void SampleMuxerMetadata::WriteCueSettings(const cue_t::settings_t& settings,
|
||||||
const cue_t::settings_t& settings,
|
std::string* pf) {
|
||||||
std::string* pf) {
|
|
||||||
if (settings.empty()) {
|
if (settings.empty()) {
|
||||||
pf->push_back('\x0A'); // LF
|
pf->push_back('\x0A'); // LF
|
||||||
return;
|
return;
|
||||||
@@ -336,9 +339,8 @@ void SampleMuxerMetadata::WriteCueSettings(
|
|||||||
pf->push_back('\x0A'); // LF
|
pf->push_back('\x0A'); // LF
|
||||||
}
|
}
|
||||||
|
|
||||||
void SampleMuxerMetadata::WriteCuePayload(
|
void SampleMuxerMetadata::WriteCuePayload(const cue_t::payload_t& payload,
|
||||||
const cue_t::payload_t& payload,
|
std::string* pf) {
|
||||||
std::string* pf) {
|
|
||||||
typedef cue_t::payload_t::const_iterator iter_t;
|
typedef cue_t::payload_t::const_iterator iter_t;
|
||||||
|
|
||||||
iter_t i = payload.begin();
|
iter_t i = payload.begin();
|
||||||
@@ -351,8 +353,7 @@ void SampleMuxerMetadata::WriteCuePayload(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SampleMuxerMetadata::SortableCue::Write(
|
bool SampleMuxerMetadata::SortableCue::Write(mkvmuxer::Segment* segment) const {
|
||||||
mkvmuxer::Segment* segment) const {
|
|
||||||
// Cue start time expressed in milliseconds
|
// Cue start time expressed in milliseconds
|
||||||
const mkvmuxer::int64 start_ms = cue.start_time.presentation();
|
const mkvmuxer::int64 start_ms = cue.start_time.presentation();
|
||||||
|
|
||||||
@@ -375,5 +376,12 @@ bool SampleMuxerMetadata::SortableCue::Write(
|
|||||||
const data_t buf = reinterpret_cast<data_t>(frame.data());
|
const data_t buf = reinterpret_cast<data_t>(frame.data());
|
||||||
const mkvmuxer::uint64 len = frame.length();
|
const mkvmuxer::uint64 len = frame.length();
|
||||||
|
|
||||||
return segment->AddMetadata(buf, len, track_num, start_ns, duration_ns);
|
mkvmuxer::Frame muxer_frame;
|
||||||
|
if (!muxer_frame.Init(buf, len))
|
||||||
|
return 0;
|
||||||
|
muxer_frame.set_track_number(track_num);
|
||||||
|
muxer_frame.set_timestamp(start_ns);
|
||||||
|
muxer_frame.set_duration(duration_ns);
|
||||||
|
muxer_frame.set_is_key(true); // All metadata frames are keyframes.
|
||||||
|
return segment->AddGenericFrame(&muxer_frame);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,13 +17,7 @@
|
|||||||
|
|
||||||
class SampleMuxerMetadata {
|
class SampleMuxerMetadata {
|
||||||
public:
|
public:
|
||||||
enum Kind {
|
enum Kind { kSubtitles, kCaptions, kDescriptions, kMetadata, kChapters };
|
||||||
kSubtitles,
|
|
||||||
kCaptions,
|
|
||||||
kDescriptions,
|
|
||||||
kMetadata,
|
|
||||||
kChapters
|
|
||||||
};
|
|
||||||
|
|
||||||
SampleMuxerMetadata();
|
SampleMuxerMetadata();
|
||||||
|
|
||||||
@@ -86,8 +80,7 @@ class SampleMuxerMetadata {
|
|||||||
|
|
||||||
// Parse the WebVTT chapters in |file| to populate |cues|. Returns
|
// Parse the WebVTT chapters in |file| to populate |cues|. Returns
|
||||||
// false on error.
|
// false on error.
|
||||||
static bool ParseChapters(const char* file,
|
static bool ParseChapters(const char* file, cue_list_t* cues);
|
||||||
cue_list_t* cues);
|
|
||||||
|
|
||||||
// Adds WebVTT cue |chapter| to the chapters element of the output
|
// Adds WebVTT cue |chapter| to the chapters element of the output
|
||||||
// file's segment element. Returns false on error.
|
// file's segment element. Returns false on error.
|
||||||
|
|||||||
168
vttdemux.cc
168
vttdemux.cc
@@ -15,6 +15,11 @@
|
|||||||
#include "./mkvreader.hpp"
|
#include "./mkvreader.hpp"
|
||||||
#include "./webvttparser.h"
|
#include "./webvttparser.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
// Disable MSVC warnings that suggest making code non-portable.
|
||||||
|
#pragma warning(disable : 4996)
|
||||||
|
#endif
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
namespace vttdemux {
|
namespace vttdemux {
|
||||||
@@ -26,12 +31,7 @@ typedef std::auto_ptr<mkvparser::Segment> segment_ptr_t;
|
|||||||
// WebVTT metadata tracks have a type (encoded in the CodecID for the track).
|
// WebVTT metadata tracks have a type (encoded in the CodecID for the track).
|
||||||
// We use |type| to synthesize a filename for the out-of-band WebVTT |file|.
|
// We use |type| to synthesize a filename for the out-of-band WebVTT |file|.
|
||||||
struct MetadataInfo {
|
struct MetadataInfo {
|
||||||
enum Type {
|
enum Type { kSubtitles, kCaptions, kDescriptions, kMetadata, kChapters } type;
|
||||||
kSubtitles,
|
|
||||||
kCaptions,
|
|
||||||
kDescriptions,
|
|
||||||
kMetadata,
|
|
||||||
kChapters } type;
|
|
||||||
FILE* file;
|
FILE* file;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -125,45 +125,36 @@ bool ParseHeader(mkvparser::IMkvReader* reader, mkvpos_t* pos);
|
|||||||
|
|
||||||
// Parse the Segment of the input file and load all of its clusters.
|
// Parse the Segment of the input file and load all of its clusters.
|
||||||
// Returns false if there was an error parsing the file.
|
// Returns false if there was an error parsing the file.
|
||||||
bool ParseSegment(
|
bool ParseSegment(mkvparser::IMkvReader* reader, mkvpos_t pos,
|
||||||
mkvparser::IMkvReader* reader,
|
segment_ptr_t* segment);
|
||||||
mkvpos_t pos,
|
|
||||||
segment_ptr_t* segment);
|
|
||||||
|
|
||||||
// If |segment| has a Chapters element (in which case, there will be a
|
// If |segment| has a Chapters element (in which case, there will be a
|
||||||
// corresponding entry in |metadata_map|), convert the MKV chapters to
|
// corresponding entry in |metadata_map|), convert the MKV chapters to
|
||||||
// WebVTT chapter cues and write them to the output file. Returns
|
// WebVTT chapter cues and write them to the output file. Returns
|
||||||
// false on error.
|
// false on error.
|
||||||
bool WriteChaptersFile(
|
bool WriteChaptersFile(const metadata_map_t& metadata_map,
|
||||||
const metadata_map_t& metadata_map,
|
const mkvparser::Segment* segment);
|
||||||
const mkvparser::Segment* segment);
|
|
||||||
|
|
||||||
// Convert an MKV Chapters Atom to a WebVTT cue and write it to the
|
// Convert an MKV Chapters Atom to a WebVTT cue and write it to the
|
||||||
// output |file|. Returns false on error.
|
// output |file|. Returns false on error.
|
||||||
bool WriteChaptersCue(
|
bool WriteChaptersCue(FILE* file, const mkvparser::Chapters* chapters,
|
||||||
FILE* file,
|
const mkvparser::Chapters::Atom* atom,
|
||||||
const mkvparser::Chapters* chapters,
|
const mkvparser::Chapters::Display* display);
|
||||||
const mkvparser::Chapters::Atom* atom,
|
|
||||||
const mkvparser::Chapters::Display* display);
|
|
||||||
|
|
||||||
// Write the Cue Identifier line of the WebVTT cue, if it's present.
|
// Write the Cue Identifier line of the WebVTT cue, if it's present.
|
||||||
// Returns false on error.
|
// Returns false on error.
|
||||||
bool WriteChaptersCueIdentifier(
|
bool WriteChaptersCueIdentifier(FILE* file,
|
||||||
FILE* file,
|
const mkvparser::Chapters::Atom* atom);
|
||||||
const mkvparser::Chapters::Atom* atom);
|
|
||||||
|
|
||||||
// Use the timecodes from the chapters |atom| to write just the
|
// Use the timecodes from the chapters |atom| to write just the
|
||||||
// timings line of the WebVTT cue. Returns false on error.
|
// timings line of the WebVTT cue. Returns false on error.
|
||||||
bool WriteChaptersCueTimings(
|
bool WriteChaptersCueTimings(FILE* file, const mkvparser::Chapters* chapters,
|
||||||
FILE* file,
|
const mkvparser::Chapters::Atom* atom);
|
||||||
const mkvparser::Chapters* chapters,
|
|
||||||
const mkvparser::Chapters::Atom* atom);
|
|
||||||
|
|
||||||
// Parse the String sub-element of the |display| and write the payload
|
// Parse the String sub-element of the |display| and write the payload
|
||||||
// of the WebVTT cue. Returns false on error.
|
// of the WebVTT cue. Returns false on error.
|
||||||
bool WriteChaptersCuePayload(
|
bool WriteChaptersCuePayload(FILE* file,
|
||||||
FILE* file,
|
const mkvparser::Chapters::Display* display);
|
||||||
const mkvparser::Chapters::Display* display);
|
|
||||||
|
|
||||||
// Iterate over the tracks of the input file (and any chapters
|
// Iterate over the tracks of the input file (and any chapters
|
||||||
// element) and cache information about each metadata track.
|
// element) and cache information about each metadata track.
|
||||||
@@ -190,16 +181,14 @@ bool InitializeFiles(const metadata_map_t& metadata_map);
|
|||||||
// Iterate over the blocks of the |cluster|, writing a WebVTT cue to
|
// Iterate over the blocks of the |cluster|, writing a WebVTT cue to
|
||||||
// its associated output file for each block of metadata. Returns
|
// its associated output file for each block of metadata. Returns
|
||||||
// false if processing a block failed, or there was a parse error.
|
// false if processing a block failed, or there was a parse error.
|
||||||
bool ProcessCluster(
|
bool ProcessCluster(const metadata_map_t& metadata_map,
|
||||||
const metadata_map_t& metadata_map,
|
const mkvparser::Cluster* cluster);
|
||||||
const mkvparser::Cluster* cluster);
|
|
||||||
|
|
||||||
// Look up this track number in the cache, and if found (meaning this
|
// Look up this track number in the cache, and if found (meaning this
|
||||||
// is a metadata track), write a WebVTT cue to the associated output
|
// is a metadata track), write a WebVTT cue to the associated output
|
||||||
// file. Returns false if writing the WebVTT cue failed.
|
// file. Returns false if writing the WebVTT cue failed.
|
||||||
bool ProcessBlockEntry(
|
bool ProcessBlockEntry(const metadata_map_t& metadata_map,
|
||||||
const metadata_map_t& metadata_map,
|
const mkvparser::BlockEntry* block_entry);
|
||||||
const mkvparser::BlockEntry* block_entry);
|
|
||||||
|
|
||||||
// Parse the lines of text from the |block_group| to reconstruct the
|
// Parse the lines of text from the |block_group| to reconstruct the
|
||||||
// original WebVTT cue, and write it to the associated output |file|.
|
// original WebVTT cue, and write it to the associated output |file|.
|
||||||
@@ -215,24 +204,18 @@ bool WriteCueIdentifier(FILE* f, FrameParser* parser);
|
|||||||
// cue settings) and write the cue timings line for this cue to the
|
// cue settings) and write the cue timings line for this cue to the
|
||||||
// associated output file. Returns false if there was an error
|
// associated output file. Returns false if there was an error
|
||||||
// writing to the file.
|
// writing to the file.
|
||||||
bool WriteCueTimings(
|
bool WriteCueTimings(FILE* f, FrameParser* parser);
|
||||||
FILE* f,
|
|
||||||
FrameParser* parser);
|
|
||||||
|
|
||||||
// Write the timestamp (representating either the start time or stop
|
// Write the timestamp (representating either the start time or stop
|
||||||
// time of the cue) to the output file. Returns false if there was an
|
// time of the cue) to the output file. Returns false if there was an
|
||||||
// error writing to the file.
|
// error writing to the file.
|
||||||
bool WriteCueTime(
|
bool WriteCueTime(FILE* f, mkvtime_t time_ns);
|
||||||
FILE* f,
|
|
||||||
mkvtime_t time_ns);
|
|
||||||
|
|
||||||
// Consume the remaining lines of text from the character stream
|
// Consume the remaining lines of text from the character stream
|
||||||
// (these lines are the actual payload of the WebVTT cue), and write
|
// (these lines are the actual payload of the WebVTT cue), and write
|
||||||
// them to the associated output file. Returns false if there was an
|
// them to the associated output file. Returns false if there was an
|
||||||
// error writing to the file.
|
// error writing to the file.
|
||||||
bool WriteCuePayload(
|
bool WriteCuePayload(FILE* f, FrameParser* parser);
|
||||||
FILE* f,
|
|
||||||
FrameParser* parser);
|
|
||||||
} // namespace vttdemux
|
} // namespace vttdemux
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
@@ -299,8 +282,7 @@ FrameParser::FrameParser(const mkvparser::BlockGroup* block_group)
|
|||||||
pos_end_ = f.pos + f.len;
|
pos_end_ = f.pos + f.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameParser::~FrameParser() {
|
FrameParser::~FrameParser() {}
|
||||||
}
|
|
||||||
|
|
||||||
int FrameParser::GetChar(char* c) {
|
int FrameParser::GetChar(char* c) {
|
||||||
if (pos_ >= pos_end_) // end-of-stream
|
if (pos_ >= pos_end_) // end-of-stream
|
||||||
@@ -320,7 +302,7 @@ int FrameParser::GetChar(char* c) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameParser::UngetChar(char /* c */ ) {
|
void FrameParser::UngetChar(char /* c */) {
|
||||||
// All we need to do here is decrement the position in the stream.
|
// All we need to do here is decrement the position in the stream.
|
||||||
// The next time GetChar is called the same character will be
|
// The next time GetChar is called the same character will be
|
||||||
// re-read from the input file.
|
// re-read from the input file.
|
||||||
@@ -335,8 +317,7 @@ ChapterAtomParser::ChapterAtomParser(
|
|||||||
str_end_ = str_ + len;
|
str_end_ = str_ + len;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChapterAtomParser::~ChapterAtomParser() {
|
ChapterAtomParser::~ChapterAtomParser() {}
|
||||||
}
|
|
||||||
|
|
||||||
int ChapterAtomParser::GetChar(char* c) {
|
int ChapterAtomParser::GetChar(char* c) {
|
||||||
if (str_ >= str_end_) // end-of-stream
|
if (str_ >= str_end_) // end-of-stream
|
||||||
@@ -346,7 +327,7 @@ int ChapterAtomParser::GetChar(char* c) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChapterAtomParser::UngetChar(char /* c */ ) {
|
void ChapterAtomParser::UngetChar(char /* c */) {
|
||||||
// All we need to do here is decrement the position in the stream.
|
// All we need to do here is decrement the position in the stream.
|
||||||
// The next time GetChar is called the same character will be
|
// The next time GetChar is called the same character will be
|
||||||
// re-read from the input file.
|
// re-read from the input file.
|
||||||
@@ -355,9 +336,7 @@ void ChapterAtomParser::UngetChar(char /* c */ ) {
|
|||||||
|
|
||||||
} // namespace vttdemux
|
} // namespace vttdemux
|
||||||
|
|
||||||
bool vttdemux::ParseHeader(
|
bool vttdemux::ParseHeader(mkvparser::IMkvReader* reader, mkvpos_t* pos) {
|
||||||
mkvparser::IMkvReader* reader,
|
|
||||||
mkvpos_t* pos) {
|
|
||||||
mkvparser::EBMLHeader h;
|
mkvparser::EBMLHeader h;
|
||||||
const mkvpos_t status = h.Parse(reader, *pos);
|
const mkvpos_t status = h.Parse(reader, *pos);
|
||||||
|
|
||||||
@@ -366,7 +345,7 @@ bool vttdemux::ParseHeader(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(h.m_docType, "webm") != 0) {
|
if (h.m_docType == NULL || strcmp(h.m_docType, "webm") != 0) {
|
||||||
printf("bad doctype\n");
|
printf("bad doctype\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -374,10 +353,8 @@ bool vttdemux::ParseHeader(
|
|||||||
return true; // success
|
return true; // success
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vttdemux::ParseSegment(
|
bool vttdemux::ParseSegment(mkvparser::IMkvReader* reader, mkvpos_t pos,
|
||||||
mkvparser::IMkvReader* reader,
|
segment_ptr_t* segment_ptr) {
|
||||||
mkvpos_t pos,
|
|
||||||
segment_ptr_t* segment_ptr) {
|
|
||||||
// We first create the segment object.
|
// We first create the segment object.
|
||||||
|
|
||||||
mkvparser::Segment* p;
|
mkvparser::Segment* p;
|
||||||
@@ -402,9 +379,8 @@ bool vttdemux::ParseSegment(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vttdemux::BuildMap(
|
void vttdemux::BuildMap(const mkvparser::Segment* segment,
|
||||||
const mkvparser::Segment* segment,
|
metadata_map_t* map_ptr) {
|
||||||
metadata_map_t* map_ptr) {
|
|
||||||
metadata_map_t& m = *map_ptr;
|
metadata_map_t& m = *map_ptr;
|
||||||
m.clear();
|
m.clear();
|
||||||
|
|
||||||
@@ -551,7 +527,11 @@ bool vttdemux::OpenFiles(metadata_map_t* metadata_map, const char* filename) {
|
|||||||
if (exists[type] > 1) {
|
if (exists[type] > 1) {
|
||||||
enum { kLen = 33 };
|
enum { kLen = 33 };
|
||||||
char str[kLen]; // max 126 tracks, so only 4 chars really needed
|
char str[kLen]; // max 126 tracks, so only 4 chars really needed
|
||||||
|
#ifndef _MSC_VER
|
||||||
snprintf(str, kLen, "%ld", v.first); // track number
|
snprintf(str, kLen, "%ld", v.first); // track number
|
||||||
|
#else
|
||||||
|
_snprintf_s(str, sizeof(str), kLen, "%ld", v.first); // track number
|
||||||
|
#endif
|
||||||
name += str;
|
name += str;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,8 +543,9 @@ bool vttdemux::OpenFiles(metadata_map_t* metadata_map, const char* filename) {
|
|||||||
// open the WebVTT output file.
|
// open the WebVTT output file.
|
||||||
|
|
||||||
info.file = fopen(name.c_str(), "wb");
|
info.file = fopen(name.c_str(), "wb");
|
||||||
|
const bool success = (info.file != NULL);
|
||||||
|
|
||||||
if (info.file == NULL) {
|
if (!success) {
|
||||||
printf("unable to open output file %s\n", name.c_str());
|
printf("unable to open output file %s\n", name.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -640,9 +621,8 @@ bool vttdemux::InitializeFiles(const metadata_map_t& m) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vttdemux::WriteChaptersFile(
|
bool vttdemux::WriteChaptersFile(const metadata_map_t& m,
|
||||||
const metadata_map_t& m,
|
const mkvparser::Segment* s) {
|
||||||
const mkvparser::Segment* s) {
|
|
||||||
const metadata_map_t::const_iterator info_iter = m.find(kChaptersKey);
|
const metadata_map_t::const_iterator info_iter = m.find(kChaptersKey);
|
||||||
if (info_iter == m.end()) // no chapters, so nothing to do
|
if (info_iter == m.end()) // no chapters, so nothing to do
|
||||||
return true;
|
return true;
|
||||||
@@ -713,11 +693,9 @@ bool vttdemux::WriteChaptersFile(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vttdemux::WriteChaptersCue(
|
bool vttdemux::WriteChaptersCue(FILE* f, const mkvparser::Chapters* chapters,
|
||||||
FILE* f,
|
const mkvparser::Chapters::Atom* atom,
|
||||||
const mkvparser::Chapters* chapters,
|
const mkvparser::Chapters::Display* display) {
|
||||||
const mkvparser::Chapters::Atom* atom,
|
|
||||||
const mkvparser::Chapters::Display* display) {
|
|
||||||
// We start a new cue by writing a cue separator (an empty line)
|
// We start a new cue by writing a cue separator (an empty line)
|
||||||
// into the stream.
|
// into the stream.
|
||||||
|
|
||||||
@@ -741,9 +719,7 @@ bool vttdemux::WriteChaptersCue(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool vttdemux::WriteChaptersCueIdentifier(
|
bool vttdemux::WriteChaptersCueIdentifier(
|
||||||
FILE* f,
|
FILE* f, const mkvparser::Chapters::Atom* atom) {
|
||||||
const mkvparser::Chapters::Atom* atom) {
|
|
||||||
|
|
||||||
const char* const identifier = atom->GetStringUID();
|
const char* const identifier = atom->GetStringUID();
|
||||||
|
|
||||||
if (identifier == NULL)
|
if (identifier == NULL)
|
||||||
@@ -755,10 +731,9 @@ bool vttdemux::WriteChaptersCueIdentifier(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vttdemux::WriteChaptersCueTimings(
|
bool vttdemux::WriteChaptersCueTimings(FILE* f,
|
||||||
FILE* f,
|
const mkvparser::Chapters* chapters,
|
||||||
const mkvparser::Chapters* chapters,
|
const mkvparser::Chapters::Atom* atom) {
|
||||||
const mkvparser::Chapters::Atom* atom) {
|
|
||||||
const mkvtime_t start_ns = atom->GetStartTime(chapters);
|
const mkvtime_t start_ns = atom->GetStartTime(chapters);
|
||||||
|
|
||||||
if (start_ns < 0)
|
if (start_ns < 0)
|
||||||
@@ -785,8 +760,7 @@ bool vttdemux::WriteChaptersCueTimings(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool vttdemux::WriteChaptersCuePayload(
|
bool vttdemux::WriteChaptersCuePayload(
|
||||||
FILE* f,
|
FILE* f, const mkvparser::Chapters::Display* display) {
|
||||||
const mkvparser::Chapters::Display* display) {
|
|
||||||
// Bind a Chapter parser object to the display, which allows us to
|
// Bind a Chapter parser object to the display, which allows us to
|
||||||
// extract each line of text from the title-part of the display.
|
// extract each line of text from the title-part of the display.
|
||||||
ChapterAtomParser parser(display);
|
ChapterAtomParser parser(display);
|
||||||
@@ -813,16 +787,15 @@ bool vttdemux::WriteChaptersCuePayload(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vttdemux::ProcessCluster(
|
bool vttdemux::ProcessCluster(const metadata_map_t& m,
|
||||||
const metadata_map_t& m,
|
const mkvparser::Cluster* c) {
|
||||||
const mkvparser::Cluster* c) {
|
|
||||||
// Visit the blocks in this cluster, writing a WebVTT cue for each
|
// Visit the blocks in this cluster, writing a WebVTT cue for each
|
||||||
// metadata block.
|
// metadata block.
|
||||||
|
|
||||||
const mkvparser::BlockEntry* block_entry;
|
const mkvparser::BlockEntry* block_entry;
|
||||||
|
|
||||||
long result = c->GetFirst(block_entry); // NOLINT
|
long result = c->GetFirst(block_entry); // NOLINT
|
||||||
if (result < 0) { // error
|
if (result < 0) {
|
||||||
printf("bad cluster (unable to get first block)\n");
|
printf("bad cluster (unable to get first block)\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -841,9 +814,8 @@ bool vttdemux::ProcessCluster(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vttdemux::ProcessBlockEntry(
|
bool vttdemux::ProcessBlockEntry(const metadata_map_t& m,
|
||||||
const metadata_map_t& m,
|
const mkvparser::BlockEntry* block_entry) {
|
||||||
const mkvparser::BlockEntry* block_entry) {
|
|
||||||
// If the track number for this block is in the cache, then we have
|
// If the track number for this block is in the cache, then we have
|
||||||
// a metadata block, so write the WebVTT cue to the output file.
|
// a metadata block, so write the WebVTT cue to the output file.
|
||||||
|
|
||||||
@@ -851,10 +823,10 @@ bool vttdemux::ProcessBlockEntry(
|
|||||||
const long long tn = block->GetTrackNumber(); // NOLINT
|
const long long tn = block->GetTrackNumber(); // NOLINT
|
||||||
|
|
||||||
typedef metadata_map_t::const_iterator iter_t;
|
typedef metadata_map_t::const_iterator iter_t;
|
||||||
const iter_t i = m.find(tn);
|
const iter_t i = m.find(static_cast<metadata_map_t::key_type>(tn));
|
||||||
|
|
||||||
if (i == m.end()) // not a metadata track
|
if (i == m.end()) // not a metadata track
|
||||||
return true; // nothing else to do
|
return true; // nothing else to do
|
||||||
|
|
||||||
if (block_entry->GetKind() != mkvparser::BlockEntry::kBlockGroup)
|
if (block_entry->GetKind() != mkvparser::BlockEntry::kBlockGroup)
|
||||||
return false; // weird
|
return false; // weird
|
||||||
@@ -868,9 +840,7 @@ bool vttdemux::ProcessBlockEntry(
|
|||||||
return WriteCue(f, block_group);
|
return WriteCue(f, block_group);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vttdemux::WriteCue(
|
bool vttdemux::WriteCue(FILE* f, const mkvparser::BlockGroup* block_group) {
|
||||||
FILE* f,
|
|
||||||
const mkvparser::BlockGroup* block_group) {
|
|
||||||
// Bind a FrameParser object to the block, which allows us to
|
// Bind a FrameParser object to the block, which allows us to
|
||||||
// extract each line of text from the payload of the block.
|
// extract each line of text from the payload of the block.
|
||||||
FrameParser parser(block_group);
|
FrameParser parser(block_group);
|
||||||
@@ -897,9 +867,7 @@ bool vttdemux::WriteCue(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vttdemux::WriteCueIdentifier(
|
bool vttdemux::WriteCueIdentifier(FILE* f, FrameParser* parser) {
|
||||||
FILE* f,
|
|
||||||
FrameParser* parser) {
|
|
||||||
string line;
|
string line;
|
||||||
int e = parser->GetLine(&line);
|
int e = parser->GetLine(&line);
|
||||||
|
|
||||||
@@ -922,9 +890,7 @@ bool vttdemux::WriteCueIdentifier(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vttdemux::WriteCueTimings(
|
bool vttdemux::WriteCueTimings(FILE* f, FrameParser* parser) {
|
||||||
FILE* f,
|
|
||||||
FrameParser* parser) {
|
|
||||||
const mkvparser::BlockGroup* const block_group = parser->block_group_;
|
const mkvparser::BlockGroup* const block_group = parser->block_group_;
|
||||||
const mkvparser::Cluster* const cluster = block_group->GetCluster();
|
const mkvparser::Cluster* const cluster = block_group->GetCluster();
|
||||||
const mkvparser::Block* const block = block_group->GetBlock();
|
const mkvparser::Block* const block = block_group->GetBlock();
|
||||||
@@ -986,9 +952,7 @@ bool vttdemux::WriteCueTimings(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vttdemux::WriteCueTime(
|
bool vttdemux::WriteCueTime(FILE* f, mkvtime_t time_ns) {
|
||||||
FILE* f,
|
|
||||||
mkvtime_t time_ns) {
|
|
||||||
mkvtime_t ms = time_ns / 1000000; // WebVTT time has millisecond resolution
|
mkvtime_t ms = time_ns / 1000000; // WebVTT time has millisecond resolution
|
||||||
|
|
||||||
mkvtime_t sec = ms / 1000;
|
mkvtime_t sec = ms / 1000;
|
||||||
@@ -1006,14 +970,12 @@ bool vttdemux::WriteCueTime(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fprintf(f, "%02lld:%02lld.%03lld", min, sec, ms) < 0)
|
if (fprintf(f, "%02lld:%02lld.%03lld", min, sec, ms) < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vttdemux::WriteCuePayload(
|
bool vttdemux::WriteCuePayload(FILE* f, FrameParser* parser) {
|
||||||
FILE* f,
|
|
||||||
FrameParser* parser) {
|
|
||||||
int count = 0; // count of lines of payload text written to output file
|
int count = 0; // count of lines of payload text written to output file
|
||||||
for (string line;;) {
|
for (string line;;) {
|
||||||
const int e = parser->GetLine(&line);
|
const int e = parser->GetLine(&line);
|
||||||
|
|||||||
12
vttreader.cc
12
vttreader.cc
@@ -8,14 +8,16 @@
|
|||||||
|
|
||||||
#include "./vttreader.h" // NOLINT
|
#include "./vttreader.h" // NOLINT
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
// Disable MSVC warnings that suggest making code non-portable.
|
||||||
|
#pragma warning(disable : 4996)
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace libwebvtt {
|
namespace libwebvtt {
|
||||||
|
|
||||||
VttReader::VttReader() : file_(NULL) {
|
VttReader::VttReader() : file_(NULL) {}
|
||||||
}
|
|
||||||
|
|
||||||
VttReader::~VttReader() {
|
VttReader::~VttReader() { Close(); }
|
||||||
Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
int VttReader::Open(const char* filename) {
|
int VttReader::Open(const char* filename) {
|
||||||
if (filename == NULL || file_ != NULL)
|
if (filename == NULL || file_ != NULL)
|
||||||
|
|||||||
517
webm2pes.cc
Normal file
517
webm2pes.cc
Normal file
@@ -0,0 +1,517 @@
|
|||||||
|
// Copyright (c) 2015 The WebM project authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style license
|
||||||
|
// that can be found in the LICENSE file in the root of the source
|
||||||
|
// tree. An additional intellectual property rights grant can be found
|
||||||
|
// in the file PATENTS. All contributing project authors may
|
||||||
|
// be found in the AUTHORS file in the root of the source tree.
|
||||||
|
#include "webm2pes.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void Usage(const char* argv[]) {
|
||||||
|
printf("Usage: %s <WebM file> <output file>", argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteUint8(std::uint8_t val, std::FILE* fileptr) {
|
||||||
|
if (fileptr == nullptr)
|
||||||
|
return false;
|
||||||
|
return (std::fputc(val, fileptr) == val);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Range {
|
||||||
|
Range(std::size_t off, std::size_t len) : offset(off), length(len) {}
|
||||||
|
Range() = delete;
|
||||||
|
Range(const Range&) = default;
|
||||||
|
Range(Range&&) = default;
|
||||||
|
~Range() = default;
|
||||||
|
const std::size_t offset;
|
||||||
|
const std::size_t length;
|
||||||
|
};
|
||||||
|
typedef std::vector<Range> FrameRanges;
|
||||||
|
|
||||||
|
// Returns true and stores frame offsets and lengths in |frame_ranges| when
|
||||||
|
// |frame| has a valid VP9 super frame index.
|
||||||
|
bool ParseVP9SuperFrameIndex(const std::uint8_t* frame,
|
||||||
|
std::size_t length,
|
||||||
|
FrameRanges* frame_ranges) {
|
||||||
|
if (frame == nullptr || length == 0 || frame_ranges == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool parse_ok = false;
|
||||||
|
const std::uint8_t marker = frame[length - 1];
|
||||||
|
const std::uint32_t kHasSuperFrameIndexMask = 0xe0;
|
||||||
|
const std::uint32_t kSuperFrameMarker = 0xc0;
|
||||||
|
|
||||||
|
if ((marker & kHasSuperFrameIndexMask) == kSuperFrameMarker) {
|
||||||
|
const std::uint32_t kFrameCountMask = 0x7;
|
||||||
|
const int num_frames = (marker & kFrameCountMask) + 1;
|
||||||
|
const int length_field_size = ((marker >> 3) & 0x3) + 1;
|
||||||
|
const std::size_t index_length = 2 + length_field_size * num_frames;
|
||||||
|
|
||||||
|
// Consume the super frame index.
|
||||||
|
std::size_t frame_offset = index_length;
|
||||||
|
|
||||||
|
if (length >= index_length && frame[length - index_length] == marker) {
|
||||||
|
// Found a valid superframe index.
|
||||||
|
const std::uint8_t* byte = frame + length - index_length + 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < num_frames; ++i) {
|
||||||
|
std::uint32_t child_frame_length = 0;
|
||||||
|
|
||||||
|
for (int j = 0; j < length_field_size; ++j) {
|
||||||
|
child_frame_length |= (*byte++) << (j * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
frame_ranges->push_back(Range(frame_offset, child_frame_length));
|
||||||
|
frame_offset += child_frame_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame_ranges->size() != num_frames) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: superframe index parse failed.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_ok = true;
|
||||||
|
} else {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: Invalid superframe index.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return parse_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::int64_t NanosecondsTo90KhzTicks(std::int64_t nanoseconds) {
|
||||||
|
const double kNanosecondsPerSecond = 1000000000.0;
|
||||||
|
const double pts_seconds = nanoseconds / kNanosecondsPerSecond;
|
||||||
|
return pts_seconds * 90000;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetPacketPayloadRanges(const libwebm::PesHeader& header,
|
||||||
|
const FrameRanges& frame_ranges,
|
||||||
|
FrameRanges* packet_payload_ranges) {
|
||||||
|
// TODO(tomfinegan): The length field in PES is actually number of bytes that
|
||||||
|
// follow the length field, and does not include the 6 byte fixed portion of
|
||||||
|
// the header (4 byte start code + 2 bytes for the length). We can fit in 6
|
||||||
|
// more bytes if we really want to, and avoid packetization when size is very
|
||||||
|
// close to UINT16_MAX.
|
||||||
|
if (packet_payload_ranges == nullptr) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: nullptr getting payload ranges.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::size_t kMaxPacketPayloadSize = UINT16_MAX - header.size();
|
||||||
|
|
||||||
|
for (const Range& frame_range : frame_ranges) {
|
||||||
|
if (frame_range.length + header.size() > kMaxPacketPayloadSize) {
|
||||||
|
// make packet ranges until range.length is exhausted
|
||||||
|
const std::size_t kBytesToPacketize = frame_range.length;
|
||||||
|
std::size_t packet_payload_length = 0;
|
||||||
|
for (std::size_t pos = 0; pos < kBytesToPacketize;
|
||||||
|
pos += packet_payload_length) {
|
||||||
|
packet_payload_length =
|
||||||
|
(frame_range.length - pos < kMaxPacketPayloadSize)
|
||||||
|
? frame_range.length - pos
|
||||||
|
: kMaxPacketPayloadSize;
|
||||||
|
packet_payload_ranges->push_back(
|
||||||
|
Range(frame_range.offset + pos, packet_payload_length));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// copy range into |packet_ranges|
|
||||||
|
packet_payload_ranges->push_back(
|
||||||
|
Range(frame_range.offset, frame_range.length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace libwebm {
|
||||||
|
|
||||||
|
//
|
||||||
|
// PesOptionalHeader methods.
|
||||||
|
//
|
||||||
|
|
||||||
|
void PesOptionalHeader::SetPtsBits(std::int64_t pts_90khz) {
|
||||||
|
std::uint64_t* pts_bits = &pts.bits;
|
||||||
|
*pts_bits = 0;
|
||||||
|
|
||||||
|
// PTS is broken up and stored in 40 bits as shown:
|
||||||
|
//
|
||||||
|
// PES PTS Only flag
|
||||||
|
// / Marker Marker Marker
|
||||||
|
// | / / /
|
||||||
|
// | | | |
|
||||||
|
// 7654 321 0 765432107654321 0 765432107654321 0
|
||||||
|
// 0010 PTS 32-30 1 PTS 29-15 1 PTS 14-0 1
|
||||||
|
const std::uint32_t pts1 = (pts_90khz >> 30) & 0x7;
|
||||||
|
const std::uint32_t pts2 = (pts_90khz >> 15) & 0x7FFF;
|
||||||
|
const std::uint32_t pts3 = pts_90khz & 0x7FFF;
|
||||||
|
|
||||||
|
std::uint8_t buffer[5] = {0};
|
||||||
|
// PTS only flag.
|
||||||
|
buffer[0] |= 1 << 5;
|
||||||
|
// Top 3 bits of PTS and 1 bit marker.
|
||||||
|
buffer[0] |= pts1 << 1;
|
||||||
|
// Marker.
|
||||||
|
buffer[0] |= 1;
|
||||||
|
|
||||||
|
// Next 15 bits of pts and 1 bit marker.
|
||||||
|
// Top 8 bits of second PTS chunk.
|
||||||
|
buffer[1] |= (pts2 >> 7) & 0xff;
|
||||||
|
// bottom 7 bits of second PTS chunk.
|
||||||
|
buffer[2] |= (pts2 << 1);
|
||||||
|
// Marker.
|
||||||
|
buffer[2] |= 1;
|
||||||
|
|
||||||
|
// Last 15 bits of pts and 1 bit marker.
|
||||||
|
// Top 8 bits of second PTS chunk.
|
||||||
|
buffer[3] |= (pts3 >> 7) & 0xff;
|
||||||
|
// bottom 7 bits of second PTS chunk.
|
||||||
|
buffer[4] |= (pts3 << 1);
|
||||||
|
// Marker.
|
||||||
|
buffer[4] |= 1;
|
||||||
|
|
||||||
|
// Write bits into PesHeaderField.
|
||||||
|
std::memcpy(reinterpret_cast<std::uint8_t*>(pts_bits), buffer, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes fields to |file| and returns true. Returns false when write or
|
||||||
|
// field value validation fails.
|
||||||
|
bool PesOptionalHeader::Write(std::FILE* file, bool write_pts) const {
|
||||||
|
if (file == nullptr) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: nullptr in opt header writer.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint8_t header[9] = {0};
|
||||||
|
std::uint8_t* byte = header;
|
||||||
|
|
||||||
|
if (marker.Check() != true || scrambling.Check() != true ||
|
||||||
|
priority.Check() != true || data_alignment.Check() != true ||
|
||||||
|
copyright.Check() != true || original.Check() != true ||
|
||||||
|
has_pts.Check() != true || has_dts.Check() != true ||
|
||||||
|
pts.Check() != true || stuffing_byte.Check() != true) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: Invalid PES Optional Header field.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(tomfinegan): As noted in above, the PesHeaderFields should be an
|
||||||
|
// array (or some data structure) that can be iterated over.
|
||||||
|
|
||||||
|
// First byte of header, fields: marker, scrambling, priority, alignment,
|
||||||
|
// copyright, original.
|
||||||
|
*byte = 0;
|
||||||
|
*byte |= marker.bits << marker.shift;
|
||||||
|
*byte |= scrambling.bits << scrambling.shift;
|
||||||
|
*byte |= priority.bits << priority.shift;
|
||||||
|
*byte |= data_alignment.bits << data_alignment.shift;
|
||||||
|
*byte |= copyright.bits << copyright.shift;
|
||||||
|
*byte |= original.bits << original.shift;
|
||||||
|
|
||||||
|
// Second byte of header, fields: has_pts, has_dts, unused fields.
|
||||||
|
*++byte = 0;
|
||||||
|
if (write_pts == true) {
|
||||||
|
*byte |= has_pts.bits << has_pts.shift;
|
||||||
|
*byte |= has_dts.bits << has_dts.shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Third byte of header, fields: remaining size of header.
|
||||||
|
*++byte = remaining_size.bits; // Field is 8 bits wide.
|
||||||
|
|
||||||
|
int num_stuffing_bytes =
|
||||||
|
(pts.num_bits + 7) / 8 + 1 /* always 1 stuffing byte */;
|
||||||
|
if (write_pts == true) {
|
||||||
|
// Set the PTS value and adjust stuffing byte count accordingly.
|
||||||
|
*++byte = (pts.bits >> 32) & 0xff;
|
||||||
|
*++byte = (pts.bits >> 24) & 0xff;
|
||||||
|
*++byte = (pts.bits >> 16) & 0xff;
|
||||||
|
*++byte = (pts.bits >> 8) & 0xff;
|
||||||
|
*++byte = pts.bits & 0xff;
|
||||||
|
num_stuffing_bytes = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the stuffing byte(s).
|
||||||
|
for (int i = 0; i < num_stuffing_bytes; ++i)
|
||||||
|
*++byte = stuffing_byte.bits;
|
||||||
|
|
||||||
|
if (std::fwrite(reinterpret_cast<void*>(header), 1, size_in_bytes(), file) !=
|
||||||
|
size_in_bytes()) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: unable to write PES opt header to file.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// BCMVHeader methods.
|
||||||
|
//
|
||||||
|
|
||||||
|
bool BCMVHeader::Write(std::FILE* fileptr) const {
|
||||||
|
if (fileptr == nullptr) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: nullptr for file in BCMV Write.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (std::fwrite(bcmv, 1, 4, fileptr) != 4) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: BCMV write failed.\n");
|
||||||
|
}
|
||||||
|
const std::size_t kRemainingBytes = 6;
|
||||||
|
const uint8_t buffer[kRemainingBytes] = {(length >> 24) & 0xff,
|
||||||
|
(length >> 16) & 0xff,
|
||||||
|
(length >> 8) & 0xff,
|
||||||
|
length & 0xff,
|
||||||
|
0,
|
||||||
|
0 /* 2 bytes 0 padding */};
|
||||||
|
for (std::int8_t i = 0; i < kRemainingBytes; ++i) {
|
||||||
|
if (WriteUint8(buffer[i], fileptr) != true) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: BCMV remainder write failed.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// PesHeader methods.
|
||||||
|
//
|
||||||
|
|
||||||
|
// Writes out the header to |file|. Calls PesOptionalHeader::Write() to write
|
||||||
|
// |optional_header| contents. Returns true when successful, false otherwise.
|
||||||
|
bool PesHeader::Write(std::FILE* file, bool write_pts) const {
|
||||||
|
if (file == nullptr) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: nullptr in header writer.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write |start_code|.
|
||||||
|
if (std::fwrite(reinterpret_cast<const void*>(start_code), 1, 4, file) != 4) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: cannot write packet start code.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write |packet_length| as big endian.
|
||||||
|
std::uint8_t byte = (packet_length >> 8) & 0xff;
|
||||||
|
if (WriteUint8(byte, file) != true) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: cannot write packet length (byte 0).\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
byte = packet_length & 0xff;
|
||||||
|
if (WriteUint8(byte, file) != true) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: cannot write packet length (byte 1).\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the (not really) optional header.
|
||||||
|
if (optional_header.Write(file, write_pts) != true) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: PES optional header write failed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Webm2Pes methods.
|
||||||
|
//
|
||||||
|
|
||||||
|
bool Webm2Pes::Convert() {
|
||||||
|
if (input_file_name_.empty() || output_file_name_.empty()) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: input and/or output file name(s) empty.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (webm_reader_.Open(input_file_name_.c_str()) != 0) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: Cannot open %s as input.\n",
|
||||||
|
input_file_name_.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
output_file_ = FilePtr(fopen(output_file_name_.c_str(), "wb"), FILEDeleter());
|
||||||
|
if (output_file_ == nullptr) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: Cannot open %s for output.\n",
|
||||||
|
output_file_name_.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
using mkvparser::Segment;
|
||||||
|
Segment* webm_parser = nullptr;
|
||||||
|
if (Segment::CreateInstance(&webm_reader_, 0 /* pos */,
|
||||||
|
webm_parser /* Segment*& */) != 0) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: Cannot create WebM parser.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
webm_parser_.reset(webm_parser);
|
||||||
|
|
||||||
|
if (webm_parser_->Load() != 0) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: Cannot parse %s.\n",
|
||||||
|
input_file_name_.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store timecode scale.
|
||||||
|
timecode_scale_ = webm_parser_->GetInfo()->GetTimeCodeScale();
|
||||||
|
|
||||||
|
// Make sure there's a video track.
|
||||||
|
const mkvparser::Tracks* tracks = webm_parser_->GetTracks();
|
||||||
|
if (tracks == nullptr) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: %s has no tracks.\n",
|
||||||
|
input_file_name_.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int track_index = 0; track_index < tracks->GetTracksCount();
|
||||||
|
++track_index) {
|
||||||
|
const mkvparser::Track* track = tracks->GetTrackByIndex(track_index);
|
||||||
|
if (track && track->GetType() == mkvparser::Track::kVideo) {
|
||||||
|
if (std::string(track->GetCodecId()) == std::string("V_VP8"))
|
||||||
|
codec_ = VP8;
|
||||||
|
else if (std::string(track->GetCodecId()) == std::string("V_VP9"))
|
||||||
|
codec_ = VP9;
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "Webm2Pes: Codec must be VP8 or VP9.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
video_track_num_ = track_index + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (video_track_num_ < 1) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: No video track found in %s.\n",
|
||||||
|
input_file_name_.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk clusters in segment.
|
||||||
|
const mkvparser::Cluster* cluster = webm_parser_->GetFirst();
|
||||||
|
while (cluster != nullptr && cluster->EOS() == false) {
|
||||||
|
const mkvparser::BlockEntry* block_entry = nullptr;
|
||||||
|
std::int64_t block_status = cluster->GetFirst(block_entry);
|
||||||
|
if (block_status < 0) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: Cannot parse first block in %s.\n",
|
||||||
|
input_file_name_.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk blocks in cluster.
|
||||||
|
while (block_entry != nullptr && block_entry->EOS() == false) {
|
||||||
|
const mkvparser::Block* block = block_entry->GetBlock();
|
||||||
|
if (block->GetTrackNumber() == video_track_num_) {
|
||||||
|
const int frame_count = block->GetFrameCount();
|
||||||
|
|
||||||
|
// Walk frames in block.
|
||||||
|
for (int frame_num = 0; frame_num < frame_count; ++frame_num) {
|
||||||
|
const mkvparser::Block::Frame& frame = block->GetFrame(frame_num);
|
||||||
|
|
||||||
|
// Write frame out as PES packet(s).
|
||||||
|
const bool pes_status =
|
||||||
|
WritePesPacket(frame, block->GetTime(cluster));
|
||||||
|
if (pes_status != true) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: WritePesPacket failed.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
block_status = cluster->GetNext(block_entry, block_entry);
|
||||||
|
if (block_status < 0) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: Cannot parse block in %s.\n",
|
||||||
|
input_file_name_.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cluster = webm_parser_->GetNext(cluster);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Webm2Pes::WritePesPacket(const mkvparser::Block::Frame& vpx_frame,
|
||||||
|
double nanosecond_pts) {
|
||||||
|
// Read the input frame.
|
||||||
|
std::unique_ptr<uint8_t[]> frame_data(new (std::nothrow)
|
||||||
|
uint8_t[vpx_frame.len]);
|
||||||
|
if (frame_data.get() == nullptr) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: Out of memory.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (vpx_frame.Read(&webm_reader_, frame_data.get()) != 0) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: Error reading VPx frame!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FrameRanges frame_ranges;
|
||||||
|
if (codec_ == VP9) {
|
||||||
|
bool has_superframe_index =
|
||||||
|
ParseVP9SuperFrameIndex(frame_data.get(), vpx_frame.len, &frame_ranges);
|
||||||
|
if (has_superframe_index == false) {
|
||||||
|
frame_ranges.push_back(Range(0, vpx_frame.len));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
frame_ranges.push_back(Range(0, vpx_frame.len));
|
||||||
|
}
|
||||||
|
|
||||||
|
PesHeader header;
|
||||||
|
FrameRanges packet_payload_ranges;
|
||||||
|
if (GetPacketPayloadRanges(header, frame_ranges, &packet_payload_ranges) !=
|
||||||
|
true) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: Error preparing packet payload ranges!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// TODO: DEBUG/REMOVE
|
||||||
|
///
|
||||||
|
printf("-FRAME TOTAL LENGTH %ld--\n", vpx_frame.len);
|
||||||
|
for (const Range& frame_range : frame_ranges) {
|
||||||
|
printf("--frame range: off:%lu len:%lu\n", frame_range.offset,
|
||||||
|
frame_range.length);
|
||||||
|
}
|
||||||
|
for (const Range& payload_range : packet_payload_ranges) {
|
||||||
|
printf("---payload range: off:%lu len:%lu\n", payload_range.offset,
|
||||||
|
payload_range.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::int64_t khz90_pts = NanosecondsTo90KhzTicks(nanosecond_pts);
|
||||||
|
header.optional_header.SetPtsBits(khz90_pts);
|
||||||
|
|
||||||
|
bool write_pts = true;
|
||||||
|
for (const Range& packet_payload_range : packet_payload_ranges) {
|
||||||
|
header.packet_length =
|
||||||
|
header.optional_header.size_in_bytes() + packet_payload_range.length;
|
||||||
|
if (header.Write(output_file_.get(), write_pts) != true) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: packet header write failed.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_pts = false;
|
||||||
|
|
||||||
|
BCMVHeader bcmv_header(packet_payload_range.length);
|
||||||
|
if (bcmv_header.Write(output_file_.get()) != true) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: BCMV write failed.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the payload.
|
||||||
|
if (std::fwrite(frame_data.get() + packet_payload_range.offset, 1,
|
||||||
|
packet_payload_range.length,
|
||||||
|
output_file_.get()) != packet_payload_range.length) {
|
||||||
|
std::fprintf(stderr, "Webm2Pes: packet payload write failed.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} // namespace libwebm
|
||||||
|
|
||||||
|
int main(int argc, const char* argv[]) {
|
||||||
|
if (argc < 3) {
|
||||||
|
Usage(argv);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string input_path = argv[1];
|
||||||
|
const std::string output_path = argv[2];
|
||||||
|
|
||||||
|
libwebm::Webm2Pes converter(input_path, output_path);
|
||||||
|
return converter.Convert() == true ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
|
}
|
||||||
209
webm2pes.h
Normal file
209
webm2pes.h
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
// Copyright (c) 2015 The WebM project authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style license
|
||||||
|
// that can be found in the LICENSE file in the root of the source
|
||||||
|
// tree. An additional intellectual property rights grant can be found
|
||||||
|
// in the file PATENTS. All contributing project authors may
|
||||||
|
// be found in the AUTHORS file in the root of the source tree.
|
||||||
|
#ifndef LIBWEBM_WEBM2PES_H_
|
||||||
|
#define LIBWEBM_WEBM2PES_H_
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "mkvparser.hpp"
|
||||||
|
#include "mkvreader.hpp"
|
||||||
|
|
||||||
|
namespace libwebm {
|
||||||
|
|
||||||
|
// Stores a value and its size in bits for writing into a PES Optional Header.
|
||||||
|
// Maximum size is 64 bits. Users may call the Check() method to perform minimal
|
||||||
|
// validation (size > 0 and <= 64).
|
||||||
|
struct PesHeaderField {
|
||||||
|
PesHeaderField(std::uint64_t value,
|
||||||
|
std::uint32_t size_in_bits,
|
||||||
|
std::uint8_t byte_index,
|
||||||
|
std::uint8_t bits_to_shift)
|
||||||
|
: bits(value),
|
||||||
|
num_bits(size_in_bits),
|
||||||
|
index(byte_index),
|
||||||
|
shift(bits_to_shift) {}
|
||||||
|
PesHeaderField() = delete;
|
||||||
|
PesHeaderField(const PesHeaderField&) = default;
|
||||||
|
PesHeaderField(PesHeaderField&&) = default;
|
||||||
|
~PesHeaderField() = default;
|
||||||
|
bool Check() const {
|
||||||
|
return num_bits > 0 && num_bits <= 64 && shift >= 0 && shift < 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value to be stored in the field.
|
||||||
|
std::uint64_t bits;
|
||||||
|
|
||||||
|
// Number of bits in the value.
|
||||||
|
const std::uint32_t num_bits;
|
||||||
|
|
||||||
|
// Index into the header for the byte in which |bits| will be written.
|
||||||
|
const std::uint8_t index;
|
||||||
|
|
||||||
|
// Number of bits to shift value before or'ing.
|
||||||
|
const std::uint8_t shift;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Storage for PES Optional Header values. Fields written in order using sizes
|
||||||
|
// specified.
|
||||||
|
struct PesOptionalHeader {
|
||||||
|
// TODO(tomfinegan): The fields could be in an array, which would allow the
|
||||||
|
// code writing the optional header to iterate over the fields instead of
|
||||||
|
// having code for dealing with each one.
|
||||||
|
|
||||||
|
// 2 bits (marker): 2 ('10')
|
||||||
|
const PesHeaderField marker = PesHeaderField(2, 2, 0, 6);
|
||||||
|
|
||||||
|
// 2 bits (no scrambling): 0x0 ('00')
|
||||||
|
const PesHeaderField scrambling = PesHeaderField(0, 2, 0, 4);
|
||||||
|
|
||||||
|
// 1 bit (priority): 0x0 ('0')
|
||||||
|
const PesHeaderField priority = PesHeaderField(0, 1, 0, 3);
|
||||||
|
|
||||||
|
// TODO(tomfinegan): The BCMV header could be considered a sync word, and this
|
||||||
|
// field should be 1 when a sync word follows the packet. Clarify.
|
||||||
|
// 1 bit (data alignment): 0x0 ('0')
|
||||||
|
const PesHeaderField data_alignment = PesHeaderField(0, 1, 0, 2);
|
||||||
|
|
||||||
|
// 1 bit (copyright): 0x0 ('0')
|
||||||
|
const PesHeaderField copyright = PesHeaderField(0, 1, 0, 1);
|
||||||
|
|
||||||
|
// 1 bit (original/copy): 0x0 ('0')
|
||||||
|
const PesHeaderField original = PesHeaderField(0, 1, 0, 0);
|
||||||
|
|
||||||
|
// 1 bit (has_pts): 0x1 ('1')
|
||||||
|
const PesHeaderField has_pts = PesHeaderField(1, 1, 1, 7);
|
||||||
|
|
||||||
|
// 1 bit (has_dts): 0x0 ('0')
|
||||||
|
const PesHeaderField has_dts = PesHeaderField(0, 1, 1, 6);
|
||||||
|
|
||||||
|
// 6 bits (unused fields): 0x0 ('000000')
|
||||||
|
const PesHeaderField unused = PesHeaderField(0, 6, 1, 0);
|
||||||
|
|
||||||
|
// 8 bits (size of remaining data in the Header).
|
||||||
|
const PesHeaderField remaining_size = PesHeaderField(6, 8, 2, 0);
|
||||||
|
|
||||||
|
// PTS: 5 bytes
|
||||||
|
// 4 bits (flag: PTS present, but no DTS): 0x2 ('0010')
|
||||||
|
// 36 bits (90khz PTS):
|
||||||
|
// top 3 bits
|
||||||
|
// marker ('1')
|
||||||
|
// middle 15 bits
|
||||||
|
// marker ('1')
|
||||||
|
// bottom 15 bits
|
||||||
|
// marker ('1')
|
||||||
|
PesHeaderField pts = PesHeaderField(0, 40, 3, 0);
|
||||||
|
|
||||||
|
PesHeaderField stuffing_byte = PesHeaderField(0xFF, 8, 8, 0);
|
||||||
|
|
||||||
|
// PTS omitted in fragments. Size remains unchanged: More stuffing bytes.
|
||||||
|
bool fragment = false;
|
||||||
|
|
||||||
|
static std::size_t size_in_bytes() { return 9; }
|
||||||
|
|
||||||
|
// Writes |pts_90khz| to |pts| per format described at its declaration above.
|
||||||
|
void SetPtsBits(std::int64_t pts_90khz);
|
||||||
|
|
||||||
|
// Writes fields to |file| and returns true. Returns false when write or
|
||||||
|
// field value validation fails.
|
||||||
|
bool Write(std::FILE* file, bool write_pts) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Describes custom 10 byte header that immediately follows the PES Optional
|
||||||
|
// Header in each PES packet output by Webm2Pes:
|
||||||
|
// 4 byte 'B' 'C' 'M' 'V'
|
||||||
|
// 4 byte big-endian length of frame
|
||||||
|
// 2 bytes 0 padding
|
||||||
|
struct BCMVHeader {
|
||||||
|
explicit BCMVHeader(std::uint32_t frame_length) : length(frame_length) {}
|
||||||
|
BCMVHeader() = delete;
|
||||||
|
BCMVHeader(const BCMVHeader&) = delete;
|
||||||
|
BCMVHeader(BCMVHeader&&) = delete;
|
||||||
|
~BCMVHeader() = default;
|
||||||
|
const std::uint8_t bcmv[4] = {'B', 'C', 'M', 'V'};
|
||||||
|
const std::uint32_t length;
|
||||||
|
|
||||||
|
static std::size_t size() { return 10; }
|
||||||
|
|
||||||
|
// Write the BCMV Header into the FILE stream.
|
||||||
|
bool Write(std::FILE* fileptr) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PesHeader {
|
||||||
|
const std::uint8_t start_code[4] = {
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x01, // 0x000001 is the PES packet start code prefix.
|
||||||
|
0xE0}; // 0xE0 is the minimum video stream ID.
|
||||||
|
std::uint16_t packet_length = 0; // Number of bytes _after_ this field.
|
||||||
|
PesOptionalHeader optional_header;
|
||||||
|
std::size_t size() const {
|
||||||
|
return optional_header.size_in_bytes() + BCMVHeader::size() +
|
||||||
|
6 /* start_code + packet_length */ + packet_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes out the header to |file|. Calls PesOptionalHeader::Write() to write
|
||||||
|
// |optional_header| contents. Returns true when successful, false otherwise.
|
||||||
|
bool Write(std::FILE* file, bool write_pts) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Converts the VP9 track of a WebM file to a Packetized Elementary Stream
|
||||||
|
// suitable for use in a MPEG2TS.
|
||||||
|
// https://en.wikipedia.org/wiki/Packetized_elementary_stream
|
||||||
|
// https://en.wikipedia.org/wiki/MPEG_transport_stream
|
||||||
|
class Webm2Pes {
|
||||||
|
public:
|
||||||
|
enum VideoCodec { VP8, VP9 };
|
||||||
|
|
||||||
|
Webm2Pes(const std::string& input_file, const std::string& output_file)
|
||||||
|
: input_file_name_(input_file), output_file_name_(output_file) {}
|
||||||
|
|
||||||
|
Webm2Pes() = delete;
|
||||||
|
Webm2Pes(const Webm2Pes&) = delete;
|
||||||
|
Webm2Pes(Webm2Pes&&) = delete;
|
||||||
|
~Webm2Pes() = default;
|
||||||
|
|
||||||
|
// Converts the VPx video stream to a PES and returns true. Returns false
|
||||||
|
// to report failure.
|
||||||
|
bool Convert();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// fclose functor for wrapping FILE in std::unique_ptr.
|
||||||
|
struct FILEDeleter {
|
||||||
|
int operator()(FILE* f) {
|
||||||
|
if (f != nullptr)
|
||||||
|
return fclose(f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
typedef std::unique_ptr<FILE, FILEDeleter> FilePtr;
|
||||||
|
|
||||||
|
bool WritePesPacket(const mkvparser::Block::Frame& vpx_frame,
|
||||||
|
double nanosecond_pts);
|
||||||
|
|
||||||
|
const std::string input_file_name_;
|
||||||
|
const std::string output_file_name_;
|
||||||
|
std::unique_ptr<mkvparser::Segment> webm_parser_;
|
||||||
|
mkvparser::MkvReader webm_reader_;
|
||||||
|
FilePtr output_file_;
|
||||||
|
|
||||||
|
// Video track num in the WebM file.
|
||||||
|
int video_track_num_ = 0;
|
||||||
|
|
||||||
|
// Video codec reported by CodecName from Video TrackEntry.
|
||||||
|
VideoCodec codec_;
|
||||||
|
|
||||||
|
// Input timecode scale.
|
||||||
|
std::int64_t timecode_scale_ = 1000000;
|
||||||
|
};
|
||||||
|
} // namespace libwebm
|
||||||
|
|
||||||
|
#endif // LIBWEBM_WEBM2PES_H_
|
||||||
251
webmids.hpp
251
webmids.hpp
@@ -12,127 +12,144 @@
|
|||||||
namespace mkvmuxer {
|
namespace mkvmuxer {
|
||||||
|
|
||||||
enum MkvId {
|
enum MkvId {
|
||||||
kMkvEBML = 0x1A45DFA3,
|
kMkvEBML = 0x1A45DFA3,
|
||||||
kMkvEBMLVersion = 0x4286,
|
kMkvEBMLVersion = 0x4286,
|
||||||
kMkvEBMLReadVersion = 0x42F7,
|
kMkvEBMLReadVersion = 0x42F7,
|
||||||
kMkvEBMLMaxIDLength = 0x42F2,
|
kMkvEBMLMaxIDLength = 0x42F2,
|
||||||
kMkvEBMLMaxSizeLength = 0x42F3,
|
kMkvEBMLMaxSizeLength = 0x42F3,
|
||||||
kMkvDocType = 0x4282,
|
kMkvDocType = 0x4282,
|
||||||
kMkvDocTypeVersion = 0x4287,
|
kMkvDocTypeVersion = 0x4287,
|
||||||
kMkvDocTypeReadVersion = 0x4285,
|
kMkvDocTypeReadVersion = 0x4285,
|
||||||
kMkvVoid = 0xEC,
|
kMkvVoid = 0xEC,
|
||||||
kMkvSignatureSlot = 0x1B538667,
|
kMkvSignatureSlot = 0x1B538667,
|
||||||
kMkvSignatureAlgo = 0x7E8A,
|
kMkvSignatureAlgo = 0x7E8A,
|
||||||
kMkvSignatureHash = 0x7E9A,
|
kMkvSignatureHash = 0x7E9A,
|
||||||
kMkvSignaturePublicKey = 0x7EA5,
|
kMkvSignaturePublicKey = 0x7EA5,
|
||||||
kMkvSignature = 0x7EB5,
|
kMkvSignature = 0x7EB5,
|
||||||
kMkvSignatureElements = 0x7E5B,
|
kMkvSignatureElements = 0x7E5B,
|
||||||
kMkvSignatureElementList = 0x7E7B,
|
kMkvSignatureElementList = 0x7E7B,
|
||||||
kMkvSignedElement = 0x6532,
|
kMkvSignedElement = 0x6532,
|
||||||
//segment
|
// segment
|
||||||
kMkvSegment = 0x18538067,
|
kMkvSegment = 0x18538067,
|
||||||
//Meta Seek Information
|
// Meta Seek Information
|
||||||
kMkvSeekHead = 0x114D9B74,
|
kMkvSeekHead = 0x114D9B74,
|
||||||
kMkvSeek = 0x4DBB,
|
kMkvSeek = 0x4DBB,
|
||||||
kMkvSeekID = 0x53AB,
|
kMkvSeekID = 0x53AB,
|
||||||
kMkvSeekPosition = 0x53AC,
|
kMkvSeekPosition = 0x53AC,
|
||||||
//Segment Information
|
// Segment Information
|
||||||
kMkvInfo = 0x1549A966,
|
kMkvInfo = 0x1549A966,
|
||||||
kMkvTimecodeScale = 0x2AD7B1,
|
kMkvTimecodeScale = 0x2AD7B1,
|
||||||
kMkvDuration = 0x4489,
|
kMkvDuration = 0x4489,
|
||||||
kMkvDateUTC = 0x4461,
|
kMkvDateUTC = 0x4461,
|
||||||
kMkvMuxingApp = 0x4D80,
|
kMkvTitle = 0x7BA9,
|
||||||
kMkvWritingApp = 0x5741,
|
kMkvMuxingApp = 0x4D80,
|
||||||
//Cluster
|
kMkvWritingApp = 0x5741,
|
||||||
kMkvCluster = 0x1F43B675,
|
// Cluster
|
||||||
kMkvTimecode = 0xE7,
|
kMkvCluster = 0x1F43B675,
|
||||||
kMkvPrevSize = 0xAB,
|
kMkvTimecode = 0xE7,
|
||||||
kMkvBlockGroup = 0xA0,
|
kMkvPrevSize = 0xAB,
|
||||||
kMkvBlock = 0xA1,
|
kMkvBlockGroup = 0xA0,
|
||||||
kMkvBlockDuration = 0x9B,
|
kMkvBlock = 0xA1,
|
||||||
kMkvReferenceBlock = 0xFB,
|
kMkvBlockDuration = 0x9B,
|
||||||
kMkvLaceNumber = 0xCC,
|
kMkvReferenceBlock = 0xFB,
|
||||||
kMkvSimpleBlock = 0xA3,
|
kMkvLaceNumber = 0xCC,
|
||||||
kMkvBlockAdditions = 0x75A1,
|
kMkvSimpleBlock = 0xA3,
|
||||||
kMkvBlockMore = 0xA6,
|
kMkvBlockAdditions = 0x75A1,
|
||||||
kMkvBlockAddID = 0xEE,
|
kMkvBlockMore = 0xA6,
|
||||||
kMkvBlockAdditional = 0xA5,
|
kMkvBlockAddID = 0xEE,
|
||||||
//Track
|
kMkvBlockAdditional = 0xA5,
|
||||||
kMkvTracks = 0x1654AE6B,
|
kMkvDiscardPadding = 0x75A2,
|
||||||
kMkvTrackEntry = 0xAE,
|
// Track
|
||||||
kMkvTrackNumber = 0xD7,
|
kMkvTracks = 0x1654AE6B,
|
||||||
kMkvTrackUID = 0x73C5,
|
kMkvTrackEntry = 0xAE,
|
||||||
kMkvTrackType = 0x83,
|
kMkvTrackNumber = 0xD7,
|
||||||
kMkvFlagEnabled = 0xB9,
|
kMkvTrackUID = 0x73C5,
|
||||||
kMkvFlagDefault = 0x88,
|
kMkvTrackType = 0x83,
|
||||||
kMkvFlagForced = 0x55AA,
|
kMkvFlagEnabled = 0xB9,
|
||||||
kMkvFlagLacing = 0x9C,
|
kMkvFlagDefault = 0x88,
|
||||||
kMkvDefaultDuration = 0x23E383,
|
kMkvFlagForced = 0x55AA,
|
||||||
kMkvName = 0x536E,
|
kMkvFlagLacing = 0x9C,
|
||||||
kMkvLanguage = 0x22B59C,
|
kMkvDefaultDuration = 0x23E383,
|
||||||
kMkvCodecID = 0x86,
|
kMkvMaxBlockAdditionID = 0x55EE,
|
||||||
kMkvCodecPrivate = 0x63A2,
|
kMkvName = 0x536E,
|
||||||
kMkvCodecName = 0x258688,
|
kMkvLanguage = 0x22B59C,
|
||||||
kMkvMaxBlockAdditionID = 0x55EE,
|
kMkvCodecID = 0x86,
|
||||||
//video
|
kMkvCodecPrivate = 0x63A2,
|
||||||
kMkvVideo = 0xE0,
|
kMkvCodecName = 0x258688,
|
||||||
kMkvFlagInterlaced = 0x9A,
|
kMkvCodecDelay = 0x56AA,
|
||||||
kMkvStereoMode = 0x53B8,
|
kMkvSeekPreRoll = 0x56BB,
|
||||||
kMkvAlphaMode = 0x53C0,
|
// video
|
||||||
kMkvPixelWidth = 0xB0,
|
kMkvVideo = 0xE0,
|
||||||
kMkvPixelHeight = 0xBA,
|
kMkvFlagInterlaced = 0x9A,
|
||||||
kMkvPixelCropBottom = 0x54AA,
|
kMkvStereoMode = 0x53B8,
|
||||||
kMkvPixelCropTop = 0x54BB,
|
kMkvAlphaMode = 0x53C0,
|
||||||
kMkvPixelCropLeft = 0x54CC,
|
kMkvPixelWidth = 0xB0,
|
||||||
kMkvPixelCropRight = 0x54DD,
|
kMkvPixelHeight = 0xBA,
|
||||||
kMkvDisplayWidth = 0x54B0,
|
kMkvPixelCropBottom = 0x54AA,
|
||||||
kMkvDisplayHeight = 0x54BA,
|
kMkvPixelCropTop = 0x54BB,
|
||||||
kMkvDisplayUnit = 0x54B2,
|
kMkvPixelCropLeft = 0x54CC,
|
||||||
kMkvAspectRatioType = 0x54B3,
|
kMkvPixelCropRight = 0x54DD,
|
||||||
kMkvFrameRate = 0x2383E3,
|
kMkvDisplayWidth = 0x54B0,
|
||||||
//end video
|
kMkvDisplayHeight = 0x54BA,
|
||||||
//audio
|
kMkvDisplayUnit = 0x54B2,
|
||||||
kMkvAudio = 0xE1,
|
kMkvAspectRatioType = 0x54B3,
|
||||||
kMkvSamplingFrequency = 0xB5,
|
kMkvFrameRate = 0x2383E3,
|
||||||
|
// end video
|
||||||
|
// audio
|
||||||
|
kMkvAudio = 0xE1,
|
||||||
|
kMkvSamplingFrequency = 0xB5,
|
||||||
kMkvOutputSamplingFrequency = 0x78B5,
|
kMkvOutputSamplingFrequency = 0x78B5,
|
||||||
kMkvChannels = 0x9F,
|
kMkvChannels = 0x9F,
|
||||||
kMkvBitDepth = 0x6264,
|
kMkvBitDepth = 0x6264,
|
||||||
//end audio
|
// end audio
|
||||||
//ContentEncodings
|
// ContentEncodings
|
||||||
kMkvContentEncodings = 0x6D80,
|
kMkvContentEncodings = 0x6D80,
|
||||||
kMkvContentEncoding = 0x6240,
|
kMkvContentEncoding = 0x6240,
|
||||||
kMkvContentEncodingOrder = 0x5031,
|
kMkvContentEncodingOrder = 0x5031,
|
||||||
kMkvContentEncodingScope = 0x5032,
|
kMkvContentEncodingScope = 0x5032,
|
||||||
kMkvContentEncodingType = 0x5033,
|
kMkvContentEncodingType = 0x5033,
|
||||||
kMkvContentEncryption = 0x5035,
|
kMkvContentCompression = 0x5034,
|
||||||
kMkvContentEncAlgo = 0x47E1,
|
kMkvContentCompAlgo = 0x4254,
|
||||||
kMkvContentEncKeyID = 0x47E2,
|
kMkvContentCompSettings = 0x4255,
|
||||||
kMkvContentEncAESSettings = 0x47E7,
|
kMkvContentEncryption = 0x5035,
|
||||||
kMkvAESSettingsCipherMode = 0x47E8,
|
kMkvContentEncAlgo = 0x47E1,
|
||||||
|
kMkvContentEncKeyID = 0x47E2,
|
||||||
|
kMkvContentSignature = 0x47E3,
|
||||||
|
kMkvContentSigKeyID = 0x47E4,
|
||||||
|
kMkvContentSigAlgo = 0x47E5,
|
||||||
|
kMkvContentSigHashAlgo = 0x47E6,
|
||||||
|
kMkvContentEncAESSettings = 0x47E7,
|
||||||
|
kMkvAESSettingsCipherMode = 0x47E8,
|
||||||
kMkvAESSettingsCipherInitData = 0x47E9,
|
kMkvAESSettingsCipherInitData = 0x47E9,
|
||||||
//end ContentEncodings
|
// end ContentEncodings
|
||||||
//Cueing Data
|
// Cueing Data
|
||||||
kMkvCues = 0x1C53BB6B,
|
kMkvCues = 0x1C53BB6B,
|
||||||
kMkvCuePoint = 0xBB,
|
kMkvCuePoint = 0xBB,
|
||||||
kMkvCueTime = 0xB3,
|
kMkvCueTime = 0xB3,
|
||||||
kMkvCueTrackPositions = 0xB7,
|
kMkvCueTrackPositions = 0xB7,
|
||||||
kMkvCueTrack = 0xF7,
|
kMkvCueTrack = 0xF7,
|
||||||
kMkvCueClusterPosition = 0xF1,
|
kMkvCueClusterPosition = 0xF1,
|
||||||
kMkvCueBlockNumber = 0x5378,
|
kMkvCueBlockNumber = 0x5378,
|
||||||
//Chapters
|
// Chapters
|
||||||
kMkvChapters = 0x1043A770,
|
kMkvChapters = 0x1043A770,
|
||||||
kMkvEditionEntry = 0x45B9,
|
kMkvEditionEntry = 0x45B9,
|
||||||
kMkvChapterAtom = 0xB6,
|
kMkvChapterAtom = 0xB6,
|
||||||
kMkvChapterUID = 0x73C4,
|
kMkvChapterUID = 0x73C4,
|
||||||
kMkvChapterStringUID = 0x5654,
|
kMkvChapterStringUID = 0x5654,
|
||||||
kMkvChapterTimeStart = 0x91,
|
kMkvChapterTimeStart = 0x91,
|
||||||
kMkvChapterTimeEnd = 0x92,
|
kMkvChapterTimeEnd = 0x92,
|
||||||
kMkvChapterDisplay = 0x80,
|
kMkvChapterDisplay = 0x80,
|
||||||
kMkvChapString = 0x85,
|
kMkvChapString = 0x85,
|
||||||
kMkvChapLanguage = 0x437C,
|
kMkvChapLanguage = 0x437C,
|
||||||
kMkvChapCountry = 0x437E
|
kMkvChapCountry = 0x437E,
|
||||||
|
// Tags
|
||||||
|
kMkvTags = 0x1254C367,
|
||||||
|
kMkvTag = 0x7373,
|
||||||
|
kMkvSimpleTag = 0x67C8,
|
||||||
|
kMkvTagName = 0x45A3,
|
||||||
|
kMkvTagString = 0x4487
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace mkvmuxer
|
} // end namespace mkvmuxer
|
||||||
|
|
||||||
#endif // WEBMIDS_HPP
|
#endif // WEBMIDS_HPP
|
||||||
|
|||||||
@@ -11,19 +11,19 @@
|
|||||||
|
|
||||||
namespace libwebvtt {
|
namespace libwebvtt {
|
||||||
|
|
||||||
|
// NOLINT'ing this enum because clang-format puts it in a single line which
|
||||||
|
// makes it look really unreadable.
|
||||||
enum {
|
enum {
|
||||||
kNUL = '\x00',
|
kNUL = '\x00',
|
||||||
kSPACE = ' ',
|
kSPACE = ' ',
|
||||||
kTAB = '\x09',
|
kTAB = '\x09',
|
||||||
kLF = '\x0A',
|
kLF = '\x0A',
|
||||||
kCR = '\x0D'
|
kCR = '\x0D'
|
||||||
};
|
}; // NOLINT
|
||||||
|
|
||||||
Reader::~Reader() {
|
Reader::~Reader() {}
|
||||||
}
|
|
||||||
|
|
||||||
LineReader::~LineReader() {
|
LineReader::~LineReader() {}
|
||||||
}
|
|
||||||
|
|
||||||
int LineReader::GetLine(std::string* line_ptr) {
|
int LineReader::GetLine(std::string* line_ptr) {
|
||||||
if (line_ptr == NULL)
|
if (line_ptr == NULL)
|
||||||
@@ -101,11 +101,9 @@ int LineReader::GetLine(std::string* line_ptr) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser::Parser(Reader* r) : reader_(r), unget_(-1) {
|
Parser::Parser(Reader* r) : reader_(r), unget_(-1) {}
|
||||||
}
|
|
||||||
|
|
||||||
Parser::~Parser() {
|
Parser::~Parser() {}
|
||||||
}
|
|
||||||
|
|
||||||
int Parser::Init() {
|
int Parser::Init() {
|
||||||
int e = ParseBOM();
|
int e = ParseBOM();
|
||||||
@@ -226,10 +224,7 @@ int Parser::Parse(Cue* cue) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
e = ParseTimingsLine(&line,
|
e = ParseTimingsLine(&line, arrow_pos, &cue->start_time, &cue->stop_time,
|
||||||
arrow_pos,
|
|
||||||
&cue->start_time,
|
|
||||||
&cue->stop_time,
|
|
||||||
&cue->settings);
|
&cue->settings);
|
||||||
|
|
||||||
if (e) // error
|
if (e) // error
|
||||||
@@ -269,9 +264,7 @@ int Parser::GetChar(char* c) {
|
|||||||
return reader_->GetChar(c);
|
return reader_->GetChar(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::UngetChar(char c) {
|
void Parser::UngetChar(char c) { unget_ = static_cast<unsigned char>(c); }
|
||||||
unget_ = static_cast<unsigned char>(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Parser::ParseBOM() {
|
int Parser::ParseBOM() {
|
||||||
// Explanation of UTF-8 BOM:
|
// Explanation of UTF-8 BOM:
|
||||||
@@ -303,12 +296,9 @@ int Parser::ParseBOM() {
|
|||||||
return 0; // success
|
return 0; // success
|
||||||
}
|
}
|
||||||
|
|
||||||
int Parser::ParseTimingsLine(
|
int Parser::ParseTimingsLine(std::string* line_ptr,
|
||||||
std::string* line_ptr,
|
std::string::size_type arrow_pos, Time* start_time,
|
||||||
std::string::size_type arrow_pos,
|
Time* stop_time, Cue::settings_t* settings) {
|
||||||
Time* start_time,
|
|
||||||
Time* stop_time,
|
|
||||||
Cue::settings_t* settings) {
|
|
||||||
if (line_ptr == NULL)
|
if (line_ptr == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -353,10 +343,8 @@ int Parser::ParseTimingsLine(
|
|||||||
return 0; // success
|
return 0; // success
|
||||||
}
|
}
|
||||||
|
|
||||||
int Parser::ParseTime(
|
int Parser::ParseTime(const std::string& line, std::string::size_type* idx_ptr,
|
||||||
const std::string& line,
|
Time* time) {
|
||||||
std::string::size_type* idx_ptr,
|
|
||||||
Time* time) {
|
|
||||||
if (idx_ptr == NULL)
|
if (idx_ptr == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -511,10 +499,8 @@ int Parser::ParseTime(
|
|||||||
return 0; // success
|
return 0; // success
|
||||||
}
|
}
|
||||||
|
|
||||||
int Parser::ParseSettings(
|
int Parser::ParseSettings(const std::string& line, std::string::size_type idx,
|
||||||
const std::string& line,
|
Cue::settings_t* settings) {
|
||||||
std::string::size_type idx,
|
|
||||||
Cue::settings_t* settings) {
|
|
||||||
settings->clear();
|
settings->clear();
|
||||||
|
|
||||||
if (idx == std::string::npos || idx >= line.length())
|
if (idx == std::string::npos || idx >= line.length())
|
||||||
@@ -573,7 +559,7 @@ int Parser::ParseSettings(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (c == ':') // suspicious when part of VALUE
|
if (c == ':') // suspicious when part of VALUE
|
||||||
return -1; // TODO(matthewjheaney): verify this behavior
|
return -1; // TODO(matthewjheaney): verify this behavior
|
||||||
|
|
||||||
s.value.push_back(c);
|
s.value.push_back(c);
|
||||||
|
|
||||||
@@ -585,9 +571,8 @@ int Parser::ParseSettings(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Parser::ParseNumber(
|
int Parser::ParseNumber(const std::string& line,
|
||||||
const std::string& line,
|
std::string::size_type* idx_ptr) {
|
||||||
std::string::size_type* idx_ptr) {
|
|
||||||
if (idx_ptr == NULL)
|
if (idx_ptr == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -656,17 +641,11 @@ bool Time::operator<(const Time& rhs) const {
|
|||||||
return (milliseconds < rhs.milliseconds);
|
return (milliseconds < rhs.milliseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Time::operator>(const Time& rhs) const {
|
bool Time::operator>(const Time& rhs) const { return rhs.operator<(*this); }
|
||||||
return rhs.operator<(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Time::operator<=(const Time& rhs) const {
|
bool Time::operator<=(const Time& rhs) const { return !this->operator>(rhs); }
|
||||||
return !this->operator>(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Time::operator>=(const Time& rhs) const {
|
bool Time::operator>=(const Time& rhs) const { return !this->operator<(rhs); }
|
||||||
return !this->operator<(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
presentation_t Time::presentation() const {
|
presentation_t Time::presentation() const {
|
||||||
const presentation_t h = 1000LL * 3600LL * presentation_t(hours);
|
const presentation_t h = 1000LL * 3600LL * presentation_t(hours);
|
||||||
@@ -686,8 +665,8 @@ Time& Time::presentation(presentation_t d) {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
seconds = d / 1000;
|
seconds = static_cast<int>(d / 1000);
|
||||||
milliseconds = d - 1000 * seconds;
|
milliseconds = static_cast<int>(d - 1000 * seconds);
|
||||||
|
|
||||||
minutes = seconds / 60;
|
minutes = seconds / 60;
|
||||||
seconds -= 60 * minutes;
|
seconds -= 60 * minutes;
|
||||||
@@ -711,9 +690,7 @@ Time Time::operator+(presentation_t d) const {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
Time& Time::operator-=(presentation_t d) {
|
Time& Time::operator-=(presentation_t d) { return this->operator+=(-d); }
|
||||||
return this->operator+=(-d);
|
|
||||||
}
|
|
||||||
|
|
||||||
presentation_t Time::operator-(const Time& t) const {
|
presentation_t Time::operator-(const Time& t) const {
|
||||||
const presentation_t rhs = t.presentation();
|
const presentation_t rhs = t.presentation();
|
||||||
|
|||||||
@@ -120,8 +120,7 @@ class Parser : private LineReader {
|
|||||||
//
|
//
|
||||||
static int ParseTimingsLine(std::string* line,
|
static int ParseTimingsLine(std::string* line,
|
||||||
std::string::size_type arrow_pos,
|
std::string::size_type arrow_pos,
|
||||||
Time* start_time,
|
Time* start_time, Time* stop_time,
|
||||||
Time* stop_time,
|
|
||||||
Cue::settings_t* settings);
|
Cue::settings_t* settings);
|
||||||
|
|
||||||
// Parse a single time specifier (from the timings line), starting
|
// Parse a single time specifier (from the timings line), starting
|
||||||
@@ -129,23 +128,20 @@ class Parser : private LineReader {
|
|||||||
// is detected. The function modifies offset |off| by the number of
|
// is detected. The function modifies offset |off| by the number of
|
||||||
// characters consumed. Returns negative if error, 0 on success.
|
// characters consumed. Returns negative if error, 0 on success.
|
||||||
//
|
//
|
||||||
static int ParseTime(const std::string& line,
|
static int ParseTime(const std::string& line, std::string::size_type* off,
|
||||||
std::string::size_type* off,
|
|
||||||
Time* time);
|
Time* time);
|
||||||
|
|
||||||
// Parse the cue settings from the timings line, starting at the
|
// Parse the cue settings from the timings line, starting at the
|
||||||
// given offset. Returns negative if error, 0 on success.
|
// given offset. Returns negative if error, 0 on success.
|
||||||
//
|
//
|
||||||
static int ParseSettings(const std::string& line,
|
static int ParseSettings(const std::string& line, std::string::size_type off,
|
||||||
std::string::size_type off,
|
|
||||||
Cue::settings_t* settings);
|
Cue::settings_t* settings);
|
||||||
|
|
||||||
// Parse a non-negative integer from the characters in |line| beginning
|
// Parse a non-negative integer from the characters in |line| beginning
|
||||||
// at offset |off|. The function increments |off| by the number
|
// at offset |off|. The function increments |off| by the number
|
||||||
// of characters consumed. Returns the value, or negative if error.
|
// of characters consumed. Returns the value, or negative if error.
|
||||||
//
|
//
|
||||||
static int ParseNumber(const std::string& line,
|
static int ParseNumber(const std::string& line, std::string::size_type* off);
|
||||||
std::string::size_type* off);
|
|
||||||
|
|
||||||
Reader* const reader_;
|
Reader* const reader_;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user