Compare commits
86 Commits
libwebm-1.
...
sandbox/ma
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
379839bedc | ||
|
|
484c71d875 | ||
|
|
a45b72d731 | ||
|
|
6fa7c7611c | ||
|
|
71d296e44c | ||
|
|
72052ed8b1 | ||
|
|
a88d62b682 | ||
|
|
28d54555a7 | ||
|
|
359b3654ad | ||
|
|
000944c4e4 | ||
|
|
8da8206fa0 | ||
|
|
7a9a72f984 | ||
|
|
d2327e2b65 | ||
|
|
1e37a264f1 | ||
|
|
01d5924817 | ||
|
|
a20f4255c7 | ||
|
|
69df730519 | ||
|
|
f7aa8ab33d | ||
|
|
73ad7bd83c | ||
|
|
4c682199b0 | ||
|
|
9303667611 | ||
|
|
4affedd0a7 | ||
|
|
23808a7ba4 | ||
|
|
32227e70c1 | ||
|
|
2d3461b4b3 | ||
|
|
a09f15f00e | ||
|
|
6d99850e7c | ||
|
|
1ae4335c1c | ||
|
|
52f0a92192 | ||
|
|
6ebe4a39df | ||
|
|
a3dd40877d | ||
|
|
1623fb983b | ||
|
|
18ac83d501 | ||
|
|
5942099a85 | ||
|
|
9ecedef185 | ||
|
|
6f68021678 | ||
|
|
3395c36a8e | ||
|
|
ffe5a8e548 | ||
|
|
a9c65fbbc0 | ||
|
|
31a9d5470e | ||
|
|
2b84a12da8 | ||
|
|
bd833a82e4 | ||
|
|
7b07758854 | ||
|
|
00ed87aad6 | ||
|
|
06f08663be | ||
|
|
35ded77a23 | ||
|
|
1f33611caa | ||
|
|
70f9644a8d | ||
|
|
f2bd78ef6b | ||
|
|
2083c72300 | ||
|
|
f5ec272e54 | ||
|
|
b324e52139 | ||
|
|
4137f9c999 | ||
|
|
ba4096f120 | ||
|
|
365a39b5ec | ||
|
|
601f7903a3 | ||
|
|
16b2cdaf57 | ||
|
|
ca1e6b7323 | ||
|
|
c226b79e61 | ||
|
|
dc8bdb3389 | ||
|
|
31b2d8689c | ||
|
|
227d62aadf | ||
|
|
85beb00fe3 | ||
|
|
eb4bd69098 | ||
|
|
cf36dc2848 | ||
|
|
b0465e167e | ||
|
|
a1aa16692a | ||
|
|
f971a94349 | ||
|
|
5ac9764a95 | ||
|
|
d82f86a40a | ||
|
|
a1736157be | ||
|
|
2c835bcc28 | ||
|
|
d931a6ecc6 | ||
|
|
7a8b013f16 | ||
|
|
a977a2b536 | ||
|
|
5e72a2dfc2 | ||
|
|
056b0d96a8 | ||
|
|
dbc58d0510 | ||
|
|
a131a01446 | ||
|
|
b8cb358204 | ||
|
|
5b06b22b31 | ||
|
|
598de03ef3 | ||
|
|
94f2d589fc | ||
|
|
786357a59d | ||
|
|
6e723319e8 | ||
|
|
9911f61616 |
33
Makefile
33
Makefile
@@ -1,20 +1,25 @@
|
||||
LIB = libmkvparser.a
|
||||
OBJECTS = mkvparser.o mkvreader.o sample.o
|
||||
EXE = sample
|
||||
CFLAGS = -W -Wall -g
|
||||
CXX := g++
|
||||
CXXFLAGS := -W -Wall -g
|
||||
LIBWEBM := libwebm.a
|
||||
WEBMOBJS := mkvparser.o mkvreader.o mkvmuxer.o mkvmuxerutil.o mkvwriter.o
|
||||
OBJECTS1 := $(PARSEOBJ) sample.o
|
||||
OBJECTS2 := $(PARSEOBJ) $(MUXEROBJ) sample_muxer/sample_muxer.o
|
||||
INCLUDES := -I.
|
||||
EXES := samplemuxer sample
|
||||
|
||||
$(EXE): $(OBJECTS)
|
||||
$(AR) rcs $(LIB) mkvparser.o
|
||||
$(CXX) $(OBJECTS) -L./ -lmkvparser -o $(EXE)
|
||||
all: $(EXES)
|
||||
|
||||
mkvparser.o: mkvparser.cpp
|
||||
$(CXX) -c $(CFLAGS) mkvparser.cpp -o mkvparser.o
|
||||
sample: sample.o $(LIBWEBM)
|
||||
$(CXX) $^ -o $@
|
||||
|
||||
mkvreader.o: mkvreader.cpp
|
||||
$(CXX) -c $(CFLAGS) mkvreader.cpp -o mkvreader.o
|
||||
samplemuxer: sample_muxer/sample_muxer.o $(LIBWEBM)
|
||||
$(CXX) $^ -o $@
|
||||
|
||||
sample.o: sample.cpp
|
||||
$(CXX) -c $(CFLAGS) sample.cpp -o sample.o
|
||||
libwebm.a: $(WEBMOBJS)
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $(INCLUDES) $< -o $@
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJECTS) $(LIB) $(EXE) Makefile.bak
|
||||
$(RM) -f $(OBJECTS1) $(OBJECTS2) $(WEBMOBJS) $(LIBWEBM) $(EXES) Makefile.bak
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||
# Visual Studio 2005
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mkvparser_2005", "mkvparser_2005.vcproj", "{F9128EC6-C008-41AD-B38F-0E70D549D9F4}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwebm", "libwebm_2005.vcproj", "{F9128EC6-C008-41AD-B38F-0E70D549D9F4}"
|
||||
ProjectSection(WebsiteProperties) = preProject
|
||||
Debug.AspNetCompiler.Debug = "True"
|
||||
Release.AspNetCompiler.Debug = "False"
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_2005", "sample_2005.vcproj", "{0CB5681F-6065-490C-98C8-05531732ED7E}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample", "sample_2005.vcproj", "{0CB5681F-6065-490C-98C8-05531732ED7E}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{F9128EC6-C008-41AD-B38F-0E70D549D9F4} = {F9128EC6-C008-41AD-B38F-0E70D549D9F4}
|
||||
EndProjectSection
|
||||
ProjectSection(WebsiteProperties) = preProject
|
||||
Debug.AspNetCompiler.Debug = "True"
|
||||
Release.AspNetCompiler.Debug = "False"
|
||||
@@ -2,7 +2,7 @@
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="mkvparser"
|
||||
Name="libwebm"
|
||||
ProjectGUID="{F9128EC6-C008-41AD-B38F-0E70D549D9F4}"
|
||||
RootNamespace="mkvparser"
|
||||
Keyword="Win32Proj"
|
||||
@@ -42,13 +42,13 @@
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
|
||||
MinimalRebuild="true"
|
||||
MinimalRebuild="false"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
@@ -104,11 +104,11 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="2"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
DebugInformationFormat="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
@@ -147,6 +147,10 @@
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\mkvmuxerutil.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mkvparser.cpp"
|
||||
>
|
||||
@@ -155,12 +159,28 @@
|
||||
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"
|
||||
>
|
||||
@@ -169,6 +189,14 @@
|
||||
RelativePath=".\mkvreader.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mkvwriter.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\webmids.hpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
38
libwebm_2008.sln
Normal file
38
libwebm_2008.sln
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
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\sample_muxer.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
|
||||
@@ -2,11 +2,11 @@
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="mkvparser"
|
||||
ProjectGUID="{F9128EC6-C008-41AD-B38F-0E70D549D9F4}"
|
||||
RootNamespace="mkvparser"
|
||||
Name="libwebm"
|
||||
ProjectGUID="{7B1F12CA-0724-430B-B61A-1D357C912CBA}"
|
||||
RootNamespace="libwebm"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="131072"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
@@ -21,7 +21,6 @@
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
UseOfMFC="0"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
@@ -48,7 +47,6 @@
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="1"
|
||||
/>
|
||||
<Tool
|
||||
@@ -84,7 +82,6 @@
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
UseOfMFC="1"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
@@ -105,12 +102,14 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
|
||||
RuntimeLibrary="2"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="3"
|
||||
WarningLevel="4"
|
||||
DebugInformationFormat="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
@@ -149,6 +148,14 @@
|
||||
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"
|
||||
>
|
||||
@@ -157,12 +164,28 @@
|
||||
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"
|
||||
>
|
||||
@@ -171,6 +194,14 @@
|
||||
RelativePath=".\mkvreader.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mkvwriter.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\webmids.hpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
2081
mkvmuxer.cpp
Normal file
2081
mkvmuxer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
841
mkvmuxer.hpp
Normal file
841
mkvmuxer.hpp
Normal file
@@ -0,0 +1,841 @@
|
||||
// Copyright (c) 2011 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 MKVMUXER_HPP
|
||||
#define MKVMUXER_HPP
|
||||
|
||||
#include "mkvmuxertypes.hpp"
|
||||
|
||||
// For a description of the WebM elements see
|
||||
// http://www.webmproject.org/code/specs/container/.
|
||||
|
||||
namespace mkvmuxer {
|
||||
|
||||
class MkvWriter;
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Interface used by the mkvmuxer to write out the Mkv data.
|
||||
class IMkvWriter {
|
||||
public:
|
||||
// Writes out |len| bytes of |buf|. Returns 0 on success.
|
||||
virtual int32 Write(const void* buf, uint32 len) = 0;
|
||||
|
||||
// Returns the offset of the output position from the beginning of the
|
||||
// output.
|
||||
virtual int64 Position() const = 0;
|
||||
|
||||
// Set the current File position. Returns 0 on success.
|
||||
virtual int32 Position(int64 position) = 0;
|
||||
|
||||
// Returns true if the writer is seekable.
|
||||
virtual bool Seekable() const = 0;
|
||||
|
||||
// Element start notification. Called whenever an element identifier is about
|
||||
// to be written to the stream. |element_id| is the element identifier, and
|
||||
// |position| is the location in the WebM stream where the first octet of the
|
||||
// element identifier will be written.
|
||||
// Note: the |MkvId| enumeration in webmids.hpp defines element values.
|
||||
virtual void ElementStartNotify(uint64 element_id, int64 position) = 0;
|
||||
|
||||
protected:
|
||||
IMkvWriter();
|
||||
virtual ~IMkvWriter();
|
||||
|
||||
private:
|
||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(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);
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Class to hold data the will be written to a block.
|
||||
class Frame {
|
||||
public:
|
||||
Frame();
|
||||
~Frame();
|
||||
|
||||
// Copies |frame| data into |frame_|. Returns true on success.
|
||||
bool Init(const uint8* frame, uint64 length);
|
||||
|
||||
const uint8* frame() const { return frame_; }
|
||||
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_; }
|
||||
|
||||
private:
|
||||
// Pointer to the data. Owned by this class.
|
||||
uint8* frame_;
|
||||
|
||||
// Length of the data.
|
||||
uint64 length_;
|
||||
|
||||
// Mkv track number the data is associated with.
|
||||
uint64 track_number_;
|
||||
|
||||
// Timestamp of the data in nanoseconds.
|
||||
uint64 timestamp_;
|
||||
|
||||
// Flag telling if the data should set the key flag of a block.
|
||||
bool is_key_;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Class to hold one cue point in a Cues element.
|
||||
class CuePoint {
|
||||
public:
|
||||
CuePoint();
|
||||
~CuePoint();
|
||||
|
||||
// Returns the size in bytes for the entire CuePoint element.
|
||||
uint64 Size() const;
|
||||
|
||||
// Output the CuePoint element to the writer. Returns true on success.
|
||||
bool Write(IMkvWriter* writer) const;
|
||||
|
||||
void set_time(uint64 time) { time_ = time; }
|
||||
uint64 time() const { return time_; }
|
||||
void set_track(uint64 track) { track_ = track; }
|
||||
uint64 track() const { return track_; }
|
||||
void set_cluster_pos(uint64 cluster_pos) { cluster_pos_ = cluster_pos; }
|
||||
uint64 cluster_pos() const { return cluster_pos_; }
|
||||
void set_block_number(uint64 block_number) { block_number_ = block_number; }
|
||||
uint64 block_number() const { return block_number_; }
|
||||
void set_output_block_number(bool output_block_number) {
|
||||
output_block_number_ = output_block_number;
|
||||
}
|
||||
bool output_block_number() const { return output_block_number_; }
|
||||
|
||||
private:
|
||||
// Returns the size in bytes for the payload of the CuePoint element.
|
||||
uint64 PayloadSize() const;
|
||||
|
||||
// Absolute timecode according to the segment time base.
|
||||
uint64 time_;
|
||||
|
||||
// The Track element associated with the CuePoint.
|
||||
uint64 track_;
|
||||
|
||||
// The position of the Cluster containing the Block.
|
||||
uint64 cluster_pos_;
|
||||
|
||||
// Number of the Block within the Cluster, starting from 1.
|
||||
uint64 block_number_;
|
||||
|
||||
// If true the muxer will write out the block number for the cue if the
|
||||
// block number is different than the default of 1. Default is set to true.
|
||||
bool output_block_number_;
|
||||
|
||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(CuePoint);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Cues element.
|
||||
class Cues {
|
||||
public:
|
||||
Cues();
|
||||
~Cues();
|
||||
|
||||
// Adds a cue point to the Cues element. Returns true on success.
|
||||
bool AddCue(CuePoint* cue);
|
||||
|
||||
// Returns the cue point by index. Returns NULL if there is no cue point
|
||||
// match.
|
||||
const CuePoint* GetCueByIndex(int32 index) const;
|
||||
|
||||
// Output the Cues element to the writer. Returns true on success.
|
||||
bool Write(IMkvWriter* writer) const;
|
||||
|
||||
int32 cue_entries_size() const { return cue_entries_size_; }
|
||||
void set_output_block_number(bool output_block_number) {
|
||||
output_block_number_ = output_block_number;
|
||||
}
|
||||
bool output_block_number() const { return output_block_number_; }
|
||||
|
||||
private:
|
||||
// Number of allocated elements in |cue_entries_|.
|
||||
int32 cue_entries_capacity_;
|
||||
|
||||
// Number of CuePoints in |cue_entries_|.
|
||||
int32 cue_entries_size_;
|
||||
|
||||
// CuePoint list.
|
||||
CuePoint** cue_entries_;
|
||||
|
||||
// If true the muxer will write out the block number for the cue if the
|
||||
// block number is different than the default of 1. Default is set to true.
|
||||
bool output_block_number_;
|
||||
|
||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Cues);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// ContentEncoding element
|
||||
// Elements used to describe if the track data has been encrypted or
|
||||
// compressed with zlib or header stripping.
|
||||
// Currently only whole frames can only be encrypted once with AES. This
|
||||
// dictates that ContentEncodingOrder will be 0, ContentEncodingScope will
|
||||
// be 1, ContentEncodingType will be 1, and ContentEncAlgo will be 5.
|
||||
class ContentEncoding {
|
||||
public:
|
||||
ContentEncoding();
|
||||
~ContentEncoding();
|
||||
|
||||
uint64 enc_algo() const { return enc_algo_; }
|
||||
uint64 encoding_order() const { return encoding_order_; }
|
||||
uint64 encoding_scope() const { return encoding_scope_; }
|
||||
uint64 encoding_type() const { return encoding_type_; }
|
||||
|
||||
// Sets the content encryption id. Copies |length| bytes from |id| to
|
||||
// |enc_key_id_|. Returns true on success.
|
||||
bool SetEncryptionID(const uint8* id, uint64 length);
|
||||
|
||||
// Returns the size in bytes for the ContentEncoding element.
|
||||
uint64 Size() const;
|
||||
|
||||
// Writes out the ContentEncoding element to |writer|. Returns true on
|
||||
// success.
|
||||
bool Write(IMkvWriter* writer) const;
|
||||
|
||||
private:
|
||||
// Returns the size in bytes for the encoding elements.
|
||||
uint64 EncodingSize(uint64 compresion_size, uint64 encryption_size) const;
|
||||
|
||||
// Returns the size in bytes for the encryption elements.
|
||||
uint64 EncryptionSize() const;
|
||||
|
||||
// Track element names
|
||||
uint64 enc_algo_;
|
||||
uint8* enc_key_id_;
|
||||
uint64 encoding_order_;
|
||||
uint64 encoding_scope_;
|
||||
uint64 encoding_type_;
|
||||
|
||||
// Size of the ContentEncKeyID data in bytes.
|
||||
uint64 enc_key_id_length_;
|
||||
|
||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncoding);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Track element.
|
||||
class Track {
|
||||
public:
|
||||
Track();
|
||||
virtual ~Track();
|
||||
|
||||
// Adds a ContentEncoding element to the Track. Returns true on success.
|
||||
virtual bool AddContentEncoding();
|
||||
|
||||
// Returns the ContentEncoding by index. Returns NULL if there is no
|
||||
// ContentEncoding match.
|
||||
ContentEncoding* GetContentEncodingByIndex(uint32 index) const;
|
||||
|
||||
// Returns the size in bytes for the payload of the Track element.
|
||||
virtual uint64 PayloadSize() const;
|
||||
|
||||
// Returns the size in bytes of the Track element.
|
||||
virtual uint64 Size() const;
|
||||
|
||||
// Output the Track element to the writer. Returns true on success.
|
||||
virtual bool Write(IMkvWriter* writer) const;
|
||||
|
||||
// Sets the CodecPrivate element of the Track element. Copies |length|
|
||||
// bytes from |codec_private| to |codec_private_|. Returns true on success.
|
||||
bool SetCodecPrivate(const uint8* codec_private, uint64 length);
|
||||
|
||||
void set_codec_id(const char* codec_id);
|
||||
const char* codec_id() const { return codec_id_; }
|
||||
const uint8* codec_private() const { return codec_private_; }
|
||||
void set_language(const char* language);
|
||||
const char* language() const { return language_; }
|
||||
void set_name(const char* name);
|
||||
const char* name() const { return name_; }
|
||||
void set_number(uint64 number) { number_ = number; }
|
||||
uint64 number() const { return number_; }
|
||||
void set_type(uint64 type) { type_ = type; }
|
||||
uint64 type() const { return type_; }
|
||||
uint64 uid() const { return uid_; }
|
||||
|
||||
uint64 codec_private_length() const { return codec_private_length_; }
|
||||
uint32 content_encoding_entries_size() const {
|
||||
return content_encoding_entries_size_;
|
||||
}
|
||||
|
||||
private:
|
||||
// Returns a random number to be used for the Track UID.
|
||||
static uint64 MakeUID();
|
||||
|
||||
// Track element names
|
||||
char* codec_id_;
|
||||
uint8* codec_private_;
|
||||
char* language_;
|
||||
char* name_;
|
||||
uint64 number_;
|
||||
uint64 type_;
|
||||
const uint64 uid_;
|
||||
|
||||
// Size of the CodecPrivate data in bytes.
|
||||
uint64 codec_private_length_;
|
||||
|
||||
// ContentEncoding element list.
|
||||
ContentEncoding** content_encoding_entries_;
|
||||
|
||||
// Number of ContentEncoding elements added.
|
||||
uint32 content_encoding_entries_size_;
|
||||
|
||||
// Flag telling if the rand call was seeded.
|
||||
static bool is_seeded_;
|
||||
|
||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Track);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Track that has video specific elements.
|
||||
class VideoTrack : public Track {
|
||||
public:
|
||||
// Supported modes for stereo 3D.
|
||||
enum StereoMode {
|
||||
kMono = 0,
|
||||
kSideBySideLeftIsFirst = 1,
|
||||
kTopBottomRightIsFirst = 2,
|
||||
kTopBottomLeftIsFirst = 3,
|
||||
kSideBySideRightIsFirst = 11
|
||||
};
|
||||
|
||||
VideoTrack();
|
||||
virtual ~VideoTrack();
|
||||
|
||||
// Returns the size in bytes for the payload of the Track element plus the
|
||||
// video specific elements.
|
||||
virtual uint64 PayloadSize() const;
|
||||
|
||||
// Output the VideoTrack element to the writer. Returns true on success.
|
||||
virtual bool Write(IMkvWriter* writer) const;
|
||||
|
||||
// Sets the video's stereo mode. Returns true on success.
|
||||
bool SetStereoMode(uint64 stereo_mode);
|
||||
|
||||
void set_display_height(uint64 height) { display_height_ = height; }
|
||||
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_frame_rate(double frame_rate) { frame_rate_ = frame_rate; }
|
||||
double frame_rate() const { return frame_rate_; }
|
||||
void set_height(uint64 height) { height_ = height; }
|
||||
uint64 height() const { return height_; }
|
||||
uint64 stereo_mode() { return stereo_mode_; }
|
||||
void set_width(uint64 width) { width_ = width; }
|
||||
uint64 width() const { return width_; }
|
||||
|
||||
private:
|
||||
// Returns the size in bytes of the Video element.
|
||||
uint64 VideoPayloadSize() const;
|
||||
|
||||
// Video track element names.
|
||||
uint64 display_height_;
|
||||
uint64 display_width_;
|
||||
double frame_rate_;
|
||||
uint64 height_;
|
||||
uint64 stereo_mode_;
|
||||
uint64 width_;
|
||||
|
||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(VideoTrack);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Track that has audio specific elements.
|
||||
class AudioTrack : public Track {
|
||||
public:
|
||||
AudioTrack();
|
||||
virtual ~AudioTrack();
|
||||
|
||||
// Returns the size in bytes for the payload of the Track element plus the
|
||||
// audio specific elements.
|
||||
virtual uint64 PayloadSize() const;
|
||||
|
||||
// Output the AudioTrack element to the writer. Returns true on success.
|
||||
virtual bool Write(IMkvWriter* writer) const;
|
||||
|
||||
void set_bit_depth(uint64 bit_depth) { bit_depth_ = bit_depth; }
|
||||
uint64 bit_depth() const { return bit_depth_; }
|
||||
void set_channels(uint64 channels) { channels_ = channels; }
|
||||
uint64 channels() const { return channels_; }
|
||||
void set_sample_rate(double sample_rate) { sample_rate_ = sample_rate; }
|
||||
double sample_rate() const { return sample_rate_; }
|
||||
|
||||
private:
|
||||
// Audio track element names.
|
||||
uint64 bit_depth_;
|
||||
uint64 channels_;
|
||||
double sample_rate_;
|
||||
|
||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(AudioTrack);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Tracks element
|
||||
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;
|
||||
|
||||
Tracks();
|
||||
~Tracks();
|
||||
|
||||
// Adds a Track element to the Tracks object. |track| will be owned and
|
||||
// deleted by the Tracks object. Returns true on success. |number| is the
|
||||
// number to use for the track. |number| must be >= 0. If |number| == 0
|
||||
// then the muxer will decide on the track number.
|
||||
bool AddTrack(Track* track, int32 number);
|
||||
|
||||
// Returns the track by index. Returns NULL if there is no track match.
|
||||
const Track* GetTrackByIndex(uint32 idx) const;
|
||||
|
||||
// Search the Tracks and return the track that matches |tn|. Returns NULL
|
||||
// if there is no track match.
|
||||
Track* GetTrackByNumber(uint64 track_number) const;
|
||||
|
||||
// Returns true if the track number is an audio track.
|
||||
bool TrackIsAudio(uint64 track_number) const;
|
||||
|
||||
// Returns true if the track number is a video track.
|
||||
bool TrackIsVideo(uint64 track_number) const;
|
||||
|
||||
// Output the Tracks element to the writer. Returns true on success.
|
||||
bool Write(IMkvWriter* writer) const;
|
||||
|
||||
uint32 track_entries_size() const { return track_entries_size_; }
|
||||
|
||||
private:
|
||||
// Track element list.
|
||||
Track** track_entries_;
|
||||
|
||||
// Number of Track elements added.
|
||||
uint32 track_entries_size_;
|
||||
|
||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tracks);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Cluster element
|
||||
//
|
||||
// Notes:
|
||||
// |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.
|
||||
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.
|
||||
// Inputs:
|
||||
// frame: Pointer to the data
|
||||
// length: Length of the data
|
||||
// track_number: Track to add the data to. Value returned by Add track
|
||||
// functions.
|
||||
// timestamp: Timecode of the frame relative to the cluster timecode.
|
||||
// is_key: Flag telling whether or not this frame is a key frame.
|
||||
bool AddFrame(const uint8* frame,
|
||||
uint64 length,
|
||||
uint64 track_number,
|
||||
short timecode,
|
||||
bool is_key);
|
||||
|
||||
// Increments the size of the cluster's data in bytes.
|
||||
void AddPayloadSize(uint64 size);
|
||||
|
||||
// Closes the cluster so no more data can be written to it. Will update the
|
||||
// cluster's size if |writer_| is seekable. Returns true on success.
|
||||
bool Finalize();
|
||||
|
||||
// Returns the size in bytes for the entire Cluster element.
|
||||
uint64 Size() const;
|
||||
|
||||
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_; }
|
||||
|
||||
private:
|
||||
// Outputs the Cluster header to |writer_|. Returns true on success.
|
||||
bool WriteClusterHeader();
|
||||
|
||||
// Number of blocks added to the cluster.
|
||||
int32 blocks_added_;
|
||||
|
||||
// Flag telling if the cluster has been closed.
|
||||
bool finalized_;
|
||||
|
||||
// Flag telling if the cluster's header has been written.
|
||||
bool header_written_;
|
||||
|
||||
// The size of the cluster elements in bytes.
|
||||
uint64 payload_size_;
|
||||
|
||||
// The file position used for cue points.
|
||||
const int64 position_for_cues_;
|
||||
|
||||
// The file position of the cluster's size element.
|
||||
int64 size_position_;
|
||||
|
||||
// The absolute timecode of the cluster.
|
||||
const uint64 timecode_;
|
||||
|
||||
// Pointer to the writer object. Not owned by this class.
|
||||
IMkvWriter* writer_;
|
||||
|
||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Cluster);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// SeekHead element
|
||||
class SeekHead {
|
||||
public:
|
||||
SeekHead();
|
||||
~SeekHead();
|
||||
|
||||
// TODO(fgalligan): Change this to reserve a certain size. Then check how
|
||||
// big the seek entry to be added is as not every seek entry will be the
|
||||
// maximum size it could be.
|
||||
// Adds a seek entry to be written out when the element is finalized. |id|
|
||||
// must be the coded mkv element id. |pos| is the file position of the
|
||||
// element. Returns true on success.
|
||||
bool AddSeekEntry(uint32 id, uint64 pos);
|
||||
|
||||
// Writes out SeekHead and SeekEntry elements. Returns true on success.
|
||||
bool Finalize(IMkvWriter* writer) const;
|
||||
|
||||
// Reserves space by writing out a Void element which will be updated with
|
||||
// a SeekHead element later. Returns true on success.
|
||||
bool Write(IMkvWriter* writer);
|
||||
|
||||
private:
|
||||
// We are going to put a cap on the number of Seek Entries.
|
||||
const static int32 kSeekEntryCount = 4;
|
||||
|
||||
// Returns the maximum size in bytes of one seek entry.
|
||||
uint64 MaxEntrySize() const;
|
||||
|
||||
// Seek entry id element list.
|
||||
uint32 seek_entry_id_[kSeekEntryCount];
|
||||
|
||||
// Seek entry pos element list.
|
||||
uint64 seek_entry_pos_[kSeekEntryCount];
|
||||
|
||||
// The file position of SeekHead element.
|
||||
int64 start_pos_;
|
||||
|
||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(SeekHead);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Segment Information element
|
||||
class SegmentInfo {
|
||||
public:
|
||||
SegmentInfo();
|
||||
~SegmentInfo();
|
||||
|
||||
// Will update the duration if |duration_| is > 0.0. Returns true on success.
|
||||
bool Finalize(IMkvWriter* writer) const;
|
||||
|
||||
// Sets |muxing_app_| and |writing_app_|.
|
||||
bool Init();
|
||||
|
||||
// Output the Segment Information element to the writer. Returns true on
|
||||
// success.
|
||||
bool Write(IMkvWriter* writer);
|
||||
|
||||
void set_duration(double duration) { duration_ = duration; }
|
||||
double duration() const { return duration_; }
|
||||
const char* muxing_app() const { return muxing_app_; }
|
||||
void set_timecode_scale(uint64 scale) { timecode_scale_ = scale; }
|
||||
uint64 timecode_scale() const { return timecode_scale_; }
|
||||
void set_writing_app(const char* app);
|
||||
const char* writing_app() const { return writing_app_; }
|
||||
|
||||
private:
|
||||
// Segment Information element names.
|
||||
// Initially set to -1 to signify that a duration has not been set and should
|
||||
// not be written out.
|
||||
double duration_;
|
||||
// Set to libwebm-%d.%d.%d.%d, major, minor, build, revision.
|
||||
char* muxing_app_;
|
||||
uint64 timecode_scale_;
|
||||
// Initially set to libwebm-%d.%d.%d.%d, major, minor, build, revision.
|
||||
char* writing_app_;
|
||||
|
||||
// The file position of the duration element.
|
||||
int64 duration_pos_;
|
||||
|
||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(SegmentInfo);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// This class represents the main segment in a WebM file. Currently only
|
||||
// supports one Segment element.
|
||||
//
|
||||
// Notes:
|
||||
// |Init| must be called before any other method in this class.
|
||||
class Segment {
|
||||
public:
|
||||
enum Mode {
|
||||
kLive = 0x1,
|
||||
kFile = 0x2
|
||||
};
|
||||
|
||||
const static uint64 kDefaultMaxClusterDuration = 30000000000ULL;
|
||||
|
||||
Segment();
|
||||
~Segment();
|
||||
|
||||
// Initializes |SegmentInfo| and returns result. Always returns false when
|
||||
// |ptr_writer| is NULL.
|
||||
bool Init(IMkvWriter* ptr_writer);
|
||||
|
||||
// Adds an audio track to the segment. Returns the number of the track on
|
||||
// success, 0 on error.
|
||||
uint64 AddAudioTrack(int32 sample_rate, int32 channels);
|
||||
|
||||
// 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.
|
||||
// |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);
|
||||
|
||||
// Adds a frame to be output in the file. Returns true on success.
|
||||
// Inputs:
|
||||
// frame: 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,
|
||||
bool is_key);
|
||||
|
||||
// Adds a video track to the segment. Returns the number of the track on
|
||||
// success, 0 on error.
|
||||
uint64 AddVideoTrack(int32 width, int32 height);
|
||||
|
||||
// Adds a 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.
|
||||
uint64 AddVideoTrack(int32 width, int32 height, int32 number);
|
||||
|
||||
// Sets which track to use for the Cues element. Must have added the track
|
||||
// before calling this function. Returns true on success. |track_number| is
|
||||
// returned by the Add track functions.
|
||||
bool CuesTrack(uint64 track_number);
|
||||
|
||||
// Writes out any frames that have not been written out. Finalizes the last
|
||||
// cluster. May update the size and duration of the segment. May output the
|
||||
// Cues element. May finalize the SeekHead element. Returns true on success.
|
||||
bool Finalize();
|
||||
|
||||
// Returns the Cues object.
|
||||
Cues* GetCues() { return &cues_; }
|
||||
|
||||
// Returns the Segment Information object.
|
||||
SegmentInfo* GetSegmentInfo() { return &segment_info_; }
|
||||
|
||||
// Search the Tracks and return the track that matches |track_number|.
|
||||
// Returns NULL if there is no track match.
|
||||
Track* GetTrackByNumber(uint64 track_number) const;
|
||||
|
||||
// Toggles whether to output a cues element.
|
||||
void OutputCues(bool output_cues);
|
||||
|
||||
// Sets if the muxer will output files in chunks or not. |chunking| is a
|
||||
// flag telling whether or not to turn on chunking. |filename| is the base
|
||||
// filename for the chunk files. The header chunk file will be named
|
||||
// |filename|.hdr and the data chunks will be named
|
||||
// |filename|_XXXXXX.chk. Chunking implies that the muxer will be writing
|
||||
// to files so the muxer will use the default MkvWriter class to control
|
||||
// what data is written to what files. Returns true on success.
|
||||
// TODO: Should we change the IMkvWriter Interface to add Open and Close?
|
||||
// That will force the interface to be dependent on files.
|
||||
bool SetChunking(bool chunking, const char* filename);
|
||||
|
||||
bool chunking() const { return chunking_; }
|
||||
uint64 cues_track() const { return cues_track_; }
|
||||
void set_max_cluster_duration(uint64 max_cluster_duration) {
|
||||
max_cluster_duration_ = max_cluster_duration;
|
||||
}
|
||||
uint64 max_cluster_duration() const { return max_cluster_duration_; }
|
||||
void set_max_cluster_size(uint64 max_cluster_size) {
|
||||
max_cluster_size_ = max_cluster_size;
|
||||
}
|
||||
uint64 max_cluster_size() const { return max_cluster_size_; }
|
||||
void set_mode(Mode mode) { mode_ = mode; }
|
||||
Mode mode() const { return mode_; }
|
||||
bool output_cues() const { return output_cues_; }
|
||||
const SegmentInfo* segment_info() const { return &segment_info_; }
|
||||
|
||||
private:
|
||||
// Adds a cue point to the Cues element. |timestamp| is the time in
|
||||
// nanoseconds of the cue's time. Returns true on success.
|
||||
bool AddCuePoint(uint64 timestamp);
|
||||
|
||||
// Checks if header information has been output and initialized. If not it
|
||||
// will output the Segment element and initialize the SeekHead elment and
|
||||
// Cues elements.
|
||||
bool CheckHeaderInfo();
|
||||
|
||||
// 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.
|
||||
bool UpdateChunkName(const char* ext, char** name) const;
|
||||
|
||||
// Returns the maximum offset within the segment's payload. When chunking
|
||||
// this function is needed to determine offsets of elements within the
|
||||
// chunked files. Returns -1 on error.
|
||||
int64 MaxOffset();
|
||||
|
||||
// Adds the frame to our frame array.
|
||||
bool QueueFrame(Frame* frame);
|
||||
|
||||
// Output all frames that are queued. Returns true on success and if there
|
||||
// are no frames queued.
|
||||
bool WriteFramesAll();
|
||||
|
||||
// Output all frames that are queued that have an end time that is less
|
||||
// then |timestamp|. Returns true on success and if there are no frames
|
||||
// queued.
|
||||
bool WriteFramesLessThan(uint64 timestamp);
|
||||
|
||||
// Outputs the segment header, Segment Information element, SeekHead element,
|
||||
// and Tracks element to |writer_|.
|
||||
bool WriteSegmentHeader();
|
||||
|
||||
// WebM elements
|
||||
Cues cues_;
|
||||
SeekHead seek_head_;
|
||||
SegmentInfo segment_info_;
|
||||
Tracks tracks_;
|
||||
|
||||
// Number of chunks written.
|
||||
int chunk_count_;
|
||||
|
||||
// Current chunk filename.
|
||||
char* chunk_name_;
|
||||
|
||||
// Default MkvWriter object created by this class used for writing clusters
|
||||
// out in separate files.
|
||||
MkvWriter* chunk_writer_cluster_;
|
||||
|
||||
// Default MkvWriter object created by this class used for writing Cues
|
||||
// element out to a file.
|
||||
MkvWriter* chunk_writer_cues_;
|
||||
|
||||
// Default MkvWriter object created by this class used for writing the
|
||||
// Matroska header out to a file.
|
||||
MkvWriter* chunk_writer_header_;
|
||||
|
||||
// Flag telling whether or not the muxer is chunking output to multiple
|
||||
// files.
|
||||
bool chunking_;
|
||||
|
||||
// Base filename for the chunked files.
|
||||
char* chunking_base_name_;
|
||||
|
||||
// List of clusters.
|
||||
Cluster** cluster_list_;
|
||||
|
||||
// Number of cluster pointers allocated in the cluster list.
|
||||
int32 cluster_list_capacity_;
|
||||
|
||||
// Number of clusters in the cluster list.
|
||||
int32 cluster_list_size_;
|
||||
|
||||
// Track number that is associated with the cues element for this segment.
|
||||
uint64 cues_track_;
|
||||
|
||||
// List of stored audio frames. These variables are used to store frames so
|
||||
// the muxer can follow the guideline "Audio blocks that contain the video
|
||||
// key frame's timecode should be in the same cluster as the video key frame
|
||||
// block."
|
||||
Frame** frames_;
|
||||
|
||||
// Number of frame pointers allocated in the frame list.
|
||||
int32 frames_capacity_;
|
||||
|
||||
// Number of frames in the frame list.
|
||||
int32 frames_size_;
|
||||
|
||||
// Flag telling if a video track has been added to the segment.
|
||||
bool has_video_;
|
||||
|
||||
// Flag telling if the segment's header has been written.
|
||||
bool header_written_;
|
||||
|
||||
// Last timestamp in nanoseconds added to a cluster.
|
||||
uint64 last_timestamp_;
|
||||
|
||||
// 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.
|
||||
uint64 max_cluster_duration_;
|
||||
|
||||
// Maximum size in bytes for a cluster. This variable is a guideline and
|
||||
// some clusters may have a larger size. Default is 0 which signifies that
|
||||
// the muxer will decide the size.
|
||||
uint64 max_cluster_size_;
|
||||
|
||||
// The mode that segment is in. If set to |kLive| the writer must not
|
||||
// seek backwards.
|
||||
Mode mode_;
|
||||
|
||||
// Flag telling the muxer that a new cluster should be started with the next
|
||||
// frame.
|
||||
bool new_cluster_;
|
||||
|
||||
// Flag telling the muxer that a new cue point should be added.
|
||||
bool new_cuepoint_;
|
||||
|
||||
// TODO(fgalligan): Should we add support for more than one Cues element?
|
||||
// Flag whether or not the muxer should output a Cues element.
|
||||
bool output_cues_;
|
||||
|
||||
// The file position of the segment's payload.
|
||||
int64 payload_pos_;
|
||||
|
||||
// The file position of the element's size.
|
||||
int64 size_position_;
|
||||
|
||||
// Pointer to the writer objects. Not owned by this class.
|
||||
IMkvWriter* writer_cluster_;
|
||||
IMkvWriter* writer_cues_;
|
||||
IMkvWriter* writer_header_;
|
||||
|
||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Segment);
|
||||
};
|
||||
|
||||
} //end namespace mkvmuxer
|
||||
|
||||
#endif //MKVMUXER_HPP
|
||||
29
mkvmuxertypes.hpp
Normal file
29
mkvmuxertypes.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2011 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 MKVMUXERTYPES_HPP
|
||||
#define MKVMUXERTYPES_HPP
|
||||
|
||||
// Copied from Chromium basictypes.h
|
||||
// A macro to disallow the copy constructor and operator= functions
|
||||
// This should be used in the private: declarations for a class
|
||||
#define LIBWEBM_DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
void operator=(const TypeName&)
|
||||
|
||||
namespace mkvmuxer {
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef int int32;
|
||||
typedef unsigned int uint32;
|
||||
typedef long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
|
||||
} //end namespace mkvmuxer
|
||||
|
||||
#endif // MKVMUXERTYPES_HPP
|
||||
390
mkvmuxerutil.cpp
Normal file
390
mkvmuxerutil.cpp
Normal file
@@ -0,0 +1,390 @@
|
||||
// Copyright (c) 2011 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 "mkvmuxerutil.hpp"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "mkvwriter.hpp"
|
||||
#include "webmids.hpp"
|
||||
|
||||
namespace mkvmuxer {
|
||||
|
||||
int32 GetCodedUIntSize(uint64 value) {
|
||||
|
||||
if (value < 0x000000000000007FULL)
|
||||
return 1;
|
||||
else if (value < 0x0000000000003FFFULL)
|
||||
return 2;
|
||||
else if (value < 0x00000000001FFFFFULL)
|
||||
return 3;
|
||||
else if (value < 0x000000000FFFFFFFULL)
|
||||
return 4;
|
||||
else if (value < 0x00000007FFFFFFFFULL)
|
||||
return 5;
|
||||
else if (value < 0x000003FFFFFFFFFFULL)
|
||||
return 6;
|
||||
else if (value < 0x0001FFFFFFFFFFFFULL)
|
||||
return 7;
|
||||
return 8;
|
||||
}
|
||||
|
||||
int32 GetUIntSize(uint64 value) {
|
||||
|
||||
if (value < 0x0000000000000100ULL)
|
||||
return 1;
|
||||
else if (value < 0x0000000000010000ULL)
|
||||
return 2;
|
||||
else if (value < 0x0000000001000000ULL)
|
||||
return 3;
|
||||
else if (value < 0x0000000100000000ULL)
|
||||
return 4;
|
||||
else if (value < 0x0000010000000000ULL)
|
||||
return 5;
|
||||
else if (value < 0x0001000000000000ULL)
|
||||
return 6;
|
||||
else if (value < 0x0100000000000000ULL)
|
||||
return 7;
|
||||
return 8;
|
||||
}
|
||||
|
||||
uint64 EbmlMasterElementSize(uint64 type, uint64 value) {
|
||||
// Size of EBML ID
|
||||
int32 ebml_size = GetUIntSize(type);
|
||||
|
||||
// Datasize
|
||||
ebml_size += GetCodedUIntSize(value);
|
||||
|
||||
return ebml_size;
|
||||
}
|
||||
|
||||
uint64 EbmlElementSize(uint64 type, uint64 value) {
|
||||
// Size of EBML ID
|
||||
int32 ebml_size = GetUIntSize(type);
|
||||
|
||||
// Datasize
|
||||
ebml_size += GetUIntSize(value);
|
||||
|
||||
// Size of Datasize
|
||||
ebml_size++;
|
||||
|
||||
return ebml_size;
|
||||
}
|
||||
|
||||
uint64 EbmlElementSize(uint64 type, float value) {
|
||||
// Size of EBML ID
|
||||
uint64 ebml_size = GetUIntSize(type);
|
||||
|
||||
// Datasize
|
||||
ebml_size += sizeof(value);
|
||||
|
||||
// Size of Datasize
|
||||
ebml_size++;
|
||||
|
||||
return ebml_size;
|
||||
}
|
||||
|
||||
uint64 EbmlElementSize(uint64 type, const char* value) {
|
||||
if (!value)
|
||||
return 0;
|
||||
|
||||
// Size of EBML ID
|
||||
uint64 ebml_size = GetUIntSize(type);
|
||||
|
||||
// Datasize
|
||||
ebml_size += strlen(value);
|
||||
|
||||
// Size of Datasize
|
||||
ebml_size++;
|
||||
|
||||
return ebml_size;
|
||||
}
|
||||
|
||||
uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size) {
|
||||
if (!value)
|
||||
return 0;
|
||||
|
||||
// Size of EBML ID
|
||||
uint64 ebml_size = GetUIntSize(type);
|
||||
|
||||
// Datasize
|
||||
ebml_size += size;
|
||||
|
||||
// Size of Datasize
|
||||
ebml_size += GetCodedUIntSize(size);
|
||||
|
||||
return ebml_size;
|
||||
}
|
||||
|
||||
int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size) {
|
||||
if (!writer || size < 1 || size > 8)
|
||||
return -1;
|
||||
|
||||
for (int32 i = 1; i <= size; ++i) {
|
||||
const int32 byte_count = size - i;
|
||||
const int32 bit_count = byte_count * 8;
|
||||
|
||||
const int64 bb = value >> bit_count;
|
||||
const uint8 b = static_cast<uint8>(bb);
|
||||
|
||||
const int32 status = writer->Write(&b, 1);
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 SerializeFloat(IMkvWriter* writer, float f) {
|
||||
if (!writer)
|
||||
return -1;
|
||||
|
||||
const uint32& val = reinterpret_cast<const uint32&>(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 int32 status = writer->Write(&b, 1);
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 WriteUInt(IMkvWriter* writer, uint64 value) {
|
||||
if (!writer)
|
||||
return -1;
|
||||
|
||||
int32 size = GetCodedUIntSize(value);
|
||||
|
||||
return WriteUIntSize(writer, value, size);
|
||||
}
|
||||
|
||||
int32 WriteUIntSize(IMkvWriter* writer, uint64 value, int32 size) {
|
||||
if (!writer || size < 0 || size > 8)
|
||||
return -1;
|
||||
|
||||
if (size > 0) {
|
||||
const uint64 bit = 1LL << (size * 7);
|
||||
|
||||
if (value > (bit - 2))
|
||||
return -1;
|
||||
|
||||
value |= bit;
|
||||
} else {
|
||||
size = 1;
|
||||
int64 bit;
|
||||
|
||||
for (;;) {
|
||||
bit = 1LL << (size * 7);
|
||||
const uint64 max = bit - 2;
|
||||
|
||||
if (value <= max)
|
||||
break;
|
||||
|
||||
++size;
|
||||
}
|
||||
|
||||
if (size > 8)
|
||||
return false;
|
||||
|
||||
value |= bit;
|
||||
}
|
||||
|
||||
return SerializeInt(writer, value, size);
|
||||
}
|
||||
|
||||
int32 WriteID(IMkvWriter* writer, uint64 type) {
|
||||
if (!writer)
|
||||
return -1;
|
||||
|
||||
writer->ElementStartNotify(type, writer->Position());
|
||||
|
||||
const int32 size = GetUIntSize(type);
|
||||
|
||||
return SerializeInt(writer, type, size);
|
||||
}
|
||||
|
||||
bool WriteEbmlMasterElement(IMkvWriter* writer, uint64 type, uint64 size) {
|
||||
if (!writer)
|
||||
return false;
|
||||
|
||||
if (WriteID(writer, type))
|
||||
return false;
|
||||
|
||||
if (WriteUInt(writer, size))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value) {
|
||||
if (!writer)
|
||||
return false;
|
||||
|
||||
if (WriteID(writer, type))
|
||||
return false;
|
||||
|
||||
const uint64 size = GetUIntSize(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;
|
||||
|
||||
if (WriteID(writer, type))
|
||||
return false;
|
||||
|
||||
if (WriteUInt(writer, 4))
|
||||
return false;
|
||||
|
||||
if (SerializeFloat(writer, value))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value) {
|
||||
if (!writer || !value)
|
||||
return false;
|
||||
|
||||
if (WriteID(writer, type))
|
||||
return false;
|
||||
|
||||
const int32 length = strlen(value);
|
||||
if (WriteUInt(writer, length))
|
||||
return false;
|
||||
|
||||
if (writer->Write(value, length))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteEbmlElement(IMkvWriter* writer,
|
||||
uint64 type,
|
||||
const uint8* value,
|
||||
uint64 size) {
|
||||
if (!writer || !value || size < 1)
|
||||
return false;
|
||||
|
||||
if (WriteID(writer, type))
|
||||
return false;
|
||||
|
||||
if (WriteUInt(writer, size))
|
||||
return false;
|
||||
|
||||
if (writer->Write(value, static_cast<uint32>(size)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64 WriteSimpleBlock(IMkvWriter* writer,
|
||||
const uint8* data,
|
||||
uint64 length,
|
||||
char track_number,
|
||||
short timecode,
|
||||
bool is_key) {
|
||||
|
||||
if (!writer || !data || length < 1 || track_number < 1 || timecode < 0)
|
||||
return false;
|
||||
|
||||
if (WriteID(writer, kMkvSimpleBlock))
|
||||
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, static_cast<uint64>(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;
|
||||
}
|
||||
|
||||
uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
|
||||
if (!writer)
|
||||
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;
|
||||
|
||||
if (void_size != size)
|
||||
return 0;
|
||||
|
||||
const int64 payload_position = writer->Position();
|
||||
if (payload_position < 0)
|
||||
return 0;
|
||||
|
||||
if (WriteID(writer, kMkvVoid))
|
||||
return 0;
|
||||
|
||||
if (WriteUInt(writer, void_entry_size))
|
||||
return 0;
|
||||
|
||||
const uint8 value = 0;
|
||||
for (int32 i = 0; i < static_cast<int32>(void_entry_size); ++i) {
|
||||
if (writer->Write(&value, 1))
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int64 stop_position = writer->Position();
|
||||
if (stop_position < 0 ||
|
||||
stop_position - payload_position != static_cast<int64>(void_size))
|
||||
return 0;
|
||||
|
||||
return void_size;
|
||||
}
|
||||
|
||||
void GetVersion(int32& major, int32& minor, int32& build, int32& revision) {
|
||||
major = 0;
|
||||
minor = 0;
|
||||
build = 0;
|
||||
revision = 1;
|
||||
}
|
||||
|
||||
} // namespace mkvmuxer
|
||||
82
mkvmuxerutil.hpp
Normal file
82
mkvmuxerutil.hpp
Normal file
@@ -0,0 +1,82 @@
|
||||
// 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.
|
||||
|
||||
#ifndef MKVMUXERUTIL_HPP
|
||||
#define MKVMUXERUTIL_HPP
|
||||
|
||||
#include "mkvmuxertypes.hpp"
|
||||
|
||||
namespace mkvmuxer {
|
||||
|
||||
class IMkvWriter;
|
||||
|
||||
const uint64 kEbmlUnknownValue = 0x01FFFFFFFFFFFFFFULL;
|
||||
|
||||
// Writes out |value| in Big Endian order. Returns 0 on success.
|
||||
int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size);
|
||||
|
||||
// Returns the size in bytes of the element.
|
||||
uint64 EbmlMasterElementSize(uint64 type, uint64 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);
|
||||
|
||||
// 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
|
||||
// be in a coded form. Returns 0 on success.
|
||||
int32 WriteUInt(IMkvWriter* writer, uint64 value);
|
||||
|
||||
// Creates an EBML coded number from |value| and writes it out. The size of
|
||||
// the coded number is determined by the value of |size|. |value| must not
|
||||
// be in a coded form. Returns 0 on success.
|
||||
int32 WriteUIntSize(IMkvWriter* writer, uint64 value, int32 size);
|
||||
|
||||
// Output an Mkv master element. Returns true if the element was written.
|
||||
bool WriteEbmlMasterElement(IMkvWriter* writer, uint64 value, uint64 size);
|
||||
|
||||
// Outputs an Mkv ID, calls |IMkvWriter::ElementStartNotify|, and passes the
|
||||
// ID to |SerializeInt|. Returns 0 on success.
|
||||
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, float value);
|
||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value);
|
||||
bool WriteEbmlElement(IMkvWriter* writer,
|
||||
uint64 type,
|
||||
const uint8* value,
|
||||
uint64 size);
|
||||
|
||||
// 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.
|
||||
// timecode: Relative timecode of the Block.
|
||||
// is_key: Flag telling whether or not this frame is a key frame.
|
||||
uint64 WriteSimpleBlock(IMkvWriter* writer,
|
||||
const uint8* data,
|
||||
uint64 length,
|
||||
char track_number,
|
||||
short timecode,
|
||||
bool is_key);
|
||||
|
||||
// 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
|
||||
// it from |size|.
|
||||
uint64 WriteVoidElement(IMkvWriter* writer, uint64 size);
|
||||
|
||||
// Returns the version number of the muxer in |major|, |minor|, |build|,
|
||||
// and |revision|.
|
||||
void GetVersion(int32& major, int32& minor, int32& build, int32& revision);
|
||||
|
||||
} //end namespace mkvmuxer
|
||||
|
||||
#endif // MKVMUXERUTIL_HPP
|
||||
5945
mkvparser.cpp
5945
mkvparser.cpp
File diff suppressed because it is too large
Load Diff
432
mkvparser.hpp
432
mkvparser.hpp
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cstddef>
|
||||
|
||||
namespace mkvparser
|
||||
{
|
||||
@@ -33,8 +34,23 @@ long long SyncReadUInt(IMkvReader*, long long pos, long long stop, long&);
|
||||
long long UnserializeUInt(IMkvReader*, long long pos, long long size);
|
||||
float Unserialize4Float(IMkvReader*, long long);
|
||||
double Unserialize8Double(IMkvReader*, long long);
|
||||
|
||||
#if 0
|
||||
short Unserialize2SInt(IMkvReader*, long long);
|
||||
signed char Unserialize1SInt(IMkvReader*, long long);
|
||||
#else
|
||||
long UnserializeInt(IMkvReader*, long long pos, long len, long long& result);
|
||||
#endif
|
||||
|
||||
long UnserializeString(IMkvReader*, long long pos, long long size, char*&);
|
||||
|
||||
long ParseElementHeader(
|
||||
IMkvReader* pReader,
|
||||
long long& pos, //consume id and size fields
|
||||
long long stop, //if you know size of element's parent
|
||||
long long& id,
|
||||
long long& size);
|
||||
|
||||
bool Match(IMkvReader*, long long&, unsigned long, long long&);
|
||||
bool Match(IMkvReader*, long long&, unsigned long, char*&);
|
||||
bool Match(IMkvReader*, long long&, unsigned long, unsigned char*&, size_t&);
|
||||
@@ -73,9 +89,11 @@ public:
|
||||
const long long m_start;
|
||||
const long long m_size;
|
||||
|
||||
Block(long long start, long long size, IMkvReader*);
|
||||
Block(long long start, long long size);
|
||||
~Block();
|
||||
|
||||
long Parse(IMkvReader*);
|
||||
|
||||
long long GetTrackNumber() const;
|
||||
long long GetTimeCode(const Cluster*) const; //absolute, but not scaled
|
||||
long long GetTime(const Cluster*) const; //absolute, and scaled (ns)
|
||||
@@ -83,6 +101,9 @@ public:
|
||||
void SetKey(bool);
|
||||
bool IsInvisible() const;
|
||||
|
||||
enum Lacing { kLacingNone, kLacingXiph, kLacingFixed, kLacingEbml };
|
||||
Lacing GetLacing() const;
|
||||
|
||||
int GetFrameCount() const; //to index frames: [0, count)
|
||||
|
||||
struct Frame
|
||||
@@ -111,16 +132,23 @@ class BlockEntry
|
||||
BlockEntry(const BlockEntry&);
|
||||
BlockEntry& operator=(const BlockEntry&);
|
||||
|
||||
protected:
|
||||
BlockEntry(Cluster*, long index);
|
||||
|
||||
public:
|
||||
virtual ~BlockEntry();
|
||||
virtual bool EOS() const = 0;
|
||||
virtual const Cluster* GetCluster() const = 0;
|
||||
virtual size_t GetIndex() const = 0;
|
||||
|
||||
bool EOS() const;
|
||||
const Cluster* GetCluster() const;
|
||||
long GetIndex() const;
|
||||
virtual const Block* GetBlock() const = 0;
|
||||
//virtual bool IsBFrame() const = 0;
|
||||
|
||||
enum Kind { kBlockEOS, kBlockSimple, kBlockGroup };
|
||||
virtual Kind GetKind() const = 0;
|
||||
|
||||
protected:
|
||||
BlockEntry();
|
||||
Cluster* const m_pCluster;
|
||||
const long m_index;
|
||||
|
||||
};
|
||||
|
||||
@@ -131,17 +159,13 @@ class SimpleBlock : public BlockEntry
|
||||
SimpleBlock& operator=(const SimpleBlock&);
|
||||
|
||||
public:
|
||||
SimpleBlock(Cluster*, size_t, long long start, long long size);
|
||||
SimpleBlock(Cluster*, long index, long long start, long long size);
|
||||
long Parse();
|
||||
|
||||
bool EOS() const;
|
||||
const Cluster* GetCluster() const;
|
||||
size_t GetIndex() const;
|
||||
Kind GetKind() const;
|
||||
const Block* GetBlock() const;
|
||||
//bool IsBFrame() const;
|
||||
|
||||
protected:
|
||||
Cluster* const m_pCluster;
|
||||
const size_t m_index;
|
||||
Block m_block;
|
||||
|
||||
};
|
||||
@@ -153,41 +177,120 @@ class BlockGroup : public BlockEntry
|
||||
BlockGroup& operator=(const BlockGroup&);
|
||||
|
||||
public:
|
||||
BlockGroup(Cluster*, size_t, long long, long long);
|
||||
~BlockGroup();
|
||||
BlockGroup(
|
||||
Cluster*,
|
||||
long index,
|
||||
long long block_start, //absolute pos of block's payload
|
||||
long long block_size, //size of block's payload
|
||||
long long prev,
|
||||
long long next,
|
||||
long long duration);
|
||||
|
||||
bool EOS() const;
|
||||
const Cluster* GetCluster() const;
|
||||
size_t GetIndex() const;
|
||||
long Parse();
|
||||
|
||||
Kind GetKind() const;
|
||||
const Block* GetBlock() const;
|
||||
//bool IsBFrame() const;
|
||||
|
||||
short GetPrevTimeCode() const; //relative to block's time
|
||||
short GetNextTimeCode() const; //as above
|
||||
|
||||
protected:
|
||||
Cluster* const m_pCluster;
|
||||
const size_t m_index;
|
||||
long long GetPrevTimeCode() const; //relative to block's time
|
||||
long long GetNextTimeCode() const; //as above
|
||||
long long GetDuration() const;
|
||||
|
||||
private:
|
||||
BlockGroup(Cluster*, size_t, unsigned long);
|
||||
void ParseBlock(long long start, long long size);
|
||||
|
||||
short m_prevTimeCode;
|
||||
short m_nextTimeCode;
|
||||
|
||||
//TODO: the Matroska spec says you can have multiple blocks within the
|
||||
//same block group, with blocks ranked by priority (the flag bits).
|
||||
//For now we just cache a single block.
|
||||
#if 0
|
||||
typedef std::deque<Block*> blocks_t;
|
||||
blocks_t m_blocks; //In practice should contain only a single element.
|
||||
#else
|
||||
Block* m_pBlock;
|
||||
#endif
|
||||
Block m_block;
|
||||
const long long m_prev;
|
||||
const long long m_next;
|
||||
const long long m_duration;
|
||||
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// ContentEncoding element
|
||||
// Elements used to describe if the track data has been encrypted or
|
||||
// compressed with zlib or header stripping.
|
||||
class ContentEncoding {
|
||||
public:
|
||||
ContentEncoding();
|
||||
~ContentEncoding();
|
||||
|
||||
// ContentCompression element names
|
||||
struct ContentCompression {
|
||||
ContentCompression();
|
||||
~ContentCompression();
|
||||
|
||||
unsigned long long algo;
|
||||
unsigned char* settings;
|
||||
};
|
||||
|
||||
// ContentEncryption element names
|
||||
struct ContentEncryption {
|
||||
ContentEncryption();
|
||||
~ContentEncryption();
|
||||
|
||||
unsigned long long algo;
|
||||
unsigned char* key_id;
|
||||
long long key_id_len;
|
||||
unsigned char* signature;
|
||||
long long signature_len;
|
||||
unsigned char* sig_key_id;
|
||||
long long sig_key_id_len;
|
||||
unsigned long long sig_algo;
|
||||
unsigned long long sig_hash_algo;
|
||||
};
|
||||
|
||||
// Returns ContentCompression represented by |idx|. Returns NULL if |idx|
|
||||
// is out of bounds.
|
||||
const ContentCompression* GetCompressionByIndex(unsigned long idx) const;
|
||||
|
||||
// Returns number of ContentCompression elements in this ContentEncoding
|
||||
// element.
|
||||
unsigned long GetCompressionCount() const;
|
||||
|
||||
// Returns ContentEncryption represented by |idx|. Returns NULL if |idx|
|
||||
// is out of bounds.
|
||||
const ContentEncryption* GetEncryptionByIndex(unsigned long idx) const;
|
||||
|
||||
// Returns number of ContentEncryption elements in this ContentEncoding
|
||||
// element.
|
||||
unsigned long GetEncryptionCount() const;
|
||||
|
||||
// Parses the ContentEncoding element from |pReader|. |start| is the
|
||||
// starting offset of the ContentEncoding payload. |size| is the size in
|
||||
// bytes of the ContentEncoding payload. Returns true on success.
|
||||
bool ParseContentEncodingEntry(long long start,
|
||||
long long size,
|
||||
IMkvReader* const pReader);
|
||||
|
||||
// Parses the ContentEncryption element from |pReader|. |start| is the
|
||||
// starting offset of the ContentEncryption payload. |size| is the size in
|
||||
// bytes of the ContentEncryption payload. |encryption| is where the parsed
|
||||
// values will be stored.
|
||||
void ParseEncryptionEntry(long long start,
|
||||
long long size,
|
||||
IMkvReader* const pReader,
|
||||
ContentEncryption* const encryption);
|
||||
|
||||
unsigned long long encoding_order() const { return encoding_order_; }
|
||||
unsigned long long encoding_scope() const { return encoding_scope_; }
|
||||
unsigned long long encoding_type() const { return encoding_type_; }
|
||||
|
||||
private:
|
||||
// Member variables for list of ContentCompression elements.
|
||||
ContentCompression** compression_entries_;
|
||||
ContentCompression** compression_entries_end_;
|
||||
|
||||
// Member variables for list of ContentEncryption elements.
|
||||
ContentEncryption** encryption_entries_;
|
||||
ContentEncryption** encryption_entries_end_;
|
||||
|
||||
// ContentEncoding element names
|
||||
unsigned long long encoding_order_;
|
||||
unsigned long long encoding_scope_;
|
||||
unsigned long long encoding_type_;
|
||||
|
||||
// LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncoding);
|
||||
ContentEncoding(const ContentEncoding&);
|
||||
ContentEncoding& operator=(const ContentEncoding&);
|
||||
};
|
||||
|
||||
class Track
|
||||
{
|
||||
@@ -195,6 +298,8 @@ class Track
|
||||
Track& operator=(const Track&);
|
||||
|
||||
public:
|
||||
enum Type { kVideo = 1, kAudio = 2 };
|
||||
|
||||
Segment* const m_pSegment;
|
||||
const long long m_element_start;
|
||||
const long long m_element_size;
|
||||
@@ -239,12 +344,18 @@ public:
|
||||
virtual bool VetEntry(const BlockEntry*) const = 0;
|
||||
virtual long Seek(long long time_ns, const BlockEntry*&) const = 0;
|
||||
|
||||
const ContentEncoding* GetContentEncodingByIndex(unsigned long idx) const;
|
||||
unsigned long GetContentEncodingCount() const;
|
||||
|
||||
void ParseContentEncodingsEntry(long long start, long long size);
|
||||
|
||||
protected:
|
||||
Track(
|
||||
Segment*,
|
||||
const Info&,
|
||||
long long element_start,
|
||||
long long element_size);
|
||||
|
||||
const Info m_info;
|
||||
|
||||
class EOSBlock : public BlockEntry
|
||||
@@ -252,15 +363,15 @@ protected:
|
||||
public:
|
||||
EOSBlock();
|
||||
|
||||
bool EOS() const;
|
||||
const Cluster* GetCluster() const;
|
||||
size_t GetIndex() const;
|
||||
Kind GetKind() const;
|
||||
const Block* GetBlock() const;
|
||||
bool IsBFrame() const;
|
||||
};
|
||||
|
||||
EOSBlock m_eos;
|
||||
|
||||
private:
|
||||
ContentEncoding** content_encoding_entries_;
|
||||
ContentEncoding** content_encoding_entries_end_;
|
||||
};
|
||||
|
||||
|
||||
@@ -269,12 +380,20 @@ class VideoTrack : public Track
|
||||
VideoTrack(const VideoTrack&);
|
||||
VideoTrack& operator=(const VideoTrack&);
|
||||
|
||||
public:
|
||||
VideoTrack(
|
||||
Segment*,
|
||||
const Info&,
|
||||
long long element_start,
|
||||
long long element_size);
|
||||
|
||||
public:
|
||||
static long Parse(
|
||||
Segment*,
|
||||
const Info&,
|
||||
long long element_start,
|
||||
long long element_size,
|
||||
VideoTrack*&);
|
||||
|
||||
long long GetWidth() const;
|
||||
long long GetHeight() const;
|
||||
double GetFrameRate() const;
|
||||
@@ -295,12 +414,19 @@ class AudioTrack : public Track
|
||||
AudioTrack(const AudioTrack&);
|
||||
AudioTrack& operator=(const AudioTrack&);
|
||||
|
||||
public:
|
||||
AudioTrack(
|
||||
Segment*,
|
||||
const Info&,
|
||||
long long element_start,
|
||||
long long element_size);
|
||||
public:
|
||||
static long Parse(
|
||||
Segment*,
|
||||
const Info&,
|
||||
long long element_start,
|
||||
long long element_size,
|
||||
AudioTrack*&);
|
||||
|
||||
double GetSamplingRate() const;
|
||||
long long GetChannels() const;
|
||||
long long GetBitDepth() const;
|
||||
@@ -332,7 +458,12 @@ public:
|
||||
long long size,
|
||||
long long element_start,
|
||||
long long element_size);
|
||||
virtual ~Tracks();
|
||||
|
||||
~Tracks();
|
||||
|
||||
long Parse();
|
||||
|
||||
unsigned long GetTracksCount() const;
|
||||
|
||||
const Track* GetTrackByNumber(unsigned long tn) const;
|
||||
const Track* GetTrackByIndex(unsigned long idx) const;
|
||||
@@ -341,15 +472,13 @@ private:
|
||||
Track** m_trackEntries;
|
||||
Track** m_trackEntriesEnd;
|
||||
|
||||
void ParseTrackEntry(
|
||||
long long,
|
||||
long long,
|
||||
Track*&,
|
||||
long ParseTrackEntry(
|
||||
long long payload_start,
|
||||
long long payload_size,
|
||||
long long element_start,
|
||||
long long element_size);
|
||||
long long element_size,
|
||||
Track*&) const;
|
||||
|
||||
public:
|
||||
unsigned long GetTracksCount() const;
|
||||
};
|
||||
|
||||
|
||||
@@ -371,7 +500,11 @@ public:
|
||||
long long size,
|
||||
long long element_start,
|
||||
long long element_size);
|
||||
|
||||
~SegmentInfo();
|
||||
|
||||
long Parse();
|
||||
|
||||
long long GetTimeCodeScale() const;
|
||||
long long GetDuration() const; //scaled
|
||||
const char* GetMuxingAppAsUTF8() const;
|
||||
@@ -386,12 +519,79 @@ private:
|
||||
char* m_pTitleAsUTF8;
|
||||
};
|
||||
|
||||
|
||||
class SeekHead
|
||||
{
|
||||
SeekHead(const SeekHead&);
|
||||
SeekHead& operator=(const SeekHead&);
|
||||
|
||||
public:
|
||||
Segment* const m_pSegment;
|
||||
const long long m_start;
|
||||
const long long m_size;
|
||||
const long long m_element_start;
|
||||
const long long m_element_size;
|
||||
|
||||
SeekHead(
|
||||
Segment*,
|
||||
long long start,
|
||||
long long size,
|
||||
long long element_start,
|
||||
long long element_size);
|
||||
|
||||
~SeekHead();
|
||||
|
||||
long Parse();
|
||||
|
||||
struct Entry
|
||||
{
|
||||
//the SeekHead entry payload
|
||||
long long id;
|
||||
long long pos;
|
||||
|
||||
//absolute pos of SeekEntry ID
|
||||
long long element_start;
|
||||
|
||||
//SeekEntry ID size + size size + payload
|
||||
long long element_size;
|
||||
};
|
||||
|
||||
int GetCount() const;
|
||||
const Entry* GetEntry(int idx) const;
|
||||
|
||||
struct VoidElement
|
||||
{
|
||||
//absolute pos of Void ID
|
||||
long long element_start;
|
||||
|
||||
//ID size + size size + payload size
|
||||
long long element_size;
|
||||
};
|
||||
|
||||
int GetVoidElementCount() const;
|
||||
const VoidElement* GetVoidElement(int idx) const;
|
||||
|
||||
private:
|
||||
Entry* m_entries;
|
||||
int m_entry_count;
|
||||
|
||||
VoidElement* m_void_elements;
|
||||
int m_void_element_count;
|
||||
|
||||
static bool ParseEntry(
|
||||
IMkvReader*,
|
||||
long long pos, //payload
|
||||
long long size,
|
||||
Entry*);
|
||||
|
||||
};
|
||||
|
||||
class Cues;
|
||||
class CuePoint
|
||||
{
|
||||
friend class Cues;
|
||||
|
||||
CuePoint(size_t, long long);
|
||||
CuePoint(long, long long);
|
||||
~CuePoint();
|
||||
|
||||
CuePoint(const CuePoint&);
|
||||
@@ -404,7 +604,7 @@ public:
|
||||
void Load(IMkvReader*);
|
||||
|
||||
long long GetTimeCode() const; //absolute but unscaled
|
||||
long long GetTime(Segment*) const; //absolute and scaled (ns units)
|
||||
long long GetTime(const Segment*) const; //absolute and scaled (ns units)
|
||||
|
||||
struct TrackPosition
|
||||
{
|
||||
@@ -421,7 +621,7 @@ public:
|
||||
const TrackPosition* Find(const Track*) const;
|
||||
|
||||
private:
|
||||
const size_t m_index;
|
||||
const long m_index;
|
||||
long long m_timecode;
|
||||
TrackPosition* m_track_positions;
|
||||
size_t m_track_positions_count;
|
||||
@@ -473,14 +673,18 @@ public:
|
||||
const CuePoint*,
|
||||
const CuePoint::TrackPosition*) const;
|
||||
|
||||
bool LoadCuePoint() const;
|
||||
long GetCount() const; //loaded only
|
||||
//long GetTotal() const; //loaded + preloaded
|
||||
bool DoneParsing() const;
|
||||
|
||||
private:
|
||||
void Init() const;
|
||||
bool LoadCuePoint() const;
|
||||
void PreloadCuePoint(size_t&, long long) const;
|
||||
void PreloadCuePoint(long&, long long) const;
|
||||
|
||||
mutable CuePoint** m_cue_points;
|
||||
mutable size_t m_count;
|
||||
mutable size_t m_preload_count;
|
||||
mutable long m_count;
|
||||
mutable long m_preload_count;
|
||||
mutable long long m_pos;
|
||||
|
||||
};
|
||||
@@ -488,6 +692,8 @@ private:
|
||||
|
||||
class Cluster
|
||||
{
|
||||
friend class Segment;
|
||||
|
||||
Cluster(const Cluster&);
|
||||
Cluster& operator=(const Cluster&);
|
||||
|
||||
@@ -495,12 +701,11 @@ public:
|
||||
Segment* const m_pSegment;
|
||||
|
||||
public:
|
||||
static Cluster* Parse(
|
||||
static Cluster* Create(
|
||||
Segment*,
|
||||
long,
|
||||
long long off,
|
||||
long long element_start,
|
||||
long long element_size);
|
||||
long index, //index in segment
|
||||
long long off); //offset relative to segment
|
||||
//long long element_size);
|
||||
|
||||
Cluster(); //EndOfStream
|
||||
~Cluster();
|
||||
@@ -512,42 +717,64 @@ public:
|
||||
long long GetFirstTime() const; //time (ns) of first (earliest) block
|
||||
long long GetLastTime() const; //time (ns) of last (latest) block
|
||||
|
||||
const BlockEntry* GetFirst() const;
|
||||
const BlockEntry* GetLast() const;
|
||||
const BlockEntry* GetNext(const BlockEntry*) const;
|
||||
long GetFirst(const BlockEntry*&) const;
|
||||
long GetLast(const BlockEntry*&) const;
|
||||
long GetNext(const BlockEntry* curr, const BlockEntry*& next) const;
|
||||
|
||||
const BlockEntry* GetEntry(const Track*, long long ns = -1) const;
|
||||
const BlockEntry* GetEntry(
|
||||
const CuePoint&,
|
||||
const CuePoint::TrackPosition&) const;
|
||||
const BlockEntry* GetMaxKey(const VideoTrack*) const;
|
||||
//const BlockEntry* GetMaxKey(const VideoTrack*) const;
|
||||
|
||||
static bool HasBlockEntries(const Segment*, long long);
|
||||
void Load() const;
|
||||
// static bool HasBlockEntries(const Segment*, long long);
|
||||
|
||||
static long HasBlockEntries(
|
||||
const Segment*,
|
||||
long long idoff,
|
||||
long long& pos,
|
||||
long& size);
|
||||
|
||||
long GetEntryCount() const;
|
||||
|
||||
long Load(long long& pos, long& size) const;
|
||||
|
||||
long Parse(long long& pos, long& size) const;
|
||||
long GetEntry(long index, const mkvparser::BlockEntry*&) const;
|
||||
|
||||
protected:
|
||||
Cluster(
|
||||
Segment*,
|
||||
long,
|
||||
long long off,
|
||||
long long element_start,
|
||||
long long element_size);
|
||||
long index,
|
||||
long long element_start);
|
||||
//long long element_size);
|
||||
|
||||
public:
|
||||
//TODO: these should all be private, with public selector functions
|
||||
long m_index;
|
||||
mutable long long m_pos;
|
||||
mutable long long m_size;
|
||||
const long long m_element_start;
|
||||
const long long m_element_size;
|
||||
long long GetPosition() const; //offset relative to segment
|
||||
|
||||
long GetIndex() const;
|
||||
long long GetElementSize() const;
|
||||
//long long GetPayloadSize() const;
|
||||
|
||||
//long long Unparsed() const;
|
||||
|
||||
private:
|
||||
long m_index;
|
||||
mutable long long m_pos;
|
||||
//mutable long long m_size;
|
||||
mutable long long m_element_size;
|
||||
mutable long long m_timecode;
|
||||
mutable BlockEntry** m_entries;
|
||||
mutable long m_entries_size;
|
||||
mutable long m_entries_count;
|
||||
|
||||
void LoadBlockEntries() const;
|
||||
void ParseBlockGroup(long long, long long, size_t) const;
|
||||
void ParseSimpleBlock(long long, long long, size_t) const;
|
||||
long ParseSimpleBlock(long long, long long&, long&);
|
||||
long ParseBlockGroup(long long, long long&, long&);
|
||||
|
||||
long CreateBlock(long long id, long long pos, long long size);
|
||||
long CreateBlockGroup(long long, long long);
|
||||
long CreateSimpleBlock(long long, long long);
|
||||
|
||||
};
|
||||
|
||||
@@ -562,10 +789,17 @@ class Segment
|
||||
Segment& operator=(const Segment&);
|
||||
|
||||
private:
|
||||
Segment(IMkvReader*, long long pos, long long size);
|
||||
Segment(
|
||||
IMkvReader*,
|
||||
long long elem_start,
|
||||
//long long elem_size,
|
||||
long long pos,
|
||||
long long size);
|
||||
|
||||
public:
|
||||
IMkvReader* const m_pReader;
|
||||
const long long m_element_start;
|
||||
//const long long m_element_size;
|
||||
const long long m_start; //posn of segment payload
|
||||
const long long m_size; //size of segment payload
|
||||
Cluster m_eos; //TODO: make private?
|
||||
@@ -576,7 +810,8 @@ public:
|
||||
long Load(); //loads headers and all clusters
|
||||
|
||||
//for incremental loading
|
||||
long long Unparsed() const;
|
||||
//long long Unparsed() const;
|
||||
bool DoneParsing() const;
|
||||
long long ParseHeaders(); //stops when first cluster is found
|
||||
//long FindNextCluster(long long& pos, long& size) const;
|
||||
long LoadCluster(long long& pos, long& size); //load one cluster
|
||||
@@ -588,12 +823,15 @@ public:
|
||||
long long& pos,
|
||||
long& size);
|
||||
|
||||
#if 0
|
||||
//This pair parses one cluster, but only changes the state of the
|
||||
//segment object when the cluster is actually added to the index.
|
||||
long ParseCluster(long long& cluster_pos, long long& new_pos) const;
|
||||
bool AddCluster(long long cluster_pos, long long new_pos);
|
||||
#endif
|
||||
|
||||
Tracks* GetTracks() const;
|
||||
const SeekHead* GetSeekHead() const;
|
||||
const Tracks* GetTracks() const;
|
||||
const SegmentInfo* GetInfo() const;
|
||||
const Cues* GetCues() const;
|
||||
|
||||
@@ -607,9 +845,19 @@ public:
|
||||
const Cluster* FindCluster(long long time_nanoseconds) const;
|
||||
//const BlockEntry* Seek(long long time_nanoseconds, const Track*) const;
|
||||
|
||||
const Cluster* FindOrPreloadCluster(long long pos);
|
||||
|
||||
long ParseCues(
|
||||
long long cues_off, //offset relative to start of segment
|
||||
long long& parse_pos,
|
||||
long& parse_len);
|
||||
|
||||
private:
|
||||
|
||||
long long m_pos; //absolute file posn; what has been consumed so far
|
||||
Cluster* m_pUnknownSize;
|
||||
|
||||
SeekHead* m_pSeekHead;
|
||||
SegmentInfo* m_pInfo;
|
||||
Tracks* m_pTracks;
|
||||
Cues* m_pCues;
|
||||
@@ -618,12 +866,16 @@ private:
|
||||
long m_clusterPreloadCount; //number of entries for which m_index < 0
|
||||
long m_clusterSize; //array size
|
||||
|
||||
long DoLoadCluster(long long&, long&);
|
||||
long DoLoadClusterUnknownSize(long long&, long&);
|
||||
long DoParseNext(const Cluster*&, long long&, long&);
|
||||
|
||||
void AppendCluster(Cluster*);
|
||||
void PreloadCluster(Cluster*, ptrdiff_t);
|
||||
|
||||
void ParseSeekHead(long long pos, long long size);
|
||||
void ParseSeekEntry(long long pos, long long size);
|
||||
void ParseCues(long long);
|
||||
//void ParseSeekHead(long long pos, long long size);
|
||||
//void ParseSeekEntry(long long pos, long long size);
|
||||
//void ParseCues(long long);
|
||||
|
||||
const BlockEntry* GetBlock(
|
||||
const CuePoint&,
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mkvparser", "mkvparser_2008.vcproj", "{F9128EC6-C008-41AD-B38F-0E70D549D9F4}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample", "sample_2008.vcproj", "{0CB5681F-6065-490C-98C8-05531732ED7E}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{F9128EC6-C008-41AD-B38F-0E70D549D9F4} = {F9128EC6-C008-41AD-B38F-0E70D549D9F4}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{F9128EC6-C008-41AD-B38F-0E70D549D9F4}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{F9128EC6-C008-41AD-B38F-0E70D549D9F4}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{F9128EC6-C008-41AD-B38F-0E70D549D9F4}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{F9128EC6-C008-41AD-B38F-0E70D549D9F4}.Release|Win32.Build.0 = Release|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|Win32.ActiveCfg = Release|Win32
|
||||
{0CB5681F-6065-490C-98C8-05531732ED7E}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -10,6 +10,9 @@
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace mkvparser
|
||||
{
|
||||
|
||||
MkvReader::MkvReader() :
|
||||
m_file(NULL)
|
||||
{
|
||||
@@ -121,3 +124,5 @@ int MkvReader::Read(long long offset, long len, unsigned char* buffer)
|
||||
|
||||
return 0; //success
|
||||
}
|
||||
|
||||
} //end namespace mkvparser
|
||||
|
||||
@@ -12,7 +12,10 @@
|
||||
#include "mkvparser.hpp"
|
||||
#include <cstdio>
|
||||
|
||||
class MkvReader : public mkvparser::IMkvReader
|
||||
namespace mkvparser
|
||||
{
|
||||
|
||||
class MkvReader : public IMkvReader
|
||||
{
|
||||
MkvReader(const MkvReader&);
|
||||
MkvReader& operator=(const MkvReader&);
|
||||
@@ -31,4 +34,6 @@ private:
|
||||
FILE* m_file;
|
||||
};
|
||||
|
||||
} //end namespace mkvparser
|
||||
|
||||
#endif //MKVREADER_HPP
|
||||
|
||||
94
mkvwriter.cpp
Normal file
94
mkvwriter.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
// Copyright (c) 2011 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 "mkvwriter.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <share.h> // for _SH_DENYWR
|
||||
#endif
|
||||
|
||||
#include <new>
|
||||
|
||||
namespace mkvmuxer {
|
||||
|
||||
MkvWriter::MkvWriter() : file_(NULL) {
|
||||
}
|
||||
|
||||
MkvWriter::~MkvWriter() {
|
||||
Close();
|
||||
}
|
||||
|
||||
int32 MkvWriter::Write(const void* buffer, uint32 length) {
|
||||
if (!file_)
|
||||
return -1;
|
||||
|
||||
if (length == 0)
|
||||
return 0;
|
||||
|
||||
if (buffer == NULL)
|
||||
return -1;
|
||||
|
||||
const size_t bytes_written = fwrite(buffer, 1, length, file_);
|
||||
|
||||
return (bytes_written == length) ? 0 : -1;
|
||||
}
|
||||
|
||||
bool MkvWriter::Open(const char* filename) {
|
||||
if (filename == NULL)
|
||||
return false;
|
||||
|
||||
if (file_)
|
||||
return false;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
file_ = _fsopen(filename, "wb", _SH_DENYWR);
|
||||
#else
|
||||
file_ = fopen(filename, "wb");
|
||||
#endif
|
||||
if (file_ == NULL)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void MkvWriter::Close() {
|
||||
if (file_) {
|
||||
fclose(file_);
|
||||
file_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int64 MkvWriter::Position() const {
|
||||
if (!file_)
|
||||
return 0;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
return _ftelli64(file_);
|
||||
#else
|
||||
return ftell(file_);
|
||||
#endif
|
||||
}
|
||||
|
||||
int32 MkvWriter::Position(int64 position) {
|
||||
if (!file_)
|
||||
return -1;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
return _fseeki64(file_, position, SEEK_SET);
|
||||
#else
|
||||
return fseek(file_, position, SEEK_SET);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool MkvWriter::Seekable() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void MkvWriter::ElementStartNotify(uint64, int64) {
|
||||
}
|
||||
|
||||
} // namespace mkvmuxer
|
||||
49
mkvwriter.hpp
Normal file
49
mkvwriter.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
// 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.
|
||||
|
||||
#ifndef MKVWRITER_HPP
|
||||
#define MKVWRITER_HPP
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "mkvmuxer.hpp"
|
||||
#include "mkvmuxertypes.hpp"
|
||||
|
||||
namespace mkvmuxer {
|
||||
|
||||
// Default implementation of the IMkvWriter interface on Windows.
|
||||
class MkvWriter : public IMkvWriter {
|
||||
public:
|
||||
MkvWriter();
|
||||
virtual ~MkvWriter();
|
||||
|
||||
// IMkvWriter interface
|
||||
virtual int64 Position() const;
|
||||
virtual int32 Position(int64 position);
|
||||
virtual bool Seekable() const;
|
||||
virtual int32 Write(const void* buffer, uint32 length);
|
||||
virtual void ElementStartNotify(uint64 element_id, int64 position);
|
||||
|
||||
// Creates and opens a file for writing. |filename| is the name of the file
|
||||
// to open. This function will overwrite the contents of |filename|. Returns
|
||||
// true on success.
|
||||
bool Open(const char* filename);
|
||||
|
||||
// Closes an opened file.
|
||||
void Close();
|
||||
|
||||
private:
|
||||
// File handle to output file.
|
||||
FILE* file_;
|
||||
|
||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(MkvWriter);
|
||||
};
|
||||
|
||||
} //end namespace mkvmuxer
|
||||
|
||||
#endif // MKVWRITER_HPP
|
||||
76
sample.cpp
76
sample.cpp
@@ -11,6 +11,17 @@
|
||||
|
||||
#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)
|
||||
#endif
|
||||
|
||||
static const wchar_t* utf8towcs(const char* str)
|
||||
{
|
||||
@@ -73,15 +84,18 @@ int main(int argc, char* argv[])
|
||||
printf("\t\tDoc Type\t\t: %s\n", ebmlHeader.m_docType);
|
||||
printf("\t\tPos\t\t\t: %lld\n", pos);
|
||||
|
||||
mkvparser::Segment* pSegment;
|
||||
typedef mkvparser::Segment seg_t;
|
||||
seg_t* pSegment_;
|
||||
|
||||
long long ret = mkvparser::Segment::CreateInstance(&reader, pos, pSegment);
|
||||
long long ret = seg_t::CreateInstance(&reader, pos, pSegment_);
|
||||
if (ret)
|
||||
{
|
||||
printf("\n Segment::CreateInstance() failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
const std::auto_ptr<seg_t> pSegment(pSegment_);
|
||||
|
||||
ret = pSegment->Load();
|
||||
if (ret < 0)
|
||||
{
|
||||
@@ -142,7 +156,7 @@ int main(int argc, char* argv[])
|
||||
// size of segment payload
|
||||
printf("\t\tSize(Segment)\t\t: %lld\n", pSegment->m_size);
|
||||
|
||||
mkvparser::Tracks* const pTracks = pSegment->GetTracks();
|
||||
const mkvparser::Tracks* pTracks = pSegment->GetTracks();
|
||||
|
||||
unsigned long i = 0;
|
||||
const unsigned long j = pTracks->GetTracksCount();
|
||||
@@ -232,7 +246,6 @@ int main(int argc, char* argv[])
|
||||
if (clusterCount == 0)
|
||||
{
|
||||
printf("\t\tSegment has no clusters.\n");
|
||||
delete pSegment;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -246,7 +259,16 @@ int main(int argc, char* argv[])
|
||||
const long long time_ns = pCluster->GetTime();
|
||||
printf("\t\tCluster Time (ns)\t: %lld\n", time_ns);
|
||||
|
||||
const BlockEntry* pBlockEntry = pCluster->GetFirst();
|
||||
const BlockEntry* pBlockEntry;
|
||||
|
||||
long status = pCluster->GetFirst(pBlockEntry);
|
||||
|
||||
if (status < 0) //error
|
||||
{
|
||||
printf("\t\tError parsing first block of cluster\n");
|
||||
fflush(stdout);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((pBlockEntry != NULL) && !pBlockEntry->EOS())
|
||||
{
|
||||
@@ -254,30 +276,42 @@ int main(int argc, char* argv[])
|
||||
const long long trackNum = pBlock->GetTrackNumber();
|
||||
const unsigned long tn = static_cast<unsigned long>(trackNum);
|
||||
const Track* const pTrack = pTracks->GetTrackByNumber(tn);
|
||||
const long long trackType = pTrack->GetType();
|
||||
const int frameCount = pBlock->GetFrameCount();
|
||||
const long long time_ns = pBlock->GetTime(pCluster);
|
||||
|
||||
printf("\t\t\tBlock\t\t:%s,%s,%15lld\n",
|
||||
(trackType == VIDEO_TRACK) ? "V" : "A",
|
||||
pBlock->IsKey() ? "I" : "P",
|
||||
time_ns);
|
||||
|
||||
for (int i = 0; i < frameCount; ++i)
|
||||
if (pTrack == NULL)
|
||||
printf("\t\t\tBlock\t\t:UNKNOWN TRACK TYPE\n");
|
||||
else
|
||||
{
|
||||
const Block::Frame& theFrame = pBlock->GetFrame(i);
|
||||
const long size = theFrame.len;
|
||||
const long long offset = theFrame.pos;
|
||||
printf("\t\t\t %15ld,%15llx\n", size, offset);
|
||||
const long long trackType = pTrack->GetType();
|
||||
const int frameCount = pBlock->GetFrameCount();
|
||||
const long long time_ns = pBlock->GetTime(pCluster);
|
||||
|
||||
printf("\t\t\tBlock\t\t:%s,%s,%15lld\n",
|
||||
(trackType == VIDEO_TRACK) ? "V" : "A",
|
||||
pBlock->IsKey() ? "I" : "P",
|
||||
time_ns);
|
||||
|
||||
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;
|
||||
printf("\t\t\t %15ld,%15llx\n", size, offset);
|
||||
}
|
||||
}
|
||||
|
||||
pBlockEntry = pCluster->GetNext(pBlockEntry);
|
||||
status = pCluster->GetNext(pBlockEntry, pBlockEntry);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
printf("\t\t\tError parsing next block of cluster\n");
|
||||
fflush(stdout);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
pCluster = pSegment->GetNext(pCluster);
|
||||
}
|
||||
|
||||
delete pSegment;
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -42,13 +42,13 @@
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="true"
|
||||
MinimalRebuild="false"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
@@ -61,7 +61,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies=".\Debug\mkvparser.lib"
|
||||
AdditionalDependencies=".\Debug\libwebm.lib"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
@@ -118,7 +118,7 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="2"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
@@ -135,6 +135,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies=".\Release\libwebm.lib"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies=".\Debug\mkvparser.lib"
|
||||
AdditionalDependencies=".\Debug\libwebm.lib"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
@@ -118,7 +118,7 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="2"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
@@ -135,7 +135,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies=".\Release\mkvparser.lib"
|
||||
AdditionalDependencies=".\Release\libwebm.lib"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
|
||||
397
sample_muxer/sample_muxer.cpp
Normal file
397
sample_muxer/sample_muxer.cpp
Normal file
@@ -0,0 +1,397 @@
|
||||
// Copyright (c) 2011 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 <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
// libwebm parser includes
|
||||
#include "mkvreader.hpp"
|
||||
#include "mkvparser.hpp"
|
||||
|
||||
// libwebm muxer includes
|
||||
#include "mkvmuxer.hpp"
|
||||
#include "mkvwriter.hpp"
|
||||
#include "mkvmuxerutil.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
void Usage() {
|
||||
printf("Usage: sample_muxer -i input -o output [options]\n");
|
||||
printf("\n");
|
||||
printf("Main options:\n");
|
||||
printf(" -h | -? show help\n");
|
||||
printf(" -video <int> >0 outputs video\n");
|
||||
printf(" -audio <int> >0 outputs audio\n");
|
||||
printf(" -live <int> >0 puts the muxer into live mode\n");
|
||||
printf(" 0 puts the muxer into file mode\n");
|
||||
printf(" -output_cues <int> >0 outputs cues element\n");
|
||||
printf(" -cues_on_video_track <int> >0 outputs cues on video track\n");
|
||||
printf(" -cues_on_audio_track <int> >0 outputs cues on audio track\n");
|
||||
printf(" 0 outputs cues on audio track\n");
|
||||
printf(" -max_cluster_duration <double> in seconds\n");
|
||||
printf(" -max_cluster_size <int> in bytes\n");
|
||||
printf(" -switch_tracks <int> >0 switches tracks in output\n");
|
||||
printf(" -audio_track_number <int> >0 Changes the audio track number\n");
|
||||
printf(" -video_track_number <int> >0 Changes the video track number\n");
|
||||
printf(" -chunking <string> Chunk output\n");
|
||||
printf("\n");
|
||||
printf("Video options:\n");
|
||||
printf(" -display_width <int> Display width in pixels\n");
|
||||
printf(" -display_height <int> Display height in pixels\n");
|
||||
printf(" -stereo_mode <int> 3D video mode\n");
|
||||
printf("\n");
|
||||
printf("Cues options:\n");
|
||||
printf(" -output_cues_block_number <int> >0 outputs cue block number\n");
|
||||
}
|
||||
|
||||
} //end namespace
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
using mkvmuxer::uint64;
|
||||
|
||||
char* input = NULL;
|
||||
char* output = NULL;
|
||||
|
||||
// Segment variables
|
||||
bool output_video = true;
|
||||
bool output_audio = true;
|
||||
bool live_mode = false;
|
||||
bool output_cues = true;
|
||||
bool cues_on_video_track = true;
|
||||
bool cues_on_audio_track = true;
|
||||
uint64 max_cluster_duration = 0;
|
||||
uint64 max_cluster_size = 0;
|
||||
bool switch_tracks = false;
|
||||
int audio_track_number = 0; // 0 tells muxer to decide.
|
||||
int video_track_number = 0; // 0 tells muxer to decide.
|
||||
bool chunking = false;
|
||||
const char* chunk_name = NULL;
|
||||
|
||||
bool output_cues_block_number = true;
|
||||
|
||||
uint64 display_width = 0;
|
||||
uint64 display_height = 0;
|
||||
uint64 stereo_mode = 0;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
char* end;
|
||||
|
||||
if (!strcmp("-h", argv[i]) || !strcmp("-?", argv[i])) {
|
||||
Usage();
|
||||
return EXIT_SUCCESS;
|
||||
} else if (!strcmp("-i", argv[i])) {
|
||||
input = argv[++i];
|
||||
} else if (!strcmp("-o", argv[i])) {
|
||||
output = argv[++i];
|
||||
} else if (!strcmp("-video", argv[i])) {
|
||||
output_video = strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||
} else if (!strcmp("-audio", argv[i])) {
|
||||
output_audio = strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||
} else if (!strcmp("-live", argv[i])) {
|
||||
live_mode = strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||
} else if (!strcmp("-output_cues", argv[i])) {
|
||||
output_cues = strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||
} else if (!strcmp("-cues_on_video_track", argv[i])) {
|
||||
cues_on_video_track = strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||
} else if (!strcmp("-cues_on_audio_track", argv[i])) {
|
||||
cues_on_audio_track = strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||
} else if (!strcmp("-max_cluster_duration", argv[i])) {
|
||||
const double seconds = strtod(argv[++i], &end);
|
||||
max_cluster_duration =
|
||||
static_cast<uint64>(seconds * 1000000000.0);
|
||||
} else if (!strcmp("-max_cluster_size", argv[i])) {
|
||||
max_cluster_size = strtol(argv[++i], &end, 10);
|
||||
} else if (!strcmp("-switch_tracks", argv[i])) {
|
||||
switch_tracks = strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||
} else if (!strcmp("-audio_track_number", argv[i])) {
|
||||
audio_track_number = strtol(argv[++i], &end, 10);
|
||||
} else if (!strcmp("-video_track_number", argv[i])) {
|
||||
video_track_number = strtol(argv[++i], &end, 10);
|
||||
} else if (!strcmp("-chunking", argv[i])) {
|
||||
chunking = true;
|
||||
chunk_name = argv[++i];
|
||||
} else if (!strcmp("-display_width", argv[i])) {
|
||||
display_width = strtol(argv[++i], &end, 10);
|
||||
} else if (!strcmp("-display_height", argv[i])) {
|
||||
display_height = strtol(argv[++i], &end, 10);
|
||||
} else if (!strcmp("-stereo_mode", argv[i])) {
|
||||
stereo_mode = strtol(argv[++i], &end, 10);
|
||||
} else if (!strcmp("-output_cues_block_number", argv[i])) {
|
||||
output_cues_block_number =
|
||||
strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||
}
|
||||
}
|
||||
|
||||
if (input == NULL || output == NULL) {
|
||||
Usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Get parser header info
|
||||
mkvparser::MkvReader reader;
|
||||
|
||||
if (reader.Open(input)) {
|
||||
printf("\n Filename is invalid or error while opening.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
long long pos = 0;
|
||||
mkvparser::EBMLHeader ebml_header;
|
||||
ebml_header.Parse(&reader, pos);
|
||||
|
||||
mkvparser::Segment* parser_segment;
|
||||
long long ret = mkvparser::Segment::CreateInstance(&reader,
|
||||
pos,
|
||||
parser_segment);
|
||||
if (ret) {
|
||||
printf("\n Segment::CreateInstance() failed.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
ret = parser_segment->Load();
|
||||
if (ret < 0) {
|
||||
printf("\n Segment::Load() failed.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const mkvparser::SegmentInfo* const segment_info = parser_segment->GetInfo();
|
||||
const long long timeCodeScale = segment_info->GetTimeCodeScale();
|
||||
|
||||
// Set muxer header info
|
||||
mkvmuxer::MkvWriter writer;
|
||||
|
||||
if (!writer.Open(output)) {
|
||||
printf("\n Filename is invalid or error while opening.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Set Segment element attributes
|
||||
mkvmuxer::Segment muxer_segment;
|
||||
|
||||
if (!muxer_segment.Init(&writer)) {
|
||||
printf("\n Could not initialize muxer segment!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (live_mode)
|
||||
muxer_segment.set_mode(mkvmuxer::Segment::kLive);
|
||||
else
|
||||
muxer_segment.set_mode(mkvmuxer::Segment::kFile);
|
||||
|
||||
if (chunking)
|
||||
muxer_segment.SetChunking(true, chunk_name);
|
||||
|
||||
if (max_cluster_duration > 0)
|
||||
muxer_segment.set_max_cluster_duration(max_cluster_duration);
|
||||
if (max_cluster_size > 0)
|
||||
muxer_segment.set_max_cluster_size(max_cluster_size);
|
||||
muxer_segment.OutputCues(output_cues);
|
||||
|
||||
// Set SegmentInfo element attributes
|
||||
mkvmuxer::SegmentInfo* const info = muxer_segment.GetSegmentInfo();
|
||||
info->set_timecode_scale(timeCodeScale);
|
||||
info->set_writing_app("sample_muxer");
|
||||
|
||||
// Set Tracks element attributes
|
||||
enum { kVideoTrack = 1, kAudioTrack = 2 };
|
||||
const mkvparser::Tracks* const parser_tracks = parser_segment->GetTracks();
|
||||
unsigned long i = 0;
|
||||
uint64 vid_track = 0; // no track added
|
||||
uint64 aud_track = 0; // no track added
|
||||
|
||||
while (i != parser_tracks->GetTracksCount()) {
|
||||
int track_num = i++;
|
||||
if (switch_tracks)
|
||||
track_num = i % parser_tracks->GetTracksCount();
|
||||
|
||||
const mkvparser::Track* const parser_track =
|
||||
parser_tracks->GetTrackByIndex(track_num);
|
||||
|
||||
if (parser_track == NULL)
|
||||
continue;
|
||||
|
||||
// TODO(fgalligan): Add support for language to parser.
|
||||
const char* const track_name = parser_track->GetNameAsUTF8();
|
||||
|
||||
const long long track_type = parser_track->GetType();
|
||||
|
||||
if (track_type == kVideoTrack && output_video) {
|
||||
// Get the video track from the parser
|
||||
const mkvparser::VideoTrack* const pVideoTrack =
|
||||
static_cast<const mkvparser::VideoTrack*>(parser_track);
|
||||
const long long width = pVideoTrack->GetWidth();
|
||||
const long long height = pVideoTrack->GetHeight();
|
||||
|
||||
// Add the video track to the muxer
|
||||
vid_track = muxer_segment.AddVideoTrack(static_cast<int>(width),
|
||||
static_cast<int>(height),
|
||||
video_track_number);
|
||||
if (!vid_track) {
|
||||
printf("\n Could not add video track.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
mkvmuxer::VideoTrack* const video =
|
||||
static_cast<mkvmuxer::VideoTrack*>(
|
||||
muxer_segment.GetTrackByNumber(vid_track));
|
||||
if (!video) {
|
||||
printf("\n Could not get video track.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (track_name)
|
||||
video->set_name(track_name);
|
||||
|
||||
if (display_width > 0)
|
||||
video->set_display_width(display_width);
|
||||
if (display_height > 0)
|
||||
video->set_display_height(display_height);
|
||||
if (stereo_mode > 0)
|
||||
video->SetStereoMode(stereo_mode);
|
||||
|
||||
const double rate = pVideoTrack->GetFrameRate();
|
||||
if (rate > 0.0) {
|
||||
video->set_frame_rate(rate);
|
||||
}
|
||||
} else if (track_type == kAudioTrack && output_audio) {
|
||||
// Get the audio track from the parser
|
||||
const mkvparser::AudioTrack* const pAudioTrack =
|
||||
static_cast<const mkvparser::AudioTrack*>(parser_track);
|
||||
const long long channels = pAudioTrack->GetChannels();
|
||||
const double sample_rate = pAudioTrack->GetSamplingRate();
|
||||
|
||||
// Add the audio track to the muxer
|
||||
aud_track = muxer_segment.AddAudioTrack(static_cast<int>(sample_rate),
|
||||
static_cast<int>(channels),
|
||||
audio_track_number);
|
||||
if (!aud_track) {
|
||||
printf("\n Could not add audio track.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
mkvmuxer::AudioTrack* const audio =
|
||||
static_cast<mkvmuxer::AudioTrack*>(
|
||||
muxer_segment.GetTrackByNumber(aud_track));
|
||||
if (!audio) {
|
||||
printf("\n Could not get audio track.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (track_name)
|
||||
audio->set_name(track_name);
|
||||
|
||||
size_t private_size;
|
||||
const unsigned char* const private_data =
|
||||
pAudioTrack->GetCodecPrivate(private_size);
|
||||
if (private_size > 0) {
|
||||
if (!audio->SetCodecPrivate(private_data, private_size)) {
|
||||
printf("\n Could not add audio private data.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
const long long bit_depth = pAudioTrack->GetBitDepth();
|
||||
if (bit_depth > 0)
|
||||
audio->set_bit_depth(bit_depth);
|
||||
}
|
||||
}
|
||||
|
||||
// Set Cues element attributes
|
||||
mkvmuxer::Cues* const cues = muxer_segment.GetCues();
|
||||
cues->set_output_block_number(output_cues_block_number);
|
||||
if (cues_on_video_track && vid_track)
|
||||
muxer_segment.CuesTrack(vid_track);
|
||||
if (cues_on_audio_track && aud_track)
|
||||
muxer_segment.CuesTrack(aud_track);
|
||||
|
||||
// Write clusters
|
||||
unsigned char* data = NULL;
|
||||
int data_len = 0;
|
||||
|
||||
const mkvparser::Cluster* cluster = parser_segment->GetFirst();
|
||||
|
||||
while ((cluster != NULL) && !cluster->EOS()) {
|
||||
const mkvparser::BlockEntry* block_entry;
|
||||
|
||||
long status = cluster->GetFirst(block_entry);
|
||||
|
||||
if (status)
|
||||
{
|
||||
printf("\n Could not get first block of cluster.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
while ((block_entry != NULL) && !block_entry->EOS()) {
|
||||
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));
|
||||
const long long track_type = parser_track->GetType();
|
||||
|
||||
if ((track_type == kAudioTrack && output_audio) ||
|
||||
(track_type == kVideoTrack && output_video)) {
|
||||
const int frame_count = block->GetFrameCount();
|
||||
const long long time_ns = block->GetTime(cluster);
|
||||
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;
|
||||
data = new unsigned char[frame.len];
|
||||
if (!data)
|
||||
return EXIT_FAILURE;
|
||||
data_len = frame.len;
|
||||
}
|
||||
|
||||
if (frame.Read(&reader, data))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
uint64 track_num = vid_track;
|
||||
if (track_type == kAudioTrack)
|
||||
track_num = aud_track;
|
||||
|
||||
if (!muxer_segment.AddFrame(data,
|
||||
frame.len,
|
||||
track_num,
|
||||
time_ns,
|
||||
is_key)) {
|
||||
printf("\n Could not add frame.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
status = cluster->GetNext(block_entry, block_entry);
|
||||
|
||||
if (status)
|
||||
{
|
||||
printf("\n Could not get next block of cluster.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
cluster = parser_segment->GetNext(cluster);
|
||||
}
|
||||
|
||||
muxer_segment.Finalize();
|
||||
|
||||
delete [] data;
|
||||
delete parser_segment;
|
||||
|
||||
writer.Close();
|
||||
reader.Close();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
197
sample_muxer/sample_muxer.vcproj
Normal file
197
sample_muxer/sample_muxer.vcproj
Normal file
@@ -0,0 +1,197 @@
|
||||
<?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="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(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="..\Debug\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="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(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="..\Release\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>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\sample_muxer.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
117
webmids.hpp
Normal file
117
webmids.hpp
Normal file
@@ -0,0 +1,117 @@
|
||||
// Copyright (c) 2011 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 WEBMIDS_HPP
|
||||
#define WEBMIDS_HPP
|
||||
|
||||
namespace mkvmuxer {
|
||||
|
||||
enum MkvId {
|
||||
kMkvEBML = 0x1A45DFA3,
|
||||
kMkvEBMLVersion = 0x4286,
|
||||
kMkvEBMLReadVersion = 0x42F7,
|
||||
kMkvEBMLMaxIDLength = 0x42F2,
|
||||
kMkvEBMLMaxSizeLength = 0x42F3,
|
||||
kMkvDocType = 0x4282,
|
||||
kMkvDocTypeVersion = 0x4287,
|
||||
kMkvDocTypeReadVersion = 0x4285,
|
||||
kMkvVoid = 0xEC,
|
||||
kMkvSignatureSlot = 0x1B538667,
|
||||
kMkvSignatureAlgo = 0x7E8A,
|
||||
kMkvSignatureHash = 0x7E9A,
|
||||
kMkvSignaturePublicKey = 0x7EA5,
|
||||
kMkvSignature = 0x7EB5,
|
||||
kMkvSignatureElements = 0x7E5B,
|
||||
kMkvSignatureElementList = 0x7E7B,
|
||||
kMkvSignedElement = 0x6532,
|
||||
//segment
|
||||
kMkvSegment = 0x18538067,
|
||||
//Meta Seek Information
|
||||
kMkvSeekHead = 0x114D9B74,
|
||||
kMkvSeek = 0x4DBB,
|
||||
kMkvSeekID = 0x53AB,
|
||||
kMkvSeekPosition = 0x53AC,
|
||||
//Segment Information
|
||||
kMkvInfo = 0x1549A966,
|
||||
kMkvTimecodeScale = 0x2AD7B1,
|
||||
kMkvDuration = 0x4489,
|
||||
kMkvDateUTC = 0x4461,
|
||||
kMkvMuxingApp = 0x4D80,
|
||||
kMkvWritingApp = 0x5741,
|
||||
//Cluster
|
||||
kMkvCluster = 0x1F43B675,
|
||||
kMkvTimecode = 0xE7,
|
||||
kMkvPrevSize = 0xAB,
|
||||
kMkvBlockGroup = 0xA0,
|
||||
kMkvBlock = 0xA1,
|
||||
kMkvBlockDuration = 0x9B,
|
||||
kMkvReferenceBlock = 0xFB,
|
||||
kMkvLaceNumber = 0xCC,
|
||||
kMkvSimpleBlock = 0xA3,
|
||||
//Track
|
||||
kMkvTracks = 0x1654AE6B,
|
||||
kMkvTrackEntry = 0xAE,
|
||||
kMkvTrackNumber = 0xD7,
|
||||
kMkvTrackUID = 0x73C5,
|
||||
kMkvTrackType = 0x83,
|
||||
kMkvFlagEnabled = 0xB9,
|
||||
kMkvFlagDefault = 0x88,
|
||||
kMkvFlagForced = 0x55AA,
|
||||
kMkvFlagLacing = 0x9C,
|
||||
kMkvDefaultDuration = 0x23E383,
|
||||
kMkvName = 0x536E,
|
||||
kMkvLanguage = 0x22B59C,
|
||||
kMkvCodecID = 0x86,
|
||||
kMkvCodecPrivate = 0x63A2,
|
||||
kMkvCodecName = 0x258688,
|
||||
//video
|
||||
kMkvVideo = 0xE0,
|
||||
kMkvFlagInterlaced = 0x9A,
|
||||
kMkvStereoMode = 0x53B8,
|
||||
kMkvPixelWidth = 0xB0,
|
||||
kMkvPixelHeight = 0xBA,
|
||||
kMkvPixelCropBottom = 0x54AA,
|
||||
kMkvPixelCropTop = 0x54BB,
|
||||
kMkvPixelCropLeft = 0x54CC,
|
||||
kMkvPixelCropRight = 0x54DD,
|
||||
kMkvDisplayWidth = 0x54B0,
|
||||
kMkvDisplayHeight = 0x54BA,
|
||||
kMkvDisplayUnit = 0x54B2,
|
||||
kMkvAspectRatioType = 0x54B3,
|
||||
kMkvFrameRate = 0x2383E3,
|
||||
//end video
|
||||
//audio
|
||||
kMkvAudio = 0xE1,
|
||||
kMkvSamplingFrequency = 0xB5,
|
||||
kMkvOutputSamplingFrequency = 0x78B5,
|
||||
kMkvChannels = 0x9F,
|
||||
kMkvBitDepth = 0x6264,
|
||||
//end audio
|
||||
//ContentEncodings
|
||||
kMkvContentEncodings = 0x6D80,
|
||||
kMkvContentEncoding = 0x6240,
|
||||
kMkvContentEncodingOrder = 0x5031,
|
||||
kMkvContentEncodingScope = 0x5032,
|
||||
kMkvContentEncodingType = 0x5033,
|
||||
kMkvContentEncryption = 0x5035,
|
||||
kMkvContentEncAlgo = 0x47E1,
|
||||
kMkvContentEncKeyID = 0x47E2,
|
||||
//end ContentEncodings
|
||||
//Cueing Data
|
||||
kMkvCues = 0x1C53BB6B,
|
||||
kMkvCuePoint = 0xBB,
|
||||
kMkvCueTime = 0xB3,
|
||||
kMkvCueTrackPositions = 0xB7,
|
||||
kMkvCueTrack = 0xF7,
|
||||
kMkvCueClusterPosition = 0xF1,
|
||||
kMkvCueBlockNumber = 0x5378,
|
||||
};
|
||||
|
||||
} // end namespace mkvmuxer
|
||||
|
||||
#endif // WEBMIDS_HPP
|
||||
Reference in New Issue
Block a user