Compare commits

...

128 Commits

Author SHA1 Message Date
Tom Finegan
25025a5471 Add dependency checks to Makefile.
Avoid unfortunate things like breaking the library because the make file
was not previously checking dependencies.

Change-Id: Iab20c3cfa0d1475dfb5c54127646b351df1c4c50
2013-08-19 19:32:37 -07:00
Tom Finegan
f72dc7b052 Ignore dependency files and build products.
Change-Id: I4e9da395b8e06a696e77389d0bc863b8837eceee
2013-08-19 11:02:23 -07:00
Tom Finegan
c5892de23b Fix mkvmuxer::Track::set_uid().
Modifying const variables doesn't work.

Change-Id: Ie1aa9ce1779002973ec93f808ba5e86c569b9df4
2013-08-19 11:01:49 -07:00
Tom Finegan
15a708e416 Add set_uid() to mkvmuxer::Track.
Allow users of libwebm's MKV muxer to control the Track UID. This,
for example, allows creation of tests that rely on checksum comparisons
to verify output from the library.

Change-Id: I8b052e6dd5af734d76122b2a1b6b16382ffba214
2013-08-16 10:58:17 -07:00
Vignesh Venkatasubramanian
8206558561 Handling chunking_ being set to true on repositioning cues.
CopyAndMoveCuesBeforeClusters should return false (fail gracefully)
if chunking_ is set to true.

Change-Id: Idf4d573e3f15b59c25ee0774a7875e5dfda9c02e
2013-06-27 11:30:17 -07:00
Vignesh Venkatasubramanian
d782edd68e Update Segment size if Cues size changes on repositioning
Files created with Segment::CopyAndMoveCuesBeforeClusters can't be parsed by
libwebm because the Segment size was not updated to account for the change
in Cue size. Fixing that.

Change-Id: I993f63e5c279f131cd39c54bee40163da00b8cbd
2013-06-24 11:55:53 -07:00
Vignesh Venkatasubramanian
4ac7b755f4 Repositing Cues before Clusters
A whole new approach to repositioning Cues before Clusters. This
patchset adds a new function CopyAndMoveCuesBeforeClusters to the
Segment class. This function should be called after
Segment::Finalize() to obtain a copy of the same output file with
Cues positioned before the Clusters.

Removing everything else that was added to accomplish the same in
the previous few commits.

Also, adding std:: qualifier to one of the variables in
sample_muxer_metadata which was missed accidentally in the previous
commit.

Change-Id: I2810d06a6251325add2f5e54d32d1da6e2fe143f
2013-06-14 13:01:48 -07:00
Vignesh Venkatasubramanian
09dd90fcc7 Fully qualifiying usage of std::string
Replacing "using std::string" with fully qualified namespace on
each occurance of string in sample_muxer_metadata.cc and
webvttparser.cc.

Also fixing a formatting nit in mkvwriteeofreader.cpp

Change-Id: Icf713f9e489fbdc9af14e83d0cb7ba2e89e65ab4
2013-06-12 11:23:35 -07:00
Vignesh Venkatasubramanian
54ca052b1c Changing IMkvReadableWriter to IMkvWriteEOFReader
Changing the IMkvReadableWriter interface to IMkvWriteEOFReader.
Also changing the default implementation.

Change-Id: Id37ffd7ef0af2ff7a392fb4fb0b1b134664ab20f
2013-06-11 15:11:18 -07:00
Vignesh Venkatasubramanian
74e5f0fa1d Adding mkvreadablewriter
Adding mkvreadablewriter files which was missed from previous commit.

Change-Id: I84363ca897ebe758a42538c179ad60c2adfe9247
2013-06-03 14:26:20 -07:00
Vignesh Venkatasubramanian
9b42d039ad Support for placing Cues before Clusters
Adding support for placing Cues element before the Cluster element. We
recompute the new offsets using a recursive algorithm and update the Cues and
Seek Heads with the updates offsets.

Change-Id: I038f1a403b1defa853b9026bd3e48f4ad1006866
2013-06-03 10:27:27 -07:00
Vignesh Venkatasubramanian
3f7681d11e Merge "Fixing mistyped element name in mkvmuxerutil" 2013-05-20 17:11:11 -07:00
Vignesh Venkatasubramanian
7a64466954 Fixing mistyped element name in mkvmuxerutil
Replacing correct element name in mkvmuxerutil that was mistyped
in a previous commit.

Change-Id: Ic34f544aeeb124f0950c3f45e7b638d4616f8b86
2013-05-20 16:46:33 -07:00
Vignesh Venkatasubramanian
05912e8a96 Merge "Elements and functions to support BlockAdditional" 2013-05-07 14:17:43 -07:00
Patrik2 Carlsson
a9f43fe8e7 mkvparser: Get frame default duration
Track::GetDefaultDuration is implemented as an alternative
to VideoTrack::GetFrameRate which seems to be deprecated.

Change-Id: I2c7a6d56a232125b8632d87eab75b9600c5451e1
2013-05-02 16:04:34 +02:00
Vignesh Venkatasubramanian
5af56bb9ee Elements and functions to support BlockAdditional
Adding elements and functions to support muxing of BlockAdditional element.
This is required for supporting muxing of streams with Alpha Channel (where the
Alpha data goes into BlockAdditional). Detailed design doc of Alpha Channel can
be found here: http://goo.gl/wCP1y

Change-Id: Idac144d9588de16685734850585ab7115ddd08a4
2013-04-24 16:16:14 -07:00
Frank Galligan
64cee42b85 libwebm: Remove STL dependency from Android build.
Change-Id: Id2f378f2fa8350aae97394bd8b21918cff4d179a
2013-04-15 10:24:34 -07:00
Frank Galligan
d5cb6c7fa4 libwebm: Fix random number generation on Android.
Change-Id: I593561128aaeb5806f8f015e2de3b4c9aa4411fc
2013-04-15 09:27:34 -07:00
Frank Galligan
252bd24950 libwebm: Update Android build
- Change to libwebm.
- Add muxer support.
- Remove sample app.

Change-Id: I39c31ecbff573f86214e85b3ac08e0dcdfe22ae2
2013-04-15 09:13:07 -07:00
Michael Szal
9cb9ee4efa Removed IsOpen because it should not have been there.
Change-Id: I4d5149de362e50a8f15ebfd382e39218ca2ca560
2013-03-29 11:44:28 -07:00
Patrik Carlsson
3af8d02ca1 mkvparser: support seek for generic tracks (subtitles)
To support seek in generic tracks with subtitles the audio track
implementation of seek is made generic and inherited by audio track.

Change-Id: Ic88d2e859d077a1054b2af7d7680cfddfba8a589
2013-02-28 15:47:04 +01:00
Patrik Carlsson
0d5b3fc5ae mkvparser: add support for compression elements
ContentCompression elements are now parsed.

Change-Id: I9a67ae444ed929e49c7ea223a16c13c9d16a4c13
2013-02-28 15:46:58 +01:00
Patrik Carlsson
3980cf4159 mkvparser: read track language information
Track::GetLanguageAsUTF8 is implemented to allow the user to
choose between available audio and subtitle tracks.

Change-Id: I5ec9b1c1c00182da759681ba486cbace46e9b63f
2013-02-27 15:40:33 +01:00
Matthew Heaney
1274be1184 libwebm: fixed compilation error
Change-Id: I2dfa93f3a2470e016ca905caee33c3dceb789b57
2013-01-31 14:13:33 -08:00
Matthew Heaney
43178b4c9a libwebm: fixed rand() on windows
Change-Id: Ie17445072f10f91bdaabfba74a1be58764d78b94
2013-01-24 17:29:23 -08:00
Matthew Heaney
8376a8e9d7 mkvparser: liberalize parsing of bad elements
Normally, if a sub-element of a cluster reports a size
that lies beyond the end of its enclosing cluster, we
would treat this as a malformed stream and immediately
terminate the parse.

However, if the sub-element is not a simple block or block
group, we would ignore the (sub)element anyway, so there
doesn't appear to be any harm in just concontinuing to
ignore the (sub)element, and treating this case as if
we had reached the end-of-cluster in the normal way.

Change-Id: I16c0a44f7458823ed579612d917b09ee08a8d90a
2013-01-10 19:24:21 -08:00
David Schalig
2b09f9b53a mkvparser: ignore 0-size elements in TrackEntry
ParseTrackEntry handled MKVs with 0-sized EBML elements
as malformed. Relaxing this and allow empty elements to allow
parsing such MKV content.

Change-Id: I7e430e9b2d177df7fe1e656546f63ee8673e784e
2012-12-11 17:08:22 +09:00
Matthew Heaney
28222b4927 Add support for WebVTT cue identifier line
Modified the mkvmuxer to write the ChapterStringUID
sub-element of the Chapter Atom element.

Modified the mkvparser to read the ChapterStringUID
sub-element of the chapter atom.

Modified the vttdemux app to write the Cue Identifier
line of the WebVTT cue.

Change-Id: I06fe386f44897ada3fe10cbf89096df104dcf779
2012-11-13 12:44:06 -08:00
Matthew Heaney
0fcf5e5a40 Merge "vttdemux: add support for WebVTT chapters" 2012-11-13 09:38:29 -08:00
Matthew Heaney
c26db03d5a vttdemux: add support for WebVTT chapters
Change-Id: If5e12ff7057ce4217907ef91d493e1bcd8a72656
2012-11-12 11:52:15 -08:00
Frank Galligan
baefebcf1c libwebm: Fix BlockNumber on CuePoint
- libwebm was writing the BlockNumber of the next Block instead
  of the Block that was just written.

Change-Id: I344800fcea919a82d7f0a04a54cf510be3851ec6
2012-11-12 08:35:39 -08:00
Matthew Heaney
386928d8b8 mkvparser: add missing definitions
Change-Id: I043a6d974bdf146a8726d090722159943eb20752
2012-11-08 18:12:30 -08:00
Matthew Heaney
50ee255b8c mkvparser: add support for MKV chapters
Change-Id: I2404b6886ed592fe505ee973bf05c769a9d134b1
2012-11-02 14:42:40 -07:00
Matthew Heaney
ad54bfb572 sample_muxer: added support for WebVTT chapters
Change-Id: Ic5ab8097c0981ef300eadc4a3c151f63b2aad81d
2012-11-02 14:20:43 -07:00
Matthew Heaney
c99838a5fe Merge "mkvmuxer: add support for WebVTT chapters" 2012-10-31 18:03:59 -07:00
Matthew Heaney
2c5836837e mkvmuxer: add support for WebVTT chapters
Change-Id: I469ce3bd79a9b50b82e00ac8c63fc3d1db220887
2012-10-30 17:07:38 -07:00
Frank Galligan
50afbea946 muxer: Add support to force Cluster placement.
Change-Id: I7d4653561ca760885ba6926825ba6b80cdbea8ab
2012-10-29 09:24:41 -07:00
Matthew Heaney
25ee621061 mkvmuxer: add MakeUID utility function
Change-Id: I3fb57438767ddcc8f9e17c050d494f48ff203e58
2012-10-22 16:50:48 -07:00
Matthew Heaney
ac238c0c5c webvttparser: check intermediate values while parsing int
Change-Id: I145529097246f75c27ff2d29cf091416ba1c437d
2012-10-16 11:32:42 -07:00
Matthew Heaney
4a5141344e vttdemux: initial revision
vttdemux is a tool for demuxing a webm file containing
WebVTT metadata tracks, extracting the embedded metadata
from each track and storing it as a standalone WebVTT file.

Change-Id: I8897b3dc502c49c92f5b79925939baa5a9490aaa
2012-10-12 11:00:24 -07:00
Matthew Heaney
2fc496a0d6 mkvparser: create generic track objects
Formerly, it was only possible to create instances of
the Track subclasses, VideoTrack and AudioTrack.  However,
we now populate WebM files with WebVTT metadata blocks,
so we must allow for a third kind of track object.

We now enable instances of type Track to be created,
by providing a new factory function, Track::Create, and
making all Track methods non-pure and with a generic
implementation.

Change-Id: I7d4c965eb566b9fc2f5ceefe1d43723cf8c1e5f0
2012-10-10 16:51:21 -07:00
Matthew Heaney
cb8899a920 sample_muxer: clean-up to conform to style guide
Change-Id: I77a4657d71359777a8f55f40346014f90051e02d
2012-10-08 12:52:55 -07:00
Matthew Heaney
49078292b4 webvttparser: added LineReader class
Previously the Parser class had an internal function to parse
the character stream into separate lines.  This functionality
was separated out into its own class, LineReader, in order
to make this functionality available to clients too.

Change-Id: Ic5a1b0b73d7a253cf21cb6b4804b4941fd69c8ab
2012-10-02 18:14:51 -07:00
Matthew Heaney
4f494f6dd4 mkvparser: implemented BlockGroup::GetDuration method
Change-Id: Ib0106df3823c29e45a8fe59669c0fa65dd13a123
2012-09-28 14:55:24 -07:00
Matthew Heaney
7ef225de9f sample_muxer: added WebVTT support
Change-Id: If72d31ca4828adf39e4637003979a314e5dda98e
2012-09-28 10:38:19 -07:00
Frank Galligan
8f0c3333d1 Merge "mkvparser: Version 1.0.0.26 mkvmuxer: Version 0.2.0.0" 2012-09-27 10:06:58 -07:00
Frank Galligan
bf664baf05 mkvparser: Version 1.0.0.26 mkvmuxer: Version 0.2.0.0
Change-Id: I6875b1c10adea41c45762d82b7dd2f9551f5b7ca
2012-09-27 09:56:24 -07:00
James Zern
232bae0d50 Merge "Added a rule to the Makefile to build libwebm as a shared library." 2012-09-26 13:37:17 -07:00
Michael Szal
69c9348f07 Added a rule to the Makefile to build libwebm as a shared
library.

I'm building two different object files now: the ones for
libwebm.a are compiled normally (*_a.o), and the ones for
libwebm.so are compiled with -fPIC and linked with -shared
(*_so.o).

