Compare commits

...

79 Commits

Author SHA1 Message Date
matthewjheaney
f031dc1731 preliminary work on parser class
Change-Id: I792fd2a0f08f5383574f583b55e867056db36efe
2012-03-02 19:04:27 -05:00
matthewjheaney
274c641666 initial revision
Change-Id: I31cc4d08f7d5230e97750766414f28774481ab8c
2012-03-02 18:36:50 -05:00
matthewjheaney
6fa7c7611c Block parsing is now robust
Previously, parsing of a Block element was done inside its
constructor.  Parsing errors were handled via assertion checks,
but this only works in practice if there are no actual errors
in the file.

We did come across a file, however, that used EMBL-style lacing,
but the lacing was done incorrectly and so the parse asserted.
This isn't acceptable for a production system, and more a graceful
handling of parse errors was needed.

The code was restructured such that the Block object's ctor does
only trivial initialization of member variables.  A separate Parse
method was added, that is called after the object is constructed.
If the parse succeeds all is well, otherwise the object is destroyed
and the error is reported to the caller.

This commit fixes bug tracker issue #398, described here:

http://code.google.com/p/webm/issues/detail?id=398

Change-Id: Ib95ca95d0eec08cf670b308c461e42ed8345e890
2012-02-28 14:03:21 -05:00
matthewjheaney
71d296e44c Merge "mkvparser: overflow in biased count of laced frames" 2012-02-23 18:07:34 -08:00
matthewjheaney
72052ed8b1 mkvparser: overflow in biased count of laced frames
Change-Id: I946b233d559186fc8a24d0769607075333598191
2012-02-23 13:33:46 -05:00
Frank Galligan
a88d62b682 Fix muxer output with no Cues.
- Fixed a bug with the muxer where it would generate a entry in
  the SeekHead for a Cues element with OutputCues set to false.
- Fixed a bug with the muxer where it would generate an empty
  Cues element with OutputCues set to false.
- Issue:http://code.google.com/p/webm/issues/detail?id=383

Change-Id: I99cc404a7e8ad61759dbb57ab769625dd724240c
2012-02-16 16:34:59 -05:00
Frank Galligan
28d54555a7 Fix for audio and video track size calculation.
- There was a bug where the calculation for the audio and video
track size where the code would calculate the size of the track
elements minus the size of the audio or video elements. If the
coded size of the track elements was one byte smaller than with
the audio or video elements then the muxer would return an
error.
- Fixed another issue that the track's virtual Size function was
calling the Track's PayloadSize function where it should have
been calling the virtual PayloadSize function.

Change-Id: Ie6d66d6d720334180a11e06926a3bd8c7788a1f1
2012-01-25 13:23:40 -05:00
Frank Galligan
359b3654ad Merge "Fix bug with calculating master element sizes." 2012-01-25 10:01:39 -08:00
Frank Galligan
000944c4e4 Fix bug with calculating master element sizes.
There was a potential bug with calculating the size of a master
element. The size was being calculated with a straight unsigned
integer when it should have been calculated with a coded
integer.

Change-Id: I68422ecdb7818af51ded2953a8914fcdc8858f7a
2012-01-25 10:28:26 -05:00
Tom Finegan
8da8206fa0 mkvmuxer: Use WriteID for all element IDs.
Fixes reliability issue with IMkvWriter::ElementStartNotify: the
cluster and segment IDs were being written with SerializeInt instead
of WriteID.

Also:
- Remove completed TODO.
- Fix method declaration order in MkvWriter.

Change-Id: Ie37e141169af6e0ca7d931cc39f001722e7b9078
2012-01-23 16:42:03 -05:00
Tom Finegan
7a9a72f984 mkvmuxer: Disallow non-monotonically increasing timestamps.
Segment::AddFrame will now return false (fail) when a non-monotonically
increasing timestamp value is passed to the method.

