Skip to content

Commit

Permalink
feat: [DIOS-5853] Media server - Handle scte35 messages as unregister…
Browse files Browse the repository at this point in the history
…ed SEI user data
  • Loading branch information
phil-moss-dolby committed Jul 3, 2024
2 parents 1f98f19 + 322ef67 commit ccdd3e3
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 4 deletions.
3 changes: 1 addition & 2 deletions include/MediaFrameListenerBridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,14 @@ class MediaFrameListenerBridge :
virtual int SendPLI(DWORD ssrc) override { return 1; };
virtual int Reset(DWORD ssrc) override { return 1; };


private:
void Dispatch(const std::vector<RTPPacket::shared>& packet);

public:
TimeService& timeService;
Timer::shared dispatchTimer;

std::queue<PacketScheduleInfo> packets;
std::queue<PacketScheduleInfo> packets;

DWORD ssrc = 0;
DWORD extSeqNum = 0;
Expand Down
1 change: 1 addition & 0 deletions include/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -513,4 +513,5 @@ inline size_t CountBits(uint64_t val)
}
return count;
}

#endif
61 changes: 59 additions & 2 deletions src/h264/H264Packetizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,19 @@
#include "video.h"
#include "h264/h264.h"


H264Packetizer::H264Packetizer() : H26xPacketizer(VideoCodec::H264)
{

sei.clear(); // Flush any previous data
sei.push_back(0x06); // SEI NAL
sei.push_back(0x05); // User unregistered data
sei.push_back(0x00); // Payload size

uint8_t uuid[16] = {
0x2b, 0x69, 0xba, 0x1b, 0x77, 0x7e, 0x46, 0x53,
0x99, 0x7a, 0xc6, 0x75, 0xb9, 0xd3, 0xac, 0xaf
};
sei.insert(sei.end(), uuid, uuid + sizeof(uuid));
scteMessageId = 0;
}

void H264Packetizer::EmitNal(VideoFrame& frame, BufferReader nal)
Expand Down Expand Up @@ -175,6 +184,22 @@ void H264Packetizer::OnNal(VideoFrame& frame, BufferReader& reader, std::optiona
frame.AllocateCodecConfig(config.GetSize());
config.Serialize(frame.GetCodecConfigData(), frame.GetCodecConfigSize());
}

if (scteMessage.GetSize() != 0)
{
//Escape nal
uint8_t seiEscaped[sei.size()*2];
auto seiSize = NalEscapeRbsp(seiEscaped, sizeof(seiEscaped), sei.data(), sei.size()).value();
Debug("H264Packetizer::OnNal() | Emit SCTE data as SEI Unregistered User Data, Size %lu \n", seiSize);

EmitNal(frame, BufferReader(seiEscaped, seiSize));
if (repeatFrameCounter-- <= 0)
{
scteMessage.Reset();
repeatFrameCounter = scteFrameRepeatCount;
}

}

EmitNal(frame, BufferReader(nalUnit, nalSize));
}
Expand All @@ -186,3 +211,35 @@ std::unique_ptr<MediaFrame> H264Packetizer::ProcessAU(BufferReader& reader)

return H26xPacketizer::ProcessAU(reader);
}

void H264Packetizer::AppendScteData(uint64_t ts, const Buffer& data, uint8_t repeatCount)
{
scteMessage.AppendData(data.GetData(), data.GetSize());
scteFrameRepeatCount = repeatFrameCounter = repeatCount;
scteTimestamp = ts;

// Clear just the scte payload and retain the 2 byte code, size and 16 bytes UUID
sei.erase(sei.begin() + 2 + 1 + 16, sei.end());

// Binary format - SEI NAL (0x06) + Unregistered User data code (0x05) + UUID (16 bytes) + SCTE ID (2 bytes) + TS (8 bytes) + Base64 encoded scte payload (x bytes)


// Modify the payload size at pos 2 (zero indexed)
// [0] 0x06 SEI NAL
// [1] 0x05 Unregistered user data
// [2] Payload size
sei.at(2) = 16 + 2 + 8 + scteMessage.GetSize(); // UUID 16 bytes + SCTE ID (2 bytes) + TS (8 bytes) + Scte payload (x bytes)

// Insert 2 byte scte message ID
scteMessageId++;
sei.insert(sei.end(), (uint8_t*)&scteMessageId, (uint8_t*)&scteMessageId + sizeof(uint16_t));

// Insert 8 byte timestamp
sei.insert(sei.end(), (uint8_t*)&scteTimestamp, (uint8_t*)&scteTimestamp + sizeof(uint64_t));

// scte payload
sei.insert(sei.end(), scteMessage.GetData(), scteMessage.GetData() + scteMessage.GetSize());

// rbsp_trailing_bits
sei.push_back(0x80);
}
13 changes: 13 additions & 0 deletions src/h264/H264Packetizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class H264Packetizer : public H26xPacketizer
H264Packetizer();
std::unique_ptr<MediaFrame> ProcessAU(BufferReader &reader) override;

void AppendScteData(uint64_t ts, const Buffer& data, uint8_t repeatCount);

protected:
void OnNal(VideoFrame& frame, BufferReader& nal, std::optional<bool>& frameEnd) override;
void EmitNal(VideoFrame& frame, BufferReader nal);
Expand All @@ -24,6 +26,17 @@ class H264Packetizer : public H26xPacketizer
bool noSPSInFrame = true;

std::unique_ptr<H264SeqParameterSet> sps;

Buffer scteMessage;
uint64_t scteTimestamp;
// To account for potential packet loss, we repeat the SEI containing
// scte tags for 20 frames to provide added resiliency.
// Also, we assume that another scte message cannot arrive within is interval
uint8_t scteFrameRepeatCount;
uint8_t repeatFrameCounter;
//Unregistered SEI message NAL
std::vector<uint8_t> sei;
uint16_t scteMessageId;
};

#endif // H264PACKETIZER_H

0 comments on commit ccdd3e3

Please sign in to comment.