nalunit.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /**
  2. * Copyright (c) 2020 Filip Klembara (in2core)
  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 "nalunit.hpp"
  10. #include "impl/internals.hpp"
  11. #include <cmath>
  12. namespace rtc {
  13. std::vector<binary> NalUnit::GenerateFragments(const std::vector<NalUnit> &nalus,
  14. size_t maxFragmentSize) {
  15. std::vector<binary> result;
  16. for (const 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 this
  22. result.push_back(nalu);
  23. }
  24. }
  25. return result;
  26. }
  27. std::vector<NalUnitFragmentA> NalUnit::generateFragments(size_t maxFragmentSize) const {
  28. assert(size() > maxFragmentSize);
  29. // TODO: check this
  30. auto fragments_count = ceil(double(size()) / maxFragmentSize);
  31. maxFragmentSize = uint16_t(int(ceil(size() / fragments_count)));
  32. // 2 bytes for FU indicator and FU header
  33. maxFragmentSize -= 2;
  34. auto f = forbiddenBit();
  35. uint8_t nri = this->nri() & 0x03;
  36. uint8_t unitType = this->unitType() & 0x1F;
  37. auto payload = this->payload();
  38. size_t offset = 0;
  39. std::vector<NalUnitFragmentA> result;
  40. while (offset < payload.size()) {
  41. vector<byte> fragmentData;
  42. using FragmentType = NalUnitFragmentA::FragmentType;
  43. FragmentType fragmentType;
  44. if (offset == 0) {
  45. fragmentType = FragmentType::Start;
  46. } else if (offset + maxFragmentSize < payload.size()) {
  47. fragmentType = FragmentType::Middle;
  48. } else {
  49. if (offset + maxFragmentSize > payload.size()) {
  50. maxFragmentSize = uint16_t(payload.size() - offset);
  51. }
  52. fragmentType = FragmentType::End;
  53. }
  54. fragmentData = {payload.begin() + offset, payload.begin() + offset + maxFragmentSize};
  55. result.emplace_back(fragmentType, f, nri, unitType, fragmentData);
  56. offset += maxFragmentSize;
  57. }
  58. return result;
  59. }
  60. NalUnitStartSequenceMatch NalUnit::StartSequenceMatchSucc(NalUnitStartSequenceMatch match,
  61. std::byte _byte, Separator separator) {
  62. assert(separator != Separator::Length);
  63. auto byte = (uint8_t)_byte;
  64. auto detectShort =
  65. separator == Separator::ShortStartSequence || separator == Separator::StartSequence;
  66. auto detectLong =
  67. separator == Separator::LongStartSequence || separator == Separator::StartSequence;
  68. switch (match) {
  69. case NUSM_noMatch:
  70. if (byte == 0x00) {
  71. return NUSM_firstZero;
  72. }
  73. break;
  74. case NUSM_firstZero:
  75. if (byte == 0x00) {
  76. return NUSM_secondZero;
  77. }
  78. break;
  79. case NUSM_secondZero:
  80. if (byte == 0x00 && detectLong) {
  81. return NUSM_thirdZero;
  82. } else if (byte == 0x00 && detectShort) {
  83. return NUSM_secondZero;
  84. } else if (byte == 0x01 && detectShort) {
  85. return NUSM_shortMatch;
  86. }
  87. break;
  88. case NUSM_thirdZero:
  89. if (byte == 0x00 && detectLong) {
  90. return NUSM_thirdZero;
  91. } else if (byte == 0x01 && detectLong) {
  92. return NUSM_longMatch;
  93. }
  94. break;
  95. case NUSM_shortMatch:
  96. return NUSM_shortMatch;
  97. case NUSM_longMatch:
  98. return NUSM_longMatch;
  99. }
  100. return NUSM_noMatch;
  101. }
  102. NalUnitFragmentA::NalUnitFragmentA(FragmentType type, bool forbiddenBit, uint8_t nri,
  103. uint8_t unitType, binary data)
  104. : NalUnit(data.size() + 2) {
  105. setForbiddenBit(forbiddenBit);
  106. setNRI(nri);
  107. fragmentIndicator()->setUnitType(NalUnitFragmentA::nal_type_fu_A);
  108. setFragmentType(type);
  109. setUnitType(unitType);
  110. copy(data.begin(), data.end(), begin() + 2);
  111. }
  112. // For backward compatibility, do not use
  113. std::vector<shared_ptr<NalUnitFragmentA>>
  114. NalUnitFragmentA::fragmentsFrom(shared_ptr<NalUnit> nalu, uint16_t maxFragmentSize) {
  115. auto fragments = nalu->generateFragments(maxFragmentSize);
  116. std::vector<shared_ptr<NalUnitFragmentA>> result;
  117. result.reserve(fragments.size());
  118. for (auto fragment : fragments)
  119. result.push_back(std::make_shared<NalUnitFragmentA>(std::move(fragment)));
  120. return result;
  121. }
  122. void NalUnitFragmentA::setFragmentType(FragmentType type) {
  123. fragmentHeader()->setReservedBit6(false);
  124. switch (type) {
  125. case FragmentType::Start:
  126. fragmentHeader()->setStart(true);
  127. fragmentHeader()->setEnd(false);
  128. break;
  129. case FragmentType::End:
  130. fragmentHeader()->setStart(false);
  131. fragmentHeader()->setEnd(true);
  132. break;
  133. default:
  134. fragmentHeader()->setStart(false);
  135. fragmentHeader()->setEnd(false);
  136. }
  137. }
  138. // For backward compatibility, do not use
  139. std::vector<shared_ptr<binary>> NalUnits::generateFragments(uint16_t maxFragmentSize) {
  140. std::vector<NalUnit> nalus;
  141. for (auto nalu : *this)
  142. nalus.push_back(*nalu);
  143. auto fragments = NalUnit::GenerateFragments(nalus, maxFragmentSize);
  144. std::vector<shared_ptr<binary>> result;
  145. result.reserve(fragments.size());
  146. for (auto fragment : fragments)
  147. result.push_back(std::make_shared<binary>(std::move(fragment)));
  148. return result;
  149. }
  150. } // namespace rtc
  151. #endif /* RTC_ENABLE_MEDIA */