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>
|
|
||||||
1341
mkvmuxer.cpp
1341
mkvmuxer.cpp
File diff suppressed because it is too large
Load Diff
466
mkvmuxer.hpp
466
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_;
|
||||||
@@ -361,10 +429,7 @@ class VideoTrack : public Track {
|
|||||||
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
|
||||||
|
|||||||
@@ -25,6 +25,6 @@ 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
|
||||||
|
|||||||
6834
mkvparser.cpp
6834
mkvparser.cpp
File diff suppressed because it is too large
Load Diff
659
mkvparser.hpp
659
mkvparser.hpp
File diff suppressed because it is too large
Load Diff
@@ -10,44 +10,49 @@
|
|||||||
|
|
||||||
#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
|
#endif
|
||||||
|
return !GetFileSize();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
bool MkvReader::GetFileSize() {
|
||||||
|
if (m_file == NULL)
|
||||||
|
return false;
|
||||||
|
#ifdef _MSC_VER
|
||||||
int status = _fseeki64(m_file, 0L, SEEK_END);
|
int status = _fseeki64(m_file, 0L, SEEK_END);
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
return -1; //error
|
return false; // error
|
||||||
|
|
||||||
m_length = _ftelli64(m_file);
|
m_length = _ftelli64(m_file);
|
||||||
#else
|
#else
|
||||||
@@ -56,29 +61,29 @@ int MkvReader::Open(const char* fileName)
|
|||||||
#endif
|
#endif
|
||||||
assert(m_length >= 0);
|
assert(m_length >= 0);
|
||||||
|
|
||||||
#ifdef WIN32
|
if (m_length < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
status = _fseeki64(m_file, 0L, SEEK_SET);
|
status = _fseeki64(m_file, 0L, SEEK_SET);
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
return -1; //error
|
return false; // error
|
||||||
#else
|
#else
|
||||||
fseek(m_file, 0L, SEEK_SET);
|
fseek(m_file, 0L, SEEK_SET);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MkvReader::Close()
|
void MkvReader::Close() {
|
||||||
{
|
if (m_file != NULL) {
|
||||||
if (m_file != NULL)
|
|
||||||
{
|
|
||||||
fclose(m_file);
|
fclose(m_file);
|
||||||
m_file = NULL;
|
m_file = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int MkvReader::Length(long long* total, long long* available)
|
int MkvReader::Length(long long* total, long long* available) {
|
||||||
{
|
|
||||||
if (m_file == NULL)
|
if (m_file == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -91,8 +96,7 @@ int MkvReader::Length(long long* total, long long* available)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MkvReader::Read(long long offset, long len, unsigned char* buffer)
|
int MkvReader::Read(long long offset, long len, unsigned char* buffer) {
|
||||||
{
|
|
||||||
if (m_file == NULL)
|
if (m_file == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -108,11 +112,11 @@ int MkvReader::Read(long long offset, long len, unsigned char* buffer)
|
|||||||
if (offset >= m_length)
|
if (offset >= m_length)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef _MSC_VER
|
||||||
const int status = _fseeki64(m_file, offset, SEEK_SET);
|
const int status = _fseeki64(m_file, offset, SEEK_SET);
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
return -1; //error
|
return -1; // error
|
||||||
#else
|
#else
|
||||||
fseek(m_file, offset, SEEK_SET);
|
fseek(m_file, offset, SEEK_SET);
|
||||||
#endif
|
#endif
|
||||||
@@ -120,9 +124,9 @@ int MkvReader::Read(long long offset, long len, unsigned char* buffer)
|
|||||||
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,15 +12,12 @@
|
|||||||
#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& operator=(const MkvReader&);
|
|
||||||
public:
|
|
||||||
MkvReader();
|
MkvReader();
|
||||||
|
explicit MkvReader(FILE* fp);
|
||||||
virtual ~MkvReader();
|
virtual ~MkvReader();
|
||||||
|
|
||||||
int Open(const char*);
|
int Open(const char*);
|
||||||
@@ -28,11 +25,21 @@ public:
|
|||||||
|
|
||||||
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:
|
|
||||||
|
private:
|
||||||
|
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;
|
long long m_length;
|
||||||
FILE* m_file;
|
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 {
|
||||||
@@ -84,11 +83,8 @@ int32 MkvWriter::Position(int64 position) {
|
|||||||
#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
|
||||||
|
|||||||
191
sample.cpp
191
sample.cpp
@@ -6,37 +6,34 @@
|
|||||||
// 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';
|
||||||
@@ -44,11 +41,23 @@ static const wchar_t* utf8towcs(const char* str)
|
|||||||
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)
|
|
||||||
{
|
const mkvparser::CuePoint* const cue_point = cues->GetFirst();
|
||||||
|
if (cue_point == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc == 1) {
|
||||||
printf("\t\t\tMkv Parser Sample Application\n");
|
printf("\t\t\tMkv Parser Sample Application\n");
|
||||||
printf("\t\t\tUsage: \n");
|
printf("\t\t\tUsage: \n");
|
||||||
printf("\t\t\t ./sample [input file] \n");
|
printf("\t\t\t ./sample [input file] \n");
|
||||||
@@ -60,8 +69,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
MkvReader reader;
|
MkvReader reader;
|
||||||
|
|
||||||
if (reader.Open(argv[1]))
|
if (reader.Open(argv[1])) {
|
||||||
{
|
|
||||||
printf("\n Filename is invalid or error while opening.\n");
|
printf("\n Filename is invalid or error while opening.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -75,7 +83,11 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
EBMLHeader ebmlHeader;
|
EBMLHeader ebmlHeader;
|
||||||
|
|
||||||
ebmlHeader.Parse(&reader, pos);
|
long long ret = ebmlHeader.Parse(&reader, pos);
|
||||||
|
if (ret < 0) {
|
||||||
|
printf("\n EBMLHeader::Parse() failed.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
printf("\t\t\t EBML Header\n");
|
printf("\t\t\t EBML Header\n");
|
||||||
printf("\t\tEBML Version\t\t: %lld\n", ebmlHeader.m_version);
|
printf("\t\tEBML Version\t\t: %lld\n", ebmlHeader.m_version);
|
||||||
@@ -87,9 +99,8 @@ int main(int argc, char* argv[])
|
|||||||
typedef mkvparser::Segment seg_t;
|
typedef mkvparser::Segment seg_t;
|
||||||
seg_t* pSegment_;
|
seg_t* pSegment_;
|
||||||
|
|
||||||
long long ret = seg_t::CreateInstance(&reader, pos, pSegment_);
|
ret = seg_t::CreateInstance(&reader, pos, pSegment_);
|
||||||
if (ret)
|
if (ret) {
|
||||||
{
|
|
||||||
printf("\n Segment::CreateInstance() failed.");
|
printf("\n Segment::CreateInstance() failed.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -97,13 +108,16 @@ int main(int argc, char* argv[])
|
|||||||
const std::auto_ptr<seg_t> pSegment(pSegment_);
|
const std::auto_ptr<seg_t> pSegment(pSegment_);
|
||||||
|
|
||||||
ret = pSegment->Load();
|
ret = pSegment->Load();
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
{
|
|
||||||
printf("\n Segment::Load() failed.");
|
printf("\n Segment::Load() failed.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SegmentInfo* const pSegmentInfo = pSegment->GetInfo();
|
const SegmentInfo* const pSegmentInfo = pSegment->GetInfo();
|
||||||
|
if (pSegmentInfo == NULL) {
|
||||||
|
printf("\n Segment::GetInfo() failed.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
const long long timeCodeScale = pSegmentInfo->GetTimeCodeScale();
|
const long long timeCodeScale = pSegmentInfo->GetTimeCodeScale();
|
||||||
const long long duration_ns = pSegmentInfo->GetDuration();
|
const long long duration_ns = pSegmentInfo->GetDuration();
|
||||||
@@ -127,27 +141,23 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
if (pTitle == NULL)
|
if (pTitle == NULL)
|
||||||
printf("\t\tTrack Name\t\t: NULL\n");
|
printf("\t\tTrack Name\t\t: NULL\n");
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
printf("\t\tTrack Name\t\t: %ls\n", pTitle);
|
printf("\t\tTrack Name\t\t: %ls\n", pTitle);
|
||||||
delete [] pTitle;
|
delete[] pTitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (pMuxingApp == NULL)
|
if (pMuxingApp == NULL)
|
||||||
printf("\t\tMuxing App\t\t: NULL\n");
|
printf("\t\tMuxing App\t\t: NULL\n");
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
printf("\t\tMuxing App\t\t: %ls\n", pMuxingApp);
|
printf("\t\tMuxing App\t\t: %ls\n", pMuxingApp);
|
||||||
delete [] pMuxingApp;
|
delete[] pMuxingApp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pWritingApp == NULL)
|
if (pWritingApp == NULL)
|
||||||
printf("\t\tWriting App\t\t: NULL\n");
|
printf("\t\tWriting App\t\t: NULL\n");
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
printf("\t\tWriting App\t\t: %ls\n", pWritingApp);
|
printf("\t\tWriting App\t\t: %ls\n", pWritingApp);
|
||||||
delete [] pWritingApp;
|
delete[] pWritingApp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// pos of segment payload
|
// pos of segment payload
|
||||||
@@ -158,14 +168,13 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
const mkvparser::Tracks* pTracks = pSegment->GetTracks();
|
const mkvparser::Tracks* pTracks = pSegment->GetTracks();
|
||||||
|
|
||||||
unsigned long i = 0;
|
unsigned long track_num = 0;
|
||||||
const unsigned long j = pTracks->GetTracksCount();
|
const unsigned long num_tracks = pTracks->GetTracksCount();
|
||||||
|
|
||||||
printf("\n\t\t\t Track Info\n");
|
printf("\n\t\t\t Track Info\n");
|
||||||
|
|
||||||
while (i != j)
|
while (track_num != num_tracks) {
|
||||||
{
|
const Track* const pTrack = pTracks->GetTrackByIndex(track_num++);
|
||||||
const Track* const pTrack = pTracks->GetTrackByIndex(i++);
|
|
||||||
|
|
||||||
if (pTrack == NULL)
|
if (pTrack == NULL)
|
||||||
continue;
|
continue;
|
||||||
@@ -181,10 +190,9 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
if (pTrackName == NULL)
|
if (pTrackName == NULL)
|
||||||
printf("\t\tTrack Name\t\t: NULL\n");
|
printf("\t\tTrack Name\t\t: NULL\n");
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
printf("\t\tTrack Name\t\t: %ls \n", pTrackName);
|
printf("\t\tTrack Name\t\t: %ls \n", pTrackName);
|
||||||
delete [] pTrackName;
|
delete[] pTrackName;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* const pCodecId = pTrack->GetCodecId();
|
const char* const pCodecId = pTrack->GetCodecId();
|
||||||
@@ -199,14 +207,12 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
if (pCodecName == NULL)
|
if (pCodecName == NULL)
|
||||||
printf("\t\tCodec Name\t\t: NULL\n");
|
printf("\t\tCodec Name\t\t: NULL\n");
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
printf("\t\tCodec Name\t\t: %ls\n", pCodecName);
|
printf("\t\tCodec Name\t\t: %ls\n", pCodecName);
|
||||||
delete [] pCodecName;
|
delete[] pCodecName;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trackType == mkvparser::Track::kVideo)
|
if (trackType == mkvparser::Track::kVideo) {
|
||||||
{
|
|
||||||
const VideoTrack* const pVideoTrack =
|
const VideoTrack* const pVideoTrack =
|
||||||
static_cast<const VideoTrack*>(pTrack);
|
static_cast<const VideoTrack*>(pTrack);
|
||||||
|
|
||||||
@@ -217,11 +223,10 @@ int main(int argc, char* argv[])
|
|||||||
printf("\t\tVideo Height\t\t: %lld\n", height);
|
printf("\t\tVideo Height\t\t: %lld\n", height);
|
||||||
|
|
||||||
const double rate = pVideoTrack->GetFrameRate();
|
const double rate = pVideoTrack->GetFrameRate();
|
||||||
printf("\t\tVideo Rate\t\t: %f\n",rate);
|
printf("\t\tVideo Rate\t\t: %f\n", rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trackType == mkvparser::Track::kAudio)
|
if (trackType == mkvparser::Track::kAudio) {
|
||||||
{
|
|
||||||
const AudioTrack* const pAudioTrack =
|
const AudioTrack* const pAudioTrack =
|
||||||
static_cast<const AudioTrack*>(pTrack);
|
static_cast<const AudioTrack*>(pTrack);
|
||||||
|
|
||||||
@@ -233,6 +238,12 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
const double sampleRate = pAudioTrack->GetSamplingRate();
|
const double sampleRate = pAudioTrack->GetSamplingRate();
|
||||||
printf("\t\tAddio Sample Rate\t: %.3f\n", sampleRate);
|
printf("\t\tAddio Sample Rate\t: %.3f\n", sampleRate);
|
||||||
|
|
||||||
|
const long long codecDelay = pAudioTrack->GetCodecDelay();
|
||||||
|
printf("\t\tAudio Codec Delay\t\t: %lld\n", codecDelay);
|
||||||
|
|
||||||
|
const long long seekPreRoll = pAudioTrack->GetSeekPreRoll();
|
||||||
|
printf("\t\tAudio Seek Pre Roll\t\t: %lld\n", seekPreRoll);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,16 +252,14 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
printf("\t\tCluster Count\t: %ld\n\n", clusterCount);
|
printf("\t\tCluster Count\t: %ld\n\n", clusterCount);
|
||||||
|
|
||||||
if (clusterCount == 0)
|
if (clusterCount == 0) {
|
||||||
{
|
|
||||||
printf("\t\tSegment has no clusters.\n");
|
printf("\t\tSegment has no clusters.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mkvparser::Cluster* pCluster = pSegment->GetFirst();
|
const mkvparser::Cluster* pCluster = pSegment->GetFirst();
|
||||||
|
|
||||||
while ((pCluster != NULL) && !pCluster->EOS())
|
while ((pCluster != NULL) && !pCluster->EOS()) {
|
||||||
{
|
|
||||||
const long long timeCode = pCluster->GetTimeCode();
|
const long long timeCode = pCluster->GetTimeCode();
|
||||||
printf("\t\tCluster Time Code\t: %lld\n", timeCode);
|
printf("\t\tCluster Time Code\t: %lld\n", timeCode);
|
||||||
|
|
||||||
@@ -261,15 +270,14 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
long status = pCluster->GetFirst(pBlockEntry);
|
long status = pCluster->GetFirst(pBlockEntry);
|
||||||
|
|
||||||
if (status < 0) //error
|
if (status < 0) // error
|
||||||
{
|
{
|
||||||
printf("\t\tError parsing first block of cluster\n");
|
printf("\t\tError parsing first block of cluster\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((pBlockEntry != NULL) && !pBlockEntry->EOS())
|
while ((pBlockEntry != NULL) && !pBlockEntry->EOS()) {
|
||||||
{
|
|
||||||
const Block* const pBlock = pBlockEntry->GetBlock();
|
const Block* const pBlock = pBlockEntry->GetBlock();
|
||||||
const long long trackNum = pBlock->GetTrackNumber();
|
const long long trackNum = pBlock->GetTrackNumber();
|
||||||
const unsigned long tn = static_cast<unsigned long>(trackNum);
|
const unsigned long tn = static_cast<unsigned long>(trackNum);
|
||||||
@@ -277,19 +285,17 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
if (pTrack == NULL)
|
if (pTrack == NULL)
|
||||||
printf("\t\t\tBlock\t\t:UNKNOWN TRACK TYPE\n");
|
printf("\t\t\tBlock\t\t:UNKNOWN TRACK TYPE\n");
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
const long long trackType = pTrack->GetType();
|
const long long trackType = pTrack->GetType();
|
||||||
const int frameCount = pBlock->GetFrameCount();
|
const int frameCount = pBlock->GetFrameCount();
|
||||||
const long long time_ns = pBlock->GetTime(pCluster);
|
const long long time_ns = pBlock->GetTime(pCluster);
|
||||||
|
const long long discard_padding = pBlock->GetDiscardPadding();
|
||||||
|
|
||||||
printf("\t\t\tBlock\t\t:%s,%s,%15lld\n",
|
printf("\t\t\tBlock\t\t:%s,%s,%15lld,%lld\n",
|
||||||
(trackType == mkvparser::Track::kVideo) ? "V" : "A",
|
(trackType == mkvparser::Track::kVideo) ? "V" : "A",
|
||||||
pBlock->IsKey() ? "I" : "P",
|
pBlock->IsKey() ? "I" : "P", time_ns, discard_padding);
|
||||||
time_ns);
|
|
||||||
|
|
||||||
for (int i = 0; i < frameCount; ++i)
|
for (int i = 0; i < frameCount; ++i) {
|
||||||
{
|
|
||||||
const Block::Frame& theFrame = pBlock->GetFrame(i);
|
const Block::Frame& theFrame = pBlock->GetFrame(i);
|
||||||
const long size = theFrame.len;
|
const long size = theFrame.len;
|
||||||
const long long offset = theFrame.pos;
|
const long long offset = theFrame.pos;
|
||||||
@@ -299,8 +305,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
status = pCluster->GetNext(pBlockEntry, pBlockEntry);
|
status = pCluster->GetNext(pBlockEntry, pBlockEntry);
|
||||||
|
|
||||||
if (status < 0)
|
if (status < 0) {
|
||||||
{
|
|
||||||
printf("\t\t\tError parsing next block of cluster\n");
|
printf("\t\t\tError parsing next block of cluster\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -310,6 +315,52 @@ int main(int argc, char* argv[])
|
|||||||
pCluster = pSegment->GetNext(pCluster);
|
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);
|
fflush(stdout);
|
||||||
return 0;
|
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>
|
|
||||||
141
sample_muxer.cpp
141
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,8 +84,7 @@ 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;
|
||||||
|
|
||||||
@@ -94,22 +101,21 @@ bool LoadMetadataFiles(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ParseArgWebVTT(
|
int ParseArgWebVTT(char* argv[], int* argv_index, int argc_check,
|
||||||
char* argv[],
|
|
||||||
int* argv_index,
|
|
||||||
int argc_check,
|
|
||||||
metadata_files_t* metadata_files) {
|
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;
|
||||||
@@ -336,8 +366,7 @@ 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");
|
||||||
@@ -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)
|
||||||
@@ -374,8 +405,7 @@ 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");
|
||||||
@@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,8 +484,15 @@ int main(int argc, char* argv[]) {
|
|||||||
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;
|
||||||
}
|
}
|
||||||
@@ -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,8 +92,7 @@ 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,9 +245,7 @@ bool SampleMuxerMetadata::AddTrack(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SampleMuxerMetadata::Parse(
|
bool SampleMuxerMetadata::Parse(const char* file, Kind /* kind */,
|
||||||
const char* file,
|
|
||||||
Kind /* kind */,
|
|
||||||
mkvmuxer::uint64 track_num) {
|
mkvmuxer::uint64 track_num) {
|
||||||
libwebvtt::VttReader r;
|
libwebvtt::VttReader r;
|
||||||
int e = r.Open(file);
|
int e = r.Open(file);
|
||||||
@@ -300,15 +305,13 @@ 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
|
||||||
@@ -336,8 +339,7 @@ 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;
|
||||||
|
|
||||||
@@ -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.
|
||||||
|
|||||||
128
vttdemux.cc
128
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,44 +125,35 @@ 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,
|
|
||||||
mkvpos_t pos,
|
|
||||||
segment_ptr_t* segment);
|
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* chapters,
|
|
||||||
const mkvparser::Chapters::Atom* atom,
|
const mkvparser::Chapters::Atom* atom,
|
||||||
const mkvparser::Chapters::Display* display);
|
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* chapters,
|
|
||||||
const mkvparser::Chapters::Atom* atom);
|
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
|
||||||
@@ -190,15 +181,13 @@ 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
|
||||||
@@ -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,9 +353,7 @@ bool vttdemux::ParseHeader(
|
|||||||
return true; // success
|
return true; // success
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vttdemux::ParseSegment(
|
bool vttdemux::ParseSegment(mkvparser::IMkvReader* reader, mkvpos_t pos,
|
||||||
mkvparser::IMkvReader* reader,
|
|
||||||
mkvpos_t pos,
|
|
||||||
segment_ptr_t* segment_ptr) {
|
segment_ptr_t* segment_ptr) {
|
||||||
// We first create the segment object.
|
// We first create the segment object.
|
||||||
|
|
||||||
@@ -402,8 +379,7 @@ 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,8 +621,7 @@ 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
|
||||||
@@ -713,9 +693,7 @@ bool vttdemux::WriteChaptersFile(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vttdemux::WriteChaptersCue(
|
bool vttdemux::WriteChaptersCue(FILE* f, const mkvparser::Chapters* chapters,
|
||||||
FILE* f,
|
|
||||||
const mkvparser::Chapters* chapters,
|
|
||||||
const mkvparser::Chapters::Atom* atom,
|
const mkvparser::Chapters::Atom* atom,
|
||||||
const mkvparser::Chapters::Display* display) {
|
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)
|
||||||
@@ -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,8 +731,7 @@ 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);
|
||||||
@@ -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,8 +787,7 @@ 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.
|
||||||
@@ -822,7 +795,7 @@ bool vttdemux::ProcessCluster(
|
|||||||
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,8 +814,7 @@ 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,7 +823,7 @@ 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
|
||||||
@@ -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;
|
||||||
@@ -1011,9 +975,7 @@ bool vttdemux::WriteCueTime(
|
|||||||
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_
|
||||||
47
webmids.hpp
47
webmids.hpp
@@ -29,21 +29,22 @@ enum MkvId {
|
|||||||
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,
|
||||||
|
kMkvTitle = 0x7BA9,
|
||||||
kMkvMuxingApp = 0x4D80,
|
kMkvMuxingApp = 0x4D80,
|
||||||
kMkvWritingApp = 0x5741,
|
kMkvWritingApp = 0x5741,
|
||||||
//Cluster
|
// Cluster
|
||||||
kMkvCluster = 0x1F43B675,
|
kMkvCluster = 0x1F43B675,
|
||||||
kMkvTimecode = 0xE7,
|
kMkvTimecode = 0xE7,
|
||||||
kMkvPrevSize = 0xAB,
|
kMkvPrevSize = 0xAB,
|
||||||
@@ -57,7 +58,8 @@ enum MkvId {
|
|||||||
kMkvBlockMore = 0xA6,
|
kMkvBlockMore = 0xA6,
|
||||||
kMkvBlockAddID = 0xEE,
|
kMkvBlockAddID = 0xEE,
|
||||||
kMkvBlockAdditional = 0xA5,
|
kMkvBlockAdditional = 0xA5,
|
||||||
//Track
|
kMkvDiscardPadding = 0x75A2,
|
||||||
|
// Track
|
||||||
kMkvTracks = 0x1654AE6B,
|
kMkvTracks = 0x1654AE6B,
|
||||||
kMkvTrackEntry = 0xAE,
|
kMkvTrackEntry = 0xAE,
|
||||||
kMkvTrackNumber = 0xD7,
|
kMkvTrackNumber = 0xD7,
|
||||||
@@ -68,13 +70,15 @@ enum MkvId {
|
|||||||
kMkvFlagForced = 0x55AA,
|
kMkvFlagForced = 0x55AA,
|
||||||
kMkvFlagLacing = 0x9C,
|
kMkvFlagLacing = 0x9C,
|
||||||
kMkvDefaultDuration = 0x23E383,
|
kMkvDefaultDuration = 0x23E383,
|
||||||
|
kMkvMaxBlockAdditionID = 0x55EE,
|
||||||
kMkvName = 0x536E,
|
kMkvName = 0x536E,
|
||||||
kMkvLanguage = 0x22B59C,
|
kMkvLanguage = 0x22B59C,
|
||||||
kMkvCodecID = 0x86,
|
kMkvCodecID = 0x86,
|
||||||
kMkvCodecPrivate = 0x63A2,
|
kMkvCodecPrivate = 0x63A2,
|
||||||
kMkvCodecName = 0x258688,
|
kMkvCodecName = 0x258688,
|
||||||
kMkvMaxBlockAdditionID = 0x55EE,
|
kMkvCodecDelay = 0x56AA,
|
||||||
//video
|
kMkvSeekPreRoll = 0x56BB,
|
||||||
|
// video
|
||||||
kMkvVideo = 0xE0,
|
kMkvVideo = 0xE0,
|
||||||
kMkvFlagInterlaced = 0x9A,
|
kMkvFlagInterlaced = 0x9A,
|
||||||
kMkvStereoMode = 0x53B8,
|
kMkvStereoMode = 0x53B8,
|
||||||
@@ -90,28 +94,35 @@ enum MkvId {
|
|||||||
kMkvDisplayUnit = 0x54B2,
|
kMkvDisplayUnit = 0x54B2,
|
||||||
kMkvAspectRatioType = 0x54B3,
|
kMkvAspectRatioType = 0x54B3,
|
||||||
kMkvFrameRate = 0x2383E3,
|
kMkvFrameRate = 0x2383E3,
|
||||||
//end video
|
// end video
|
||||||
//audio
|
// audio
|
||||||
kMkvAudio = 0xE1,
|
kMkvAudio = 0xE1,
|
||||||
kMkvSamplingFrequency = 0xB5,
|
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,
|
||||||
|
kMkvContentCompression = 0x5034,
|
||||||
|
kMkvContentCompAlgo = 0x4254,
|
||||||
|
kMkvContentCompSettings = 0x4255,
|
||||||
kMkvContentEncryption = 0x5035,
|
kMkvContentEncryption = 0x5035,
|
||||||
kMkvContentEncAlgo = 0x47E1,
|
kMkvContentEncAlgo = 0x47E1,
|
||||||
kMkvContentEncKeyID = 0x47E2,
|
kMkvContentEncKeyID = 0x47E2,
|
||||||
|
kMkvContentSignature = 0x47E3,
|
||||||
|
kMkvContentSigKeyID = 0x47E4,
|
||||||
|
kMkvContentSigAlgo = 0x47E5,
|
||||||
|
kMkvContentSigHashAlgo = 0x47E6,
|
||||||
kMkvContentEncAESSettings = 0x47E7,
|
kMkvContentEncAESSettings = 0x47E7,
|
||||||
kMkvAESSettingsCipherMode = 0x47E8,
|
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,
|
||||||
@@ -119,7 +130,7 @@ enum MkvId {
|
|||||||
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,
|
||||||
@@ -130,7 +141,13 @@ enum MkvId {
|
|||||||
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
|
||||||
|
|||||||
@@ -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,9 +343,7 @@ 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,
|
|
||||||
std::string::size_type* idx_ptr,
|
|
||||||
Time* time) {
|
Time* time) {
|
||||||
if (idx_ptr == NULL)
|
if (idx_ptr == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -511,9 +499,7 @@ 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,
|
|
||||||
std::string::size_type idx,
|
|
||||||
Cue::settings_t* settings) {
|
Cue::settings_t* settings) {
|
||||||
settings->clear();
|
settings->clear();
|
||||||
|
|
||||||
@@ -585,8 +571,7 @@ 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