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
|
||||
dumpvtt
|
||||
sample
|
||||
samplemuxer
|
||||
sample_muxer
|
||||
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.
|
||||
DEPS := $(WEBMOBJS:.o=.d) $(OBJECTS1:.o=.d) $(OBJECTS2:.o=.d)
|
||||
DEPS += $(OBJECTS3:.o=.d) $(OBJECTS4:.o=.d)
|
||||
EXES := samplemuxer sample dumpvtt vttdemux
|
||||
EXES := sample_muxer sample dumpvtt vttdemux
|
||||
|
||||
all: $(EXES)
|
||||
|
||||
sample: sample.o $(LIBWEBMA)
|
||||
$(CXX) $^ -o $@
|
||||
|
||||
samplemuxer: $(OBJECTS2) $(LIBWEBMA)
|
||||
sample_muxer: $(OBJECTS2) $(LIBWEBMA)
|
||||
$(CXX) $^ -o $@
|
||||
|
||||
dumpvtt: $(OBJECTS3)
|
||||
39
PATENTS.TXT
39
PATENTS.TXT
@@ -1,22 +1,23 @@
|
||||
Additional IP Rights Grant (Patents)
|
||||
------------------------------------
|
||||
|
||||
"This implementation" means the copyrightable works distributed by
|
||||
Google as part of the WebM Project.
|
||||
"These implementations" means the copyrightable works that implement the WebM
|
||||
codecs distributed by Google as part of the WebM Project.
|
||||
|
||||
Google hereby grants to you a perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable (except as stated in this section)
|
||||
patent license to make, have made, use, offer to sell, sell, import,
|
||||
transfer, and otherwise run, modify and propagate the contents of this
|
||||
implementation of VP8, where such license applies only to those patent
|
||||
claims, both currently owned by Google and acquired in the future,
|
||||
licensable by Google that are necessarily infringed by this
|
||||
implementation of VP8. This grant does not include claims that would be
|
||||
infringed only as a consequence of further modification of this
|
||||
implementation. If you or your agent or exclusive licensee institute or
|
||||
order or agree to the institution of patent litigation against any
|
||||
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||
that this implementation of VP8 or any code incorporated within this
|
||||
implementation of VP8 constitutes direct or contributory patent
|
||||
infringement, or inducement of patent infringement, then any patent
|
||||
rights granted to you under this License for this implementation of VP8
|
||||
shall terminate as of the date such litigation is filed.
|
||||
Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge,
|
||||
royalty-free, irrevocable (except as stated in this section) patent license to
|
||||
make, have made, use, offer to sell, sell, import, transfer, and otherwise
|
||||
run, modify and propagate the contents of these implementations of WebM, where
|
||||
such license applies only to those patent claims, both currently owned by
|
||||
Google and acquired in the future, licensable by Google that are necessarily
|
||||
infringed by these implementations of WebM. This grant does not include claims
|
||||
that would be infringed only as a consequence of further modification of these
|
||||
implementations. If you or your agent or exclusive licensee institute or order
|
||||
or agree to the institution of patent litigation or any other patent
|
||||
enforcement activity against any entity (including a cross-claim or
|
||||
counterclaim in a lawsuit) alleging that any of these implementations of WebM
|
||||
or any code incorporated within any of these implementations of WebM
|
||||
constitute direct or contributory patent infringement, or inducement of
|
||||
patent infringement, then any patent rights granted to you under this License
|
||||
for these implementations of WebM shall terminate as of the date such
|
||||
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());
|
||||
|
||||
const libwebvtt::Time& st = cue.start_time;
|
||||
fprintf(stdout, "cue start time: \"HH=%i MM=%i SS=%i SSS=%i\"\n",
|
||||
st.hours,
|
||||
st.minutes,
|
||||
st.seconds,
|
||||
st.milliseconds);
|
||||
fprintf(stdout, "cue start time: \"HH=%i MM=%i SS=%i SSS=%i\"\n", st.hours,
|
||||
st.minutes, st.seconds, st.milliseconds);
|
||||
|
||||
const libwebvtt::Time& sp = cue.stop_time;
|
||||
fprintf(stdout, "cue stop time: \"HH=%i MM=%i SS=%i SSS=%i\"\n",
|
||||
sp.hours,
|
||||
sp.minutes,
|
||||
sp.seconds,
|
||||
sp.milliseconds);
|
||||
fprintf(stdout, "cue stop time: \"HH=%i MM=%i SS=%i SSS=%i\"\n", sp.hours,
|
||||
sp.minutes, sp.seconds, sp.milliseconds);
|
||||
|
||||
{
|
||||
typedef libwebvtt::Cue::settings_t::const_iterator iter_t;
|
||||
@@ -72,8 +66,7 @@ int main(int argc, const char* argv[]) {
|
||||
while (i != j) {
|
||||
const libwebvtt::Setting& setting = *i++;
|
||||
fprintf(stdout, "cue setting: name=%s value=%s\n",
|
||||
setting.name.c_str(),
|
||||
setting.value.c_str());
|
||||
setting.name.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/.
|
||||
|
||||
namespace mkvparser {
|
||||
class IMkvReader;
|
||||
class IMkvReader;
|
||||
} // end namespace
|
||||
|
||||
namespace mkvmuxer {
|
||||
@@ -23,6 +23,8 @@ namespace mkvmuxer {
|
||||
class MkvWriter;
|
||||
class Segment;
|
||||
|
||||
const uint64 kMaxTrackNumber = 126;
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Interface used by the mkvmuxer to write out the Mkv data.
|
||||
class IMkvWriter {
|
||||
@@ -57,11 +59,15 @@ class IMkvWriter {
|
||||
|
||||
// Writes out the EBML header for a WebM file. This function must be 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);
|
||||
|
||||
// Copies in Chunk from source to destination between the given byte positions
|
||||
bool ChunkedCopy(mkvparser::IMkvReader* source, IMkvWriter* dst,
|
||||
int64 start, int64 size);
|
||||
bool ChunkedCopy(mkvparser::IMkvReader* source, IMkvWriter* dst, int64 start,
|
||||
int64 size);
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Class to hold data the will be written to a block.
|
||||
@@ -70,22 +76,65 @@ class 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.
|
||||
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_; }
|
||||
void set_is_key(bool key) { is_key_ = key; }
|
||||
bool is_key() const { return is_key_; }
|
||||
uint64 length() const { return length_; }
|
||||
void set_track_number(uint64 track_number) { track_number_ = track_number; }
|
||||
uint64 track_number() const { return track_number_; }
|
||||
void set_timestamp(uint64 timestamp) { timestamp_ = timestamp; }
|
||||
uint64 timestamp() const { return timestamp_; }
|
||||
void set_is_key(bool key) { is_key_ = key; }
|
||||
bool is_key() const { return is_key_; }
|
||||
void set_discard_padding(int64 discard_padding) {
|
||||
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:
|
||||
// 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.
|
||||
uint8* frame_;
|
||||
|
||||
// Flag telling if the data should set the key flag of a block.
|
||||
bool is_key_;
|
||||
|
||||
// Length of the data.
|
||||
uint64 length_;
|
||||
|
||||
@@ -95,8 +144,16 @@ class Frame {
|
||||
// Timestamp of the data in nanoseconds.
|
||||
uint64 timestamp_;
|
||||
|
||||
// Flag telling if the data should set the key flag of a block.
|
||||
bool is_key_;
|
||||
// Discard padding for the frame.
|
||||
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
|
||||
class ContentEncAESSettings {
|
||||
public:
|
||||
enum {
|
||||
kCTR = 1
|
||||
};
|
||||
enum { kCTR = 1 };
|
||||
|
||||
ContentEncAESSettings();
|
||||
~ContentEncAESSettings() {}
|
||||
@@ -319,6 +374,16 @@ class Track {
|
||||
uint64 type() const { return type_; }
|
||||
void set_uid(uint64 uid) { uid_ = 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_; }
|
||||
uint32 content_encoding_entries_size() const {
|
||||
@@ -326,7 +391,7 @@ class Track {
|
||||
}
|
||||
|
||||
private:
|
||||
// Track element names
|
||||
// Track element names.
|
||||
char* codec_id_;
|
||||
uint8* codec_private_;
|
||||
char* language_;
|
||||
@@ -335,6 +400,9 @@ class Track {
|
||||
uint64 number_;
|
||||
uint64 type_;
|
||||
uint64 uid_;
|
||||
uint64 codec_delay_;
|
||||
uint64 seek_pre_roll_;
|
||||
uint64 default_duration_;
|
||||
|
||||
// Size of the CodecPrivate data in bytes.
|
||||
uint64 codec_private_length_;
|
||||
@@ -361,10 +429,7 @@ class VideoTrack : public Track {
|
||||
kSideBySideRightIsFirst = 11
|
||||
};
|
||||
|
||||
enum AlphaMode {
|
||||
kNoAlpha = 0,
|
||||
kAlpha = 1
|
||||
};
|
||||
enum AlphaMode { kNoAlpha = 0, kAlpha = 1 };
|
||||
|
||||
// The |seed| parameter is used to synthesize a UID for the track.
|
||||
explicit VideoTrack(unsigned int* seed);
|
||||
@@ -387,6 +452,16 @@ class VideoTrack : public Track {
|
||||
uint64 display_height() const { return display_height_; }
|
||||
void set_display_width(uint64 width) { display_width_ = 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; }
|
||||
double frame_rate() const { return frame_rate_; }
|
||||
void set_height(uint64 height) { height_ = height; }
|
||||
@@ -403,6 +478,10 @@ class VideoTrack : public Track {
|
||||
// Video track element names.
|
||||
uint64 display_height_;
|
||||
uint64 display_width_;
|
||||
uint64 crop_left_;
|
||||
uint64 crop_right_;
|
||||
uint64 crop_top_;
|
||||
uint64 crop_bottom_;
|
||||
double frame_rate_;
|
||||
uint64 height_;
|
||||
uint64 stereo_mode_;
|
||||
@@ -448,13 +527,13 @@ class AudioTrack : public Track {
|
||||
class Tracks {
|
||||
public:
|
||||
// Audio and video type defined by the Matroska specs.
|
||||
enum {
|
||||
kVideo = 0x1,
|
||||
kAudio = 0x2
|
||||
};
|
||||
// Vorbis and VP8 coded id defined by the Matroska specs.
|
||||
static const char* const kVorbisCodecId;
|
||||
static const char* const kVp8CodecId;
|
||||
enum { kVideo = 0x1, kAudio = 0x2 };
|
||||
|
||||
static const char kOpusCodecId[];
|
||||
static const char kVorbisCodecId[];
|
||||
static const char kVp8CodecId[];
|
||||
static const char kVp9CodecId[];
|
||||
static const char kVp10CodecId[];
|
||||
|
||||
Tracks();
|
||||
~Tracks();
|
||||
@@ -490,6 +569,9 @@ class Tracks {
|
||||
// Number of Track elements added.
|
||||
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);
|
||||
};
|
||||
|
||||
@@ -506,10 +588,13 @@ class Chapter {
|
||||
|
||||
// Converts the nanosecond start and stop times of this chapter to
|
||||
// their corresponding timecode values, and stores them that way.
|
||||
void set_time(const Segment& segment,
|
||||
uint64 start_time_ns,
|
||||
void set_time(const Segment& segment, uint64 start_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
|
||||
// here:
|
||||
// http://www.matroska.org/technical/specs/index.html
|
||||
@@ -526,9 +611,7 @@ class Chapter {
|
||||
// http://www.iana.org/domains/root/db/
|
||||
//
|
||||
// The function returns false if the string could not be allocated.
|
||||
bool add_string(const char* title,
|
||||
const char* language,
|
||||
const char* country);
|
||||
bool add_string(const char* title, const char* language, const char* country);
|
||||
|
||||
private:
|
||||
friend class Chapters;
|
||||
@@ -657,6 +740,112 @@ class 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
|
||||
//
|
||||
@@ -664,34 +853,36 @@ class Chapters {
|
||||
// |Init| must be called before any other method in this class.
|
||||
class Cluster {
|
||||
public:
|
||||
Cluster(uint64 timecode, int64 cues_pos);
|
||||
~Cluster();
|
||||
|
||||
// |timecode| is the absolute timecode of the cluster. |cues_pos| is the
|
||||
// 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);
|
||||
|
||||
// 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
|
||||
// |writer_| if successful. Returns true on success.
|
||||
// Inputs:
|
||||
// frame: Pointer to the data
|
||||
// data: Pointer to the data
|
||||
// length: Length of the data
|
||||
// track_number: Track to add the data to. Value returned by Add track
|
||||
// functions. The range of allowed values is [1, 126].
|
||||
// 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 AddFrame(const uint8* frame,
|
||||
uint64 length,
|
||||
uint64 track_number,
|
||||
bool AddFrame(const uint8* data, uint64 length, uint64 track_number,
|
||||
uint64 timecode, // timecode units (absolute)
|
||||
bool is_key);
|
||||
|
||||
// Adds a frame to be output in the file. The frame is written out through
|
||||
// |writer_| if successful. Returns true on success.
|
||||
// Inputs:
|
||||
// frame: Pointer to the data
|
||||
// data: Pointer to the data
|
||||
// length: Length of the data
|
||||
// additional: Pointer to 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
|
||||
// frame, expressed in timecode units.
|
||||
// is_key: Flag telling whether or not this frame is a key frame.
|
||||
bool AddFrameWithAdditional(const uint8* frame,
|
||||
uint64 length,
|
||||
const uint8* additional,
|
||||
uint64 additional_length,
|
||||
uint64 add_id,
|
||||
uint64 track_number,
|
||||
uint64 abs_timecode,
|
||||
bool is_key);
|
||||
bool AddFrameWithAdditional(const uint8* data, uint64 length,
|
||||
const uint8* additional, uint64 additional_length,
|
||||
uint64 add_id, uint64 track_number,
|
||||
uint64 abs_timecode, bool is_key);
|
||||
|
||||
// Adds a frame to be output in the file. The frame is written out through
|
||||
// |writer_| if successful. 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. 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
|
||||
// success.
|
||||
// Inputs:
|
||||
// frame: Pointer to the data
|
||||
// data: Pointer to the data
|
||||
// length: Length of the data
|
||||
// track_number: Track to add the data to. Value returned by Add track
|
||||
// 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
|
||||
// sub-element but no reference time sub-elements (indicating that
|
||||
// it is considered a keyframe, per Matroska semantics).
|
||||
bool AddMetadata(const uint8* frame,
|
||||
uint64 length,
|
||||
uint64 track_number,
|
||||
uint64 timecode, // timecode units (absolute)
|
||||
uint64 duration); // timecode units
|
||||
bool AddMetadata(const uint8* data, uint64 length, uint64 track_number,
|
||||
uint64 timecode, uint64 duration);
|
||||
|
||||
// Increments the size of the cluster's data in bytes.
|
||||
void AddPayloadSize(uint64 size);
|
||||
@@ -740,52 +939,29 @@ class Cluster {
|
||||
// Returns the size in bytes for the entire Cluster element.
|
||||
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_; }
|
||||
int32 blocks_added() const { return blocks_added_; }
|
||||
uint64 payload_size() const { return payload_size_; }
|
||||
int64 position_for_cues() const { return position_for_cues_; }
|
||||
uint64 timecode() const { return timecode_; }
|
||||
uint64 timecode_scale() const { return timecode_scale_; }
|
||||
|
||||
private:
|
||||
// Signature that matches either of WriteSimpleBlock or WriteMetadataBlock
|
||||
// in the muxer utilities package.
|
||||
typedef uint64 (*WriteBlock)(IMkvWriter* writer,
|
||||
const uint8* data,
|
||||
uint64 length,
|
||||
uint64 track_number,
|
||||
int64 timecode,
|
||||
uint64 generic_arg);
|
||||
// Utility method that confirms that blocks can still be added, and that the
|
||||
// cluster header has been written. Used by |DoWriteFrame*|. Returns true
|
||||
// when successful.
|
||||
bool PreWriteBlock();
|
||||
|
||||
// Signature that matches WriteBlockWithAdditional
|
||||
// in the muxer utilities package.
|
||||
typedef uint64 (*WriteBlockAdditional)(IMkvWriter* writer,
|
||||
const uint8* data,
|
||||
uint64 length,
|
||||
const uint8* additional,
|
||||
uint64 add_id,
|
||||
uint64 additional_length,
|
||||
uint64 track_number,
|
||||
int64 timecode,
|
||||
uint64 is_key);
|
||||
// Utility method used by the |DoWriteFrame*| methods that handles the book
|
||||
// keeping required after each block is written.
|
||||
void PostWriteBlock(uint64 element_size);
|
||||
|
||||
// Used to implement AddFrame and AddMetadata.
|
||||
bool DoWriteBlock(const uint8* 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);
|
||||
// Does some verification and calls WriteFrame.
|
||||
bool DoWriteFrame(const Frame* const frame);
|
||||
|
||||
// Outputs the Cluster header to |writer_|. Returns true on success.
|
||||
bool WriteClusterHeader();
|
||||
@@ -811,6 +987,9 @@ class Cluster {
|
||||
// The absolute timecode of the cluster.
|
||||
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.
|
||||
IMkvWriter* writer_;
|
||||
|
||||
@@ -895,6 +1074,8 @@ class SegmentInfo {
|
||||
uint64 timecode_scale() const { return timecode_scale_; }
|
||||
void set_writing_app(const char* 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:
|
||||
// Segment Information element names.
|
||||
@@ -906,6 +1087,8 @@ class SegmentInfo {
|
||||
uint64 timecode_scale_;
|
||||
// Initially set to libwebm-%d.%d.%d.%d, major, minor, build, revision.
|
||||
char* writing_app_;
|
||||
// LLONG_MIN when DateUTC is not set.
|
||||
int64 date_utc_;
|
||||
|
||||
// The file position of the duration element.
|
||||
int64 duration_pos_;
|
||||
@@ -921,16 +1104,14 @@ class SegmentInfo {
|
||||
// |Init| must be called before any other method in this class.
|
||||
class Segment {
|
||||
public:
|
||||
enum Mode {
|
||||
kLive = 0x1,
|
||||
kFile = 0x2
|
||||
};
|
||||
enum Mode { kLive = 0x1, kFile = 0x2 };
|
||||
|
||||
enum CuesPosition {
|
||||
kAfterClusters = 0x0, // Position Cues after Clusters - Default
|
||||
kBeforeClusters = 0x1 // Position Cues before Clusters
|
||||
};
|
||||
|
||||
const static uint32 kDefaultDocTypeVersion = 2;
|
||||
const static uint64 kDefaultMaxClusterDuration = 30000000000ULL;
|
||||
|
||||
Segment();
|
||||
@@ -947,8 +1128,8 @@ class Segment {
|
||||
// track number.
|
||||
Track* AddTrack(int32 number);
|
||||
|
||||
// Adds an audio track to the segment. Returns the number of the track on
|
||||
// success, 0 on error. |number| is the number to use for the audio track.
|
||||
// Adds a Vorbis audio track to the segment. Returns the number of the 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
|
||||
// the track number.
|
||||
uint64 AddAudioTrack(int32 sample_rate, int32 channels, int32 number);
|
||||
@@ -958,6 +1139,11 @@ class Segment {
|
||||
// populate its fields via the Chapter member functions.
|
||||
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
|
||||
// nanoseconds of the cue's time. |track| is the Track of the Cue. This
|
||||
// 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.
|
||||
// Inputs:
|
||||
// frame: Pointer to the data
|
||||
// data: Pointer to the data
|
||||
// length: Length of the data
|
||||
// track_number: Track to add the data to. Value returned by Add track
|
||||
// functions.
|
||||
// timestamp: Timestamp of the frame in nanoseconds from 0.
|
||||
// is_key: Flag telling whether or not this frame is a key frame.
|
||||
bool AddFrame(const uint8* frame,
|
||||
uint64 length,
|
||||
uint64 track_number,
|
||||
uint64 timestamp_ns,
|
||||
bool is_key);
|
||||
bool AddFrame(const uint8* data, uint64 length, uint64 track_number,
|
||||
uint64 timestamp_ns, bool is_key);
|
||||
|
||||
// Writes a frame of metadata to the output medium; returns true on
|
||||
// success.
|
||||
// Inputs:
|
||||
// frame: Pointer to the data
|
||||
// data: Pointer to the data
|
||||
// length: Length of the data
|
||||
// track_number: Track to add the data to. Value returned by Add track
|
||||
// functions.
|
||||
@@ -992,22 +1175,49 @@ class Segment {
|
||||
// The metadata frame is written as a block group, with a duration
|
||||
// sub-element but no reference time sub-elements (indicating that
|
||||
// it is considered a keyframe, per Matroska semantics).
|
||||
bool AddMetadata(const uint8* frame,
|
||||
uint64 length,
|
||||
uint64 track_number,
|
||||
uint64 timestamp_ns,
|
||||
uint64 duration_ns);
|
||||
bool AddMetadata(const uint8* data, uint64 length, uint64 track_number,
|
||||
uint64 timestamp_ns, uint64 duration_ns);
|
||||
|
||||
bool AddFrameWithAdditional(const uint8* frame,
|
||||
uint64 length,
|
||||
const uint8* additional,
|
||||
uint64 additional_length,
|
||||
uint64 add_id,
|
||||
uint64 track_number,
|
||||
uint64 timestamp,
|
||||
bool is_key);
|
||||
// Writes a frame with additional data to the output medium; returns true on
|
||||
// success.
|
||||
// Inputs:
|
||||
// data: Pointer to the data.
|
||||
// length: Length of the data.
|
||||
// additional: Pointer to additional data.
|
||||
// additional_length: Length of additional data.
|
||||
// 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.
|
||||
// |number| must be >= 0. If |number| == 0 then the muxer will decide on
|
||||
// the track number.
|
||||
@@ -1088,6 +1298,9 @@ class Segment {
|
||||
// Cues elements.
|
||||
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
|
||||
// file extension. |name| must be deleted by the calling app. Returns true
|
||||
// on success.
|
||||
@@ -1133,7 +1346,6 @@ class Segment {
|
||||
// was necessary but creation was not successful.
|
||||
bool DoNewClusterProcessing(uint64 track_num, uint64 timestamp_ns, bool key);
|
||||
|
||||
|
||||
// Adjusts Cue Point values (to place Cues before Clusters) so that they
|
||||
// reflect the correct offsets.
|
||||
void MoveCuesBeforeClusters();
|
||||
@@ -1145,7 +1357,7 @@ class Segment {
|
||||
// diff - indicates the difference in size of the Cues element that needs to
|
||||
// accounted for.
|
||||
// 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);
|
||||
|
||||
// Seeds the random number generator used to make UIDs.
|
||||
@@ -1157,6 +1369,7 @@ class Segment {
|
||||
SegmentInfo segment_info_;
|
||||
Tracks tracks_;
|
||||
Chapters chapters_;
|
||||
Tags tags_;
|
||||
|
||||
// Number of chunks written.
|
||||
int chunk_count_;
|
||||
@@ -1222,9 +1435,15 @@ class Segment {
|
||||
// Flag telling if the segment's header has been written.
|
||||
bool header_written_;
|
||||
|
||||
// Duration of the last block in nanoseconds.
|
||||
uint64 last_block_duration_;
|
||||
|
||||
// Last timestamp in nanoseconds added to a cluster.
|
||||
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
|
||||
// guideline and some clusters may have a longer duration. Default is 30
|
||||
// seconds.
|
||||
@@ -1246,12 +1465,23 @@ class Segment {
|
||||
// Flag whether or not the muxer should output a Cues element.
|
||||
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.
|
||||
int64 payload_pos_;
|
||||
|
||||
// The file position of the element's size.
|
||||
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.
|
||||
IMkvWriter* writer_cluster_;
|
||||
IMkvWriter* writer_cues_;
|
||||
@@ -1260,6 +1490,6 @@ class 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 unsigned long long uint64;
|
||||
|
||||
} //end namespace mkvmuxer
|
||||
} // end namespace mkvmuxer
|
||||
|
||||
#endif // MKVMUXERTYPES_HPP
|
||||
|
||||
507
mkvmuxerutil.cpp
507
mkvmuxerutil.cpp
@@ -12,22 +12,169 @@
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#ifdef _WIN32
|
||||
#define _CRT_RAND_S
|
||||
#endif
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "mkvwriter.hpp"
|
||||
#include "webmids.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Disable MSVC warnings that suggest making code non-portable.
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
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) {
|
||||
if (value < 0x000000000000007FULL)
|
||||
return 1;
|
||||
@@ -64,6 +211,13 @@ int32 GetUIntSize(uint64 value) {
|
||||
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) {
|
||||
// Size of EBML ID
|
||||
int32 ebml_size = GetUIntSize(type);
|
||||
@@ -74,6 +228,19 @@ uint64 EbmlMasterElementSize(uint64 type, uint64 value) {
|
||||
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) {
|
||||
// Size of EBML ID
|
||||
int32 ebml_size = GetUIntSize(type);
|
||||
@@ -87,7 +254,7 @@ uint64 EbmlElementSize(uint64 type, uint64 value) {
|
||||
return ebml_size;
|
||||
}
|
||||
|
||||
uint64 EbmlElementSize(uint64 type, float /* value */ ) {
|
||||
uint64 EbmlElementSize(uint64 type, float /* value */) {
|
||||
// Size of EBML ID
|
||||
uint64 ebml_size = GetUIntSize(type);
|
||||
|
||||
@@ -132,6 +299,19 @@ uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 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) {
|
||||
if (!writer || size < 1 || size > 8)
|
||||
return -1;
|
||||
@@ -156,16 +336,22 @@ int32 SerializeFloat(IMkvWriter* writer, float f) {
|
||||
if (!writer)
|
||||
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) {
|
||||
const int32 byte_count = 4 - i;
|
||||
const int32 bit_count = byte_count * 8;
|
||||
|
||||
const uint32 bb = val >> bit_count;
|
||||
const uint8 b = static_cast<uint8>(bb);
|
||||
const uint8 byte = static_cast<uint8>(value.u32 >> bit_count);
|
||||
|
||||
const int32 status = writer->Write(&b, 1);
|
||||
const int32 status = writer->Write(&byte, 1);
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
@@ -258,6 +444,23 @@ bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value) {
|
||||
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) {
|
||||
if (!writer)
|
||||
return false;
|
||||
@@ -281,19 +484,17 @@ bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value) {
|
||||
if (WriteID(writer, type))
|
||||
return false;
|
||||
|
||||
const int32 length = strlen(value);
|
||||
const uint64 length = strlen(value);
|
||||
if (WriteUInt(writer, length))
|
||||
return false;
|
||||
|
||||
if (writer->Write(value, length))
|
||||
if (writer->Write(value, static_cast<const uint32>(length)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteEbmlElement(IMkvWriter* writer,
|
||||
uint64 type,
|
||||
const uint8* value,
|
||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const uint8* value,
|
||||
uint64 size) {
|
||||
if (!writer || !value || size < 1)
|
||||
return false;
|
||||
@@ -310,247 +511,41 @@ bool WriteEbmlElement(IMkvWriter* writer,
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64 WriteSimpleBlock(IMkvWriter* writer,
|
||||
const uint8* data,
|
||||
uint64 length,
|
||||
uint64 track_number,
|
||||
int64 timecode,
|
||||
uint64 is_key) {
|
||||
bool WriteEbmlDateElement(IMkvWriter* writer, uint64 type, int64 value) {
|
||||
if (!writer)
|
||||
return false;
|
||||
|
||||
if (!data || length < 1)
|
||||
if (WriteID(writer, type))
|
||||
return false;
|
||||
|
||||
// Here we only permit track number values to be no greater than
|
||||
// 126, which the largest value we can store having a Matroska
|
||||
// integer representation of only 1 byte.
|
||||
|
||||
if (track_number < 1 || track_number > 126)
|
||||
if (WriteUInt(writer, kDateElementSize))
|
||||
return false;
|
||||
|
||||
// Technically the timestamp for a block can be less than the
|
||||
// timestamp for the cluster itself (remember that block timestamp
|
||||
if (SerializeInt(writer, value, kDateElementSize))
|
||||
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
|
||||
// only permit non-negative cluster-relative timestamps for blocks.
|
||||
|
||||
if (timecode < 0 || timecode > kMaxBlockTimecode)
|
||||
return false;
|
||||
|
||||
if (WriteID(writer, kMkvSimpleBlock))
|
||||
// only permit non-negative cluster-relative timecodes for blocks.
|
||||
const int64 relative_timecode = cluster->GetRelativeTimecode(
|
||||
frame->timestamp() / cluster->timecode_scale());
|
||||
if (relative_timecode < 0 || relative_timecode > kMaxBlockTimecode)
|
||||
return 0;
|
||||
|
||||
const int32 size = static_cast<int32>(length) + 4;
|
||||
if (WriteUInt(writer, size))
|
||||
return 0;
|
||||
|
||||
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;
|
||||
return frame->CanBeSimpleBlock() ?
|
||||
WriteSimpleBlock(writer, frame, relative_timecode) :
|
||||
WriteBlock(writer, frame, relative_timecode,
|
||||
cluster->timecode_scale());
|
||||
}
|
||||
|
||||
uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
|
||||
@@ -558,9 +553,9 @@ uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
|
||||
return false;
|
||||
|
||||
// Subtract one for the void ID and the coded size.
|
||||
uint64 void_entry_size = size - 1 - GetCodedUIntSize(size-1);
|
||||
uint64 void_size = EbmlMasterElementSize(kMkvVoid, void_entry_size) +
|
||||
void_entry_size;
|
||||
uint64 void_entry_size = size - 1 - GetCodedUIntSize(size - 1);
|
||||
uint64 void_size =
|
||||
EbmlMasterElementSize(kMkvVoid, void_entry_size) + void_entry_size;
|
||||
|
||||
if (void_size != size)
|
||||
return 0;
|
||||
@@ -600,16 +595,18 @@ void GetVersion(int32* major, int32* minor, int32* build, int32* revision) {
|
||||
|
||||
mkvmuxer::uint64 mkvmuxer::MakeUID(unsigned int* seed) {
|
||||
uint64 uid = 0;
|
||||
|
||||
#ifdef __MINGW32__
|
||||
srand(*seed);
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < 7; ++i) { // avoid problems with 8-byte values
|
||||
uid <<= 8;
|
||||
|
||||
// TODO(fgalligan): Move random number generation to platform specific code.
|
||||
#ifdef _WIN32
|
||||
// TODO(fgalligan): Move random number generation to platform specific code.
|
||||
#ifdef _MSC_VER
|
||||
(void)seed;
|
||||
unsigned int random_value;
|
||||
const errno_t e = rand_s(&random_value);
|
||||
(void)e;
|
||||
const int32 nn = random_value;
|
||||
const int32 nn = rand();
|
||||
#elif __ANDROID__
|
||||
int32 temp_num = 1;
|
||||
int fd = open("/dev/urandom", O_RDONLY);
|
||||
@@ -618,6 +615,8 @@ mkvmuxer::uint64 mkvmuxer::MakeUID(unsigned int* seed) {
|
||||
close(fd);
|
||||
}
|
||||
const int32 nn = temp_num;
|
||||
#elif defined __MINGW32__
|
||||
const int32 nn = rand();
|
||||
#else
|
||||
const int32 nn = rand_r(seed);
|
||||
#endif
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#ifndef MKVMUXERUTIL_HPP
|
||||
#define MKVMUXERUTIL_HPP
|
||||
|
||||
#include "mkvmuxer.hpp"
|
||||
#include "mkvmuxertypes.hpp"
|
||||
|
||||
namespace mkvmuxer {
|
||||
@@ -23,12 +24,15 @@ int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size);
|
||||
|
||||
// Returns the size in bytes of the element.
|
||||
int32 GetUIntSize(uint64 value);
|
||||
int32 GetIntSize(int64 value);
|
||||
int32 GetCodedUIntSize(uint64 value);
|
||||
uint64 EbmlMasterElementSize(uint64 type, uint64 value);
|
||||
uint64 EbmlElementSize(uint64 type, int64 value);
|
||||
uint64 EbmlElementSize(uint64 type, uint64 value);
|
||||
uint64 EbmlElementSize(uint64 type, float value);
|
||||
uint64 EbmlElementSize(uint64 type, const char* value);
|
||||
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
|
||||
// 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.
|
||||
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, const char* value);
|
||||
bool WriteEbmlElement(IMkvWriter* writer,
|
||||
uint64 type,
|
||||
const uint8* value,
|
||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const uint8* value,
|
||||
uint64 size);
|
||||
bool WriteEbmlDateElement(IMkvWriter* writer, uint64 type, int64 value);
|
||||
|
||||
// Output an Mkv Simple Block.
|
||||
// Inputs:
|
||||
// data: Pointer to the data.
|
||||
// length: Length of the 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: 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 Mkv Frame. It decides the correct element to write (Block vs
|
||||
// SimpleBlock) based on the parameters of the Frame.
|
||||
uint64 WriteFrame(IMkvWriter* writer, const Frame* const frame,
|
||||
Cluster* cluster);
|
||||
|
||||
// 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
|
||||
@@ -126,6 +78,6 @@ void GetVersion(int32* major, int32* minor, int32* build, int32* revision);
|
||||
// the random-number generator (see POSIX rand_r() for semantics).
|
||||
uint64 MakeUID(unsigned int* seed);
|
||||
|
||||
} //end namespace mkvmuxer
|
||||
} // end namespace mkvmuxer
|
||||
|
||||
#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>
|
||||
|
||||
namespace mkvparser
|
||||
{
|
||||
namespace mkvparser {
|
||||
|
||||
MkvReader::MkvReader() :
|
||||
m_file(NULL)
|
||||
{
|
||||
MkvReader::MkvReader() : m_file(NULL), reader_owns_file_(true) {}
|
||||
|
||||
MkvReader::MkvReader(FILE* fp) : m_file(fp), reader_owns_file_(false) {
|
||||
GetFileSize();
|
||||
}
|
||||
|
||||
MkvReader::~MkvReader()
|
||||
{
|
||||
MkvReader::~MkvReader() {
|
||||
if (reader_owns_file_)
|
||||
Close();
|
||||
m_file = NULL;
|
||||
}
|
||||
|
||||
int MkvReader::Open(const char* fileName)
|
||||
{
|
||||
int MkvReader::Open(const char* fileName) {
|
||||
if (fileName == NULL)
|
||||
return -1;
|
||||
|
||||
if (m_file)
|
||||
return -1;
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _MSC_VER
|
||||
const errno_t e = fopen_s(&m_file, fileName, "rb");
|
||||
|
||||
if (e)
|
||||
return -1; //error
|
||||
return -1; // error
|
||||
#else
|
||||
m_file = fopen(fileName, "rb");
|
||||
|
||||
if (m_file == NULL)
|
||||
return -1;
|
||||
#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);
|
||||
|
||||
if (status)
|
||||
return -1; //error
|
||||
return false; // error
|
||||
|
||||
m_length = _ftelli64(m_file);
|
||||
#else
|
||||
@@ -56,29 +61,29 @@ int MkvReader::Open(const char* fileName)
|
||||
#endif
|
||||
assert(m_length >= 0);
|
||||
|
||||
#ifdef WIN32
|
||||
if (m_length < 0)
|
||||
return false;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
status = _fseeki64(m_file, 0L, SEEK_SET);
|
||||
|
||||
if (status)
|
||||
return -1; //error
|
||||
return false; // error
|
||||
#else
|
||||
fseek(m_file, 0L, SEEK_SET);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void MkvReader::Close()
|
||||
{
|
||||
if (m_file != NULL)
|
||||
{
|
||||
void MkvReader::Close() {
|
||||
if (m_file != NULL) {
|
||||
fclose(m_file);
|
||||
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)
|
||||
return -1;
|
||||
|
||||
@@ -91,8 +96,7 @@ int MkvReader::Length(long long* total, long long* available)
|
||||
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)
|
||||
return -1;
|
||||
|
||||
@@ -108,11 +112,11 @@ int MkvReader::Read(long long offset, long len, unsigned char* buffer)
|
||||
if (offset >= m_length)
|
||||
return -1;
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _MSC_VER
|
||||
const int status = _fseeki64(m_file, offset, SEEK_SET);
|
||||
|
||||
if (status)
|
||||
return -1; //error
|
||||
return -1; // error
|
||||
#else
|
||||
fseek(m_file, offset, SEEK_SET);
|
||||
#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);
|
||||
|
||||
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 <cstdio>
|
||||
|
||||
namespace mkvparser
|
||||
{
|
||||
namespace mkvparser {
|
||||
|
||||
class MkvReader : public IMkvReader
|
||||
{
|
||||
MkvReader(const MkvReader&);
|
||||
MkvReader& operator=(const MkvReader&);
|
||||
public:
|
||||
class MkvReader : public IMkvReader {
|
||||
public:
|
||||
MkvReader();
|
||||
explicit MkvReader(FILE* fp);
|
||||
virtual ~MkvReader();
|
||||
|
||||
int Open(const char*);
|
||||
@@ -28,11 +25,21 @@ public:
|
||||
|
||||
virtual int Read(long long position, long length, unsigned char* buffer);
|
||||
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;
|
||||
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 {
|
||||
|
||||
MkvWriter::MkvWriter() : file_(NULL) {
|
||||
}
|
||||
MkvWriter::MkvWriter() : file_(NULL), writer_owns_file_(true) {}
|
||||
|
||||
MkvWriter::~MkvWriter() {
|
||||
Close();
|
||||
}
|
||||
MkvWriter::MkvWriter(FILE* fp) : file_(fp), writer_owns_file_(false) {}
|
||||
|
||||
MkvWriter::~MkvWriter() { Close(); }
|
||||
|
||||
int32 MkvWriter::Write(const void* buffer, uint32 length) {
|
||||
if (!file_)
|
||||
@@ -56,10 +55,10 @@ bool MkvWriter::Open(const char* filename) {
|
||||
}
|
||||
|
||||
void MkvWriter::Close() {
|
||||
if (file_) {
|
||||
if (file_ && writer_owns_file_) {
|
||||
fclose(file_);
|
||||
file_ = NULL;
|
||||
}
|
||||
file_ = NULL;
|
||||
}
|
||||
|
||||
int64 MkvWriter::Position() const {
|
||||
@@ -84,11 +83,8 @@ int32 MkvWriter::Position(int64 position) {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool MkvWriter::Seekable() const {
|
||||
return true;
|
||||
}
|
||||
bool MkvWriter::Seekable() const { return true; }
|
||||
|
||||
void MkvWriter::ElementStartNotify(uint64, int64) {
|
||||
}
|
||||
void MkvWriter::ElementStartNotify(uint64, int64) {}
|
||||
|
||||
} // namespace mkvmuxer
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace mkvmuxer {
|
||||
class MkvWriter : public IMkvWriter {
|
||||
public:
|
||||
MkvWriter();
|
||||
explicit MkvWriter(FILE* fp);
|
||||
virtual ~MkvWriter();
|
||||
|
||||
// IMkvWriter interface
|
||||
@@ -40,10 +41,11 @@ class MkvWriter : public IMkvWriter {
|
||||
private:
|
||||
// File handle to output file.
|
||||
FILE* file_;
|
||||
bool writer_owns_file_;
|
||||
|
||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(MkvWriter);
|
||||
};
|
||||
|
||||
} //end namespace mkvmuxer
|
||||
} // end namespace mkvmuxer
|
||||
|
||||
#endif // MKVWRITER_HPP
|
||||
|
||||
191
sample.cpp
191
sample.cpp
@@ -6,37 +6,34 @@
|
||||
// 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.
|
||||
// This sample application demonstrates how to use the Matroska parser
|
||||
// library, which allows clients to handle a Matroska format file.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "mkvreader.hpp"
|
||||
#include "mkvparser.hpp"
|
||||
#include <memory>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Silences these warnings:
|
||||
// warning C4996: 'mbstowcs': This function or variable may be unsafe. Consider
|
||||
// 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)
|
||||
// Disable MSVC warnings that suggest making code non-portable.
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
static const wchar_t* utf8towcs(const char* str)
|
||||
{
|
||||
static const wchar_t* utf8towcs(const char* str) {
|
||||
if (str == NULL)
|
||||
return NULL;
|
||||
|
||||
//TODO: this probably requires that the locale be
|
||||
//configured somehow:
|
||||
// TODO: this probably requires that the locale be
|
||||
// configured somehow:
|
||||
|
||||
const size_t size = mbstowcs(NULL, str, 0);
|
||||
|
||||
if (size == 0)
|
||||
if (size == 0 || size == static_cast<size_t>(-1))
|
||||
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);
|
||||
val[size] = L'\0';
|
||||
@@ -44,11 +41,23 @@ static const wchar_t* utf8towcs(const char* str)
|
||||
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[])
|
||||
{
|
||||
if (argc == 1)
|
||||
{
|
||||
while (!cues->DoneParsing())
|
||||
cues->LoadCuePoint();
|
||||
|
||||
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\tUsage: \n");
|
||||
printf("\t\t\t ./sample [input file] \n");
|
||||
@@ -60,8 +69,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
MkvReader reader;
|
||||
|
||||
if (reader.Open(argv[1]))
|
||||
{
|
||||
if (reader.Open(argv[1])) {
|
||||
printf("\n Filename is invalid or error while opening.\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -75,7 +83,11 @@ int main(int argc, char* argv[])
|
||||
|
||||
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\tEBML Version\t\t: %lld\n", ebmlHeader.m_version);
|
||||
@@ -87,9 +99,8 @@ int main(int argc, char* argv[])
|
||||
typedef mkvparser::Segment seg_t;
|
||||
seg_t* pSegment_;
|
||||
|
||||
long long ret = seg_t::CreateInstance(&reader, pos, pSegment_);
|
||||
if (ret)
|
||||
{
|
||||
ret = seg_t::CreateInstance(&reader, pos, pSegment_);
|
||||
if (ret) {
|
||||
printf("\n Segment::CreateInstance() failed.");
|
||||
return -1;
|
||||
}
|
||||
@@ -97,13 +108,16 @@ int main(int argc, char* argv[])
|
||||
const std::auto_ptr<seg_t> pSegment(pSegment_);
|
||||
|
||||
ret = pSegment->Load();
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
printf("\n Segment::Load() failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
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 duration_ns = pSegmentInfo->GetDuration();
|
||||
@@ -127,27 +141,23 @@ int main(int argc, char* argv[])
|
||||
|
||||
if (pTitle == NULL)
|
||||
printf("\t\tTrack Name\t\t: NULL\n");
|
||||
else
|
||||
{
|
||||
else {
|
||||
printf("\t\tTrack Name\t\t: %ls\n", pTitle);
|
||||
delete [] pTitle;
|
||||
delete[] pTitle;
|
||||
}
|
||||
|
||||
|
||||
if (pMuxingApp == NULL)
|
||||
printf("\t\tMuxing App\t\t: NULL\n");
|
||||
else
|
||||
{
|
||||
else {
|
||||
printf("\t\tMuxing App\t\t: %ls\n", pMuxingApp);
|
||||
delete [] pMuxingApp;
|
||||
delete[] pMuxingApp;
|
||||
}
|
||||
|
||||
if (pWritingApp == NULL)
|
||||
printf("\t\tWriting App\t\t: NULL\n");
|
||||
else
|
||||
{
|
||||
else {
|
||||
printf("\t\tWriting App\t\t: %ls\n", pWritingApp);
|
||||
delete [] pWritingApp;
|
||||
delete[] pWritingApp;
|
||||
}
|
||||
|
||||
// pos of segment payload
|
||||
@@ -158,14 +168,13 @@ int main(int argc, char* argv[])
|
||||
|
||||
const mkvparser::Tracks* pTracks = pSegment->GetTracks();
|
||||
|
||||
unsigned long i = 0;
|
||||
const unsigned long j = pTracks->GetTracksCount();
|
||||
unsigned long track_num = 0;
|
||||
const unsigned long num_tracks = pTracks->GetTracksCount();
|
||||
|
||||
printf("\n\t\t\t Track Info\n");
|
||||
|
||||
while (i != j)
|
||||
{
|
||||
const Track* const pTrack = pTracks->GetTrackByIndex(i++);
|
||||
while (track_num != num_tracks) {
|
||||
const Track* const pTrack = pTracks->GetTrackByIndex(track_num++);
|
||||
|
||||
if (pTrack == NULL)
|
||||
continue;
|
||||
@@ -181,10 +190,9 @@ int main(int argc, char* argv[])
|
||||
|
||||
if (pTrackName == NULL)
|
||||
printf("\t\tTrack Name\t\t: NULL\n");
|
||||
else
|
||||
{
|
||||
else {
|
||||
printf("\t\tTrack Name\t\t: %ls \n", pTrackName);
|
||||
delete [] pTrackName;
|
||||
delete[] pTrackName;
|
||||
}
|
||||
|
||||
const char* const pCodecId = pTrack->GetCodecId();
|
||||
@@ -199,14 +207,12 @@ int main(int argc, char* argv[])
|
||||
|
||||
if (pCodecName == NULL)
|
||||
printf("\t\tCodec Name\t\t: NULL\n");
|
||||
else
|
||||
{
|
||||
else {
|
||||
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 =
|
||||
static_cast<const VideoTrack*>(pTrack);
|
||||
|
||||
@@ -217,11 +223,10 @@ int main(int argc, char* argv[])
|
||||
printf("\t\tVideo Height\t\t: %lld\n", height);
|
||||
|
||||
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 =
|
||||
static_cast<const AudioTrack*>(pTrack);
|
||||
|
||||
@@ -233,6 +238,12 @@ int main(int argc, char* argv[])
|
||||
|
||||
const double sampleRate = pAudioTrack->GetSamplingRate();
|
||||
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);
|
||||
|
||||
if (clusterCount == 0)
|
||||
{
|
||||
if (clusterCount == 0) {
|
||||
printf("\t\tSegment has no clusters.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
const mkvparser::Cluster* pCluster = pSegment->GetFirst();
|
||||
|
||||
while ((pCluster != NULL) && !pCluster->EOS())
|
||||
{
|
||||
while ((pCluster != NULL) && !pCluster->EOS()) {
|
||||
const long long timeCode = pCluster->GetTimeCode();
|
||||
printf("\t\tCluster Time Code\t: %lld\n", timeCode);
|
||||
|
||||
@@ -261,15 +270,14 @@ int main(int argc, char* argv[])
|
||||
|
||||
long status = pCluster->GetFirst(pBlockEntry);
|
||||
|
||||
if (status < 0) //error
|
||||
if (status < 0) // error
|
||||
{
|
||||
printf("\t\tError parsing first block of cluster\n");
|
||||
fflush(stdout);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((pBlockEntry != NULL) && !pBlockEntry->EOS())
|
||||
{
|
||||
while ((pBlockEntry != NULL) && !pBlockEntry->EOS()) {
|
||||
const Block* const pBlock = pBlockEntry->GetBlock();
|
||||
const long long trackNum = pBlock->GetTrackNumber();
|
||||
const unsigned long tn = static_cast<unsigned long>(trackNum);
|
||||
@@ -277,19 +285,17 @@ int main(int argc, char* argv[])
|
||||
|
||||
if (pTrack == NULL)
|
||||
printf("\t\t\tBlock\t\t:UNKNOWN TRACK TYPE\n");
|
||||
else
|
||||
{
|
||||
else {
|
||||
const long long trackType = pTrack->GetType();
|
||||
const int frameCount = pBlock->GetFrameCount();
|
||||
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",
|
||||
pBlock->IsKey() ? "I" : "P",
|
||||
time_ns);
|
||||
pBlock->IsKey() ? "I" : "P", time_ns, discard_padding);
|
||||
|
||||
for (int i = 0; i < frameCount; ++i)
|
||||
{
|
||||
for (int i = 0; i < frameCount; ++i) {
|
||||
const Block::Frame& theFrame = pBlock->GetFrame(i);
|
||||
const long size = theFrame.len;
|
||||
const long long offset = theFrame.pos;
|
||||
@@ -299,8 +305,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
status = pCluster->GetNext(pBlockEntry, pBlockEntry);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
if (status < 0) {
|
||||
printf("\t\t\tError parsing next block of cluster\n");
|
||||
fflush(stdout);
|
||||
return -1;
|
||||
@@ -310,6 +315,52 @@ int main(int argc, char* argv[])
|
||||
pCluster = pSegment->GetNext(pCluster);
|
||||
}
|
||||
|
||||
if (InputHasCues(pSegment.get())) {
|
||||
// Walk them.
|
||||
const mkvparser::Cues* const cues = pSegment->GetCues();
|
||||
const mkvparser::CuePoint* cue = cues->GetFirst();
|
||||
int cue_point_num = 1;
|
||||
|
||||
printf("\t\tCues\n");
|
||||
do {
|
||||
for (track_num = 0; track_num < num_tracks; ++track_num) {
|
||||
const mkvparser::Track* const track =
|
||||
pTracks->GetTrackByIndex(track_num);
|
||||
const mkvparser::CuePoint::TrackPosition* const track_pos =
|
||||
cue->Find(track);
|
||||
|
||||
if (track_pos != NULL) {
|
||||
const char track_type =
|
||||
(track->GetType() == mkvparser::Track::kVideo) ? 'V' : 'A';
|
||||
printf(
|
||||
"\t\t\tCue Point %4d Track %3lu(%c) Time %14lld "
|
||||
"Block %4lld Pos %8llx\n",
|
||||
cue_point_num, track->GetNumber(), track_type,
|
||||
cue->GetTime(pSegment.get()), track_pos->m_block,
|
||||
track_pos->m_pos);
|
||||
}
|
||||
}
|
||||
|
||||
cue = cues->GetNext(cue);
|
||||
++cue_point_num;
|
||||
} while (cue != NULL);
|
||||
}
|
||||
|
||||
const mkvparser::Tags* const tags = pSegment->GetTags();
|
||||
if (tags && tags->GetTagCount() > 0) {
|
||||
printf("\t\tTags\n");
|
||||
for (int i = 0; i < tags->GetTagCount(); ++i) {
|
||||
const mkvparser::Tags::Tag* const tag = tags->GetTag(i);
|
||||
printf("\t\t\tTag\n");
|
||||
for (int j = 0; j < tag->GetSimpleTagCount(); j++) {
|
||||
const mkvparser::Tags::SimpleTag* const simple_tag =
|
||||
tag->GetSimpleTag(j);
|
||||
printf("\t\t\t\tSimple Tag \"%s\" Value \"%s\"\n",
|
||||
simple_tag->GetTagName(), simple_tag->GetTagString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,181 +0,0 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="sample"
|
||||
ProjectGUID="{0CB5681F-6065-490C-98C8-05531732ED7E}"
|
||||
RootNamespace="sample"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="131072"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(ProjectDir)..\exe\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ProjectDir)..\obj\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="false"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="$(ProjectDir)..\lib\libwebm_2008\libwebm\$(PlatformName)\$(ConfigurationName)\libwebm.lib"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(ProjectDir)..\exe\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ProjectDir)..\obj\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="$(ProjectDir)..\lib\libwebm_2008\libwebm\$(PlatformName)\$(ConfigurationName)\libwebm.lib"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<File
|
||||
RelativePath=".\sample.cpp"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -1,181 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug DLL|Win32">
|
||||
<Configuration>Debug DLL</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release DLL|Win32">
|
||||
<Configuration>Release DLL</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectName>sample</ProjectName>
|
||||
<ProjectGuid>{0CB5681F-6065-490C-98C8-05531732ED7E}</ProjectGuid>
|
||||
<RootNamespace>sample</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>Windows7.1SDK</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>Windows7.1SDK</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>Windows7.1SDK</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>Windows7.1SDK</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">true</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="sample.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="libwebm_2010.vcxproj">
|
||||
<Project>{7b1f12ca-0724-430b-b61a-1d357c912cba}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="sample.cpp" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
141
sample_muxer.cpp
141
sample_muxer.cpp
@@ -9,6 +9,7 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
@@ -23,8 +24,14 @@
|
||||
|
||||
#include "sample_muxer_metadata.h"
|
||||
|
||||
using mkvmuxer::int64;
|
||||
using mkvmuxer::uint64;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Disable MSVC warnings that suggest making code non-portable.
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
void Usage() {
|
||||
@@ -45,6 +52,7 @@ void Usage() {
|
||||
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(" -chunking <string> Chunk output\n");
|
||||
printf(" -copy_tags <int> >0 Copies the tags\n");
|
||||
printf("\n");
|
||||
printf("Video options:\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("\n");
|
||||
printf("Metadata options:\n");
|
||||
printf(" -webvtt-subtitles <vttfile> "
|
||||
"add WebVTT subtitles as metadata track\n");
|
||||
printf(" -webvtt-captions <vttfile> "
|
||||
"add WebVTT captions as metadata track\n");
|
||||
printf(" -webvtt-descriptions <vttfile> "
|
||||
"add WebVTT descriptions as metadata track\n");
|
||||
printf(" -webvtt-metadata <vttfile> "
|
||||
"add WebVTT subtitles as metadata track\n");
|
||||
printf(" -webvtt-chapters <vttfile> "
|
||||
"add WebVTT chapters as MKV chapters element\n");
|
||||
printf(" -webvtt-subtitles <vttfile> ");
|
||||
printf("add WebVTT subtitles as metadata track\n");
|
||||
printf(" -webvtt-captions <vttfile> ");
|
||||
printf("add WebVTT captions as metadata track\n");
|
||||
printf(" -webvtt-descriptions <vttfile> ");
|
||||
printf("add WebVTT descriptions as metadata track\n");
|
||||
printf(" -webvtt-metadata <vttfile> ");
|
||||
printf("add WebVTT subtitles as metadata track\n");
|
||||
printf(" -webvtt-chapters <vttfile> ");
|
||||
printf("add WebVTT chapters as MKV chapters element\n");
|
||||
}
|
||||
|
||||
struct MetadataFile {
|
||||
@@ -76,8 +84,7 @@ struct MetadataFile {
|
||||
typedef std::list<MetadataFile> metadata_files_t;
|
||||
|
||||
// Cache the WebVTT filenames specified as command-line args.
|
||||
bool LoadMetadataFiles(
|
||||
const metadata_files_t& files,
|
||||
bool LoadMetadataFiles(const metadata_files_t& files,
|
||||
SampleMuxerMetadata* metadata) {
|
||||
typedef metadata_files_t::const_iterator iter_t;
|
||||
|
||||
@@ -94,22 +101,21 @@ bool LoadMetadataFiles(
|
||||
return true;
|
||||
}
|
||||
|
||||
int ParseArgWebVTT(
|
||||
char* argv[],
|
||||
int* argv_index,
|
||||
int argc_check,
|
||||
int ParseArgWebVTT(char* argv[], int* argv_index, int argc_check,
|
||||
metadata_files_t* metadata_files) {
|
||||
int& i = *argv_index;
|
||||
|
||||
enum { kCount = 5 };
|
||||
struct Arg { const char* name; SampleMuxerMetadata::Kind kind; };
|
||||
const Arg args[kCount] = {
|
||||
{ "-webvtt-subtitles", SampleMuxerMetadata::kSubtitles },
|
||||
{ "-webvtt-captions", SampleMuxerMetadata::kCaptions },
|
||||
{ "-webvtt-descriptions", SampleMuxerMetadata::kDescriptions },
|
||||
{ "-webvtt-metadata", SampleMuxerMetadata::kMetadata },
|
||||
{ "-webvtt-chapters", SampleMuxerMetadata::kChapters }
|
||||
struct Arg {
|
||||
const char* name;
|
||||
SampleMuxerMetadata::Kind kind;
|
||||
};
|
||||
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) {
|
||||
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 video_track_number = 0; // 0 tells muxer to decide.
|
||||
bool chunking = false;
|
||||
bool copy_tags = false;
|
||||
const char* chunk_name = NULL;
|
||||
|
||||
bool output_cues_block_number = true;
|
||||
@@ -196,8 +203,7 @@ int main(int argc, char* argv[]) {
|
||||
cues_on_video_track = false;
|
||||
} else if (!strcmp("-max_cluster_duration", argv[i]) && i < argc_check) {
|
||||
const double seconds = strtod(argv[++i], &end);
|
||||
max_cluster_duration =
|
||||
static_cast<uint64>(seconds * 1000000000.0);
|
||||
max_cluster_duration = static_cast<uint64>(seconds * 1000000000.0);
|
||||
} else if (!strcmp("-max_cluster_size", argv[i]) && i < argc_check) {
|
||||
max_cluster_size = strtol(argv[++i], &end, 10);
|
||||
} 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) {
|
||||
chunking = true;
|
||||
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) {
|
||||
display_width = strtol(argv[++i], &end, 10);
|
||||
} else if (!strcmp("-display_height", argv[i]) && i < argc_check) {
|
||||
@@ -240,17 +248,20 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
long long pos = 0;
|
||||
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;
|
||||
long long ret = mkvparser::Segment::CreateInstance(&reader,
|
||||
pos,
|
||||
parser_segment);
|
||||
mkvparser::Segment* parser_segment_;
|
||||
ret = mkvparser::Segment::CreateInstance(&reader, pos, parser_segment_);
|
||||
if (ret) {
|
||||
printf("\n Segment::CreateInstance() failed.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const std::auto_ptr<mkvparser::Segment> parser_segment(parser_segment_);
|
||||
ret = parser_segment->Load();
|
||||
if (ret < 0) {
|
||||
printf("\n Segment::Load() failed.");
|
||||
@@ -258,6 +269,10 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
// Set muxer header info
|
||||
@@ -296,6 +311,21 @@ int main(int argc, char* argv[]) {
|
||||
info->set_timecode_scale(timeCodeScale);
|
||||
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
|
||||
const mkvparser::Tracks* const parser_tracks = parser_segment->GetTracks();
|
||||
unsigned long i = 0;
|
||||
@@ -336,8 +366,7 @@ int main(int argc, char* argv[]) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
mkvmuxer::VideoTrack* const video =
|
||||
static_cast<mkvmuxer::VideoTrack*>(
|
||||
mkvmuxer::VideoTrack* const video = static_cast<mkvmuxer::VideoTrack*>(
|
||||
muxer_segment.GetTrackByNumber(vid_track));
|
||||
if (!video) {
|
||||
printf("\n Could not get video track.\n");
|
||||
@@ -347,6 +376,8 @@ int main(int argc, char* argv[]) {
|
||||
if (track_name)
|
||||
video->set_name(track_name);
|
||||
|
||||
video->set_codec_id(pVideoTrack->GetCodecId());
|
||||
|
||||
if (display_width > 0)
|
||||
video->set_display_width(display_width);
|
||||
if (display_height > 0)
|
||||
@@ -374,8 +405,7 @@ int main(int argc, char* argv[]) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
mkvmuxer::AudioTrack* const audio =
|
||||
static_cast<mkvmuxer::AudioTrack*>(
|
||||
mkvmuxer::AudioTrack* const audio = static_cast<mkvmuxer::AudioTrack*>(
|
||||
muxer_segment.GetTrackByNumber(aud_track));
|
||||
if (!audio) {
|
||||
printf("\n Could not get audio track.\n");
|
||||
@@ -385,6 +415,8 @@ int main(int argc, char* argv[]) {
|
||||
if (track_name)
|
||||
audio->set_name(track_name);
|
||||
|
||||
audio->set_codec_id(pAudioTrack->GetCodecId());
|
||||
|
||||
size_t private_size;
|
||||
const unsigned char* const private_data =
|
||||
pAudioTrack->GetCodecPrivate(private_size);
|
||||
@@ -398,6 +430,11 @@ int main(int argc, char* argv[]) {
|
||||
const long long bit_depth = pAudioTrack->GetBitDepth();
|
||||
if (bit_depth > 0)
|
||||
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 long long trackNum = block->GetTrackNumber();
|
||||
const mkvparser::Track* const parser_track =
|
||||
parser_tracks->GetTrackByNumber(
|
||||
static_cast<unsigned long>(trackNum));
|
||||
parser_tracks->GetTrackByNumber(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 time_ns = block->GetTime(cluster);
|
||||
|
||||
@@ -460,13 +504,12 @@ int main(int argc, char* argv[]) {
|
||||
if ((track_type == Track::kAudio && output_audio) ||
|
||||
(track_type == Track::kVideo && output_video)) {
|
||||
const int frame_count = block->GetFrameCount();
|
||||
const bool is_key = block->IsKey();
|
||||
|
||||
for (int i = 0; i < frame_count; ++i) {
|
||||
const mkvparser::Block::Frame& frame = block->GetFrame(i);
|
||||
|
||||
if (frame.len > data_len) {
|
||||
delete [] data;
|
||||
delete[] data;
|
||||
data = new unsigned char[frame.len];
|
||||
if (!data)
|
||||
return EXIT_FAILURE;
|
||||
@@ -476,15 +519,16 @@ int main(int argc, char* argv[]) {
|
||||
if (frame.Read(&reader, data))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
uint64 track_num = vid_track;
|
||||
if (track_type == Track::kAudio)
|
||||
track_num = aud_track;
|
||||
|
||||
if (!muxer_segment.AddFrame(data,
|
||||
frame.len,
|
||||
track_num,
|
||||
time_ns,
|
||||
is_key)) {
|
||||
mkvmuxer::Frame muxer_frame;
|
||||
if (!muxer_frame.Init(data, frame.len))
|
||||
return EXIT_FAILURE;
|
||||
muxer_frame.set_track_number(track_type == Track::kAudio ? aud_track :
|
||||
vid_track);
|
||||
if (block->GetDiscardPadding())
|
||||
muxer_frame.set_discard_padding(block->GetDiscardPadding());
|
||||
muxer_frame.set_timestamp(time_ns);
|
||||
muxer_frame.set_is_key(block->IsKey());
|
||||
if (!muxer_segment.AddGenericFrame(&muxer_frame)) {
|
||||
printf("\n Could not add frame.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -533,8 +577,7 @@ int main(int argc, char* argv[]) {
|
||||
remove(temp_file);
|
||||
}
|
||||
|
||||
delete [] data;
|
||||
delete parser_segment;
|
||||
delete[] data;
|
||||
|
||||
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 <string>
|
||||
#include "vttreader.h"
|
||||
|
||||
SampleMuxerMetadata::SampleMuxerMetadata() : segment_(NULL) {
|
||||
}
|
||||
SampleMuxerMetadata::SampleMuxerMetadata() : segment_(NULL) {}
|
||||
|
||||
bool SampleMuxerMetadata::Init(mkvmuxer::Segment* segment) {
|
||||
if (segment == NULL || segment_ != NULL)
|
||||
@@ -82,8 +92,7 @@ bool SampleMuxerMetadata::LoadChapters(const char* file) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SampleMuxerMetadata::ParseChapters(
|
||||
const char* file,
|
||||
bool SampleMuxerMetadata::ParseChapters(const char* file,
|
||||
cue_list_t* cues_ptr) {
|
||||
cue_list_t& cues = *cues_ptr;
|
||||
cues.clear();
|
||||
@@ -188,9 +197,7 @@ bool SampleMuxerMetadata::AddChapter(const cue_t& cue) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SampleMuxerMetadata::AddTrack(
|
||||
Kind kind,
|
||||
mkvmuxer::uint64* track_num) {
|
||||
bool SampleMuxerMetadata::AddTrack(Kind kind, mkvmuxer::uint64* track_num) {
|
||||
*track_num = 0;
|
||||
|
||||
// Track number value 0 means "let muxer choose track number"
|
||||
@@ -238,9 +245,7 @@ bool SampleMuxerMetadata::AddTrack(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SampleMuxerMetadata::Parse(
|
||||
const char* file,
|
||||
Kind /* kind */,
|
||||
bool SampleMuxerMetadata::Parse(const char* file, Kind /* kind */,
|
||||
mkvmuxer::uint64 track_num) {
|
||||
libwebvtt::VttReader r;
|
||||
int e = r.Open(file);
|
||||
@@ -300,15 +305,13 @@ void SampleMuxerMetadata::MakeFrame(const cue_t& c, std::string* pf) {
|
||||
WriteCuePayload(c.payload, pf);
|
||||
}
|
||||
|
||||
void SampleMuxerMetadata::WriteCueIdentifier(
|
||||
const std::string& identifier,
|
||||
void SampleMuxerMetadata::WriteCueIdentifier(const std::string& identifier,
|
||||
std::string* pf) {
|
||||
pf->append(identifier);
|
||||
pf->push_back('\x0A'); // LF
|
||||
}
|
||||
|
||||
void SampleMuxerMetadata::WriteCueSettings(
|
||||
const cue_t::settings_t& settings,
|
||||
void SampleMuxerMetadata::WriteCueSettings(const cue_t::settings_t& settings,
|
||||
std::string* pf) {
|
||||
if (settings.empty()) {
|
||||
pf->push_back('\x0A'); // LF
|
||||
@@ -336,8 +339,7 @@ void SampleMuxerMetadata::WriteCueSettings(
|
||||
pf->push_back('\x0A'); // LF
|
||||
}
|
||||
|
||||
void SampleMuxerMetadata::WriteCuePayload(
|
||||
const cue_t::payload_t& payload,
|
||||
void SampleMuxerMetadata::WriteCuePayload(const cue_t::payload_t& payload,
|
||||
std::string* pf) {
|
||||
typedef cue_t::payload_t::const_iterator iter_t;
|
||||
|
||||
@@ -351,8 +353,7 @@ void SampleMuxerMetadata::WriteCuePayload(
|
||||
}
|
||||
}
|
||||
|
||||
bool SampleMuxerMetadata::SortableCue::Write(
|
||||
mkvmuxer::Segment* segment) const {
|
||||
bool SampleMuxerMetadata::SortableCue::Write(mkvmuxer::Segment* segment) const {
|
||||
// Cue start time expressed in milliseconds
|
||||
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 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 {
|
||||
public:
|
||||
enum Kind {
|
||||
kSubtitles,
|
||||
kCaptions,
|
||||
kDescriptions,
|
||||
kMetadata,
|
||||
kChapters
|
||||
};
|
||||
enum Kind { kSubtitles, kCaptions, kDescriptions, kMetadata, kChapters };
|
||||
|
||||
SampleMuxerMetadata();
|
||||
|
||||
@@ -86,8 +80,7 @@ class SampleMuxerMetadata {
|
||||
|
||||
// Parse the WebVTT chapters in |file| to populate |cues|. Returns
|
||||
// false on error.
|
||||
static bool ParseChapters(const char* file,
|
||||
cue_list_t* cues);
|
||||
static bool ParseChapters(const char* file, cue_list_t* cues);
|
||||
|
||||
// Adds WebVTT cue |chapter| to the chapters element of the output
|
||||
// file's segment element. Returns false on error.
|
||||
|
||||
128
vttdemux.cc
128
vttdemux.cc
@@ -15,6 +15,11 @@
|
||||
#include "./mkvreader.hpp"
|
||||
#include "./webvttparser.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Disable MSVC warnings that suggest making code non-portable.
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
using std::string;
|
||||
|
||||
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).
|
||||
// We use |type| to synthesize a filename for the out-of-band WebVTT |file|.
|
||||
struct MetadataInfo {
|
||||
enum Type {
|
||||
kSubtitles,
|
||||
kCaptions,
|
||||
kDescriptions,
|
||||
kMetadata,
|
||||
kChapters } type;
|
||||
enum Type { kSubtitles, kCaptions, kDescriptions, kMetadata, kChapters } type;
|
||||
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.
|
||||
// Returns false if there was an error parsing the file.
|
||||
bool ParseSegment(
|
||||
mkvparser::IMkvReader* reader,
|
||||
mkvpos_t pos,
|
||||
bool ParseSegment(mkvparser::IMkvReader* reader, mkvpos_t pos,
|
||||
segment_ptr_t* segment);
|
||||
|
||||
// If |segment| has a Chapters element (in which case, there will be a
|
||||
// corresponding entry in |metadata_map|), convert the MKV chapters to
|
||||
// WebVTT chapter cues and write them to the output file. Returns
|
||||
// false on error.
|
||||
bool WriteChaptersFile(
|
||||
const metadata_map_t& metadata_map,
|
||||
bool WriteChaptersFile(const metadata_map_t& metadata_map,
|
||||
const mkvparser::Segment* segment);
|
||||
|
||||
// Convert an MKV Chapters Atom to a WebVTT cue and write it to the
|
||||
// output |file|. Returns false on error.
|
||||
bool WriteChaptersCue(
|
||||
FILE* file,
|
||||
const mkvparser::Chapters* chapters,
|
||||
bool WriteChaptersCue(FILE* file, const mkvparser::Chapters* chapters,
|
||||
const mkvparser::Chapters::Atom* atom,
|
||||
const mkvparser::Chapters::Display* display);
|
||||
|
||||
// Write the Cue Identifier line of the WebVTT cue, if it's present.
|
||||
// Returns false on error.
|
||||
bool WriteChaptersCueIdentifier(
|
||||
FILE* file,
|
||||
bool WriteChaptersCueIdentifier(FILE* file,
|
||||
const mkvparser::Chapters::Atom* atom);
|
||||
|
||||
// Use the timecodes from the chapters |atom| to write just the
|
||||
// timings line of the WebVTT cue. Returns false on error.
|
||||
bool WriteChaptersCueTimings(
|
||||
FILE* file,
|
||||
const mkvparser::Chapters* chapters,
|
||||
bool WriteChaptersCueTimings(FILE* file, const mkvparser::Chapters* chapters,
|
||||
const mkvparser::Chapters::Atom* atom);
|
||||
|
||||
// Parse the String sub-element of the |display| and write the payload
|
||||
// of the WebVTT cue. Returns false on error.
|
||||
bool WriteChaptersCuePayload(
|
||||
FILE* file,
|
||||
bool WriteChaptersCuePayload(FILE* file,
|
||||
const mkvparser::Chapters::Display* display);
|
||||
|
||||
// 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
|
||||
// its associated output file for each block of metadata. Returns
|
||||
// false if processing a block failed, or there was a parse error.
|
||||
bool ProcessCluster(
|
||||
const metadata_map_t& metadata_map,
|
||||
bool ProcessCluster(const metadata_map_t& metadata_map,
|
||||
const mkvparser::Cluster* cluster);
|
||||
|
||||
// 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
|
||||
// file. Returns false if writing the WebVTT cue failed.
|
||||
bool ProcessBlockEntry(
|
||||
const metadata_map_t& metadata_map,
|
||||
bool ProcessBlockEntry(const metadata_map_t& metadata_map,
|
||||
const mkvparser::BlockEntry* block_entry);
|
||||
|
||||
// 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
|
||||
// associated output file. Returns false if there was an error
|
||||
// writing to the file.
|
||||
bool WriteCueTimings(
|
||||
FILE* f,
|
||||
FrameParser* parser);
|
||||
bool WriteCueTimings(FILE* f, FrameParser* parser);
|
||||
|
||||
// Write the timestamp (representating either the start time or stop
|
||||
// time of the cue) to the output file. Returns false if there was an
|
||||
// error writing to the file.
|
||||
bool WriteCueTime(
|
||||
FILE* f,
|
||||
mkvtime_t time_ns);
|
||||
bool WriteCueTime(FILE* f, mkvtime_t time_ns);
|
||||
|
||||
// Consume the remaining lines of text from the character stream
|
||||
// (these lines are the actual payload of the WebVTT cue), and write
|
||||
// them to the associated output file. Returns false if there was an
|
||||
// error writing to the file.
|
||||
bool WriteCuePayload(
|
||||
FILE* f,
|
||||
FrameParser* parser);
|
||||
bool WriteCuePayload(FILE* f, FrameParser* parser);
|
||||
} // namespace vttdemux
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
@@ -299,8 +282,7 @@ FrameParser::FrameParser(const mkvparser::BlockGroup* block_group)
|
||||
pos_end_ = f.pos + f.len;
|
||||
}
|
||||
|
||||
FrameParser::~FrameParser() {
|
||||
}
|
||||
FrameParser::~FrameParser() {}
|
||||
|
||||
int FrameParser::GetChar(char* c) {
|
||||
if (pos_ >= pos_end_) // end-of-stream
|
||||
@@ -320,7 +302,7 @@ int FrameParser::GetChar(char* c) {
|
||||
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.
|
||||
// The next time GetChar is called the same character will be
|
||||
// re-read from the input file.
|
||||
@@ -335,8 +317,7 @@ ChapterAtomParser::ChapterAtomParser(
|
||||
str_end_ = str_ + len;
|
||||
}
|
||||
|
||||
ChapterAtomParser::~ChapterAtomParser() {
|
||||
}
|
||||
ChapterAtomParser::~ChapterAtomParser() {}
|
||||
|
||||
int ChapterAtomParser::GetChar(char* c) {
|
||||
if (str_ >= str_end_) // end-of-stream
|
||||
@@ -346,7 +327,7 @@ int ChapterAtomParser::GetChar(char* c) {
|
||||
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.
|
||||
// The next time GetChar is called the same character will be
|
||||
// re-read from the input file.
|
||||
@@ -355,9 +336,7 @@ void ChapterAtomParser::UngetChar(char /* c */ ) {
|
||||
|
||||
} // namespace vttdemux
|
||||
|
||||
bool vttdemux::ParseHeader(
|
||||
mkvparser::IMkvReader* reader,
|
||||
mkvpos_t* pos) {
|
||||
bool vttdemux::ParseHeader(mkvparser::IMkvReader* reader, mkvpos_t* pos) {
|
||||
mkvparser::EBMLHeader h;
|
||||
const mkvpos_t status = h.Parse(reader, *pos);
|
||||
|
||||
@@ -366,7 +345,7 @@ bool vttdemux::ParseHeader(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strcmp(h.m_docType, "webm") != 0) {
|
||||
if (h.m_docType == NULL || strcmp(h.m_docType, "webm") != 0) {
|
||||
printf("bad doctype\n");
|
||||
return false;
|
||||
}
|
||||
@@ -374,9 +353,7 @@ bool vttdemux::ParseHeader(
|
||||
return true; // success
|
||||
}
|
||||
|
||||
bool vttdemux::ParseSegment(
|
||||
mkvparser::IMkvReader* reader,
|
||||
mkvpos_t pos,
|
||||
bool vttdemux::ParseSegment(mkvparser::IMkvReader* reader, mkvpos_t pos,
|
||||
segment_ptr_t* segment_ptr) {
|
||||
// We first create the segment object.
|
||||
|
||||
@@ -402,8 +379,7 @@ bool vttdemux::ParseSegment(
|
||||
return true;
|
||||
}
|
||||
|
||||
void vttdemux::BuildMap(
|
||||
const mkvparser::Segment* segment,
|
||||
void vttdemux::BuildMap(const mkvparser::Segment* segment,
|
||||
metadata_map_t* map_ptr) {
|
||||
metadata_map_t& m = *map_ptr;
|
||||
m.clear();
|
||||
@@ -551,7 +527,11 @@ bool vttdemux::OpenFiles(metadata_map_t* metadata_map, const char* filename) {
|
||||
if (exists[type] > 1) {
|
||||
enum { kLen = 33 };
|
||||
char str[kLen]; // max 126 tracks, so only 4 chars really needed
|
||||
#ifndef _MSC_VER
|
||||
snprintf(str, kLen, "%ld", v.first); // track number
|
||||
#else
|
||||
_snprintf_s(str, sizeof(str), kLen, "%ld", v.first); // track number
|
||||
#endif
|
||||
name += str;
|
||||
}
|
||||
|
||||
@@ -563,8 +543,9 @@ bool vttdemux::OpenFiles(metadata_map_t* metadata_map, const char* filename) {
|
||||
// open the WebVTT output file.
|
||||
|
||||
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());
|
||||
return false;
|
||||
}
|
||||
@@ -640,8 +621,7 @@ bool vttdemux::InitializeFiles(const metadata_map_t& m) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vttdemux::WriteChaptersFile(
|
||||
const metadata_map_t& m,
|
||||
bool vttdemux::WriteChaptersFile(const metadata_map_t& m,
|
||||
const mkvparser::Segment* s) {
|
||||
const metadata_map_t::const_iterator info_iter = m.find(kChaptersKey);
|
||||
if (info_iter == m.end()) // no chapters, so nothing to do
|
||||
@@ -713,9 +693,7 @@ bool vttdemux::WriteChaptersFile(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vttdemux::WriteChaptersCue(
|
||||
FILE* f,
|
||||
const mkvparser::Chapters* chapters,
|
||||
bool vttdemux::WriteChaptersCue(FILE* f, const mkvparser::Chapters* chapters,
|
||||
const mkvparser::Chapters::Atom* atom,
|
||||
const mkvparser::Chapters::Display* display) {
|
||||
// We start a new cue by writing a cue separator (an empty line)
|
||||
@@ -741,9 +719,7 @@ bool vttdemux::WriteChaptersCue(
|
||||
}
|
||||
|
||||
bool vttdemux::WriteChaptersCueIdentifier(
|
||||
FILE* f,
|
||||
const mkvparser::Chapters::Atom* atom) {
|
||||
|
||||
FILE* f, const mkvparser::Chapters::Atom* atom) {
|
||||
const char* const identifier = atom->GetStringUID();
|
||||
|
||||
if (identifier == NULL)
|
||||
@@ -755,8 +731,7 @@ bool vttdemux::WriteChaptersCueIdentifier(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vttdemux::WriteChaptersCueTimings(
|
||||
FILE* f,
|
||||
bool vttdemux::WriteChaptersCueTimings(FILE* f,
|
||||
const mkvparser::Chapters* chapters,
|
||||
const mkvparser::Chapters::Atom* atom) {
|
||||
const mkvtime_t start_ns = atom->GetStartTime(chapters);
|
||||
@@ -785,8 +760,7 @@ bool vttdemux::WriteChaptersCueTimings(
|
||||
}
|
||||
|
||||
bool vttdemux::WriteChaptersCuePayload(
|
||||
FILE* f,
|
||||
const mkvparser::Chapters::Display* display) {
|
||||
FILE* f, const mkvparser::Chapters::Display* display) {
|
||||
// Bind a Chapter parser object to the display, which allows us to
|
||||
// extract each line of text from the title-part of the display.
|
||||
ChapterAtomParser parser(display);
|
||||
@@ -813,8 +787,7 @@ bool vttdemux::WriteChaptersCuePayload(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vttdemux::ProcessCluster(
|
||||
const metadata_map_t& m,
|
||||
bool vttdemux::ProcessCluster(const metadata_map_t& m,
|
||||
const mkvparser::Cluster* c) {
|
||||
// Visit the blocks in this cluster, writing a WebVTT cue for each
|
||||
// metadata block.
|
||||
@@ -822,7 +795,7 @@ bool vttdemux::ProcessCluster(
|
||||
const mkvparser::BlockEntry* block_entry;
|
||||
|
||||
long result = c->GetFirst(block_entry); // NOLINT
|
||||
if (result < 0) { // error
|
||||
if (result < 0) {
|
||||
printf("bad cluster (unable to get first block)\n");
|
||||
return false;
|
||||
}
|
||||
@@ -841,8 +814,7 @@ bool vttdemux::ProcessCluster(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vttdemux::ProcessBlockEntry(
|
||||
const metadata_map_t& m,
|
||||
bool vttdemux::ProcessBlockEntry(const metadata_map_t& m,
|
||||
const mkvparser::BlockEntry* block_entry) {
|
||||
// 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.
|
||||
@@ -851,7 +823,7 @@ bool vttdemux::ProcessBlockEntry(
|
||||
const long long tn = block->GetTrackNumber(); // NOLINT
|
||||
|
||||
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
|
||||
return true; // nothing else to do
|
||||
@@ -868,9 +840,7 @@ bool vttdemux::ProcessBlockEntry(
|
||||
return WriteCue(f, block_group);
|
||||
}
|
||||
|
||||
bool vttdemux::WriteCue(
|
||||
FILE* f,
|
||||
const mkvparser::BlockGroup* block_group) {
|
||||
bool vttdemux::WriteCue(FILE* f, const mkvparser::BlockGroup* block_group) {
|
||||
// Bind a FrameParser object to the block, which allows us to
|
||||
// extract each line of text from the payload of the block.
|
||||
FrameParser parser(block_group);
|
||||
@@ -897,9 +867,7 @@ bool vttdemux::WriteCue(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vttdemux::WriteCueIdentifier(
|
||||
FILE* f,
|
||||
FrameParser* parser) {
|
||||
bool vttdemux::WriteCueIdentifier(FILE* f, FrameParser* parser) {
|
||||
string line;
|
||||
int e = parser->GetLine(&line);
|
||||
|
||||
@@ -922,9 +890,7 @@ bool vttdemux::WriteCueIdentifier(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vttdemux::WriteCueTimings(
|
||||
FILE* f,
|
||||
FrameParser* parser) {
|
||||
bool vttdemux::WriteCueTimings(FILE* f, FrameParser* parser) {
|
||||
const mkvparser::BlockGroup* const block_group = parser->block_group_;
|
||||
const mkvparser::Cluster* const cluster = block_group->GetCluster();
|
||||
const mkvparser::Block* const block = block_group->GetBlock();
|
||||
@@ -986,9 +952,7 @@ bool vttdemux::WriteCueTimings(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vttdemux::WriteCueTime(
|
||||
FILE* f,
|
||||
mkvtime_t time_ns) {
|
||||
bool vttdemux::WriteCueTime(FILE* f, mkvtime_t time_ns) {
|
||||
mkvtime_t ms = time_ns / 1000000; // WebVTT time has millisecond resolution
|
||||
|
||||
mkvtime_t sec = ms / 1000;
|
||||
@@ -1011,9 +975,7 @@ bool vttdemux::WriteCueTime(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vttdemux::WriteCuePayload(
|
||||
FILE* f,
|
||||
FrameParser* parser) {
|
||||
bool vttdemux::WriteCuePayload(FILE* f, FrameParser* parser) {
|
||||
int count = 0; // count of lines of payload text written to output file
|
||||
for (string line;;) {
|
||||
const int e = parser->GetLine(&line);
|
||||
|
||||
12
vttreader.cc
12
vttreader.cc
@@ -8,14 +8,16 @@
|
||||
|
||||
#include "./vttreader.h" // NOLINT
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Disable MSVC warnings that suggest making code non-portable.
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
namespace libwebvtt {
|
||||
|
||||
VttReader::VttReader() : file_(NULL) {
|
||||
}
|
||||
VttReader::VttReader() : file_(NULL) {}
|
||||
|
||||
VttReader::~VttReader() {
|
||||
Close();
|
||||
}
|
||||
VttReader::~VttReader() { Close(); }
|
||||
|
||||
int VttReader::Open(const char* filename) {
|
||||
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,
|
||||
kMkvSignatureElementList = 0x7E7B,
|
||||
kMkvSignedElement = 0x6532,
|
||||
//segment
|
||||
// segment
|
||||
kMkvSegment = 0x18538067,
|
||||
//Meta Seek Information
|
||||
// Meta Seek Information
|
||||
kMkvSeekHead = 0x114D9B74,
|
||||
kMkvSeek = 0x4DBB,
|
||||
kMkvSeekID = 0x53AB,
|
||||
kMkvSeekPosition = 0x53AC,
|
||||
//Segment Information
|
||||
// Segment Information
|
||||
kMkvInfo = 0x1549A966,
|
||||
kMkvTimecodeScale = 0x2AD7B1,
|
||||
kMkvDuration = 0x4489,
|
||||
kMkvDateUTC = 0x4461,
|
||||
kMkvTitle = 0x7BA9,
|
||||
kMkvMuxingApp = 0x4D80,
|
||||
kMkvWritingApp = 0x5741,
|
||||
//Cluster
|
||||
// Cluster
|
||||
kMkvCluster = 0x1F43B675,
|
||||
kMkvTimecode = 0xE7,
|
||||
kMkvPrevSize = 0xAB,
|
||||
@@ -57,7 +58,8 @@ enum MkvId {
|
||||
kMkvBlockMore = 0xA6,
|
||||
kMkvBlockAddID = 0xEE,
|
||||
kMkvBlockAdditional = 0xA5,
|
||||
//Track
|
||||
kMkvDiscardPadding = 0x75A2,
|
||||
// Track
|
||||
kMkvTracks = 0x1654AE6B,
|
||||
kMkvTrackEntry = 0xAE,
|
||||
kMkvTrackNumber = 0xD7,
|
||||
@@ -68,13 +70,15 @@ enum MkvId {
|
||||
kMkvFlagForced = 0x55AA,
|
||||
kMkvFlagLacing = 0x9C,
|
||||
kMkvDefaultDuration = 0x23E383,
|
||||
kMkvMaxBlockAdditionID = 0x55EE,
|
||||
kMkvName = 0x536E,
|
||||
kMkvLanguage = 0x22B59C,
|
||||
kMkvCodecID = 0x86,
|
||||
kMkvCodecPrivate = 0x63A2,
|
||||
kMkvCodecName = 0x258688,
|
||||
kMkvMaxBlockAdditionID = 0x55EE,
|
||||
//video
|
||||
kMkvCodecDelay = 0x56AA,
|
||||
kMkvSeekPreRoll = 0x56BB,
|
||||
// video
|
||||
kMkvVideo = 0xE0,
|
||||
kMkvFlagInterlaced = 0x9A,
|
||||
kMkvStereoMode = 0x53B8,
|
||||
@@ -90,28 +94,35 @@ enum MkvId {
|
||||
kMkvDisplayUnit = 0x54B2,
|
||||
kMkvAspectRatioType = 0x54B3,
|
||||
kMkvFrameRate = 0x2383E3,
|
||||
//end video
|
||||
//audio
|
||||
// end video
|
||||
// audio
|
||||
kMkvAudio = 0xE1,
|
||||
kMkvSamplingFrequency = 0xB5,
|
||||
kMkvOutputSamplingFrequency = 0x78B5,
|
||||
kMkvChannels = 0x9F,
|
||||
kMkvBitDepth = 0x6264,
|
||||
//end audio
|
||||
//ContentEncodings
|
||||
// end audio
|
||||
// ContentEncodings
|
||||
kMkvContentEncodings = 0x6D80,
|
||||
kMkvContentEncoding = 0x6240,
|
||||
kMkvContentEncodingOrder = 0x5031,
|
||||
kMkvContentEncodingScope = 0x5032,
|
||||
kMkvContentEncodingType = 0x5033,
|
||||
kMkvContentCompression = 0x5034,
|
||||
kMkvContentCompAlgo = 0x4254,
|
||||
kMkvContentCompSettings = 0x4255,
|
||||
kMkvContentEncryption = 0x5035,
|
||||
kMkvContentEncAlgo = 0x47E1,
|
||||
kMkvContentEncKeyID = 0x47E2,
|
||||
kMkvContentSignature = 0x47E3,
|
||||
kMkvContentSigKeyID = 0x47E4,
|
||||
kMkvContentSigAlgo = 0x47E5,
|
||||
kMkvContentSigHashAlgo = 0x47E6,
|
||||
kMkvContentEncAESSettings = 0x47E7,
|
||||
kMkvAESSettingsCipherMode = 0x47E8,
|
||||
kMkvAESSettingsCipherInitData = 0x47E9,
|
||||
//end ContentEncodings
|
||||
//Cueing Data
|
||||
// end ContentEncodings
|
||||
// Cueing Data
|
||||
kMkvCues = 0x1C53BB6B,
|
||||
kMkvCuePoint = 0xBB,
|
||||
kMkvCueTime = 0xB3,
|
||||
@@ -119,7 +130,7 @@ enum MkvId {
|
||||
kMkvCueTrack = 0xF7,
|
||||
kMkvCueClusterPosition = 0xF1,
|
||||
kMkvCueBlockNumber = 0x5378,
|
||||
//Chapters
|
||||
// Chapters
|
||||
kMkvChapters = 0x1043A770,
|
||||
kMkvEditionEntry = 0x45B9,
|
||||
kMkvChapterAtom = 0xB6,
|
||||
@@ -130,7 +141,13 @@ enum MkvId {
|
||||
kMkvChapterDisplay = 0x80,
|
||||
kMkvChapString = 0x85,
|
||||
kMkvChapLanguage = 0x437C,
|
||||
kMkvChapCountry = 0x437E
|
||||
kMkvChapCountry = 0x437E,
|
||||
// Tags
|
||||
kMkvTags = 0x1254C367,
|
||||
kMkvTag = 0x7373,
|
||||
kMkvSimpleTag = 0x67C8,
|
||||
kMkvTagName = 0x45A3,
|
||||
kMkvTagString = 0x4487
|
||||
};
|
||||
|
||||
} // end namespace mkvmuxer
|
||||
|
||||
@@ -11,19 +11,19 @@
|
||||
|
||||
namespace libwebvtt {
|
||||
|
||||
// NOLINT'ing this enum because clang-format puts it in a single line which
|
||||
// makes it look really unreadable.
|
||||
enum {
|
||||
kNUL = '\x00',
|
||||
kSPACE = ' ',
|
||||
kTAB = '\x09',
|
||||
kLF = '\x0A',
|
||||
kCR = '\x0D'
|
||||
};
|
||||
}; // NOLINT
|
||||
|
||||
Reader::~Reader() {
|
||||
}
|
||||
Reader::~Reader() {}
|
||||
|
||||
LineReader::~LineReader() {
|
||||
}
|
||||
LineReader::~LineReader() {}
|
||||
|
||||
int LineReader::GetLine(std::string* line_ptr) {
|
||||
if (line_ptr == NULL)
|
||||
@@ -101,11 +101,9 @@ int LineReader::GetLine(std::string* line_ptr) {
|
||||
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 e = ParseBOM();
|
||||
@@ -226,10 +224,7 @@ int Parser::Parse(Cue* cue) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
e = ParseTimingsLine(&line,
|
||||
arrow_pos,
|
||||
&cue->start_time,
|
||||
&cue->stop_time,
|
||||
e = ParseTimingsLine(&line, arrow_pos, &cue->start_time, &cue->stop_time,
|
||||
&cue->settings);
|
||||
|
||||
if (e) // error
|
||||
@@ -269,9 +264,7 @@ int Parser::GetChar(char* c) {
|
||||
return reader_->GetChar(c);
|
||||
}
|
||||
|
||||
void Parser::UngetChar(char c) {
|
||||
unget_ = static_cast<unsigned char>(c);
|
||||
}
|
||||
void Parser::UngetChar(char c) { unget_ = static_cast<unsigned char>(c); }
|
||||
|
||||
int Parser::ParseBOM() {
|
||||
// Explanation of UTF-8 BOM:
|
||||
@@ -303,12 +296,9 @@ int Parser::ParseBOM() {
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
int Parser::ParseTimingsLine(
|
||||
std::string* line_ptr,
|
||||
std::string::size_type arrow_pos,
|
||||
Time* start_time,
|
||||
Time* stop_time,
|
||||
Cue::settings_t* settings) {
|
||||
int Parser::ParseTimingsLine(std::string* line_ptr,
|
||||
std::string::size_type arrow_pos, Time* start_time,
|
||||
Time* stop_time, Cue::settings_t* settings) {
|
||||
if (line_ptr == NULL)
|
||||
return -1;
|
||||
|
||||
@@ -353,9 +343,7 @@ int Parser::ParseTimingsLine(
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
int Parser::ParseTime(
|
||||
const std::string& line,
|
||||
std::string::size_type* idx_ptr,
|
||||
int Parser::ParseTime(const std::string& line, std::string::size_type* idx_ptr,
|
||||
Time* time) {
|
||||
if (idx_ptr == NULL)
|
||||
return -1;
|
||||
@@ -511,9 +499,7 @@ int Parser::ParseTime(
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
int Parser::ParseSettings(
|
||||
const std::string& line,
|
||||
std::string::size_type idx,
|
||||
int Parser::ParseSettings(const std::string& line, std::string::size_type idx,
|
||||
Cue::settings_t* settings) {
|
||||
settings->clear();
|
||||
|
||||
@@ -585,8 +571,7 @@ int Parser::ParseSettings(
|
||||
}
|
||||
}
|
||||
|
||||
int Parser::ParseNumber(
|
||||
const std::string& line,
|
||||
int Parser::ParseNumber(const std::string& line,
|
||||
std::string::size_type* idx_ptr) {
|
||||
if (idx_ptr == NULL)
|
||||
return -1;
|
||||
@@ -656,17 +641,11 @@ bool Time::operator<(const Time& rhs) const {
|
||||
return (milliseconds < rhs.milliseconds);
|
||||
}
|
||||
|
||||
bool Time::operator>(const Time& rhs) const {
|
||||
return rhs.operator<(*this);
|
||||
}
|
||||
bool Time::operator>(const Time& rhs) const { return rhs.operator<(*this); }
|
||||
|
||||
bool Time::operator<=(const Time& rhs) const {
|
||||
return !this->operator>(rhs);
|
||||
}
|
||||
bool Time::operator<=(const Time& rhs) const { return !this->operator>(rhs); }
|
||||
|
||||
bool Time::operator>=(const Time& rhs) const {
|
||||
return !this->operator<(rhs);
|
||||
}
|
||||
bool Time::operator>=(const Time& rhs) const { return !this->operator<(rhs); }
|
||||
|
||||
presentation_t Time::presentation() const {
|
||||
const presentation_t h = 1000LL * 3600LL * presentation_t(hours);
|
||||
@@ -686,8 +665,8 @@ Time& Time::presentation(presentation_t d) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
seconds = d / 1000;
|
||||
milliseconds = d - 1000 * seconds;
|
||||
seconds = static_cast<int>(d / 1000);
|
||||
milliseconds = static_cast<int>(d - 1000 * seconds);
|
||||
|
||||
minutes = seconds / 60;
|
||||
seconds -= 60 * minutes;
|
||||
@@ -711,9 +690,7 @@ Time Time::operator+(presentation_t d) const {
|
||||
return t;
|
||||
}
|
||||
|
||||
Time& Time::operator-=(presentation_t d) {
|
||||
return this->operator+=(-d);
|
||||
}
|
||||
Time& Time::operator-=(presentation_t d) { return this->operator+=(-d); }
|
||||
|
||||
presentation_t Time::operator-(const Time& t) const {
|
||||
const presentation_t rhs = t.presentation();
|
||||
|
||||
@@ -120,8 +120,7 @@ class Parser : private LineReader {
|
||||
//
|
||||
static int ParseTimingsLine(std::string* line,
|
||||
std::string::size_type arrow_pos,
|
||||
Time* start_time,
|
||||
Time* stop_time,
|
||||
Time* start_time, Time* stop_time,
|
||||
Cue::settings_t* settings);
|
||||
|
||||
// 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
|
||||
// characters consumed. Returns negative if error, 0 on success.
|
||||
//
|
||||
static int ParseTime(const std::string& line,
|
||||
std::string::size_type* off,
|
||||
static int ParseTime(const std::string& line, std::string::size_type* off,
|
||||
Time* time);
|
||||
|
||||
// Parse the cue settings from the timings line, starting at the
|
||||
// given offset. Returns negative if error, 0 on success.
|
||||
//
|
||||
static int ParseSettings(const std::string& line,
|
||||
std::string::size_type off,
|
||||
static int ParseSettings(const std::string& line, std::string::size_type off,
|
||||
Cue::settings_t* settings);
|
||||
|
||||
// Parse a non-negative integer from the characters in |line| beginning
|
||||
// at offset |off|. The function increments |off| by the number
|
||||
// of characters consumed. Returns the value, or negative if error.
|
||||
//
|
||||
static int ParseNumber(const std::string& line,
|
||||
std::string::size_type* off);
|
||||
static int ParseNumber(const std::string& line, std::string::size_type* off);
|
||||
|
||||
Reader* const reader_;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user