Change-Id: I76471ab225a006c7e169bc0d69df9a0731ff6681
2012-09-26 13:15:10 -07:00
Matthew Heaney
711af0c505 mkvmuxer: add operations for muxing metadata
Change-Id: Ia17166ee9133b4841f7d206aa7d5ec81f800e994
2012-09-24 12:13:45 -07:00
Matthew Heaney
38173f9d49 add operation to add generic track
Change-Id: I34e4ab14c0a5b022b77b98d9403125550024e730
2012-09-21 16:37:30 -07:00
Frank Galligan
21a2bd14c7 Make AddCuePoint function public.
Change-Id: I08df2b604185d6ae1d63eb360e68e84efa2cebfa
2012-09-21 16:21:03 -07:00
Frank Galligan
9ec562f72d Add Track number to AddCuePoint function.
Change-Id: I67fd8db3d436f8931f5d50deeb1f1d41cfdc0836
2012-09-21 15:42:57 -07:00
Frank Galligan
e6e2b6b387 Merge "Fix set_writing_app." 2012-09-21 14:08:43 -07:00
Frank Galligan
a2ca300513 Merge "mkvmuxer: default track_num to 0 in AddTrack" 2012-09-21 14:08:08 -07:00
Frank Galligan
6cf00207c0 Fix set_writing_app.
Change-Id: Idbb0522b10184072802be710088f0ec0bf008277
2012-09-21 12:20:43 -07:00
Frank Galligan
4df02ce68b libwebm: Add support for setting muxing app.
Change-Id: I78f4d08142aeeaacf5f9c175bab6a4993b917b1b
2012-09-21 12:17:03 -07:00
Matthew Heaney
4ffb162798 mkvmuxer: default track_num to 0 in AddTrack
Change-Id: I484cb56df7be7677a821db262c75cf8bdf1d30af
2012-09-21 11:55:47 -07:00
Matthew Heaney
76d9cf9cf4 mkvmuxer: handle large gaps in frame timestamps
Change-Id: If223a03cc37f2f373893c914e417475f62949717
2012-09-20 14:58:45 -07:00
Frank Galligan
20f64ff979 Merge "Fix incremental parsing in CreateInstance" 2012-09-14 11:18:27 -07:00
Frank Galligan
537da82f37 Fix incremental parsing in CreateInstance
- Segment::CreateInstance was treating the available data as EOF
  and returning errors.
- Added a check for potential underflow if the segment was not the
  first element after the EBML header.

Change-Id: I481bf0eea71eeb3def3bf54ec251be0b2ae13536
2012-09-14 11:05:18 -07:00
Matthew Heaney
db20aaa2b1 mkvmuxer: refactored code that creates a new cluster
Change-Id: I5db03b0e1ea23f45820dd47b7be9e4b0422f3e6a
2012-09-14 10:17:09 -07:00
Matthew Heaney
c9e284b9e7 refactor code to make a new cluster
Change-Id: Ifa7938134494e3524d6479bd026aea6d1b309d52
2012-09-13 10:15:59 -07:00
Matthew Heaney
07ac1947f0 Change return type of Segment::WriteFramesAll()
Change-Id: I7fb45f1779c384bcc1cdea507f1f2f51c28dd827
2012-09-12 10:29:40 -07:00
Matthew Heaney
0edf087bbb Refactor Cluster::AddFrame member function
Change-Id: Ibff460918243647eb76785508bb50490bc1d8561
2012-09-11 14:58:56 -07:00
Matthew Heaney
c425e965aa add operation to write metadata block
Change-Id: I08f6c7f71dbc9b0d9ce15c08cf288f4918b2c22a
2012-09-05 15:44:45 -07:00
Matthew Heaney
ed6282b2d6 webvttparser more closely conforms to style rules
A few adjustments we made such that the webvttparser
now conforms more closely to the Google C++ style guide.

Change-Id: Iefb2242678ceea6ab5b9daa3a046980deb6cd91c
2012-08-30 15:24:20 -07:00
Matthew Heaney
282a67599c added dumpvtt app
Change-Id: I9eba00412bbd05641dafd1a6cfc4656bda8bb8c2
2012-08-23 14:00:57 -07:00
Matthew Heaney
adebb53754 added webvtt parser
Change-Id: Icef6d484e8fe6e2c63dc69ab02b6ab37ffcabbd8
2012-08-16 16:39:07 -07:00
Frank Galligan
a320f5be63 Add CTR encryption.
- Added ContentEncAESSettings, AESSettingsCipherMode,
  AESSettingsCipherInitData elements to the parser and muxer.
- Changed ParseContentEncodingsEntry, ParseContentEncodingEntry,
  and ParseEncryptionEntry to use PasreElementHeader.
- Added ParseContentEncAESSettingsEntry function.
- PS6 removed AESSettingsCipherInitData.
- PS9 Addressed comments, Fixed some LINT issues, and converted
  mkvwriter.h/.cpp to Unix line endings.
- PS10 Addressed comments.

Change-Id: I9d96a0c194f74a6c9bf0001aa0286196e410f07e
2012-07-27 09:34:31 -07:00
Frank Galligan
c4d2b27b7a Add support for DLL configurations.
- Added "Release DLL" which uses /MTd and "Debug DLL" which
  uses /MDd.

Change-Id: Ibdaf58995e5ee94c34d52ece64e2f8f01524e9cd
2012-07-25 08:41:01 -07:00
Frank Galligan
13a90600ea Muxer fix for chunking file names on Linux.
Change-Id: Ica2dbfc7af64a83fc8f08d35196eabf1dd69f2f0
2012-07-12 08:01:55 -07:00
matthewjheaney
478b524df3 version 1.0.0.25
Change-Id: I438d43572f450bb6e151d4a1ede077ff22252d1f
2012-05-30 15:42:33 -04:00
Tom Finegan
010a457bc9 Add Visual Studio 2010 projects and solution.
Change-Id: I6387f1e6d68b05b8f605f155784c1025f85c1a5b
2012-05-30 14:18:23 -04:00
Tom Finegan
47a09523b2 Ignore visual studio 2010 temporary files.
Change-Id: I18d214b5ba032ff71af2fa67e72a92715636513c
2012-05-30 14:18:22 -04:00
Tom Finegan
84bf4a41dc Move build output outside the repository directory.
Change vs2008 output and intermediate directories to:
1. Avoid build output collisions when using vs2008 and vs2010 on the
   same system (makes no difference until subsequent commit adding
   vs2010 support).
2. Keep the tree clean.

Change-Id: Ie819e57421b7df90244eebffc0f5e608bc135930
2012-05-30 14:18:22 -04:00
Tom Finegan
177df33d25 Move the muxer sample source file and project.
They now reside in the same place as the parser sample.

Change-Id: Idb4471ea81a3d91eeeaf1b36053187203de9a21f
2012-05-30 14:18:08 -04:00
Tom Finegan
4fff53441d Remove visual studio 2005 projects and solution.
Change-Id: I1d4d8cffeb8997eee415246753ea3c29c1af45ec
2012-05-30 11:36:31 -04:00
Tom Finegan
ca13a5bae0 Rename sample_muxer.vcproj to sample_muxer_2008.vcproj.
Also update the solution file path to the project.

Change-Id: I7e83b99893bcde5429e6de03772c61369b29d332
2012-05-29 10:55:00 -04:00
Tom Finegan
cb69e608b4 Enable auto CRLF for visual studio project and solution files.
Change-Id: I23ca85442173eec7a144c001080ca8a3b41609f3
2012-05-29 10:45:59 -04:00
Tom Finegan
f6b0408aba Use LF as EoL in visual studio solutions and projects.
Makes files easier to read in gitweb, and prevents conflict with
upcoming .gitattributes change.

Change-Id: I185e496d8df8efb4987bfb848a582f7d0da81fb8
2012-05-29 10:43:40 -04:00
matthewjheaney
9a561ab4dd libwebm: handle negative time for a block
Change-Id: Iafa0254fb1554621b42635cb99d40b2c0177468f
2012-05-11 11:53:23 -04:00
Frank Galligan
0568dd63a6 Memory Leak Fix in Muxer.
- Track language_ and name_ member variables were not properly
  deleted.
- http://code.google.com/p/webm/issues/detail?id=416

Change-Id: Id0da669c347270cd355ad0b5e1e45ebf6415e367
2012-04-17 15:28:28 -04:00
Frank Galligan
56488f73ef Merge "sample_muxer: Fixed bug with outputting audio cues." 2012-03-16 08:06:54 -07:00
Frank Galligan
f270ddaeb8 sample_muxer: Fixed bug with outputting audio cues.
- For muxed content with default settings the cues was getting
  output on the audio track when it should be on the video track
  by default.
- Added check to command line parameter parsing to make sure
  there are enough parameters.
- If Cues are set to output on one type of track the other type
  is now disabled.

Change-Id: I96ef1978dc3f442f34364f6dee6cfb01571c7289
2012-03-16 09:26:28 -04:00
matthewjheaney
041a5c5811 Parse headers outside of constructor
In several cases, the parser would parse a header
(say, a track header, or the segment info header)
in the constructor for the type.  The parser had
assumed (incorrectly) that the file was well-formed,
but this turned out to be an incorrect assumption.

The parse errors triggered some assertion failures,
but this is not acceptable in a production system.

The parser solved that problem by separating the
construction of the header object from the parsing
of the file.  There is now a separate parse method
to be called after construction of the object,
which returns a status whether the parse was
successful.

This change fixes the bugs from the following
tracker issues:

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

Change-Id: Idb09154ae7008429d8613ce3b3e8294f5a12de86
2012-03-13 14:40:17 -04: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
40 changed files with 13390 additions and 2993 deletions

4
.gitattributes vendored Normal file
View File

@@ -0,0 +1,4 @@
*.sln eol=crlf
*.vcproj eol=crlf
*.vsprops eol=crlf
*.vcxproj eol=crlf

10
.gitignore vendored
View File

@@ -2,6 +2,7 @@
*.MKV
core
*.a
*.d
*.so*
*.o
*~
@@ -12,4 +13,11 @@ core
*.exe
*.webm
Debug
Release
Release
*.sdf
*.opensdf
ipch
dumpvtt
sample
samplemuxer
vttdemux

View File

@@ -1,13 +1,10 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= libmkvparser
LOCAL_MODULE:= libwebm
LOCAL_SRC_FILES:= mkvparser.cpp \
mkvreader.cpp
mkvreader.cpp \
mkvmuxer.cpp \
mkvmuxerutil.cpp \
mkvwriter.cpp
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= mkvparser
LOCAL_SRC_FILES:= sample.cpp
LOCAL_STATIC_LIBRARIES:= libmkvparser
include $(BUILD_EXECUTABLE)

View File

