Compare commits

...

212 Commits

Author SHA1 Message Date
Tom Finegan
82ac5fcdc8 Remove RELEASE.TXT.
It's stale and redundant.

Change-Id: I91c3a1e0f0c717c8f1b3ae30d648127cb2f3590c
2015-12-09 08:12:34 -08:00
Tom Finegan
852e1733a8 webm2pes: Split super frames and packetize large frames.
- PES depacketizers don't want anything but simple encoded frames.
- Large in this case means frame size + size of PES header
  is > UINT16_MAX.

Change-Id: Ifb76caaa97a0dcf3600228a0cbc4d4f2533027a7
2015-12-07 20:14:53 -08:00
Tom Finegan
faf85c227d webm2pes: Refactor header/optional header writing.
- Move class declarations to webm2pes.h.
- Add some visual demarcation between the method definitions for each
  class in webm2pes.cc.
- Reorganize the output code to make further development simpler.
- Also, clang format noise.

Change-Id: Id6d156e1f255cefe30a62784a3eadde6b93ae614
2015-12-03 14:42:37 -08:00
Tom Finegan
7c19266548 Add Webm2Pes.
Add tool for converting WebM VPx streams to Packetized Elementary
Streams.

Change-Id: I599de053df5423a803a3ea450876c52c3e400034
2015-12-02 11:42:24 -08:00
Tom Finegan
01fdee435c mkvmuxer: Disallow AddTrack() after Tracks element is output.
BUG=https://code.google.com/p/webm/issues/detail?id=1083

Change-Id: I6a603337ba5fea1333f3f1c2595f9b87b148c427
2015-10-21 09:07:00 -07:00
James Zern
1ad314e297 mkvparser: EBMLHeader::Parse: remove dead init
Change-Id: Ie06b44c3b7fd948d11aa86ae521a196ea668312b
2015-10-13 16:10:55 -07:00
James Zern
476366249e mkvparser: fix type warnings
Change-Id: Ia77a9a4e694986ece4c2e0f86f2857f320432f48
2015-09-11 18:56:09 -07:00
James Zern
267f71c76e mkvparser: SafeArrayAlloc fix type warning
num_bytes has been validated so it's safe to cast to size_t for use with
new

Change-Id: If1a6c5521dd6fbcb7e30f434b81daa3b26bd0386
2015-09-11 18:56:09 -07:00
James Zern
f1a99d5f25 mkvparser: s/LONG_LONG_MAX/LLONG_MAX/ for compatibility
Change-Id: If3b80bfd08f02ec9cba0be223ff95991564f6fd7
2015-09-11 18:56:09 -07:00
James Zern
bff1aa512d mkvparser: add msvc compatibility for isnan/isinf
fixes build errors related to these functions on visual studio prior to
2013

Change-Id: I8272f9065195e5447055aad7d0f899afa0294ea9
2015-09-11 18:55:03 -07:00
Vignesh Venkatasubramanian
a58c32339e mkvmuxer: Add codec id constant for VP10.
This was added in the libvpx's snapshot here:
https://chromium-review.googlesource.com/#/c/293861

Change-Id: I58b9635c62535ecdb0dff14dc294466262590861
2015-09-10 12:10:01 -07:00
Tom Finegan
714f3c4e4f mkvparser: validate results in EBMLHeader::Parse.
Return an error when DocType, DocTypeReadVersion, DocTypeVersion
EBMLMaxIDLength or EBMLMaxSizeLength are invalid or cannot be
handled by mkvparser.

Update samples to respect the return value from EBMLHeader::Parse.

BUG=https://code.google.com/p/webm/issues/detail?id=1057

Change-Id: I9337f13c1d5fa366b1101e48fe6bc46eb5b2ee97
2015-09-05 08:06:45 -07:00
Tom Finegan
cec98d4110 mkvparser: Correct the ReadID implementation.
Return real, known MKV IDs when reading them. Previously
IDs were treated as EBML integer values. This was both
wrong and confusing. Wrong because this results in values
that are not part of the Matroska spec, and confusing
because the code was littered with magic numbers
representing the invented IDs.

Currently uses mkvmuxer::MkvId; A TODO in the code addresses this.
Additional IDs have been added that were not previously in the enum:
mkvparser parses many elements that we do not write in the muxer.

Change-Id: I5db2b4d70d786d5239d2e2a0cbff4e7f8d844aa6
2015-09-04 09:55:59 -07:00
Tom Finegan
eb36ae4840 Merge changes I029a268e,Ia272b150,I5c4d1bbc,Ia47a2478,I3a2e2226
* changes:
  mkvparser: Cluster::Parse clean up.
  mkvparser: Disallow EBML IDs equal to 0.
  mkvparser: Cluster::Load clean up.
  mkvparser: Segment::Load asserts to error checks.
  mkvparser: Segment::PreloadCluster asserts to error checks.
2015-08-31 22:48:36 +00:00
Tom Finegan
229f49347d Merge "mkvparser: Segment::AppendCluster asserts to error checks." 2015-08-31 22:10:13 +00:00
Tom Finegan
287faf95f6 Merge "mkvparser: Segment::DoLoadClusterUnknownSize asserts to error checks." 2015-08-31 22:09:51 +00:00
Tom Finegan
1a87b59032 Merge "mkvparser: Segment assert clean up." 2015-08-31 22:09:37 +00:00
Tom Finegan
d26ec6909d mkvparser: Cluster::Parse clean up.
- Remove "// weird"'s.
- Remove commented out asserts.
- Asserts to error checks.
- Use ReadID to read IDs.

Change-Id: I029a268e4fa45931e3c6a72e41448f0b8fb2d0c3
2015-08-31 14:32:53 -07:00
Tom Finegan
f2029be5f4 mkvparser: Disallow EBML IDs equal to 0.
Change-Id: Ia272b1505dc62fdadf06348365a6aef058b081d8
2015-08-31 14:23:38 -07:00
Tom Finegan
19f5694277 mkvparser: Cluster::Load clean up.
- Remove "// weird"'s.
- Remove needless extra scoping.
- Asserts to error checks.

Change-Id: I5c4d1bbc59d9debe95e1e35e63ff0679335048ff
2015-08-31 13:59:35 -07:00
Tom Finegan
27a07c1fd1 mkvparser: Segment::Load asserts to error checks.
Change-Id: Ia47a24786789d6f94a786f76e313318e013f4f40
2015-08-31 13:38:35 -07:00
Tom Finegan
d0313dd7ce mkvparser: Segment::PreloadCluster asserts to error checks.
Change-Id: I3a2e2226f30ee047f96f5136c52e4cb9081d42c8
2015-08-31 13:36:15 -07:00
Tom Finegan
b108695b9b mkvparser: Segment::AppendCluster asserts to error checks.
Change-Id: Id6bb378b22a7c6397e3d950c2fdd84396279e881
2015-08-31 12:40:24 -07:00
Tom Finegan
4630f80f79 mkvparser: Segment::DoLoadClusterUnknownSize asserts to error checks.
Change-Id: I4597416261efb9202d2307e1ac4abfeb38e7c515
2015-08-31 12:38:20 -07:00
Tom Finegan
841a9b5fd9 mkvparser: Segment assert clean up.
- Remove asserts from ~Segment, CreateInstance, and DoLoadCluster.
- Adds new return constant (E_PARSE_FAILED == -1); most places in
  mkvparser that return -1 are the result of an internal inconsistency
  and/or misusing the API. In those cases E_FILE_FORMAT_INVALID is not
  appropriate as a return value because it's misleading to libwebm users.

Change-Id: I0d46e831b3475d69432b8745066de3329419fa11
2015-08-31 12:38:09 -07:00
Tom Finegan
8c4ca2ea04 Merge "mkvparser: Make mkvparser namespace usage uniform." 2015-08-28 21:55:13 +00:00
Tom Finegan
49ae6f0dd9 Merge "mkvparser: Fix include order." 2015-08-28 21:54:04 +00:00
Tom Finegan
0735bb5bdc mkvparser: Make mkvparser namespace usage uniform.
Instead of being weird and defining the first few functions
in mkvparser by explicitly prepending the namespace, open the
namespace immediately and define all functions within it.

Change-Id: I9a44a0fda8b04f89c8f874a2a6edc78f1b8e5bcc
2015-08-28 14:26:46 -07:00
Tom Finegan
93b24c4195 mkvparser: Fix include order.
Change-Id: Ia03ce824c78c19f5ab62c736069ea0972b8c93ea
2015-08-28 11:06:03 -07:00
James Zern
a57d6602b4 sample_muxer: fix Segment memory leak on error
use an auto_ptr<mkvparser::Segment> for compatibility which should be
harmless as there is no attempt to transfer ownership; sample.cpp
operates similarly.

Change-Id: I2cb6982aa64c62ff2ec7cbbd646770cb4e782509
2015-08-27 21:09:16 -07:00
Tom Finegan
1c5bd949d0 mkvparser: Cues, change asserts to error checks.
Change-Id: I116845b792aa5bb9a35341097cbd393300539f79
2015-08-26 12:51:05 -07:00
Tom Finegan
7f77201dca Merge "mkvparser: Add ReadID." 2015-08-26 19:49:11 +00:00
James Zern
795fd568b6 mkvparser: set kMaxAllocSize explicitly
removes the need for the unrelated INT32_MAX and fixes the build
(stdint.h was missing)

Change-Id: Idf3315097982aec6fb28030bd2327ba6cff14668
2015-08-25 20:29:50 -07:00
Tom Finegan
23bb18b76d mkvparser: Add ReadID.
Enforce ID rules in one place instead of every time
an ID is read.

Change-Id: I6e39a2e2dbafa2d5926dea790dd563cc3a48f67e
2015-08-25 13:37:35 -07:00
Tom Finegan
7b57e37fde mkvparser: add SafeArrayAlloc.
A new wrapper that makes array allocations safer by
limiting allocated size.

BUG=23430787

Change-Id: I901ee61dc2b601e8c0b5bf13f7499b5d2479ba7a
2015-08-25 13:06:27 -07:00
Tom Finegan
83a1f68944 mkvparser: Remove buf_t typedef.
- It is useless.
- It masks errors; buf_t was unsigned char*, but const buf_t was
  not seen by the compiler as const unsigned char*, which allowed
  passing a const pointer as a mutable argument to
  IMkvReader::Read at every site where buf_t was in use.

Change-Id: I293015e11c69d992e76c88ac02052a5a9a2b2c9c
2015-08-25 10:47:17 -07:00
James Zern
507471457e Merge changes Ia1265a63,I799d54df,Icfc582e4,I3425f608
* changes:
  Block::Parse: replace pos asserts w/checks
  Cluster::ParseBlockGroup: replace pos asserts w/checks
  Tags::*::Parse: replace pos asserts w/checks
  Chapters::*::Parse: replace pos asserts w/checks
2015-08-25 06:28:43 +00:00
James Zern
b18110541a Merge changes Ie4318152,I1e65f30f
* changes:
  Block::Parse: use int64 to aggregate laced frame sizes
  UnserializeFloat: check result for Inf/NaN
2015-08-25 06:25:04 +00:00
James Zern
06b4337ed8 Block::Parse: replace pos asserts w/checks
replace the common patterns assert(pos <= stop) / assert(pos == stop)
with error checks

BUG=23431751

Change-Id: Ia1265a639086c790a2ed542f34c2f438c153b036
2015-08-24 19:59:08 -07:00
James Zern
b366a98053 Cluster::ParseBlockGroup: replace pos asserts w/checks
replace the common patterns assert(pos <= stop) / assert(pos == stop)
with error checks
+ harmonize error return -1 -> E_FILE_FORMAT_INVALID

BUG=23431751

Change-Id: I799d54df62d93388b52ac325b836ab28e0860992
2015-08-24 19:59:04 -07:00
James Zern
2857b2350c Tags::*::Parse: replace pos asserts w/checks
replace the common patterns assert(pos <= stop) / assert(pos == stop)
with error checks
+ harmonize error return -1 -> E_FILE_FORMAT_INVALID

BUG=23431751

Change-Id: Icfc582e414a7d02ae0675ef14c047922c4a12036
2015-08-24 19:59:00 -07:00
James Zern
f1b2cfa03e Chapters::*::Parse: replace pos asserts w/checks
replace the common patterns assert(pos <= stop) / assert(pos == stop)
with error checks

BUG=23431751

Change-Id: I3425f6083456b5ab4f40497e3a192569b494dfa9
2015-08-24 19:56:07 -07:00
Tom Finegan
ca8062959a Merge "mkvparser: Cues::PreloadCuePoint now returns bool." 2015-08-25 02:22:05 +00:00
James Zern
6b4b297220 Block::Parse: use int64 to aggregate laced frame sizes
this is compared against a final total which is also int64

BUG=23488728

Change-Id: Ie4318152f9f9ae049a35d0b2724ccad129316981
2015-08-24 17:00:34 -07:00
James Zern
c0d2c9852b UnserializeFloat: check result for Inf/NaN
fail in either case

BUG=23488728

Change-Id: I1e65f30ff1cf857a5d1eb4bdedc3f842423cf15f
2015-08-24 16:49:22 -07:00
Tom Finegan
1a6dc4f210 mkvparser: Cues::PreloadCuePoint now returns bool.
Check allocations and fail appropriately.

Change-Id: Ie16d258a47e46b5e15c5c6275ea83ebead8b0f49
2015-08-24 16:20:13 -07:00
Tom Finegan
275ac22cae mkvparser: Cluster::Create clean up.
- Asserts to error condition check and return.
- Use nothrow new.

Change-Id: Iff9da5806e6f3240e7ea9f9e90ccdf729848a778
2015-08-24 16:19:10 -07:00
James Zern
064f2eed62 Segment::PreloadCluster(): return a bool status
BUG=23430793

Change-Id: I10aab67e94961868be806ee7ee9df550a5187e5a
2015-08-22 11:02:55 -07:00
James Zern
3778408b2a Segment::AppendCluster(): return a bool status
BUG=23430793

Change-Id: I6072234bfe211153ad143ccf7a3c6bbfa8cd166e
2015-08-22 11:01:47 -07:00
James Zern
e86d046c07 mkvparser: check Cluster::Create() return
BUG=23430793

Change-Id: Ie932dd2ee82d41368616999ab75ba3b213008642
2015-08-22 10:47:03 -07:00
James Zern
f9885b5882 mkvparser: check allocations
some unchecked new's are left in a few void functions, they'll be
addressed in a separate commit

BUG=23430793

Change-Id: I4953e70f4e7b0401a293c6b87c02445960e9ff9e
2015-08-22 10:47:03 -07:00
James Zern
21ee398281 mkvparser: Segment::Load fail w/missing info/tracks
convert asserts to error returns

BUG=23430793

Change-Id: Ifbfb5a2e7cd41344acc9c8d7afdf183b28dc2cd2
2015-08-22 10:47:03 -07:00
James Zern
08fb6546e8 Merge changes I264e68b2,Ife6190a4,Ibf37245f,I06efadb5,I88b5dfec, ...
* changes:
  mkvparser/Cluster: convert asserts to failure returns
  mkvparser/Tracks: convert asserts to failure returns
  mkvparser/Track: convert asserts to failure returns
  mkvparser/ContentEncoding: convert asserts to failure returns
  mkvparser/Cues: convert asserts to failure returns
  mkvparser/SeekHead: convert asserts to failure returns
  mkvparser/Segment: convert asserts to failure returns
2015-08-22 05:52:07 +00:00
James Zern
c8960955db mkvparser/Cluster: convert asserts to failure returns
Change-Id: I264e68b24eeb0f719a9d60b4cb0454e38110dd39
2015-08-21 22:49:57 -07:00
James Zern
680b4bfd3d mkvparser/Tracks: convert asserts to failure returns
BUG=23431751

Change-Id: Ife6190a4bcd4ab949165f17fd0b6c26a058a661b
2015-08-21 22:49:57 -07:00
James Zern
5889e6c18b mkvparser/Track: convert asserts to failure returns
Change-Id: Ibf37245f74e019c788b3f4121082956aa209430a
2015-08-21 22:49:57 -07:00
James Zern
5135c4cd74 mkvparser/ContentEncoding: convert asserts to failure returns
Change-Id: I06efadb5242135b095ad4cdefceef0e1c42c79b9
2015-08-21 22:49:57 -07:00
James Zern
b0e4f32011 mkvparser/Cues: convert asserts to failure returns
Change-Id: I88b5dfecfd03fec7f5808959ec6f640bff838d7a
2015-08-21 22:45:02 -07:00
James Zern
13ccc7f089 mkvparser/UnserializeInt: fix sign flip
with -funsigned-char the sign will be flipped, e.g., -128 -> 128, use an
explicit signed char.

additionally drop the misguided range check; this is meant as a data
size limit not one for the big-endian encoded ints

Change-Id: Ia10ef811d16acd09cbcd3d95856d9c460c9b7f16
2015-08-21 22:35:20 -07:00
James Zern
db3f9bbd79 mkvparser/SeekHead: convert asserts to failure returns
Change-Id: Ic2c83e4eb246fd4c1fc63fe16298f0dc78801912
2015-08-21 19:47:34 -07:00
James Zern
8de3654fdb mkvparser/Segment: convert asserts to failure returns
Change-Id: I7ccfd5be5e7438561edacb06bc8e6256aa6e0369
2015-08-21 19:46:15 -07:00
James Zern
fa2aa7da2d SeekHead::Parse(): fix assertion failure
replace assertions with failure returns

BUG=23430787
BUG=23431751

Change-Id: I22f000388cf040d064ba898c5de3658b56a3dfea
2015-08-21 18:12:08 -07:00
James Zern
d9bdadeff8 sample{,_muxer}: check SegmentInfo::GetInfo() return
prevents a segfault when parsing a corrupt file

BUG=23430793

Change-Id: I909fd456555ed0d5d871e12258b4887f36f90867
2015-08-21 16:58:04 -07:00
James Zern
07a9cf7127 Merge "mkvparser: Remove some asserts." 2015-08-21 21:28:13 +00:00
Tom Finegan
c56ee29254 mkvparser: Remove some asserts.
Remove asserts in sections recently updated to do error checking, and
replace some additional nearby asserts with error checks.

Change-Id: Ia8b60824736a7a821bbca3f2bfef5de4bb584c2d
2015-08-21 13:06:09 -07:00
Tom Finegan
d9013243ff Merge "mkvparser: Remove some asserts from SegmentInfo::Parse." 2015-08-21 19:57:35 +00:00
Rob Gaunt
7f7d898a27 Fix case sensitivity issue in iosbuild.sh.
Change-Id: I82b851b442cfe46ead78d115bbd7e22927ea6334
2015-08-21 12:27:30 -07:00
Tom Finegan
42fe2cd755 mkvparser: Remove some asserts from SegmentInfo::Parse.
Just return errors.

Change-Id: Ic3510db9c298e12cbe2a40fe09344a1c8e1e4ca8
2015-08-21 12:10:38 -07:00
Tom Finegan
8bccd9c306 Merge "mkvparser: avoid rollover in UnserializeInt()." 2015-08-21 18:47:16 +00:00
Tom Finegan
7a2fa0daf3 mkvparser: avoid rollover in UnserializeInt().
- Not strictly rollover-- avoid exceeding max 64 EBML (2^26 - 2).
- Tidy up the function.

BUG=23321923

Change-Id: I172c75064c189ed0fcf224145d016fca421f60c6
2015-08-21 11:24:30 -07:00
Tom Finegan
44f5ce64b1 mkvparser: Disallow durations in seconds greater than LONG_LONG_MAX.
libwebm cannot handle a duration in seconds greater than LONG_LONG_MAX
because it stores the values in long long variables.

BUG=23321923

Change-Id: Idb73f04a73e35829ae34386ea6c388fd355dd102
2015-08-21 10:54:27 -07:00
Tom Finegan
b521e3030e Merge "mkvparser: Segment::ParseHeaders() avoid rollover and bad int sizes." 2015-08-20 16:59:29 +00:00
Tom Finegan
7680e2a76b mkvparser: Check for errors in Match().
Confirm asserted conditions are as expected in all build
configurations, and avoid rolling over pos in obvious places.

BUG=23225325

Change-Id: I8af3192283788fd4a4b5b8ba4ad94abeab7feff2
2015-08-19 21:46:32 -07:00
Tom Finegan
39a315f8c1 mkvparser: Segment::ParseHeaders() avoid rollover and bad int sizes.
BUG=23226908

Change-Id: I177fc75684daa3c0282b63ec270d095251a70881
2015-08-19 21:23:21 -07:00
Tom Finegan
f250aceeaa mkvparser: Handle invalid lengths and rollover in ParseElementHeader().
BUG=23224239

Change-Id: I597054dc552b54f99a6716fb8f1b0f2480f2a29b
2015-08-19 12:34:54 -07:00
Tom Finegan
cd96a76985 mkvparser: Avoid rollover/truncation in UnserializeString().
Change-Id: I355d00b59ec1b7645ae5b4010e292215b5da3a17
2015-08-17 15:35:44 -07:00
Tom Finegan
8e8b3dbc6a Merge "mkvparser: Add error checking in Block::Parse." 2015-08-14 18:11:24 +00:00
James Zern
82b7e5f487 sample: correct mbstowcs() error check
mbstowcs() can return (size_t)-1 if it encounters an invalid string

BUG=23200382

Change-Id: Ibf67145be3989e16cd24c06850c7a5aa581a0ada
2015-08-14 10:57:48 -07:00
James Zern
04d7809375 sample: check allocation return
BUG=23200382

Change-Id: Ic64f76000d181f169af9aed2f7891f6ed3d28681
2015-08-14 10:57:01 -07:00
Tom Finegan
986b64b8c0 mkvparser: Add error checking in Block::Parse.
Instead of relying solely on asserts, which compile away to
nothing in downstream projects using libwebm for parsing webm
input streams, actually check for the conditions being asserted,
and return errors when appropriate.

Change-Id: Id8b6352e8dda69782129dcea8f67203fd9c4f572
2015-08-14 10:45:46 -07:00
James Zern
2dec09426a mkvparser: normalize UnserializeInt signature
long size -> long long; fixes a conversion warning under visual studio

Change-Id: I216151236f4ad7e1b8af4d8b7d19e3b36083fd14
2015-08-04 19:01:06 -07:00
Francisco Facioni
b6de61a5c0 Adds support for simple tags
Change-Id: I285e4b73df0a7112bbde7ef13eddf8fdccf59178
2015-07-22 17:07:25 -03:00
Tom Finegan
75a6d2da8b sample_muxer: Don't write huge files.
sample_muxer was using the buffer size instead of the frame payload size
when passing frames to the muxer.

BUG=https://code.google.com/p/webm/issues/detail?id=1032

Change-Id: I25578934e8822553e3482ded80eaf22651be85cc
2015-07-01 14:26:55 -07:00
James Zern
cec1f8521f mkvmuxer: remove unused timecode_scale variable
unused in WriteFramesAll() / WriteFramesLessThan() since:
d6d04ac mkvmuxer: use generic Cluster::AddFrame

Change-Id: I2089dc24b6a942f342b278b46271c6144cf8351e
2015-06-17 16:23:30 -07:00
James Zern
8a61b4033e Merge "mkvparser: Tiny whitespace fix." 2015-06-10 19:10:17 +00:00
Vignesh Venkatasubramanian
7affc5c3f8 clang-format re-run
Re-run clang-format to pick up some missed changes over the past
few CLs. Also update the .clang-format file to break after ternary
operator.

Change-Id: Ia4ba4e58362c2dbe36aeb33894f0411af33ef17d
2015-06-04 16:48:48 -07:00
Vignesh Venkatasubramanian
d6d04acdcc mkvmuxer: use generic Cluster::AddFrame
Replace specific Cluster::AddFrame* calls with a call to generic
Cluster::AddFrame().

Change-Id: If082490d2c29003b466034fc318f5e58791408a6
2015-06-04 16:33:36 -07:00
Vignesh Venkatasubramanian
4928b0bd5f Merge "mkvmuxer: Write Block key frames correctly." 2015-06-04 23:32:33 +00:00
Vignesh Venkatasubramanian
c2e4a46244 Merge "sample_muxer: Use AddGenericFrame to add frames." 2015-06-04 23:17:14 +00:00
Tom Finegan
e97f296855 mkvparser: Tiny whitespace fix.
Change-Id: I0f17eee0ce161c950f6d504ba1b509bd7b0e6343
2015-06-04 09:55:58 -07:00
Frank Galligan
d66ba4470a Merge "Add support to parse DisplayUnit." 2015-06-03 00:25:32 +00:00
Frank Galligan
deb41c2ea1 Add support to parse DisplayUnit.
BUG=https://code.google.com/p/webm/issues/detail?id=1009

Change-Id: I209ee6caf5bc10dfc1761e650821cc2338a4b13c
2015-06-02 16:17:13 -07:00
Leonel Togniolli
42e5660e73 Fix issues on EBML lacing block parsing
Fix EBML lacing block parsing when attempting to parse the last frame
on single-frame videos and assertion when frame_count is lower
than actual data in the file.

Change-Id: I223e30be54970ef75126c6c4ee3401cbeb92e02f
2015-06-02 15:51:48 -07:00
Leonel Togniolli
fe1e9bba6e Fix block parsing to not allow frame_size = 0
Fixed block parsing to account to cases that would
allow frame_size = 0, only to be rejected later on
Block::GetFrame assert(f.len > 0);

Change-Id: Idb93388b37e1963ec6115ac49f15e4951bc2c724
2015-06-02 15:51:48 -07:00
Leonel Togniolli
2cb6a28b09 Change assertions to checks when parsing TrackPositions
Malformed files woudl cause the parser to assert.

Instead now it stops parsing and skips the segment.

Change-Id: I256b3b72e43f969693ae16547ca98da07d665e21
2015-06-02 15:51:40 -07:00
Leonel Togniolli
d04580fda5 Fixes issues on Block Group parsing
Changed assertions to "invalid file format" errors files that
had Block Groups without Block IDs or had invalid sizes or
durations

Change-Id: I1383a63bfb76ee46aaa0aff089780383ce65fc31
2015-06-02 10:39:09 -07:00
Vignesh Venkatasubramanian
c3550fdacf mkvmuxer: Write Block key frames correctly.
Per matroska Block Structure [1], for keyframes the flag should not be
set (unlike SimpleBlocks). For Blocks, keyframes is inferred by the
absence of ReferenceBlock element.

This CL fixes Issue #933 [2].

[1] http://www.matroska.org/technical/specs/index.html#block_structure
[2] https://code.google.com/p/webm/issues/detail?id=933

Change-Id: Ia3f811c3fe17fb4dededda2f6834cf7cf2d2e022
2015-06-01 11:04:12 -07:00
Vignesh Venkatasubramanian
5dd0e40dbd Merge "mkvmuxer: Set is_key to true for metadata blocks." 2015-06-01 17:51:40 +00:00
Vignesh Venkatasubramanian
8e96863b56 mkvmuxer: Set is_key to true for metadata blocks.
Per matroska semantics, all metadata blocks should be considered
key frames. Set it to true in AddMetadata functions.

