h264rtppacketizer.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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 "h264rtppacketizer.hpp"
  10. #include "impl/internals.hpp"
  11. #include <algorithm>
  12. #include <cassert>
  13. #ifdef _WIN32
  14. #include <winsock2.h>
  15. #else
  16. #include <arpa/inet.h>
  17. #endif
  18. namespace rtc {
  19. H264RtpPacketizer::H264RtpPacketizer(shared_ptr<RtpPacketizationConfig> rtpConfig,
  20. size_t maxFragmentSize)
  21. : RtpPacketizer(std::move(rtpConfig)), mSeparator(Separator::Length), mMaxFragmentSize(maxFragmentSize) {}
  22. H264RtpPacketizer::H264RtpPacketizer(Separator separator,
  23. shared_ptr<RtpPacketizationConfig> rtpConfig,
  24. size_t maxFragmentSize)
  25. : RtpPacketizer(rtpConfig), mSeparator(separator), mMaxFragmentSize(maxFragmentSize) {}
  26. std::vector<binary> H264RtpPacketizer::fragment(binary data) {
  27. return NalUnit::GenerateFragments(splitFrame(data), mMaxFragmentSize);
  28. }
  29. std::vector<NalUnit> H264RtpPacketizer::splitFrame(const binary &frame) {
  30. std::vector<NalUnit> nalus;
  31. if (mSeparator == Separator::Length) {
  32. size_t index = 0;
  33. while (index < frame.size()) {
  34. assert(index + 4 < frame.size());
  35. if (index + 4 >= frame.size()) {
  36. LOG_WARNING << "Invalid NAL Unit data (incomplete length), ignoring!";
  37. break;
  38. }
  39. uint32_t length;
  40. std::memcpy(&length, frame.data() + index, sizeof(uint32_t));
  41. length = ntohl(length);
  42. auto naluStartIndex = index + 4;
  43. auto naluEndIndex = naluStartIndex + length;
  44. assert(naluEndIndex <= frame.size());
  45. if (naluEndIndex > frame.size()) {
  46. LOG_WARNING << "Invalid NAL Unit data (incomplete unit), ignoring!";
  47. break;
  48. }
  49. auto begin = frame.begin() + naluStartIndex;
  50. auto end = frame.begin() + naluEndIndex;
  51. nalus.emplace_back(begin, end);
  52. index = naluEndIndex;
  53. }
  54. } else {
  55. NalUnitStartSequenceMatch match = NUSM_noMatch;
  56. size_t index = 0;
  57. while (index < frame.size()) {
  58. match = NalUnit::StartSequenceMatchSucc(match, frame[index++], mSeparator);
  59. if (match == NUSM_longMatch || match == NUSM_shortMatch) {
  60. match = NUSM_noMatch;
  61. break;
  62. }
  63. }
  64. size_t naluStartIndex = index;
  65. while (index < frame.size()) {
  66. match = NalUnit::StartSequenceMatchSucc(match, frame[index], mSeparator);
  67. if (match == NUSM_longMatch || match == NUSM_shortMatch) {
  68. auto sequenceLength = match == NUSM_longMatch ? 4 : 3;
  69. size_t naluEndIndex = index - sequenceLength;
  70. match = NUSM_noMatch;
  71. auto begin = frame.begin() + naluStartIndex;
  72. auto end = frame.begin() + naluEndIndex + 1;
  73. nalus.emplace_back(begin, end);
  74. naluStartIndex = index + 1;
  75. }
  76. index++;
  77. }
  78. auto begin = frame.begin() + naluStartIndex;
  79. auto end = frame.end();
  80. nalus.emplace_back(begin, end);
  81. }
  82. return nalus;
  83. }
  84. } // namespace rtc
  85. #endif /* RTC_ENABLE_MEDIA */