@@ -1,20 +1,53 @@
LIB = libmkvparser.a
OBJECTS = mkvparser.o mkvreader.o sample.o
EXE = sample
CFLAGS = -W -Wall -g
CXX := g++
CXXFLAGS := -W -Wall -g -MMD -MP
LIBWEBMA := libwebm.a
LIBWEBMSO := libwebm.so
WEBMOBJS := mkvparser.o mkvreader.o mkvmuxer.o mkvmuxerutil.o mkvwriter.o
OBJSA := $(WEBMOBJS:.o=_a.o)
OBJSSO := $(WEBMOBJS:.o=_so.o)
OBJECTS1 := sample.o
OBJECTS2 := sample_muxer.o vttreader.o webvttparser.o sample_muxer_metadata.o
OBJECTS3 := dumpvtt.o vttreader.o webvttparser.o
OBJECTS4 := vttdemux.o webvttparser.o
INCLUDES := -I.
DEPS := $(WEBMOBJS:.o=.d) $(OBJECTS1:.o=.d) $(OBJECTS2:.o=.d)
DEPS += $(OBJECTS3:.o=.d) $(OBJECTS4:.o=.d)
EXES := samplemuxer sample dumpvtt vttdemux
$(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 $(LIBWEBMA)
$(CXX) $^ -o $@
mkvreader.o: mkvreader.cpp
$(CXX) -c $(CFLAGS) mkvreader.cpp -o mkvreader.o
samplemuxer: $(OBJECTS2) $(LIBWEBMA)
$(CXX) $^ -o $@
sample.o: sample.cpp
$(CXX) -c $(CFLAGS) sample.cpp -o sample.o
dumpvtt: $(OBJECTS3)
$(CXX) $^ -o $@
shared: $(LIBWEBMSO)
vttdemux: $(OBJECTS4) $(LIBWEBMA)
$(CXX) $^ -o $@
libwebm.a: $(OBJSA)
$(AR) rcs $@ $^
libwebm.so: $(OBJSSO)
$(CXX) $(CXXFLAGS) -shared $(OBJSSO) -o $(LIBWEBMSO)
%.o: %.cpp
$(CXX) -c $(CXXFLAGS) $(INCLUDES) $< -o $@
%_a.o: %.cpp
$(CXX) -c $(CXXFLAGS) $(INCLUDES) $< -o $@
%_so.o: %.cpp
$(CXX) -c $(CXXFLAGS) -fPIC $(INCLUDES) $< -o $@
clean:
rm -rf $(OBJECTS) $(LIB) $(EXE) Makefile.bak
$(RM) -f $(OBJECTS1) $(OBJECTS2) $(OBJECTS3) $(OBJECTS4) $(OBJSA) $(OBJSSO) $(LIBWEBMA) $(LIBWEBMSO) $(EXES) $(DEPS) Makefile.bak
ifneq ($(MAKECMDGOALS), clean)
-include $(DEPS)
endif

98
dumpvtt.cc Normal file
View File

@@ -0,0 +1,98 @@
// 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.
#include <cstdio>
#include <cstdlib>
#include "./vttreader.h"
#include "./webvttparser.h"
int main(int argc, const char* argv[]) {
if (argc != 2) {
fprintf(stdout, "usage: dumpvtt <vtt file>\n");
return EXIT_SUCCESS;
}
libwebvtt::VttReader reader;
const char* const filename = argv[1];
if (int e = reader.Open(filename)) {
(void)e;
fprintf(stderr, "open failed\n");
return EXIT_FAILURE;
}
libwebvtt::Parser parser(&reader);
if (int e = parser.Init()) {
(void)e;
fprintf(stderr, "parser init failed\n");
return EXIT_FAILURE;
}
for (libwebvtt::Cue cue;;) {
const int e = parser.Parse(&cue);
if (e < 0) { // error
fprintf(stderr, "error parsing cue\n");
return EXIT_FAILURE;
}
if (e > 0) // EOF
return EXIT_SUCCESS;
fprintf(stdout, "cue identifier: \"%s\"\n", cue.identifier.c_str());
const libwebvtt::Time& st = cue.start_time;
fprintf(stdout, "cue start time: \"HH=%i MM=%i SS=%i SSS=%i\"\n",
st.hours,
st.minutes,
st.seconds,
st.milliseconds);
const libwebvtt::Time& sp = cue.stop_time;
fprintf(stdout, "cue stop time: \"HH=%i MM=%i SS=%i SSS=%i\"\n",
sp.hours,
sp.minutes,
sp.seconds,
sp.milliseconds);
{
typedef libwebvtt::Cue::settings_t::const_iterator iter_t;
iter_t i = cue.settings.begin();
const iter_t j = cue.settings.end();
if (i == j) {
fprintf(stdout, "cue setting: <no settings present>\n");
} else {
while (i != j) {
const libwebvtt::Setting& setting = *i++;
fprintf(stdout, "cue setting: name=%s value=%s\n",
setting.name.c_str(),
setting.value.c_str());
}
}
}
{
typedef libwebvtt::Cue::payload_t::const_iterator iter_t;
iter_t i = cue.payload.begin();
const iter_t j = cue.payload.end();
int idx = 1;
while (i != j) {
const std::string& payload = *i++;
const char* const payload_str = payload.c_str();
fprintf(stdout, "cue payload[%i]: \"%s\"\n", idx, payload_str);
++idx;
}
}
fprintf(stdout, "\n");
fflush(stdout);
}
}

38
libwebm_2008.sln Normal file
View File

@@ -0,0 +1,38 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample", "sample_2008.vcproj", "{0CB5681F-6065-490C-98C8-05531732ED7E}"
ProjectSection(ProjectDependencies) = postProject
{7B1F12CA-0724-430B-B61A-1D357C912CBA} = {7B1F12CA-0724-430B-B61A-1D357C912CBA}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwebm", "libwebm_2008.vcproj", "{7B1F12CA-0724-430B-B61A-1D357C912CBA}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_muxer", "sample_muxer_2008.vcproj", "{B407561F-1F5E-4798-B9C2-81AB09CFBC16}"
ProjectSection(ProjectDependencies) = postProject
{7B1F12CA-0724-430B-B61A-1D357C912CBA} = {7B1F12CA-0724-430B-B61A-1D357C912CBA}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0CB5681F-6065-490C-98C8-05531732ED7E}.Debug|Win32.ActiveCfg = Debug|Win32
{0CB5681F-6065-490C-98C8-05531732ED7E}.Debug|Win32.Build.0 = Debug|Win32
{0CB5681F-6065-490C-98C8-05531732ED7E}.Release|Win32.ActiveCfg = Release|Win32
{0CB5681F-6065-490C-98C8-05531732ED7E}.Release|Win32.Build.0 = Release|Win32
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Debug|Win32.ActiveCfg = Debug|Win32
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Debug|Win32.Build.0 = Debug|Win32
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Release|Win32.ActiveCfg = Release|Win32
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Release|Win32.Build.0 = Release|Win32
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Debug|Win32.ActiveCfg = Debug|Win32
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Debug|Win32.Build.0 = Debug|Win32
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Release|Win32.ActiveCfg = Release|Win32
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -1,178 +1,210 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="mkvparser"
ProjectGUID="{F9128EC6-C008-41AD-B38F-0E70D549D9F4}"
RootNamespace="mkvparser"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
UseOfMFC="0"
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"
Detect64BitPortabilityProblems="false"
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"
UseOfMFC="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
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>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\mkvparser.cpp"
>
</File>
<File
RelativePath=".\mkvreader.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\mkvparser.hpp"
>
</File>
<File
RelativePath=".\mkvreader.hpp"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="libwebm"
ProjectGUID="{7B1F12CA-0724-430B-B61A-1D357C912CBA}"
RootNamespace="libwebm"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(ProjectDir)..\lib\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(ProjectDir)..\obj\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="false"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="4"
DebugInformationFormat="1"
DisableSpecificWarnings="4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(ProjectDir)..\lib\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(ProjectDir)..\obj\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
DebugInformationFormat="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\mkvmuxer.cpp"
>
</File>
<File
RelativePath=".\mkvmuxerutil.cpp"
>
</File>
<File
RelativePath=".\mkvparser.cpp"
>
</File>
<File
RelativePath=".\mkvreader.cpp"
>
</File>
<File
RelativePath=".\mkvwriter.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\mkvmuxer.hpp"
>
</File>
<File
RelativePath=".\mkvmuxertypes.hpp"
>
</File>
<File
RelativePath=".\mkvmuxerutil.hpp"
>
</File>
<File
RelativePath=".\mkvparser.hpp"
>
</File>
<File
RelativePath=".\mkvreader.hpp"
>
</File>
<File
RelativePath=".\mkvwriter.hpp"
>
</File>
<File
RelativePath=".\webmids.hpp"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

46
libwebm_2010.sln Normal file
View File

@@ -0,0 +1,46 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample", "sample_2010.vcxproj", "{0CB5681F-6065-490C-98C8-05531732ED7E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwebm", "libwebm_2010.vcxproj", "{7B1F12CA-0724-430B-B61A-1D357C912CBA}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_muxer", "sample_muxer_2010.vcxproj", "{B407561F-1F5E-4798-B9C2-81AB09CFBC16}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug DLL|Win32 = Debug DLL|Win32
Debug|Win32 = Debug|Win32
Release DLL|Win32 = Release DLL|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0CB5681F-6065-490C-98C8-05531732ED7E}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32
{0CB5681F-6065-490C-98C8-05531732ED7E}.Debug DLL|Win32.Build.0 = Debug DLL|Win32
{0CB5681F-6065-490C-98C8-05531732ED7E}.Debug|Win32.ActiveCfg = Debug|Win32
{0CB5681F-6065-490C-98C8-05531732ED7E}.Debug|Win32.Build.0 = Debug|Win32
{0CB5681F-6065-490C-98C8-05531732ED7E}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
{0CB5681F-6065-490C-98C8-05531732ED7E}.Release DLL|Win32.Build.0 = Release DLL|Win32
{0CB5681F-6065-490C-98C8-05531732ED7E}.Release|Win32.ActiveCfg = Release|Win32
{0CB5681F-6065-490C-98C8-05531732ED7E}.Release|Win32.Build.0 = Release|Win32
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Debug DLL|Win32.Build.0 = Debug DLL|Win32
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Debug|Win32.ActiveCfg = Debug|Win32
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Debug|Win32.Build.0 = Debug|Win32
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Release DLL|Win32.Build.0 = Release DLL|Win32
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Release|Win32.ActiveCfg = Release|Win32
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Release|Win32.Build.0 = Release|Win32
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Debug DLL|Win32.Build.0 = Debug DLL|Win32
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Debug|Win32.ActiveCfg = Debug|Win32
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Debug|Win32.Build.0 = Debug|Win32
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Release DLL|Win32.Build.0 = Release DLL|Win32
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Release|Win32.ActiveCfg = Release|Win32
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

150
libwebm_2010.vcxproj Normal file
View File

@@ -0,0 +1,150 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug DLL|Win32">
<Configuration>Debug DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release DLL|Win32">
<Configuration>Release DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>libwebm</ProjectName>
<ProjectGuid>{7B1F12CA-0724-430B-B61A-1D357C912CBA}</ProjectGuid>
<RootNamespace>libwebm</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>Windows7.1SDK</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>Windows7.1SDK</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>Windows7.1SDK</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>Windows7.1SDK</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\lib\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">$(ProjectDir)..\lib\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\lib\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">$(ProjectDir)..\lib\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="mkvmuxer.cpp" />
<ClCompile Include="mkvmuxerutil.cpp" />
<ClCompile Include="mkvparser.cpp" />
<ClCompile Include="mkvreader.cpp" />
<ClCompile Include="mkvwriter.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="mkvmuxer.hpp" />
<ClInclude Include="mkvmuxertypes.hpp" />
<ClInclude Include="mkvmuxerutil.hpp" />
<ClInclude Include="mkvparser.hpp" />
<ClInclude Include="mkvreader.hpp" />
<ClInclude Include="mkvwriter.hpp" />
<ClInclude Include="webmids.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="mkvmuxer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mkvmuxerutil.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mkvparser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mkvreader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mkvwriter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="mkvmuxer.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mkvmuxertypes.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mkvmuxerutil.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mkvparser.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mkvreader.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mkvwriter.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="webmids.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

3020
mkvmuxer.cpp Normal file

File diff suppressed because it is too large Load Diff

1265
mkvmuxer.hpp Normal file

File diff suppressed because it is too large Load Diff

30
mkvmuxertypes.hpp Normal file
View File

@@ -0,0 +1,30 @@
// 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 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 short int16;
typedef int int32;
typedef unsigned int uint32;
typedef long long int64;
typedef unsigned long long uint64;
} //end namespace mkvmuxer
#endif // MKVMUXERTYPES_HPP

630
mkvmuxerutil.cpp Normal file
View File

@@ -0,0 +1,630 @@
// 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.
#include "mkvmuxerutil.hpp"
#ifdef __ANDROID__
#include <fcntl.h>
#endif
#include <cmath>
#include <cstdio>
#ifdef _WIN32
#define _CRT_RAND_S
#endif
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <new>
#include "mkvwriter.hpp"
#include "webmids.hpp"
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(float);
// 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,
uint64 track_number,
int64 timecode,
uint64 is_key) {
if (!writer)
return false;
if (!data || length < 1)
return false;
// Here we only permit track number values to be no greater than
// 126, which the largest value we can store having a Matroska
// integer representation of only 1 byte.
if (track_number < 1 || track_number > 126)
return false;
// Technically the timestamp for a block can be less than the
// timestamp for the cluster itself (remember that block timestamp
// is a signed, 16-bit integer). However, as a simplification we
// only permit non-negative cluster-relative timestamps for blocks.
if (timecode < 0 || timecode > kMaxBlockTimecode)
return false;
if (WriteID(writer, kMkvSimpleBlock))
return 0;
const int32 size = static_cast<int32>(length) + 4;
if (WriteUInt(writer, size))
return 0;
if (WriteUInt(writer, static_cast<uint64>(track_number)))
return 0;
if (SerializeInt(writer, timecode, 2))
return 0;
uint64 flags = 0;
if (is_key)
flags |= 0x80;
if (SerializeInt(writer, flags, 1))
return 0;
if (writer->Write(data, static_cast<uint32>(length)))
return 0;
const uint64 element_size =
GetUIntSize(kMkvSimpleBlock) + GetCodedUIntSize(size) + 4 + length;
return element_size;
}
// We must write the metadata (key)frame as a BlockGroup element,
// because we need to specify a duration for the frame. The
// BlockGroup element comprises the frame itself and its duration,
// and is laid out as follows:
//
// BlockGroup tag
// BlockGroup size
// Block tag
// Block size
// (the frame is the block payload)
// Duration tag
// Duration size
// (duration payload)
//
uint64 WriteMetadataBlock(IMkvWriter* writer,
const uint8* data,
uint64 length,
uint64 track_number,
int64 timecode,
uint64 duration) {
// We don't backtrack when writing to the stream, so we must
// pre-compute the BlockGroup size, by summing the sizes of each
// sub-element (the block and the duration).
// We use a single byte for the track number of the block, which
// means the block header is exactly 4 bytes.
// TODO(matthewjheaney): use EbmlMasterElementSize and WriteEbmlMasterElement
const uint64 block_payload_size = 4 + length;
const int32 block_size = GetCodedUIntSize(block_payload_size);
const uint64 block_elem_size = 1 + block_size + block_payload_size;
const int32 duration_payload_size = GetUIntSize(duration);
const int32 duration_size = GetCodedUIntSize(duration_payload_size);
const uint64 duration_elem_size = 1 + duration_size + duration_payload_size;
const uint64 blockg_payload_size = block_elem_size + duration_elem_size;
const int32 blockg_size = GetCodedUIntSize(blockg_payload_size);
const uint64 blockg_elem_size = 1 + blockg_size + blockg_payload_size;
if (WriteID(writer, kMkvBlockGroup)) // 1-byte ID size
return 0;
if (WriteUInt(writer, blockg_payload_size))
return 0;
// Write Block element
if (WriteID(writer, kMkvBlock)) // 1-byte ID size
return 0;
if (WriteUInt(writer, block_payload_size))
return 0;
// Byte 1 of 4
if (WriteUInt(writer, track_number))
return 0;
// Bytes 2 & 3 of 4
if (SerializeInt(writer, timecode, 2))
return 0;
// Byte 4 of 4
const uint64 flags = 0;
if (SerializeInt(writer, flags, 1))
return 0;
// Now write the actual frame (of metadata)
if (writer->Write(data, static_cast<uint32>(length)))
return 0;
// Write Duration element
if (WriteID(writer, kMkvBlockDuration)) // 1-byte ID size
return 0;
if (WriteUInt(writer, duration_payload_size))
return 0;
if (SerializeInt(writer, duration, duration_payload_size))
return 0;
// Note that we don't write a reference time as part of the block
// group; no reference time(s) indicates that this block is a
// keyframe. (Unlike the case for a SimpleBlock element, the header
// bits of the Block sub-element of a BlockGroup element do not
// indicate keyframe status. The keyframe status is inferred from
// the absence of reference time sub-elements.)
return blockg_elem_size;
}
// Writes a WebM Block with Additional. The structure is as follows
// Indentation shows sub-levels
// BlockGroup
// Block
// Data
// BlockAdditions
// BlockMore
// BlockAddID
// 1 (Denotes Alpha)
// BlockAdditional
// Data
uint64 WriteBlockWithAdditional(IMkvWriter* writer,
const uint8* data,
uint64 length,
const uint8* additional,
uint64 additional_length,
uint64 add_id,
uint64 track_number,
int64 timecode,
uint64 is_key) {
if (!data || !additional || length < 1 || additional_length < 1)
return 0;
const uint64 block_payload_size = 4 + length;
const uint64 block_elem_size = EbmlMasterElementSize(kMkvBlock,
block_payload_size) +
block_payload_size;
const uint64 block_additional_elem_size = EbmlElementSize(kMkvBlockAdditional,
additional,
additional_length);
const uint64 block_addid_elem_size = EbmlElementSize(kMkvBlockAddID, add_id);
const uint64 block_more_payload_size = block_addid_elem_size +
block_additional_elem_size;
const uint64 block_more_elem_size = EbmlMasterElementSize(
kMkvBlockMore,
block_more_payload_size) +
block_more_payload_size;
const uint64 block_additions_payload_size = block_more_elem_size;
const uint64 block_additions_elem_size = EbmlMasterElementSize(
kMkvBlockAdditions,
block_additions_payload_size) +
block_additions_payload_size;
const uint64 block_group_payload_size = block_elem_size +
block_additions_elem_size;
const uint64 block_group_elem_size = EbmlMasterElementSize(
kMkvBlockGroup,
block_group_payload_size) +
block_group_payload_size;
if (!WriteEbmlMasterElement(writer, kMkvBlockGroup,
block_group_payload_size))
return 0;
if (!WriteEbmlMasterElement(writer, kMkvBlock, block_payload_size))
return 0;
if (WriteUInt(writer, track_number))
return 0;
if (SerializeInt(writer, timecode, 2))
return 0;
uint64 flags = 0;
if (is_key)
flags |= 0x80;
if (SerializeInt(writer, flags, 1))
return 0;
if (writer->Write(data, static_cast<uint32>(length)))
return 0;
if (!WriteEbmlMasterElement(writer, kMkvBlockAdditions,
block_additions_payload_size))
return 0;
if (!WriteEbmlMasterElement(writer, kMkvBlockMore, block_more_payload_size))
return 0;
if (!WriteEbmlElement(writer, kMkvBlockAddID, add_id))
return 0;
if (!WriteEbmlElement(writer, kMkvBlockAdditional,
additional, additional_length))
return 0;
return block_group_elem_size;
}
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 = 2;
*build = 1;
*revision = 0;
}
} // namespace mkvmuxer
mkvmuxer::uint64 mkvmuxer::MakeUID(unsigned int* seed) {
uint64 uid = 0;
for (int i = 0; i < 7; ++i) { // avoid problems with 8-byte values
uid <<= 8;
// TODO(fgalligan): Move random number generation to platform specific code.
#ifdef _WIN32
(void)seed;
unsigned int random_value;
const errno_t e = rand_s(&random_value);
(void)e;
const int32 nn = random_value;
#elif __ANDROID__
int32 temp_num = 1;
int fd = open("/dev/urandom", O_RDONLY);
if (fd != -1) {
read(fd, &temp_num, sizeof(int32));
close(fd);
}
const int32 nn = temp_num;
#else
const int32 nn = rand_r(seed);
#endif
const int32 n = 0xFF & (nn >> 4); // throw away low-order bits
uid |= n;
}
return uid;
}

