h265nalunit.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /**
  2. * Copyright (c) 2023 Zita Liao (Dolby)
  3. *
  4. * This Source Code Form is subject to the terms of the Mozilla Public
  5. * License, v. 2.0. If a copy of the MPL was not distributed with this
  6. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
  7. */
  8. #if RTC_ENABLE_MEDIA
  9. #include "h265nalunit.hpp"
  10. #include "impl/internals.hpp"
  11. #include <cmath>
  12. namespace rtc {
  13. std::vector<binary> H265NalUnit::GenerateFragments(const std::vector<H265NalUnit> &nalus,
  14. size_t maxFragmentSize) {
  15. std::vector<binary> result;
  16. for (auto nalu : nalus) {
  17. if (nalu.size() > maxFragmentSize) {
  18. auto fragments = nalu.generateFragments(maxFragmentSize);
  19. result.insert(result.end(), fragments.begin(), fragments.end());
  20. } else {
  21. // TODO: check
  22. result.push_back(nalu);
  23. }
  24. }
  25. return result;
  26. }
  27. std::vector<H265NalUnitFragment> H265NalUnit::generateFragments(size_t maxFragmentSize) const {
  28. // TODO: check
  29. assert(size() > maxFragmentSize);
  30. auto fragments_count = ceil(double(size()) / maxFragmentSize);
  31. maxFragmentSize = uint16_t(int(ceil(size() / fragments_count)));
  32. // 3 bytes for FU indicator and FU header
  33. maxFragmentSize -= (H265_NAL_HEADER_SIZE + H265_FU_HEADER_SIZE);
  34. bool forbiddenBit = this->forbiddenBit();
  35. uint8_t nuhLayerId = this->nuhLayerId() & 0x3F; // 6 bits
  36. uint8_t nuhTempIdPlus1 = this->nuhTempIdPlus1() & 0x7; // 3 bits
  37. uint8_t naluType = this->unitType() & 0x3F; // 6 bits
  38. auto payload = this->payload();
  39. vector<H265NalUnitFragment> result;
  40. uint64_t offset = 0;
  41. while (offset < payload.size()) {
  42. vector<byte> fragmentData;
  43. using FragmentType = H265NalUnitFragment::FragmentType;
  44. FragmentType fragmentType;
  45. if (offset == 0) {
  46. fragmentType = FragmentType::Start;
  47. } else if (offset + maxFragmentSize < payload.size()) {
  48. fragmentType = FragmentType::Middle;
  49. } else {
  50. if (offset + maxFragmentSize > payload.size()) {
  51. maxFragmentSize = uint16_t(payload.size() - offset);
  52. }
  53. fragmentType = FragmentType::End;
  54. }
  55. fragmentData = {payload.begin() + offset, payload.begin() + offset + maxFragmentSize};
  56. result.emplace_back(fragmentType, forbiddenBit, nuhLayerId, nuhTempIdPlus1, naluType,
  57. fragmentData);
  58. offset += maxFragmentSize;
  59. }
  60. return result;
  61. }
  62. H265NalUnitFragment::H265NalUnitFragment(FragmentType type, bool forbiddenBit, uint8_t nuhLayerId,
  63. uint8_t nuhTempIdPlus1, uint8_t unitType, binary data)
  64. : H265NalUnit(data.size() + H265_NAL_HEADER_SIZE + H265_FU_HEADER_SIZE) {
  65. setForbiddenBit(forbiddenBit);
  66. setNuhLayerId(nuhLayerId);
  67. setNuhTempIdPlus1(nuhTempIdPlus1);
  68. fragmentIndicator()->setUnitType(H265NalUnitFragment::nal_type_fu);
  69. setFragmentType(type);
  70. setUnitType(unitType);
  71. copy(data.begin(), data.end(), begin() + H265_NAL_HEADER_SIZE + H265_FU_HEADER_SIZE);
  72. }
  73. std::vector<shared_ptr<H265NalUnitFragment>>
  74. H265NalUnitFragment::fragmentsFrom(shared_ptr<H265NalUnit> nalu, uint16_t maxFragmentSize) {
  75. auto fragments = nalu->generateFragments(maxFragmentSize);
  76. std::vector<shared_ptr<H265NalUnitFragment>> result;
  77. result.reserve(fragments.size());
  78. for (auto fragment : fragments)
  79. result.push_back(std::make_shared<H265NalUnitFragment>(std::move(fragment)));
  80. return result;
  81. }
  82. void H265NalUnitFragment::setFragmentType(FragmentType type) {
  83. switch (type) {
  84. case FragmentType::Start:
  85. fragmentHeader()->setStart(true);
  86. fragmentHeader()->setEnd(false);
  87. break;
  88. case FragmentType::End:
  89. fragmentHeader()->setStart(false);
  90. fragmentHeader()->setEnd(true);
  91. break;
  92. default:
  93. fragmentHeader()->setStart(false);
  94. fragmentHeader()->setEnd(false);
  95. }
  96. }
  97. std::vector<shared_ptr<binary>> H265NalUnits::generateFragments(uint16_t maxFragmentSize) {
  98. std::vector<H265NalUnit> nalus;
  99. for (auto nalu : *this)
  100. nalus.push_back(*nalu);
  101. auto fragments = H265NalUnit::GenerateFragments(nalus, maxFragmentSize);
  102. std::vector<shared_ptr<binary>> result;
  103. result.reserve(fragments.size());
  104. for (auto fragment : fragments)
  105. result.push_back(std::make_shared<binary>(std::move(fragment)));
  106. return result;
  107. }
  108. } // namespace rtc
  109. #endif /* RTC_ENABLE_MEDIA */