OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 The WebM project authors. All Rights Reserved. |
| 2 // |
| 3 // Use of this source code is governed by a BSD-style license |
| 4 // that can be found in the LICENSE file in the root of the source |
| 5 // tree. An additional intellectual property rights grant can be found |
| 6 // in the file PATENTS. All contributing project authors may |
| 7 // be found in the AUTHORS file in the root of the source tree. |
| 8 |
| 9 #ifndef MKVPARSER_HPP |
| 10 #define MKVPARSER_HPP |
| 11 |
| 12 #include <cstdlib> |
| 13 #include <cstdio> |
| 14 #include <cstddef> |
| 15 |
| 16 namespace mkvparser |
| 17 { |
| 18 |
| 19 const int E_FILE_FORMAT_INVALID = -2; |
| 20 const int E_BUFFER_NOT_FULL = -3; |
| 21 |
| 22 class IMkvReader |
| 23 { |
| 24 public: |
| 25 virtual int Read(long long pos, long len, unsigned char* buf) = 0; |
| 26 virtual int Length(long long* total, long long* available) = 0; |
| 27 protected: |
| 28 virtual ~IMkvReader(); |
| 29 }; |
| 30 |
| 31 long long GetUIntLength(IMkvReader*, long long, long&); |
| 32 long long ReadUInt(IMkvReader*, long long, long&); |
| 33 long long UnserializeUInt(IMkvReader*, long long pos, long long size); |
| 34 |
| 35 long UnserializeFloat(IMkvReader*, long long pos, long long size, double&); |
| 36 long UnserializeInt(IMkvReader*, long long pos, long len, long long& result); |
| 37 |
| 38 long UnserializeString( |
| 39 IMkvReader*, |
| 40 long long pos, |
| 41 long long size, |
| 42 char*& str); |
| 43 |
| 44 long ParseElementHeader( |
| 45 IMkvReader* pReader, |
| 46 long long& pos, //consume id and size fields |
| 47 long long stop, //if you know size of element's parent |
| 48 long long& id, |
| 49 long long& size); |
| 50 |
| 51 bool Match(IMkvReader*, long long&, unsigned long, long long&); |
| 52 bool Match(IMkvReader*, long long&, unsigned long, unsigned char*&, size_t&); |
| 53 |
| 54 void GetVersion(int& major, int& minor, int& build, int& revision); |
| 55 |
| 56 struct EBMLHeader |
| 57 { |
| 58 EBMLHeader(); |
| 59 ~EBMLHeader(); |
| 60 long long m_version; |
| 61 long long m_readVersion; |
| 62 long long m_maxIdLength; |
| 63 long long m_maxSizeLength; |
| 64 char* m_docType; |
| 65 long long m_docTypeVersion; |
| 66 long long m_docTypeReadVersion; |
| 67 |
| 68 long long Parse(IMkvReader*, long long&); |
| 69 void Init(); |
| 70 }; |
| 71 |
| 72 |
| 73 class Segment; |
| 74 class Track; |
| 75 class Cluster; |
| 76 |
| 77 class Block |
| 78 { |
| 79 Block(const Block&); |
| 80 Block& operator=(const Block&); |
| 81 |
| 82 public: |
| 83 const long long m_start; |
| 84 const long long m_size; |
| 85 |
| 86 Block(long long start, long long size, long long discard_padding); |
| 87 ~Block(); |
| 88 |
| 89 long Parse(const Cluster*); |
| 90 |
| 91 long long GetTrackNumber() const; |
| 92 long long GetTimeCode(const Cluster*) const; //absolute, but not scaled |
| 93 long long GetTime(const Cluster*) const; //absolute, and scaled (ns) |
| 94 bool IsKey() const; |
| 95 void SetKey(bool); |
| 96 bool IsInvisible() const; |
| 97 |
| 98 enum Lacing { kLacingNone, kLacingXiph, kLacingFixed, kLacingEbml }; |
| 99 Lacing GetLacing() const; |
| 100 |
| 101 int GetFrameCount() const; //to index frames: [0, count) |
| 102 |
| 103 struct Frame |
| 104 { |
| 105 long long pos; //absolute offset |
| 106 long len; |
| 107 |
| 108 long Read(IMkvReader*, unsigned char*) const; |
| 109 }; |
| 110 |
| 111 const Frame& GetFrame(int frame_index) const; |
| 112 |
| 113 long long GetDiscardPadding() const; |
| 114 |
| 115 private: |
| 116 long long m_track; //Track::Number() |
| 117 short m_timecode; //relative to cluster |
| 118 unsigned char m_flags; |
| 119 |
| 120 Frame* m_frames; |
| 121 int m_frame_count; |
| 122 |
| 123 protected: |
| 124 const long long m_discard_padding; |
| 125 }; |
| 126 |
| 127 |
| 128 class BlockEntry |
| 129 { |
| 130 BlockEntry(const BlockEntry&); |
| 131 BlockEntry& operator=(const BlockEntry&); |
| 132 |
| 133 protected: |
| 134 BlockEntry(Cluster*, long index); |
| 135 |
| 136 public: |
| 137 virtual ~BlockEntry(); |
| 138 |
| 139 bool EOS() const; |
| 140 const Cluster* GetCluster() const; |
| 141 long GetIndex() const; |
| 142 virtual const Block* GetBlock() const = 0; |
| 143 |
| 144 enum Kind { kBlockEOS, kBlockSimple, kBlockGroup }; |
| 145 virtual Kind GetKind() const = 0; |
| 146 |
| 147 protected: |
| 148 Cluster* const m_pCluster; |
| 149 const long m_index; |
| 150 |
| 151 }; |
| 152 |
| 153 |
| 154 class SimpleBlock : public BlockEntry |
| 155 { |
| 156 SimpleBlock(const SimpleBlock&); |
| 157 SimpleBlock& operator=(const SimpleBlock&); |
| 158 |
| 159 public: |
| 160 SimpleBlock(Cluster*, long index, long long start, long long size); |
| 161 long Parse(); |
| 162 |
| 163 Kind GetKind() const; |
| 164 const Block* GetBlock() const; |
| 165 |
| 166 protected: |
| 167 Block m_block; |
| 168 |
| 169 }; |
| 170 |
| 171 |
| 172 class BlockGroup : public BlockEntry |
| 173 { |
| 174 BlockGroup(const BlockGroup&); |
| 175 BlockGroup& operator=(const BlockGroup&); |
| 176 |
| 177 public: |
| 178 BlockGroup( |
| 179 Cluster*, |
| 180 long index, |
| 181 long long block_start, //absolute pos of block's payload |
| 182 long long block_size, //size of block's payload |
| 183 long long prev, |
| 184 long long next, |
| 185 long long duration, |
| 186 long long discard_padding); |
| 187 |
| 188 long Parse(); |
| 189 |
| 190 Kind GetKind() const; |
| 191 const Block* GetBlock() const; |
| 192 |
| 193 long long GetPrevTimeCode() const; //relative to block's time |
| 194 long long GetNextTimeCode() const; //as above |
| 195 long long GetDurationTimeCode() const; |
| 196 |
| 197 private: |
| 198 Block m_block; |
| 199 const long long m_prev; |
| 200 const long long m_next; |
| 201 const long long m_duration; |
| 202 }; |
| 203 |
| 204 /////////////////////////////////////////////////////////////// |
| 205 // ContentEncoding element |
| 206 // Elements used to describe if the track data has been encrypted or |
| 207 // compressed with zlib or header stripping. |
| 208 class ContentEncoding { |
| 209 public: |
| 210 enum { |
| 211 kCTR = 1 |
| 212 }; |
| 213 |
| 214 ContentEncoding(); |
| 215 ~ContentEncoding(); |
| 216 |
| 217 // ContentCompression element names |
| 218 struct ContentCompression { |
| 219 ContentCompression(); |
| 220 ~ContentCompression(); |
| 221 |
| 222 unsigned long long algo; |
| 223 unsigned char* settings; |
| 224 long long settings_len; |
| 225 }; |
| 226 |
| 227 // ContentEncAESSettings element names |
| 228 struct ContentEncAESSettings { |
| 229 ContentEncAESSettings() : cipher_mode(kCTR) {} |
| 230 ~ContentEncAESSettings() {} |
| 231 |
| 232 unsigned long long cipher_mode; |
| 233 }; |
| 234 |
| 235 // ContentEncryption element names |
| 236 struct ContentEncryption { |
| 237 ContentEncryption(); |
| 238 ~ContentEncryption(); |
| 239 |
| 240 unsigned long long algo; |
| 241 unsigned char* key_id; |
| 242 long long key_id_len; |
| 243 unsigned char* signature; |
| 244 long long signature_len; |
| 245 unsigned char* sig_key_id; |
| 246 long long sig_key_id_len; |
| 247 unsigned long long sig_algo; |
| 248 unsigned long long sig_hash_algo; |
| 249 |
| 250 ContentEncAESSettings aes_settings; |
| 251 }; |
| 252 |
| 253 // Returns ContentCompression represented by |idx|. Returns NULL if |idx| |
| 254 // is out of bounds. |
| 255 const ContentCompression* GetCompressionByIndex(unsigned long idx) const; |
| 256 |
| 257 // Returns number of ContentCompression elements in this ContentEncoding |
| 258 // element. |
| 259 unsigned long GetCompressionCount() const; |
| 260 |
| 261 // Parses the ContentCompression element from |pReader|. |start| is the |
| 262 // starting offset of the ContentCompression payload. |size| is the size in |
| 263 // bytes of the ContentCompression payload. |compression| is where the parse
d |
| 264 // values will be stored. |
| 265 long ParseCompressionEntry(long long start, |
| 266 long long size, |
| 267 IMkvReader* pReader, |
| 268 ContentCompression* compression); |
| 269 |
| 270 // Returns ContentEncryption represented by |idx|. Returns NULL if |idx| |
| 271 // is out of bounds. |
| 272 const ContentEncryption* GetEncryptionByIndex(unsigned long idx) const; |
| 273 |
| 274 // Returns number of ContentEncryption elements in this ContentEncoding |
| 275 // element. |
| 276 unsigned long GetEncryptionCount() const; |
| 277 |
| 278 // Parses the ContentEncAESSettings element from |pReader|. |start| is the |
| 279 // starting offset of the ContentEncAESSettings payload. |size| is the |
| 280 // size in bytes of the ContentEncAESSettings payload. |encryption| is |
| 281 // where the parsed values will be stored. |
| 282 long ParseContentEncAESSettingsEntry(long long start, |
| 283 long long size, |
| 284 IMkvReader* pReader, |
| 285 ContentEncAESSettings* aes); |
| 286 |
| 287 // Parses the ContentEncoding element from |pReader|. |start| is the |
| 288 // starting offset of the ContentEncoding payload. |size| is the size in |
| 289 // bytes of the ContentEncoding payload. Returns true on success. |
| 290 long ParseContentEncodingEntry(long long start, |
| 291 long long size, |
| 292 IMkvReader* pReader); |
| 293 |
| 294 // Parses the ContentEncryption element from |pReader|. |start| is the |
| 295 // starting offset of the ContentEncryption payload. |size| is the size in |
| 296 // bytes of the ContentEncryption payload. |encryption| is where the parsed |
| 297 // values will be stored. |
| 298 long ParseEncryptionEntry(long long start, |
| 299 long long size, |
| 300 IMkvReader* pReader, |
| 301 ContentEncryption* encryption); |
| 302 |
| 303 unsigned long long encoding_order() const { return encoding_order_; } |
| 304 unsigned long long encoding_scope() const { return encoding_scope_; } |
| 305 unsigned long long encoding_type() const { return encoding_type_; } |
| 306 |
| 307 private: |
| 308 // Member variables for list of ContentCompression elements. |
| 309 ContentCompression** compression_entries_; |
| 310 ContentCompression** compression_entries_end_; |
| 311 |
| 312 // Member variables for list of ContentEncryption elements. |
| 313 ContentEncryption** encryption_entries_; |
| 314 ContentEncryption** encryption_entries_end_; |
| 315 |
| 316 // ContentEncoding element names |
| 317 unsigned long long encoding_order_; |
| 318 unsigned long long encoding_scope_; |
| 319 unsigned long long encoding_type_; |
| 320 |
| 321 // LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncoding); |
| 322 ContentEncoding(const ContentEncoding&); |
| 323 ContentEncoding& operator=(const ContentEncoding&); |
| 324 }; |
| 325 |
| 326 class Track |
| 327 { |
| 328 Track(const Track&); |
| 329 Track& operator=(const Track&); |
| 330 |
| 331 public: |
| 332 class Info; |
| 333 static long Create( |
| 334 Segment*, |
| 335 const Info&, |
| 336 long long element_start, |
| 337 long long element_size, |
| 338 Track*&); |
| 339 |
| 340 enum Type { |
| 341 kVideo = 1, |
| 342 kAudio = 2, |
| 343 kSubtitle = 0x11, |
| 344 kMetadata = 0x21 |
| 345 }; |
| 346 |
| 347 Segment* const m_pSegment; |
| 348 const long long m_element_start; |
| 349 const long long m_element_size; |
| 350 virtual ~Track(); |
| 351 |
| 352 long GetType() const; |
| 353 long GetNumber() const; |
| 354 unsigned long long GetUid() const; |
| 355 const char* GetNameAsUTF8() const; |
| 356 const char* GetLanguage() const; |
| 357 const char* GetCodecNameAsUTF8() const; |
| 358 const char* GetCodecId() const; |
| 359 const unsigned char* GetCodecPrivate(size_t&) const; |
| 360 bool GetLacing() const; |
| 361 unsigned long long GetDefaultDuration() const; |
| 362 unsigned long long GetCodecDelay() const; |
| 363 unsigned long long GetSeekPreRoll() const; |
| 364 |
| 365 const BlockEntry* GetEOS() const; |
| 366 |
| 367 struct Settings |
| 368 { |
| 369 long long start; |
| 370 long long size; |
| 371 }; |
| 372 |
| 373 class Info |
| 374 { |
| 375 public: |
| 376 Info(); |
| 377 ~Info(); |
| 378 int Copy(Info&) const; |
| 379 void Clear(); |
| 380 long type; |
| 381 long number; |
| 382 unsigned long long uid; |
| 383 unsigned long long defaultDuration; |
| 384 unsigned long long codecDelay; |
| 385 unsigned long long seekPreRoll; |
| 386 char* nameAsUTF8; |
| 387 char* language; |
| 388 char* codecId; |
| 389 char* codecNameAsUTF8; |
| 390 unsigned char* codecPrivate; |
| 391 size_t codecPrivateSize; |
| 392 bool lacing; |
| 393 Settings settings; |
| 394 |
| 395 private: |
| 396 Info(const Info&); |
| 397 Info& operator=(const Info&); |
| 398 int CopyStr(char* Info::*str, Info&) const; |
| 399 }; |
| 400 |
| 401 long GetFirst(const BlockEntry*&) const; |
| 402 long GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const; |
| 403 virtual bool VetEntry(const BlockEntry*) const; |
| 404 virtual long Seek(long long time_ns, const BlockEntry*&) const; |
| 405 |
| 406 const ContentEncoding* GetContentEncodingByIndex(unsigned long idx) const; |
| 407 unsigned long GetContentEncodingCount() const; |
| 408 |
| 409 long ParseContentEncodingsEntry(long long start, long long size); |
| 410 |
| 411 protected: |
| 412 Track( |
| 413 Segment*, |
| 414 long long element_start, |
| 415 long long element_size); |
| 416 |
| 417 Info m_info; |
| 418 |
| 419 class EOSBlock : public BlockEntry |
| 420 { |
| 421 public: |
| 422 EOSBlock(); |
| 423 |
| 424 Kind GetKind() const; |
| 425 const Block* GetBlock() const; |
| 426 }; |
| 427 |
| 428 EOSBlock m_eos; |
| 429 |
| 430 private: |
| 431 ContentEncoding** content_encoding_entries_; |
| 432 ContentEncoding** content_encoding_entries_end_; |
| 433 }; |
| 434 |
| 435 |
| 436 class VideoTrack : public Track |
| 437 { |
| 438 VideoTrack(const VideoTrack&); |
| 439 VideoTrack& operator=(const VideoTrack&); |
| 440 |
| 441 VideoTrack( |
| 442 Segment*, |
| 443 long long element_start, |
| 444 long long element_size); |
| 445 |
| 446 public: |
| 447 static long Parse( |
| 448 Segment*, |
| 449 const Info&, |
| 450 long long element_start, |
| 451 long long element_size, |
| 452 VideoTrack*&); |
| 453 |
| 454 long long GetWidth() const; |
| 455 long long GetHeight() const; |
| 456 double GetFrameRate() const; |
| 457 |
| 458 bool VetEntry(const BlockEntry*) const; |
| 459 long Seek(long long time_ns, const BlockEntry*&) const; |
| 460 |
| 461 private: |
| 462 long long m_width; |
| 463 long long m_height; |
| 464 double m_rate; |
| 465 |
| 466 }; |
| 467 |
| 468 |
| 469 class AudioTrack : public Track |
| 470 { |
| 471 AudioTrack(const AudioTrack&); |
| 472 AudioTrack& operator=(const AudioTrack&); |
| 473 |
| 474 AudioTrack( |
| 475 Segment*, |
| 476 long long element_start, |
| 477 long long element_size); |
| 478 public: |
| 479 static long Parse( |
| 480 Segment*, |
| 481 const Info&, |
| 482 long long element_start, |
| 483 long long element_size, |
| 484 AudioTrack*&); |
| 485 |
| 486 double GetSamplingRate() const; |
| 487 long long GetChannels() const; |
| 488 long long GetBitDepth() const; |
| 489 |
| 490 private: |
| 491 double m_rate; |
| 492 long long m_channels; |
| 493 long long m_bitDepth; |
| 494 }; |
| 495 |
| 496 |
| 497 class Tracks |
| 498 { |
| 499 Tracks(const Tracks&); |
| 500 Tracks& operator=(const Tracks&); |
| 501 |
| 502 public: |
| 503 Segment* const m_pSegment; |
| 504 const long long m_start; |
| 505 const long long m_size; |
| 506 const long long m_element_start; |
| 507 const long long m_element_size; |
| 508 |
| 509 Tracks( |
| 510 Segment*, |
| 511 long long start, |
| 512 long long size, |
| 513 long long element_start, |
| 514 long long element_size); |
| 515 |
| 516 ~Tracks(); |
| 517 |
| 518 long Parse(); |
| 519 |
| 520 unsigned long GetTracksCount() const; |
| 521 |
| 522 const Track* GetTrackByNumber(long tn) const; |
| 523 const Track* GetTrackByIndex(unsigned long idx) const; |
| 524 |
| 525 private: |
| 526 Track** m_trackEntries; |
| 527 Track** m_trackEntriesEnd; |
| 528 |
| 529 long ParseTrackEntry( |
| 530 long long payload_start, |
| 531 long long payload_size, |
| 532 long long element_start, |
| 533 long long element_size, |
| 534 Track*&) const; |
| 535 |
| 536 }; |
| 537 |
| 538 |
| 539 class Chapters |
| 540 { |
| 541 Chapters(const Chapters&); |
| 542 Chapters& operator=(const Chapters&); |
| 543 |
| 544 public: |
| 545 Segment* const m_pSegment; |
| 546 const long long m_start; |
| 547 const long long m_size; |
| 548 const long long m_element_start; |
| 549 const long long m_element_size; |
| 550 |
| 551 Chapters( |
| 552 Segment*, |
| 553 long long payload_start, |
| 554 long long payload_size, |
| 555 long long element_start, |
| 556 long long element_size); |
| 557 |
| 558 ~Chapters(); |
| 559 |
| 560 long Parse(); |
| 561 |
| 562 class Atom; |
| 563 class Edition; |
| 564 |
| 565 class Display |
| 566 { |
| 567 friend class Atom; |
| 568 Display(); |
| 569 Display(const Display&); |
| 570 ~Display(); |
| 571 Display& operator=(const Display&); |
| 572 public: |
| 573 const char* GetString() const; |
| 574 const char* GetLanguage() const; |
| 575 const char* GetCountry() const; |
| 576 private: |
| 577 void Init(); |
| 578 void ShallowCopy(Display&) const; |
| 579 void Clear(); |
| 580 long Parse(IMkvReader*, long long pos, long long size); |
| 581 |
| 582 char* m_string; |
| 583 char* m_language; |
| 584 char* m_country; |
| 585 }; |
| 586 |
| 587 class Atom |
| 588 { |
| 589 friend class Edition; |
| 590 Atom(); |
| 591 Atom(const Atom&); |
| 592 ~Atom(); |
| 593 Atom& operator=(const Atom&); |
| 594 public: |
| 595 unsigned long long GetUID() const; |
| 596 const char* GetStringUID() const; |
| 597 |
| 598 long long GetStartTimecode() const; |
| 599 long long GetStopTimecode() const; |
| 600 |
| 601 long long GetStartTime(const Chapters*) const; |
| 602 long long GetStopTime(const Chapters*) const; |
| 603 |
| 604 int GetDisplayCount() const; |
| 605 const Display* GetDisplay(int index) const; |
| 606 private: |
| 607 void Init(); |
| 608 void ShallowCopy(Atom&) const; |
| 609 void Clear(); |
| 610 long Parse(IMkvReader*, long long pos, long long size); |
| 611 static long long GetTime(const Chapters*, long long timecode); |
| 612 |
| 613 long ParseDisplay(IMkvReader*, long long pos, long long size); |
| 614 bool ExpandDisplaysArray(); |
| 615 |
| 616 char* m_string_uid; |
| 617 unsigned long long m_uid; |
| 618 long long m_start_timecode; |
| 619 long long m_stop_timecode; |
| 620 |
| 621 Display* m_displays; |
| 622 int m_displays_size; |
| 623 int m_displays_count; |
| 624 }; |
| 625 |
| 626 class Edition |
| 627 { |
| 628 friend class Chapters; |
| 629 Edition(); |
| 630 Edition(const Edition&); |
| 631 ~Edition(); |
| 632 Edition& operator=(const Edition&); |
| 633 public: |
| 634 int GetAtomCount() const; |
| 635 const Atom* GetAtom(int index) const; |
| 636 private: |
| 637 void Init(); |
| 638 void ShallowCopy(Edition&) const; |
| 639 void Clear(); |
| 640 long Parse(IMkvReader*, long long pos, long long size); |
| 641 |
| 642 long ParseAtom(IMkvReader*, long long pos, long long size); |
| 643 bool ExpandAtomsArray(); |
| 644 |
| 645 Atom* m_atoms; |
| 646 int m_atoms_size; |
| 647 int m_atoms_count; |
| 648 }; |
| 649 |
| 650 int GetEditionCount() const; |
| 651 const Edition* GetEdition(int index) const; |
| 652 |
| 653 private: |
| 654 long ParseEdition(long long pos, long long size); |
| 655 bool ExpandEditionsArray(); |
| 656 |
| 657 Edition* m_editions; |
| 658 int m_editions_size; |
| 659 int m_editions_count; |
| 660 |
| 661 }; |
| 662 |
| 663 |
| 664 class SegmentInfo |
| 665 { |
| 666 SegmentInfo(const SegmentInfo&); |
| 667 SegmentInfo& operator=(const SegmentInfo&); |
| 668 |
| 669 public: |
| 670 Segment* const m_pSegment; |
| 671 const long long m_start; |
| 672 const long long m_size; |
| 673 const long long m_element_start; |
| 674 const long long m_element_size; |
| 675 |
| 676 SegmentInfo( |
| 677 Segment*, |
| 678 long long start, |
| 679 long long size, |
| 680 long long element_start, |
| 681 long long element_size); |
| 682 |
| 683 ~SegmentInfo(); |
| 684 |
| 685 long Parse(); |
| 686 |
| 687 long long GetTimeCodeScale() const; |
| 688 long long GetDuration() const; //scaled |
| 689 const char* GetMuxingAppAsUTF8() const; |
| 690 const char* GetWritingAppAsUTF8() const; |
| 691 const char* GetTitleAsUTF8() const; |
| 692 |
| 693 private: |
| 694 long long m_timecodeScale; |
| 695 double m_duration; |
| 696 char* m_pMuxingAppAsUTF8; |
| 697 char* m_pWritingAppAsUTF8; |
| 698 char* m_pTitleAsUTF8; |
| 699 }; |
| 700 |
| 701 |
| 702 class SeekHead |
| 703 { |
| 704 SeekHead(const SeekHead&); |
| 705 SeekHead& operator=(const SeekHead&); |
| 706 |
| 707 public: |
| 708 Segment* const m_pSegment; |
| 709 const long long m_start; |
| 710 const long long m_size; |
| 711 const long long m_element_start; |
| 712 const long long m_element_size; |
| 713 |
| 714 SeekHead( |
| 715 Segment*, |
| 716 long long start, |
| 717 long long size, |
| 718 long long element_start, |
| 719 long long element_size); |
| 720 |
| 721 ~SeekHead(); |
| 722 |
| 723 long Parse(); |
| 724 |
| 725 struct Entry |
| 726 { |
| 727 //the SeekHead entry payload |
| 728 long long id; |
| 729 long long pos; |
| 730 |
| 731 //absolute pos of SeekEntry ID |
| 732 long long element_start; |
| 733 |
| 734 //SeekEntry ID size + size size + payload |
| 735 long long element_size; |
| 736 }; |
| 737 |
| 738 int GetCount() const; |
| 739 const Entry* GetEntry(int idx) const; |
| 740 |
| 741 struct VoidElement |
| 742 { |
| 743 //absolute pos of Void ID |
| 744 long long element_start; |
| 745 |
| 746 //ID size + size size + payload size |
| 747 long long element_size; |
| 748 }; |
| 749 |
| 750 int GetVoidElementCount() const; |
| 751 const VoidElement* GetVoidElement(int idx) const; |
| 752 |
| 753 private: |
| 754 Entry* m_entries; |
| 755 int m_entry_count; |
| 756 |
| 757 VoidElement* m_void_elements; |
| 758 int m_void_element_count; |
| 759 |
| 760 static bool ParseEntry( |
| 761 IMkvReader*, |
| 762 long long pos, //payload |
| 763 long long size, |
| 764 Entry*); |
| 765 |
| 766 }; |
| 767 |
| 768 class Cues; |
| 769 class CuePoint |
| 770 { |
| 771 friend class Cues; |
| 772 |
| 773 CuePoint(long, long long); |
| 774 ~CuePoint(); |
| 775 |
| 776 CuePoint(const CuePoint&); |
| 777 CuePoint& operator=(const CuePoint&); |
| 778 |
| 779 public: |
| 780 long long m_element_start; |
| 781 long long m_element_size; |
| 782 |
| 783 void Load(IMkvReader*); |
| 784 |
| 785 long long GetTimeCode() const; //absolute but unscaled |
| 786 long long GetTime(const Segment*) const; //absolute and scaled (ns units) |
| 787 |
| 788 struct TrackPosition |
| 789 { |
| 790 long long m_track; |
| 791 long long m_pos; //of cluster |
| 792 long long m_block; |
| 793 //codec_state //defaults to 0 |
| 794 //reference = clusters containing req'd referenced blocks |
| 795 // reftime = timecode of the referenced block |
| 796 |
| 797 void Parse(IMkvReader*, long long, long long); |
| 798 }; |
| 799 |
| 800 const TrackPosition* Find(const Track*) const; |
| 801 |
| 802 private: |
| 803 const long m_index; |
| 804 long long m_timecode; |
| 805 TrackPosition* m_track_positions; |
| 806 size_t m_track_positions_count; |
| 807 |
| 808 }; |
| 809 |
| 810 |
| 811 class Cues |
| 812 { |
| 813 friend class Segment; |
| 814 |
| 815 Cues( |
| 816 Segment*, |
| 817 long long start, |
| 818 long long size, |
| 819 long long element_start, |
| 820 long long element_size); |
| 821 ~Cues(); |
| 822 |
| 823 Cues(const Cues&); |
| 824 Cues& operator=(const Cues&); |
| 825 |
| 826 public: |
| 827 Segment* const m_pSegment; |
| 828 const long long m_start; |
| 829 const long long m_size; |
| 830 const long long m_element_start; |
| 831 const long long m_element_size; |
| 832 |
| 833 bool Find( //lower bound of time_ns |
| 834 long long time_ns, |
| 835 const Track*, |
| 836 const CuePoint*&, |
| 837 const CuePoint::TrackPosition*&) const; |
| 838 |
| 839 #if 0 |
| 840 bool FindNext( //upper_bound of time_ns |
| 841 long long time_ns, |
| 842 const Track*, |
| 843 const CuePoint*&, |
| 844 const CuePoint::TrackPosition*&) const; |
| 845 #endif |
| 846 |
| 847 const CuePoint* GetFirst() const; |
| 848 const CuePoint* GetLast() const; |
| 849 const CuePoint* GetNext(const CuePoint*) const; |
| 850 |
| 851 const BlockEntry* GetBlock( |
| 852 const CuePoint*, |
| 853 const CuePoint::TrackPosition*) const; |
| 854 |
| 855 bool LoadCuePoint() const; |
| 856 long GetCount() const; //loaded only |
| 857 //long GetTotal() const; //loaded + preloaded |
| 858 bool DoneParsing() const; |
| 859 |
| 860 private: |
| 861 void Init() const; |
| 862 void PreloadCuePoint(long&, long long) const; |
| 863 |
| 864 mutable CuePoint** m_cue_points; |
| 865 mutable long m_count; |
| 866 mutable long m_preload_count; |
| 867 mutable long long m_pos; |
| 868 |
| 869 }; |
| 870 |
| 871 |
| 872 class Cluster |
| 873 { |
| 874 friend class Segment; |
| 875 |
| 876 Cluster(const Cluster&); |
| 877 Cluster& operator=(const Cluster&); |
| 878 |
| 879 public: |
| 880 Segment* const m_pSegment; |
| 881 |
| 882 public: |
| 883 static Cluster* Create( |
| 884 Segment*, |
| 885 long index, //index in segment |
| 886 long long off); //offset relative to segment |
| 887 //long long element_size); |
| 888 |
| 889 Cluster(); //EndOfStream |
| 890 ~Cluster(); |
| 891 |
| 892 bool EOS() const; |
| 893 |
| 894 long long GetTimeCode() const; //absolute, but not scaled |
| 895 long long GetTime() const; //absolute, and scaled (nanosecond units) |
| 896 long long GetFirstTime() const; //time (ns) of first (earliest) block |
| 897 long long GetLastTime() const; //time (ns) of last (latest) block |
| 898 |
| 899 long GetFirst(const BlockEntry*&) const; |
| 900 long GetLast(const BlockEntry*&) const; |
| 901 long GetNext(const BlockEntry* curr, const BlockEntry*& next) const; |
| 902 |
| 903 const BlockEntry* GetEntry(const Track*, long long ns = -1) const; |
| 904 const BlockEntry* GetEntry( |
| 905 const CuePoint&, |
| 906 const CuePoint::TrackPosition&) const; |
| 907 //const BlockEntry* GetMaxKey(const VideoTrack*) const; |
| 908 |
| 909 // static bool HasBlockEntries(const Segment*, long long); |
| 910 |
| 911 static long HasBlockEntries( |
| 912 const Segment*, |
| 913 long long idoff, |
| 914 long long& pos, |
| 915 long& size); |
| 916 |
| 917 long GetEntryCount() const; |
| 918 |
| 919 long Load(long long& pos, long& size) const; |
| 920 |
| 921 long Parse(long long& pos, long& size) const; |
| 922 long GetEntry(long index, const mkvparser::BlockEntry*&) const; |
| 923 |
| 924 protected: |
| 925 Cluster( |
| 926 Segment*, |
| 927 long index, |
| 928 long long element_start); |
| 929 //long long element_size); |
| 930 |
| 931 public: |
| 932 const long long m_element_start; |
| 933 long long GetPosition() const; //offset relative to segment |
| 934 |
| 935 long GetIndex() const; |
| 936 long long GetElementSize() const; |
| 937 //long long GetPayloadSize() const; |
| 938 |
| 939 //long long Unparsed() const; |
| 940 |
| 941 private: |
| 942 long m_index; |
| 943 mutable long long m_pos; |
| 944 //mutable long long m_size; |
| 945 mutable long long m_element_size; |
| 946 mutable long long m_timecode; |
| 947 mutable BlockEntry** m_entries; |
| 948 mutable long m_entries_size; |
| 949 mutable long m_entries_count; |
| 950 |
| 951 long ParseSimpleBlock(long long, long long&, long&); |
| 952 long ParseBlockGroup(long long, long long&, long&); |
| 953 |
| 954 long CreateBlock(long long id, long long pos, long long size, |
| 955 long long discard_padding); |
| 956 long CreateBlockGroup(long long start_offset, long long size, |
| 957 long long discard_padding); |
| 958 long CreateSimpleBlock(long long, long long); |
| 959 |
| 960 }; |
| 961 |
| 962 |
| 963 class Segment |
| 964 { |
| 965 friend class Cues; |
| 966 friend class Track; |
| 967 friend class VideoTrack; |
| 968 |
| 969 Segment(const Segment&); |
| 970 Segment& operator=(const Segment&); |
| 971 |
| 972 private: |
| 973 Segment( |
| 974 IMkvReader*, |
| 975 long long elem_start, |
| 976 //long long elem_size, |
| 977 long long pos, |
| 978 long long size); |
| 979 |
| 980 public: |
| 981 IMkvReader* const m_pReader; |
| 982 const long long m_element_start; |
| 983 //const long long m_element_size; |
| 984 const long long m_start; //posn of segment payload |
| 985 const long long m_size; //size of segment payload |
| 986 Cluster m_eos; //TODO: make private? |
| 987 |
| 988 static long long CreateInstance(IMkvReader*, long long, Segment*&); |
| 989 ~Segment(); |
| 990 |
| 991 long Load(); //loads headers and all clusters |
| 992 |
| 993 //for incremental loading |
| 994 //long long Unparsed() const; |
| 995 bool DoneParsing() const; |
| 996 long long ParseHeaders(); //stops when first cluster is found |
| 997 //long FindNextCluster(long long& pos, long& size) const; |
| 998 long LoadCluster(long long& pos, long& size); //load one cluster |
| 999 long LoadCluster(); |
| 1000 |
| 1001 long ParseNext( |
| 1002 const Cluster* pCurr, |
| 1003 const Cluster*& pNext, |
| 1004 long long& pos, |
| 1005 long& size); |
| 1006 |
| 1007 #if 0 |
| 1008 //This pair parses one cluster, but only changes the state of the |
| 1009 //segment object when the cluster is actually added to the index. |
| 1010 long ParseCluster(long long& cluster_pos, long long& new_pos) const; |
| 1011 bool AddCluster(long long cluster_pos, long long new_pos); |
| 1012 #endif |
| 1013 |
| 1014 const SeekHead* GetSeekHead() const; |
| 1015 const Tracks* GetTracks() const; |
| 1016 const SegmentInfo* GetInfo() const; |
| 1017 const Cues* GetCues() const; |
| 1018 const Chapters* GetChapters() const; |
| 1019 |
| 1020 long long GetDuration() const; |
| 1021 |
| 1022 unsigned long GetCount() const; |
| 1023 const Cluster* GetFirst() const; |
| 1024 const Cluster* GetLast() const; |
| 1025 const Cluster* GetNext(const Cluster*); |
| 1026 |
| 1027 const Cluster* FindCluster(long long time_nanoseconds) const; |
| 1028 //const BlockEntry* Seek(long long time_nanoseconds, const Track*) const; |
| 1029 |
| 1030 const Cluster* FindOrPreloadCluster(long long pos); |
| 1031 |
| 1032 long ParseCues( |
| 1033 long long cues_off, //offset relative to start of segment |
| 1034 long long& parse_pos, |
| 1035 long& parse_len); |
| 1036 |
| 1037 private: |
| 1038 |
| 1039 long long m_pos; //absolute file posn; what has been consumed so far |
| 1040 Cluster* m_pUnknownSize; |
| 1041 |
| 1042 SeekHead* m_pSeekHead; |
| 1043 SegmentInfo* m_pInfo; |
| 1044 Tracks* m_pTracks; |
| 1045 Cues* m_pCues; |
| 1046 Chapters* m_pChapters; |
| 1047 Cluster** m_clusters; |
| 1048 long m_clusterCount; //number of entries for which m_index >= 0 |
| 1049 long m_clusterPreloadCount; //number of entries for which m_index < 0 |
| 1050 long m_clusterSize; //array size |
| 1051 |
| 1052 long DoLoadCluster(long long&, long&); |
| 1053 long DoLoadClusterUnknownSize(long long&, long&); |
| 1054 long DoParseNext(const Cluster*&, long long&, long&); |
| 1055 |
| 1056 void AppendCluster(Cluster*); |
| 1057 void PreloadCluster(Cluster*, ptrdiff_t); |
| 1058 |
| 1059 //void ParseSeekHead(long long pos, long long size); |
| 1060 //void ParseSeekEntry(long long pos, long long size); |
| 1061 //void ParseCues(long long); |
| 1062 |
| 1063 const BlockEntry* GetBlock( |
| 1064 const CuePoint&, |
| 1065 const CuePoint::TrackPosition&); |
| 1066 |
| 1067 }; |
| 1068 |
| 1069 } //end namespace mkvparser |
| 1070 |
| 1071 inline long mkvparser::Segment::LoadCluster() |
| 1072 { |
| 1073 long long pos; |
| 1074 long size; |
| 1075 |
| 1076 return LoadCluster(pos, size); |
| 1077 } |
| 1078 |
| 1079 #endif //MKVPARSER_HPP |
OLD | NEW |