131
mkvmuxerutil.hpp Normal file
View File

@@ -0,0 +1,131 @@
// 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;
const int64 kMaxBlockTimecode = 0x07FFFLL;
// 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.
int32 GetUIntSize(uint64 value);
int32 GetCodedUIntSize(uint64 value);
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. Only values in the range [1, 126] are
// permitted.
// timecode: Relative timecode of the Block. Only values in the
// range [0, 2^15) are permitted.
// is_key: Non-zero value specifies that frame is a key frame.
uint64 WriteSimpleBlock(IMkvWriter* writer,
const uint8* data,
uint64 length,
uint64 track_number,
int64 timecode,
uint64 is_key);
// Output a metadata keyframe, using a Block Group element.
// Inputs:
// data: Pointer to the (meta)data.
// length: Length of the (meta)data.
// track_number: Track to add the data to. Value returned by Add track
// functions. Only values in the range [1, 126] are
// permitted.
// timecode Timecode of frame, relative to cluster timecode. Only
// values in the range [0, 2^15) are permitted.
// duration_timecode Duration of frame, using timecode units.
uint64 WriteMetadataBlock(IMkvWriter* writer,
const uint8* data,
uint64 length,
uint64 track_number,
int64 timecode,
uint64 duration_timecode);
// Output an Mkv Block with BlockAdditional data.
// Inputs:
// data: Pointer to the data.
// length: Length of the data.
// additional: Pointer to the additional data
// additional_length: Length of the additional data.
// add_id: Value of BlockAddID element.
// track_number: Track to add the data to. Value returned by Add track
// functions. Only values in the range [1, 126] are
// permitted.
// timecode: Relative timecode of the Block. Only values in the
// range [0, 2^15) are permitted.
// is_key: Non-zero value specifies that frame is a key frame.
uint64 WriteBlockWithAdditional(IMkvWriter* writer,
const uint8* data,
uint64 length,
const uint8* additional,
uint64 additional_length,
uint64 add_id,
uint64 track_number,
int64 timecode,
uint64 is_key);
// Output a void element. |size| must be the entire size in bytes that will be
// 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);
// Returns a random number to be used for UID, using |seed| to seed
// the random-number generator (see POSIX rand_r() for semantics).
uint64 MakeUID(unsigned int* seed);
} //end namespace mkvmuxer
#endif // MKVMUXERUTIL_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
// 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
@@ -11,6 +11,7 @@
#include <cstdlib>
#include <cstdio>
#include <cstddef>
namespace mkvparser
{
@@ -29,17 +30,26 @@ protected:
long long GetUIntLength(IMkvReader*, long long, long&);
long long ReadUInt(IMkvReader*, long long, long&);
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);
short Unserialize2SInt(IMkvReader*, long long);
signed char Unserialize1SInt(IMkvReader*, long long);
long UnserializeFloat(IMkvReader*, long long pos, long long size, double&);
long UnserializeInt(IMkvReader*, long long pos, long len, long long& result);
long UnserializeString(
IMkvReader*,
long long pos,
long long size,
char*& str);
long ParseElementHeader(
IMkvReader* pReader,
long long& pos, //consume id and size fields
long long stop, //if you know size of element's parent
long long& id,
long long& size);
bool Match(IMkvReader*, long long&, unsigned long, long long&);
bool Match(IMkvReader*, long long&, unsigned long, char*&);
bool Match(IMkvReader*, long long&, unsigned long, unsigned char*&, size_t&);
bool Match(IMkvReader*, long long&, unsigned long, double&);
bool Match(IMkvReader*, long long&, unsigned long, short&);
void GetVersion(int& major, int& minor, int& build, int& revision);
@@ -73,9 +83,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(const Cluster*);
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 +95,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 +126,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 +153,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 +171,153 @@ 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 GetDurationTimeCode() 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:
enum {
kCTR = 1
};
ContentEncoding();
~ContentEncoding();
// ContentCompression element names
struct ContentCompression {
ContentCompression();
~ContentCompression();
unsigned long long algo;
unsigned char* settings;
long long settings_len;
};
// ContentEncAESSettings element names
struct ContentEncAESSettings {
ContentEncAESSettings() : cipher_mode(kCTR) {}
~ContentEncAESSettings() {}
unsigned long long cipher_mode;
};
// 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;
ContentEncAESSettings aes_settings;
};
// 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;
// Parses the ContentCompression element from |pReader|. |start| is the
// starting offset of the ContentCompression payload. |size| is the size in
// bytes of the ContentCompression payload. |compression| is where the parsed
// values will be stored.
long ParseCompressionEntry(long long start,
long long size,
IMkvReader* pReader,
ContentCompression* compression);
// 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 ContentEncAESSettings element from |pReader|. |start| is the
// starting offset of the ContentEncAESSettings payload. |size| is the
// size in bytes of the ContentEncAESSettings payload. |encryption| is
// where the parsed values will be stored.
long ParseContentEncAESSettingsEntry(long long start,
long long size,
IMkvReader* pReader,
ContentEncAESSettings* aes);
// 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.
long ParseContentEncodingEntry(long long start,
long long size,
IMkvReader* 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.
long ParseEncryptionEntry(long long start,
long long size,
IMkvReader* pReader,
ContentEncryption* encryption);
unsigned long long encoding_order() const { return encoding_order_; }
unsigned long long encoding_scope() const { return encoding_scope_; }
unsigned long long encoding_type() const { return encoding_type_; }
private:
// Member variables for list of ContentCompression elements.
ContentCompression** compression_entries_;
ContentCompression** compression_entries_end_;
// Member variables for list of ContentEncryption elements.
ContentEncryption** encryption_entries_;
ContentEncryption** encryption_entries_end_;
// ContentEncoding element names
unsigned long long encoding_order_;
unsigned long long encoding_scope_;
unsigned long long encoding_type_;
// LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncoding);
ContentEncoding(const ContentEncoding&);
ContentEncoding& operator=(const ContentEncoding&);
};
class Track
{
@@ -195,19 +325,36 @@ class Track
Track& operator=(const Track&);
public:
class Info;
static long Create(
Segment*,
const Info&,
long long element_start,
long long element_size,
Track*&);
enum Type {
kVideo = 1,
kAudio = 2,
kSubtitle = 0x11,
kMetadata = 0x21
};
Segment* const m_pSegment;
const long long m_element_start;
const long long m_element_size;
virtual ~Track();
long long GetType() const;
long long GetNumber() const;
long GetType() const;
long GetNumber() const;
unsigned long long GetUid() const;
const char* GetNameAsUTF8() const;
const char* GetLanguage() const;
const char* GetCodecNameAsUTF8() const;
const char* GetCodecId() const;
const unsigned char* GetCodecPrivate(size_t&) const;
bool GetLacing() const;
unsigned long long GetDefaultDuration() const;
const BlockEntry* GetEOS() const;
@@ -217,50 +364,65 @@ public:
long long size;
};
struct Info
class Info
{
long long type;
long long number;
public:
Info();
~Info();
int Copy(Info&) const;
void Clear();
private:
Info(const Info&);
Info& operator=(const Info&);
public:
long type;
long number;
unsigned long long uid;
unsigned long long defaultDuration;
char* nameAsUTF8;
char* language;
char* codecId;
char* codecNameAsUTF8;
unsigned char* codecPrivate;
size_t codecPrivateSize;
char* codecNameAsUTF8;
bool lacing;
Settings settings;
Info();
void Clear();
private:
int CopyStr(char* Info::*str, Info&) const;
};
long GetFirst(const BlockEntry*&) const;
long GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const;
virtual bool VetEntry(const BlockEntry*) const = 0;
virtual long Seek(long long time_ns, const BlockEntry*&) const = 0;
virtual bool VetEntry(const BlockEntry*) const;
virtual long Seek(long long time_ns, const BlockEntry*&) const;
const ContentEncoding* GetContentEncodingByIndex(unsigned long idx) const;
unsigned long GetContentEncodingCount() const;
long ParseContentEncodingsEntry(long long start, long long size);
protected:
Track(
Segment*,
const Info&,
long long element_start,
long long element_size);
const Info m_info;
Info m_info;
class EOSBlock : public BlockEntry
{
public:
EOSBlock();
bool EOS() const;
const Cluster* GetCluster() const;
size_t GetIndex() const;
Kind GetKind() const;
const Block* GetBlock() const;
bool IsBFrame() const;
};
EOSBlock m_eos;
private:
ContentEncoding** content_encoding_entries_;
ContentEncoding** content_encoding_entries_end_;
};
@@ -269,12 +431,19 @@ class VideoTrack : public Track
VideoTrack(const VideoTrack&);
VideoTrack& operator=(const VideoTrack&);
public:
VideoTrack(
Segment*,
long long element_start,
long long element_size);
public:
static long Parse(
Segment*,
const Info&,
long long element_start,
long long element_size);
long long element_size,
VideoTrack*&);
long long GetWidth() const;
long long GetHeight() const;
double GetFrameRate() const;
@@ -295,17 +464,21 @@ class AudioTrack : public Track
AudioTrack(const AudioTrack&);
AudioTrack& operator=(const AudioTrack&);
public:
AudioTrack(
Segment*,
long long element_start,
long long element_size);
public:
static long Parse(
Segment*,
const Info&,
long long element_start,
long long element_size);
long long element_size,
AudioTrack*&);
double GetSamplingRate() const;
long long GetChannels() const;
long long GetBitDepth() const;
bool VetEntry(const BlockEntry*) const;
long Seek(long long time_ns, const BlockEntry*&) const;
private:
double m_rate;
@@ -332,24 +505,152 @@ public:
long long size,
long long element_start,
long long element_size);
virtual ~Tracks();
const Track* GetTrackByNumber(unsigned long tn) const;
~Tracks();
long Parse();
unsigned long GetTracksCount() const;
const Track* GetTrackByNumber(long tn) const;
const Track* GetTrackByIndex(unsigned long idx) const;
private:
Track** m_trackEntries;
Track** m_trackEntriesEnd;
void ParseTrackEntry(
long long,
long long,
Track*&,
long ParseTrackEntry(
long long payload_start,
long long payload_size,
long long element_start,
long long element_size,
Track*&) const;
};
class Chapters
{
Chapters(const Chapters&);
Chapters& operator=(const Chapters&);
public:
Segment* const m_pSegment;
const long long m_start;
const long long m_size;
const long long m_element_start;
const long long m_element_size;
Chapters(
Segment*,
long long payload_start,
long long payload_size,
long long element_start,
long long element_size);
public:
unsigned long GetTracksCount() const;
~Chapters();
long Parse();
class Atom;
class Edition;
class Display
{
friend class Atom;
Display();
Display(const Display&);
~Display();
Display& operator=(const Display&);
public:
const char* GetString() const;
const char* GetLanguage() const;
const char* GetCountry() const;
private:
void Init();
void ShallowCopy(Display&) const;
void Clear();
long Parse(IMkvReader*, long long pos, long long size);
char* m_string;
char* m_language;
char* m_country;
};
class Atom
{
friend class Edition;
Atom();
Atom(const Atom&);
~Atom();
Atom& operator=(const Atom&);
public:
unsigned long long GetUID() const;
const char* GetStringUID() const;
long long GetStartTimecode() const;
long long GetStopTimecode() const;
long long GetStartTime(const Chapters*) const;
long long GetStopTime(const Chapters*) const;
int GetDisplayCount() const;
const Display* GetDisplay(int index) const;
private:
void Init();
void ShallowCopy(Atom&) const;
void Clear();
long Parse(IMkvReader*, long long pos, long long size);
static long long GetTime(const Chapters*, long long timecode);
long ParseDisplay(IMkvReader*, long long pos, long long size);
bool ExpandDisplaysArray();
char* m_string_uid;
unsigned long long m_uid;
long long m_start_timecode;
long long m_stop_timecode;
Display* m_displays;
int m_displays_size;
int m_displays_count;
};
class Edition
{
friend class Chapters;
Edition();
Edition(const Edition&);
~Edition();
Edition& operator=(const Edition&);
public:
int GetAtomCount() const;
const Atom* GetAtom(int index) const;
private:
void Init();
void ShallowCopy(Edition&) const;
void Clear();
long Parse(IMkvReader*, long long pos, long long size);
long ParseAtom(IMkvReader*, long long pos, long long size);
bool ExpandAtomsArray();
Atom* m_atoms;
int m_atoms_size;
int m_atoms_count;
};
int GetEditionCount() const;
const Edition* GetEdition(int index) const;
private:
long ParseEdition(long long pos, long long size);
bool ExpandEditionsArray();
Edition* m_editions;
int m_editions_size;
int m_editions_count;
};
@@ -374,6 +675,8 @@ public:
~SegmentInfo();
long Parse();
long long GetTimeCodeScale() const;
long long GetDuration() const; //scaled
const char* GetMuxingAppAsUTF8() const;
@@ -410,24 +713,48 @@ public:
~SeekHead();
long Parse();
struct Entry
{
//the SeekHead entry payload
long long id;
long long pos;
//absolute pos of SeekEntry ID
long long element_start;
//SeekEntry ID size + size size + payload
long long element_size;
};
int GetCount() const;
const Entry* GetEntry(int idx) const;
struct VoidElement
{
//absolute pos of Void ID
long long element_start;
//ID size + size size + payload size
long long element_size;
};
int GetVoidElementCount() const;
const VoidElement* GetVoidElement(int idx) const;
private:
Entry* m_entries;
int m_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*);
};
@@ -562,9 +889,10 @@ 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&,
@@ -581,11 +909,8 @@ public:
long GetEntryCount() const;
//void Load() const;
long Load(long long& pos, long& size) const;
//void LoadBlockEntries() const;
long Parse(long long& pos, long& size) const;
long GetEntry(long index, const mkvparser::BlockEntry*&) const;
@@ -616,12 +941,12 @@ private:
mutable long m_entries_size;
mutable long m_entries_count;
long ParseSimpleBlock(long long, long long&, long&) const;
long ParseBlockGroup(long long, long long&, long&) const;
long ParseSimpleBlock(long long, long long&, long&);
long ParseBlockGroup(long long, long long&, long&);
void CreateBlock(long long id, long long pos, long long size) const;
void CreateBlockGroup(long long, long long, BlockEntry**&) const;
void CreateSimpleBlock(long long, long long, BlockEntry**&) const;
long CreateBlock(long long id, long long pos, long long size);
long CreateBlockGroup(long long, long long);
long CreateSimpleBlock(long long, long long);
};
@@ -629,17 +954,24 @@ private:
class Segment
{
friend class Cues;
friend class Track;
friend class VideoTrack;
friend class AudioTrack;
Segment(const 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?
@@ -674,6 +1006,7 @@ public:
const Tracks* GetTracks() const;
const SegmentInfo* GetInfo() const;
const Cues* GetCues() const;
const Chapters* GetChapters() const;
long long GetDuration() const;
@@ -701,6 +1034,7 @@ private:
SegmentInfo* m_pInfo;
Tracks* m_pTracks;
Cues* m_pCues;
Chapters* m_pChapters;
Cluster** m_clusters;
long m_clusterCount; //number of entries for which m_index >= 0
long m_clusterPreloadCount; //number of entries for which m_index < 0

View File

@@ -1,34 +0,0 @@

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}"
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}"
ProjectSection(WebsiteProperties) = preProject
Debug.AspNetCompiler.Debug = "True"
Release.AspNetCompiler.Debug = "False"
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