Change-Id: Icfac093e6bddf18e3ef252df79e35c33dbe1e134
2012-01-20 15:59:38 -05:00
Tom Finegan
d2327e2b65 sample_muxer: Cosmetics.
- Fix return values; use EXIT_FAILURE and EXIT_SUCCESS
  instead of -1 and 0.
- Use C++ versions of C library includes.

Change-Id: Ib3a36e799d6a91b7fea0f328480e977ef21ca260
2012-01-19 20:21:36 -05:00
Tom Finegan
1e37a264f1 mkvmuxer: Add element start notification.
Just before the first byte of an element identifier is written
the muxer calls IMkvWriter::ElementStartNotify to report the
position of the element in the WebM stream.

Change-Id: Iac40090587bd9496b05f41203aace00902f5606e
2012-01-19 20:21:35 -05:00
Tom Finegan
01d5924817 mkvmuxer: Cosmetics.
- Use c++ versions of C library includes.
- Make Segment::~Segment non-virtual.

Change-Id: I868c1f3769b5a87362efe99383cca880586b57f3
2012-01-19 20:21:35 -05:00
Tom Finegan
a20f4255c7 mkvmuxer: Return errors instead of using assert.
NDEBUG is defined in our release build, which allowed for misuse of
the library by users that would result in dereferencing NULL
MkvWriter pointers in various places throughout the muxer code.

Change-Id: I6ab51453ef26786ca988310c051bb49db16ecbc5
2012-01-19 20:21:30 -05:00
Tom Finegan
69df730519 mkvmuxer: Add Init method to Cluster and Segment.
Remove asserts on the MkvWriter pointer in each constructor,
and assign the pointer in each Init method. Update Segment::Init
usage site in sample_muxer.

Change-Id: Id940f76b50dc15603742e76afc04cdffe0ec4990
2012-01-19 20:21:25 -05:00
Tom Finegan
f7aa8ab33d Merge "Add output of elements to separate files." 2012-01-18 13:54:56 -08:00
Frank Galligan
73ad7bd83c Add output of elements to separate files.
Support outputting header, clusters, and cues to separate files.

Change-Id: Ia89bf59ddbddc094c3daf944123fd01630ae9193
2012-01-18 16:02:43 -05:00
matthewjheaney
4c682199b0 mkvparser: cache SeekEntry start and size
Change-Id: I54a0ac4035f7174f51ae2145dedb1c3ed5ad7ec8
2011-12-08 16:07:15 -05:00
matthewjheaney
9303667611 parse void elements in seek head
Change-Id: Ifc8841909f6aa877108abebb5b5623c2344d0e35
2011-11-17 19:08:48 -05:00
Frank Galligan
4affedd0a7 Add support for encryption elements.
Added support for the ContentEncoding element to be added to a
Track element for muxing. Currently only one ContentEncoding may
be added. The ContentEncoding must be encryption of the whole
frame with AES.
Added support for parsing the ConentEncoding elements. Currently
the parser does not parse any ContentCompression elements.

Change-Id: Ie199116a1bcc18a0c2b5eea3dba6622887c108c8
2011-11-04 14:09:56 -04:00
Frank Galligan
23808a7ba4 Switch AddFrame parameter to const.
Change-Id: I4ae4ac3a57f91eb19a7bb1b1d1c63fe64128efe2
2011-10-27 13:21:04 -04:00
Frank Galligan
32227e70c1 Fix for writing audio to first cluster.
If the muxer had audio frames that were earlier in time than the
first video frame then the first cluster would not be initialized
in time to write out the first audio frames.

Change-Id: I6a2ca25a25c326a4215c307bdae666db9107e9b5
2011-09-13 11:41:15 -04:00
Frank Galligan
2d3461b4b3 Add support for setting track numbers.
When adding tracks to the muxer the application can set the
track number.

Change-Id: Id4dbbfec5cd541b1354c03361a40a3d2d7f921b9
2011-08-15 15:29:20 -04:00
Frank Galligan
a09f15f00e Better support for audio only webm files.
Changed max_cluster_duration to 30 seconds so default command line
will not crash on audio only WebM files. Added support to the sample
muxer to output cues on the audio track. Created a muxer helper
function to clean up the code a little.

