Skip to content

Commit 90d26c6

Browse files
committed
Linux: Remove filter_NAL and avoid copy
1 parent 7ab85d9 commit 90d26c6

File tree

5 files changed

+41
-79
lines changed

5 files changed

+41
-79
lines changed

alvr/server/cpp/platform/linux/CEncoder.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,6 @@ void CEncoder::Run() {
224224

225225
fprintf(stderr, "CEncoder starting to read present packets");
226226
present_packet frame_info;
227-
std::vector<uint8_t> encoded_data;
228227
while (not m_exiting) {
229228
read_latest(client, (char *)&frame_info, sizeof(frame_info), m_exiting);
230229

@@ -250,9 +249,8 @@ void CEncoder::Run() {
250249

251250
static_assert(sizeof(frame_info.pose) == sizeof(vr::HmdMatrix34_t&));
252251

253-
encoded_data.clear();
254-
uint64_t pts;
255-
if (!encode_pipeline->GetEncoded(encoded_data, &pts)) {
252+
alvr::FramePacket packet;
253+
if (!encode_pipeline->GetEncoded(packet)) {
256254
Error("Failed to get encoded data!");
257255
continue;
258256
}
@@ -279,10 +277,11 @@ void CEncoder::Run() {
279277
ReportPresent(pose->targetTimestampNs, present_offset);
280278
ReportComposed(pose->targetTimestampNs, composed_offset);
281279

282-
m_listener->SendVideo(encoded_data.data(), encoded_data.size(), pts);
280+
m_listener->SendVideo(packet.data, packet.size, packet.pts);
283281

284282
m_listener->GetStatistics()->EncodeOutput();
285283

284+
encode_pipeline->Free();
286285
}
287286
}
288287
catch (std::exception &e) {

alvr/server/cpp/platform/linux/EncodePipeline.cpp

Lines changed: 16 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -12,59 +12,6 @@ extern "C" {
1212
#include <libavcodec/avcodec.h>
1313
}
1414

15-
namespace {
16-
17-
bool should_keep_nal_h264(const uint8_t * header_start)
18-
{
19-
uint8_t nal_type = (header_start[2] == 0 ? header_start[4] : header_start[3]) & 0x1F;
20-
switch (nal_type)
21-
{
22-
case 6: // supplemental enhancement information
23-
case 9: // access unit delimiter
24-
return false;
25-
default:
26-
return true;
27-
}
28-
}
29-
30-
bool should_keep_nal_h265(const uint8_t * header_start)
31-
{
32-
uint8_t nal_type = ((header_start[2] == 0 ? header_start[4] : header_start[3]) >> 1) & 0x3F;
33-
switch (nal_type)
34-
{
35-
case 35: // access unit delimiter
36-
case 39: // supplemental enhancement information
37-
return false;
38-
default:
39-
return true;
40-
}
41-
}
42-
43-
void filter_NAL(const uint8_t* input, size_t input_size, std::vector<uint8_t> &out)
44-
{
45-
if (input_size < 4)
46-
return;
47-
auto codec = Settings::Instance().m_codec;
48-
std::array<uint8_t, 3> header = {{0, 0, 1}};
49-
auto end = input + input_size;
50-
auto header_start = input;
51-
while (header_start != end)
52-
{
53-
auto next_header = std::search(header_start + 3, end, header.begin(), header.end());
54-
if (next_header != end and next_header[-1] == 0)
55-
{
56-
next_header--;
57-
}
58-
if (codec == ALVR_CODEC_H264 and should_keep_nal_h264(header_start))
59-
out.insert(out.end(), header_start, next_header);
60-
if (codec == ALVR_CODEC_H265 and should_keep_nal_h265(header_start))
61-
out.insert(out.end(), header_start, next_header);
62-
header_start = next_header;
63-
}
64-
}
65-
66-
}
67-
6815
void alvr::EncodePipeline::SetBitrate(int64_t bitrate) {
6916
encoder_ctx->bit_rate = bitrate;
7017
encoder_ctx->rc_buffer_size = bitrate / Settings::Instance().m_refreshRate;
@@ -111,17 +58,24 @@ alvr::EncodePipeline::~EncodePipeline()
11158
avcodec_free_context(&encoder_ctx);
11259
}
11360

114-
bool alvr::EncodePipeline::GetEncoded(std::vector<uint8_t> &out, uint64_t *pts)
61+
bool alvr::EncodePipeline::GetEncoded(FramePacket &packet)
11562
{
116-
AVPacket * enc_pkt = av_packet_alloc();
117-
int err = avcodec_receive_packet(encoder_ctx, enc_pkt);
118-
if (err == AVERROR(EAGAIN)) {
119-
return false;
120-
} else if (err) {
63+
encoder_packet = av_packet_alloc();
64+
int err = avcodec_receive_packet(encoder_ctx, encoder_packet);
65+
if (err != 0) {
66+
av_packet_free(&encoder_packet);
67+
if (err == AVERROR(EAGAIN)) {
68+
return false;
69+
}
12170
throw alvr::AvException("failed to encode", err);
12271
}
123-
filter_NAL(enc_pkt->data, enc_pkt->size, out);
124-
*pts = enc_pkt->pts;
125-
av_packet_free(&enc_pkt);
72+
packet->data = encoder_packet->data;
73+
packet->size = encoder_packet->size;
74+
packet->pts = encoder_packet->pts;
12675
return true;
12776
}
77+
78+
void alvr::EncodePipeline::Free()
79+
{
80+
av_packet_free(&encoder_packet);
81+
}

alvr/server/cpp/platform/linux/EncodePipeline.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ class VkFrame;
1414
class VkFrameCtx;
1515
class VkContext;
1616

17+
struct FramePacket {
18+
uint8_t *data;
19+
int size;
20+
uint64_t pts;
21+
};
22+
1723
class EncodePipeline
1824
{
1925
public:
@@ -25,13 +31,15 @@ class EncodePipeline
2531
virtual ~EncodePipeline();
2632

2733
virtual void PushFrame(uint64_t targetTimestampNs, bool idr) = 0;
28-
virtual bool GetEncoded(std::vector<uint8_t> & out, uint64_t *pts);
34+
virtual bool GetEncoded(FramePacket &data);
35+
virtual void Free();
2936
virtual Timestamp GetTimestamp() { return timestamp; }
3037

3138
virtual void SetBitrate(int64_t bitrate);
3239
static std::unique_ptr<EncodePipeline> Create(Renderer *render, VkContext &vk_ctx, VkFrame &input_frame, VkFrameCtx &vk_frame_ctx, uint32_t width, uint32_t height);
3340
protected:
3441
AVCodecContext *encoder_ctx = nullptr; //shall be initialized by child class
42+
AVPacket *encoder_packet = NULL;
3543
Timestamp timestamp = {};
3644
};
3745

alvr/server/cpp/platform/linux/EncodePipelineAMF.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -456,26 +456,24 @@ void EncodePipelineAMF::PushFrame(uint64_t targetTimestampNs, bool idr)
456456
m_amfComponents.front()->SubmitInput(surface);
457457
}
458458

459-
bool EncodePipelineAMF::GetEncoded(std::vector<uint8_t> &out, uint64_t *pts)
459+
bool EncodePipelineAMF::GetEncoded(FramePacket &packet)
460460
{
461461
if (m_hasQueryTimeout) {
462462
m_pipeline->Run();
463463
} else {
464464
uint32_t timeout = 4 * 1000; // 1 second
465-
while (m_outBuffer.empty() && --timeout != 0) {
465+
while (m_framePacket->data == nullptr && --timeout != 0) {
466466
std::this_thread::sleep_for(std::chrono::microseconds(250));
467467
m_pipeline->Run();
468468
}
469469
}
470470

471-
if (m_outBuffer.empty()) {
471+
if (m_framePacket->data == nullptr) {
472472
Error("Timed out waiting for encoder data");
473473
return false;
474474
}
475475

476-
out = m_outBuffer;
477-
*pts = m_targetTimestampNs;
478-
m_outBuffer.clear();
476+
packet = m_framePacket;
479477

480478
uint64_t query;
481479
VK_CHECK(vkGetQueryPoolResults(m_render->m_dev, m_queryPool, 0, 1, sizeof(uint64_t), &query, sizeof(uint64_t), VK_QUERY_RESULT_64_BIT));
@@ -484,6 +482,10 @@ bool EncodePipelineAMF::GetEncoded(std::vector<uint8_t> &out, uint64_t *pts)
484482
return true;
485483
}
486484

485+
void EncodePipelineAMF::Free() {
486+
m_framePacket = {nullptr, 0, 0};
487+
}
488+
487489
void EncodePipelineAMF::SetBitrate(int64_t bitrate)
488490
{
489491
if (m_codec == ALVR_CODEC_H264) {
@@ -501,10 +503,9 @@ void EncodePipelineAMF::Receive(amf::AMFDataPtr data)
501503
{
502504
amf::AMFBufferPtr buffer(data); // query for buffer interface
503505

504-
char *p = reinterpret_cast<char*>(buffer->GetNative());
505-
int length = static_cast<int>(buffer->GetSize());
506-
507-
m_outBuffer = std::vector<uint8_t>(p, p + length);
506+
m_framePacket->data = reinterpret_cast<uint8_t *>(buffer->GetNative());
507+
m_framePacket->size = static_cast<int>(buffer->GetSize());
508+
m_framePacket->pts = m_targetTimestampNs;
508509
}
509510

510511
void EncodePipelineAMF::ApplyFrameProperties(const amf::AMFSurfacePtr &surface, bool insertIDR)

alvr/server/cpp/platform/linux/EncodePipelineAMF.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ class EncodePipelineAMF : public EncodePipeline
9696
int m_bitrateInMBits;
9797

9898
bool m_hasQueryTimeout = false;
99-
std::vector<uint8_t> m_outBuffer;
99+
FramePacket m_framePacket = {nullptr, 0, 0};
100100
uint64_t m_targetTimestampNs;
101101
};
102102

0 commit comments

Comments
 (0)