@@ -1,176 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="mkvparser"
ProjectGUID="{F9128EC6-C008-41AD-B38F-0E70D549D9F4}"
RootNamespace="mkvparser"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
UseOfMFC="0"
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="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<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"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
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>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\mkvparser.cpp"
>
</File>
<File
RelativePath=".\mkvreader.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\mkvparser.hpp"
>
</File>
<File
RelativePath=".\mkvreader.hpp"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

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&);
@@ -22,7 +25,6 @@ public:
int Open(const char*);
void Close();
bool IsOpen() const;
virtual int Read(long long position, long length, unsigned char* buffer);
virtual int Length(long long* total, long long* available);
@@ -31,4 +33,6 @@ private:
FILE* m_file;
};
} //end namespace mkvparser
#endif //MKVREADER_HPP

94
mkvwriter.cpp Normal file
View File

@@ -0,0 +1,94 @@
// 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.
#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

@@ -11,6 +11,17 @@
#include "mkvreader.hpp"
#include "mkvparser.hpp"
#include <memory>
#ifdef _MSC_VER
// Silences these warnings:
// warning C4996: 'mbstowcs': This function or variable may be unsafe. Consider
// using mbstowcs_s instead. To disable deprecation, use
// _CRT_SECURE_NO_WARNINGS. See online help for details.
// Fixing this warning requires use of a function available only on Windows,
// and this sample code must support non-windows platforms.
#pragma warning(disable:4996)
#endif
static const wchar_t* utf8towcs(const char* str)
{
@@ -73,15 +84,18 @@ int main(int argc, char* argv[])
printf("\t\tDoc Type\t\t: %s\n", ebmlHeader.m_docType);
printf("\t\tPos\t\t\t: %lld\n", pos);
mkvparser::Segment* pSegment;
typedef mkvparser::Segment seg_t;
seg_t* pSegment_;
long long ret = mkvparser::Segment::CreateInstance(&reader, pos, pSegment);
long long ret = seg_t::CreateInstance(&reader, pos, pSegment_);
if (ret)
{
printf("\n Segment::CreateInstance() failed.");
return -1;
}
const std::auto_ptr<seg_t> pSegment(pSegment_);
ret = pSegment->Load();
if (ret < 0)
{
@@ -147,8 +161,6 @@ int main(int argc, char* argv[])
unsigned long i = 0;
const unsigned long j = pTracks->GetTracksCount();
enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
printf("\n\t\t\t Track Info\n");
while (i != j)
@@ -158,13 +170,13 @@ int main(int argc, char* argv[])
if (pTrack == NULL)
continue;
const long long trackType = pTrack->GetType();
const long long trackNumber = pTrack->GetNumber();
const long trackType = pTrack->GetType();
const long trackNumber = pTrack->GetNumber();
const unsigned long long trackUid = pTrack->GetUid();
const wchar_t* const pTrackName = utf8towcs(pTrack->GetNameAsUTF8());
printf("\t\tTrack Type\t\t: %lld\n", trackType);
printf("\t\tTrack Number\t\t: %lld\n", trackNumber);
printf("\t\tTrack Type\t\t: %ld\n", trackType);
printf("\t\tTrack Number\t\t: %ld\n", trackNumber);
printf("\t\tTrack Uid\t\t: %lld\n", trackUid);
if (pTrackName == NULL)
@@ -193,7 +205,7 @@ int main(int argc, char* argv[])
delete [] pCodecName;
}
if (trackType == VIDEO_TRACK)
if (trackType == mkvparser::Track::kVideo)
{
const VideoTrack* const pVideoTrack =
static_cast<const VideoTrack*>(pTrack);
@@ -208,7 +220,7 @@ int main(int argc, char* argv[])
printf("\t\tVideo Rate\t\t: %f\n",rate);
}
if (trackType == AUDIO_TRACK)
if (trackType == mkvparser::Track::kAudio)
{
const AudioTrack* const pAudioTrack =
static_cast<const AudioTrack*>(pTrack);
@@ -232,7 +244,6 @@ int main(int argc, char* argv[])
if (clusterCount == 0)
{
printf("\t\tSegment has no clusters.\n");
delete pSegment;
return -1;
}
@@ -246,7 +257,16 @@ int main(int argc, char* argv[])
const long long time_ns = pCluster->GetTime();
printf("\t\tCluster Time (ns)\t: %lld\n", time_ns);
const BlockEntry* pBlockEntry = pCluster->GetFirst();
const BlockEntry* pBlockEntry;
long status = pCluster->GetFirst(pBlockEntry);
if (status < 0) //error
{
printf("\t\tError parsing first block of cluster\n");
fflush(stdout);
return -1;
}
while ((pBlockEntry != NULL) && !pBlockEntry->EOS())
{
@@ -254,30 +274,42 @@ int main(int argc, char* argv[])
const long long trackNum = pBlock->GetTrackNumber();
const unsigned long tn = static_cast<unsigned long>(trackNum);
const Track* const pTrack = pTracks->GetTrackByNumber(tn);
const long long trackType = pTrack->GetType();
const int frameCount = pBlock->GetFrameCount();
const long long time_ns = pBlock->GetTime(pCluster);
printf("\t\t\tBlock\t\t:%s,%s,%15lld\n",
(trackType == VIDEO_TRACK) ? "V" : "A",
pBlock->IsKey() ? "I" : "P",
time_ns);
for (int i = 0; i < frameCount; ++i)
if (pTrack == NULL)
printf("\t\t\tBlock\t\t:UNKNOWN TRACK TYPE\n");
else
{
const Block::Frame& theFrame = pBlock->GetFrame(i);
const long size = theFrame.len;
const long long offset = theFrame.pos;
printf("\t\t\t %15ld,%15llx\n", size, offset);
const long long trackType = pTrack->GetType();
const int frameCount = pBlock->GetFrameCount();
const long long time_ns = pBlock->GetTime(pCluster);
printf("\t\t\tBlock\t\t:%s,%s,%15lld\n",
(trackType == mkvparser::Track::kVideo) ? "V" : "A",
pBlock->IsKey() ? "I" : "P",
time_ns);
for (int i = 0; i < frameCount; ++i)
{
const Block::Frame& theFrame = pBlock->GetFrame(i);
const long size = theFrame.len;
const long long offset = theFrame.pos;
printf("\t\t\t %15ld,%15llx\n", size, offset);
}
}
pBlockEntry = pCluster->GetNext(pBlockEntry);
status = pCluster->GetNext(pBlockEntry, pBlockEntry);
if (status < 0)
{
printf("\t\t\tError parsing next block of cluster\n");
fflush(stdout);
return -1;
}
}
pCluster = pSegment->GetNext(pCluster);
}
delete pSegment;
fflush(stdout);
return 0;
}

View File