Change-Id: I2871836b64cef7defd10aa51a209b4abd9046832
2011-08-14 10:49:50 -04:00
Tom Finegan
6d99850e7c Build muxer and parser into a single library.
Makefile:
- Add a new target that makes a single libwebm.a instead of building
separate muxer and parser libraries.
- Update sample targets accordingly.

Visual Studio:
- Use a single project for muxing and parsing, and build a single library
name libwebm.lib.
- Update code generation settings (DLL -> static runtimes).
- Use C7 debug information format (instead of PDB)
- Disable minimal rebuild (C7 use causes warning otherwise).

Change-Id: Ie221d4ee02c93f98f2521757c08b75ecbf75f54f
2011-08-11 17:19:45 -04:00
matthewjheaney
1ae4335c1c libwebm: liberalize handling of reference blocks
Change-Id: I3df0235e005c57507eb974ad3754b4c800a99825
2011-08-09 16:03:50 -04:00
Frank Galligan
52f0a92192 Added const to some pointers.
Updated some long assignment statements to indent 4 per the
coding guide. Added explicit calls to Close on the reader and
writer objects.

Change-Id: I149326c3a07543d7eb9323c702cf13852c5bc3c2
2011-07-18 14:28:12 -04:00
Frank Galligan
6ebe4a39df Merge "Add support for muxing to libwebm." 2011-07-18 08:09:34 -07:00
Frank Galligan
a3dd40877d Add support for muxing to libwebm.
Squashed commit of the following:

9f73b86 Updated code to Google C++ style guide.
8580901 Added support for linux.
fd0b59c Fixed segment size issue.
d51d5ef Added more Track and Video options.
0fc73fd Fixed issue where cue point was being written out on wrong
        track.
fcfdd07 Updated sample_muxer to read in a webm and output a webm file.
        Added some options to sample_muxer. Fixed writing out unknown
        size.
285c558 Added support for muxer guideline "Audio that matches video key
        frame should be in the same cluster." Added support for
        block_number in cue points. Added support for setting max
        cluster size.
f956dec Add support for setting the max duration for all clusters.
92ca53e Add support for Cues element.
d6b4cba Added typedefs for unsigned long long, long long, and unsigned
        char. Reformated some code.
1b1f8b2 Added support for SeekHead element. Added WriteVoidElement
        function.
8faa187 Add support for CodecPrivate. Add support for updating
        SegmentInfo duration. Add support for updating Segment size.
        Added new sample that swicthes the tracks.
1dd3555 Refactored some code. Check to see if track is a video track if
        starting a new cluster on a key-frame.
1bc8374 Refacotrs code so Cluster is in charge of wirting out its own
        data.
836cd74 Added basic cluster and simple_block support for writing frames.
cc48cc2 Add simple support for Audio tracks.
4efd614 Added support for using the encoded ID value for the elements.
fb8b5a6 Initial commit of libwebm muxer.

Removed switch_sample project. Fixed initialization order warnings on
Linux. Reformatted code to follow Google C++ style guide. Fixed Makefile.
Removed tester.cpp.

Change-Id: I4857042f804edb834be52787a7d5ccdd578b7275
2011-07-15 17:30:27 -04:00
James Zern
1623fb983b mkvparser: silence initializer list warnings
Ensure initializer lists match declaration order, from gcc -Wreorder.

Change-Id: I9ba245ab9c28d89978cdfe3865edcb54da2e949c
2011-07-14 10:30:47 -07:00
Frank Galligan
18ac83d501 Add default mkvreader object to mkvparser namespace. Add mkvreader
object to linux and mac libmkvparser.a.

Change-Id: Ibb94e8dee9a3a897bcda925916c5713cb45d35fe
2011-06-06 13:08:08 -04:00
Joel Dice
5942099a85 fix warnings when building with gcc -Wall -Wextra
This commit addresses three types of warnings:

 * constructor initialization order inconsistencies
 * statements with no effect
 * possible use of uninitialized fields

