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