Implement Aggregation Packet construction for HEVC
This commit is contained in:
parent
6317abb58b
commit
a1981dfdfa
|
@ -12,6 +12,17 @@ namespace uvg_rtp {
|
|||
|
||||
namespace formats {
|
||||
|
||||
enum H265_NAL_TYPES {
|
||||
H265_PKT_AGGR = 48,
|
||||
H265_PKT_FRAG = 49
|
||||
};
|
||||
|
||||
struct h265_aggregation_packet {
|
||||
uint8_t nal_header[uvg_rtp::frame::HEADER_SIZE_H265_NAL];
|
||||
uvg_rtp::buf_vec buffers; /* discrete NAL units */
|
||||
uvg_rtp::buf_vec aggr_pkt; /* crafted aggregation packet */
|
||||
};
|
||||
|
||||
struct h265_headers {
|
||||
uint8_t nal_header[uvg_rtp::frame::HEADER_SIZE_H265_NAL];
|
||||
|
||||
|
@ -82,7 +93,14 @@ namespace uvg_rtp {
|
|||
rtp_error_t push_nal_unit(uint8_t *data, size_t data_len, bool more);
|
||||
|
||||
private:
|
||||
/* Construct an aggregation packet from data in "aggr_pkt_info_" */
|
||||
rtp_error_t make_aggregation_pkt();
|
||||
|
||||
/* Clear aggregation buffers */
|
||||
void clear_aggregation_info();
|
||||
|
||||
h265_frame_info_t finfo_;
|
||||
h265_aggregation_packet aggr_pkt_info_;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -14,26 +14,103 @@
|
|||
|
||||
#include "formats/h265.hh"
|
||||
|
||||
void uvg_rtp::formats::h265::clear_aggregation_info()
|
||||
{
|
||||
aggr_pkt_info_.buffers.clear();
|
||||
aggr_pkt_info_.aggr_pkt.clear();
|
||||
}
|
||||
|
||||
rtp_error_t uvg_rtp::formats::h265::make_aggregation_pkt()
|
||||
{
|
||||
rtp_error_t ret;
|
||||
|
||||
if (aggr_pkt_info_.buffers.empty())
|
||||
return RTP_INVALID_VALUE;
|
||||
|
||||
/* Only one buffer in the vector -> no need to create an aggregation packet */
|
||||
if (aggr_pkt_info_.buffers.size() == 1) {
|
||||
if ((ret = fqueue_->enqueue_message(aggr_pkt_info_.buffers)) != RTP_OK) {
|
||||
LOG_ERROR("Failed to enqueue Single NAL Unit packet!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return fqueue_->flush_queue();
|
||||
}
|
||||
|
||||
/* create header for the packet and craft the aggregation packet
|
||||
* according to the format defined in RFC 7798 */
|
||||
aggr_pkt_info_.nal_header[0] = H265_PKT_AGGR << 1;
|
||||
aggr_pkt_info_.nal_header[1] = 1;
|
||||
|
||||
aggr_pkt_info_.aggr_pkt.push_back(
|
||||
std::make_pair(
|
||||
uvg_rtp::frame::HEADER_SIZE_H265_NAL,
|
||||
aggr_pkt_info_.nal_header
|
||||
)
|
||||
);
|
||||
|
||||
for (size_t i = 0; i < aggr_pkt_info_.buffers.size(); ++i) {
|
||||
auto pkt_size = aggr_pkt_info_.buffers[i].first;
|
||||
aggr_pkt_info_.buffers[i].first = htons(aggr_pkt_info_.buffers[i].first);
|
||||
|
||||
aggr_pkt_info_.aggr_pkt.push_back(
|
||||
std::make_pair(
|
||||
sizeof(uint16_t),
|
||||
(uint8_t *)&aggr_pkt_info_.buffers[i].first
|
||||
)
|
||||
);
|
||||
|
||||
aggr_pkt_info_.aggr_pkt.push_back(
|
||||
std::make_pair(
|
||||
pkt_size,
|
||||
aggr_pkt_info_.buffers[i].second
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ((ret = fqueue_->enqueue_message(aggr_pkt_info_.aggr_pkt)) != RTP_OK) {
|
||||
LOG_ERROR("Failed to enqueue buffers of an aggregation packet!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
rtp_error_t uvg_rtp::formats::h265::push_nal_unit(uint8_t *data, size_t data_len, bool more)
|
||||
{
|
||||
if (data_len <= 3)
|
||||
return RTP_INVALID_VALUE;
|
||||
|
||||
uint8_t nal_type = (data[0] >> 1) & 0x3F;
|
||||
uint8_t nal_type = (data[0] >> 1) & 0x3f;
|
||||
rtp_error_t ret = RTP_OK;
|
||||
size_t data_left = data_len;
|
||||
size_t data_pos = 0;
|
||||
size_t payload_size = rtp_ctx_->get_payload_size();
|
||||
|
||||
if (data_len - 3 <= payload_size) {
|
||||
if ((ret = fqueue_->enqueue_message(data, data_len)) != RTP_OK) {
|
||||
LOG_ERROR("enqeueu failed for small packet");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (more)
|
||||
/* If there is more data coming in (possibly another small packet)
|
||||
* create entry to "aggr_pkt_info_" to construct an aggregation packet */
|
||||
if (more) {
|
||||
aggr_pkt_info_.buffers.push_back(std::make_pair(data_len, data));
|
||||
return RTP_NOT_READY;
|
||||
return fqueue_->flush_queue();
|
||||
} else {
|
||||
if (aggr_pkt_info_.buffers.empty()) {
|
||||
if ((ret = fqueue_->enqueue_message(data, data_len)) != RTP_OK) {
|
||||
LOG_ERROR("Failed to enqueue Single NAL Unit packet!");
|
||||
return ret;
|
||||
}
|
||||
return fqueue_->flush_queue();
|
||||
} else {
|
||||
(void)make_aggregation_pkt();
|
||||
ret = fqueue_->flush_queue();
|
||||
clear_aggregation_info();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* If smaller NALUs were queued before this NALU,
|
||||
* send them in an aggregation packet before proceeding with fragmentation */
|
||||
(void)make_aggregation_pkt();
|
||||
}
|
||||
|
||||
/* The payload is larger than MTU (1500 bytes) so we must split it into smaller RTP frames
|
||||
|
@ -47,8 +124,8 @@ rtp_error_t uvg_rtp::formats::h265::push_nal_unit(uint8_t *data, size_t data_len
|
|||
auto buffers = fqueue_->get_buffer_vector();
|
||||
auto headers = (uvg_rtp::formats::h265_headers *)fqueue_->get_media_headers();
|
||||
|
||||
headers->nal_header[0] = 49 << 1; /* fragmentation unit */
|
||||
headers->nal_header[1] = 1; /* temporal id */
|
||||
headers->nal_header[0] = H265_PKT_FRAG << 1; /* fragmentation unit */
|
||||
headers->nal_header[1] = 1; /* temporal id */
|
||||
|
||||
headers->fu_headers[0] = (uint8_t)((1 << 7) | nal_type);
|
||||
headers->fu_headers[1] = nal_type;
|
||||
|
@ -67,6 +144,7 @@ rtp_error_t uvg_rtp::formats::h265::push_nal_unit(uint8_t *data, size_t data_len
|
|||
|
||||
if ((ret = fqueue_->enqueue_message(buffers)) != RTP_OK) {
|
||||
LOG_ERROR("Queueing the message failed!");
|
||||
clear_aggregation_info();
|
||||
fqueue_->deinit_transaction();
|
||||
return ret;
|
||||
}
|
||||
|
@ -86,12 +164,15 @@ rtp_error_t uvg_rtp::formats::h265::push_nal_unit(uint8_t *data, size_t data_len
|
|||
|
||||
if ((ret = fqueue_->enqueue_message(buffers)) != RTP_OK) {
|
||||
LOG_ERROR("Failed to send HEVC frame!");
|
||||
clear_aggregation_info();
|
||||
fqueue_->deinit_transaction();
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (more)
|
||||
return RTP_NOT_READY;
|
||||
|
||||
clear_aggregation_info();
|
||||
return fqueue_->flush_queue();
|
||||
}
|
||||
|
||||
|
|
|
@ -130,6 +130,8 @@ rtp_error_t uvg_rtp::frame_queue::init_transaction(std::unique_ptr<uint8_t[]> da
|
|||
|
||||
rtp_error_t uvg_rtp::frame_queue::destroy_transaction(uvg_rtp::transaction_t *t)
|
||||
{
|
||||
fprintf(stderr, "destroying transaction\n");
|
||||
|
||||
if (!t)
|
||||
return RTP_INVALID_VALUE;
|
||||
|
||||
|
|
Loading…
Reference in New Issue