Change-Id: I572ccdc6813d8cfeff3e9e06d7acf6a8ab5ac7b1
2011-05-09 16:34:40 -04:00
matthewjheaney
9ecedef185 libwebm: include <cstddef>
Change-Id: Ieba2507dd82b34558ffef4febb6f80225009cc30
2011-05-03 15:48:13 -04:00
matthewjheaney
6f68021678 libwebm: re-implemented Block::EOS()
Change-Id: I91c6746d3e06e2f74dc899dbeec5c5270e150d08
2011-04-07 19:36:15 -07:00
matthewjheaney
3395c36a8e libwebm: added UnserializeInt function
Change-Id: I2298e547cd38d3aea04c0c993a67e5e291b8fea8
2011-04-05 20:55:26 -07:00
matthewjheaney
ffe5a8e548 libwebm: added GetLacing selector function for Block
Change-Id: I77bff875919f7a57a8c838beb05bc9a992cadacd
2011-04-05 20:55:25 -07:00
matthewjheaney
a9c65fbbc0 libwebm: added BlockEntry::GetKind op
Change-Id: I7d7daac0d3b8be1b8839f96503250170f675e34d
2011-04-05 20:55:24 -07:00
matthewjheaney
31a9d5470e libwebm: don't alloc block object in block group
Change-Id: I55ff9451591da86b89ed58c22eb9778317b89364
2011-04-05 20:55:23 -07:00
matthewjheaney
2b84a12da8 libwebm: removed old Cluster::Load
Change-Id: I02448e6c9d5850368282353dba40a549753c26bc
2011-04-05 20:55:22 -07:00
matthewjheaney
bd833a82e4 libwebm: removed old LoadBlockEntries
Change-Id: I340f444f719fa9c5d9da986f1527522d8a5f9812
2011-04-05 20:55:21 -07:00
matthewjheaney
7b07758854 libwebm: refactor BlockEntry class
Change-Id: I68d799d5b928de0ff7be293731ab73750c7cbb86
2011-04-05 20:55:20 -07:00
matthewjheaney
00ed87aad6 libwebm: Block::GetIndex returns type long
Change-Id: I7b233a18b5054398ae22696148ede17817ea608a
2011-04-05 20:55:11 -07:00
matthewjheaney
06f08663be libwebm: Block::GetTimeCode allows NULL param
Change-Id: Ia62820637f1819d1904d2e6e7b20bd3c39053bb5
2011-04-05 20:54:14 -07:00
matthewjheaney
35ded77a23 libwebm: change version to 1.0.0.21
Change-Id: Ic8ef4e8f02a3dc5b07939f0b09903d31dc4a403f
2011-03-28 13:04:26 -04:00
matthewjheaney
1f33611caa libwebm: bad assert in Cluster::GetEntry
Change-Id: I5bcee1f496260416b438a1c2632dd24e8b26eee4
2011-03-22 14:18:14 -04:00
matthewjheaney
70f9644a8d libwebm: restored Cluster::GetLast
Change-Id: I73564fb508e23004392b5aaab1f1ad7cdedc8bb1
2011-03-19 10:34:12 -04:00
matthewjheaney
f2bd78ef6b libwebm: changed semantics of LoadCuePoint retval
Change-Id: Iabbc82b24bde27c06b44b9f9f45e64215b9164c5
2011-03-19 09:54:41 -04:00
matthewjheaney
2083c72300 libwebm: removed LoadBlockEntries
Change-Id: I1d65c07d91de568573f48e9fddf83b4c5672871d
2011-03-18 21:43:06 -04:00
matthewjheaney
f5ec272e54 libwebm: removed Cluster::Load (non-incremental)
Change-Id: I1f2ad153e0c643d04fa1fe1ec85410bbef1954ef
2011-03-18 11:18:46 -04:00
matthewjheaney
b324e52139 libwebm: handle truncated segment
Change-Id: Iddd15a207bce4a2c26f72e5e35f736c1b3f700d7
2011-03-16 15:08:06 -04:00
matthewjheaney
4137f9c999 libwebm: v1.0.0.20
Change-Id: I8a93517762c0edecd59a38e2f4fc99566c7b2de5
2011-03-15 14:27:53 -04:00
matthewjheaney
ba4096f120 libwebm: fixed bug in LoadBlockEntries
Change-Id: I4a0870030803bcbb5502800ae5627f716d417440
2011-03-10 15:12:16 -05:00
matthewjheaney
365a39b5ec libwebm: set version to v1.0.0.19
Change-Id: I5e88dce1c52bc18bdab2063111830b5fbd0faafe
2011-03-09 11:04:21 -05:00
matthewjheaney
601f7903a3 libwebm: block group must parse ref times too
Change-Id: Iadf7674dfaf311e04f2eea35fc396e2eaab18163
2011-03-08 21:51:13 -05:00
matthewjheaney
16b2cdaf57 libwebm: changed to version v1.0.0.18
Change-Id: I9f0f0c25fca48cfe18fd16c332bf21265bfef204
2011-03-08 13:13:07 -05:00
matthewjheaney
ca1e6b7323 libwebm: defend against truncated stream
Change-Id: I3fb983f9601ac133752fbbdb8bb8b179b18d14fb
2011-03-08 12:25:26 -05:00
matthewjheaney
c226b79e61 libwebm: safer way to handle truncated cluster
Change-Id: Ifa9df95fedee14846835c16942a80735e7f3c0ed
2011-03-07 23:44:47 -05:00
matthewjheaney
dc8bdb3389 libwebm: handle EOF in ParseNext
Change-Id: I1d93fca0c6ad259e76b79bdba8bb0debdd96bd94
2011-03-07 22:40:00 -05:00
matthewjheaney
31b2d8689c libwebm: parse unkown cluster size
Change-Id: I74f7f552185aafaa4466556644e95c3a25063a08
2011-03-07 21:11:57 -05:00
matthewjheaney
227d62aadf libwebm: changed type from size_t to long
Change-Id: I5a684628119877a2f89116b760a1c7e41716748d
2011-03-02 19:05:28 -05:00
matthewjheaney
85beb00fe3 libwebm: changed idx from size_t to long
Change-Id: I7ea9637ab3c55d7535fe9f2fe11fe88f4d47e474
2011-03-02 18:21:21 -05:00
matthewjheaney
eb4bd69098 libwebm: do not lazy-load cue points
Change-Id: I07646f1942d1f473f051ff8ab0aa07b2f4381d4c
2011-02-26 16:59:42 -05:00
matthewjheaney
cf36dc2848 libwebm: added Cues::GetCount
Change-Id: I5b2bca8fd7229318783d9b97c50a4e20ce2ba640
2011-02-26 11:50:23 -05:00
matthewjheaney
b0465e167e libwebm: audio track channel count defaults to 1
Change-Id: Id12bec611bd34f299235a278738f3b55cf5a36c5
2011-02-23 13:15:37 -05:00
matthewjheaney
a1aa16692a libwebm: added support for incremental cluster parsing
Change-Id: Idb1bd292a01b7c9971967760ad016691ac628c29
2011-02-22 11:51:23 -05:00
matthewjheaney
f971a94349 changed version to 1.0.0.17
Change-Id: I213e1279a25d8b7830e635434723b4770d31662c
2011-02-14 15:31:38 -05:00
matthewjheaney
5ac9764a95 libwebm: liberalized parsing of next cluster
Change-Id: I166ecfb5a76d475b77c3e418c4ae91195ff58d32
2011-02-13 19:00:31 -05:00
matthewjheaney
d82f86a40a libwebm: handle underflow from IMkvReader::Read
Change-Id: I8bb0ed53b7bfdde6c0ed24665591f95d7cf43083
2011-02-10 20:42:52 -05:00
matthewjheaney
a1736157be libwebm: handle unknown cluster size in Segment::Load too
Change-Id: I7ed5feb7fe29cd413c8de35274138605725c5b38
2011-02-10 14:41:54 -05:00
matthewjheaney
2c835bcc28 libwebm: handle (as error) cluster with unknown size
Change-Id: I8342d50d0482d77cb895ae659568016eb48ed2be
2011-02-10 13:32:40 -05:00
matthewjheaney
d931a6ecc6 libwebm: set version to 1.0.0.16
Change-Id: Id8f9d8a5d1aa50545c403eb9da04f62347b4604f
2011-02-01 18:49:47 -08:00
matthewjheaney
7a8b013f16 libwebm: handle unknown file length
Change-Id: I6ad22ce302e40a4ec882b4f9ac59d5ca7f6489d7
2011-02-01 16:29:02 -08:00
matthewjheaney
a977a2b536 libwebm: changed version to 1.0.0.15
Change-Id: I70c6b22d75defcb11fecbbcd8763659cca7f77e0
2011-01-28 16:56:27 -05:00
matthewjheaney
5e72a2dfc2 libwebm: changed signature of CuePoint::GetTime
Change-Id: Ia80da8af5607c7067e848bafd453842cfe8cfcca
2011-01-28 00:52:13 -05:00
matthewjheaney
056b0d96a8 libwebm: changed version to 1.0.0.14
Change-Id: Id8147672e7fb761b2a69ff0d1ec05705e34eefc1
2011-01-26 19:08:43 -05:00
matthewjheaney
dbc58d0510 libwebm: make unserialize operations endian-neutral
Change-Id: I0c754ea8192020886dac14e3a0bd6a74c3165a92
2011-01-26 18:50:07 -05:00
matthewjheaney
a131a01446 libwebm: incrementally load block entries
Change-Id: I566df5979e7638b6a5411a3338bbb0cf7d9ad111
2011-01-25 23:01:51 -05:00
Hwasoo Lee
b8cb358204 fixed build error in sample
Change-Id: Id6ac66f5e625952918857c3e13e655452c32abc8
2011-01-25 11:31:20 -05:00
26 changed files with 8529 additions and 1085 deletions