@@ -1,193 +1,181 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="sample"
ProjectGUID="{0CB5681F-6065-490C-98C8-05531732ED7E}"
RootNamespace="sample"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(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="false"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies=".\Debug\mkvparser.lib"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(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"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies=".\Release\mkvparser.lib"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<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.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="sample"
ProjectGUID="{0CB5681F-6065-490C-98C8-05531732ED7E}"
RootNamespace="sample"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(ProjectDir)..\exe\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(ProjectDir)..\obj\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="false"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(ProjectDir)..\lib\libwebm_2008\libwebm\$(PlatformName)\$(ConfigurationName)\libwebm.lib"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(ProjectDir)..\exe\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(ProjectDir)..\obj\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(ProjectDir)..\lib\libwebm_2008\libwebm\$(PlatformName)\$(ConfigurationName)\libwebm.lib"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=".\sample.cpp"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

181
sample_2010.vcxproj Normal file
View File

@@ -0,0 +1,181 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug DLL|Win32">
<Configuration>Debug DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release DLL|Win32">
<Configuration>Release DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>sample</ProjectName>
<ProjectGuid>{0CB5681F-6065-490C-98C8-05531732ED7E}</ProjectGuid>
<RootNamespace>sample</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>Windows7.1SDK</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>Windows7.1SDK</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>Windows7.1SDK</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>Windows7.1SDK</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="sample.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libwebm_2010.vcxproj">
<Project>{7b1f12ca-0724-430b-b61a-1d357c912cba}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="sample.cpp" />
</ItemGroup>
</Project>

540
sample_muxer.cpp Normal file
View File

@@ -0,0 +1,540 @@
// 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>
#include <list>
#include <string>
// libwebm parser includes
#include "mkvreader.hpp"
#include "mkvparser.hpp"
// libwebm muxer includes
#include "mkvmuxer.hpp"
#include "mkvwriter.hpp"
#include "mkvmuxerutil.hpp"
#include "sample_muxer_metadata.h"
using mkvmuxer::uint64;
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(" -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");
printf(" -cues_before_clusters <int> >0 puts Cues before Clusters\n");
printf("\n");
printf("Metadata options:\n");
printf(" -webvtt-subtitles <vttfile> "
"add WebVTT subtitles as metadata track\n");
printf(" -webvtt-captions <vttfile> "
"add WebVTT captions as metadata track\n");
printf(" -webvtt-descriptions <vttfile> "
"add WebVTT descriptions as metadata track\n");
printf(" -webvtt-metadata <vttfile> "
"add WebVTT subtitles as metadata track\n");
printf(" -webvtt-chapters <vttfile> "
"add WebVTT chapters as MKV chapters element\n");
}
struct MetadataFile {
const char* name;
SampleMuxerMetadata::Kind kind;
};
typedef std::list<MetadataFile> metadata_files_t;
// Cache the WebVTT filenames specified as command-line args.
bool LoadMetadataFiles(
const metadata_files_t& files,
SampleMuxerMetadata* metadata) {
typedef metadata_files_t::const_iterator iter_t;
iter_t i = files.begin();
const iter_t j = files.end();
while (i != j) {
const metadata_files_t::value_type& v = *i++;
if (!metadata->Load(v.name, v.kind))
return false;
}
return true;
}
int ParseArgWebVTT(
char* argv[],
int* argv_index,
int argc_check,
metadata_files_t* metadata_files) {
int& i = *argv_index;
enum { kCount = 5 };
struct Arg { const char* name; SampleMuxerMetadata::Kind kind; };
const Arg args[kCount] = {
{ "-webvtt-subtitles", SampleMuxerMetadata::kSubtitles },
{ "-webvtt-captions", SampleMuxerMetadata::kCaptions },
{ "-webvtt-descriptions", SampleMuxerMetadata::kDescriptions },
{ "-webvtt-metadata", SampleMuxerMetadata::kMetadata },
{ "-webvtt-chapters", SampleMuxerMetadata::kChapters }
};
for (int idx = 0; idx < kCount; ++idx) {
const Arg& arg = args[idx];
if (strcmp(arg.name, argv[i]) != 0) // no match
continue;
++i; // consume arg name here
if (i > argc_check) {
printf("missing value for %s\n", arg.name);
return -1; // error
}
MetadataFile f;
f.name = argv[i]; // arg value is consumed via caller's loop idx
f.kind = arg.kind;
metadata_files->push_back(f);
return 1; // successfully parsed WebVTT arg
}
return 0; // not a WebVTT arg
}
} // end namespace
int main(int argc, char* argv[]) {
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_before_clusters = false;
bool cues_on_video_track = true;
bool cues_on_audio_track = false;
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;
metadata_files_t metadata_files;
const int argc_check = argc - 1;
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]) && i < argc_check) {
input = argv[++i];
} else if (!strcmp("-o", argv[i]) && i < argc_check) {
output = argv[++i];
} else if (!strcmp("-video", argv[i]) && i < argc_check) {
output_video = strtol(argv[++i], &end, 10) == 0 ? false : true;
} else if (!strcmp("-audio", argv[i]) && i < argc_check) {
output_audio = strtol(argv[++i], &end, 10) == 0 ? false : true;
} else if (!strcmp("-live", argv[i]) && i < argc_check) {
live_mode = strtol(argv[++i], &end, 10) == 0 ? false : true;
} else if (!strcmp("-output_cues", argv[i]) && i < argc_check) {
output_cues = strtol(argv[++i], &end, 10) == 0 ? false : true;
} else if (!strcmp("-cues_before_clusters", argv[i]) && i < argc_check) {
cues_before_clusters = strtol(argv[++i], &end, 10) == 0 ? false : true;
} else if (!strcmp("-cues_on_video_track", argv[i]) && i < argc_check) {
cues_on_video_track = strtol(argv[++i], &end, 10) == 0 ? false : true;
if (cues_on_video_track)
cues_on_audio_track = false;
} else if (!strcmp("-cues_on_audio_track", argv[i]) && i < argc_check) {
cues_on_audio_track = strtol(argv[++i], &end, 10) == 0 ? false : true;
if (cues_on_audio_track)
cues_on_video_track = false;
} else if (!strcmp("-max_cluster_duration", argv[i]) && i < argc_check) {
const double seconds = strtod(argv[++i], &end);
max_cluster_duration =
static_cast<uint64>(seconds * 1000000000.0);
} else if (!strcmp("-max_cluster_size", argv[i]) && i < argc_check) {
max_cluster_size = strtol(argv[++i], &end, 10);
} else if (!strcmp("-switch_tracks", argv[i]) && i < argc_check) {
switch_tracks = strtol(argv[++i], &end, 10) == 0 ? false : true;
} else if (!strcmp("-audio_track_number", argv[i]) && i < argc_check) {
audio_track_number = strtol(argv[++i], &end, 10);
} else if (!strcmp("-video_track_number", argv[i]) && i < argc_check) {
video_track_number = strtol(argv[++i], &end, 10);
} else if (!strcmp("-chunking", argv[i]) && i < argc_check) {
chunking = true;
chunk_name = argv[++i];
} else if (!strcmp("-display_width", argv[i]) && i < argc_check) {
display_width = strtol(argv[++i], &end, 10);
} else if (!strcmp("-display_height", argv[i]) && i < argc_check) {
display_height = strtol(argv[++i], &end, 10);
} else if (!strcmp("-stereo_mode", argv[i]) && i < argc_check) {
stereo_mode = strtol(argv[++i], &end, 10);
} else if (!strcmp("-output_cues_block_number", argv[i]) &&
i < argc_check) {
output_cues_block_number =
strtol(argv[++i], &end, 10) == 0 ? false : true;
} else if (int e = ParseArgWebVTT(argv, &i, argc_check, &metadata_files)) {
if (e < 0)
return EXIT_FAILURE;
}
}
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;
char* temp_file = tmpnam(NULL);
if (!writer.Open(cues_before_clusters ? temp_file : 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
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
using mkvparser::Track;
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 == Track::kVideo && 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 == Track::kAudio && 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);
}
}
// We have created all the video and audio tracks. If any WebVTT
// files were specified as command-line args, then parse them and
// add a track to the output file corresponding to each metadata
// input file.
SampleMuxerMetadata metadata;
if (!metadata.Init(&muxer_segment)) {
printf("\n Could not initialize metadata cache.\n");
return EXIT_FAILURE;
}
if (!LoadMetadataFiles(metadata_files, &metadata))
return EXIT_FAILURE;
if (!metadata.AddChapters())
return EXIT_FAILURE;
// 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();
const long long time_ns = block->GetTime(cluster);
// Flush any metadata frames to the output file, before we write
// the current block.
if (!metadata.Write(time_ns))
return EXIT_FAILURE;
if ((track_type == Track::kAudio && output_audio) ||
(track_type == Track::kVideo && output_video)) {
const int frame_count = block->GetFrameCount();
const bool is_key = block->IsKey();
for (int i = 0; i < frame_count; ++i) {
const mkvparser::Block::Frame& frame = block->GetFrame(i);
if (frame.len > data_len) {
delete [] data;
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 == Track::kAudio)
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);
}
// We have exhausted all video and audio frames in the input file.
// Flush any remaining metadata frames to the output file.
if (!metadata.Write(-1))
return EXIT_FAILURE;
if (!muxer_segment.Finalize()) {
printf("Finalization of segment failed.\n");
return EXIT_FAILURE;
}
reader.Close();
writer.Close();
if (cues_before_clusters) {
if (reader.Open(temp_file)) {
printf("\n Filename is invalid or error while opening.\n");
return EXIT_FAILURE;
}
if (!writer.Open(output)) {
printf("\n Filename is invalid or error while opening.\n");
return EXIT_FAILURE;
}
if (!muxer_segment.CopyAndMoveCuesBeforeClusters(&reader, &writer)) {
printf("\n Unable to copy and move cues before clusters.\n");
return EXIT_FAILURE;
}
reader.Close();
writer.Close();
remove(temp_file);
}
delete [] data;
delete parser_segment;
return EXIT_SUCCESS;
}

View File

@@ -1,193 +1,179 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="sample"
ProjectGUID="{0CB5681F-6065-490C-98C8-05531732ED7E}"
RootNamespace="sample"
Keyword="Win32Proj"
>
<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="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies=".\Debug\mkvparser.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="VCWebDeploymentTool"
/>
<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"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
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="VCWebDeploymentTool"
/>
<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.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="sample_muxer"
ProjectGUID="{B407561F-1F5E-4798-B9C2-81AB09CFBC16}"
RootNamespace="sample_muxer"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(ProjectDir)..\exe\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(ProjectDir)..\obj\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(ProjectDir)..\lib\libwebm_2008\libwebm\$(PlatformName)\$(ConfigurationName)\libwebm.lib"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(ProjectDir)..\exe\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(ProjectDir)..\obj\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="../"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(ProjectDir)..\lib\libwebm_2008\libwebm\$(PlatformName)\$(ConfigurationName)\libwebm.lib"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=".\sample_muxer.cpp"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

185
sample_muxer_2010.vcxproj Normal file
View File

@@ -0,0 +1,185 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug DLL|Win32">
<Configuration>Debug DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release DLL|Win32">
<Configuration>Release DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>sample_muxer</ProjectName>
<ProjectGuid>{B407561F-1F5E-4798-B9C2-81AB09CFBC16}</ProjectGuid>
<RootNamespace>sample_muxer</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>Windows7.1SDK</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>Windows7.1SDK</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>Windows7.1SDK</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>Windows7.1SDK</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">$(ProjectDir)..\exe\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">$(ProjectDir)..\obj\libwebm_2010\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>$(ProjectDir)..\lib\libwebm_2010\libwebm\$(Platform)\$(Configuration)\libwebm.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="sample_muxer.cpp" />
<ClCompile Include="sample_muxer_metadata.cc" />
<ClCompile Include="vttreader.cc" />
<ClCompile Include="webvttparser.cc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libwebm_2010.vcxproj">
<Project>{7b1f12ca-0724-430b-b61a-1d357c912cba}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="sample_muxer_metadata.h" />
<ClInclude Include="vttreader.h" />
<ClInclude Include="webvttparser.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="sample_muxer.cpp" />
<ClCompile Include="sample_muxer_metadata.cc" />
<ClCompile Include="vttreader.cc" />
<ClCompile Include="webvttparser.cc" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="sample_muxer_metadata.h" />
<ClInclude Include="vttreader.h" />
<ClInclude Include="webvttparser.h" />
</ItemGroup>
</Project>

379
sample_muxer_metadata.cc Normal file
View File

@@ -0,0 +1,379 @@
#include "sample_muxer_metadata.h"
#include <string>
#include "vttreader.h"
SampleMuxerMetadata::SampleMuxerMetadata() : segment_(NULL) {
}
bool SampleMuxerMetadata::Init(mkvmuxer::Segment* segment) {
if (segment == NULL || segment_ != NULL)
return false;
segment_ = segment;
return true;
}
bool SampleMuxerMetadata::Load(const char* file, Kind kind) {
if (kind == kChapters)
return LoadChapters(file);
mkvmuxer::uint64 track_num;
if (!AddTrack(kind, &track_num)) {
printf("Unable to add track for WebVTT file \"%s\"\n", file);
return false;
}
return Parse(file, kind, track_num);
}
bool SampleMuxerMetadata::AddChapters() {
typedef cue_list_t::const_iterator iter_t;
iter_t i = chapter_cues_.begin();
const iter_t j = chapter_cues_.end();
while (i != j) {
const cue_t& chapter = *i++;
if (!AddChapter(chapter))
return false;
}
return true;
}
bool SampleMuxerMetadata::Write(mkvmuxer::int64 time_ns) {
typedef cues_set_t::iterator iter_t;
iter_t i = cues_set_.begin();
const iter_t j = cues_set_.end();
while (i != j) {
const cues_set_t::value_type& v = *i;
if (time_ns >= 0 && v > time_ns)
return true; // nothing else to do just yet
if (!v.Write(segment_)) {
printf("\nCould not add metadata.\n");
return false; // error
}
cues_set_.erase(i++);
}
return true;
}
bool SampleMuxerMetadata::LoadChapters(const char* file) {
if (!chapter_cues_.empty()) {
printf("Support for more than one chapters file is not yet implemented\n");
return false;
}
cue_list_t cues;
if (!ParseChapters(file, &cues))
return false;
// TODO(matthewjheaney): support more than one chapters file
chapter_cues_.swap(cues);
return true;
}
bool SampleMuxerMetadata::ParseChapters(
const char* file,
cue_list_t* cues_ptr) {
cue_list_t& cues = *cues_ptr;
cues.clear();
libwebvtt::VttReader r;
int e = r.Open(file);
if (e) {
printf("Unable to open WebVTT file: \"%s\"\n", file);
return false;
}
libwebvtt::Parser p(&r);
e = p.Init();
if (e < 0) { // error
printf("Error parsing WebVTT file: \"%s\"\n", file);
return false;
}
libwebvtt::Time t;
t.hours = -1;
for (;;) {
cue_t c;
e = p.Parse(&c);
if (e < 0) { // error
printf("Error parsing WebVTT file: \"%s\"\n", file);
return false;
}
if (e > 0) // EOF
return true;
if (c.start_time < t) {
printf("bad WebVTT cue timestamp (out-of-order)\n");
return false;
}
if (c.stop_time < c.start_time) {
printf("bad WebVTT cue timestamp (stop < start)\n");
return false;
}
t = c.start_time;
cues.push_back(c);
}
}
bool SampleMuxerMetadata::AddChapter(const cue_t& cue) {
// TODO(matthewjheaney): support language and country
mkvmuxer::Chapter* const chapter = segment_->AddChapter();
if (chapter == NULL) {
printf("Unable to add chapter\n");
return false;
}
if (cue.identifier.empty()) {
chapter->set_id(NULL);
} else {
const char* const id = cue.identifier.c_str();
if (!chapter->set_id(id)) {
printf("Unable to set chapter id\n");
return false;
}
}
typedef libwebvtt::presentation_t time_ms_t;
const time_ms_t start_time_ms = cue.start_time.presentation();
const time_ms_t stop_time_ms = cue.stop_time.presentation();
enum { kNsPerMs = 1000000 };
const mkvmuxer::uint64 start_time_ns = start_time_ms * kNsPerMs;
const mkvmuxer::uint64 stop_time_ns = stop_time_ms * kNsPerMs;
chapter->set_time(*segment_, start_time_ns, stop_time_ns);
typedef libwebvtt::Cue::payload_t::const_iterator iter_t;
iter_t i = cue.payload.begin();
const iter_t j = cue.payload.end();
std::string title;
for (;;) {
title += *i++;
if (i == j)
break;
enum { kLF = '\x0A' };
title += kLF;
}
if (!chapter->add_string(title.c_str(), NULL, NULL)) {
printf("Unable to set chapter title\n");
return false;
}
return true;
}
bool SampleMuxerMetadata::AddTrack(
Kind kind,
mkvmuxer::uint64* track_num) {
*track_num = 0;
// Track number value 0 means "let muxer choose track number"
mkvmuxer::Track* const track = segment_->AddTrack(0);
if (track == NULL) // error
return false;
// Return the track number value chosen by the muxer
*track_num = track->number();
int type;
const char* codec_id;
switch (kind) {
case kSubtitles:
type = 0x11;
codec_id = "D_WEBVTT/SUBTITLES";
break;
case kCaptions:
type = 0x11;
codec_id = "D_WEBVTT/CAPTIONS";
break;
case kDescriptions:
type = 0x21;
codec_id = "D_WEBVTT/DESCRIPTIONS";
break;
case kMetadata:
type = 0x21;
codec_id = "D_WEBVTT/METADATA";
break;
default:
return false;
}
track->set_type(type);
track->set_codec_id(codec_id);
// TODO(matthewjheaney): set name and language
return true;
}
bool SampleMuxerMetadata::Parse(
const char* file,
Kind /* kind */,
mkvmuxer::uint64 track_num) {
libwebvtt::VttReader r;
int e = r.Open(file);
if (e) {
printf("Unable to open WebVTT file: \"%s\"\n", file);
return false;
}
libwebvtt::Parser p(&r);
e = p.Init();
if (e < 0) { // error
printf("Error parsing WebVTT file: \"%s\"\n", file);
return false;
}
SortableCue cue;
cue.track_num = track_num;
libwebvtt::Time t;
t.hours = -1;
for (;;) {
cue_t& c = cue.cue;
e = p.Parse(&c);
if (e < 0) { // error
printf("Error parsing WebVTT file: \"%s\"\n", file);
return false;
}
if (e > 0) // EOF
return true;
if (c.start_time >= t) {
t = c.start_time;
} else {
printf("bad WebVTT cue timestamp (out-of-order)\n");
return false;
}
if (c.stop_time < c.start_time) {
printf("bad WebVTT cue timestamp (stop < start)\n");
return false;
}
cues_set_.insert(cue);
}
}
void SampleMuxerMetadata::MakeFrame(const cue_t& c, std::string* pf) {
pf->clear();
WriteCueIdentifier(c.identifier, pf);
WriteCueSettings(c.settings, pf);
WriteCuePayload(c.payload, pf);
}
void SampleMuxerMetadata::WriteCueIdentifier(
const std::string& identifier,
std::string* pf) {
pf->append(identifier);
pf->push_back('\x0A'); // LF
}
void SampleMuxerMetadata::WriteCueSettings(
const cue_t::settings_t& settings,
std::string* pf) {
if (settings.empty()) {
pf->push_back('\x0A'); // LF
return;
}
typedef cue_t::settings_t::const_iterator iter_t;
iter_t i = settings.begin();
const iter_t j = settings.end();
for (;;) {
const libwebvtt::Setting& setting = *i++;
pf->append(setting.name);
pf->push_back(':');
pf->append(setting.value);
if (i == j)
break;
pf->push_back(' '); // separate settings with whitespace
}
pf->push_back('\x0A'); // LF
}
void SampleMuxerMetadata::WriteCuePayload(
const cue_t::payload_t& payload,
std::string* pf) {
typedef cue_t::payload_t::const_iterator iter_t;
iter_t i = payload.begin();
const iter_t j = payload.end();
while (i != j) {
const std::string& line = *i++;
pf->append(line);
pf->push_back('\x0A'); // LF
}
}
bool SampleMuxerMetadata::SortableCue::Write(
mkvmuxer::Segment* segment) const {
// Cue start time expressed in milliseconds
const mkvmuxer::int64 start_ms = cue.start_time.presentation();
// Cue start time expressed in nanoseconds (MKV time)
const mkvmuxer::int64 start_ns = start_ms * 1000000;
// Cue stop time expressed in milliseconds
const mkvmuxer::int64 stop_ms = cue.stop_time.presentation();
// Cue stop time expressed in nanonseconds
const mkvmuxer::int64 stop_ns = stop_ms * 1000000;
// Metadata blocks always specify the block duration.
const mkvmuxer::int64 duration_ns = stop_ns - start_ns;
std::string frame;
MakeFrame(cue, &frame);
typedef const mkvmuxer::uint8* data_t;
const data_t buf = reinterpret_cast<data_t>(frame.data());
const mkvmuxer::uint64 len = frame.length();
return segment->AddMetadata(buf, len, track_num, start_ns, duration_ns);
}