Change-Id: Ibc26845dc6cc72ccbf90ae8d4dcc27c948e8a375
2015-06-01 10:49:19 -07:00
Vignesh Venkatasubramanian
a9e4819e9f sample_muxer: Use AddGenericFrame to add frames.
Use Segment::AddGenericFrame to add frames to the output file. The
other AddFrame* functions will soon be deprecated and this will be
the preferred way of adding frames.

Change-Id: I3ed862543a1e0199617dc613a1760ff5f233ce7d
2015-06-01 10:32:07 -07:00
Leonel Togniolli
5a3be734f3 Change assertions to checks when load CuePoints
Malformed files would cause the parser to assert.

Instead now it stops parsing and skips the segment.

Change-Id: I07e3baf5c9eb6feb115e155f226d8abc2c37698e
2015-05-25 01:27:38 +01:00
James Zern
f99f3b20fb mkvmuxerutil::EbmlDateElementSize: remove value param
this is unused as the size of dates is fixed:
Date - signed 8 octets integer in nanoseconds with 0 indicating the
precise beginning of the millennium (at 2001-01-01T00:00:00,000000000
UTC)

Change-Id: I7d44c92a6b746e92e4041238b110115b56e38a93
2015-05-23 10:33:12 -07:00
James Zern
ff572b5399 Frame::IsValid: fix track_number check
previously IsValidTrackNumber() expected a track_number > 0
this also fixes a warning:
'comparison of unsigned expression < 0 is always false'

Change-Id: I839863986ff776aae59e38ee7e4a1a710081303a
2015-05-23 10:32:56 -07:00
Vignesh Venkatasubramanian
b6311dc16f mkvmuxer: Refactor to remove a lot of duplicate code
Refactor muxer to remove a lot of duplicate code. This CL strives
to not change the API as much as possible. Although, there is one
minor public API change (constructor of the Cluster class). Other
than that, all the functions should work exactly the same way as
before.

Following up on this CL, we are going to make AddGenericFrame the
preferred way of adding frames to a segment and deprecate (and
eventually remove) all the other specific AddFrame* functions.

Change-Id: Ie410f1a64a981e1545ade53ce476bbe8b3610c4f
2015-05-20 10:24:26 -07:00
Vignesh Venkatasubramanian
256cd02327 Merge "mkvmuxer: DiscardPadding should be signed integer." 2015-05-14 13:42:50 +00:00
Vignesh Venkatasubramanian
16c8e78265 mkvmuxer: s/frame/data in all AddFrame* functions.
Rename variable "frame" to "data" in all the AddFrame* functions.
This is in prepararation for a follow-up CL.

Change-Id: Ifd0d96cfbeca85c12be23d854bc87e085436984d
2015-05-12 15:31:07 -07:00
Vignesh Venkatasubramanian
c5e511c00a mkvmuxer: DiscardPadding should be signed integer.
Discard Padding getter and setter should take and return a signed
integer respectively.

Change-Id: Ieb6b9cd8c9830c2335ffdbcd608c727a3d135bb8
2015-05-12 14:56:12 -07:00
Tom Finegan
4baaa2c9a3 Add framework build script: iosbuild.sh
Builds WebM.framework.

Change-Id: I6f71defa18a7cbb21e290dbbb819a85353912e53
2015-05-06 10:33:48 -07:00
James Zern
3d06eb1e2c PATENTS: fix a typo: constitutes -> constitute
Change-Id: Iec2d5fea1b89fc97f981f5cd0a545b83110bd8c2
2015-04-30 15:40:13 -07:00
Tom Finegan
d3849c2f7b mkvparser: Dead code removal.
Change-Id: Ic4cf359ecc80641b97f40c20639ce9c32b34077d
2015-04-14 23:36:29 -07:00
Leonel Togniolli
f439e523b8 Change assertions to checks when preloading Cues
If a malformed webm file contains invalid information on the Cues
the segment, the parser would assert.

Instead, now it ignores the Cues and skips the segment.

Change-Id: I9270f6a0935ce9e9a3765a5f324ae542c1ade1c7
2015-04-14 01:25:25 +01:00
Leonel Togniolli
d3a44cd549 Fix track transversal when listing Cues on sample
It could skip tracks or crash if track numbers were non-sequential or tracks were missing.

Change-Id: I485bd4c14c73500775f2944b4486f9a5e154a5e8
2015-04-11 00:24:30 +01:00
Leonel Togniolli
c6255af02a Tweak .gitignore so git status is clean after checkout and build:
- added missing underscore to sample_muxer
- added cmake and make related files

Change-Id: Id9a6f12be83d28c95941098b57b61a7a11510f1b
2015-04-09 00:38:17 +01:00
James Zern
b5229c7bc8 Makefile.unix: s/samplemuxer/sample_muxer/
this matches the target name used in CMakeLists.txt and the writing app
stored in the output file

Change-Id: I161675c6bff8ebfa041331a329589441d3874514
2015-03-18 15:33:06 -07:00
Sasi Inguva
e3616a6614 Add support to parse stereo mode, display width and display height in mkvparser
Change-Id: I7ff99275b70e96b84601c32836f1b79f95fcf0d4
2015-03-12 00:25:58 -07:00
Vignesh Venkatasubramanian
a4b68f825e parser: Fix bug in Chapters::Atom::Parse()
Reading the UID is considered to be failed only if status is < 0
and not the value read.

Change-Id: I88fee3aa5b8c323d099930a6823406c012b70f81
2015-03-03 12:08:28 -08:00
Tom Finegan
bab0a002c5 cmake: Set library and project name the proper way on Windows.
Revert previous hack and use target properties to correct project
and library names.

Change-Id: Ib35da1cedcedf86f3f020d879cd39199fd236572
2015-03-02 12:43:56 -08:00
Tom Finegan
feeb9b13ff Set library name to match Windows expectations.
Back to libwebm.lib from webm.lib.

Change-Id: I6ced362c987a7b5d3d56365a1ed53de7bf9f849b
2015-02-25 15:37:05 -08:00
Vignesh Venkatasubramanian
b9a549b467 Fix CMakefile to generate libwebm.a
The existing CMakeLists.txt ends up generating a static library
with name "liblibwebm.a" rather than "libwebm.a". This patch fixes
it.

Change-Id: I4dabac5158530714a38045b8af29e75ade0a939e
2015-02-25 14:04:04 -08:00
Tom Finegan
b386aa5c6b Add CMakeLists.txt and msvc_runtime.cmake.
- These files facilitate project/makefile generation.
- Remove old Visual Studio projects.
- Rename Makefile to Makefile.unix.

Change-Id: If786edd75d44c462538526c286eccc5cbf15d828
2015-02-13 16:07:01 -08:00
Vignesh Venkatasubramanian
b0f8a81df9 parser: Fix memory leak in Chapter parsing
Fix a memory leak in parsing Chapters element.

Change-Id: I95324299014174d3f0926d96022eeb747b07d1a7
2015-02-06 15:17:28 -08:00
Vignesh Venkatasubramanian
f06e152abd mkvmuxer: Fix MoveCuesBeforeClustersHelper recursive call.
The third parameter of the MoveCuesBeforeClustersHelper recursive function
should always be the size of the cues element without the master element's size
(i.e.) it should be the sum of size of all Cue Points. This way, the changes in
the Length of the master element itself will be computed correctly.

Change-Id: I05ff1606fb74168f80ffed81fd3c0de3f237c579
2015-02-02 18:34:18 -08:00
Lajos Molnar
27bb7476dd allow subtitle tracks with ContentEncodings
This is allowed by matroska spec

Change-Id: I1842b6e7c6bab4ba0f86938bbe6b110be0c5435f
2015-01-13 12:56:25 -08:00
James Zern
623d182613 DoLoadCluster: tolerate empty clusters
previously only empty clusters of known size were accepted; with
clusters of unknown size the cluster has been successfully parsed and a
working copy of the file position updated, so parsing can continue.
clusters of this type are discarded as clusters of known size currently
are.

Change-Id: I3ef848768519ab7f1887a11629c50af72249cead
2014-10-01 12:53:14 -07:00
Lou Quillio
1156da8d29 Update PATENTS to reflect s/VP8/WebM/g
Sync with http://www.webmproject.org/license/additional/

modified:   PATENTS.TXT

Change-Id: I3e1b3a570b26ada0e6e0d344f1783ef0e3cd5fa1
2014-08-11 14:30:54 -07:00
Tom Finegan
0d4cb404ea mkvmuxerutil: Use rand() in MSVC builds.
Instead of rand_s(), which can make things unpleasant for downstream
projects.

Change-Id: Ie172867c28aaa43223dc5fb694eb4a4fd26515d6
2014-07-18 11:37:06 -07:00
Vignesh Venkatasubramanian
e12fff0ebb mkvmuxer: Overload WriteEbmlHeader for backward compatibility
WriteEbmlHeader function was updated on
a321704b4c. It is a public function that
is exposed outside of the library. Overload it with an old signature
to maintain compatibility. The overloaded function writes the
doc_type_version as 2 by default (thereby retaining the old behavior).

Change-Id: If887a1bfa3e81e7e639c986a922aa5155faab2cf
2014-07-09 11:24:09 -07:00
James Zern
a321704b4c mkvmuxer: write correct DocTypeVersion
Change-Id: I9a463394dec5e69ae8a7b5a1378f19d390e441e4
2: default
4: if CodecDelay/SeekPreRoll/DiscardPadding are present
2014-06-24 16:17:29 -07:00
James Zern
574045edd4 mkvmuxer: fix DiscardPadding
DiscardPadding is a signed int.
this change fixes 2 things:
- allows negative values for discard padding
- fixes cases where an unsigned value would be written such that on read
  the sign would be flipped

Change-Id: I9418da7a22c09768e02d5b61da8d01c2bccb5dee
2014-06-18 12:50:25 -07:00
Sergey Ulanov
8be63972fd Include crop elements when calculating size of Video element
Change acf788 added Crop* elements support, but they were not
added when calculating size of Video element.

Change-Id: I64495cc35406a28b86b40d915dbc291f45aa1263
2014-06-06 00:40:50 -07:00
James Zern
8f2d1b3cde mkvparser: fix DiscardPadding extraction
the element length was being read twice; the second attempt would
consume a portion of the discard padding field often failing due to
limitations in GetUIntLength.

Change-Id: Ibbe3f082e2d05460734a0e1f7d23f3c665e3f24b
2014-05-30 14:44:28 -07:00
Vignesh Venkatasubramanian
1c36c24694 mkvmuxer: fix style guide violations
fix a few style guide violations in mkvmuxer.cpp

Change-Id: If800a5d6851f8ba4b904341fd054e1c2091e281e
2014-05-29 08:30:30 -07:00
Vignesh Venkatasubramanian
568504e64e Merge "UUIDs can have their high bit set" 2014-05-23 09:01:20 -07:00
Sergey Ulanov
acf788bedd Add support for CropLeft, CropRight, CropTop and CropBottom elements.
Change-Id: Ic5993a3e04b3eefccc3016fbe6b49d1e4a5fc05d
2014-05-21 19:46:36 -07:00
Vignesh Venkatasubramanian
418188b03e Merge "muxer: codec_id is a mandatory element" 2014-05-18 12:48:29 -07:00
Vignesh Venkatasubramanian
07688c92d7 mkvmuxer: Reject frames if invalid track number is passed.
Reject frames if an invalid track number is passed. Also change sample_muxer
to reject files which have Block elements with invalid track numbers.

Fixes Issue #659: https://code.google.com/p/webm/issues/detail?id=659

Change-Id: Ie6cf39a409b68bb4d2261f308409ee0c36d5dd8e
2014-05-18 12:45:49 -07:00
Vignesh Venkatasubramanian
2a63e473d8 muxer: codec_id is a mandatory element
codec_id element for a Track is mandatory and it does not have a default.
Rejecting the file if that happens.

Change-Id: I4fb0dfcd4c09eeabf22634db7fdf6ca818c93917
2014-05-16 11:42:05 -07:00
Vignesh Venkatasubramanian
d13c017744 UUIDs can have their high bit set
mkvparser::UnserializeUInt() assumes that unsigned values never have
their high bit set. This is too limiting for UUIDs. In addition, the
Chapters::Atom::Parse() method would truncate a "negative" 64-bit UUID
value to 32 bits and return the truncated value as a status code.
This value then might or might not be treated as an error by the caller
depending on whether the truncated value was itself negative.

Change-Id: I15624ac62d0b02691a1405ee6a5f7eb441b3bc48
2014-05-16 11:25:22 -07:00
James Zern
249629d46c make Mkv(Reader|Writer)(FILE*) explicit
Change-Id: I2c6e0df3049903f8ea53babeacffaa87f6c222b0
2014-05-02 11:47:44 -07:00
Vignesh Venkatasubramanian
7f3cda494a mkvparser: fix a bunch of windows warnings
fix a bunch of windows warnings in parser.

Change-Id: Ia9a03879540595306d8fa2b90ceb9b3b5b0d93a6
2014-05-01 13:50:19 -07:00
Vignesh Venkatasubramanian
5c0617852f Merge "clang-format on mkvparser.[ch]pp" 2014-05-01 11:50:03 -07:00
Vignesh Venkatasubramanian
4df111e60a clang-format on mkvparser.[ch]pp
Conformance of mkvparser.[ch]pp to Google C++ style guide.

