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 #include "mkvmuxerutil.hpp" 10 11 #ifdef __ANDROID__ 12 #include <fcntl.h> 13 #endif 14 15 #include <cassert> 16 #include <cmath> 17 #include <cstdio> 18 #ifdef _MSC_VER 19 #define _CRT_RAND_S 20 #endif 21 #include <cstdlib> 22 #include <cstring> 23 #include <ctime> 24 25 #include <new> 26 27 #include "mkvwriter.hpp" 28 #include "webmids.hpp" 29 30 namespace mkvmuxer { 31 32 int32 GetCodedUIntSize(uint64 value) { 33 if (value < 0x000000000000007FULL) 34 return 1; 35 else if (value < 0x0000000000003FFFULL) 36 return 2; 37 else if (value < 0x00000000001FFFFFULL) 38 return 3; 39 else if (value < 0x000000000FFFFFFFULL) 40 return 4; 41 else if (value < 0x00000007FFFFFFFFULL) 42 return 5; 43 else if (value < 0x000003FFFFFFFFFFULL) 44 return 6; 45 else if (value < 0x0001FFFFFFFFFFFFULL) 46 return 7; 47 return 8; 48 } 49 50 int32 GetUIntSize(uint64 value) { 51 if (value < 0x0000000000000100ULL) 52 return 1; 53 else if (value < 0x0000000000010000ULL) 54 return 2; 55 else if (value < 0x0000000001000000ULL) 56 return 3; 57 else if (value < 0x0000000100000000ULL) 58 return 4; 59 else if (value < 0x0000010000000000ULL) 60 return 5; 61 else if (value < 0x0001000000000000ULL) 62 return 6; 63 else if (value < 0x0100000000000000ULL) 64 return 7; 65 return 8; 66 } 67 68 uint64 EbmlMasterElementSize(uint64 type, uint64 value) { 69 // Size of EBML ID 70 int32 ebml_size = GetUIntSize(type); 71 72 // Datasize 73 ebml_size += GetCodedUIntSize(value); 74 75 return ebml_size; 76 } 77 78 uint64 EbmlElementSize(uint64 type, int64 value) { 79 return EbmlElementSize(type, static_cast<uint64>(value)); 80 } 81 82 uint64 EbmlElementSize(uint64 type, uint64 value) { 83 // Size of EBML ID 84 int32 ebml_size = GetUIntSize(type); 85 86 // Datasize 87 ebml_size += GetUIntSize(value); 88 89 // Size of Datasize 90 ebml_size++; 91 92 return ebml_size; 93 } 94 95 uint64 EbmlElementSize(uint64 type, float /* value */ ) { 96 // Size of EBML ID 97 uint64 ebml_size = GetUIntSize(type); 98 99 // Datasize 100 ebml_size += sizeof(float); 101 102 // Size of Datasize 103 ebml_size++; 104 105 return ebml_size; 106 } 107 108 uint64 EbmlElementSize(uint64 type, const char* value) { 109 if (!value) 110 return 0; 111 112 // Size of EBML ID 113 uint64 ebml_size = GetUIntSize(type); 114 115 // Datasize 116 ebml_size += strlen(value); 117 118 // Size of Datasize 119 ebml_size++; 120 121 return ebml_size; 122 } 123 124 uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size) { 125 if (!value) 126 return 0; 127 128 // Size of EBML ID 129 uint64 ebml_size = GetUIntSize(type); 130 131 // Datasize 132 ebml_size += size; 133 134 // Size of Datasize 135 ebml_size += GetCodedUIntSize(size); 136 137 return ebml_size; 138 } 139 140 int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size) { 141 if (!writer || size < 1 || size > 8) 142 return -1; 143 144 for (int32 i = 1; i <= size; ++i) { 145 const int32 byte_count = size - i; 146 const int32 bit_count = byte_count * 8; 147 148 const int64 bb = value >> bit_count; 149 const uint8 b = static_cast<uint8>(bb); 150 151 const int32 status = writer->Write(&b, 1); 152 153 if (status < 0) 154 return status; 155 } 156 157 return 0; 158 } 159 160 int32 SerializeFloat(IMkvWriter* writer, float f) { 161 if (!writer) 162 return -1; 163 164 assert(sizeof(uint32) == sizeof(float)); 165 // This union is merely used to avoid a reinterpret_cast from float& to 166 // uint32& which will result in violation of strict aliasing. 167 union U32 { 168 uint32 u32; 169 float f; 170 } value; 171 value.f = f; 172 173 for (int32 i = 1; i <= 4; ++i) { 174 const int32 byte_count = 4 - i; 175 const int32 bit_count = byte_count * 8; 176 177 const uint8 byte = static_cast<uint8>(value.u32 >> bit_count); 178 179 const int32 status = writer->Write(&byte, 1); 180 181 if (status < 0) 182 return status; 183 } 184 185 return 0; 186 } 187 188 int32 WriteUInt(IMkvWriter* writer, uint64 value) { 189 if (!writer) 190 return -1; 191 192 int32 size = GetCodedUIntSize(value); 193 194 return WriteUIntSize(writer, value, size); 195 } 196 197 int32 WriteUIntSize(IMkvWriter* writer, uint64 value, int32 size) { 198 if (!writer || size < 0 || size > 8) 199 return -1; 200 201 if (size > 0) { 202 const uint64 bit = 1LL << (size * 7); 203 204 if (value > (bit - 2)) 205 return -1; 206 207 value |= bit; 208 } else { 209 size = 1; 210 int64 bit; 211 212 for (;;) { 213 bit = 1LL << (size * 7); 214 const uint64 max = bit - 2; 215 216 if (value <= max) 217 break; 218 219 ++size; 220 } 221 222 if (size > 8) 223 return false; 224 225 value |= bit; 226 } 227 228 return SerializeInt(writer, value, size); 229 } 230 231 int32 WriteID(IMkvWriter* writer, uint64 type) { 232 if (!writer) 233 return -1; 234 235 writer->ElementStartNotify(type, writer->Position()); 236 237 const int32 size = GetUIntSize(type); 238 239 return SerializeInt(writer, type, size); 240 } 241 242 bool WriteEbmlMasterElement(IMkvWriter* writer, uint64 type, uint64 size) { 243 if (!writer) 244 return false; 245 246 if (WriteID(writer, type)) 247 return false; 248 249 if (WriteUInt(writer, size)) 250 return false; 251 252 return true; 253 } 254 255 bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value) { 256 if (!writer) 257 return false; 258 259 if (WriteID(writer, type)) 260 return false; 261 262 const uint64 size = GetUIntSize(value); 263 if (WriteUInt(writer, size)) 264 return false; 265 266 if (SerializeInt(writer, value, static_cast<int32>(size))) 267 return false; 268 269 return true; 270 } 271 272 bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value) { 273 if (!writer) 274 return false; 275 276 if (WriteID(writer, type)) 277 return false; 278 279 if (WriteUInt(writer, 4)) 280 return false; 281 282 if (SerializeFloat(writer, value)) 283 return false; 284 285 return true; 286 } 287 288 bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value) { 289 if (!writer || !value) 290 return false; 291 292 if (WriteID(writer, type)) 293 return false; 294 295 const int32 length = strlen(value); 296 if (WriteUInt(writer, length)) 297 return false; 298 299 if (writer->Write(value, length)) 300 return false; 301 302 return true; 303 } 304 305 bool WriteEbmlElement(IMkvWriter* writer, 306 uint64 type, 307 const uint8* value, 308 uint64 size) { 309 if (!writer || !value || size < 1) 310 return false; 311 312 if (WriteID(writer, type)) 313 return false; 314 315 if (WriteUInt(writer, size)) 316 return false; 317 318 if (writer->Write(value, static_cast<uint32>(size))) 319 return false; 320 321 return true; 322 } 323 324 uint64 WriteSimpleBlock(IMkvWriter* writer, 325 const uint8* data, 326 uint64 length, 327 uint64 track_number, 328 int64 timecode, 329 uint64 is_key) { 330 if (!writer) 331 return false; 332 333 if (!data || length < 1) 334 return false; 335 336 // Here we only permit track number values to be no greater than 337 // 126, which the largest value we can store having a Matroska 338 // integer representation of only 1 byte. 339 340 if (track_number < 1 || track_number > 126) 341 return false; 342 343 // Technically the timestamp for a block can be less than the 344 // timestamp for the cluster itself (remember that block timestamp 345 // is a signed, 16-bit integer). However, as a simplification we 346 // only permit non-negative cluster-relative timestamps for blocks. 347 348 if (timecode < 0 || timecode > kMaxBlockTimecode) 349 return false; 350 351 if (WriteID(writer, kMkvSimpleBlock)) 352 return 0; 353 354 const int32 size = static_cast<int32>(length) + 4; 355 if (WriteUInt(writer, size)) 356 return 0; 357 358 if (WriteUInt(writer, static_cast<uint64>(track_number))) 359 return 0; 360 361 if (SerializeInt(writer, timecode, 2)) 362 return 0; 363 364 uint64 flags = 0; 365 if (is_key) 366 flags |= 0x80; 367 368 if (SerializeInt(writer, flags, 1)) 369 return 0; 370 371 if (writer->Write(data, static_cast<uint32>(length))) 372 return 0; 373 374 const uint64 element_size = 375 GetUIntSize(kMkvSimpleBlock) + GetCodedUIntSize(size) + 4 + length; 376 377 return element_size; 378 } 379 380 // We must write the metadata (key)frame as a BlockGroup element, 381 // because we need to specify a duration for the frame. The 382 // BlockGroup element comprises the frame itself and its duration, 383 // and is laid out as follows: 384 // 385 // BlockGroup tag 386 // BlockGroup size 387 // Block tag 388 // Block size 389 // (the frame is the block payload) 390 // Duration tag 391 // Duration size 392 // (duration payload) 393 // 394 uint64 WriteMetadataBlock(IMkvWriter* writer, 395 const uint8* data, 396 uint64 length, 397 uint64 track_number, 398 int64 timecode, 399 uint64 duration) { 400 // We don't backtrack when writing to the stream, so we must 401 // pre-compute the BlockGroup size, by summing the sizes of each 402 // sub-element (the block and the duration). 403 404 // We use a single byte for the track number of the block, which 405 // means the block header is exactly 4 bytes. 406 407 // TODO(matthewjheaney): use EbmlMasterElementSize and WriteEbmlMasterElement 408 409 const uint64 block_payload_size = 4 + length; 410 const int32 block_size = GetCodedUIntSize(block_payload_size); 411 const uint64 block_elem_size = 1 + block_size + block_payload_size; 412 413 const int32 duration_payload_size = GetUIntSize(duration); 414 const int32 duration_size = GetCodedUIntSize(duration_payload_size); 415 const uint64 duration_elem_size = 1 + duration_size + duration_payload_size; 416 417 const uint64 blockg_payload_size = block_elem_size + duration_elem_size; 418 const int32 blockg_size = GetCodedUIntSize(blockg_payload_size); 419 const uint64 blockg_elem_size = 1 + blockg_size + blockg_payload_size; 420 421 if (WriteID(writer, kMkvBlockGroup)) // 1-byte ID size 422 return 0; 423 424 if (WriteUInt(writer, blockg_payload_size)) 425 return 0; 426 427 // Write Block element 428 429 if (WriteID(writer, kMkvBlock)) // 1-byte ID size 430 return 0; 431 432 if (WriteUInt(writer, block_payload_size)) 433 return 0; 434 435 // Byte 1 of 4 436 437 if (WriteUInt(writer, track_number)) 438 return 0; 439 440 // Bytes 2 & 3 of 4 441 442 if (SerializeInt(writer, timecode, 2)) 443 return 0; 444 445 // Byte 4 of 4 446 447 const uint64 flags = 0; 448 449 if (SerializeInt(writer, flags, 1)) 450 return 0; 451 452 // Now write the actual frame (of metadata) 453 454 if (writer->Write(data, static_cast<uint32>(length))) 455 return 0; 456 457 // Write Duration element 458 459 if (WriteID(writer, kMkvBlockDuration)) // 1-byte ID size 460 return 0; 461 462 if (WriteUInt(writer, duration_payload_size)) 463 return 0; 464 465 if (SerializeInt(writer, duration, duration_payload_size)) 466 return 0; 467 468 // Note that we don't write a reference time as part of the block 469 // group; no reference time(s) indicates that this block is a 470 // keyframe. (Unlike the case for a SimpleBlock element, the header 471 // bits of the Block sub-element of a BlockGroup element do not 472 // indicate keyframe status. The keyframe status is inferred from 473 // the absence of reference time sub-elements.) 474 475 return blockg_elem_size; 476 } 477 478 // Writes a WebM BlockGroup with BlockAdditional data. The structure is as 479 // follows: 480 // Indentation shows sub-levels 481 // BlockGroup 482 // Block 483 // Data 484 // BlockAdditions 485 // BlockMore 486 // BlockAddID 487 // 1 (Denotes Alpha) 488 // BlockAdditional 489 // Data 490 uint64 WriteBlockWithAdditional(IMkvWriter* writer, 491 const uint8* data, 492 uint64 length, 493 const uint8* additional, 494 uint64 additional_length, 495 uint64 add_id, 496 uint64 track_number, 497 int64 timecode, 498 uint64 is_key) { 499 if (!data || !additional || length < 1 || additional_length < 1) 500 return 0; 501 502 const uint64 block_payload_size = 4 + length; 503 const uint64 block_elem_size = EbmlMasterElementSize(kMkvBlock, 504 block_payload_size) + 505 block_payload_size; 506 const uint64 block_additional_elem_size = EbmlElementSize(kMkvBlockAdditional, 507 additional, 508 additional_length); 509 const uint64 block_addid_elem_size = EbmlElementSize(kMkvBlockAddID, add_id); 510 511 const uint64 block_more_payload_size = block_addid_elem_size + 512 block_additional_elem_size; 513 const uint64 block_more_elem_size = EbmlMasterElementSize( 514 kMkvBlockMore, 515 block_more_payload_size) + 516 block_more_payload_size; 517 const uint64 block_additions_payload_size = block_more_elem_size; 518 const uint64 block_additions_elem_size = EbmlMasterElementSize( 519 kMkvBlockAdditions, 520 block_additions_payload_size) + 521 block_additions_payload_size; 522 const uint64 block_group_payload_size = block_elem_size + 523 block_additions_elem_size; 524 const uint64 block_group_elem_size = EbmlMasterElementSize( 525 kMkvBlockGroup, 526 block_group_payload_size) + 527 block_group_payload_size; 528 529 if (!WriteEbmlMasterElement(writer, kMkvBlockGroup, 530 block_group_payload_size)) 531 return 0; 532 533 if (!WriteEbmlMasterElement(writer, kMkvBlock, block_payload_size)) 534 return 0; 535 536 if (WriteUInt(writer, track_number)) 537 return 0; 538 539 if (SerializeInt(writer, timecode, 2)) 540 return 0; 541 542 uint64 flags = 0; 543 if (is_key) 544 flags |= 0x80; 545 if (SerializeInt(writer, flags, 1)) 546 return 0; 547 548 if (writer->Write(data, static_cast<uint32>(length))) 549 return 0; 550 551 if (!WriteEbmlMasterElement(writer, kMkvBlockAdditions, 552 block_additions_payload_size)) 553 return 0; 554 555 if (!WriteEbmlMasterElement(writer, kMkvBlockMore, block_more_payload_size)) 556 return 0; 557 558 if (!WriteEbmlElement(writer, kMkvBlockAddID, add_id)) 559 return 0; 560 561 if (!WriteEbmlElement(writer, kMkvBlockAdditional, 562 additional, additional_length)) 563 return 0; 564 565 return block_group_elem_size; 566 } 567 568 // Writes a WebM BlockGroup with DiscardPadding. The structure is as follows: 569 // Indentation shows sub-levels 570 // BlockGroup 571 // Block 572 // Data 573 // DiscardPadding 574 uint64 WriteBlockWithDiscardPadding(IMkvWriter* writer, 575 const uint8* data, 576 uint64 length, 577 int64 discard_padding, 578 uint64 track_number, 579 int64 timecode, 580 uint64 is_key) { 581 if (!data || length < 1 || discard_padding <= 0) 582 return 0; 583 584 const uint64 block_payload_size = 4 + length; 585 const uint64 block_elem_size = EbmlMasterElementSize(kMkvBlock, 586 block_payload_size) + 587 block_payload_size; 588 const uint64 discard_padding_elem_size = EbmlElementSize(kMkvDiscardPadding, 589 discard_padding); 590 const uint64 block_group_payload_size = block_elem_size + 591 discard_padding_elem_size; 592 const uint64 block_group_elem_size = EbmlMasterElementSize( 593 kMkvBlockGroup, 594 block_group_payload_size) + 595 block_group_payload_size; 596 597 if (!WriteEbmlMasterElement(writer, kMkvBlockGroup, 598 block_group_payload_size)) 599 return 0; 600 601 if (!WriteEbmlMasterElement(writer, kMkvBlock, block_payload_size)) 602 return 0; 603 604 if (WriteUInt(writer, track_number)) 605 return 0; 606 607 if (SerializeInt(writer, timecode, 2)) 608 return 0; 609 610 uint64 flags = 0; 611 if (is_key) 612 flags |= 0x80; 613 if (SerializeInt(writer, flags, 1)) 614 return 0; 615 616 if (writer->Write(data, static_cast<uint32>(length))) 617 return 0; 618 619 if (WriteID(writer, kMkvDiscardPadding)) 620 return 0; 621 622 const uint64 size = GetUIntSize(discard_padding); 623 if (WriteUInt(writer, size)) 624 return false; 625 626 if (SerializeInt(writer, discard_padding, static_cast<int32>(size))) 627 return false; 628 629 return block_group_elem_size; 630 } 631 632 uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) { 633 if (!writer) 634 return false; 635 636 // Subtract one for the void ID and the coded size. 637 uint64 void_entry_size = size - 1 - GetCodedUIntSize(size-1); 638 uint64 void_size = EbmlMasterElementSize(kMkvVoid, void_entry_size) + 639 void_entry_size; 640 641 if (void_size != size) 642 return 0; 643 644 const int64 payload_position = writer->Position(); 645 if (payload_position < 0) 646 return 0; 647 648 if (WriteID(writer, kMkvVoid)) 649 return 0; 650 651 if (WriteUInt(writer, void_entry_size)) 652 return 0; 653 654 const uint8 value = 0; 655 for (int32 i = 0; i < static_cast<int32>(void_entry_size); ++i) { 656 if (writer->Write(&value, 1)) 657 return 0; 658 } 659 660 const int64 stop_position = writer->Position(); 661 if (stop_position < 0 || 662 stop_position - payload_position != static_cast<int64>(void_size)) 663 return 0; 664 665 return void_size; 666 } 667 668 void GetVersion(int32* major, int32* minor, int32* build, int32* revision) { 669 *major = 0; 670 *minor = 2; 671 *build = 1; 672 *revision = 0; 673 } 674 675 } // namespace mkvmuxer 676 677 mkvmuxer::uint64 mkvmuxer::MakeUID(unsigned int* seed) { 678 uint64 uid = 0; 679 680 #ifdef __MINGW32__ 681 srand(*seed); 682 #endif 683 684 for (int i = 0; i < 7; ++i) { // avoid problems with 8-byte values 685 uid <<= 8; 686 687 // TODO(fgalligan): Move random number generation to platform specific code. 688 #ifdef _MSC_VER 689 (void)seed; 690 unsigned int random_value; 691 const errno_t e = rand_s(&random_value); 692 (void)e; 693 const int32 nn = random_value; 694 #elif __ANDROID__ 695 int32 temp_num = 1; 696 int fd = open("/dev/urandom", O_RDONLY); 697 if (fd != -1) { 698 read(fd, &temp_num, sizeof(int32)); 699 close(fd); 700 } 701 const int32 nn = temp_num; 702 #elif defined __MINGW32__ 703 const int32 nn = rand(); 704 #else 705 const int32 nn = rand_r(seed); 706 #endif 707 const int32 n = 0xFF & (nn >> 4); // throw away low-order bits 708 709 uid |= n; 710 } 711 712 return uid; 713 } 714