Add unique_ptr support for RTP writer API and all media formats
This commit is contained in:
parent
45d2a4ec26
commit
434a07156c
|
|
@ -33,6 +33,21 @@ rtp_error_t kvz_rtp::generic::push_frame(kvz_rtp::connection *conn, uint8_t *dat
|
|||
return kvz_rtp::send::send_frame(conn, header, sizeof(header), data, data_len);
|
||||
}
|
||||
|
||||
rtp_error_t kvz_rtp::generic::push_frame(kvz_rtp::connection *conn, std::unique_ptr<uint8_t[]> data, size_t data_len, int flags)
|
||||
{
|
||||
(void)flags;
|
||||
|
||||
if (data_len > MAX_PAYLOAD) {
|
||||
LOG_WARN("packet is larger (%zu bytes) than MAX_PAYLOAD (%u bytes)", data_len, MAX_PAYLOAD);
|
||||
}
|
||||
|
||||
uint8_t header[kvz_rtp::frame::HEADER_SIZE_RTP];
|
||||
conn->fill_rtp_header(header);
|
||||
|
||||
/* We don't need to transfer the ownership of of "data" to socket because send_frame() executes immediately */
|
||||
return kvz_rtp::send::send_frame(conn, header, sizeof(header), data.get(), data_len);
|
||||
}
|
||||
|
||||
rtp_error_t kvz_rtp::generic::frame_receiver(kvz_rtp::reader *reader)
|
||||
{
|
||||
LOG_INFO("Generic frame receiver starting...");
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ namespace kvz_rtp {
|
|||
/* TODO: */
|
||||
rtp_error_t push_frame(kvz_rtp::connection *conn, uint8_t *data, size_t data_len, int flags);
|
||||
|
||||
/* TODO: */
|
||||
rtp_error_t push_frame(kvz_rtp::connection *conn, std::unique_ptr<uint8_t[]> data, size_t data_len, int flags);
|
||||
|
||||
/* TODO: */
|
||||
rtp_error_t frame_receiver(kvz_rtp::reader *reader);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ end:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static rtp_error_t __push_hevc_frame(
|
||||
static rtp_error_t __push_hevc_nal(
|
||||
kvz_rtp::connection *conn,
|
||||
kvz_rtp::frame_queue *fqueue,
|
||||
uint8_t *data, size_t data_len,
|
||||
|
|
@ -298,7 +298,9 @@ static rtp_error_t __push_hevc_frame(
|
|||
return ret;
|
||||
}
|
||||
|
||||
return fqueue->flush_queue(conn);
|
||||
int retzzz = fqueue->flush_queue(conn);
|
||||
fprintf(stderr, "kvzrtp: %d %u\n", ret, ret);
|
||||
return (rtp_error_t)retzzz;
|
||||
#else
|
||||
if (data_len <= MAX_PAYLOAD) {
|
||||
LOG_DEBUG("send unfrag size %zu, type %u", data_len, nalType);
|
||||
|
|
@ -347,8 +349,12 @@ static rtp_error_t __push_hevc_frame(
|
|||
#endif
|
||||
}
|
||||
|
||||
/* TODO: mitä speksi sanoo slicejen lähettämisestä */
|
||||
rtp_error_t __push_hevc_slice(kvz_rtp::connection *conn, uint8_t *data, size_t data_len, int flags)
|
||||
static rtp_error_t __push_hevc_slice(
|
||||
kvz_rtp::connection *conn,
|
||||
kvz_rtp::frame_queue *fqueue,
|
||||
uint8_t *data, size_t data_len,
|
||||
int flags
|
||||
)
|
||||
{
|
||||
rtp_error_t ret;
|
||||
|
||||
|
|
@ -357,9 +363,6 @@ rtp_error_t __push_hevc_slice(kvz_rtp::connection *conn, uint8_t *data, size_t d
|
|||
return RTP_INVALID_VALUE;
|
||||
}
|
||||
|
||||
kvz_rtp::frame_queue *fqueue = conn->get_frame_queue();
|
||||
(void)fqueue->init_transaction(conn);
|
||||
|
||||
if (data_len >= MAX_PAYLOAD) {
|
||||
LOG_ERROR("slice is too big!");
|
||||
(void)fqueue->deinit_transaction();
|
||||
|
|
@ -378,10 +381,15 @@ rtp_error_t __push_hevc_slice(kvz_rtp::connection *conn, uint8_t *data, size_t d
|
|||
return ret;
|
||||
}
|
||||
|
||||
rtp_error_t kvz_rtp::hevc::push_frame(kvz_rtp::connection *conn, uint8_t *data, size_t data_len, int flags)
|
||||
static rtp_error_t __push_hevc_frame(
|
||||
kvz_rtp::connection *conn,
|
||||
kvz_rtp::frame_queue *fqueue,
|
||||
uint8_t *data, size_t data_len,
|
||||
int flags
|
||||
)
|
||||
{
|
||||
if (flags & RTP_SLICE)
|
||||
return __push_hevc_slice(conn, data, data_len, flags);
|
||||
return __push_hevc_slice(conn, fqueue, data, data_len, flags);
|
||||
|
||||
#ifdef __linux__
|
||||
/* find first start code */
|
||||
|
|
@ -396,14 +404,11 @@ rtp_error_t kvz_rtp::hevc::push_frame(kvz_rtp::connection *conn, uint8_t *data,
|
|||
return kvz_rtp::generic::push_frame(conn, data + r_off, data_len - r_off, flags);
|
||||
}
|
||||
|
||||
kvz_rtp::frame_queue *fqueue = conn->get_frame_queue();
|
||||
(void)fqueue->init_transaction(conn);
|
||||
|
||||
while (offset != -1) {
|
||||
offset = __get_hevc_start(data, data_len, offset, start_len);
|
||||
|
||||
if (offset != -1) {
|
||||
ret = __push_hevc_frame(conn, fqueue, &data[prev_offset], offset - prev_offset - start_len, true);
|
||||
ret = __push_hevc_nal(conn, fqueue, &data[prev_offset], offset - prev_offset - start_len, true);
|
||||
|
||||
if (ret != RTP_NOT_READY)
|
||||
goto error;
|
||||
|
|
@ -412,7 +417,7 @@ rtp_error_t kvz_rtp::hevc::push_frame(kvz_rtp::connection *conn, uint8_t *data,
|
|||
}
|
||||
}
|
||||
|
||||
if ((ret = __push_hevc_frame(conn, fqueue, &data[prev_offset], data_len - prev_offset, false)) == RTP_OK)
|
||||
if ((ret = __push_hevc_nal(conn, fqueue, &data[prev_offset], data_len - prev_offset, false)) == RTP_OK)
|
||||
return RTP_OK;
|
||||
|
||||
error:
|
||||
|
|
@ -428,7 +433,7 @@ error:
|
|||
offset = __get_hevc_start(data, data_len, offset, start_len);
|
||||
|
||||
if (offset > 4 && offset != -1) {
|
||||
if (__push_hevc_frame(conn, nullptr, &data[prev_offset], offset - prev_offset - start_len, false) == -1)
|
||||
if (__push_hevc_nal(conn, nullptr, &data[prev_offset], offset - prev_offset - start_len, false) == -1)
|
||||
return RTP_GENERIC_ERROR;
|
||||
|
||||
prev_offset = offset;
|
||||
|
|
@ -438,10 +443,56 @@ error:
|
|||
if (prev_offset == -1)
|
||||
prev_offset = 0;
|
||||
|
||||
return __push_hevc_frame(conn, nullptr, &data[prev_offset], data_len - prev_offset, false);
|
||||
return __push_hevc_nal(conn, nullptr, &data[prev_offset], data_len - prev_offset, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
rtp_error_t kvz_rtp::hevc::push_frame(kvz_rtp::connection *conn, uint8_t *data, size_t data_len, int flags)
|
||||
{
|
||||
if (!conn || !data || data_len == 0)
|
||||
return RTP_INVALID_VALUE;
|
||||
|
||||
rtp_error_t ret = RTP_GENERIC_ERROR;
|
||||
kvz_rtp::frame_queue *fqueue = conn->get_frame_queue();
|
||||
|
||||
if (!fqueue || (ret = fqueue->init_transaction(conn, data, flags)) != RTP_OK) {
|
||||
LOG_ERROR("Invalid frame queue or failed to initialize transaction!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (flags & RTP_SLICE)
|
||||
return __push_hevc_slice(conn, fqueue, data, data_len, flags);
|
||||
return __push_hevc_frame(conn, fqueue, data, data_len, flags);
|
||||
}
|
||||
|
||||
rtp_error_t kvz_rtp::hevc::push_frame(kvz_rtp::connection *conn, std::unique_ptr<uint8_t[]> data, size_t data_len, int flags)
|
||||
{
|
||||
if (!conn || !data || data_len == 0)
|
||||
return RTP_INVALID_VALUE;
|
||||
|
||||
if (!conn || !data || data_len == 0)
|
||||
return RTP_INVALID_VALUE;
|
||||
|
||||
uint8_t *data_ptr = nullptr;
|
||||
rtp_error_t ret = RTP_GENERIC_ERROR;
|
||||
kvz_rtp::frame_queue *fqueue = conn->get_frame_queue();
|
||||
|
||||
if (!fqueue || (ret = fqueue->init_transaction(conn, std::move(data))) != RTP_OK) {
|
||||
LOG_ERROR("Invalid frame queue or failed to initialize transaction!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((data_ptr = fqueue->get_active_dataptr()) == nullptr) {
|
||||
LOG_ERROR("Invalid data pointer, cannot continue!");
|
||||
return RTP_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if (flags & RTP_SLICE)
|
||||
return __push_hevc_slice(conn, fqueue, data_ptr, data_len, flags);
|
||||
return __push_hevc_frame(conn, fqueue, data_ptr, data_len, flags);
|
||||
|
||||
}
|
||||
|
||||
rtp_error_t kvz_rtp::hevc::frame_receiver(kvz_rtp::reader *reader)
|
||||
{
|
||||
#ifdef __RTP_USE_OPTIMISTIC_RECEIVER__
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@ namespace kvz_rtp {
|
|||
/* TODO: */
|
||||
rtp_error_t push_frame(kvz_rtp::connection *conn, uint8_t *data, size_t data_len, int flags);
|
||||
|
||||
/* TODO: */
|
||||
rtp_error_t push_frame(kvz_rtp::connection *conn, std::unique_ptr<uint8_t[]> data, size_t data_len, int flags);
|
||||
|
||||
/* TODO: */
|
||||
rtp_error_t frame_receiver(kvz_rtp::reader *reader);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -44,6 +44,11 @@ rtp_error_t kvz_rtp::opus::push_frame(connection *conn, uint8_t *data, uint32_t
|
|||
#endif
|
||||
}
|
||||
|
||||
rtp_error_t kvz_rtp::opus::push_frame(connection *conn, std::unique_ptr<uint8_t[]> data, uint32_t data_len, int flags)
|
||||
{
|
||||
return kvz_rtp::generic::push_frame(conn, std::move(data), data_len, flags);
|
||||
}
|
||||
|
||||
kvz_rtp::frame::rtp_frame *kvz_rtp::opus::process_opus_frame(
|
||||
kvz_rtp::frame::rtp_frame *frame,
|
||||
std::pair<size_t, std::vector<kvz_rtp::frame::rtp_frame *>>& fu,
|
||||
|
|
|
|||
|
|
@ -10,8 +10,12 @@ namespace kvz_rtp {
|
|||
uint8_t config_number;
|
||||
};
|
||||
|
||||
/* TODO: */
|
||||
rtp_error_t push_frame(connection *conn, uint8_t *data, uint32_t data_len, int flags);
|
||||
|
||||
/* TODO: */
|
||||
rtp_error_t push_frame(connection *conn, std::unique_ptr<uint8_t[]> data, uint32_t data_len, int flags);
|
||||
|
||||
/* Process the incoming Opus frame
|
||||
* The RTP frame "frame" given as parameter should be considered invalid after calling this function
|
||||
* and no operatios should be performed on it after the function has returned.
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ rtp_error_t kvz_rtp::writer::start()
|
|||
return RTP_OK;
|
||||
}
|
||||
|
||||
rtp_error_t kvz_rtp::writer::push_frame(uint8_t *data, uint32_t data_len, int flags)
|
||||
rtp_error_t kvz_rtp::writer::push_frame(uint8_t *data, size_t data_len, int flags)
|
||||
{
|
||||
switch (get_payload()) {
|
||||
case RTP_FORMAT_HEVC:
|
||||
|
|
@ -96,6 +96,21 @@ rtp_error_t kvz_rtp::writer::push_frame(uint8_t *data, uint32_t data_len, int fl
|
|||
}
|
||||
}
|
||||
|
||||
rtp_error_t kvz_rtp::writer::push_frame(std::unique_ptr<uint8_t[]> data, size_t data_len, int flags)
|
||||
{
|
||||
switch (get_payload()) {
|
||||
case RTP_FORMAT_HEVC:
|
||||
return kvz_rtp::hevc::push_frame(this, std::move(data), data_len, flags);
|
||||
|
||||
case RTP_FORMAT_OPUS:
|
||||
return kvz_rtp::opus::push_frame(this, std::move(data), data_len, flags);
|
||||
|
||||
default:
|
||||
LOG_DEBUG("Format not recognized, pushing the frame as generic");
|
||||
return kvz_rtp::generic::push_frame(this, std::move(data), data_len, flags);
|
||||
}
|
||||
}
|
||||
|
||||
sockaddr_in kvz_rtp::writer::get_out_address()
|
||||
{
|
||||
return addr_out_;
|
||||
|
|
|
|||
|
|
@ -11,15 +11,38 @@ namespace kvz_rtp {
|
|||
class writer : public connection {
|
||||
|
||||
public:
|
||||
/* "src_port" is an optional argument, given if holepunching want to be used */
|
||||
writer(rtp_format_t fmt, std::string dst_addr, int dst_port);
|
||||
writer(rtp_format_t fmt, std::string dst_addr, int dst_port, int src_port);
|
||||
~writer();
|
||||
|
||||
// open socket for sending frames
|
||||
/* Open socket for sending frames and start SCD if enabled
|
||||
* Start RTCP instance if not already started
|
||||
*
|
||||
* Return RTP_OK on success
|
||||
* Return RTP_SOCKET_ERROR if the socket couldn't be initialized
|
||||
* Return RTP_BIND_ERROR if binding to src_port_ failed
|
||||
* Return RTP_MEMORY_ERROR if RTCP instance couldn't be allocated
|
||||
* Return RTP_GENERIC_ERROR for any other error condition */
|
||||
rtp_error_t start();
|
||||
|
||||
/* TODO: */
|
||||
rtp_error_t push_frame(uint8_t *data, uint32_t data_len, int flags);
|
||||
/* Split "data" into 1500 byte chunks and send them to remote
|
||||
*
|
||||
* NOTE: If SCD has been enabled, calling this version of push_frame()
|
||||
* requires either that the caller has given a deallocation callback to
|
||||
* SCD OR that "flags" contains flags "RTP_COPY"
|
||||
*
|
||||
* Return RTP_OK success
|
||||
* Return RTP_INVALID_VALUE if one of the parameters are invalid
|
||||
* Return RTP_MEMORY_ERROR if the data chunk is too large to be processed
|
||||
* Return RTP_SEND_ERROR if kvzRTP failed to send the data to remote
|
||||
* Return RTP_GENERIC_ERROR for any other error condition */
|
||||
rtp_error_t push_frame(uint8_t *data, size_t data_len, int flags);
|
||||
|
||||
/* Same as push_frame() defined above but no callback nor RTP_COPY must be provided
|
||||
* One must call this like: push_frame(std::move(data), ...) to give ownership of the
|
||||
* memory to kvzRTP */
|
||||
rtp_error_t push_frame(std::unique_ptr<uint8_t[]> data, size_t data_len, int flags);
|
||||
|
||||
/* TODO: remove */
|
||||
sockaddr_in get_out_address();
|
||||
|
|
|
|||
Loading…
Reference in New Issue