View File

@@ -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

View File

@@ -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"

View File

@@ -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>

44
libwebm_2008.sln Normal file
View File

@@ -0,0 +1,44 @@

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
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwebvtt", "libwebvtt.vcproj", "{9545310B-A6E6-4B42-BB00-655D66B6E3D5}"
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
{9545310B-A6E6-4B42-BB00-655D66B6E3D5}.Debug|Win32.ActiveCfg = Debug|Win32
{9545310B-A6E6-4B42-BB00-655D66B6E3D5}.Debug|Win32.Build.0 = Debug|Win32
{9545310B-A6E6-4B42-BB00-655D66B6E3D5}.Release|Win32.ActiveCfg = Release|Win32
{9545310B-A6E6-4B42-BB00-655D66B6E3D5}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -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>

157
libwebvtt.vcproj Normal file
View File

@@ -0,0 +1,157 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="libwebvtt_2008"
ProjectGUID="{9545310B-A6E6-4B42-BB00-655D66B6E3D5}"
RootNamespace="libwebvtt"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)..\lib\$(SolutionName)\$(ProjectName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)..\obj\$(SolutionName)\$(ProjectName)\$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="false"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="4"
DebugInformationFormat="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=".\webvttparser.cpp"
>
</File>
<File
RelativePath=".\webvttparser.hpp"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