135
sample_muxer_metadata.h Normal file
View File

@@ -0,0 +1,135 @@
// 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 SAMPLE_MUXER_METADATA_H_ // NOLINT
#define SAMPLE_MUXER_METADATA_H_
#include <list>
#include <set>
#include "mkvmuxer.hpp"
#include "webvttparser.h"
class SampleMuxerMetadata {
public:
enum Kind {
kSubtitles,
kCaptions,
kDescriptions,
kMetadata,
kChapters
};
SampleMuxerMetadata();
// Bind this metadata object to the muxer instance. Returns false
// if segment equals NULL, or Init has already been called.
bool Init(mkvmuxer::Segment* segment);
// Parse the WebVTT file |filename| having the indicated |kind|, and
// create a corresponding track (or chapters element) in the
// segment. Returns false on error.
bool Load(const char* filename, Kind kind);
bool AddChapters();
// Write any WebVTT cues whose time is less or equal to |time_ns| as
// a metadata block in its corresponding track. If |time_ns| is
// negative, write all remaining cues. Returns false on error.
bool Write(mkvmuxer::int64 time_ns);
private:
typedef libwebvtt::Cue cue_t;
// Used to sort cues as they are loaded.
struct SortableCue {
bool operator>(mkvmuxer::int64 time_ns) const {
// Cue start time expressed in milliseconds
const mkvmuxer::int64 start_ms = cue.start_time.presentation();
// Cue start time expressed in nanoseconds (MKV time)
const mkvmuxer::int64 start_ns = start_ms * 1000000;
return (start_ns > time_ns);
}
bool operator<(const SortableCue& rhs) const {
if (cue.start_time < rhs.cue.start_time)
return true;
if (cue.start_time > rhs.cue.start_time)
return false;
return (track_num < rhs.track_num);
}
// Write this cue as a metablock to |segment|. Returns false on
// error.
bool Write(mkvmuxer::Segment* segment) const;
mkvmuxer::uint64 track_num;
cue_t cue;
};
typedef std::multiset<SortableCue> cues_set_t;
typedef std::list<cue_t> cue_list_t;
// Parse the WebVTT cues in the named |file|, returning false on
// error. We handle chapters as a special case, because they are
// stored in their own, dedicated level-1 element.
bool LoadChapters(const char* file);
// Parse the WebVTT chapters in |file| to populate |cues|. Returns
// false on error.
static bool ParseChapters(const char* file,
cue_list_t* cues);
// Adds WebVTT cue |chapter| to the chapters element of the output
// file's segment element. Returns false on error.
bool AddChapter(const cue_t& chapter);
// Add a metadata track to the segment having the indicated |kind|,
// returning the |track_num| that has been chosen for this track.
// Returns false on error.
bool AddTrack(Kind kind, mkvmuxer::uint64* track_num);
// Parse the WebVTT |file| having the indicated |kind| and
// |track_num|, adding each parsed cue to cues set. Returns false
// on error.
bool Parse(const char* file, Kind kind, mkvmuxer::uint64 track_num);
// Converts a WebVTT cue to a Matroska metadata block.
static void MakeFrame(const cue_t& cue, std::string* frame);
// Populate the cue identifier part of the metadata block.
static void WriteCueIdentifier(const std::string& identifier,
std::string* frame);
// Populate the cue settings part of the metadata block.
static void WriteCueSettings(const cue_t::settings_t& settings,
std::string* frame);
// Populate the payload part of the metadata block.
static void WriteCuePayload(const cue_t::payload_t& payload,
std::string* frame);
mkvmuxer::Segment* segment_;
// Set of cues ordered by time and then by track number.
cues_set_t cues_set_;
// The cues that will be used to populate the Chapters level-1
// element of the output file.
cue_list_t chapter_cues_;
// Disable copy ctor and copy assign.
SampleMuxerMetadata(const SampleMuxerMetadata&);
SampleMuxerMetadata& operator=(const SampleMuxerMetadata&);
};
#endif // SAMPLE_MUXER_METADATA_H_ // NOLINT

1037
vttdemux.cc Normal file

File diff suppressed because it is too large Load Diff

57
vttreader.cc Normal file
View File

@@ -0,0 +1,57 @@
// 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.
#include "./vttreader.h" // NOLINT
namespace libwebvtt {
VttReader::VttReader() : file_(NULL) {
}
VttReader::~VttReader() {
Close();
}
int VttReader::Open(const char* filename) {
if (filename == NULL || file_ != NULL)
return -1;
file_ = fopen(filename, "rb");
if (file_ == NULL)
return -1;
return 0; // success
}
void VttReader::Close() {
if (file_) {
fclose(file_);
file_ = NULL;
}
}
int VttReader::GetChar(char* c) {
if (c == NULL || file_ == NULL)
return -1;
const int result = fgetc(file_);
if (result != EOF) {
*c = static_cast<char>(result);
return 0; // success
}
if (ferror(file_))
return -1; // error
if (feof(file_))
return 1; // EOF
return -1; // weird
}
} // namespace libwebvtt

44
vttreader.h Normal file
View File

@@ -0,0 +1,44 @@
// 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 VTTREADER_H_ // NOLINT
#define VTTREADER_H_
#include <cstdio>
#include "./webvttparser.h"
namespace libwebvtt {
class VttReader : public libwebvtt::Reader {
public:
VttReader();
virtual ~VttReader();
// Open the file identified by |filename| in read-only mode, as a
// binary stream of bytes. Returns 0 on success, negative if error.
int Open(const char* filename);
// Closes the file stream. Note that the stream is automatically
// closed when the VttReader object is destroyed.
void Close();
// Reads the next character in the file stream, as per the semantics
// of Reader::GetChar. Returns negative if error, 0 on success, and
// positive if end-of-stream has been reached.
virtual int GetChar(char* c);
private:
FILE* file_;
VttReader(const VttReader&);
VttReader& operator=(const VttReader&);
};
} // namespace libwebvtt
#endif // VTTREADER_H_ // NOLINT

138
webmids.hpp Normal file
View File

@@ -0,0 +1,138 @@
// 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 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,
kMkvBlockAdditions = 0x75A1,
kMkvBlockMore = 0xA6,
kMkvBlockAddID = 0xEE,
kMkvBlockAdditional = 0xA5,
//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,
kMkvMaxBlockAdditionID = 0x55EE,
//video
kMkvVideo = 0xE0,
kMkvFlagInterlaced = 0x9A,
kMkvStereoMode = 0x53B8,
kMkvAlphaMode = 0x53C0,
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,
kMkvContentEncAESSettings = 0x47E7,
kMkvAESSettingsCipherMode = 0x47E8,
kMkvAESSettingsCipherInitData = 0x47E9,
//end ContentEncodings
//Cueing Data
kMkvCues = 0x1C53BB6B,
kMkvCuePoint = 0xBB,
kMkvCueTime = 0xB3,
kMkvCueTrackPositions = 0xB7,
kMkvCueTrack = 0xF7,
kMkvCueClusterPosition = 0xF1,
kMkvCueBlockNumber = 0x5378,
//Chapters
kMkvChapters = 0x1043A770,
kMkvEditionEntry = 0x45B9,
kMkvChapterAtom = 0xB6,
kMkvChapterUID = 0x73C4,
kMkvChapterStringUID = 0x5654,
kMkvChapterTimeStart = 0x91,
kMkvChapterTimeEnd = 0x92,
kMkvChapterDisplay = 0x80,
kMkvChapString = 0x85,
kMkvChapLanguage = 0x437C,
kMkvChapCountry = 0x437E
};
} // end namespace mkvmuxer
#endif // WEBMIDS_HPP

725
webvttparser.cc Normal file
View File

