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