2081
mkvmuxer.cpp Normal file

File diff suppressed because it is too large Load Diff

841
mkvmuxer.hpp Normal file
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

View File

@@ -11,6 +11,7 @@
#include <cstdlib>
#include <cstdio>
#include <cstddef>
namespace mkvparser
{
@@ -33,8 +34,14 @@ 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
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 +80,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 +92,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 +123,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 +150,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 +168,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
{
@@ -239,6 +333,11 @@ 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*,
@@ -252,15 +351,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_;
};
@@ -412,22 +511,44 @@ public:
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_count;
int m_entry_count;
static void ParseEntry(
VoidElement* m_void_elements;
int m_void_element_count;
static bool ParseEntry(
IMkvReader*,
long long pos,
long long pos, //payload
long long size,
Entry*&);
Entry*);
};
@@ -436,7 +557,7 @@ class CuePoint
{
friend class Cues;
CuePoint(size_t, long long);
CuePoint(long, long long);
~CuePoint();
CuePoint(const CuePoint&);
@@ -449,7 +570,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
{
@@ -466,7 +587,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;
@@ -519,14 +640,17 @@ public:
const CuePoint::TrackPosition*) const;
bool LoadCuePoint() const;
long GetCount() const; //loaded only
//long GetTotal() const; //loaded + preloaded
bool DoneParsing() const;
private:
void Init() 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;
};
@@ -534,6 +658,8 @@ private:
class Cluster
{
friend class Segment;
Cluster(const Cluster&);
Cluster& operator=(const Cluster&);
@@ -541,12 +667,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();
@@ -558,44 +683,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);
// static bool HasBlockEntries(const Segment*, long long);
static long HasBlockEntries(
const Segment*,
long long idoff,
long long& pos,
long& size);
long GetEntryCount() const;
void Load() 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);
};
@@ -610,10 +755,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?
@@ -624,7 +776,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
@@ -636,10 +789,12 @@ 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
const SeekHead* GetSeekHead() const;
const Tracks* GetTracks() const;
@@ -666,6 +821,7 @@ public:
private:
long long m_pos; //absolute file posn; what has been consumed so far
Cluster* m_pUnknownSize;
SeekHead* m_pSeekHead;
SegmentInfo* m_pInfo;
@@ -676,6 +832,10 @@ 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);