@@ -0,0 +1,725 @@
// 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.
#include "./webvttparser.h" // NOLINT
#include <climits>
namespace libwebvtt {
enum {
kNUL = '\x00',
kSPACE = ' ',
kTAB = '\x09',
kLF = '\x0A',
kCR = '\x0D'
};
Reader::~Reader() {
}
LineReader::~LineReader() {
}
int LineReader::GetLine(std::string* line_ptr) {
if (line_ptr == NULL)
return -1;
std::string& ln = *line_ptr;
ln.clear();
// Consume characters from the stream, until we
// reach end-of-line (or end-of-stream).
// The WebVTT spec states that lines may be
// terminated in any of these three ways:
// LF
// CR
// CR LF
// We interrogate each character as we read it from the stream.
// If we detect an end-of-line character, we consume the full
// end-of-line indication, and we're done; otherwise, accumulate
// the character and repeat.
for (;;) {
char c;
const int e = GetChar(&c);
if (e < 0) // error
return e;
if (e > 0) // EOF
return (ln.empty()) ? 1 : 0;
// We have a character, so we must first determine
// whether we have reached end-of-line.
if (c == kLF)
return 0; // handle the easy end-of-line case immediately
if (c == kCR)
break; // handle the hard end-of-line case outside of loop
if (c == '\xFE' || c == '\xFF') // not UTF-8
return -1;
// To defend against pathological or malicious streams, we
// cap the line length at some arbitrarily-large value:
enum { kMaxLineLength = 10000 }; // arbitrary
if (ln.length() >= kMaxLineLength)
return -1;
// We don't have an end-of-line character, so accumulate
// the character in our line buffer.
ln.push_back(c);
}
// We detected a CR. We must interrogate the next character
// in the stream, to determine whether we have a LF (which
// would make it part of this same line).
char c;
const int e = GetChar(&c);
if (e < 0) // error
return e;
if (e > 0) // EOF
return 0;
// If next character in the stream is not a LF, return it
// to the stream (because it's part of the next line).
if (c != kLF)
UngetChar(c);
return 0;
}
Parser::Parser(Reader* r) : reader_(r), unget_(-1) {
}
Parser::~Parser() {
}
int Parser::Init() {
int e = ParseBOM();
if (e < 0) // error
return e;
if (e > 0) // EOF
return -1;
// Parse "WEBVTT". We read from the stream one character at-a-time, in
// order to defend against non-WebVTT streams (e.g. binary files) that don't
// happen to comprise lines of text demarcated with line terminators.
const char kId[] = "WEBVTT";
for (const char* p = kId; *p; ++p) {
char c;
e = GetChar(&c);
if (e < 0) // error
return e;
if (e > 0) // EOF
return -1;
if (c != *p)
return -1;
}
std::string line;
e = GetLine(&line);
if (e < 0) // error
return e;
if (e > 0) // EOF
return 0; // weird but valid
if (!line.empty()) {
// Parse optional characters that follow "WEBVTT"
const char c = line[0];
if (c != kSPACE && c != kTAB)
return -1;
}
// The WebVTT spec requires that the "WEBVTT" line
// be followed by an empty line (to separate it from
// first cue).
e = GetLine(&line);
if (e < 0) // error
return e;
if (e > 0) // EOF
return 0; // weird but we allow it
if (!line.empty())
return -1;
return 0; // success
}
int Parser::Parse(Cue* cue) {
if (cue == NULL)
return -1;
// Parse first non-blank line
std::string line;
int e;
for (;;) {
e = GetLine(&line);
if (e) // EOF is OK here
return e;
if (!line.empty())
break;
}
// A WebVTT cue comprises an optional cue identifier line followed
// by a (non-optional) timings line. You determine whether you have
// a timings line by scanning for the arrow token, the lexeme of which
// may not appear in the cue identifier line.
const char kArrow[] = "-->";
std::string::size_type arrow_pos = line.find(kArrow);
if (arrow_pos != std::string::npos) {
// We found a timings line, which implies that we don't have a cue
// identifier.
cue->identifier.clear();
} else {
// We did not find a timings line, so we assume that we have a cue
// identifier line, and then try again to find the cue timings on
// the next line.
cue->identifier.swap(line);
e = GetLine(&line);
if (e < 0) // error
return e;
if (e > 0) // EOF
return -1;
arrow_pos = line.find(kArrow);
if (arrow_pos == std::string::npos) // not a timings line
return -1;
}
e = ParseTimingsLine(&line,
arrow_pos,
&cue->start_time,
&cue->stop_time,
&cue->settings);
if (e) // error
return e;
// The cue payload comprises all the non-empty
// lines that follow the timings line.
Cue::payload_t& p = cue->payload;
p.clear();
for (;;) {
e = GetLine(&line);
if (e < 0) // error
return e;
if (line.empty())
break;
p.push_back(line);
}
if (p.empty())
return -1;
return 0; // success
}
int Parser::GetChar(char* c) {
if (unget_ >= 0) {
*c = static_cast<char>(unget_);
unget_ = -1;
return 0;
}
return reader_->GetChar(c);
}
void Parser::UngetChar(char c) {
unget_ = static_cast<unsigned char>(c);
}
int Parser::ParseBOM() {
// Explanation of UTF-8 BOM:
// http://en.wikipedia.org/wiki/Byte_order_mark
static const char BOM[] = "\xEF\xBB\xBF"; // UTF-8 BOM
for (int i = 0; i < 3; ++i) {
char c;
int e = GetChar(&c);
if (e < 0) // error
return e;
if (e > 0) // EOF
return 1;
if (c != BOM[i]) {
if (i == 0) { // we don't have a BOM
UngetChar(c);
return 0; // success
}
// We started a BOM, so we must finish the BOM.
return -1; // error
}
}
return 0; // success
}
int Parser::ParseTimingsLine(
std::string* line_ptr,
std::string::size_type arrow_pos,
Time* start_time,
Time* stop_time,
Cue::settings_t* settings) {
if (line_ptr == NULL)
return -1;
std::string& line = *line_ptr;
if (arrow_pos == std::string::npos || arrow_pos >= line.length())
return -1;
// Place a NUL character at the start of the arrow token, in
// order to demarcate the start time from remainder of line.
line[arrow_pos] = kNUL;
std::string::size_type idx = 0;
int e = ParseTime(line, &idx, start_time);
if (e) // error
return e;
// Detect any junk that follows the start time,
// but precedes the arrow symbol.
while (char c = line[idx]) {
if (c != kSPACE && c != kTAB)
return -1;
++idx;
}
// Place a NUL character at the end of the line,
// so the scanner has a place to stop, and begin
// the scan just beyond the arrow token.
line.push_back(kNUL);
idx = arrow_pos + 3;
e = ParseTime(line, &idx, stop_time);
if (e) // error
return e;
e = ParseSettings(line, idx, settings);
if (e) // error
return e;
return 0; // success
}
int Parser::ParseTime(
const std::string& line,
std::string::size_type* idx_ptr,
Time* time) {
if (idx_ptr == NULL)
return -1;
std::string::size_type& idx = *idx_ptr;
if (idx == std::string::npos || idx >= line.length())
return -1;
if (time == NULL)
return -1;
// Consume any whitespace that precedes the timestamp.
while (char c = line[idx]) {
if (c != kSPACE && c != kTAB)
break;
++idx;
}
// WebVTT timestamp syntax comes in three flavors:
// SS[.sss]
// MM:SS[.sss]
// HH:MM:SS[.sss]
// Parse a generic number value. We don't know which component
// of the time we have yet, until we do more parsing.
int val = ParseNumber(line, &idx);
if (val < 0) // error
return val;
Time& t = *time;
// The presence of a colon character indicates that we have
// an [HH:]MM:SS style syntax.
if (line[idx] == ':') {
// We have either HH:MM:SS or MM:SS
// The value we just parsed is either the hours or minutes.
// It must be followed by another number value (that is
// either minutes or seconds).
const int first_val = val;
++idx; // consume colon
// Parse second value
val = ParseNumber(line, &idx);
if (val < 0)
return val;
if (val >= 60) // either MM or SS
return -1;
if (line[idx] == ':') {
// We have HH:MM:SS
t.hours = first_val;
t.minutes = val; // vetted above
++idx; // consume MM:SS colon
// We have parsed the hours and minutes.
// We must now parse the seconds.
val = ParseNumber(line, &idx);
if (val < 0)
return val;
if (val >= 60) // SS part of HH:MM:SS
return -1;
t.seconds = val;
} else {
// We have MM:SS
// The implication here is that the hour value was omitted
// from the timestamp (because it was 0).
if (first_val >= 60) // minutes
return -1;
t.hours = 0;
t.minutes = first_val;
t.seconds = val; // vetted above
}
} else {
// We have SS (only)
// The time is expressed as total number of seconds,
// so the seconds value has no upper bound.
t.seconds = val;
// Convert SS to HH:MM:SS
t.minutes = t.seconds / 60;
t.seconds -= t.minutes * 60;
t.hours = t.minutes / 60;
t.minutes -= t.hours * 60;
}
// We have parsed the hours, minutes, and seconds.
// We must now parse the milliseconds.
char c = line[idx];
// TODO(matthewjheaney): one option here is to slightly relax the
// syntax rules for WebVTT timestamps, to permit the comma character
// to also be used as the seconds/milliseconds separator. This
// would handle streams that use localization conventions for
// countries in Western Europe. For now we obey the rules specified
// in the WebVTT spec (allow "full stop" only).
const bool have_milliseconds = (c == '.');
if (!have_milliseconds) {
t.milliseconds = 0;
} else {
++idx; // consume FULL STOP
val = ParseNumber(line, &idx);
if (val < 0)
return val;
if (val >= 1000)
return -1;
if (val < 10)
t.milliseconds = val * 100;
else if (val < 100)
t.milliseconds = val * 10;
else
t.milliseconds = val;
}
// We have parsed the time proper. We must check for any
// junk that immediately follows the time specifier.
c = line[idx];
if (c != kNUL && c != kSPACE && c != kTAB)
return -1;
return 0; // success
}
int Parser::ParseSettings(
const std::string& line,
std::string::size_type idx,
Cue::settings_t* settings) {
settings->clear();
if (idx == std::string::npos || idx >= line.length())
return -1;
for (;;) {
// We must parse a line comprising a sequence of 0 or more
// NAME:VALUE pairs, separated by whitespace. The line iself is
// terminated with a NUL char (indicating end-of-line).
for (;;) {
const char c = line[idx];
if (c == kNUL) // end-of-line
return 0; // success
if (c != kSPACE && c != kTAB)
break;
++idx; // consume whitespace
}
// We have consumed the whitespace, and have not yet reached
// end-of-line, so there is something on the line for us to parse.
settings->push_back(Setting());
Setting& s = settings->back();
// Parse the NAME part of the settings pair.
for (;;) {
const char c = line[idx];
if (c == ':') // we have reached end of NAME part
break;
if (c == kNUL || c == kSPACE || c == kTAB)
return -1;
s.name.push_back(c);
++idx;
}
if (s.name.empty())
return -1;
++idx; // consume colon
// Parse the VALUE part of the settings pair.
for (;;) {
const char c = line[idx];
if (c == kNUL || c == kSPACE || c == kTAB)
break;
if (c == ':') // suspicious when part of VALUE
return -1; // TODO(matthewjheaney): verify this behavior
s.value.push_back(c);
++idx;
}
if (s.value.empty())
return -1;
}
}
int Parser::ParseNumber(
const std::string& line,
std::string::size_type* idx_ptr) {
if (idx_ptr == NULL)
return -1;
std::string::size_type& idx = *idx_ptr;
if (idx == std::string::npos || idx >= line.length())
return -1;
if (!isdigit(line[idx]))
return -1;
int result = 0;
while (isdigit(line[idx])) {
const char c = line[idx];
const int i = c - '0';
if (result > INT_MAX / 10)
return -1;
result *= 10;
if (result > INT_MAX - i)
return -1;
result += i;
++idx;
}
return result;
}
bool Time::operator==(const Time& rhs) const {
if (hours != rhs.hours)
return false;
if (minutes != rhs.minutes)
return false;
if (seconds != rhs.seconds)
return false;
return (milliseconds == rhs.milliseconds);
}
bool Time::operator<(const Time& rhs) const {
if (hours < rhs.hours)
return true;
if (hours > rhs.hours)
return false;
if (minutes < rhs.minutes)
return true;
if (minutes > rhs.minutes)
return false;
if (seconds < rhs.seconds)
return true;
if (seconds > rhs.seconds)
return false;
return (milliseconds < rhs.milliseconds);
}
bool Time::operator>(const Time& rhs) const {
return rhs.operator<(*this);
}
bool Time::operator<=(const Time& rhs) const {
return !this->operator>(rhs);
}
bool Time::operator>=(const Time& rhs) const {
return !this->operator<(rhs);
}
presentation_t Time::presentation() const {
const presentation_t h = 1000LL * 3600LL * presentation_t(hours);
const presentation_t m = 1000LL * 60LL * presentation_t(minutes);
const presentation_t s = 1000LL * presentation_t(seconds);
const presentation_t result = h + m + s + milliseconds;
return result;
}
Time& Time::presentation(presentation_t d) {
if (d < 0) { // error
hours = 0;
minutes = 0;
seconds = 0;
milliseconds = 0;
return *this;
}
seconds = d / 1000;
milliseconds = d - 1000 * seconds;
minutes = seconds / 60;
seconds -= 60 * minutes;
hours = minutes / 60;
minutes -= 60 * hours;
return *this;
}
Time& Time::operator+=(presentation_t rhs) {
const presentation_t d = this->presentation();
const presentation_t dd = d + rhs;
this->presentation(dd);
return *this;
}
Time Time::operator+(presentation_t d) const {
Time t(*this);
t += d;
return t;
}
Time& Time::operator-=(presentation_t d) {
return this->operator+=(-d);
}
presentation_t Time::operator-(const Time& t) const {
const presentation_t rhs = t.presentation();
const presentation_t lhs = this->presentation();
const presentation_t result = lhs - rhs;
return result;
}
} // namespace libwebvtt

162
webvttparser.h Normal file
View File

@@ -0,0 +1,162 @@
// 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 WEBVTTPARSER_H_ // NOLINT
#define WEBVTTPARSER_H_
#include <list>
#include <string>
namespace libwebvtt {
class Reader {
public:
// Fetch a character from the stream. Return
// negative if error, positive if end-of-stream,
// and 0 if a character is available.
virtual int GetChar(char* c) = 0;
protected:
virtual ~Reader();
};
class LineReader : protected Reader {
public:
// Consume a line of text from the stream, stripping off
// the line terminator characters. Returns negative if error,
// 0 on success, and positive at end-of-stream.
int GetLine(std::string* line);
protected:
virtual ~LineReader();
// Puts a character back into the stream.
virtual void UngetChar(char c) = 0;
};
// As measured in thousandths of a second,
// e.g. a duration of 1 equals 0.001 seconds,
// and a duration of 1000 equals 1 second.
typedef long long presentation_t; // NOLINT
struct Time {
int hours;
int minutes;
int seconds;
int milliseconds;
bool operator==(const Time& rhs) const;
bool operator<(const Time& rhs) const;
bool operator>(const Time& rhs) const;
bool operator<=(const Time& rhs) const;
bool operator>=(const Time& rhs) const;
presentation_t presentation() const;
Time& presentation(presentation_t);
Time& operator+=(presentation_t);
Time operator+(presentation_t) const;
Time& operator-=(presentation_t);
presentation_t operator-(const Time&) const;
};
struct Setting {
std::string name;
std::string value;
};
struct Cue {
std::string identifier;
Time start_time;
Time stop_time;
typedef std::list<Setting> settings_t;
settings_t settings;
typedef std::list<std::string> payload_t;
payload_t payload;
};
class Parser : private LineReader {
public:
explicit Parser(Reader* r);
virtual ~Parser();
// Pre-parse enough of the stream to determine whether
// this is really a WEBVTT file. Returns 0 on success,
// negative if error.
int Init();
// Parse the next WebVTT cue from the stream. Returns 0 if
// an entire cue was parsed, negative if error, and positive
// at end-of-stream.
int Parse(Cue* cue);
private:
// Returns the next character in the stream, using the look-back character
// if present (as per Reader::GetChar).
virtual int GetChar(char* c);
// Puts a character back into the stream (as per LineReader::UngetChar).
virtual void UngetChar(char c);
// Check for presence of a UTF-8 BOM in the stream. Returns
// negative if error, 0 on success, and positive at end-of-stream.
int ParseBOM();
// Parse the distinguished "cue timings" line, which includes the start
// and stop times and settings. Argument |line| contains the complete
// line of text (as returned by ParseLine()), which the function is free
// to modify as it sees fit, to facilitate scanning. Argument |arrow_pos|
// is the offset of the arrow token ("-->"), which indicates that this is
// the timings line. Returns negative if error, 0 on success.
//
static int ParseTimingsLine(std::string* line,
std::string::size_type arrow_pos,
Time* start_time,
Time* stop_time,
Cue::settings_t* settings);
// Parse a single time specifier (from the timings line), starting
// at the given offset; lexical scanning stops when a NUL character
// is detected. The function modifies offset |off| by the number of
// characters consumed. Returns negative if error, 0 on success.
//
static int ParseTime(const std::string& line,
std::string::size_type* off,
Time* time);
// Parse the cue settings from the timings line, starting at the
// given offset. Returns negative if error, 0 on success.
//
static int ParseSettings(const std::string& line,
std::string::size_type off,
Cue::settings_t* settings);
// Parse a non-negative integer from the characters in |line| beginning
// at offset |off|. The function increments |off| by the number
// of characters consumed. Returns the value, or negative if error.
//
static int ParseNumber(const std::string& line,
std::string::size_type* off);
Reader* const reader_;
// Provides one character's worth of look-back, to facilitate scanning.
int unget_;
// Disable copy ctor and copy assign for Parser.
Parser(const Parser&);
Parser& operator=(const Parser&);
};
} // namespace libwebvtt
#endif // WEBVTTPARSER_H_ // NOLINT