nalunit.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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. NalUnitFragmentA::NalUnitFragmentA(FragmentType type, bool forbiddenBit, uint8_t nri,
  14. uint8_t unitType, binary data)
  15. : NalUnit(data.size() + 2) {
  16. setForbiddenBit(forbiddenBit);
  17. setNRI(nri);
  18. fragmentIndicator()->setUnitType(NalUnitFragmentA::nal_type_fu_A);
  19. setFragmentType(type);
  20. setUnitType(unitType);
  21. copy(data.begin(), data.end(), begin() + 2);
  22. }
  23. std::vector<shared_ptr<NalUnitFragmentA>>
  24. NalUnitFragmentA::fragmentsFrom(shared_ptr<NalUnit> nalu, uint16_t maxFragmentSize) {
  25. assert(nalu->size() > maxFragmentSize);
  26. auto fragments_count = ceil(double(nalu->size()) / maxFragmentSize);
  27. maxFragmentSize = uint16_t(int(ceil(nalu->size() / fragments_count)));
  28. // 2 bytes for FU indicator and FU header
  29. maxFragmentSize -= 2;
  30. auto f = nalu->forbiddenBit();
  31. uint8_t nri = nalu->nri() & 0x03;
  32. uint8_t naluType = nalu->unitType() & 0x1F;
  33. auto payload = nalu->payload();
  34. vector<shared_ptr<NalUnitFragmentA>> result{};
  35. uint64_t offset = 0;
  36. while (offset < payload.size()) {
  37. vector<byte> fragmentData;
  38. FragmentType fragmentType;
  39. if (offset == 0) {
  40. fragmentType = FragmentType::Start;
  41. } else if (offset + maxFragmentSize < payload.size()) {
  42. fragmentType = FragmentType::Middle;
  43. } else {
  44. if (offset + maxFragmentSize > payload.size()) {
  45. maxFragmentSize = uint16_t(payload.size() - offset);
  46. }
  47. fragmentType = FragmentType::End;
  48. }
  49. fragmentData = {payload.begin() + offset, payload.begin() + offset + maxFragmentSize};
  50. auto fragment =
  51. std::make_shared<NalUnitFragmentA>(fragmentType, f, nri, naluType, fragmentData);
  52. result.push_back(fragment);
  53. offset += maxFragmentSize;
  54. }
  55. return result;
  56. }
  57. void NalUnitFragmentA::setFragmentType(FragmentType type) {
  58. fragmentHeader()->setReservedBit6(false);
  59. switch (type) {
  60. case FragmentType::Start:
  61. fragmentHeader()->setStart(true);
  62. fragmentHeader()->setEnd(false);
  63. break;
  64. case FragmentType::End:
  65. fragmentHeader()->setStart(false);
  66. fragmentHeader()->setEnd(true);
  67. break;
  68. default:
  69. fragmentHeader()->setStart(false);
  70. fragmentHeader()->setEnd(false);
  71. }
  72. }
  73. std::vector<shared_ptr<binary>> NalUnits::generateFragments(uint16_t maxFragmentSize) {
  74. vector<shared_ptr<binary>> result{};
  75. for (auto nalu : *this) {
  76. if (nalu->size() > maxFragmentSize) {
  77. std::vector<shared_ptr<NalUnitFragmentA>> fragments =
  78. NalUnitFragmentA::fragmentsFrom(nalu, maxFragmentSize);
  79. result.insert(result.end(), fragments.begin(), fragments.end());
  80. } else {
  81. result.push_back(nalu);
  82. }
  83. }
  84. return result;
  85. }
  86. } // namespace rtc
  87. #endif /* RTC_ENABLE_MEDIA */