View File

@@ -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

View File

@@ -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

View File

@@ -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
View 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
View 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

View File

@@ -12,6 +12,16 @@
#include "mkvreader.hpp"
#include "mkvparser.hpp"
#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)
{
if (str == NULL)
@@ -142,7 +152,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();
@@ -246,7 +256,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);
goto done;
}
while ((pBlockEntry != NULL) && !pBlockEntry->EOS())
{
@@ -271,12 +290,20 @@ int main(int argc, char* argv[])
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);
goto done;
}
}
pCluster = pSegment->GetNext(pCluster);
}
done:
delete pSegment;
return 0;

View File

@@ -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"

View File

@@ -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"

View 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;
}

View 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
View 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

23
webvttparser.cpp Normal file
View File

@@ -0,0 +1,23 @@
#include "webvttparser.hpp"
namespace WebvttParser
{
IReader::IReader()
{
}
IReader::~IReader()
{
}
Parser::Parser(IReader* p) :
m_pReader(p)
{
}
Parser::~Parser()
{
}
} //end namespace WebvttParser

60
webvttparser.hpp Normal file
View File

@@ -0,0 +1,60 @@
#ifndef WEBVTTPARSER_HPP
#define WEBVTTPARSER_HPP
namespace WebvttParser
{
class IReader
{
protected:
IReader();
virtual ~IReader();
public:
virtual int Read(char& c) = 0;
};
class Parser
{
private:
Parser(const Parser&);
Parser& operator=(const Parser&);
public:
Parser(IReader*);
~Parser();
int Parse();
//need to know kind:
// caption, description, metadata, etc
// is this a webvtt stream?
//
//cue identifier
//timestamp (or defaults?) + cue settings
//payload
// preserve each line
//machine states:
// parsing stream id ("webvtt")
// parsing file-wide metadata
// parsing cue
//
//within cue:
// parsing line
// is this a cue identifier or timestamp line?
//
// parsing cue id
// parsing timestamp
// parsing lines, looking for end-of-cue
private:
IReader* const m_pReader;
};
} //end namespace WebvttParser
#endif