Change-Id: I459adac3da1496b432b71b3580b4dbd63037df2b
2014-04-29 11:30:00 -07:00
Vignesh Venkatasubramanian
7b2450131c clang-format re-run.
Re-running clang-format to take into account the recent change in it.
(https://gerrit.chromium.org/gerrit/#/c/69926/ )

Change-Id: Ie11afcaaf07a1967f65fd765f1a7c7112c85875a
2014-04-29 11:27:31 -07:00
Vignesh Venkatasubramanian
c6767b94fd Change AlignTrailingComments to false in .clang-format
AlignTrailingComments set to true seems to be causing some unwanted
alignments. Turning it off.

Change-Id: I5fd99db90b00c76cc7891f2cd1c80ec69ae97697
2014-04-29 00:38:14 -07:00
Vignesh Venkatasubramanian
9097a0691b Merge "muxer: Reject file if TrackType is never specified" 2014-04-29 00:18:55 -07:00
Vignesh Venkatasubramanian
eddf9744cb Merge "clang-format on mkvmuxertypes.hpp and webmids.hpp" 2014-04-28 10:40:43 -07:00
Vignesh Venkatasubramanian
def325c010 muxer: Reject file if TrackType is never specified
According to matroska specification, TrackType is a mandatory element without a
default value [1]. But we have been producing invalid matroska files when
TrackType is never specified because we write 0 by default.

This patch will reject writing a track without specifying the TrackType value.
Specifically, this path will be triggered when Segment::AddTrack() is called
but there is no subsequent call to Track::set_type().

[1] http://www.matroska.org/technical/specs/index.html#TrackType

Fixes issue #769: https://code.google.com/p/webm/issues/detail?id=769

Change-Id: I4d75d169fd96c7e1fad278561f0e7a3e1135989c
2014-04-26 03:14:05 -07:00
Vignesh Venkatasubramanian
41f869cb0c Merge "clang-format on webvttparser.(cc|h)" 2014-04-25 22:19:26 -07:00
Vignesh Venkatasubramanian
fd0be37ba4 clang-format on webvttparser.(cc|h)
Conformance of webvttparser.(cc|h) to Google C++ style guide.

Change-Id: I19610c5795c0bd2446c07a6c2abde58c3286b2ea
2014-04-25 22:18:40 -07:00
Vignesh Venkatasubramanian
207d8a193a Merge "clang-format on mkvmuxerutil.[ch]pp" 2014-04-25 22:09:48 -07:00
Vignesh Venkatasubramanian
02429eb11b Merge "clang-format on mkvwriter.[ch]pp" 2014-04-25 22:09:17 -07:00
Vignesh Venkatasubramanian
0cf7b1b7d3 Merge "clang-format on mkvreader.[ch]pp" 2014-04-25 22:09:02 -07:00
Vignesh Venkatasubramanian
2e80fedf8c Merge "clang-format on sample.cpp" 2014-04-25 22:08:38 -07:00
Vignesh Venkatasubramanian
3402e12d1a Merge "clang-format on sample_muxer.cpp" 2014-04-25 22:08:27 -07:00
Vignesh Venkatasubramanian
1a685db45b Merge "clang-format on sample_muxer_metadata.(cc|h)" 2014-04-25 22:07:59 -07:00
Vignesh Venkatasubramanian
6634c7f87a Merge "clang-format on vttreader.cc" 2014-04-25 22:07:46 -07:00
Vignesh Venkatasubramanian
7566004462 Merge "clang-format on vttdemux.cc" 2014-04-25 22:06:42 -07:00
Vignesh Venkatasubramanian
9915b8408e clang-format on mkvreader.[ch]pp
Conformance of mkvreader.[ch]pp to Google C++ style guide.

Change-Id: I9928a1a7daf9afaa30355b17b3eeeb2966626031
2014-04-15 12:05:58 -07:00
Vignesh Venkatasubramanian
743725477c clang-format on mkvmuxertypes.hpp and webmids.hpp
Conformance of mkvmuxertypes.hpp and webmids.hpp to Google C++ style guide.

Change-Id: Ib5e524f75f04ae6f6f5f24600d70b8448d01964c
2014-04-15 11:39:44 -07:00
Vignesh Venkatasubramanian
0d5a98cee5 clang-format on sample_muxer.cpp
Conformance of sample_muxer.cpp to Google C++ style guide.

Change-Id: I8d7ef884fbaac8ebbf12fc3e3215532ced5ac29b
2014-04-15 11:36:43 -07:00
Vignesh Venkatasubramanian
e3485c9b9f clang-format on vttdemux.cc
Conformance of vttdemux.cc to Google C++ style guide.

Change-Id: Id8838ddec286f935c8a3c1b78d9d9027b467165f
2014-04-15 11:31:20 -07:00
Vignesh Venkatasubramanian
46cc823994 clang-format on dumpvtt.cc
Conformance of dumpvtt.cc to Google C++ style guide.

Change-Id: I5fa11e79e95e61c1a1d923ba76ac7ae343c9c8e4
2014-04-14 12:15:04 -07:00
Vignesh Venkatasubramanian
5218bd291c clang-format on vttreader.cc
Conformance of vttreader.cc to Google C++ style guide.

Change-Id: Id5d2baf0977bca9ab938831cf6e6204acd4ed647
2014-04-14 12:11:27 -07:00
Vignesh Venkatasubramanian
1a0130d069 clang-format on sample_muxer_metadata.(cc|h)
Conformance of sample_muxer_metadata.(cc|h) to Google C++ style guide.

Change-Id: I500a8cdbc443981ecae6ac2a7d8de7cab1c72e28
2014-04-14 12:09:20 -07:00
Vignesh Venkatasubramanian
867f1894da clang-format on sample.cpp
Conformance of sample.cpp to Google C++ style guide.

Change-Id: Icb6bfce6af5df04775a086e080e6fa742c6d68f9
2014-04-14 12:05:21 -07:00
Vignesh Venkatasubramanian
4c7bec5743 clang-format on mkvwriter.[ch]pp
Conformance of mkvwriter.[ch]pp to Google C++ style guide.

Change-Id: I997545b366277b7f1235b9fa7cc30a4969098553
2014-04-14 10:30:33 -07:00
Vignesh Venkatasubramanian
9ead078aaf clang-format on mkvmuxerutil.[ch]pp
Conformance of mkvmuxerutil.[ch]pp to Google C++ style guide.

Change-Id: Ib66b73adb2682cd5560f6f363fc04d75ab3815c6
2014-04-14 10:28:59 -07:00
Vignesh Venkatasubramanian
fb6b6e6444 clang-format on mkvmuxer.[ch]pp
Conformance of mkvmuxer.[ch]pp to Google C++ style guide.

Change-Id: I9bcd14710adbad4f32aa1a6be2ea7e40fb715e91
2014-04-11 11:41:01 -07:00
Vignesh Venkatasubramanian
ce775929a6 Update .clang-format to allow short functions in one line
Update .clang-format so that it allows short functions and constructors in a
single line if it fits.

Change-Id: I60788089fc7a4e2f4c4df6947368ebc0f3fa8c49
2014-04-11 11:24:46 -07:00
Tom Finegan
0a24fe44ae Merge "Add support for DateUTC and DefaultDuration in MKV Muxer." 2014-04-10 16:13:21 -07:00
Vignesh Venkatasubramanian
11d5b66eb4 Merge "Add .clang-format" 2014-04-09 11:55:47 -07:00
Vignesh Venkatasubramanian
a1a3b14538 Add .clang-format
Add .clang-format file so that it can be used to maintain
the same style throughout the library.

Change-Id: I22bd21055f565a886b5a880856810f4b35b22cce
2014-04-09 11:50:54 -07:00
Sergey Ulanov
0fcec38045 Add support for DateUTC and DefaultDuration in MKV Muxer.
BUG=crbug.com/321825

Change-Id: I5ff8c5b9fd4e6be23ef2bc91a7a4ba021db6441f
2014-04-08 21:48:00 -07:00
Vignesh Venkatasubramanian
a7118d8ec5 Fixing a warning in mkvmuxerutil.cpp
Changing a constant from int32 to uint64 to fix a warning in
mkmuxerutil.cpp

Change-Id: Ifd9f76ea4be848eff4d98a797d2d4dcd22f11478
2014-04-08 16:15:28 -07:00
Vignesh Venkatasubramanian
abe9c2d0d1 Adding support for user file ownership in MkvReader
Adding a constructor to MkvReader that will enable user application
ownership of the file.

Change-Id: I10f8f71715392df3d4b78c7c11076e19c30e1af6
2014-04-04 13:49:52 -07:00
Vignesh Venkatasubramanian
630a0e3c33 mkvmuxerutil: Getting rid of strict-aliasing warning
Replacing a reinterpret_cast from float& to uint32& with a union to get rid of
"dereferencing type-punned pointer will break strict-aliasing rules" warning.
This warning is produced on passing -O3 in gcc.

Change-Id: Ie942597f418e3659e3ff29a909c43dd99266c04d
2014-03-17 12:19:21 -07:00
Vignesh Venkatasubramanian
e369bed319 Support user ownership of files in MkvWriter
Overloading MkvWriter's constructor so that it can wrap a user owned
FILE pointer. Doing this so that applications which handle the file opening
and closing by themselves don't have to have their own implementation of the
IMkvWriter interface.

Change-Id: I69c57f3e6927ea13b616c425e3b5f179d2e69215
2014-03-12 12:48:17 -07:00
Tom Finegan
a9d94ef2c5 Merge "vttdemux: Add VS2013 project." 2014-03-10 11:49:55 -07:00
Tom Finegan
3b66306126 vttdemux: Add VS2013 project.
And add it to the libwebm VS2013 solution.

Change-Id: I9957b47b291722bc0e5eb435795252cf780f968b
2014-03-10 11:46:53 -07:00
Tom Finegan
acb7a2c8bc Add VS2010 DLL build configurations for vttdemux.
- Link to libwebm instead of building sources.
- Add missing dependency on libwebm.

Change-Id: I8f977f767f6104d07f716c7c5ebecda249c202f2
2014-03-07 16:53:47 -08:00
Tom Finegan
99f40649a7 Merge "mkvmuxer: Silence MSVC warning that suggests making code non-portable." 2014-03-06 16:40:59 -08:00
Matthew Heaney
c6634bca44 Merge "vttdemux: created win32 project" 2014-03-06 14:36:03 -08:00
Matthew Heaney
17cf7cc519 vttdemux: created win32 project
Change-Id: I2a1ce12bc374f7493c50021cbe4fc4a4716a6829
2014-03-06 14:31:02 -08:00
Tom Finegan
7f79df14a8 Add Visual Studio 2013 projects.
Basically identical to the 2010 projects, but with platform
toolset set to VS 2013, and output files/paths updated to
avoid collisions with VS 2010 output.

Change-Id: I02b827288319db22eeb0beeed71261dc0673d6ef
2014-03-04 16:53:39 -08:00
Tom Finegan
23cdb09fd2 mkvmuxer: Silence MSVC warning that suggests making code non-portable.
Change-Id: I19bfa107bf01b1e10ac5a43040d409f4d620f4a7
2014-03-04 16:50:34 -08:00
Tom Finegan
8ae2137637 mkvparser: Silence MSVC warning that suggests making code non-portable.
Change-Id: Ia8b4cd39711105a5b3462b512160f9250e8a5966
2014-02-25 09:36:32 -08:00
Tom Finegan
7952ce8f78 Merge "mkvparser: Fix unused variable warnings when NDEBUG is defined." 2014-02-05 20:56:22 -08:00
Tom Finegan
d58f55542f mkvparser: Fix unused variable warnings when NDEBUG is defined.
Change-Id: I98b1121768e5650c2184acbf35636a15e9241148
2014-02-05 20:44:29 -08:00
Tom Finegan
a0c85b1e46 mkvparser/sample: Fix incorrect printf format specifiers.
Change-Id: I8b61f429f7bb1da7b3def612f6413895f8cb945d
2014-02-05 18:51:17 -08:00
Tom Finegan
4600f5b4a2 Merge "Fix mingw build." 2014-01-24 11:13:56 -08:00
Tom Finegan
a142b15ada Fix mingw build.
Change-Id: Iec913e0cf5849bec459e98df59b0e0bd8e02965b
2014-01-23 22:31:42 -08:00
Tom Finegan
4a3f5c9f99 Merge "mkvparser: Add basic cues walking to sample." 2014-01-23 22:29:12 -08:00
Tom Finegan
84f2156ca1 Merge "mkvmuxer: Add DiscardPadding support." 2014-01-23 15:34:12 -08:00
Tom Finegan
5440f20071 mkvparser: Add basic cues walking to sample.
Change-Id: Ia90e760f04083fa60b44f4d372e118474fc59fee
2014-01-23 15:31:18 -08:00
Tom Finegan
5c14a3f035 mkvparser/mkvreader/sample: CRLF -> LF
Change-Id: Id4a5bea411d104289548b276d0e996352cc816b1
2014-01-23 10:57:06 -08:00
Tom Finegan
71a097fb12 mkvparser sample: clang-formatify
Exception asterisk placement, which was left as before to match the rest of
libwebm.

Change-Id: I3947acc936cca68df72a5bcd8dec17ed40658ba6
2014-01-23 10:52:46 -08:00
Tom Finegan
cd6f7bff4b mkvmuxer: Add DiscardPadding support.
Also a bit of refactoring to remove some duplicate code.

Change-Id: Ia3d17461ae5f6275534e06c31f348bdfc4bba169
2014-01-22 23:26:26 -08:00
Tom Finegan
327e8ab617 Minor clean up: msvc warnings/include order/comment text.
Change-Id: I2b54abcb9f535715d8713930942447c0b0f5f862
2014-01-22 14:03:40 -08:00
Tom Finegan
796c90798a Merge "sample_muxer: Silence MSVC warning." 2014-01-16 13:01:54 -08:00
Sergey Ulanov
0f7815b036 Add license header in sample_muxer_metadata.cc.
This is required by the checklicenses.py script in chromium.

Change-Id: Ice6155b1332adcbda74532e558438083212e1511
2014-01-16 11:31:13 -08:00
Tom Finegan
ccb7fa9c73 sample_muxer: Silence MSVC warning.
Disable C4996; A warning that encourages users to make their code
require the "secure" variant of functions like tmpnam(). Doing so
just happens to make the resulting code require the MSVC runtime.

Change-Id: I0329ce3aa93da060110d24a4bc7f48a7f9c87227
2014-01-15 15:00:59 -08:00
Tom Finegan
4ec1e5cae5 Merge "mkvmuxer: Fix warnings." 2014-01-15 14:36:06 -08:00
Tom Finegan
849093f84f mkvmuxer: CRLF->LF webmids.h.
Match the other muxer sources. Also fix declaration order
of elements in the track grouping.

Change-Id: I06fdb98eb42815af96e80e33379ef73d41b470b3
2014-01-15 12:37:15 -08:00
Tom Finegan
32e1556e68 mkvmuxer: Fix warnings.
Remove useless spam from build output.

Change-Id: Iae200d32cda1fc11cd471772725345d0979e97bc
2014-01-15 12:14:27 -08:00
Tom Finegan
5efd6e3c1d mkvmuxer: Add support for VP9 and Opus tracks.
Also make codec ID constants really constant.

Change-Id: I951d25e83ce507afb1ca475e2d5dbfe6402f3d61
2014-01-10 15:03:47 -08:00
Tom Finegan
a6c71c1407 mkvmuxer: Add support for writing CodecDelay and SeekPreRoll elements.
Change-Id: Iad8c671b76c4b97abad58946df7f3c0ebe6cb01b
2014-01-10 11:32:56 -08:00
Tom Finegan
81c1d8415c mkvparser: Add support for CodecDelay, DiscardPadding, and SeekPreRoll elements.
Change-Id: Ic9e6ebcc2ba533f8cc1ab933d0bf55782ccab932
2014-01-08 17:33:03 -08:00
Vignesh Venkatasubramanian
d2f7478148 Initializing last_block_duration_ to zero.
Adding a missing initialization.

Change-Id: Id4223765968745a46653139b2a9f1537102c3618
2013-10-30 11:13:38 -07:00
Vignesh Venkatasubramanian
fd0a65af98 Merge "Fixing a bug in Chapter::Clear" 2013-10-25 11:13:05 -07:00
Vignesh Venkatasubramanian
872cc57de4 Adding set_uid to Chapter Class
Adding set_uid function to the Chapter class. It can be used to
achieve deterministic output from the muxer. For example, for files
with only one segment, track number or track id can be used for
chapter uid.

Change-Id: I2e94c6150e32cb9019a6623af7919acc099aa20d
2013-10-25 09:33:28 -07:00
Vignesh Venkatasubramanian
ddfea3431f Fixing a bug in Chapter::Clear
Replacing a typo'd < with > in Chapter::Clear of mkvmuxer.

Change-Id: I8784d19dbca5a8a62c92ed14e2efa61d96c5375f
2013-10-25 09:12:11 -07:00
Vignesh Venkatasubramanian
4134f6e04e Adding AddLastFrame to Segment
Adding AddLastFrame function to the Segment muxer so that the duration
of the Segment can be accurately calculated given the last Block's duration.
We now provide an AddLastFrame function which will take duration of that block
as a parameter. When this function is used to add the last frame, the duration
of it is taken into account when computing the Segment's duration.

Change-Id: I3e1456299fefa1a4dd6d845c47292951d1ce3ad0
2013-10-25 08:28:23 -07:00
44 changed files with 12372 additions and 13833 deletions

53
.clang-format Normal file
View File

@@ -0,0 +1,53 @@
---
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -1
ConstructorInitializerIndentWidth: 4
AlignEscapedNewlinesLeft: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortFunctionsOnASingleLine: true
AlwaysBreakTemplateDeclarations: true
AlwaysBreakBeforeMultilineStrings: true
BreakBeforeBinaryOperators: false
BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: false
BinPackParameters: true
ColumnLimit: 80
ConstructorInitializerAllOnOneLineOrOnePerLine: true
DerivePointerBinding: true
ExperimentalAutoDetectBinPacking: false
IndentCaseLabels: true
MaxEmptyLinesToKeep: 1
KeepEmptyLinesAtTheStartOfBlocks: false
NamespaceIndentation: None
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: false
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakString: 1000
PenaltyBreakFirstLessLess: 120
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerBindsToType: true
SpacesBeforeTrailingComments: 2
Cpp11BracedListStyle: true
Standard: Auto
IndentWidth: 2
TabWidth: 8
UseTab: Never
BreakBeforeBraces: Attach
IndentFunctionDeclarationAfterType: true
SpacesInParentheses: false
SpacesInAngles: false
SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: true
SpaceBeforeAssignmentOperators: true
ContinuationIndentWidth: 4
CommentPragmas: '^ IWYU pragma:'
SpaceBeforeParens: ControlStatements
...

6
.gitignore vendored
View File

@@ -19,5 +19,9 @@ Release
ipch
dumpvtt
sample
samplemuxer
sample_muxer
vttdemux
Makefile
CMakeFiles
CMakeCache.txt
*.cmake

64
CMakeLists.txt Normal file
View File

@@ -0,0 +1,64 @@
## Copyright (c) 2015 The WebM project authors. All Rights Reserved.
##
## Use of this source code is governed by a BSD-style license
## that can be found in the LICENSE file in the root of the source
## tree. An additional intellectual property rights grant can be found
## in the file PATENTS. All contributing project authors may
## be found in the AUTHORS file in the root of the source tree.
cmake_minimum_required(VERSION 2.8)
project(LIBWEBM)
include("${CMAKE_CURRENT_SOURCE_DIR}/build/msvc_runtime.cmake")
set(LIBWEBM_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
# Libwebm section.
add_library(webm STATIC
"${LIBWEBM_SRC_DIR}/mkvmuxer.cpp"
"${LIBWEBM_SRC_DIR}/mkvmuxer.hpp"
"${LIBWEBM_SRC_DIR}/mkvmuxertypes.hpp"
"${LIBWEBM_SRC_DIR}/mkvmuxerutil.cpp"
"${LIBWEBM_SRC_DIR}/mkvmuxerutil.hpp"
"${LIBWEBM_SRC_DIR}/mkvparser.cpp"
"${LIBWEBM_SRC_DIR}/mkvparser.hpp"
"${LIBWEBM_SRC_DIR}/mkvreader.cpp"
"${LIBWEBM_SRC_DIR}/mkvreader.hpp"
"${LIBWEBM_SRC_DIR}/mkvwriter.cpp"
"${LIBWEBM_SRC_DIR}/mkvwriter.hpp"
"${LIBWEBM_SRC_DIR}/webmids.hpp")
if(WIN32)
# Use libwebm and libwebm.lib for project and library name on Windows (instead
# webm and webm.lib).
set_target_properties(webm PROPERTIES PROJECT_LABEL libwebm)
set_target_properties(webm PROPERTIES PREFIX lib)
endif(WIN32)
include_directories("${LIBWEBM_SRC_DIR}")
# Sample section.
add_executable(sample
"${LIBWEBM_SRC_DIR}/sample.cpp")
target_link_libraries(sample LINK_PUBLIC webm)
# Sample muxer section.
add_executable(sample_muxer
"${LIBWEBM_SRC_DIR}/sample_muxer.cpp"
"${LIBWEBM_SRC_DIR}/sample_muxer_metadata.cc"
"${LIBWEBM_SRC_DIR}/sample_muxer_metadata.h"
"${LIBWEBM_SRC_DIR}/vttreader.cc"
"${LIBWEBM_SRC_DIR}/vttreader.h"
"${LIBWEBM_SRC_DIR}/webvttparser.cc"
"${LIBWEBM_SRC_DIR}/webvttparser.h")
target_link_libraries(sample_muxer LINK_PUBLIC webm)
# Vttdemux section.
add_executable(vttdemux
"${LIBWEBM_SRC_DIR}/vttdemux.cc"
"${LIBWEBM_SRC_DIR}/webvttparser.cc"
"${LIBWEBM_SRC_DIR}/webvttparser.h")
target_link_libraries(vttdemux LINK_PUBLIC webm)
# webm2pes section.
add_executable(webm2pes
"${LIBWEBM_SRC_DIR}/webm2pes.cc"
"${LIBWEBM_SRC_DIR}/webm2pes.h")
target_link_libraries(webm2pes LINK_PUBLIC webm)

View File

@@ -12,14 +12,14 @@ OBJECTS4 := vttdemux.o webvttparser.o
INCLUDES := -I.
DEPS := $(WEBMOBJS:.o=.d) $(OBJECTS1:.o=.d) $(OBJECTS2:.o=.d)
DEPS += $(OBJECTS3:.o=.d) $(OBJECTS4:.o=.d)
EXES := samplemuxer sample dumpvtt vttdemux
EXES := sample_muxer sample dumpvtt vttdemux
all: $(EXES)
sample: sample.o $(LIBWEBMA)
$(CXX) $^ -o $@
samplemuxer: $(OBJECTS2) $(LIBWEBMA)
sample_muxer: $(OBJECTS2) $(LIBWEBMA)
$(CXX) $^ -o $@
dumpvtt: $(OBJECTS3)

View File

@@ -1,22 +1,23 @@
Additional IP Rights Grant (Patents)
------------------------------------
"This implementation" means the copyrightable works distributed by
Google as part of the WebM Project.
"These implementations" means the copyrightable works that implement the WebM
codecs distributed by Google as part of the WebM Project.
Google hereby grants to you a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section)
patent license to make, have made, use, offer to sell, sell, import,
transfer, and otherwise run, modify and propagate the contents of this
implementation of VP8, where such license applies only to those patent
claims, both currently owned by Google and acquired in the future,
licensable by Google that are necessarily infringed by this
implementation of VP8. This grant does not include claims that would be
infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or
order or agree to the institution of patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging
that this implementation of VP8 or any code incorporated within this
implementation of VP8 constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of VP8
shall terminate as of the date such litigation is filed.
Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge,
royalty-free, irrevocable (except as stated in this section) patent license to
make, have made, use, offer to sell, sell, import, transfer, and otherwise
run, modify and propagate the contents of these implementations of WebM, where
such license applies only to those patent claims, both currently owned by
Google and acquired in the future, licensable by Google that are necessarily
infringed by these implementations of WebM. This grant does not include claims
that would be infringed only as a consequence of further modification of these
implementations. If you or your agent or exclusive licensee institute or order
or agree to the institution of patent litigation or any other patent
enforcement activity against any entity (including a cross-claim or
counterclaim in a lawsuit) alleging that any of these implementations of WebM
or any code incorporated within any of these implementations of WebM
constitute direct or contributory patent infringement, or inducement of
patent infringement, then any patent rights granted to you under this License
for these implementations of WebM shall terminate as of the date such
litigation is filed.

57
README.libwebm Normal file
View File

@@ -0,0 +1,57 @@
Building Libwebm
To build libwebm you must first create project files. To do this run cmake
and pass it the path to your libwebm repo.
Makefile.unix can be used as a fallback on systems that cmake does not
support.
CMake Basics
To generate project/make files for the default toolchain on your system simply
run cmake with the path to the libwebm repo:
$ cmake path/to/libwebm
On Windows the above command will produce Visual Studio project files for the
newest Visual Studio detected on the system. On Mac OS X and Linux systems, the
above command will produce a makefile.
To control what types of projects are generated the -G parameter is added to
the cmake command line. This argument must be followed by the name of a
generator. Running cmake with the --help argument will list the available
generators for your system.
On Mac OS X you would run the following command to generate Xcode projects:
$ cmake path/to/libwebm -G Xcode
On a Windows box you would run the following command to generate Visual Studio
2013 projects:
$ cmake path/to/libwebm -G "Visual Studio 12"
To generate 64-bit Windows Visual Studio 2013 projects:
$ cmake path/to/libwebm "Visual Studio 12 Win64"
CMake Makefiles: Debugging and Optimization
Unlike Visual Studio and Xcode projects, the build configuration for make builds
is controlled when you run cmake. The following examples demonstrate various
build configurations.
Omitting the build type produces makefiles that use build flags containing
neither optimization nor debug flags:
$ cmake path/to/libwebm
A makefile using release (optimized) flags is produced like this:
$ cmake path/to/libwebm -DCMAKE_BUILD_TYPE=release
A release build with debug info can be produced as well:
$ cmake path/to/libwebm -DCMAKE_BUILD_TYPE=relwithdebinfo
And your standard debug build will be produced using:
$ cmake path/to/libwebm -DCMAKE_BUILD_TYPE=debug

View File

@@ -1,34 +0,0 @@
1.0.0.5
* Handled case when no duration
* Handled empty clusters
* Handled empty clusters when seeking
* Implemented check lacing bits
1.0.0.4
* Made Cues member variables mutables
* Defined against badly-formatted cue points
* Segment::GetCluster returns CuePoint too
* Separated cue-based searches
1.0.0.3
* Added Block::GetOffset() to get a frame's offset in a block
* Changed cluster count type from size_t to long
* Parsed SeekHead to find cues
* Allowed seeking beyond end of cluster cache
* Added not to attempt to reparse cues element
* Restructured Segment::LoadCluster
* Marked position of cues without parsing cues element
* Allowed cue points to be loaded incrementally
* Implemented to load lazily cue points as they're searched
* Merged Cues::LoadCuePoint into Cues::Find
* Lazy init cues
* Loaded cue point during find
1.0.0.2
* added support for Cues element
* seeking was improved
1.0.0.1
* fixed item 141
* added item 142
* added this file, RELEASE.TXT, to repository

24
build/msvc_runtime.cmake Normal file
View File

@@ -0,0 +1,24 @@
## Copyright (c) 2015 The WebM project authors. All Rights Reserved.
##
## Use of this source code is governed by a BSD-style license
## that can be found in the LICENSE file in the root of the source
## tree. An additional intellectual property rights grant can be found
## in the file PATENTS. All contributing project authors may
## be found in the AUTHORS file in the root of the source tree.
cmake_minimum_required(VERSION 2.8)
if(WIN32)
# CMake defaults to producing code linked to the DLL MSVC runtime. In libwebm
# static is typically desired. Force static code generation unless the user
# running CMake set MSVC_RUNTIME to dll.
if(NOT "${MSVC_RUNTIME}" STREQUAL "dll")
foreach(flag_var
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
if(${flag_var} MATCHES "/MD")
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
endif(${flag_var} MATCHES "/MD")
endforeach(flag_var)
endif(NOT "${MSVC_RUNTIME}" STREQUAL "dll")
endif(WIN32)

62
common/common.sh Normal file
View File

@@ -0,0 +1,62 @@
#!/bin/sh
##
## Copyright (c) 2015 The WebM project authors. All Rights Reserved.
##
## Use of this source code is governed by a BSD-style license
## that can be found in the LICENSE file in the root of the source
## tree. An additional intellectual property rights grant can be found
## in the file PATENTS. All contributing project authors may
## be found in the AUTHORS file in the root of the source tree.
##
set -e
devnull='> /dev/null 2>&1'
readonly ORIG_PWD="$(pwd)"
elog() {
echo "${0##*/} failed because: $@" 1>&2
}
vlog() {
if [ "${VERBOSE}" = "yes" ]; then
echo "$@"
fi
}
# Terminates script when name of current directory does not match $1.
check_dir() {
current_dir="$(pwd)"
required_dir="$1"
if [ "${current_dir##*/}" != "${required_dir}" ]; then
elog "This script must be run from the ${required_dir} directory."
exit 1
fi
}
# Terminates the script when $1 is not in $PATH. Any arguments required for
# the tool being tested to return a successful exit code can be passed as
# additional arguments.
check_tool() {
tool="$1"
shift
tool_args="$@"
if ! eval "${tool}" ${tool_args} > /dev/null 2>&1; then
elog "${tool} must be in your path."
exit 1
fi
}
# Echoes git describe output for the directory specified by $1 to stdout.
git_describe() {
git_dir="$1"
check_git
echo $(git -C "${git_dir}" describe)
}
# Echoes current git revision for the directory specifed by $1 to stdout.
git_revision() {
git_dir="$1"
check_git
echo $(git -C "${git_dir}" rev-parse HEAD)
}

View File

@@ -48,18 +48,12 @@ int main(int argc, const char* argv[]) {
fprintf(stdout, "cue identifier: \"%s\"\n", cue.identifier.c_str());
const libwebvtt::Time& st = cue.start_time;
fprintf(stdout, "cue start time: \"HH=%i MM=%i SS=%i SSS=%i\"\n",
st.hours,
st.minutes,
st.seconds,
st.milliseconds);
fprintf(stdout, "cue start time: \"HH=%i MM=%i SS=%i SSS=%i\"\n", st.hours,
st.minutes, st.seconds, st.milliseconds);
const libwebvtt::Time& sp = cue.stop_time;
fprintf(stdout, "cue stop time: \"HH=%i MM=%i SS=%i SSS=%i\"\n",
sp.hours,
sp.minutes,
sp.seconds,
sp.milliseconds);
fprintf(stdout, "cue stop time: \"HH=%i MM=%i SS=%i SSS=%i\"\n", sp.hours,
sp.minutes, sp.seconds, sp.milliseconds);
{
typedef libwebvtt::Cue::settings_t::const_iterator iter_t;
@@ -72,8 +66,7 @@ int main(int argc, const char* argv[]) {
while (i != j) {
const libwebvtt::Setting& setting = *i++;
fprintf(stdout, "cue setting: name=%s value=%s\n",
setting.name.c_str(),
setting.value.c_str());
setting.name.c_str(), setting.value.c_str());
}
}
}

193
iosbuild.sh Executable file
View File

@@ -0,0 +1,193 @@
#!/bin/sh
##
## Copyright (c) 2015 The WebM project authors. All Rights Reserved.
##
## Use of this source code is governed by a BSD-style license
## that can be found in the LICENSE file in the root of the source
## tree. An additional intellectual property rights grant can be found
## in the file PATENTS. All contributing project authors may
## be found in the AUTHORS file in the root of the source tree.
##
## This script generates 'WebM.framework'. An iOS app can mux/demux WebM
## container files by including 'WebM.framework'.
##
## Run ./iosbuild.sh to generate 'WebM.framework'. By default the framework
## bundle will be created in a directory called framework. Use --out-dir to
## change the output directory.
##
## This script is based on iosbuild.sh from the libwebp project.
. $(dirname $0)/common/common.sh
# Trap function. Cleans up build output.
cleanup() {
local readonly res=$?
cd "${ORIG_PWD}"
for dir in ${LIBDIRS}; do
if [ -d "${dir}" ]; then
rm -rf "${dir}"
fi
done
if [ $res -ne 0 ]; then
elog "build exited with error ($res)"
fi
}
trap cleanup EXIT
check_dir libwebm
iosbuild_usage() {
cat << EOF
Usage: ${0##*/} [arguments]
--help: Display this message and exit.
--out-dir: Override output directory (default is ${OUTDIR}).
--show-build-output: Show output from each library build.
--verbose: Output information about the environment and each stage of the
build.
EOF
}
# Extract the latest SDK version from the final field of the form: iphoneosX.Y
readonly SDK=$(xcodebuild -showsdks \
| grep iphoneos | sort | tail -n 1 | awk '{print substr($NF, 9)}'
)
# Extract Xcode version.
readonly XCODE=$(xcodebuild -version | grep Xcode | cut -d " " -f2)
if [ -z "${XCODE}" ]; then
echo "Xcode not available"
exit 1
fi
# Add iPhoneOS-V6 to the list of platforms below if you need armv6 support.
# Note that iPhoneOS-V6 support is not available with the iOS6 SDK.
readonly INCLUDES="mkvmuxer.hpp
mkvmuxertypes.hpp
mkvmuxerutil.hpp
mkvparser.hpp
mkvreader.hpp
mkvwriter.hpp
webmids.hpp"
readonly PLATFORMS="iPhoneSimulator
iPhoneSimulator64
iPhoneOS-V7
iPhoneOS-V7s
iPhoneOS-V7-arm64"
readonly TARGETDIR="WebM.framework"
readonly DEVELOPER="$(xcode-select --print-path)"
readonly PLATFORMSROOT="${DEVELOPER}/Platforms"
readonly LIPO="$(xcrun -sdk iphoneos${SDK} -find lipo)"
LIBLIST=""
OPT_FLAGS="-DNDEBUG -O3"
readonly SDK_MAJOR_VERSION="$(echo ${SDK} | awk -F '.' '{ print $1 }')"
if [ -z "${SDK_MAJOR_VERSION}" ]; then
elog "iOS SDK not available"
exit 1
elif [ "${SDK_MAJOR_VERSION}" -lt "6" ]; then
elog "You need iOS SDK version 6 or above"
exit 1
else
vlog "iOS SDK Version ${SDK}"
fi
# Parse the command line.
while [ -n "$1" ]; do
case "$1" in
--help)
iosbuild_usage
exit
;;
--out-dir)
OUTDIR="$2"
shift
;;
--enable-debug)
OPT_FLAGS="-g"
;;
--show-build-output)
devnull=
;;
--verbose)
VERBOSE=yes
;;
*)
iosbuild_usage
exit 1
;;
esac
shift
done
readonly OPT_FLAGS="${OPT_FLAGS}"
readonly OUTDIR="${OUTDIR:-framework}"
if [ "${VERBOSE}" = "yes" ]; then
cat << EOF
OUTDIR=${OUTDIR}
INCLUDES=${INCLUDES}
PLATFORMS=${PLATFORMS}
TARGETDIR=${TARGETDIR}
DEVELOPER=${DEVELOPER}
LIPO=${LIPO}
OPT_FLAGS=${OPT_FLAGS}
ORIG_PWD=${ORIG_PWD}
EOF
fi
rm -rf "${OUTDIR}/${TARGETDIR}"
mkdir -p "${OUTDIR}/${TARGETDIR}/Headers/"
for PLATFORM in ${PLATFORMS}; do
ARCH2=""
if [ "${PLATFORM}" = "iPhoneOS-V7-arm64" ]; then
PLATFORM="iPhoneOS"
ARCH="aarch64"
ARCH2="arm64"
elif [ "${PLATFORM}" = "iPhoneOS-V7s" ]; then
PLATFORM="iPhoneOS"
ARCH="armv7s"
elif [ "${PLATFORM}" = "iPhoneOS-V7" ]; then
PLATFORM="iPhoneOS"
ARCH="armv7"
elif [ "${PLATFORM}" = "iPhoneOS-V6" ]; then
PLATFORM="iPhoneOS"
ARCH="armv6"
elif [ "${PLATFORM}" = "iPhoneSimulator64" ]; then
PLATFORM="iPhoneSimulator"
ARCH="x86_64"
else
ARCH="i386"
fi
LIBDIR="${OUTDIR}/${PLATFORM}-${SDK}-${ARCH}"
LIBDIRS="${LIBDIRS} ${LIBDIR}"
LIBFILE="${LIBDIR}/libwebm.a"
eval mkdir -p "${LIBDIR}" ${devnull}
DEVROOT="${DEVELOPER}/Toolchains/XcodeDefault.xctoolchain"
SDKROOT="${PLATFORMSROOT}/"
SDKROOT="${SDKROOT}${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDK}.sdk/"
CXXFLAGS="-arch ${ARCH2:-${ARCH}} -isysroot ${SDKROOT} ${OPT_FLAGS}
-miphoneos-version-min=6.0"
# Build using the legacy makefile (instead of generating via cmake).
eval make -f Makefile.unix libwebm.a CXXFLAGS=\"${CXXFLAGS}\" ${devnull}
# copy lib and add it to LIBLIST.
eval cp libwebm.a "${LIBFILE}" ${devnull}
LIBLIST="${LIBLIST} ${LIBFILE}"
# clean build so we can go again.
eval make -f Makefile.unix clean ${devnull}
done
for include_file in ${INCLUDES}; do
eval cp -p ${include_file} "${OUTDIR}/${TARGETDIR}/Headers/" ${devnull}
done
eval ${LIPO} -create ${LIBLIST} -output "${OUTDIR}/${TARGETDIR}/WebM" ${devnull}
echo "Succesfully built ${TARGETDIR} in ${OUTDIR}."

View File

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

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

View File

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

View File

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

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,7 @@
// http://www.webmproject.org/code/specs/container/.
namespace mkvparser {
class IMkvReader;
class IMkvReader;
} // end namespace
namespace mkvmuxer {
@@ -23,6 +23,8 @@ namespace mkvmuxer {
class MkvWriter;
class Segment;
const uint64 kMaxTrackNumber = 126;
///////////////////////////////////////////////////////////////
// Interface used by the mkvmuxer to write out the Mkv data.
class IMkvWriter {
@@ -57,11 +59,15 @@ class IMkvWriter {
// Writes out the EBML header for a WebM file. This function must be called
// before any other libwebm writing functions are called.
bool WriteEbmlHeader(IMkvWriter* writer, uint64 doc_type_version);
// Deprecated. Writes out EBML header with doc_type_version as
// kDefaultDocTypeVersion. Exists for backward compatibility.
bool WriteEbmlHeader(IMkvWriter* writer);
// Copies in Chunk from source to destination between the given byte positions
bool ChunkedCopy(mkvparser::IMkvReader* source, IMkvWriter* dst,
int64 start, int64 size);
bool ChunkedCopy(mkvparser::IMkvReader* source, IMkvWriter* dst, int64 start,
int64 size);
///////////////////////////////////////////////////////////////
// Class to hold data the will be written to a block.
@@ -70,22 +76,65 @@ class Frame {
Frame();
~Frame();
// Sets this frame's contents based on |frame|. Returns true on success. On
// failure, this frame's existing contents may be lost.
bool CopyFrom(const Frame& frame);
// Copies |frame| data into |frame_|. Returns true on success.
bool Init(const uint8* frame, uint64 length);
// Copies |additional| data into |additional_|. Returns true on success.
bool AddAdditionalData(const uint8* additional, uint64 length, uint64 add_id);
// Returns true if the frame has valid parameters.
bool IsValid() const;
// Returns true if the frame can be written as a SimpleBlock based on current
// parameters.
bool CanBeSimpleBlock() const;
uint64 add_id() const { return add_id_; }
const uint8* additional() const { return additional_; }
uint64 additional_length() const { return additional_length_; }
void set_duration(uint64 duration) { duration_ = duration; }
uint64 duration() const { return duration_; }
const uint8* frame() const { return frame_; }
void set_is_key(bool key) { is_key_ = key; }
bool is_key() const { return is_key_; }
uint64 length() const { return length_; }
void set_track_number(uint64 track_number) { track_number_ = track_number; }
uint64 track_number() const { return track_number_; }
void set_timestamp(uint64 timestamp) { timestamp_ = timestamp; }
uint64 timestamp() const { return timestamp_; }
void set_is_key(bool key) { is_key_ = key; }
bool is_key() const { return is_key_; }
void set_discard_padding(int64 discard_padding) {
discard_padding_ = discard_padding;
}
int64 discard_padding() const { return discard_padding_; }
void set_reference_block_timestamp(int64 reference_block_timestamp);
int64 reference_block_timestamp() const { return reference_block_timestamp_; }
bool reference_block_timestamp_set() const {
return reference_block_timestamp_set_;
}
private:
// Id of the Additional data.
uint64 add_id_;
// Pointer to additional data. Owned by this class.
uint8* additional_;
// Length of the additional data.
uint64 additional_length_;
// Duration of the frame in nanoseconds.
uint64 duration_;
// Pointer to the data. Owned by this class.
uint8* frame_;
// Flag telling if the data should set the key flag of a block.
bool is_key_;
// Length of the data.
uint64 length_;
@@ -95,8 +144,16 @@ class Frame {
// Timestamp of the data in nanoseconds.
uint64 timestamp_;
// Flag telling if the data should set the key flag of a block.
bool is_key_;
// Discard padding for the frame.
int64 discard_padding_;
// Reference block timestamp.
int64 reference_block_timestamp_;
// Flag indicating if |reference_block_timestamp_| has been set.
bool reference_block_timestamp_set_;
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Frame);
};
///////////////////////////////////////////////////////////////
@@ -195,9 +252,7 @@ class Cues {
// ContentEncAESSettings element
class ContentEncAESSettings {
public:
enum {
kCTR = 1
};
enum { kCTR = 1 };
ContentEncAESSettings();
~ContentEncAESSettings() {}
@@ -319,6 +374,16 @@ class Track {
uint64 type() const { return type_; }
void set_uid(uint64 uid) { uid_ = uid; }
uint64 uid() const { return uid_; }
void set_codec_delay(uint64 codec_delay) { codec_delay_ = codec_delay; }
uint64 codec_delay() const { return codec_delay_; }
void set_seek_pre_roll(uint64 seek_pre_roll) {
seek_pre_roll_ = seek_pre_roll;
}
uint64 seek_pre_roll() const { return seek_pre_roll_; }
void set_default_duration(uint64 default_duration) {
default_duration_ = default_duration;
}
uint64 default_duration() const { return default_duration_; }
uint64 codec_private_length() const { return codec_private_length_; }
uint32 content_encoding_entries_size() const {
@@ -326,7 +391,7 @@ class Track {
}
private:
// Track element names
// Track element names.
char* codec_id_;
uint8* codec_private_;
char* language_;
@@ -335,6 +400,9 @@ class Track {
uint64 number_;
uint64 type_;
uint64 uid_;
uint64 codec_delay_;
uint64 seek_pre_roll_;
uint64 default_duration_;
// Size of the CodecPrivate data in bytes.
uint64 codec_private_length_;
@@ -355,16 +423,13 @@ class VideoTrack : public Track {
// Supported modes for stereo 3D.
enum StereoMode {
kMono = 0,
kSideBySideLeftIsFirst = 1,
kTopBottomRightIsFirst = 2,
kTopBottomLeftIsFirst = 3,
kSideBySideLeftIsFirst = 1,
kTopBottomRightIsFirst = 2,
kTopBottomLeftIsFirst = 3,
kSideBySideRightIsFirst = 11
};
enum AlphaMode {
kNoAlpha = 0,
kAlpha = 1
};
enum AlphaMode { kNoAlpha = 0, kAlpha = 1 };
// The |seed| parameter is used to synthesize a UID for the track.
explicit VideoTrack(unsigned int* seed);
@@ -387,6 +452,16 @@ class VideoTrack : public Track {
uint64 display_height() const { return display_height_; }
void set_display_width(uint64 width) { display_width_ = width; }
uint64 display_width() const { return display_width_; }
void set_crop_left(uint64 crop_left) { crop_left_ = crop_left; }
uint64 crop_left() const { return crop_left_; }
void set_crop_right(uint64 crop_right) { crop_right_ = crop_right; }
uint64 crop_right() const { return crop_right_; }
void set_crop_top(uint64 crop_top) { crop_top_ = crop_top; }
uint64 crop_top() const { return crop_top_; }
void set_crop_bottom(uint64 crop_bottom) { crop_bottom_ = crop_bottom; }
uint64 crop_bottom() const { return crop_bottom_; }
void set_frame_rate(double frame_rate) { frame_rate_ = frame_rate; }
double frame_rate() const { return frame_rate_; }
void set_height(uint64 height) { height_ = height; }
@@ -403,6 +478,10 @@ class VideoTrack : public Track {
// Video track element names.
uint64 display_height_;
uint64 display_width_;
uint64 crop_left_;
uint64 crop_right_;
uint64 crop_top_;
uint64 crop_bottom_;
double frame_rate_;
uint64 height_;
uint64 stereo_mode_;
@@ -448,13 +527,13 @@ class AudioTrack : public Track {
class Tracks {
public:
// Audio and video type defined by the Matroska specs.
enum {
kVideo = 0x1,
kAudio = 0x2
};
// Vorbis and VP8 coded id defined by the Matroska specs.
static const char* const kVorbisCodecId;
static const char* const kVp8CodecId;
enum { kVideo = 0x1, kAudio = 0x2 };
static const char kOpusCodecId[];
static const char kVorbisCodecId[];
static const char kVp8CodecId[];
static const char kVp9CodecId[];
static const char kVp10CodecId[];
Tracks();
~Tracks();
@@ -490,6 +569,9 @@ class Tracks {
// Number of Track elements added.
uint32 track_entries_size_;
// Whether or not Tracks element has already been written via IMkvWriter.
mutable bool wrote_tracks_;
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tracks);
};
@@ -506,10 +588,13 @@ class Chapter {
// Converts the nanosecond start and stop times of this chapter to
// their corresponding timecode values, and stores them that way.
void set_time(const Segment& segment,
uint64 start_time_ns,
void set_time(const Segment& segment, uint64 start_time_ns,
uint64 end_time_ns);
// Sets the uid for this chapter. Primarily used to enable
// deterministic output from the muxer.
void set_uid(const uint64 uid) { uid_ = uid; }
// Add a title string to this chapter, per the semantics described
// here:
// http://www.matroska.org/technical/specs/index.html
@@ -526,9 +611,7 @@ class Chapter {
// http://www.iana.org/domains/root/db/
//
// The function returns false if the string could not be allocated.
bool add_string(const char* title,
const char* language,
const char* country);
bool add_string(const char* title, const char* language, const char* country);
private:
friend class Chapters;
@@ -657,6 +740,112 @@ class Chapters {
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Chapters);
};
///////////////////////////////////////////////////////////////
// Tag element
//
class Tag {
public:
bool add_simple_tag(const char* tag_name, const char* tag_string);
private:
// Tags calls Clear and the destructor of Tag
friend class Tags;
// For storage of simple tags
class SimpleTag {
public:
// Establish representation invariant for new SimpleTag object.
void Init();
// Reclaim resources, in anticipation of destruction.
void Clear();
// Copies the title to the |tag_name_| member. Returns false on
// error.
bool set_tag_name(const char* tag_name);
// Copies the language to the |tag_string_| member. Returns false
// on error.
bool set_tag_string(const char* tag_string);
// If |writer| is non-NULL, serialize the SimpleTag sub-element of
// the Atom into the stream. Returns the SimpleTag element size on
// success, 0 if error.
uint64 Write(IMkvWriter* writer) const;
private:
char* tag_name_;
char* tag_string_;
};
Tag();
~Tag();
// Copies this Tag object to a different one. This is used when
// expanding a plain array of Tag objects (see Tags).
void ShallowCopy(Tag* dst) const;
// Reclaim resources used by this Tag object, pending its
// destruction.
void Clear();
// If there is no storage remaining on the |simple_tags_| array for a
// new display object, creates a new, longer array and copies the
// existing SimpleTag objects to the new array. Returns false if the
// array cannot be expanded.
bool ExpandSimpleTagsArray();
// If |writer| is non-NULL, serialize the Tag sub-element into the
// stream. Returns the total size of the element on success, 0 if
// error.
uint64 Write(IMkvWriter* writer) const;
// The Atom element can contain multiple SimpleTag sub-elements
SimpleTag* simple_tags_;
// The physical length (total size) of the |simple_tags_| array.
int simple_tags_size_;
// The logical length (number of active elements) on the |simple_tags_|
// array.
int simple_tags_count_;
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tag);
};
///////////////////////////////////////////////////////////////
// Tags element
//
class Tags {
public:
Tags();
~Tags();
Tag* AddTag();
// Returns the number of tags that have been added.
int Count() const;
// Output the Tags element to the writer. Returns true on success.
bool Write(IMkvWriter* writer) const;
private:
// Expands the tags_ array if there is not enough space to contain
// another tag object. Returns true on success.
bool ExpandTagsArray();
// Total length of the tags_ array.
int tags_size_;
// Number of active tags on the tags_ array.
int tags_count_;
// Array for storage of tag objects.
Tag* tags_;
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tags);
};
///////////////////////////////////////////////////////////////
// Cluster element
//
@@ -664,34 +853,36 @@ class Chapters {
// |Init| must be called before any other method in this class.
class Cluster {
public:
Cluster(uint64 timecode, int64 cues_pos);
~Cluster();
// |timecode| is the absolute timecode of the cluster. |cues_pos| is the
// position for the cluster within the segment that should be written in
// the cues element.
// the cues element. |timecode_scale| is the timecode scale of the segment.
Cluster(uint64 timecode, int64 cues_pos, uint64 timecode_scale);
~Cluster();
bool Init(IMkvWriter* ptr_writer);
// Adds a frame to be output in the file. The frame is written out through
// |writer_| if successful. Returns true on success.
bool AddFrame(const Frame* frame);
// Adds a frame to be output in the file. The frame is written out through
// |writer_| if successful. Returns true on success.
// Inputs:
// frame: Pointer to the data
// data: Pointer to the data
// length: Length of the data
// track_number: Track to add the data to. Value returned by Add track
// functions. The range of allowed values is [1, 126].
// timecode: Absolute (not relative to cluster) timestamp of the
// frame, expressed in timecode units.
// is_key: Flag telling whether or not this frame is a key frame.
bool AddFrame(const uint8* frame,
uint64 length,
uint64 track_number,
bool AddFrame(const uint8* data, uint64 length, uint64 track_number,
uint64 timecode, // timecode units (absolute)
bool is_key);
// Adds a frame to be output in the file. The frame is written out through
// |writer_| if successful. Returns true on success.
// Inputs:
// frame: Pointer to the data
// data: Pointer to the data
// length: Length of the data
// additional: Pointer to the additional data
// additional_length: Length of the additional data
@@ -701,19 +892,30 @@ class Cluster {
// abs_timecode: Absolute (not relative to cluster) timestamp of the
// frame, expressed in timecode units.
// is_key: Flag telling whether or not this frame is a key frame.
bool AddFrameWithAdditional(const uint8* frame,
uint64 length,
const uint8* additional,
uint64 additional_length,
uint64 add_id,
uint64 track_number,
uint64 abs_timecode,
bool is_key);
bool AddFrameWithAdditional(const uint8* data, uint64 length,
const uint8* additional, uint64 additional_length,
uint64 add_id, uint64 track_number,
uint64 abs_timecode, bool is_key);
// Adds a frame to be output in the file. The frame is written out through
// |writer_| if successful. Returns true on success.
// Inputs:
// data: Pointer to the data.
// length: Length of the data.
// discard_padding: DiscardPadding element value.
// track_number: Track to add the data to. Value returned by Add track
// functions. The range of allowed values is [1, 126].
// abs_timecode: Absolute (not relative to cluster) timestamp of the
// frame, expressed in timecode units.
// is_key: Flag telling whether or not this frame is a key frame.
bool AddFrameWithDiscardPadding(const uint8* data, uint64 length,
int64 discard_padding, uint64 track_number,
uint64 abs_timecode, bool is_key);
// Writes a frame of metadata to the output medium; returns true on
// success.
// Inputs:
// frame: Pointer to the data
// data: Pointer to the data
// length: Length of the data
// track_number: Track to add the data to. Value returned by Add track
// functions. The range of allowed values is [1, 126].
@@ -724,11 +926,8 @@ class Cluster {
// The metadata frame is written as a block group, with a duration
// sub-element but no reference time sub-elements (indicating that
// it is considered a keyframe, per Matroska semantics).
bool AddMetadata(const uint8* frame,
uint64 length,
uint64 track_number,
uint64 timecode, // timecode units (absolute)
uint64 duration); // timecode units
bool AddMetadata(const uint8* data, uint64 length, uint64 track_number,
uint64 timecode, uint64 duration);
// Increments the size of the cluster's data in bytes.
void AddPayloadSize(uint64 size);
@@ -740,52 +939,29 @@ class Cluster {
// Returns the size in bytes for the entire Cluster element.
uint64 Size() const;
// Given |abs_timecode|, calculates timecode relative to most recent timecode.
// Returns -1 on failure, or a relative timecode.
int64 GetRelativeTimecode(int64 abs_timecode) const;
int64 size_position() const { return size_position_; }
int32 blocks_added() const { return blocks_added_; }
uint64 payload_size() const { return payload_size_; }
int64 position_for_cues() const { return position_for_cues_; }
uint64 timecode() const { return timecode_; }
uint64 timecode_scale() const { return timecode_scale_; }
private:
// Signature that matches either of WriteSimpleBlock or WriteMetadataBlock
// in the muxer utilities package.
typedef uint64 (*WriteBlock)(IMkvWriter* writer,
const uint8* data,
uint64 length,
uint64 track_number,
int64 timecode,
uint64 generic_arg);
// Utility method that confirms that blocks can still be added, and that the
// cluster header has been written. Used by |DoWriteFrame*|. Returns true
// when successful.
bool PreWriteBlock();
// Signature that matches WriteBlockWithAdditional
// in the muxer utilities package.
typedef uint64 (*WriteBlockAdditional)(IMkvWriter* writer,
const uint8* data,
uint64 length,
const uint8* additional,
uint64 add_id,
uint64 additional_length,
uint64 track_number,
int64 timecode,
uint64 is_key);
// Utility method used by the |DoWriteFrame*| methods that handles the book
// keeping required after each block is written.
void PostWriteBlock(uint64 element_size);
// Used to implement AddFrame and AddMetadata.
bool DoWriteBlock(const uint8* frame,
uint64 length,
uint64 track_number,
uint64 absolute_timecode,
uint64 generic_arg,
WriteBlock write_block);
// Used to implement AddFrameWithAdditional
bool DoWriteBlockWithAdditional(const uint8* frame,
uint64 length,
const uint8* additional,
uint64 additional_length,
uint64 add_id,
uint64 track_number,
uint64 absolute_timecode,
uint64 generic_arg,
WriteBlockAdditional write_block);
// Does some verification and calls WriteFrame.
bool DoWriteFrame(const Frame* const frame);
// Outputs the Cluster header to |writer_|. Returns true on success.
bool WriteClusterHeader();
@@ -811,6 +987,9 @@ class Cluster {
// The absolute timecode of the cluster.
const uint64 timecode_;
// The timecode scale of the Segment containing the cluster.
const uint64 timecode_scale_;
// Pointer to the writer object. Not owned by this class.
IMkvWriter* writer_;
@@ -895,6 +1074,8 @@ class SegmentInfo {
uint64 timecode_scale() const { return timecode_scale_; }
void set_writing_app(const char* app);
const char* writing_app() const { return writing_app_; }
void set_date_utc(int64 date_utc) { date_utc_ = date_utc; }
int64 date_utc() const { return date_utc_; }
private:
// Segment Information element names.
@@ -906,6 +1087,8 @@ class SegmentInfo {
uint64 timecode_scale_;
// Initially set to libwebm-%d.%d.%d.%d, major, minor, build, revision.
char* writing_app_;
// LLONG_MIN when DateUTC is not set.
int64 date_utc_;
// The file position of the duration element.
int64 duration_pos_;
@@ -921,16 +1104,14 @@ class SegmentInfo {
// |Init| must be called before any other method in this class.
class Segment {
public:
enum Mode {
kLive = 0x1,
kFile = 0x2
};
enum Mode { kLive = 0x1, kFile = 0x2 };
enum CuesPosition {
kAfterClusters = 0x0, // Position Cues after Clusters - Default
kBeforeClusters = 0x1 // Position Cues before Clusters
};
const static uint32 kDefaultDocTypeVersion = 2;
const static uint64 kDefaultMaxClusterDuration = 30000000000ULL;
Segment();
@@ -947,8 +1128,8 @@ class Segment {
// track number.
Track* AddTrack(int32 number);
// Adds an audio track to the segment. Returns the number of the track on
// success, 0 on error. |number| is the number to use for the audio track.
// Adds a Vorbis audio track to the segment. Returns the number of the track
// on success, 0 on error. |number| is the number to use for the audio track.
// |number| must be >= 0. If |number| == 0 then the muxer will decide on
// the track number.
uint64 AddAudioTrack(int32 sample_rate, int32 channels, int32 number);
@@ -958,6 +1139,11 @@ class Segment {
// populate its fields via the Chapter member functions.
Chapter* AddChapter();
// Adds an empty tag to the tags of this segment. Returns
// non-NULL on success. After adding the tag, the caller should
// populate its fields via the Tag member functions.
Tag* AddTag();
// Adds a cue point to the Cues element. |timestamp| is the time in
// nanoseconds of the cue's time. |track| is the Track of the Cue. This
// function must be called after AddFrame to calculate the correct
@@ -966,22 +1152,19 @@ class Segment {
// Adds a frame to be output in the file. Returns true on success.
// Inputs:
// frame: Pointer to the data
// data: Pointer to the data
// length: Length of the data
// track_number: Track to add the data to. Value returned by Add track
// functions.
// timestamp: Timestamp of the frame in nanoseconds from 0.
// is_key: Flag telling whether or not this frame is a key frame.
bool AddFrame(const uint8* frame,
uint64 length,
uint64 track_number,
uint64 timestamp_ns,
bool is_key);
bool AddFrame(const uint8* data, uint64 length, uint64 track_number,
uint64 timestamp_ns, bool is_key);
// Writes a frame of metadata to the output medium; returns true on
// success.
// Inputs:
// frame: Pointer to the data
// data: Pointer to the data
// length: Length of the data
// track_number: Track to add the data to. Value returned by Add track
// functions.
@@ -992,22 +1175,49 @@ class Segment {
// The metadata frame is written as a block group, with a duration
// sub-element but no reference time sub-elements (indicating that
// it is considered a keyframe, per Matroska semantics).
bool AddMetadata(const uint8* frame,
uint64 length,
uint64 track_number,
uint64 timestamp_ns,
uint64 duration_ns);
bool AddMetadata(const uint8* data, uint64 length, uint64 track_number,
uint64 timestamp_ns, uint64 duration_ns);
bool AddFrameWithAdditional(const uint8* frame,
uint64 length,
const uint8* additional,
uint64 additional_length,
uint64 add_id,
uint64 track_number,
uint64 timestamp,
bool is_key);
// Writes a frame with additional data to the output medium; returns true on
// success.
// Inputs:
// data: Pointer to the data.
// length: Length of the data.
// additional: Pointer to additional data.
// additional_length: Length of additional data.
// add_id: Additional ID which identifies the type of additional data.
// track_number: Track to add the data to. Value returned by Add track
// functions.
// timestamp: Absolute timestamp of the frame, expressed in nanosecond
// units.
// is_key: Flag telling whether or not this frame is a key frame.
bool AddFrameWithAdditional(const uint8* data, uint64 length,
const uint8* additional, uint64 additional_length,
uint64 add_id, uint64 track_number,
uint64 timestamp, bool is_key);
// Adds a video track to the segment. Returns the number of the track on
// Writes a frame with DiscardPadding to the output medium; returns true on
// success.
// Inputs:
// data: Pointer to the data.
// length: Length of the data.
// discard_padding: DiscardPadding element value.
// track_number: Track to add the data to. Value returned by Add track
// functions.
// timestamp: Absolute timestamp of the frame, expressed in nanosecond
// units.
// is_key: Flag telling whether or not this frame is a key frame.
bool AddFrameWithDiscardPadding(const uint8* data, uint64 length,
int64 discard_padding, uint64 track_number,
uint64 timestamp, bool is_key);
// Writes a Frame to the output medium. Chooses the correct way of writing
// the frame (Block vs SimpleBlock) based on the parameters passed.
// Inputs:
// frame: frame object
bool AddGenericFrame(const Frame* frame);
// Adds a VP8 video track to the segment. Returns the number of the track on
// success, 0 on error. |number| is the number to use for the video track.
// |number| must be >= 0. If |number| == 0 then the muxer will decide on
// the track number.
@@ -1088,6 +1298,9 @@ class Segment {
// Cues elements.
bool CheckHeaderInfo();
// Sets |doc_type_version_| based on the current element requirements.
void UpdateDocTypeVersion();
// Sets |name| according to how many chunks have been written. |ext| is the
// file extension. |name| must be deleted by the calling app. Returns true
// on success.
@@ -1133,7 +1346,6 @@ class Segment {
// was necessary but creation was not successful.
bool DoNewClusterProcessing(uint64 track_num, uint64 timestamp_ns, bool key);
// Adjusts Cue Point values (to place Cues before Clusters) so that they
// reflect the correct offsets.
void MoveCuesBeforeClusters();
@@ -1145,7 +1357,7 @@ class Segment {
// diff - indicates the difference in size of the Cues element that needs to
// accounted for.
// index - index in the list of Cues which is currently being adjusted.
// cue_size - size of the Cues element.
// cue_size - sum of size of all the CuePoint elements.
void MoveCuesBeforeClustersHelper(uint64 diff, int index, uint64* cue_size);
// Seeds the random number generator used to make UIDs.
@@ -1157,6 +1369,7 @@ class Segment {
SegmentInfo segment_info_;
Tracks tracks_;
Chapters chapters_;
Tags tags_;
// Number of chunks written.
int chunk_count_;
@@ -1222,9 +1435,15 @@ class Segment {
// Flag telling if the segment's header has been written.
bool header_written_;
// Duration of the last block in nanoseconds.
uint64 last_block_duration_;
// Last timestamp in nanoseconds added to a cluster.
uint64 last_timestamp_;
// Last timestamp in nanoseconds by track number added to a cluster.
uint64 last_track_timestamp_[kMaxTrackNumber];
// Maximum time in nanoseconds for a cluster duration. This variable is a
// guideline and some clusters may have a longer duration. Default is 30
// seconds.
@@ -1246,12 +1465,23 @@ class Segment {
// Flag whether or not the muxer should output a Cues element.
bool output_cues_;
// The size of the EBML header, used to validate the header if
// WriteEbmlHeader() is called more than once.
int32 ebml_header_size_;
// The file position of the segment's payload.
int64 payload_pos_;
// The file position of the element's size.
int64 size_position_;
// Current DocTypeVersion (|doc_type_version_|) and that written in
// WriteSegmentHeader().
// WriteEbmlHeader() will be called from Finalize() if |doc_type_version_|
// differs from |doc_type_version_written_|.
uint32 doc_type_version_;
uint32 doc_type_version_written_;
// Pointer to the writer objects. Not owned by this class.
IMkvWriter* writer_cluster_;
IMkvWriter* writer_cues_;
@@ -1260,6 +1490,6 @@ class Segment {
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Segment);
};
} //end namespace mkvmuxer
} // end namespace mkvmuxer
#endif //MKVMUXER_HPP
#endif // MKVMUXER_HPP

View File

@@ -1,30 +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
// 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

View File

@@ -12,22 +12,169 @@
#include <fcntl.h>
#endif
#include <cassert>
#include <cmath>
#include <cstdio>
#ifdef _WIN32
#define _CRT_RAND_S
#endif
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <new>
#include "mkvwriter.hpp"
#include "webmids.hpp"
#ifdef _MSC_VER
// Disable MSVC warnings that suggest making code non-portable.
#pragma warning(disable : 4996)
#endif
namespace mkvmuxer {
namespace {
// Date elements are always 8 octets in size.
const int kDateElementSize = 8;
uint64 WriteBlock(IMkvWriter* writer, const Frame* const frame, int64 timecode,
uint64 timecode_scale) {
uint64 block_additional_elem_size = 0;
uint64 block_addid_elem_size = 0;
uint64 block_more_payload_size = 0;
uint64 block_more_elem_size = 0;
uint64 block_additions_payload_size = 0;
uint64 block_additions_elem_size = 0;
if (frame->additional()) {
block_additional_elem_size = EbmlElementSize(
kMkvBlockAdditional, frame->additional(), frame->additional_length());
block_addid_elem_size = EbmlElementSize(kMkvBlockAddID, frame->add_id());
block_more_payload_size =
block_addid_elem_size + block_additional_elem_size;
block_more_elem_size =
EbmlMasterElementSize(kMkvBlockMore, block_more_payload_size) +
block_more_payload_size;
block_additions_payload_size = block_more_elem_size;
block_additions_elem_size =
EbmlMasterElementSize(kMkvBlockAdditions,
block_additions_payload_size) +
block_additions_payload_size;
}
uint64 discard_padding_elem_size = 0;
if (frame->discard_padding() != 0) {
discard_padding_elem_size =
EbmlElementSize(kMkvDiscardPadding, frame->discard_padding());
}
const uint64 reference_block_timestamp =
frame->reference_block_timestamp() / timecode_scale;
uint64 reference_block_elem_size = 0;
if (!frame->is_key()) {
reference_block_elem_size =
EbmlElementSize(kMkvReferenceBlock, reference_block_timestamp);
}
const uint64 duration = frame->duration() / timecode_scale;
uint64 block_duration_elem_size = 0;
if (duration > 0)
block_duration_elem_size = EbmlElementSize(kMkvBlockDuration, duration);
const uint64 block_payload_size = 4 + frame->length();
const uint64 block_elem_size =
EbmlMasterElementSize(kMkvBlock, block_payload_size) + block_payload_size;
const uint64 block_group_payload_size =
block_elem_size + block_additions_elem_size + block_duration_elem_size +
discard_padding_elem_size + reference_block_elem_size;
if (!WriteEbmlMasterElement(writer, kMkvBlockGroup,
block_group_payload_size)) {
return 0;
}
if (!WriteEbmlMasterElement(writer, kMkvBlock, block_payload_size))
return 0;
if (WriteUInt(writer, frame->track_number()))
return 0;
if (SerializeInt(writer, timecode, 2))
return 0;
// For a Block, flags is always 0.
if (SerializeInt(writer, 0, 1))
return 0;
if (writer->Write(frame->frame(), static_cast<uint32>(frame->length())))
return 0;
if (frame->additional()) {
if (!WriteEbmlMasterElement(writer, kMkvBlockAdditions,
block_additions_payload_size)) {
return 0;
}
if (!WriteEbmlMasterElement(writer, kMkvBlockMore, block_more_payload_size))
return 0;
if (!WriteEbmlElement(writer, kMkvBlockAddID, frame->add_id()))
return 0;
if (!WriteEbmlElement(writer, kMkvBlockAdditional, frame->additional(),
frame->additional_length())) {
return 0;
}
}
if (frame->discard_padding() != 0 &&
!WriteEbmlElement(writer, kMkvDiscardPadding, frame->discard_padding())) {
return false;
}
if (!frame->is_key() &&
!WriteEbmlElement(writer, kMkvReferenceBlock,
reference_block_timestamp)) {
return false;
}
if (duration > 0 && !WriteEbmlElement(writer, kMkvBlockDuration, duration)) {
return false;
}
return EbmlMasterElementSize(kMkvBlockGroup, block_group_payload_size) +
block_group_payload_size;
}
uint64 WriteSimpleBlock(IMkvWriter* writer, const Frame* const frame,
int64 timecode) {
if (WriteID(writer, kMkvSimpleBlock))
return 0;
const int32 size = static_cast<int32>(frame->length()) + 4;
if (WriteUInt(writer, size))
return 0;
if (WriteUInt(writer, static_cast<uint64>(frame->track_number())))
return 0;
if (SerializeInt(writer, timecode, 2))
return 0;
uint64 flags = 0;
if (frame->is_key())
flags |= 0x80;
if (SerializeInt(writer, flags, 1))
return 0;
if (writer->Write(frame->frame(), static_cast<uint32>(frame->length())))
return 0;
return GetUIntSize(kMkvSimpleBlock) + GetCodedUIntSize(size) + 4 +
frame->length();
}
} // namespace
int32 GetCodedUIntSize(uint64 value) {
if (value < 0x000000000000007FULL)
return 1;
@@ -64,6 +211,13 @@ int32 GetUIntSize(uint64 value) {
return 8;
}
int32 GetIntSize(int64 value) {
// Doubling the requested value ensures positive values with their high bit
// set are written with 0-padding to avoid flipping the signedness.
const uint64 v = (value < 0) ? value ^ -1LL : value;
return GetUIntSize(2 * v);
}
uint64 EbmlMasterElementSize(uint64 type, uint64 value) {
// Size of EBML ID
int32 ebml_size = GetUIntSize(type);
@@ -74,6 +228,19 @@ uint64 EbmlMasterElementSize(uint64 type, uint64 value) {
return ebml_size;
}
uint64 EbmlElementSize(uint64 type, int64 value) {
// Size of EBML ID
int32 ebml_size = GetUIntSize(type);
// Datasize
ebml_size += GetIntSize(value);
// Size of Datasize
ebml_size++;
return ebml_size;
}
uint64 EbmlElementSize(uint64 type, uint64 value) {
// Size of EBML ID
int32 ebml_size = GetUIntSize(type);
@@ -87,7 +254,7 @@ uint64 EbmlElementSize(uint64 type, uint64 value) {
return ebml_size;
}
uint64 EbmlElementSize(uint64 type, float /* value */ ) {
uint64 EbmlElementSize(uint64 type, float /* value */) {
// Size of EBML ID
uint64 ebml_size = GetUIntSize(type);
@@ -132,6 +299,19 @@ uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size) {
return ebml_size;
}
uint64 EbmlDateElementSize(uint64 type) {
// Size of EBML ID
uint64 ebml_size = GetUIntSize(type);
// Datasize
ebml_size += kDateElementSize;
// Size of Datasize
ebml_size++;
return ebml_size;
}
int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size) {
if (!writer || size < 1 || size > 8)
return -1;
@@ -156,16 +336,22 @@ int32 SerializeFloat(IMkvWriter* writer, float f) {
if (!writer)
return -1;
const uint32& val = reinterpret_cast<const uint32&>(f);
assert(sizeof(uint32) == sizeof(float));
// This union is merely used to avoid a reinterpret_cast from float& to
// uint32& which will result in violation of strict aliasing.
union U32 {
uint32 u32;
float f;
} value;
value.f = f;
for (int32 i = 1; i <= 4; ++i) {
const int32 byte_count = 4 - i;
const int32 bit_count = byte_count * 8;
const uint32 bb = val >> bit_count;
const uint8 b = static_cast<uint8>(bb);
const uint8 byte = static_cast<uint8>(value.u32 >> bit_count);
const int32 status = writer->Write(&b, 1);
const int32 status = writer->Write(&byte, 1);
if (status < 0)
return status;
@@ -258,6 +444,23 @@ bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value) {
return true;
}
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, int64 value) {
if (!writer)
return false;
if (WriteID(writer, type))
return 0;
const uint64 size = GetIntSize(value);
if (WriteUInt(writer, size))
return false;
if (SerializeInt(writer, value, static_cast<int32>(size)))
return false;
return true;
}
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value) {
if (!writer)
return false;
@@ -281,19 +484,17 @@ bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value) {
if (WriteID(writer, type))
return false;
const int32 length = strlen(value);
const uint64 length = strlen(value);
if (WriteUInt(writer, length))
return false;
if (writer->Write(value, length))
if (writer->Write(value, static_cast<const uint32>(length)))
return false;
return true;
}
bool WriteEbmlElement(IMkvWriter* writer,
uint64 type,
const uint8* value,
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const uint8* value,
uint64 size) {
if (!writer || !value || size < 1)
return false;
@@ -310,247 +511,41 @@ bool WriteEbmlElement(IMkvWriter* writer,
return true;
}
uint64 WriteSimpleBlock(IMkvWriter* writer,
const uint8* data,
uint64 length,
uint64 track_number,
int64 timecode,
uint64 is_key) {
bool WriteEbmlDateElement(IMkvWriter* writer, uint64 type, int64 value) {
if (!writer)
return false;
if (!data || length < 1)
if (WriteID(writer, type))
return false;
// Here we only permit track number values to be no greater than
// 126, which the largest value we can store having a Matroska
// integer representation of only 1 byte.
if (track_number < 1 || track_number > 126)
if (WriteUInt(writer, kDateElementSize))
return false;
// Technically the timestamp for a block can be less than the
// timestamp for the cluster itself (remember that block timestamp
if (SerializeInt(writer, value, kDateElementSize))
return false;
return true;
}
uint64 WriteFrame(IMkvWriter* writer, const Frame* const frame,
Cluster* cluster) {
if (!writer || !frame || !frame->IsValid() || !cluster ||
!cluster->timecode_scale())
return 0;
// Technically the timecode for a block can be less than the
// timecode for the cluster itself (remember that block timecode
// is a signed, 16-bit integer). However, as a simplification we
// only permit non-negative cluster-relative timestamps for blocks.
if (timecode < 0 || timecode > kMaxBlockTimecode)
return false;
if (WriteID(writer, kMkvSimpleBlock))
// only permit non-negative cluster-relative timecodes for blocks.
const int64 relative_timecode = cluster->GetRelativeTimecode(
frame->timestamp() / cluster->timecode_scale());
if (relative_timecode < 0 || relative_timecode > kMaxBlockTimecode)
return 0;
const int32 size = static_cast<int32>(length) + 4;
if (WriteUInt(writer, size))
return 0;
if (WriteUInt(writer, static_cast<uint64>(track_number)))
return 0;
if (SerializeInt(writer, timecode, 2))
return 0;
uint64 flags = 0;
if (is_key)
flags |= 0x80;
if (SerializeInt(writer, flags, 1))
return 0;
if (writer->Write(data, static_cast<uint32>(length)))
return 0;
const uint64 element_size =
GetUIntSize(kMkvSimpleBlock) + GetCodedUIntSize(size) + 4 + length;
return element_size;
}
// We must write the metadata (key)frame as a BlockGroup element,
// because we need to specify a duration for the frame. The
// BlockGroup element comprises the frame itself and its duration,
// and is laid out as follows:
//
// BlockGroup tag
// BlockGroup size
// Block tag
// Block size
// (the frame is the block payload)
// Duration tag
// Duration size
// (duration payload)
//
uint64 WriteMetadataBlock(IMkvWriter* writer,
const uint8* data,
uint64 length,
uint64 track_number,
int64 timecode,
uint64 duration) {
// We don't backtrack when writing to the stream, so we must
// pre-compute the BlockGroup size, by summing the sizes of each
// sub-element (the block and the duration).
// We use a single byte for the track number of the block, which
// means the block header is exactly 4 bytes.
// TODO(matthewjheaney): use EbmlMasterElementSize and WriteEbmlMasterElement
const uint64 block_payload_size = 4 + length;
const int32 block_size = GetCodedUIntSize(block_payload_size);
const uint64 block_elem_size = 1 + block_size + block_payload_size;
const int32 duration_payload_size = GetUIntSize(duration);
const int32 duration_size = GetCodedUIntSize(duration_payload_size);
const uint64 duration_elem_size = 1 + duration_size + duration_payload_size;
const uint64 blockg_payload_size = block_elem_size + duration_elem_size;
const int32 blockg_size = GetCodedUIntSize(blockg_payload_size);
const uint64 blockg_elem_size = 1 + blockg_size + blockg_payload_size;
if (WriteID(writer, kMkvBlockGroup)) // 1-byte ID size
return 0;
if (WriteUInt(writer, blockg_payload_size))
return 0;
// Write Block element
if (WriteID(writer, kMkvBlock)) // 1-byte ID size
return 0;
if (WriteUInt(writer, block_payload_size))
return 0;
// Byte 1 of 4
if (WriteUInt(writer, track_number))
return 0;
// Bytes 2 & 3 of 4
if (SerializeInt(writer, timecode, 2))
return 0;
// Byte 4 of 4
const uint64 flags = 0;
if (SerializeInt(writer, flags, 1))
return 0;
// Now write the actual frame (of metadata)
if (writer->Write(data, static_cast<uint32>(length)))
return 0;
// Write Duration element
if (WriteID(writer, kMkvBlockDuration)) // 1-byte ID size
return 0;
if (WriteUInt(writer, duration_payload_size))
return 0;
if (SerializeInt(writer, duration, duration_payload_size))
return 0;
// Note that we don't write a reference time as part of the block
// group; no reference time(s) indicates that this block is a
// keyframe. (Unlike the case for a SimpleBlock element, the header
// bits of the Block sub-element of a BlockGroup element do not
// indicate keyframe status. The keyframe status is inferred from
// the absence of reference time sub-elements.)
return blockg_elem_size;
}
// Writes a WebM Block with Additional. The structure is as follows
// Indentation shows sub-levels
// BlockGroup
// Block
// Data
// BlockAdditions
// BlockMore
// BlockAddID
// 1 (Denotes Alpha)
// BlockAdditional
// Data
uint64 WriteBlockWithAdditional(IMkvWriter* writer,
const uint8* data,
uint64 length,
const uint8* additional,
uint64 additional_length,
uint64 add_id,
uint64 track_number,
int64 timecode,
uint64 is_key) {
if (!data || !additional || length < 1 || additional_length < 1)
return 0;
const uint64 block_payload_size = 4 + length;
const uint64 block_elem_size = EbmlMasterElementSize(kMkvBlock,
block_payload_size) +
block_payload_size;
const uint64 block_additional_elem_size = EbmlElementSize(kMkvBlockAdditional,
additional,
additional_length);
const uint64 block_addid_elem_size = EbmlElementSize(kMkvBlockAddID, add_id);
const uint64 block_more_payload_size = block_addid_elem_size +
block_additional_elem_size;
const uint64 block_more_elem_size = EbmlMasterElementSize(
kMkvBlockMore,
block_more_payload_size) +
block_more_payload_size;
const uint64 block_additions_payload_size = block_more_elem_size;
const uint64 block_additions_elem_size = EbmlMasterElementSize(
kMkvBlockAdditions,
block_additions_payload_size) +
block_additions_payload_size;
const uint64 block_group_payload_size = block_elem_size +
block_additions_elem_size;
const uint64 block_group_elem_size = EbmlMasterElementSize(
kMkvBlockGroup,
block_group_payload_size) +
block_group_payload_size;
if (!WriteEbmlMasterElement(writer, kMkvBlockGroup,
block_group_payload_size))
return 0;
if (!WriteEbmlMasterElement(writer, kMkvBlock, block_payload_size))
return 0;
if (WriteUInt(writer, track_number))
return 0;
if (SerializeInt(writer, timecode, 2))
return 0;
uint64 flags = 0;
if (is_key)
flags |= 0x80;
if (SerializeInt(writer, flags, 1))
return 0;
if (writer->Write(data, static_cast<uint32>(length)))
return 0;
if (!WriteEbmlMasterElement(writer, kMkvBlockAdditions,
block_additions_payload_size))
return 0;
if (!WriteEbmlMasterElement(writer, kMkvBlockMore, block_more_payload_size))
return 0;
if (!WriteEbmlElement(writer, kMkvBlockAddID, add_id))
return 0;
if (!WriteEbmlElement(writer, kMkvBlockAdditional,
additional, additional_length))
return 0;
return block_group_elem_size;
return frame->CanBeSimpleBlock() ?
WriteSimpleBlock(writer, frame, relative_timecode) :
WriteBlock(writer, frame, relative_timecode,
cluster->timecode_scale());
}
uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
@@ -558,9 +553,9 @@ uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
return false;
// Subtract one for the void ID and the coded size.
uint64 void_entry_size = size - 1 - GetCodedUIntSize(size-1);
uint64 void_size = EbmlMasterElementSize(kMkvVoid, void_entry_size) +
void_entry_size;
uint64 void_entry_size = size - 1 - GetCodedUIntSize(size - 1);
uint64 void_size =
EbmlMasterElementSize(kMkvVoid, void_entry_size) + void_entry_size;
if (void_size != size)
return 0;
@@ -600,16 +595,18 @@ void GetVersion(int32* major, int32* minor, int32* build, int32* revision) {
mkvmuxer::uint64 mkvmuxer::MakeUID(unsigned int* seed) {
uint64 uid = 0;
#ifdef __MINGW32__
srand(*seed);
#endif
for (int i = 0; i < 7; ++i) { // avoid problems with 8-byte values
uid <<= 8;
// TODO(fgalligan): Move random number generation to platform specific code.
#ifdef _WIN32
// TODO(fgalligan): Move random number generation to platform specific code.
#ifdef _MSC_VER
(void)seed;
unsigned int random_value;
const errno_t e = rand_s(&random_value);
(void)e;
const int32 nn = random_value;
const int32 nn = rand();
#elif __ANDROID__
int32 temp_num = 1;
int fd = open("/dev/urandom", O_RDONLY);
@@ -618,6 +615,8 @@ mkvmuxer::uint64 mkvmuxer::MakeUID(unsigned int* seed) {
close(fd);
}
const int32 nn = temp_num;
#elif defined __MINGW32__
const int32 nn = rand();
#else
const int32 nn = rand_r(seed);
#endif

View File

@@ -9,6 +9,7 @@
#ifndef MKVMUXERUTIL_HPP
#define MKVMUXERUTIL_HPP
#include "mkvmuxer.hpp"
#include "mkvmuxertypes.hpp"
namespace mkvmuxer {
@@ -23,12 +24,15 @@ int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size);
// Returns the size in bytes of the element.
int32 GetUIntSize(uint64 value);
int32 GetIntSize(int64 value);
int32 GetCodedUIntSize(uint64 value);
uint64 EbmlMasterElementSize(uint64 type, uint64 value);
uint64 EbmlElementSize(uint64 type, int64 value);
uint64 EbmlElementSize(uint64 type, uint64 value);
uint64 EbmlElementSize(uint64 type, float value);
uint64 EbmlElementSize(uint64 type, const char* value);
uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size);
uint64 EbmlDateElementSize(uint64 type);
// Creates an EBML coded number from |value| and writes it out. The size of
// the coded number is determined by the value of |value|. |value| must not
@@ -49,69 +53,17 @@ int32 WriteID(IMkvWriter* writer, uint64 type);
// Output an Mkv non-master element. Returns true if the element was written.
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value);
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, int64 value);
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value);
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value);
bool WriteEbmlElement(IMkvWriter* writer,
uint64 type,
const uint8* value,
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const uint8* value,
uint64 size);
bool WriteEbmlDateElement(IMkvWriter* writer, uint64 type, int64 value);
// Output an Mkv Simple Block.
// Inputs:
// data: Pointer to the data.
// length: Length of the data.
// track_number: Track to add the data to. Value returned by Add track
// functions. Only values in the range [1, 126] are
// permitted.
// timecode: Relative timecode of the Block. Only values in the
// range [0, 2^15) are permitted.
// is_key: Non-zero value specifies that frame is a key frame.
uint64 WriteSimpleBlock(IMkvWriter* writer,
const uint8* data,
uint64 length,
uint64 track_number,
int64 timecode,
uint64 is_key);
// Output a metadata keyframe, using a Block Group element.
// Inputs:
// data: Pointer to the (meta)data.
// length: Length of the (meta)data.
// track_number: Track to add the data to. Value returned by Add track
// functions. Only values in the range [1, 126] are
// permitted.
// timecode Timecode of frame, relative to cluster timecode. Only
// values in the range [0, 2^15) are permitted.
// duration_timecode Duration of frame, using timecode units.
uint64 WriteMetadataBlock(IMkvWriter* writer,
const uint8* data,
uint64 length,
uint64 track_number,
int64 timecode,
uint64 duration_timecode);
// Output an Mkv Block with BlockAdditional data.
// Inputs:
// data: Pointer to the data.
// length: Length of the data.
// additional: Pointer to the additional data
// additional_length: Length of the additional data.
// add_id: Value of BlockAddID element.
// track_number: Track to add the data to. Value returned by Add track
// functions. Only values in the range [1, 126] are
// permitted.
// timecode: Relative timecode of the Block. Only values in the
// range [0, 2^15) are permitted.
// is_key: Non-zero value specifies that frame is a key frame.
uint64 WriteBlockWithAdditional(IMkvWriter* writer,
const uint8* data,
uint64 length,
const uint8* additional,
uint64 additional_length,
uint64 add_id,
uint64 track_number,
int64 timecode,
uint64 is_key);
// Output a Mkv Frame. It decides the correct element to write (Block vs
// SimpleBlock) based on the parameters of the Frame.
uint64 WriteFrame(IMkvWriter* writer, const Frame* const frame,
Cluster* cluster);
// Output a void element. |size| must be the entire size in bytes that will be
// void. The function will calculate the size of the void header and subtract
@@ -126,6 +78,6 @@ void GetVersion(int32* major, int32* minor, int32* build, int32* revision);
// the random-number generator (see POSIX rand_r() for semantics).
uint64 MakeUID(unsigned int* seed);
} //end namespace mkvmuxer
} // end namespace mkvmuxer
#endif // MKVMUXERUTIL_HPP
#endif // MKVMUXERUTIL_HPP

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,128 +1,132 @@
// Copyright (c) 2010 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 "mkvreader.hpp"
#include <cassert>
namespace mkvparser
{
MkvReader::MkvReader() :
m_file(NULL)
{
}
MkvReader::~MkvReader()
{
Close();
}
int MkvReader::Open(const char* fileName)
{
if (fileName == NULL)
return -1;
if (m_file)
return -1;
#ifdef WIN32
const errno_t e = fopen_s(&m_file, fileName, "rb");
if (e)
return -1; //error
#else
m_file = fopen(fileName, "rb");
if (m_file == NULL)
return -1;
#endif
#ifdef WIN32
int status = _fseeki64(m_file, 0L, SEEK_END);
if (status)
return -1; //error
m_length = _ftelli64(m_file);
#else
fseek(m_file, 0L, SEEK_END);
m_length = ftell(m_file);
#endif
assert(m_length >= 0);
#ifdef WIN32
status = _fseeki64(m_file, 0L, SEEK_SET);
if (status)
return -1; //error
#else
fseek(m_file, 0L, SEEK_SET);
#endif
return 0;
}
void MkvReader::Close()
{
if (m_file != NULL)
{
fclose(m_file);
m_file = NULL;
}
}
int MkvReader::Length(long long* total, long long* available)
{
if (m_file == NULL)
return -1;
if (total)
*total = m_length;
if (available)
*available = m_length;
return 0;
}
int MkvReader::Read(long long offset, long len, unsigned char* buffer)
{
if (m_file == NULL)
return -1;
if (offset < 0)
return -1;
if (len < 0)
return -1;
if (len == 0)
return 0;
if (offset >= m_length)
return -1;
#ifdef WIN32
const int status = _fseeki64(m_file, offset, SEEK_SET);
if (status)
return -1; //error
#else
fseek(m_file, offset, SEEK_SET);
#endif
const size_t size = fread(buffer, 1, len, m_file);
if (size < size_t(len))
return -1; //error
return 0; //success
}
} //end namespace mkvparser
// Copyright (c) 2010 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 "mkvreader.hpp"
#include <cassert>
namespace mkvparser {
MkvReader::MkvReader() : m_file(NULL), reader_owns_file_(true) {}
MkvReader::MkvReader(FILE* fp) : m_file(fp), reader_owns_file_(false) {
GetFileSize();
}
MkvReader::~MkvReader() {
if (reader_owns_file_)
Close();
m_file = NULL;
}
int MkvReader::Open(const char* fileName) {
if (fileName == NULL)
return -1;
if (m_file)
return -1;
#ifdef _MSC_VER
const errno_t e = fopen_s(&m_file, fileName, "rb");
if (e)
return -1; // error
#else
m_file = fopen(fileName, "rb");
if (m_file == NULL)
return -1;
#endif
return !GetFileSize();
}
bool MkvReader::GetFileSize() {
if (m_file == NULL)
return false;
#ifdef _MSC_VER
int status = _fseeki64(m_file, 0L, SEEK_END);
if (status)
return false; // error
m_length = _ftelli64(m_file);
#else
fseek(m_file, 0L, SEEK_END);
m_length = ftell(m_file);
#endif
assert(m_length >= 0);
if (m_length < 0)
return false;
#ifdef _MSC_VER
status = _fseeki64(m_file, 0L, SEEK_SET);
if (status)
return false; // error
#else
fseek(m_file, 0L, SEEK_SET);
#endif
return true;
}
void MkvReader::Close() {
if (m_file != NULL) {
fclose(m_file);
m_file = NULL;
}
}
int MkvReader::Length(long long* total, long long* available) {
if (m_file == NULL)
return -1;
if (total)
*total = m_length;
if (available)
*available = m_length;
return 0;
}
int MkvReader::Read(long long offset, long len, unsigned char* buffer) {
if (m_file == NULL)
return -1;
if (offset < 0)
return -1;
if (len < 0)
return -1;
if (len == 0)
return 0;
if (offset >= m_length)
return -1;
#ifdef _MSC_VER
const int status = _fseeki64(m_file, offset, SEEK_SET);
if (status)
return -1; // error
#else
fseek(m_file, offset, SEEK_SET);
#endif
const size_t size = fread(buffer, 1, len, m_file);
if (size < size_t(len))
return -1; // error
return 0; // success
}
} // end namespace mkvparser

View File

@@ -1,38 +1,45 @@
// Copyright (c) 2010 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 MKVREADER_HPP
#define MKVREADER_HPP
#include "mkvparser.hpp"
#include <cstdio>
namespace mkvparser
{
class MkvReader : public IMkvReader
{
MkvReader(const MkvReader&);
MkvReader& operator=(const MkvReader&);
public:
MkvReader();
virtual ~MkvReader();
int Open(const char*);
void Close();
virtual int Read(long long position, long length, unsigned char* buffer);
virtual int Length(long long* total, long long* available);
private:
long long m_length;
FILE* m_file;
};
} //end namespace mkvparser
#endif //MKVREADER_HPP
// Copyright (c) 2010 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 MKVREADER_HPP
#define MKVREADER_HPP
#include "mkvparser.hpp"
#include <cstdio>
namespace mkvparser {
class MkvReader : public IMkvReader {
public:
MkvReader();
explicit MkvReader(FILE* fp);
virtual ~MkvReader();
int Open(const char*);
void Close();
virtual int Read(long long position, long length, unsigned char* buffer);
virtual int Length(long long* total, long long* available);
private:
MkvReader(const MkvReader&);
MkvReader& operator=(const MkvReader&);
// Determines the size of the file. This is called either by the constructor
// or by the Open function depending on file ownership. Returns true on
// success.
bool GetFileSize();
long long m_length;
FILE* m_file;
bool reader_owns_file_;
};
} // end namespace mkvparser
#endif // MKVREADER_HPP

View File

@@ -16,12 +16,11 @@
namespace mkvmuxer {
MkvWriter::MkvWriter() : file_(NULL) {
}
MkvWriter::MkvWriter() : file_(NULL), writer_owns_file_(true) {}
MkvWriter::~MkvWriter() {
Close();
}
MkvWriter::MkvWriter(FILE* fp) : file_(fp), writer_owns_file_(false) {}
MkvWriter::~MkvWriter() { Close(); }
int32 MkvWriter::Write(const void* buffer, uint32 length) {
if (!file_)
@@ -56,10 +55,10 @@ bool MkvWriter::Open(const char* filename) {
}
void MkvWriter::Close() {
if (file_) {
if (file_ && writer_owns_file_) {
fclose(file_);
file_ = NULL;
}
file_ = NULL;
}
int64 MkvWriter::Position() const {
@@ -67,9 +66,9 @@ int64 MkvWriter::Position() const {
return 0;
#ifdef _MSC_VER
return _ftelli64(file_);
return _ftelli64(file_);
#else
return ftell(file_);
return ftell(file_);
#endif
}
@@ -78,17 +77,14 @@ int32 MkvWriter::Position(int64 position) {
return -1;
#ifdef _MSC_VER
return _fseeki64(file_, position, SEEK_SET);
return _fseeki64(file_, position, SEEK_SET);
#else
return fseek(file_, position, SEEK_SET);
return fseek(file_, position, SEEK_SET);
#endif
}
bool MkvWriter::Seekable() const {
return true;
}
bool MkvWriter::Seekable() const { return true; }
void MkvWriter::ElementStartNotify(uint64, int64) {
}
void MkvWriter::ElementStartNotify(uint64, int64) {}
} // namespace mkvmuxer

View File

@@ -20,6 +20,7 @@ namespace mkvmuxer {
class MkvWriter : public IMkvWriter {
public:
MkvWriter();
explicit MkvWriter(FILE* fp);
virtual ~MkvWriter();
// IMkvWriter interface
@@ -40,10 +41,11 @@ class MkvWriter : public IMkvWriter {
private:
// File handle to output file.
FILE* file_;
bool writer_owns_file_;
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(MkvWriter);
};
} //end namespace mkvmuxer
} // end namespace mkvmuxer
#endif // MKVWRITER_HPP
#endif // MKVWRITER_HPP

View File

@@ -1,315 +1,366 @@
// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
//
// This sample application demonstrates how to use the matroska parser
// library, which allows clients to handle a matroska format file.
#include "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)
{
if (str == NULL)
return NULL;
//TODO: this probably requires that the locale be
//configured somehow:
const size_t size = mbstowcs(NULL, str, 0);
if (size == 0)
return NULL;
wchar_t* const val = new wchar_t[size+1];
mbstowcs(val, str, size);
val[size] = L'\0';
return val;
}
int main(int argc, char* argv[])
{
if (argc == 1)
{
printf("\t\t\tMkv Parser Sample Application\n");
printf("\t\t\tUsage: \n");
printf("\t\t\t ./sample [input file] \n");
printf("\t\t\t ./sample sample.mkv \n");
return -1;
}
using namespace mkvparser;
MkvReader reader;
if (reader.Open(argv[1]))
{
printf("\n Filename is invalid or error while opening.\n");
return -1;
}
int maj, min, build, rev;
GetVersion(maj, min, build, rev);
printf("\t\t libmkv verison: %d.%d.%d.%d\n", maj, min, build, rev);
long long pos = 0;
EBMLHeader ebmlHeader;
ebmlHeader.Parse(&reader, pos);
printf("\t\t\t EBML Header\n");
printf("\t\tEBML Version\t\t: %lld\n", ebmlHeader.m_version);
printf("\t\tEBML MaxIDLength\t: %lld\n", ebmlHeader.m_maxIdLength);
printf("\t\tEBML MaxSizeLength\t: %lld\n", ebmlHeader.m_maxSizeLength);
printf("\t\tDoc Type\t\t: %s\n", ebmlHeader.m_docType);
printf("\t\tPos\t\t\t: %lld\n", pos);
typedef mkvparser::Segment seg_t;
seg_t* 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)
{
printf("\n Segment::Load() failed.");
return -1;
}
const SegmentInfo* const pSegmentInfo = pSegment->GetInfo();
const long long timeCodeScale = pSegmentInfo->GetTimeCodeScale();
const long long duration_ns = pSegmentInfo->GetDuration();
const char* const pTitle_ = pSegmentInfo->GetTitleAsUTF8();
const wchar_t* const pTitle = utf8towcs(pTitle_);
const char* const pMuxingApp_ = pSegmentInfo->GetMuxingAppAsUTF8();
const wchar_t* const pMuxingApp = utf8towcs(pMuxingApp_);
const char* const pWritingApp_ = pSegmentInfo->GetWritingAppAsUTF8();
const wchar_t* const pWritingApp = utf8towcs(pWritingApp_);
printf("\n");
printf("\t\t\t Segment Info\n");
printf("\t\tTimeCodeScale\t\t: %lld \n", timeCodeScale);
printf("\t\tDuration\t\t: %lld\n", duration_ns);
const double duration_sec = double(duration_ns) / 1000000000;
printf("\t\tDuration(secs)\t\t: %7.3lf\n", duration_sec);
if (pTitle == NULL)
printf("\t\tTrack Name\t\t: NULL\n");
else
{
printf("\t\tTrack Name\t\t: %ls\n", pTitle);
delete [] pTitle;
}
if (pMuxingApp == NULL)
printf("\t\tMuxing App\t\t: NULL\n");
else
{
printf("\t\tMuxing App\t\t: %ls\n", pMuxingApp);
delete [] pMuxingApp;
}
if (pWritingApp == NULL)
printf("\t\tWriting App\t\t: NULL\n");
else
{
printf("\t\tWriting App\t\t: %ls\n", pWritingApp);
delete [] pWritingApp;
}
// pos of segment payload
printf("\t\tPosition(Segment)\t: %lld\n", pSegment->m_start);
// size of segment payload
printf("\t\tSize(Segment)\t\t: %lld\n", pSegment->m_size);
const mkvparser::Tracks* pTracks = pSegment->GetTracks();
unsigned long i = 0;
const unsigned long j = pTracks->GetTracksCount();
printf("\n\t\t\t Track Info\n");
while (i != j)
{
const Track* const pTrack = pTracks->GetTrackByIndex(i++);
if (pTrack == NULL)
continue;
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: %ld\n", trackType);
printf("\t\tTrack Number\t\t: %ld\n", trackNumber);
printf("\t\tTrack Uid\t\t: %lld\n", trackUid);
if (pTrackName == NULL)
printf("\t\tTrack Name\t\t: NULL\n");
else
{
printf("\t\tTrack Name\t\t: %ls \n", pTrackName);
delete [] pTrackName;
}
const char* const pCodecId = pTrack->GetCodecId();
if (pCodecId == NULL)
printf("\t\tCodec Id\t\t: NULL\n");
else
printf("\t\tCodec Id\t\t: %s\n", pCodecId);
const char* const pCodecName_ = pTrack->GetCodecNameAsUTF8();
const wchar_t* const pCodecName = utf8towcs(pCodecName_);
if (pCodecName == NULL)
printf("\t\tCodec Name\t\t: NULL\n");
else
{
printf("\t\tCodec Name\t\t: %ls\n", pCodecName);
delete [] pCodecName;
}
if (trackType == mkvparser::Track::kVideo)
{
const VideoTrack* const pVideoTrack =
static_cast<const VideoTrack*>(pTrack);
const long long width = pVideoTrack->GetWidth();
printf("\t\tVideo Width\t\t: %lld\n", width);
const long long height = pVideoTrack->GetHeight();
printf("\t\tVideo Height\t\t: %lld\n", height);
const double rate = pVideoTrack->GetFrameRate();
printf("\t\tVideo Rate\t\t: %f\n",rate);
}
if (trackType == mkvparser::Track::kAudio)
{
const AudioTrack* const pAudioTrack =
static_cast<const AudioTrack*>(pTrack);
const long long channels = pAudioTrack->GetChannels();
printf("\t\tAudio Channels\t\t: %lld\n", channels);
const long long bitDepth = pAudioTrack->GetBitDepth();
printf("\t\tAudio BitDepth\t\t: %lld\n", bitDepth);
const double sampleRate = pAudioTrack->GetSamplingRate();
printf("\t\tAddio Sample Rate\t: %.3f\n", sampleRate);
}
}
printf("\n\n\t\t\t Cluster Info\n");
const unsigned long clusterCount = pSegment->GetCount();
printf("\t\tCluster Count\t: %ld\n\n", clusterCount);
if (clusterCount == 0)
{
printf("\t\tSegment has no clusters.\n");
return -1;
}
const mkvparser::Cluster* pCluster = pSegment->GetFirst();
while ((pCluster != NULL) && !pCluster->EOS())
{
const long long timeCode = pCluster->GetTimeCode();
printf("\t\tCluster Time Code\t: %lld\n", timeCode);
const long long time_ns = pCluster->GetTime();
printf("\t\tCluster Time (ns)\t: %lld\n", time_ns);
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())
{
const Block* const pBlock = pBlockEntry->GetBlock();
const long long trackNum = pBlock->GetTrackNumber();
const unsigned long tn = static_cast<unsigned long>(trackNum);
const Track* const pTrack = pTracks->GetTrackByNumber(tn);
if (pTrack == NULL)
printf("\t\t\tBlock\t\t:UNKNOWN TRACK TYPE\n");
else
{
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);
}
}
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);
}
fflush(stdout);
return 0;
}
// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
//
// This sample application demonstrates how to use the Matroska parser
// library, which allows clients to handle a Matroska format file.
#include <memory>
#include "mkvreader.hpp"
#include "mkvparser.hpp"
#ifdef _MSC_VER
// Disable MSVC warnings that suggest making code non-portable.
#pragma warning(disable : 4996)
#endif
static const wchar_t* utf8towcs(const char* str) {
if (str == NULL)
return NULL;
// TODO: this probably requires that the locale be
// configured somehow:
const size_t size = mbstowcs(NULL, str, 0);
if (size == 0 || size == static_cast<size_t>(-1))
return NULL;
wchar_t* const val = new (std::nothrow) wchar_t[size + 1];
if (val == NULL)
return NULL;
mbstowcs(val, str, size);
val[size] = L'\0';
return val;
}
bool InputHasCues(const mkvparser::Segment* const segment) {
const mkvparser::Cues* const cues = segment->GetCues();
if (cues == NULL)
return false;
while (!cues->DoneParsing())
cues->LoadCuePoint();
const mkvparser::CuePoint* const cue_point = cues->GetFirst();
if (cue_point == NULL)
return false;
return true;
}
int main(int argc, char* argv[]) {
if (argc == 1) {
printf("\t\t\tMkv Parser Sample Application\n");
printf("\t\t\tUsage: \n");
printf("\t\t\t ./sample [input file] \n");
printf("\t\t\t ./sample sample.mkv \n");
return -1;
}
using namespace mkvparser;
MkvReader reader;
if (reader.Open(argv[1])) {
printf("\n Filename is invalid or error while opening.\n");
return -1;
}
int maj, min, build, rev;
GetVersion(maj, min, build, rev);
printf("\t\t libmkv verison: %d.%d.%d.%d\n", maj, min, build, rev);
long long pos = 0;
EBMLHeader ebmlHeader;
long long ret = ebmlHeader.Parse(&reader, pos);
if (ret < 0) {
printf("\n EBMLHeader::Parse() failed.");
return -1;
}
printf("\t\t\t EBML Header\n");
printf("\t\tEBML Version\t\t: %lld\n", ebmlHeader.m_version);
printf("\t\tEBML MaxIDLength\t: %lld\n", ebmlHeader.m_maxIdLength);
printf("\t\tEBML MaxSizeLength\t: %lld\n", ebmlHeader.m_maxSizeLength);
printf("\t\tDoc Type\t\t: %s\n", ebmlHeader.m_docType);
printf("\t\tPos\t\t\t: %lld\n", pos);
typedef mkvparser::Segment seg_t;
seg_t* pSegment_;
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) {
printf("\n Segment::Load() failed.");
return -1;
}
const SegmentInfo* const pSegmentInfo = pSegment->GetInfo();
if (pSegmentInfo == NULL) {
printf("\n Segment::GetInfo() failed.");
return -1;
}
const long long timeCodeScale = pSegmentInfo->GetTimeCodeScale();
const long long duration_ns = pSegmentInfo->GetDuration();
const char* const pTitle_ = pSegmentInfo->GetTitleAsUTF8();
const wchar_t* const pTitle = utf8towcs(pTitle_);
const char* const pMuxingApp_ = pSegmentInfo->GetMuxingAppAsUTF8();
const wchar_t* const pMuxingApp = utf8towcs(pMuxingApp_);
const char* const pWritingApp_ = pSegmentInfo->GetWritingAppAsUTF8();
const wchar_t* const pWritingApp = utf8towcs(pWritingApp_);
printf("\n");
printf("\t\t\t Segment Info\n");
printf("\t\tTimeCodeScale\t\t: %lld \n", timeCodeScale);
printf("\t\tDuration\t\t: %lld\n", duration_ns);
const double duration_sec = double(duration_ns) / 1000000000;
printf("\t\tDuration(secs)\t\t: %7.3lf\n", duration_sec);
if (pTitle == NULL)
printf("\t\tTrack Name\t\t: NULL\n");
else {
printf("\t\tTrack Name\t\t: %ls\n", pTitle);
delete[] pTitle;
}
if (pMuxingApp == NULL)
printf("\t\tMuxing App\t\t: NULL\n");
else {
printf("\t\tMuxing App\t\t: %ls\n", pMuxingApp);
delete[] pMuxingApp;
}
if (pWritingApp == NULL)
printf("\t\tWriting App\t\t: NULL\n");
else {
printf("\t\tWriting App\t\t: %ls\n", pWritingApp);
delete[] pWritingApp;
}
// pos of segment payload
printf("\t\tPosition(Segment)\t: %lld\n", pSegment->m_start);
// size of segment payload
printf("\t\tSize(Segment)\t\t: %lld\n", pSegment->m_size);
const mkvparser::Tracks* pTracks = pSegment->GetTracks();
unsigned long track_num = 0;
const unsigned long num_tracks = pTracks->GetTracksCount();
printf("\n\t\t\t Track Info\n");
while (track_num != num_tracks) {
const Track* const pTrack = pTracks->GetTrackByIndex(track_num++);
if (pTrack == NULL)
continue;
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: %ld\n", trackType);
printf("\t\tTrack Number\t\t: %ld\n", trackNumber);
printf("\t\tTrack Uid\t\t: %lld\n", trackUid);
if (pTrackName == NULL)
printf("\t\tTrack Name\t\t: NULL\n");
else {
printf("\t\tTrack Name\t\t: %ls \n", pTrackName);
delete[] pTrackName;
}
const char* const pCodecId = pTrack->GetCodecId();
if (pCodecId == NULL)
printf("\t\tCodec Id\t\t: NULL\n");
else
printf("\t\tCodec Id\t\t: %s\n", pCodecId);
const char* const pCodecName_ = pTrack->GetCodecNameAsUTF8();
const wchar_t* const pCodecName = utf8towcs(pCodecName_);
if (pCodecName == NULL)
printf("\t\tCodec Name\t\t: NULL\n");
else {
printf("\t\tCodec Name\t\t: %ls\n", pCodecName);
delete[] pCodecName;
}
if (trackType == mkvparser::Track::kVideo) {
const VideoTrack* const pVideoTrack =
static_cast<const VideoTrack*>(pTrack);
const long long width = pVideoTrack->GetWidth();
printf("\t\tVideo Width\t\t: %lld\n", width);
const long long height = pVideoTrack->GetHeight();
printf("\t\tVideo Height\t\t: %lld\n", height);
const double rate = pVideoTrack->GetFrameRate();
printf("\t\tVideo Rate\t\t: %f\n", rate);
}
if (trackType == mkvparser::Track::kAudio) {
const AudioTrack* const pAudioTrack =
static_cast<const AudioTrack*>(pTrack);
const long long channels = pAudioTrack->GetChannels();
printf("\t\tAudio Channels\t\t: %lld\n", channels);
const long long bitDepth = pAudioTrack->GetBitDepth();
printf("\t\tAudio BitDepth\t\t: %lld\n", bitDepth);
const double sampleRate = pAudioTrack->GetSamplingRate();
printf("\t\tAddio Sample Rate\t: %.3f\n", sampleRate);
const long long codecDelay = pAudioTrack->GetCodecDelay();
printf("\t\tAudio Codec Delay\t\t: %lld\n", codecDelay);
const long long seekPreRoll = pAudioTrack->GetSeekPreRoll();
printf("\t\tAudio Seek Pre Roll\t\t: %lld\n", seekPreRoll);
}
}
printf("\n\n\t\t\t Cluster Info\n");
const unsigned long clusterCount = pSegment->GetCount();
printf("\t\tCluster Count\t: %ld\n\n", clusterCount);
if (clusterCount == 0) {
printf("\t\tSegment has no clusters.\n");
return -1;
}
const mkvparser::Cluster* pCluster = pSegment->GetFirst();
while ((pCluster != NULL) && !pCluster->EOS()) {
const long long timeCode = pCluster->GetTimeCode();
printf("\t\tCluster Time Code\t: %lld\n", timeCode);
const long long time_ns = pCluster->GetTime();
printf("\t\tCluster Time (ns)\t: %lld\n", time_ns);
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()) {
const Block* const pBlock = pBlockEntry->GetBlock();
const long long trackNum = pBlock->GetTrackNumber();
const unsigned long tn = static_cast<unsigned long>(trackNum);
const Track* const pTrack = pTracks->GetTrackByNumber(tn);
if (pTrack == NULL)
printf("\t\t\tBlock\t\t:UNKNOWN TRACK TYPE\n");
else {
const long long trackType = pTrack->GetType();
const int frameCount = pBlock->GetFrameCount();
const long long time_ns = pBlock->GetTime(pCluster);
const long long discard_padding = pBlock->GetDiscardPadding();
printf("\t\t\tBlock\t\t:%s,%s,%15lld,%lld\n",
(trackType == mkvparser::Track::kVideo) ? "V" : "A",
pBlock->IsKey() ? "I" : "P", time_ns, discard_padding);
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);
}
}
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);
}
if (InputHasCues(pSegment.get())) {
// Walk them.
const mkvparser::Cues* const cues = pSegment->GetCues();
const mkvparser::CuePoint* cue = cues->GetFirst();
int cue_point_num = 1;
printf("\t\tCues\n");
do {
for (track_num = 0; track_num < num_tracks; ++track_num) {
const mkvparser::Track* const track =
pTracks->GetTrackByIndex(track_num);
const mkvparser::CuePoint::TrackPosition* const track_pos =
cue->Find(track);
if (track_pos != NULL) {
const char track_type =
(track->GetType() == mkvparser::Track::kVideo) ? 'V' : 'A';
printf(
"\t\t\tCue Point %4d Track %3lu(%c) Time %14lld "
"Block %4lld Pos %8llx\n",
cue_point_num, track->GetNumber(), track_type,
cue->GetTime(pSegment.get()), track_pos->m_block,
track_pos->m_pos);
}
}
cue = cues->GetNext(cue);
++cue_point_num;
} while (cue != NULL);
}
const mkvparser::Tags* const tags = pSegment->GetTags();
if (tags && tags->GetTagCount() > 0) {
printf("\t\tTags\n");
for (int i = 0; i < tags->GetTagCount(); ++i) {
const mkvparser::Tags::Tag* const tag = tags->GetTag(i);
printf("\t\t\tTag\n");
for (int j = 0; j < tag->GetSimpleTagCount(); j++) {
const mkvparser::Tags::SimpleTag* const simple_tag =
tag->GetSimpleTag(j);
printf("\t\t\t\tSimple Tag \"%s\" Value \"%s\"\n",
simple_tag->GetTagName(), simple_tag->GetTagString());
}
}
}
fflush(stdout);
return 0;
}

View File

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

View File

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

View File

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

View File

@@ -9,6 +9,7 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <list>
#include <string>
@@ -23,8 +24,14 @@
#include "sample_muxer_metadata.h"
using mkvmuxer::int64;
using mkvmuxer::uint64;
#ifdef _MSC_VER
// Disable MSVC warnings that suggest making code non-portable.
#pragma warning(disable : 4996)
#endif
namespace {
void Usage() {
@@ -45,6 +52,7 @@ void Usage() {
printf(" -audio_track_number <int> >0 Changes the audio track number\n");
printf(" -video_track_number <int> >0 Changes the video track number\n");
printf(" -chunking <string> Chunk output\n");
printf(" -copy_tags <int> >0 Copies the tags\n");
printf("\n");
printf("Video options:\n");
printf(" -display_width <int> Display width in pixels\n");
@@ -56,16 +64,16 @@ void Usage() {
printf(" -cues_before_clusters <int> >0 puts Cues before Clusters\n");
printf("\n");
printf("Metadata options:\n");
printf(" -webvtt-subtitles <vttfile> "
"add WebVTT subtitles as metadata track\n");
printf(" -webvtt-captions <vttfile> "
"add WebVTT captions as metadata track\n");
printf(" -webvtt-descriptions <vttfile> "
"add WebVTT descriptions as metadata track\n");
printf(" -webvtt-metadata <vttfile> "
"add WebVTT subtitles as metadata track\n");
printf(" -webvtt-chapters <vttfile> "
"add WebVTT chapters as MKV chapters element\n");
printf(" -webvtt-subtitles <vttfile> ");
printf("add WebVTT subtitles as metadata track\n");
printf(" -webvtt-captions <vttfile> ");
printf("add WebVTT captions as metadata track\n");
printf(" -webvtt-descriptions <vttfile> ");
printf("add WebVTT descriptions as metadata track\n");
printf(" -webvtt-metadata <vttfile> ");
printf("add WebVTT subtitles as metadata track\n");
printf(" -webvtt-chapters <vttfile> ");
printf("add WebVTT chapters as MKV chapters element\n");
}
struct MetadataFile {
@@ -76,9 +84,8 @@ struct MetadataFile {
typedef std::list<MetadataFile> metadata_files_t;
// Cache the WebVTT filenames specified as command-line args.
bool LoadMetadataFiles(
const metadata_files_t& files,
SampleMuxerMetadata* metadata) {
bool LoadMetadataFiles(const metadata_files_t& files,
SampleMuxerMetadata* metadata) {
typedef metadata_files_t::const_iterator iter_t;
iter_t i = files.begin();
@@ -94,22 +101,21 @@ bool LoadMetadataFiles(
return true;
}
int ParseArgWebVTT(
char* argv[],
int* argv_index,
int argc_check,
metadata_files_t* metadata_files) {
int ParseArgWebVTT(char* argv[], int* argv_index, int argc_check,
metadata_files_t* metadata_files) {
int& i = *argv_index;
enum { kCount = 5 };
struct Arg { const char* name; SampleMuxerMetadata::Kind kind; };
const Arg args[kCount] = {
{ "-webvtt-subtitles", SampleMuxerMetadata::kSubtitles },
{ "-webvtt-captions", SampleMuxerMetadata::kCaptions },
{ "-webvtt-descriptions", SampleMuxerMetadata::kDescriptions },
{ "-webvtt-metadata", SampleMuxerMetadata::kMetadata },
{ "-webvtt-chapters", SampleMuxerMetadata::kChapters }
struct Arg {
const char* name;
SampleMuxerMetadata::Kind kind;
};
const Arg args[kCount] = {
{"-webvtt-subtitles", SampleMuxerMetadata::kSubtitles},
{"-webvtt-captions", SampleMuxerMetadata::kCaptions},
{"-webvtt-descriptions", SampleMuxerMetadata::kDescriptions},
{"-webvtt-metadata", SampleMuxerMetadata::kMetadata},
{"-webvtt-chapters", SampleMuxerMetadata::kChapters}};
for (int idx = 0; idx < kCount; ++idx) {
const Arg& arg = args[idx];
@@ -155,6 +161,7 @@ int main(int argc, char* argv[]) {
int audio_track_number = 0; // 0 tells muxer to decide.
int video_track_number = 0; // 0 tells muxer to decide.
bool chunking = false;
bool copy_tags = false;
const char* chunk_name = NULL;
bool output_cues_block_number = true;
@@ -196,8 +203,7 @@ int main(int argc, char* argv[]) {
cues_on_video_track = false;
} else if (!strcmp("-max_cluster_duration", argv[i]) && i < argc_check) {
const double seconds = strtod(argv[++i], &end);
max_cluster_duration =
static_cast<uint64>(seconds * 1000000000.0);
max_cluster_duration = static_cast<uint64>(seconds * 1000000000.0);
} else if (!strcmp("-max_cluster_size", argv[i]) && i < argc_check) {
max_cluster_size = strtol(argv[++i], &end, 10);
} else if (!strcmp("-switch_tracks", argv[i]) && i < argc_check) {
@@ -209,6 +215,8 @@ int main(int argc, char* argv[]) {
} else if (!strcmp("-chunking", argv[i]) && i < argc_check) {
chunking = true;
chunk_name = argv[++i];
} else if (!strcmp("-copy_tags", argv[i]) && i < argc_check) {
copy_tags = strtol(argv[++i], &end, 10) == 0 ? false : true;
} else if (!strcmp("-display_width", argv[i]) && i < argc_check) {
display_width = strtol(argv[++i], &end, 10);
} else if (!strcmp("-display_height", argv[i]) && i < argc_check) {
@@ -240,17 +248,20 @@ int main(int argc, char* argv[]) {
long long pos = 0;
mkvparser::EBMLHeader ebml_header;
ebml_header.Parse(&reader, pos);
long long ret = ebml_header.Parse(&reader, pos);
if (ret) {
printf("\n EBMLHeader::Parse() failed.");
return EXIT_FAILURE;
}
mkvparser::Segment* parser_segment;
long long ret = mkvparser::Segment::CreateInstance(&reader,
pos,
parser_segment);
mkvparser::Segment* parser_segment_;
ret = mkvparser::Segment::CreateInstance(&reader, pos, parser_segment_);
if (ret) {
printf("\n Segment::CreateInstance() failed.");
return EXIT_FAILURE;
}
const std::auto_ptr<mkvparser::Segment> parser_segment(parser_segment_);
ret = parser_segment->Load();
if (ret < 0) {
printf("\n Segment::Load() failed.");
@@ -258,6 +269,10 @@ int main(int argc, char* argv[]) {
}
const mkvparser::SegmentInfo* const segment_info = parser_segment->GetInfo();
if (segment_info == NULL) {
printf("\n Segment::GetInfo() failed.");
return EXIT_FAILURE;
}
const long long timeCodeScale = segment_info->GetTimeCodeScale();
// Set muxer header info
@@ -296,6 +311,21 @@ int main(int argc, char* argv[]) {
info->set_timecode_scale(timeCodeScale);
info->set_writing_app("sample_muxer");
const mkvparser::Tags* const tags = parser_segment->GetTags();
if (copy_tags && tags) {
for (int i = 0; i < tags->GetTagCount(); i++) {
const mkvparser::Tags::Tag* const tag = tags->GetTag(i);
mkvmuxer::Tag* muxer_tag = muxer_segment.AddTag();
for (int j = 0; j < tag->GetSimpleTagCount(); j++) {
const mkvparser::Tags::SimpleTag* const simple_tag =
tag->GetSimpleTag(j);
muxer_tag->add_simple_tag(simple_tag->GetTagName(),
simple_tag->GetTagString());
}
}
}
// Set Tracks element attributes
const mkvparser::Tracks* const parser_tracks = parser_segment->GetTracks();
unsigned long i = 0;
@@ -324,7 +354,7 @@ int main(int argc, char* argv[]) {
// 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 width = pVideoTrack->GetWidth();
const long long height = pVideoTrack->GetHeight();
// Add the video track to the muxer
@@ -336,9 +366,8 @@ int main(int argc, char* argv[]) {
return EXIT_FAILURE;
}
mkvmuxer::VideoTrack* const video =
static_cast<mkvmuxer::VideoTrack*>(
muxer_segment.GetTrackByNumber(vid_track));
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;
@@ -347,6 +376,8 @@ int main(int argc, char* argv[]) {
if (track_name)
video->set_name(track_name);
video->set_codec_id(pVideoTrack->GetCodecId());
if (display_width > 0)
video->set_display_width(display_width);
if (display_height > 0)
@@ -362,7 +393,7 @@ int main(int argc, char* argv[]) {
// 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 long long channels = pAudioTrack->GetChannels();
const double sample_rate = pAudioTrack->GetSamplingRate();
// Add the audio track to the muxer
@@ -374,9 +405,8 @@ int main(int argc, char* argv[]) {
return EXIT_FAILURE;
}
mkvmuxer::AudioTrack* const audio =
static_cast<mkvmuxer::AudioTrack*>(
muxer_segment.GetTrackByNumber(aud_track));
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;
@@ -385,6 +415,8 @@ int main(int argc, char* argv[]) {
if (track_name)
audio->set_name(track_name);
audio->set_codec_id(pAudioTrack->GetCodecId());
size_t private_size;
const unsigned char* const private_data =
pAudioTrack->GetCodecPrivate(private_size);
@@ -398,6 +430,11 @@ int main(int argc, char* argv[]) {
const long long bit_depth = pAudioTrack->GetBitDepth();
if (bit_depth > 0)
audio->set_bit_depth(bit_depth);
if (pAudioTrack->GetCodecDelay())
audio->set_codec_delay(pAudioTrack->GetCodecDelay());
if (pAudioTrack->GetSeekPreRoll())
audio->set_seek_pre_roll(pAudioTrack->GetSeekPreRoll());
}
}
@@ -439,16 +476,23 @@ int main(int argc, char* argv[]) {
long status = cluster->GetFirst(block_entry);
if (status) {
printf("\n Could not get first block of cluster.\n");
return EXIT_FAILURE;
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));
parser_tracks->GetTrackByNumber(static_cast<unsigned long>(trackNum));
// When |parser_track| is NULL, it means that the track number in the
// Block is invalid (i.e.) the was no TrackEntry corresponding to the
// track number. So we reject the file.
if (!parser_track) {
return EXIT_FAILURE;
}
const long long track_type = parser_track->GetType();
const long long time_ns = block->GetTime(cluster);
@@ -460,13 +504,12 @@ int main(int argc, char* argv[]) {
if ((track_type == Track::kAudio && output_audio) ||
(track_type == Track::kVideo && output_video)) {
const int frame_count = block->GetFrameCount();
const bool is_key = block->IsKey();
for (int i = 0; i < frame_count; ++i) {
const mkvparser::Block::Frame& frame = block->GetFrame(i);
if (frame.len > data_len) {
delete [] data;
delete[] data;
data = new unsigned char[frame.len];
if (!data)
return EXIT_FAILURE;
@@ -476,15 +519,16 @@ int main(int argc, char* argv[]) {
if (frame.Read(&reader, data))
return EXIT_FAILURE;
uint64 track_num = vid_track;
if (track_type == Track::kAudio)
track_num = aud_track;
if (!muxer_segment.AddFrame(data,
frame.len,
track_num,
time_ns,
is_key)) {
mkvmuxer::Frame muxer_frame;
if (!muxer_frame.Init(data, frame.len))
return EXIT_FAILURE;
muxer_frame.set_track_number(track_type == Track::kAudio ? aud_track :
vid_track);
if (block->GetDiscardPadding())
muxer_frame.set_discard_padding(block->GetDiscardPadding());
muxer_frame.set_timestamp(time_ns);
muxer_frame.set_is_key(block->IsKey());
if (!muxer_segment.AddGenericFrame(&muxer_frame)) {
printf("\n Could not add frame.\n");
return EXIT_FAILURE;
}
@@ -494,8 +538,8 @@ int main(int argc, char* argv[]) {
status = cluster->GetNext(block_entry, block_entry);
if (status) {
printf("\n Could not get next block of cluster.\n");
return EXIT_FAILURE;
printf("\n Could not get next block of cluster.\n");
return EXIT_FAILURE;
}
}
@@ -533,8 +577,7 @@ int main(int argc, char* argv[]) {
remove(temp_file);
}
delete [] data;
delete parser_segment;
delete[] data;
return EXIT_SUCCESS;
}

View File

@@ -1,179 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="sample_muxer"
ProjectGUID="{B407561F-1F5E-4798-B9C2-81AB09CFBC16}"
RootNamespace="sample_muxer"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(ProjectDir)..\exe\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(ProjectDir)..\obj\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(ProjectDir)..\lib\libwebm_2008\libwebm\$(PlatformName)\$(ConfigurationName)\libwebm.lib"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(ProjectDir)..\exe\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(ProjectDir)..\obj\libwebm_2008\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="../"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(ProjectDir)..\lib\libwebm_2008\libwebm\$(PlatformName)\$(ConfigurationName)\libwebm.lib"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=".\sample_muxer.cpp"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

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

View File

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

View File

@@ -1,9 +1,19 @@
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
//
// This sample application demonstrates how to use the matroska parser
// library, which allows clients to handle a matroska format file.
#include "sample_muxer_metadata.h"
#include <string>
#include "vttreader.h"
SampleMuxerMetadata::SampleMuxerMetadata() : segment_(NULL) {
}
SampleMuxerMetadata::SampleMuxerMetadata() : segment_(NULL) {}
bool SampleMuxerMetadata::Init(mkvmuxer::Segment* segment) {
if (segment == NULL || segment_ != NULL)
@@ -82,9 +92,8 @@ bool SampleMuxerMetadata::LoadChapters(const char* file) {
return true;
}
bool SampleMuxerMetadata::ParseChapters(
const char* file,
cue_list_t* cues_ptr) {
bool SampleMuxerMetadata::ParseChapters(const char* file,
cue_list_t* cues_ptr) {
cue_list_t& cues = *cues_ptr;
cues.clear();
@@ -188,9 +197,7 @@ bool SampleMuxerMetadata::AddChapter(const cue_t& cue) {
return true;
}
bool SampleMuxerMetadata::AddTrack(
Kind kind,
mkvmuxer::uint64* track_num) {
bool SampleMuxerMetadata::AddTrack(Kind kind, mkvmuxer::uint64* track_num) {
*track_num = 0;
// Track number value 0 means "let muxer choose track number"
@@ -238,10 +245,8 @@ bool SampleMuxerMetadata::AddTrack(
return true;
}
bool SampleMuxerMetadata::Parse(
const char* file,
Kind /* kind */,
mkvmuxer::uint64 track_num) {
bool SampleMuxerMetadata::Parse(const char* file, Kind /* kind */,
mkvmuxer::uint64 track_num) {
libwebvtt::VttReader r;
int e = r.Open(file);
@@ -300,16 +305,14 @@ void SampleMuxerMetadata::MakeFrame(const cue_t& c, std::string* pf) {
WriteCuePayload(c.payload, pf);
}
void SampleMuxerMetadata::WriteCueIdentifier(
const std::string& identifier,
std::string* 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) {
void SampleMuxerMetadata::WriteCueSettings(const cue_t::settings_t& settings,
std::string* pf) {
if (settings.empty()) {
pf->push_back('\x0A'); // LF
return;
@@ -336,9 +339,8 @@ void SampleMuxerMetadata::WriteCueSettings(
pf->push_back('\x0A'); // LF
}
void SampleMuxerMetadata::WriteCuePayload(
const cue_t::payload_t& payload,
std::string* pf) {
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();
@@ -351,8 +353,7 @@ void SampleMuxerMetadata::WriteCuePayload(
}
}
bool SampleMuxerMetadata::SortableCue::Write(
mkvmuxer::Segment* segment) const {
bool SampleMuxerMetadata::SortableCue::Write(mkvmuxer::Segment* segment) const {
// Cue start time expressed in milliseconds
const mkvmuxer::int64 start_ms = cue.start_time.presentation();
@@ -375,5 +376,12 @@ bool SampleMuxerMetadata::SortableCue::Write(
const data_t buf = reinterpret_cast<data_t>(frame.data());
const mkvmuxer::uint64 len = frame.length();
return segment->AddMetadata(buf, len, track_num, start_ns, duration_ns);
mkvmuxer::Frame muxer_frame;
if (!muxer_frame.Init(buf, len))
return 0;
muxer_frame.set_track_number(track_num);
muxer_frame.set_timestamp(start_ns);
muxer_frame.set_duration(duration_ns);
muxer_frame.set_is_key(true); // All metadata frames are keyframes.
return segment->AddGenericFrame(&muxer_frame);
}

View File

@@ -17,13 +17,7 @@
class SampleMuxerMetadata {
public:
enum Kind {
kSubtitles,
kCaptions,
kDescriptions,
kMetadata,
kChapters
};
enum Kind { kSubtitles, kCaptions, kDescriptions, kMetadata, kChapters };
SampleMuxerMetadata();
@@ -86,8 +80,7 @@ class SampleMuxerMetadata {
// Parse the WebVTT chapters in |file| to populate |cues|. Returns
// false on error.
static bool ParseChapters(const char* file,
cue_list_t* cues);
static bool ParseChapters(const char* file, cue_list_t* cues);
// Adds WebVTT cue |chapter| to the chapters element of the output
// file's segment element. Returns false on error.

View File

@@ -15,6 +15,11 @@
#include "./mkvreader.hpp"
#include "./webvttparser.h"
#ifdef _MSC_VER
// Disable MSVC warnings that suggest making code non-portable.
#pragma warning(disable : 4996)
#endif
using std::string;
namespace vttdemux {
@@ -26,12 +31,7 @@ typedef std::auto_ptr<mkvparser::Segment> segment_ptr_t;
// WebVTT metadata tracks have a type (encoded in the CodecID for the track).
// We use |type| to synthesize a filename for the out-of-band WebVTT |file|.
struct MetadataInfo {
enum Type {
kSubtitles,
kCaptions,
kDescriptions,
kMetadata,
kChapters } type;
enum Type { kSubtitles, kCaptions, kDescriptions, kMetadata, kChapters } type;
FILE* file;
};
@@ -125,45 +125,36 @@ bool ParseHeader(mkvparser::IMkvReader* reader, mkvpos_t* pos);
// Parse the Segment of the input file and load all of its clusters.
// Returns false if there was an error parsing the file.
bool ParseSegment(
mkvparser::IMkvReader* reader,
mkvpos_t pos,
segment_ptr_t* segment);
bool ParseSegment(mkvparser::IMkvReader* reader, mkvpos_t pos,
segment_ptr_t* segment);
// If |segment| has a Chapters element (in which case, there will be a
// corresponding entry in |metadata_map|), convert the MKV chapters to
// WebVTT chapter cues and write them to the output file. Returns
// false on error.
bool WriteChaptersFile(
const metadata_map_t& metadata_map,
const mkvparser::Segment* segment);
bool WriteChaptersFile(const metadata_map_t& metadata_map,
const mkvparser::Segment* segment);
// Convert an MKV Chapters Atom to a WebVTT cue and write it to the
// output |file|. Returns false on error.
bool WriteChaptersCue(
FILE* file,
const mkvparser::Chapters* chapters,
const mkvparser::Chapters::Atom* atom,
const mkvparser::Chapters::Display* display);
bool WriteChaptersCue(FILE* file, const mkvparser::Chapters* chapters,
const mkvparser::Chapters::Atom* atom,
const mkvparser::Chapters::Display* display);
// Write the Cue Identifier line of the WebVTT cue, if it's present.
// Returns false on error.
bool WriteChaptersCueIdentifier(
FILE* file,
const mkvparser::Chapters::Atom* atom);
bool WriteChaptersCueIdentifier(FILE* file,
const mkvparser::Chapters::Atom* atom);
// Use the timecodes from the chapters |atom| to write just the
// timings line of the WebVTT cue. Returns false on error.
bool WriteChaptersCueTimings(
FILE* file,
const mkvparser::Chapters* chapters,
const mkvparser::Chapters::Atom* atom);
bool WriteChaptersCueTimings(FILE* file, const mkvparser::Chapters* chapters,
const mkvparser::Chapters::Atom* atom);
// Parse the String sub-element of the |display| and write the payload
// of the WebVTT cue. Returns false on error.
bool WriteChaptersCuePayload(
FILE* file,
const mkvparser::Chapters::Display* display);
bool WriteChaptersCuePayload(FILE* file,
const mkvparser::Chapters::Display* display);
// Iterate over the tracks of the input file (and any chapters
// element) and cache information about each metadata track.
@@ -190,16 +181,14 @@ bool InitializeFiles(const metadata_map_t& metadata_map);
// Iterate over the blocks of the |cluster|, writing a WebVTT cue to
// its associated output file for each block of metadata. Returns
// false if processing a block failed, or there was a parse error.
bool ProcessCluster(
const metadata_map_t& metadata_map,
const mkvparser::Cluster* cluster);
bool ProcessCluster(const metadata_map_t& metadata_map,
const mkvparser::Cluster* cluster);
// Look up this track number in the cache, and if found (meaning this
// is a metadata track), write a WebVTT cue to the associated output
// file. Returns false if writing the WebVTT cue failed.
bool ProcessBlockEntry(
const metadata_map_t& metadata_map,
const mkvparser::BlockEntry* block_entry);
bool ProcessBlockEntry(const metadata_map_t& metadata_map,
const mkvparser::BlockEntry* block_entry);
// Parse the lines of text from the |block_group| to reconstruct the
// original WebVTT cue, and write it to the associated output |file|.
@@ -215,24 +204,18 @@ bool WriteCueIdentifier(FILE* f, FrameParser* parser);
// cue settings) and write the cue timings line for this cue to the
// associated output file. Returns false if there was an error
// writing to the file.
bool WriteCueTimings(
FILE* f,
FrameParser* parser);
bool WriteCueTimings(FILE* f, FrameParser* parser);
// Write the timestamp (representating either the start time or stop
// time of the cue) to the output file. Returns false if there was an
// error writing to the file.
bool WriteCueTime(
FILE* f,
mkvtime_t time_ns);
bool WriteCueTime(FILE* f, mkvtime_t time_ns);
// Consume the remaining lines of text from the character stream
// (these lines are the actual payload of the WebVTT cue), and write
// them to the associated output file. Returns false if there was an
// error writing to the file.
bool WriteCuePayload(
FILE* f,
FrameParser* parser);
bool WriteCuePayload(FILE* f, FrameParser* parser);
} // namespace vttdemux
int main(int argc, const char* argv[]) {
@@ -299,8 +282,7 @@ FrameParser::FrameParser(const mkvparser::BlockGroup* block_group)
pos_end_ = f.pos + f.len;
}
FrameParser::~FrameParser() {
}
FrameParser::~FrameParser() {}
int FrameParser::GetChar(char* c) {
if (pos_ >= pos_end_) // end-of-stream
@@ -320,7 +302,7 @@ int FrameParser::GetChar(char* c) {
return 0;
}
void FrameParser::UngetChar(char /* c */ ) {
void FrameParser::UngetChar(char /* c */) {
// All we need to do here is decrement the position in the stream.
// The next time GetChar is called the same character will be
// re-read from the input file.
@@ -335,8 +317,7 @@ ChapterAtomParser::ChapterAtomParser(
str_end_ = str_ + len;
}
ChapterAtomParser::~ChapterAtomParser() {
}
ChapterAtomParser::~ChapterAtomParser() {}
int ChapterAtomParser::GetChar(char* c) {
if (str_ >= str_end_) // end-of-stream
@@ -346,7 +327,7 @@ int ChapterAtomParser::GetChar(char* c) {
return 0;
}
void ChapterAtomParser::UngetChar(char /* c */ ) {
void ChapterAtomParser::UngetChar(char /* c */) {
// All we need to do here is decrement the position in the stream.
// The next time GetChar is called the same character will be
// re-read from the input file.
@@ -355,9 +336,7 @@ void ChapterAtomParser::UngetChar(char /* c */ ) {
} // namespace vttdemux
bool vttdemux::ParseHeader(
mkvparser::IMkvReader* reader,
mkvpos_t* pos) {
bool vttdemux::ParseHeader(mkvparser::IMkvReader* reader, mkvpos_t* pos) {
mkvparser::EBMLHeader h;
const mkvpos_t status = h.Parse(reader, *pos);
@@ -366,7 +345,7 @@ bool vttdemux::ParseHeader(
return false;
}
if (strcmp(h.m_docType, "webm") != 0) {
if (h.m_docType == NULL || strcmp(h.m_docType, "webm") != 0) {
printf("bad doctype\n");
return false;
}
@@ -374,10 +353,8 @@ bool vttdemux::ParseHeader(
return true; // success
}
bool vttdemux::ParseSegment(
mkvparser::IMkvReader* reader,
mkvpos_t pos,
segment_ptr_t* segment_ptr) {
bool vttdemux::ParseSegment(mkvparser::IMkvReader* reader, mkvpos_t pos,
segment_ptr_t* segment_ptr) {
// We first create the segment object.
mkvparser::Segment* p;
@@ -402,9 +379,8 @@ bool vttdemux::ParseSegment(
return true;
}
void vttdemux::BuildMap(
const mkvparser::Segment* segment,
metadata_map_t* map_ptr) {
void vttdemux::BuildMap(const mkvparser::Segment* segment,
metadata_map_t* map_ptr) {
metadata_map_t& m = *map_ptr;
m.clear();
@@ -551,7 +527,11 @@ bool vttdemux::OpenFiles(metadata_map_t* metadata_map, const char* filename) {
if (exists[type] > 1) {
enum { kLen = 33 };
char str[kLen]; // max 126 tracks, so only 4 chars really needed
#ifndef _MSC_VER
snprintf(str, kLen, "%ld", v.first); // track number
#else
_snprintf_s(str, sizeof(str), kLen, "%ld", v.first); // track number
#endif
name += str;
}
@@ -563,8 +543,9 @@ bool vttdemux::OpenFiles(metadata_map_t* metadata_map, const char* filename) {
// open the WebVTT output file.
info.file = fopen(name.c_str(), "wb");
const bool success = (info.file != NULL);
if (info.file == NULL) {
if (!success) {
printf("unable to open output file %s\n", name.c_str());
return false;
}
@@ -640,9 +621,8 @@ bool vttdemux::InitializeFiles(const metadata_map_t& m) {
return true;
}
bool vttdemux::WriteChaptersFile(
const metadata_map_t& m,
const mkvparser::Segment* s) {
bool vttdemux::WriteChaptersFile(const metadata_map_t& m,
const mkvparser::Segment* s) {
const metadata_map_t::const_iterator info_iter = m.find(kChaptersKey);
if (info_iter == m.end()) // no chapters, so nothing to do
return true;
@@ -713,11 +693,9 @@ bool vttdemux::WriteChaptersFile(
return true;
}
bool vttdemux::WriteChaptersCue(
FILE* f,
const mkvparser::Chapters* chapters,
const mkvparser::Chapters::Atom* atom,
const mkvparser::Chapters::Display* display) {
bool vttdemux::WriteChaptersCue(FILE* f, const mkvparser::Chapters* chapters,
const mkvparser::Chapters::Atom* atom,
const mkvparser::Chapters::Display* display) {
// We start a new cue by writing a cue separator (an empty line)
// into the stream.
@@ -741,9 +719,7 @@ bool vttdemux::WriteChaptersCue(
}
bool vttdemux::WriteChaptersCueIdentifier(
FILE* f,
const mkvparser::Chapters::Atom* atom) {
FILE* f, const mkvparser::Chapters::Atom* atom) {
const char* const identifier = atom->GetStringUID();
if (identifier == NULL)
@@ -755,10 +731,9 @@ bool vttdemux::WriteChaptersCueIdentifier(
return true;
}
bool vttdemux::WriteChaptersCueTimings(
FILE* f,
const mkvparser::Chapters* chapters,
const mkvparser::Chapters::Atom* atom) {
bool vttdemux::WriteChaptersCueTimings(FILE* f,
const mkvparser::Chapters* chapters,
const mkvparser::Chapters::Atom* atom) {
const mkvtime_t start_ns = atom->GetStartTime(chapters);
if (start_ns < 0)
@@ -785,8 +760,7 @@ bool vttdemux::WriteChaptersCueTimings(
}
bool vttdemux::WriteChaptersCuePayload(
FILE* f,
const mkvparser::Chapters::Display* display) {
FILE* f, const mkvparser::Chapters::Display* display) {
// Bind a Chapter parser object to the display, which allows us to
// extract each line of text from the title-part of the display.
ChapterAtomParser parser(display);
@@ -813,16 +787,15 @@ bool vttdemux::WriteChaptersCuePayload(
return true;
}
bool vttdemux::ProcessCluster(
const metadata_map_t& m,
const mkvparser::Cluster* c) {
bool vttdemux::ProcessCluster(const metadata_map_t& m,
const mkvparser::Cluster* c) {
// Visit the blocks in this cluster, writing a WebVTT cue for each
// metadata block.
const mkvparser::BlockEntry* block_entry;
long result = c->GetFirst(block_entry); // NOLINT
if (result < 0) { // error
if (result < 0) {
printf("bad cluster (unable to get first block)\n");
return false;
}
@@ -841,9 +814,8 @@ bool vttdemux::ProcessCluster(
return true;
}
bool vttdemux::ProcessBlockEntry(
const metadata_map_t& m,
const mkvparser::BlockEntry* block_entry) {
bool vttdemux::ProcessBlockEntry(const metadata_map_t& m,
const mkvparser::BlockEntry* block_entry) {
// If the track number for this block is in the cache, then we have
// a metadata block, so write the WebVTT cue to the output file.
@@ -851,10 +823,10 @@ bool vttdemux::ProcessBlockEntry(
const long long tn = block->GetTrackNumber(); // NOLINT
typedef metadata_map_t::const_iterator iter_t;
const iter_t i = m.find(tn);
const iter_t i = m.find(static_cast<metadata_map_t::key_type>(tn));
if (i == m.end()) // not a metadata track
return true; // nothing else to do
return true; // nothing else to do
if (block_entry->GetKind() != mkvparser::BlockEntry::kBlockGroup)
return false; // weird
@@ -868,9 +840,7 @@ bool vttdemux::ProcessBlockEntry(
return WriteCue(f, block_group);
}
bool vttdemux::WriteCue(
FILE* f,
const mkvparser::BlockGroup* block_group) {
bool vttdemux::WriteCue(FILE* f, const mkvparser::BlockGroup* block_group) {
// Bind a FrameParser object to the block, which allows us to
// extract each line of text from the payload of the block.
FrameParser parser(block_group);
@@ -897,9 +867,7 @@ bool vttdemux::WriteCue(
return true;
}
bool vttdemux::WriteCueIdentifier(
FILE* f,
FrameParser* parser) {
bool vttdemux::WriteCueIdentifier(FILE* f, FrameParser* parser) {
string line;
int e = parser->GetLine(&line);
@@ -922,9 +890,7 @@ bool vttdemux::WriteCueIdentifier(
return true;
}
bool vttdemux::WriteCueTimings(
FILE* f,
FrameParser* parser) {
bool vttdemux::WriteCueTimings(FILE* f, FrameParser* parser) {
const mkvparser::BlockGroup* const block_group = parser->block_group_;
const mkvparser::Cluster* const cluster = block_group->GetCluster();
const mkvparser::Block* const block = block_group->GetBlock();
@@ -986,9 +952,7 @@ bool vttdemux::WriteCueTimings(
return true;
}
bool vttdemux::WriteCueTime(
FILE* f,
mkvtime_t time_ns) {
bool vttdemux::WriteCueTime(FILE* f, mkvtime_t time_ns) {
mkvtime_t ms = time_ns / 1000000; // WebVTT time has millisecond resolution
mkvtime_t sec = ms / 1000;
@@ -1006,14 +970,12 @@ bool vttdemux::WriteCueTime(
}
if (fprintf(f, "%02lld:%02lld.%03lld", min, sec, ms) < 0)
return false;
return false;
return true;
}
bool vttdemux::WriteCuePayload(
FILE* f,
FrameParser* parser) {
bool vttdemux::WriteCuePayload(FILE* f, FrameParser* parser) {
int count = 0; // count of lines of payload text written to output file
for (string line;;) {
const int e = parser->GetLine(&line);

View File

@@ -8,14 +8,16 @@
#include "./vttreader.h" // NOLINT
#ifdef _MSC_VER
// Disable MSVC warnings that suggest making code non-portable.
#pragma warning(disable : 4996)
#endif
namespace libwebvtt {
VttReader::VttReader() : file_(NULL) {
}
VttReader::VttReader() : file_(NULL) {}
VttReader::~VttReader() {
Close();
}
VttReader::~VttReader() { Close(); }
int VttReader::Open(const char* filename) {
if (filename == NULL || file_ != NULL)

517
webm2pes.cc Normal file
View File

@@ -0,0 +1,517 @@
// Copyright (c) 2015 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "webm2pes.h"
#include <vector>
namespace {
void Usage(const char* argv[]) {
printf("Usage: %s <WebM file> <output file>", argv[0]);
}
bool WriteUint8(std::uint8_t val, std::FILE* fileptr) {
if (fileptr == nullptr)
return false;
return (std::fputc(val, fileptr) == val);
}
struct Range {
Range(std::size_t off, std::size_t len) : offset(off), length(len) {}
Range() = delete;
Range(const Range&) = default;
Range(Range&&) = default;
~Range() = default;
const std::size_t offset;
const std::size_t length;
};
typedef std::vector<Range> FrameRanges;
// Returns true and stores frame offsets and lengths in |frame_ranges| when
// |frame| has a valid VP9 super frame index.
bool ParseVP9SuperFrameIndex(const std::uint8_t* frame,
std::size_t length,
FrameRanges* frame_ranges) {
if (frame == nullptr || length == 0 || frame_ranges == nullptr)
return false;
bool parse_ok = false;
const std::uint8_t marker = frame[length - 1];
const std::uint32_t kHasSuperFrameIndexMask = 0xe0;
const std::uint32_t kSuperFrameMarker = 0xc0;
if ((marker & kHasSuperFrameIndexMask) == kSuperFrameMarker) {
const std::uint32_t kFrameCountMask = 0x7;
const int num_frames = (marker & kFrameCountMask) + 1;
const int length_field_size = ((marker >> 3) & 0x3) + 1;
const std::size_t index_length = 2 + length_field_size * num_frames;
// Consume the super frame index.
std::size_t frame_offset = index_length;
if (length >= index_length && frame[length - index_length] == marker) {
// Found a valid superframe index.
const std::uint8_t* byte = frame + length - index_length + 1;
for (int i = 0; i < num_frames; ++i) {
std::uint32_t child_frame_length = 0;
for (int j = 0; j < length_field_size; ++j) {
child_frame_length |= (*byte++) << (j * 8);
}
frame_ranges->push_back(Range(frame_offset, child_frame_length));
frame_offset += child_frame_length;
}
if (frame_ranges->size() != num_frames) {
std::fprintf(stderr, "Webm2Pes: superframe index parse failed.\n");
return false;
}
parse_ok = true;
} else {
std::fprintf(stderr, "Webm2Pes: Invalid superframe index.\n");
}
}
return parse_ok;
}
std::int64_t NanosecondsTo90KhzTicks(std::int64_t nanoseconds) {
const double kNanosecondsPerSecond = 1000000000.0;
const double pts_seconds = nanoseconds / kNanosecondsPerSecond;
return pts_seconds * 90000;
}
bool GetPacketPayloadRanges(const libwebm::PesHeader& header,
const FrameRanges& frame_ranges,
FrameRanges* packet_payload_ranges) {
// TODO(tomfinegan): The length field in PES is actually number of bytes that
// follow the length field, and does not include the 6 byte fixed portion of
// the header (4 byte start code + 2 bytes for the length). We can fit in 6
// more bytes if we really want to, and avoid packetization when size is very
// close to UINT16_MAX.
if (packet_payload_ranges == nullptr) {
std::fprintf(stderr, "Webm2Pes: nullptr getting payload ranges.\n");
return false;
}
const std::size_t kMaxPacketPayloadSize = UINT16_MAX - header.size();
for (const Range& frame_range : frame_ranges) {
if (frame_range.length + header.size() > kMaxPacketPayloadSize) {
// make packet ranges until range.length is exhausted
const std::size_t kBytesToPacketize = frame_range.length;
std::size_t packet_payload_length = 0;
for (std::size_t pos = 0; pos < kBytesToPacketize;
pos += packet_payload_length) {
packet_payload_length =
(frame_range.length - pos < kMaxPacketPayloadSize)
? frame_range.length - pos
: kMaxPacketPayloadSize;
packet_payload_ranges->push_back(
Range(frame_range.offset + pos, packet_payload_length));
}
} else {
// copy range into |packet_ranges|
packet_payload_ranges->push_back(
Range(frame_range.offset, frame_range.length));
}
}
return true;
}
} // namespace
namespace libwebm {
//
// PesOptionalHeader methods.
//
void PesOptionalHeader::SetPtsBits(std::int64_t pts_90khz) {
std::uint64_t* pts_bits = &pts.bits;
*pts_bits = 0;
// PTS is broken up and stored in 40 bits as shown:
//
// PES PTS Only flag
// / Marker Marker Marker
// | / / /
// | | | |
// 7654 321 0 765432107654321 0 765432107654321 0
// 0010 PTS 32-30 1 PTS 29-15 1 PTS 14-0 1
const std::uint32_t pts1 = (pts_90khz >> 30) & 0x7;
const std::uint32_t pts2 = (pts_90khz >> 15) & 0x7FFF;
const std::uint32_t pts3 = pts_90khz & 0x7FFF;
std::uint8_t buffer[5] = {0};
// PTS only flag.
buffer[0] |= 1 << 5;
// Top 3 bits of PTS and 1 bit marker.
buffer[0] |= pts1 << 1;
// Marker.
buffer[0] |= 1;
// Next 15 bits of pts and 1 bit marker.
// Top 8 bits of second PTS chunk.
buffer[1] |= (pts2 >> 7) & 0xff;
// bottom 7 bits of second PTS chunk.
buffer[2] |= (pts2 << 1);
// Marker.
buffer[2] |= 1;
// Last 15 bits of pts and 1 bit marker.
// Top 8 bits of second PTS chunk.
buffer[3] |= (pts3 >> 7) & 0xff;
// bottom 7 bits of second PTS chunk.
buffer[4] |= (pts3 << 1);
// Marker.
buffer[4] |= 1;
// Write bits into PesHeaderField.
std::memcpy(reinterpret_cast<std::uint8_t*>(pts_bits), buffer, 5);
}
// Writes fields to |file| and returns true. Returns false when write or
// field value validation fails.
bool PesOptionalHeader::Write(std::FILE* file, bool write_pts) const {
if (file == nullptr) {
std::fprintf(stderr, "Webm2Pes: nullptr in opt header writer.\n");
return false;
}
std::uint8_t header[9] = {0};
std::uint8_t* byte = header;
if (marker.Check() != true || scrambling.Check() != true ||
priority.Check() != true || data_alignment.Check() != true ||
copyright.Check() != true || original.Check() != true ||
has_pts.Check() != true || has_dts.Check() != true ||
pts.Check() != true || stuffing_byte.Check() != true) {
std::fprintf(stderr, "Webm2Pes: Invalid PES Optional Header field.\n");
return false;
}
// TODO(tomfinegan): As noted in above, the PesHeaderFields should be an
// array (or some data structure) that can be iterated over.
// First byte of header, fields: marker, scrambling, priority, alignment,
// copyright, original.
*byte = 0;
*byte |= marker.bits << marker.shift;
*byte |= scrambling.bits << scrambling.shift;
*byte |= priority.bits << priority.shift;
*byte |= data_alignment.bits << data_alignment.shift;
*byte |= copyright.bits << copyright.shift;
*byte |= original.bits << original.shift;
// Second byte of header, fields: has_pts, has_dts, unused fields.
*++byte = 0;
if (write_pts == true) {
*byte |= has_pts.bits << has_pts.shift;
*byte |= has_dts.bits << has_dts.shift;
}
// Third byte of header, fields: remaining size of header.
*++byte = remaining_size.bits; // Field is 8 bits wide.
int num_stuffing_bytes =
(pts.num_bits + 7) / 8 + 1 /* always 1 stuffing byte */;
if (write_pts == true) {
// Set the PTS value and adjust stuffing byte count accordingly.
*++byte = (pts.bits >> 32) & 0xff;
*++byte = (pts.bits >> 24) & 0xff;
*++byte = (pts.bits >> 16) & 0xff;
*++byte = (pts.bits >> 8) & 0xff;
*++byte = pts.bits & 0xff;
num_stuffing_bytes = 1;
}
// Add the stuffing byte(s).
for (int i = 0; i < num_stuffing_bytes; ++i)
*++byte = stuffing_byte.bits;
if (std::fwrite(reinterpret_cast<void*>(header), 1, size_in_bytes(), file) !=
size_in_bytes()) {
std::fprintf(stderr, "Webm2Pes: unable to write PES opt header to file.\n");
return false;
}
return true;
}
//
// BCMVHeader methods.
//
bool BCMVHeader::Write(std::FILE* fileptr) const {
if (fileptr == nullptr) {
std::fprintf(stderr, "Webm2Pes: nullptr for file in BCMV Write.\n");
return false;
}
if (std::fwrite(bcmv, 1, 4, fileptr) != 4) {
std::fprintf(stderr, "Webm2Pes: BCMV write failed.\n");
}
const std::size_t kRemainingBytes = 6;
const uint8_t buffer[kRemainingBytes] = {(length >> 24) & 0xff,
(length >> 16) & 0xff,
(length >> 8) & 0xff,
length & 0xff,
0,
0 /* 2 bytes 0 padding */};
for (std::int8_t i = 0; i < kRemainingBytes; ++i) {
if (WriteUint8(buffer[i], fileptr) != true) {
std::fprintf(stderr, "Webm2Pes: BCMV remainder write failed.\n");
return false;
}
}
return true;
}
//
// PesHeader methods.
//
// Writes out the header to |file|. Calls PesOptionalHeader::Write() to write
// |optional_header| contents. Returns true when successful, false otherwise.
bool PesHeader::Write(std::FILE* file, bool write_pts) const {
if (file == nullptr) {
std::fprintf(stderr, "Webm2Pes: nullptr in header writer.\n");
return false;
}
// Write |start_code|.
if (std::fwrite(reinterpret_cast<const void*>(start_code), 1, 4, file) != 4) {
std::fprintf(stderr, "Webm2Pes: cannot write packet start code.\n");
return false;
}
// Write |packet_length| as big endian.
std::uint8_t byte = (packet_length >> 8) & 0xff;
if (WriteUint8(byte, file) != true) {
std::fprintf(stderr, "Webm2Pes: cannot write packet length (byte 0).\n");
return false;
}
byte = packet_length & 0xff;
if (WriteUint8(byte, file) != true) {
std::fprintf(stderr, "Webm2Pes: cannot write packet length (byte 1).\n");
return false;
}
// Write the (not really) optional header.
if (optional_header.Write(file, write_pts) != true) {
std::fprintf(stderr, "Webm2Pes: PES optional header write failed.");
return false;
}
return true;
}
//
// Webm2Pes methods.
//
bool Webm2Pes::Convert() {
if (input_file_name_.empty() || output_file_name_.empty()) {
std::fprintf(stderr, "Webm2Pes: input and/or output file name(s) empty.\n");
return false;
}
if (webm_reader_.Open(input_file_name_.c_str()) != 0) {
std::fprintf(stderr, "Webm2Pes: Cannot open %s as input.\n",
input_file_name_.c_str());
return false;
}
output_file_ = FilePtr(fopen(output_file_name_.c_str(), "wb"), FILEDeleter());
if (output_file_ == nullptr) {
std::fprintf(stderr, "Webm2Pes: Cannot open %s for output.\n",
output_file_name_.c_str());
return false;
}
using mkvparser::Segment;
Segment* webm_parser = nullptr;
if (Segment::CreateInstance(&webm_reader_, 0 /* pos */,
webm_parser /* Segment*& */) != 0) {
std::fprintf(stderr, "Webm2Pes: Cannot create WebM parser.\n");
return false;
}
webm_parser_.reset(webm_parser);
if (webm_parser_->Load() != 0) {
std::fprintf(stderr, "Webm2Pes: Cannot parse %s.\n",
input_file_name_.c_str());
return false;
}
// Store timecode scale.
timecode_scale_ = webm_parser_->GetInfo()->GetTimeCodeScale();
// Make sure there's a video track.
const mkvparser::Tracks* tracks = webm_parser_->GetTracks();
if (tracks == nullptr) {
std::fprintf(stderr, "Webm2Pes: %s has no tracks.\n",
input_file_name_.c_str());
return false;
}
for (int track_index = 0; track_index < tracks->GetTracksCount();
++track_index) {
const mkvparser::Track* track = tracks->GetTrackByIndex(track_index);
if (track && track->GetType() == mkvparser::Track::kVideo) {
if (std::string(track->GetCodecId()) == std::string("V_VP8"))
codec_ = VP8;
else if (std::string(track->GetCodecId()) == std::string("V_VP9"))
codec_ = VP9;
else {
fprintf(stderr, "Webm2Pes: Codec must be VP8 or VP9.\n");
return false;
}
video_track_num_ = track_index + 1;
break;
}
}
if (video_track_num_ < 1) {
std::fprintf(stderr, "Webm2Pes: No video track found in %s.\n",
input_file_name_.c_str());
return false;
}
// Walk clusters in segment.
const mkvparser::Cluster* cluster = webm_parser_->GetFirst();
while (cluster != nullptr && cluster->EOS() == false) {
const mkvparser::BlockEntry* block_entry = nullptr;
std::int64_t block_status = cluster->GetFirst(block_entry);
if (block_status < 0) {
std::fprintf(stderr, "Webm2Pes: Cannot parse first block in %s.\n",
input_file_name_.c_str());
return false;
}
// Walk blocks in cluster.
while (block_entry != nullptr && block_entry->EOS() == false) {
const mkvparser::Block* block = block_entry->GetBlock();
if (block->GetTrackNumber() == video_track_num_) {
const int frame_count = block->GetFrameCount();
// Walk frames in block.
for (int frame_num = 0; frame_num < frame_count; ++frame_num) {
const mkvparser::Block::Frame& frame = block->GetFrame(frame_num);
// Write frame out as PES packet(s).
const bool pes_status =
WritePesPacket(frame, block->GetTime(cluster));
if (pes_status != true) {
std::fprintf(stderr, "Webm2Pes: WritePesPacket failed.\n");
return false;
}
}
}
block_status = cluster->GetNext(block_entry, block_entry);
if (block_status < 0) {
std::fprintf(stderr, "Webm2Pes: Cannot parse block in %s.\n",
input_file_name_.c_str());
return false;
}
}
cluster = webm_parser_->GetNext(cluster);
}
return true;
}
bool Webm2Pes::WritePesPacket(const mkvparser::Block::Frame& vpx_frame,
double nanosecond_pts) {
// Read the input frame.
std::unique_ptr<uint8_t[]> frame_data(new (std::nothrow)
uint8_t[vpx_frame.len]);
if (frame_data.get() == nullptr) {
std::fprintf(stderr, "Webm2Pes: Out of memory.\n");
return false;
}
if (vpx_frame.Read(&webm_reader_, frame_data.get()) != 0) {
std::fprintf(stderr, "Webm2Pes: Error reading VPx frame!\n");
return false;
}
FrameRanges frame_ranges;
if (codec_ == VP9) {
bool has_superframe_index =
ParseVP9SuperFrameIndex(frame_data.get(), vpx_frame.len, &frame_ranges);
if (has_superframe_index == false) {
frame_ranges.push_back(Range(0, vpx_frame.len));
}
} else {
frame_ranges.push_back(Range(0, vpx_frame.len));
}
PesHeader header;
FrameRanges packet_payload_ranges;
if (GetPacketPayloadRanges(header, frame_ranges, &packet_payload_ranges) !=
true) {
std::fprintf(stderr, "Webm2Pes: Error preparing packet payload ranges!\n");
return false;
}
///
/// TODO: DEBUG/REMOVE
///
printf("-FRAME TOTAL LENGTH %ld--\n", vpx_frame.len);
for (const Range& frame_range : frame_ranges) {
printf("--frame range: off:%lu len:%lu\n", frame_range.offset,
frame_range.length);
}
for (const Range& payload_range : packet_payload_ranges) {
printf("---payload range: off:%lu len:%lu\n", payload_range.offset,
payload_range.length);
}
const std::int64_t khz90_pts = NanosecondsTo90KhzTicks(nanosecond_pts);
header.optional_header.SetPtsBits(khz90_pts);
bool write_pts = true;
for (const Range& packet_payload_range : packet_payload_ranges) {
header.packet_length =
header.optional_header.size_in_bytes() + packet_payload_range.length;
if (header.Write(output_file_.get(), write_pts) != true) {
std::fprintf(stderr, "Webm2Pes: packet header write failed.\n");
return false;
}
write_pts = false;
BCMVHeader bcmv_header(packet_payload_range.length);
if (bcmv_header.Write(output_file_.get()) != true) {
std::fprintf(stderr, "Webm2Pes: BCMV write failed.\n");
return false;
}
// Write the payload.
if (std::fwrite(frame_data.get() + packet_payload_range.offset, 1,
packet_payload_range.length,
output_file_.get()) != packet_payload_range.length) {
std::fprintf(stderr, "Webm2Pes: packet payload write failed.\n");
return false;
}
}
return true;
}
} // namespace libwebm
int main(int argc, const char* argv[]) {
if (argc < 3) {
Usage(argv);
return EXIT_FAILURE;
}
const std::string input_path = argv[1];
const std::string output_path = argv[2];
libwebm::Webm2Pes converter(input_path, output_path);
return converter.Convert() == true ? EXIT_SUCCESS : EXIT_FAILURE;
}

209
webm2pes.h Normal file
View File

@@ -0,0 +1,209 @@
// Copyright (c) 2015 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#ifndef LIBWEBM_WEBM2PES_H_
#define LIBWEBM_WEBM2PES_H_
#include <cstdio>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include "mkvparser.hpp"
#include "mkvreader.hpp"
namespace libwebm {
// Stores a value and its size in bits for writing into a PES Optional Header.
// Maximum size is 64 bits. Users may call the Check() method to perform minimal
// validation (size > 0 and <= 64).
struct PesHeaderField {
PesHeaderField(std::uint64_t value,
std::uint32_t size_in_bits,
std::uint8_t byte_index,
std::uint8_t bits_to_shift)
: bits(value),
num_bits(size_in_bits),
index(byte_index),
shift(bits_to_shift) {}
PesHeaderField() = delete;
PesHeaderField(const PesHeaderField&) = default;
PesHeaderField(PesHeaderField&&) = default;
~PesHeaderField() = default;
bool Check() const {
return num_bits > 0 && num_bits <= 64 && shift >= 0 && shift < 64;
}
// Value to be stored in the field.
std::uint64_t bits;
// Number of bits in the value.
const std::uint32_t num_bits;
// Index into the header for the byte in which |bits| will be written.
const std::uint8_t index;
// Number of bits to shift value before or'ing.
const std::uint8_t shift;
};
// Storage for PES Optional Header values. Fields written in order using sizes
// specified.
struct PesOptionalHeader {
// TODO(tomfinegan): The fields could be in an array, which would allow the
// code writing the optional header to iterate over the fields instead of
// having code for dealing with each one.
// 2 bits (marker): 2 ('10')
const PesHeaderField marker = PesHeaderField(2, 2, 0, 6);
// 2 bits (no scrambling): 0x0 ('00')
const PesHeaderField scrambling = PesHeaderField(0, 2, 0, 4);
// 1 bit (priority): 0x0 ('0')
const PesHeaderField priority = PesHeaderField(0, 1, 0, 3);
// TODO(tomfinegan): The BCMV header could be considered a sync word, and this
// field should be 1 when a sync word follows the packet. Clarify.
// 1 bit (data alignment): 0x0 ('0')
const PesHeaderField data_alignment = PesHeaderField(0, 1, 0, 2);
// 1 bit (copyright): 0x0 ('0')
const PesHeaderField copyright = PesHeaderField(0, 1, 0, 1);
// 1 bit (original/copy): 0x0 ('0')
const PesHeaderField original = PesHeaderField(0, 1, 0, 0);
// 1 bit (has_pts): 0x1 ('1')
const PesHeaderField has_pts = PesHeaderField(1, 1, 1, 7);
// 1 bit (has_dts): 0x0 ('0')
const PesHeaderField has_dts = PesHeaderField(0, 1, 1, 6);
// 6 bits (unused fields): 0x0 ('000000')
const PesHeaderField unused = PesHeaderField(0, 6, 1, 0);
// 8 bits (size of remaining data in the Header).
const PesHeaderField remaining_size = PesHeaderField(6, 8, 2, 0);
// PTS: 5 bytes
// 4 bits (flag: PTS present, but no DTS): 0x2 ('0010')
// 36 bits (90khz PTS):
// top 3 bits
// marker ('1')
// middle 15 bits
// marker ('1')
// bottom 15 bits
// marker ('1')
PesHeaderField pts = PesHeaderField(0, 40, 3, 0);
PesHeaderField stuffing_byte = PesHeaderField(0xFF, 8, 8, 0);
// PTS omitted in fragments. Size remains unchanged: More stuffing bytes.
bool fragment = false;
static std::size_t size_in_bytes() { return 9; }
// Writes |pts_90khz| to |pts| per format described at its declaration above.
void SetPtsBits(std::int64_t pts_90khz);
// Writes fields to |file| and returns true. Returns false when write or
// field value validation fails.
bool Write(std::FILE* file, bool write_pts) const;
};
// Describes custom 10 byte header that immediately follows the PES Optional
// Header in each PES packet output by Webm2Pes:
// 4 byte 'B' 'C' 'M' 'V'
// 4 byte big-endian length of frame
// 2 bytes 0 padding
struct BCMVHeader {
explicit BCMVHeader(std::uint32_t frame_length) : length(frame_length) {}
BCMVHeader() = delete;
BCMVHeader(const BCMVHeader&) = delete;
BCMVHeader(BCMVHeader&&) = delete;
~BCMVHeader() = default;
const std::uint8_t bcmv[4] = {'B', 'C', 'M', 'V'};
const std::uint32_t length;
static std::size_t size() { return 10; }
// Write the BCMV Header into the FILE stream.
bool Write(std::FILE* fileptr) const;
};
struct PesHeader {
const std::uint8_t start_code[4] = {
0x00,
0x00,
0x01, // 0x000001 is the PES packet start code prefix.
0xE0}; // 0xE0 is the minimum video stream ID.
std::uint16_t packet_length = 0; // Number of bytes _after_ this field.
PesOptionalHeader optional_header;
std::size_t size() const {
return optional_header.size_in_bytes() + BCMVHeader::size() +
6 /* start_code + packet_length */ + packet_length;
}
// Writes out the header to |file|. Calls PesOptionalHeader::Write() to write
// |optional_header| contents. Returns true when successful, false otherwise.
bool Write(std::FILE* file, bool write_pts) const;
};
// Converts the VP9 track of a WebM file to a Packetized Elementary Stream
// suitable for use in a MPEG2TS.
// https://en.wikipedia.org/wiki/Packetized_elementary_stream
// https://en.wikipedia.org/wiki/MPEG_transport_stream
class Webm2Pes {
public:
enum VideoCodec { VP8, VP9 };
Webm2Pes(const std::string& input_file, const std::string& output_file)
: input_file_name_(input_file), output_file_name_(output_file) {}
Webm2Pes() = delete;
Webm2Pes(const Webm2Pes&) = delete;
Webm2Pes(Webm2Pes&&) = delete;
~Webm2Pes() = default;
// Converts the VPx video stream to a PES and returns true. Returns false
// to report failure.
bool Convert();
private:
// fclose functor for wrapping FILE in std::unique_ptr.
struct FILEDeleter {
int operator()(FILE* f) {
if (f != nullptr)
return fclose(f);
return 0;
}
};
typedef std::unique_ptr<FILE, FILEDeleter> FilePtr;
bool WritePesPacket(const mkvparser::Block::Frame& vpx_frame,
double nanosecond_pts);
const std::string input_file_name_;
const std::string output_file_name_;
std::unique_ptr<mkvparser::Segment> webm_parser_;
mkvparser::MkvReader webm_reader_;
FilePtr output_file_;
// Video track num in the WebM file.
int video_track_num_ = 0;
// Video codec reported by CodecName from Video TrackEntry.
VideoCodec codec_;
// Input timecode scale.
std::int64_t timecode_scale_ = 1000000;
};
} // namespace libwebm
#endif // LIBWEBM_WEBM2PES_H_

View File

@@ -1,138 +1,155 @@
// 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
// 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,
kMkvTitle = 0x7BA9,
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,
kMkvDiscardPadding = 0x75A2,
// Track
kMkvTracks = 0x1654AE6B,
kMkvTrackEntry = 0xAE,
kMkvTrackNumber = 0xD7,
kMkvTrackUID = 0x73C5,
kMkvTrackType = 0x83,
kMkvFlagEnabled = 0xB9,
kMkvFlagDefault = 0x88,
kMkvFlagForced = 0x55AA,
kMkvFlagLacing = 0x9C,
kMkvDefaultDuration = 0x23E383,
kMkvMaxBlockAdditionID = 0x55EE,
kMkvName = 0x536E,
kMkvLanguage = 0x22B59C,
kMkvCodecID = 0x86,
kMkvCodecPrivate = 0x63A2,
kMkvCodecName = 0x258688,
kMkvCodecDelay = 0x56AA,
kMkvSeekPreRoll = 0x56BB,
// 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,
kMkvContentCompression = 0x5034,
kMkvContentCompAlgo = 0x4254,
kMkvContentCompSettings = 0x4255,
kMkvContentEncryption = 0x5035,
kMkvContentEncAlgo = 0x47E1,
kMkvContentEncKeyID = 0x47E2,
kMkvContentSignature = 0x47E3,
kMkvContentSigKeyID = 0x47E4,
kMkvContentSigAlgo = 0x47E5,
kMkvContentSigHashAlgo = 0x47E6,
kMkvContentEncAESSettings = 0x47E7,
kMkvAESSettingsCipherMode = 0x47E8,
kMkvAESSettingsCipherInitData = 0x47E9,
// end ContentEncodings
// Cueing Data
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,
// Tags
kMkvTags = 0x1254C367,
kMkvTag = 0x7373,
kMkvSimpleTag = 0x67C8,
kMkvTagName = 0x45A3,
kMkvTagString = 0x4487
};
} // end namespace mkvmuxer
#endif // WEBMIDS_HPP

View File

@@ -11,19 +11,19 @@
namespace libwebvtt {
// NOLINT'ing this enum because clang-format puts it in a single line which
// makes it look really unreadable.
enum {
kNUL = '\x00',
kSPACE = ' ',
kTAB = '\x09',
kLF = '\x0A',
kCR = '\x0D'
};
}; // NOLINT
Reader::~Reader() {
}
Reader::~Reader() {}
LineReader::~LineReader() {
}
LineReader::~LineReader() {}
int LineReader::GetLine(std::string* line_ptr) {
if (line_ptr == NULL)
@@ -101,11 +101,9 @@ int LineReader::GetLine(std::string* line_ptr) {
return 0;
}
Parser::Parser(Reader* r) : reader_(r), unget_(-1) {
}
Parser::Parser(Reader* r) : reader_(r), unget_(-1) {}
Parser::~Parser() {
}
Parser::~Parser() {}
int Parser::Init() {
int e = ParseBOM();
@@ -226,10 +224,7 @@ int Parser::Parse(Cue* cue) {
return -1;
}
e = ParseTimingsLine(&line,
arrow_pos,
&cue->start_time,
&cue->stop_time,
e = ParseTimingsLine(&line, arrow_pos, &cue->start_time, &cue->stop_time,
&cue->settings);
if (e) // error
@@ -269,9 +264,7 @@ int Parser::GetChar(char* c) {
return reader_->GetChar(c);
}
void Parser::UngetChar(char c) {
unget_ = static_cast<unsigned char>(c);
}
void Parser::UngetChar(char c) { unget_ = static_cast<unsigned char>(c); }
int Parser::ParseBOM() {
// Explanation of UTF-8 BOM:
@@ -303,12 +296,9 @@ int Parser::ParseBOM() {
return 0; // success
}
int Parser::ParseTimingsLine(
std::string* line_ptr,
std::string::size_type arrow_pos,
Time* start_time,
Time* stop_time,
Cue::settings_t* settings) {
int Parser::ParseTimingsLine(std::string* line_ptr,
std::string::size_type arrow_pos, Time* start_time,
Time* stop_time, Cue::settings_t* settings) {
if (line_ptr == NULL)
return -1;
@@ -353,10 +343,8 @@ int Parser::ParseTimingsLine(
return 0; // success
}
int Parser::ParseTime(
const std::string& line,
std::string::size_type* idx_ptr,
Time* time) {
int Parser::ParseTime(const std::string& line, std::string::size_type* idx_ptr,
Time* time) {
if (idx_ptr == NULL)
return -1;
@@ -511,10 +499,8 @@ int Parser::ParseTime(
return 0; // success
}
int Parser::ParseSettings(
const std::string& line,
std::string::size_type idx,
Cue::settings_t* settings) {
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())
@@ -573,7 +559,7 @@ int Parser::ParseSettings(
break;
if (c == ':') // suspicious when part of VALUE
return -1; // TODO(matthewjheaney): verify this behavior
return -1; // TODO(matthewjheaney): verify this behavior
s.value.push_back(c);
@@ -585,9 +571,8 @@ int Parser::ParseSettings(
}
}
int Parser::ParseNumber(
const std::string& line,
std::string::size_type* idx_ptr) {
int Parser::ParseNumber(const std::string& line,
std::string::size_type* idx_ptr) {
if (idx_ptr == NULL)
return -1;
@@ -656,17 +641,11 @@ bool Time::operator<(const Time& rhs) const {
return (milliseconds < rhs.milliseconds);
}
bool Time::operator>(const Time& rhs) const {
return rhs.operator<(*this);
}
bool Time::operator>(const Time& rhs) const { return rhs.operator<(*this); }
bool Time::operator<=(const Time& rhs) const {
return !this->operator>(rhs);
}
bool Time::operator<=(const Time& rhs) const { return !this->operator>(rhs); }
bool Time::operator>=(const Time& rhs) const {
return !this->operator<(rhs);
}
bool Time::operator>=(const Time& rhs) const { return !this->operator<(rhs); }
presentation_t Time::presentation() const {
const presentation_t h = 1000LL * 3600LL * presentation_t(hours);
@@ -686,8 +665,8 @@ Time& Time::presentation(presentation_t d) {
return *this;
}
seconds = d / 1000;
milliseconds = d - 1000 * seconds;
seconds = static_cast<int>(d / 1000);
milliseconds = static_cast<int>(d - 1000 * seconds);
minutes = seconds / 60;
seconds -= 60 * minutes;
@@ -711,9 +690,7 @@ Time Time::operator+(presentation_t d) const {
return t;
}
Time& Time::operator-=(presentation_t d) {
return this->operator+=(-d);
}
Time& Time::operator-=(presentation_t d) { return this->operator+=(-d); }
presentation_t Time::operator-(const Time& t) const {
const presentation_t rhs = t.presentation();

View File

@@ -120,8 +120,7 @@ class Parser : private LineReader {
//
static int ParseTimingsLine(std::string* line,
std::string::size_type arrow_pos,
Time* start_time,
Time* stop_time,
Time* start_time, Time* stop_time,
Cue::settings_t* settings);
// Parse a single time specifier (from the timings line), starting
@@ -129,23 +128,20 @@ class Parser : private LineReader {
// is detected. The function modifies offset |off| by the number of
// characters consumed. Returns negative if error, 0 on success.
//
static int ParseTime(const std::string& line,
std::string::size_type* off,
static int ParseTime(const std::string& line, std::string::size_type* off,
Time* time);
// Parse the cue settings from the timings line, starting at the
// given offset. Returns negative if error, 0 on success.
//
static int ParseSettings(const std::string& line,
std::string::size_type off,
static int ParseSettings(const std::string& line, std::string::size_type off,
Cue::settings_t* settings);
// Parse a non-negative integer from the characters in |line| beginning
// at offset |off|. The function increments |off| by the number
// of characters consumed. Returns the value, or negative if error.
//
static int ParseNumber(const std::string& line,
std::string::size_type* off);
static int ParseNumber(const std::string& line, std::string::size_type* off);
Reader* const reader_;