mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-27 02:30:35 +00:00
cudaipc: Add support for custom meta forwarding
Forward custom meta to peer ipcsrc elements Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6006>
This commit is contained in:
parent
c760c72f7a
commit
07ba225183
11 changed files with 387 additions and 62 deletions
|
@ -38,7 +38,10 @@
|
|||
|
||||
constexpr guint GST_CUDA_IPC_PKT_HAVE_DATA_PAYLOAD_MIN_SIZE =
|
||||
sizeof (GstClockTime) + sizeof (CUipcMemHandle) +
|
||||
sizeof (GstCudaIpcMemLayout) + sizeof (guint8);
|
||||
sizeof (GstCudaIpcMemLayout) + sizeof (guint) + sizeof (guint);
|
||||
constexpr guint GST_CUDA_IPC_PKT_HAVE_MMAP_DATA_PAYLOAD_MIN_SIZE =
|
||||
sizeof (GstClockTime) + sizeof (GstCudaSharableHandle) +
|
||||
sizeof (GstCudaIpcMemLayout) + sizeof (guint) + sizeof (guint);
|
||||
constexpr guint GST_CUDA_IPC_PKT_RELEASE_DATA_PAYLOAD_SIZE =
|
||||
sizeof (CUipcMemHandle);
|
||||
|
||||
|
@ -150,26 +153,28 @@ gst_cuda_ipc_pkt_build_need_data (std::vector < guint8 > &buf)
|
|||
/* *INDENT-OFF* */
|
||||
bool
|
||||
gst_cuda_ipc_pkt_build_have_data (std::vector < guint8 > &buf, GstClockTime pts,
|
||||
const GstVideoInfo & info, const CUipcMemHandle & handle, GstCaps * caps)
|
||||
const GstVideoInfo & info, const CUipcMemHandle & handle, GstCaps * caps,
|
||||
const std::vector<guint8> & meta)
|
||||
{
|
||||
GstCudaIpcPacketHeader header;
|
||||
GstCudaIpcMemLayout layout;
|
||||
guint8 *ptr;
|
||||
guint caps_len = 0;
|
||||
gchar *caps_str = nullptr;
|
||||
guint caps_size = 1;
|
||||
|
||||
if (caps) {
|
||||
caps_str = gst_caps_serialize (caps, GST_SERIALIZE_FLAG_NONE);
|
||||
if (!caps_str)
|
||||
return false;
|
||||
|
||||
caps_size += strlen (caps_str) + 1;
|
||||
caps_len = strlen (caps_str) + 1;
|
||||
}
|
||||
|
||||
header.type = GstCudaIpcPktType::HAVE_DATA;
|
||||
header.magic = GST_CUDA_IPC_MAGIC_NUMBER;
|
||||
header.payload_size = sizeof (GstClockTime) + sizeof (CUipcMemHandle) +
|
||||
sizeof (GstCudaIpcMemLayout) + caps_size;
|
||||
sizeof (GstCudaIpcMemLayout) + sizeof (guint) + caps_len +
|
||||
sizeof (guint) + meta.size ();
|
||||
|
||||
layout.size = layout.max_size = info.size;
|
||||
layout.pitch = info.stride[0];
|
||||
|
@ -191,35 +196,46 @@ gst_cuda_ipc_pkt_build_have_data (std::vector < guint8 > &buf, GstClockTime pts,
|
|||
memcpy (ptr, &handle, sizeof (CUipcMemHandle));
|
||||
ptr += sizeof (CUipcMemHandle);
|
||||
|
||||
if (caps) {
|
||||
*ptr = 1;
|
||||
ptr++;
|
||||
|
||||
*((guint *) ptr) = caps_len;
|
||||
ptr += sizeof (guint);
|
||||
if (caps_len > 0) {
|
||||
strcpy ((char *) ptr, caps_str);
|
||||
} else {
|
||||
*ptr = 0;
|
||||
ptr += caps_len;
|
||||
}
|
||||
|
||||
*((guint *) ptr) = meta.size ();
|
||||
ptr += sizeof (guint);
|
||||
if (!meta.empty ())
|
||||
memcpy (ptr, meta.data (), meta.size ());
|
||||
|
||||
g_free (caps_str);
|
||||
|
||||
return true;
|
||||
}
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#define DO_OFFSET(p,r,s) G_STMT_START { \
|
||||
(p) += s; \
|
||||
(r) -= s; \
|
||||
} G_STMT_END
|
||||
|
||||
bool
|
||||
gst_cuda_ipc_pkt_parse_have_data (const std::vector < guint8 > &buf,
|
||||
GstClockTime & pts, GstCudaIpcMemLayout & layout, CUipcMemHandle & handle,
|
||||
GstCaps ** caps)
|
||||
GstCaps ** caps, std::vector < guint8 > &meta)
|
||||
{
|
||||
GstCudaIpcPacketHeader header;
|
||||
const guint8 *ptr;
|
||||
std::string str;
|
||||
size_t remaining;
|
||||
|
||||
g_return_val_if_fail (buf.size () >=
|
||||
GST_CUDA_IPC_PKT_HEADER_SIZE +
|
||||
GST_CUDA_IPC_PKT_HAVE_DATA_PAYLOAD_MIN_SIZE, false);
|
||||
g_return_val_if_fail (caps, false);
|
||||
|
||||
meta.clear ();
|
||||
remaining = buf.size ();
|
||||
|
||||
ptr = &buf[0];
|
||||
memcpy (&header, ptr, GST_CUDA_IPC_PKT_HEADER_SIZE);
|
||||
|
||||
|
@ -228,25 +244,43 @@ gst_cuda_ipc_pkt_parse_have_data (const std::vector < guint8 > &buf,
|
|||
header.payload_size < GST_CUDA_IPC_PKT_HAVE_DATA_PAYLOAD_MIN_SIZE) {
|
||||
return false;
|
||||
}
|
||||
ptr += GST_CUDA_IPC_PKT_HEADER_SIZE;
|
||||
|
||||
DO_OFFSET (ptr, remaining, GST_CUDA_IPC_PKT_HEADER_SIZE);
|
||||
|
||||
memcpy (&pts, ptr, sizeof (GstClockTime));
|
||||
ptr += sizeof (GstClockTime);
|
||||
DO_OFFSET (ptr, remaining, sizeof (GstClockTime));
|
||||
|
||||
memcpy (&layout, ptr, sizeof (GstCudaIpcMemLayout));
|
||||
ptr += sizeof (GstCudaIpcMemLayout);
|
||||
DO_OFFSET (ptr, remaining, sizeof (GstCudaIpcMemLayout));
|
||||
|
||||
memcpy (&handle, ptr, sizeof (CUipcMemHandle));
|
||||
ptr += sizeof (CUipcMemHandle);
|
||||
DO_OFFSET (ptr, remaining, sizeof (CUipcMemHandle));
|
||||
|
||||
if (*ptr) {
|
||||
ptr++;
|
||||
auto caps_len = *((guint *) ptr);
|
||||
DO_OFFSET (ptr, remaining, sizeof (guint));
|
||||
if (caps_len > 0) {
|
||||
if (remaining < caps_len + sizeof (guint))
|
||||
return false;
|
||||
|
||||
*caps = gst_caps_from_string ((const gchar *) ptr);
|
||||
if (*caps == nullptr)
|
||||
return false;
|
||||
}
|
||||
|
||||
DO_OFFSET (ptr, remaining, caps_len);
|
||||
if (remaining < sizeof (guint))
|
||||
return false;
|
||||
|
||||
auto meta_len = *((guint *) ptr);
|
||||
DO_OFFSET (ptr, remaining, sizeof (guint));
|
||||
if (meta_len > 0) {
|
||||
if (remaining < meta_len)
|
||||
return false;
|
||||
|
||||
meta.resize (meta_len);
|
||||
memcpy (meta.data (), ptr, meta_len);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -254,26 +288,28 @@ gst_cuda_ipc_pkt_parse_have_data (const std::vector < guint8 > &buf,
|
|||
bool
|
||||
gst_cuda_ipc_pkt_build_have_mmap_data (std::vector<guint8> & buf,
|
||||
GstClockTime pts, const GstVideoInfo & info, guint32 max_size,
|
||||
GstCudaSharableHandle handle, GstCaps * caps)
|
||||
GstCudaSharableHandle handle, GstCaps * caps,
|
||||
const std::vector<guint8> & meta)
|
||||
{
|
||||
GstCudaIpcPacketHeader header;
|
||||
GstCudaIpcMemLayout layout;
|
||||
guint8 *ptr;
|
||||
guint caps_len = 0;
|
||||
gchar *caps_str = nullptr;
|
||||
guint caps_size = 1;
|
||||
|
||||
if (caps) {
|
||||
caps_str = gst_caps_serialize (caps, GST_SERIALIZE_FLAG_NONE);
|
||||
if (!caps_str)
|
||||
return false;
|
||||
|
||||
caps_size = strlen (caps_str) + 1;
|
||||
caps_len = strlen (caps_str) + 1;
|
||||
}
|
||||
|
||||
header.type = GstCudaIpcPktType::HAVE_MMAP_DATA;
|
||||
header.magic = GST_CUDA_IPC_MAGIC_NUMBER;
|
||||
header.payload_size = sizeof (GstClockTime) + sizeof (GstCudaIpcMemLayout) +
|
||||
sizeof (GstCudaSharableHandle) + caps_size;
|
||||
sizeof (GstCudaSharableHandle) + sizeof (guint) + caps_len +
|
||||
sizeof (guint) + meta.size ();
|
||||
|
||||
layout.size = info.size;
|
||||
layout.max_size = max_size;
|
||||
|
@ -296,15 +332,18 @@ gst_cuda_ipc_pkt_build_have_mmap_data (std::vector<guint8> & buf,
|
|||
*((GstCudaSharableHandle *) ptr) = handle;
|
||||
ptr += sizeof (GstCudaSharableHandle);
|
||||
|
||||
if (caps) {
|
||||
*ptr = 1;
|
||||
ptr++;
|
||||
|
||||
*((guint *) ptr) = caps_len;
|
||||
ptr += sizeof (guint);
|
||||
if (caps_len > 0) {
|
||||
strcpy ((char *) ptr, caps_str);
|
||||
} else {
|
||||
*ptr = 0;
|
||||
ptr += caps_len;
|
||||
}
|
||||
|
||||
*((guint *) ptr) = meta.size ();
|
||||
ptr += sizeof (guint);
|
||||
if (!meta.empty ())
|
||||
memcpy (ptr, meta.data (), meta.size ());
|
||||
|
||||
g_free (caps_str);
|
||||
|
||||
return true;
|
||||
|
@ -314,47 +353,66 @@ gst_cuda_ipc_pkt_build_have_mmap_data (std::vector<guint8> & buf,
|
|||
bool
|
||||
gst_cuda_ipc_pkt_parse_have_mmap_data (const std::vector < guint8 > &buf,
|
||||
GstClockTime & pts, GstCudaIpcMemLayout & layout,
|
||||
GstCudaSharableHandle * handle, GstCaps ** caps)
|
||||
GstCudaSharableHandle * handle, GstCaps ** caps,
|
||||
std::vector < guint8 > &meta)
|
||||
{
|
||||
GstCudaIpcPacketHeader header;
|
||||
const guint8 *ptr;
|
||||
std::string str;
|
||||
size_t remaining;
|
||||
|
||||
g_return_val_if_fail (buf.size () >
|
||||
g_return_val_if_fail (buf.size () >=
|
||||
GST_CUDA_IPC_PKT_HEADER_SIZE +
|
||||
sizeof (GstClockTime) + sizeof (GstCudaIpcMemLayout) +
|
||||
sizeof (GstCudaSharableHandle), false);
|
||||
GST_CUDA_IPC_PKT_HAVE_MMAP_DATA_PAYLOAD_MIN_SIZE, false);
|
||||
g_return_val_if_fail (caps, false);
|
||||
|
||||
meta.clear ();
|
||||
remaining = buf.size ();
|
||||
|
||||
ptr = &buf[0];
|
||||
memcpy (&header, ptr, GST_CUDA_IPC_PKT_HEADER_SIZE);
|
||||
|
||||
if (header.type != GstCudaIpcPktType::HAVE_MMAP_DATA ||
|
||||
header.magic != GST_CUDA_IPC_MAGIC_NUMBER ||
|
||||
header.payload_size <=
|
||||
sizeof (GstClockTime) + sizeof (GstCudaIpcMemLayout) +
|
||||
sizeof (GstCudaSharableHandle)) {
|
||||
header.payload_size < GST_CUDA_IPC_PKT_HAVE_MMAP_DATA_PAYLOAD_MIN_SIZE) {
|
||||
return false;
|
||||
}
|
||||
ptr += GST_CUDA_IPC_PKT_HEADER_SIZE;
|
||||
|
||||
DO_OFFSET (ptr, remaining, GST_CUDA_IPC_PKT_HEADER_SIZE);
|
||||
|
||||
memcpy (&pts, ptr, sizeof (GstClockTime));
|
||||
ptr += sizeof (GstClockTime);
|
||||
DO_OFFSET (ptr, remaining, sizeof (GstClockTime));
|
||||
|
||||
memcpy (&layout, ptr, sizeof (GstCudaIpcMemLayout));
|
||||
ptr += sizeof (GstCudaIpcMemLayout);
|
||||
DO_OFFSET (ptr, remaining, sizeof (GstCudaIpcMemLayout));
|
||||
|
||||
*handle = *((GstCudaSharableHandle *) ptr);
|
||||
ptr += sizeof (GstCudaSharableHandle);
|
||||
DO_OFFSET (ptr, remaining, sizeof (GstCudaSharableHandle));
|
||||
|
||||
if (*ptr) {
|
||||
ptr++;
|
||||
auto caps_len = *((guint *) ptr);
|
||||
DO_OFFSET (ptr, remaining, sizeof (guint));
|
||||
if (caps_len > 0) {
|
||||
if (remaining < caps_len + sizeof (guint))
|
||||
return false;
|
||||
|
||||
*caps = gst_caps_from_string ((const gchar *) ptr);
|
||||
if (*caps == nullptr)
|
||||
return false;
|
||||
}
|
||||
|
||||
DO_OFFSET (ptr, remaining, caps_len);
|
||||
if (remaining < sizeof (guint))
|
||||
return false;
|
||||
|
||||
auto meta_len = *((guint *) ptr);
|
||||
DO_OFFSET (ptr, remaining, sizeof (guint));
|
||||
if (meta_len > 0) {
|
||||
if (remaining < meta_len)
|
||||
return false;
|
||||
|
||||
meta.resize (meta_len);
|
||||
memcpy (meta.data (), ptr, meta_len);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -134,26 +134,30 @@ bool gst_cuda_ipc_pkt_build_have_data (std::vector<guint8> & buf,
|
|||
GstClockTime pts,
|
||||
const GstVideoInfo & info,
|
||||
const CUipcMemHandle & handle,
|
||||
GstCaps * caps);
|
||||
GstCaps * caps,
|
||||
const std::vector<guint8> & meta);
|
||||
|
||||
bool gst_cuda_ipc_pkt_parse_have_data (const std::vector<guint8> & buf,
|
||||
GstClockTime & pts,
|
||||
GstCudaIpcMemLayout & layout,
|
||||
CUipcMemHandle & handle,
|
||||
GstCaps ** caps);
|
||||
GstCaps ** caps,
|
||||
std::vector<guint8> & meta);
|
||||
|
||||
bool gst_cuda_ipc_pkt_build_have_mmap_data (std::vector<guint8> & buf,
|
||||
GstClockTime pts,
|
||||
const GstVideoInfo & info,
|
||||
guint32 max_size,
|
||||
GstCudaSharableHandle handle,
|
||||
GstCaps * caps);
|
||||
GstCaps * caps,
|
||||
const std::vector<guint8> & meta);
|
||||
|
||||
bool gst_cuda_ipc_pkt_parse_have_mmap_data (const std::vector<guint8> & buf,
|
||||
GstClockTime & pts,
|
||||
GstCudaIpcMemLayout & layout,
|
||||
GstCudaSharableHandle * handle,
|
||||
GstCaps ** caps);
|
||||
GstCaps ** caps,
|
||||
std::vector<guint8> & meta);
|
||||
|
||||
void gst_cuda_ipc_pkt_build_read_done (std::vector<guint8> & buf);
|
||||
|
||||
|
|
|
@ -659,9 +659,10 @@ gst_cuda_ipc_client_have_data (GstCudaIpcClient * self)
|
|||
std::shared_ptr < GstCudaIpcImportData > import_data;
|
||||
std::unique_lock < std::mutex > lk (priv->lock);
|
||||
auto conn = priv->conn;
|
||||
std::vector < guint8 > meta;
|
||||
|
||||
if (!gst_cuda_ipc_pkt_parse_have_data (conn->server_msg,
|
||||
pts, layout, handle, &caps)) {
|
||||
pts, layout, handle, &caps, meta)) {
|
||||
GST_ERROR_OBJECT (self, "Couldn't parse HAVE-DATA packet");
|
||||
return false;
|
||||
}
|
||||
|
@ -774,6 +775,16 @@ gst_cuda_ipc_client_have_data (GstCudaIpcClient * self)
|
|||
GST_BUFFER_DTS (buffer) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
|
||||
|
||||
while (!meta.empty ()) {
|
||||
guint32 consumed = 0;
|
||||
if (!gst_meta_deserialize (buffer, meta.data (), meta.size (),
|
||||
&consumed) || consumed == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
meta.erase (meta.begin (), meta.begin () + consumed);
|
||||
}
|
||||
|
||||
sample = gst_sample_new (buffer, priv->caps, nullptr, nullptr);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
|
@ -1008,7 +1019,8 @@ gst_cuda_ipc_client_wait_msg_finish (GstCudaIpcClient * client, bool result)
|
|||
void
|
||||
gst_cuda_ipc_client_have_mmap_data (GstCudaIpcClient * client,
|
||||
GstClockTime pts, const GstCudaIpcMemLayout & layout, GstCaps * caps,
|
||||
GstCudaSharableHandle server_handle, GstCudaSharableHandle client_handle)
|
||||
GstCudaSharableHandle server_handle, GstCudaSharableHandle client_handle,
|
||||
std::vector < guint8 > &meta)
|
||||
{
|
||||
GstCudaIpcClientPrivate *priv = client->priv;
|
||||
std::unique_lock < std::mutex > lk (priv->lock);
|
||||
|
@ -1136,6 +1148,16 @@ gst_cuda_ipc_client_have_mmap_data (GstCudaIpcClient * client,
|
|||
GST_BUFFER_DTS (buffer) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
|
||||
|
||||
while (!meta.empty ()) {
|
||||
guint32 consumed = 0;
|
||||
if (!gst_meta_deserialize (buffer, meta.data (), meta.size (),
|
||||
&consumed) || consumed == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
meta.erase (meta.begin (), meta.begin () + consumed);
|
||||
}
|
||||
|
||||
sample = gst_sample_new (buffer, priv->caps, nullptr, nullptr);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
|
|
|
@ -111,7 +111,8 @@ void gst_cuda_ipc_client_have_mmap_data (GstCudaIpcClient * client
|
|||
const GstCudaIpcMemLayout & layout,
|
||||
GstCaps * caps,
|
||||
GstCudaSharableHandle server_handle,
|
||||
GstCudaSharableHandle client_handle);
|
||||
GstCudaSharableHandle client_handle,
|
||||
std::vector <guint8> & meta);
|
||||
|
||||
void gst_cuda_ipc_client_on_idle (GstCudaIpcClient * client);
|
||||
|
||||
|
|
|
@ -188,9 +188,10 @@ gst_cuda_ipc_client_unix_finish_have_mmap_data (GstCudaIpcClient * client,
|
|||
GstCudaSharableHandle client_handle = 0;
|
||||
GstCaps *caps = nullptr;
|
||||
GError *err = nullptr;
|
||||
std::vector < guint8 > meta;
|
||||
|
||||
if (!gst_cuda_ipc_pkt_parse_have_mmap_data (conn->server_msg, pts,
|
||||
layout, &server_handle, &caps)) {
|
||||
layout, &server_handle, &caps, meta)) {
|
||||
GST_ERROR_OBJECT (client, "Couldn't parse MMAP-DATA");
|
||||
goto error;
|
||||
}
|
||||
|
@ -204,7 +205,7 @@ gst_cuda_ipc_client_unix_finish_have_mmap_data (GstCudaIpcClient * client,
|
|||
}
|
||||
|
||||
gst_cuda_ipc_client_have_mmap_data (client, pts, layout, caps,
|
||||
server_handle, client_handle);
|
||||
server_handle, client_handle, meta);
|
||||
return;
|
||||
|
||||
error:
|
||||
|
|
|
@ -195,6 +195,7 @@ gst_cuda_ipc_client_win32_finish_have_mmap_data (GstCudaIpcClient * client,
|
|||
GstCudaSharableHandle server_handle = nullptr;
|
||||
GstCudaSharableHandle client_handle = nullptr;
|
||||
GstCaps *caps = nullptr;
|
||||
std::vector < guint8 > meta;
|
||||
|
||||
if (!priv->server_process) {
|
||||
GST_ERROR_OBJECT (self, "Server process handle is not available");
|
||||
|
@ -202,7 +203,7 @@ gst_cuda_ipc_client_win32_finish_have_mmap_data (GstCudaIpcClient * client,
|
|||
}
|
||||
|
||||
if (!gst_cuda_ipc_pkt_parse_have_mmap_data (win32_conn->server_msg, pts,
|
||||
layout, &server_handle, &caps)) {
|
||||
layout, &server_handle, &caps, meta)) {
|
||||
GST_ERROR_OBJECT (self, "Couldn't parse MMAP-DATA");
|
||||
goto error;
|
||||
}
|
||||
|
@ -218,7 +219,7 @@ gst_cuda_ipc_client_win32_finish_have_mmap_data (GstCudaIpcClient * client,
|
|||
}
|
||||
|
||||
gst_cuda_ipc_client_have_mmap_data (client, pts, layout, caps,
|
||||
server_handle, client_handle);
|
||||
server_handle, client_handle, meta);
|
||||
return;
|
||||
|
||||
error:
|
||||
|
|
|
@ -123,7 +123,8 @@ gst_cuda_ipc_server_finalize (GObject * object)
|
|||
|
||||
GstFlowReturn
|
||||
gst_cuda_ipc_server_send_data (GstCudaIpcServer * server, GstSample * sample,
|
||||
const GstVideoInfo & info, const CUipcMemHandle & handle, GstClockTime pts)
|
||||
const GstVideoInfo & info, const CUipcMemHandle & handle, GstClockTime pts,
|
||||
GByteArray * meta)
|
||||
{
|
||||
GstCudaIpcServerPrivate *priv;
|
||||
GstCudaIpcServerClass *klass;
|
||||
|
@ -153,6 +154,10 @@ gst_cuda_ipc_server_send_data (GstCudaIpcServer * server, GstSample * sample,
|
|||
data->handle = handle;
|
||||
data->pts = pts;
|
||||
data->seq_num = priv->seq_num;
|
||||
if (meta && meta->len) {
|
||||
data->meta.resize (meta->len);
|
||||
memcpy (data->meta.data (), meta->data, meta->len);
|
||||
}
|
||||
|
||||
priv->seq_num++;
|
||||
priv->data = data;
|
||||
|
@ -166,7 +171,7 @@ gst_cuda_ipc_server_send_data (GstCudaIpcServer * server, GstSample * sample,
|
|||
GstFlowReturn
|
||||
gst_cuda_ipc_server_send_mmap_data (GstCudaIpcServer * server,
|
||||
GstSample * sample, const GstVideoInfo & info, GstCudaSharableHandle handle,
|
||||
GstClockTime pts)
|
||||
GstClockTime pts, GByteArray * meta)
|
||||
{
|
||||
GstCudaIpcServerPrivate *priv;
|
||||
GstCudaIpcServerClass *klass;
|
||||
|
@ -196,6 +201,10 @@ gst_cuda_ipc_server_send_mmap_data (GstCudaIpcServer * server,
|
|||
data->os_handle = handle;
|
||||
data->pts = pts;
|
||||
data->seq_num = priv->seq_num;
|
||||
if (meta && meta->len) {
|
||||
data->meta.resize (meta->len);
|
||||
memcpy (data->meta.data (), meta->data, meta->len);
|
||||
}
|
||||
|
||||
priv->seq_num++;
|
||||
priv->data = data;
|
||||
|
@ -373,7 +382,7 @@ gst_cuda_ipc_server_have_data (GstCudaIpcServer * self,
|
|||
handle_dump.c_str (), conn->id);
|
||||
|
||||
if (!gst_cuda_ipc_pkt_build_have_data (conn->server_msg, conn->data->pts,
|
||||
conn->data->info, conn->data->handle, caps)) {
|
||||
conn->data->info, conn->data->handle, caps, conn->data->meta)) {
|
||||
GST_ERROR_OBJECT (self, "Couldn't build HAVE-DATA pkt, conn-id: %u",
|
||||
conn->id);
|
||||
gst_cuda_ipc_server_close_connection (self, conn);
|
||||
|
@ -388,7 +397,7 @@ gst_cuda_ipc_server_have_data (GstCudaIpcServer * self,
|
|||
conn->id);
|
||||
if (!gst_cuda_ipc_pkt_build_have_mmap_data (conn->server_msg,
|
||||
conn->data->pts, conn->data->info, max_size, conn->data->os_handle,
|
||||
caps)) {
|
||||
caps, conn->data->meta)) {
|
||||
GST_ERROR_OBJECT (self, "Couldn't build HAVE-MMAP-DATA pkt, conn-id: %u",
|
||||
conn->id);
|
||||
gst_cuda_ipc_server_close_connection (self, conn);
|
||||
|
|
|
@ -86,13 +86,15 @@ GstFlowReturn gst_cuda_ipc_server_send_data (GstCudaIpcServer * server,
|
|||
GstSample * sample,
|
||||
const GstVideoInfo & info,
|
||||
const CUipcMemHandle & handle,
|
||||
GstClockTime pts);
|
||||
GstClockTime pts,
|
||||
GByteArray * meta);
|
||||
|
||||
GstFlowReturn gst_cuda_ipc_server_send_mmap_data (GstCudaIpcServer * server,
|
||||
GstSample * sample,
|
||||
const GstVideoInfo & info,
|
||||
GstCudaSharableHandle handle,
|
||||
GstClockTime pts);
|
||||
GstClockTime pts,
|
||||
GByteArray * meta);
|
||||
|
||||
|
||||
void gst_cuda_ipc_server_stop (GstCudaIpcServer * server);
|
||||
|
@ -133,6 +135,7 @@ struct GstCudaIpcServerData
|
|||
CUipcMemHandle handle;
|
||||
GstCudaSharableHandle os_handle;
|
||||
GstClockTime pts;
|
||||
std::vector<guint8> meta;
|
||||
guint64 seq_num;
|
||||
};
|
||||
|
||||
|
|
|
@ -79,6 +79,16 @@ enum
|
|||
/* *INDENT-OFF* */
|
||||
struct GstCudaIpcSinkPrivate
|
||||
{
|
||||
GstCudaIpcSinkPrivate ()
|
||||
{
|
||||
meta = g_byte_array_new ();
|
||||
}
|
||||
|
||||
~GstCudaIpcSinkPrivate ()
|
||||
{
|
||||
g_byte_array_unref (meta);
|
||||
}
|
||||
|
||||
GstCudaContext *context = nullptr;
|
||||
GstCudaStream *stream = nullptr;
|
||||
|
||||
|
@ -91,6 +101,7 @@ struct GstCudaIpcSinkPrivate
|
|||
GstVideoInfo mem_info;
|
||||
CUipcMemHandle prepared_handle;
|
||||
GstCudaSharableHandle prepared_os_handle;
|
||||
GByteArray *meta;
|
||||
|
||||
std::mutex lock;
|
||||
|
||||
|
@ -542,6 +553,20 @@ gst_cuda_ipc_sink_query (GstBaseSink * sink, GstQuery * query)
|
|||
return GST_BASE_SINK_CLASS (parent_class)->query (sink, query);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_cuda_ipc_sink_foreach_meta (GstBuffer * buffer, GstMeta ** meta,
|
||||
GstCudaIpcSink * self)
|
||||
{
|
||||
auto priv = self->priv;
|
||||
|
||||
if (!gst_meta_info_is_custom ((*meta)->info))
|
||||
return TRUE;
|
||||
|
||||
gst_meta_serialize_simple (*meta, priv->meta);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_cuda_ipc_sink_prepare (GstBaseSink * sink, GstBuffer * buf)
|
||||
{
|
||||
|
@ -642,6 +667,10 @@ gst_cuda_ipc_sink_prepare (GstBaseSink * sink, GstBuffer * buf)
|
|||
priv->prepared_sample = gst_sample_new (cuda_buf,
|
||||
priv->caps, nullptr, nullptr);
|
||||
|
||||
g_byte_array_set_size (priv->meta, 0);
|
||||
gst_buffer_foreach_meta (buf,
|
||||
(GstBufferForeachMetaFunc) gst_cuda_ipc_sink_foreach_meta, self);
|
||||
|
||||
if (cuda_buf != buf)
|
||||
gst_buffer_unref (cuda_buf);
|
||||
|
||||
|
@ -706,10 +735,11 @@ gst_cuda_ipc_sink_render (GstBaseSink * sink, GstBuffer * buf)
|
|||
|
||||
if (priv->ipc_mode == GST_CUDA_IPC_LEGACY) {
|
||||
ret = gst_cuda_ipc_server_send_data (priv->server, priv->prepared_sample,
|
||||
priv->mem_info, priv->prepared_handle, pts);
|
||||
priv->mem_info, priv->prepared_handle, pts, priv->meta);
|
||||
} else {
|
||||
ret = gst_cuda_ipc_server_send_mmap_data (priv->server,
|
||||
priv->prepared_sample, priv->mem_info, priv->prepared_os_handle, pts);
|
||||
priv->prepared_sample, priv->mem_info, priv->prepared_os_handle, pts,
|
||||
priv->meta);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
189
subprojects/gst-plugins-bad/tests/examples/nvcodec/cudaipc.c
Normal file
189
subprojects/gst-plugins-bad/tests/examples/nvcodec/cudaipc.c
Normal file
|
@ -0,0 +1,189 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2024 Seungha Yang <seungha@centricular.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#define CUSTOM_META_NAME "GstCudaIpcTestMeta"
|
||||
|
||||
static GstPadProbeReturn
|
||||
server_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
GstCustomMeta *meta;
|
||||
GstStructure *s;
|
||||
gchar *str;
|
||||
|
||||
buf = GST_PAD_PROBE_INFO_BUFFER (info);
|
||||
|
||||
meta = gst_buffer_add_custom_meta (buf, CUSTOM_META_NAME);
|
||||
s = gst_custom_meta_get_structure (meta);
|
||||
gst_structure_set (s, "foo", G_TYPE_STRING, "bar", "timestamp",
|
||||
G_TYPE_UINT64, GST_BUFFER_PTS (buf), NULL);
|
||||
str = gst_structure_serialize (s, GST_SERIALIZE_FLAG_NONE);
|
||||
|
||||
gst_println ("Added custom meta %s", str);
|
||||
|
||||
return GST_PAD_PROBE_OK;
|
||||
}
|
||||
|
||||
static GstElement *
|
||||
server_process (const gchar * address)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GstPad *sinkpad;
|
||||
GstElement *sink;
|
||||
GstElement *pipeline =
|
||||
gst_parse_launch
|
||||
("videotestsrc ! video/x-raw,format=RGBA,framerate=1/1 ! "
|
||||
"queue ! cudaupload ! cudaipcsink name=sink", &error);
|
||||
|
||||
if (!pipeline) {
|
||||
gst_printerrln ("couldn't create pipeline, err: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sink = gst_bin_get_by_name (GST_BIN (pipeline), "sink");
|
||||
g_assert (sink);
|
||||
|
||||
if (address)
|
||||
g_object_set (sink, "address", address, NULL);
|
||||
|
||||
sinkpad = gst_element_get_static_pad (sink, "sink");
|
||||
gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_BUFFER,
|
||||
(GstPadProbeCallback) server_probe_cb, NULL, NULL);
|
||||
gst_object_unref (sinkpad);
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
static GstPadProbeReturn
|
||||
client_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
GstCustomMeta *meta;
|
||||
|
||||
buf = GST_PAD_PROBE_INFO_BUFFER (info);
|
||||
|
||||
meta = gst_buffer_get_custom_meta (buf, CUSTOM_META_NAME);
|
||||
if (!meta) {
|
||||
gst_printerrln ("Buffer without meta");
|
||||
} else {
|
||||
GstStructure *s;
|
||||
gchar *str;
|
||||
|
||||
s = gst_custom_meta_get_structure (meta);
|
||||
str = gst_structure_serialize (s, GST_SERIALIZE_FLAG_NONE);
|
||||
gst_println ("Found custom meta \"%s\"", str);
|
||||
g_free (str);
|
||||
}
|
||||
|
||||
return GST_PAD_PROBE_OK;
|
||||
}
|
||||
|
||||
static GstElement *
|
||||
client_process (const gchar * address)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GstPad *srcpad;
|
||||
GstElement *src;
|
||||
GstElement *pipeline =
|
||||
gst_parse_launch ("cudaipcsrc name=src ! fakesink", &error);
|
||||
|
||||
if (!pipeline) {
|
||||
gst_printerrln ("couldn't create pipeline, err: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
src = gst_bin_get_by_name (GST_BIN (pipeline), "src");
|
||||
g_assert (src);
|
||||
|
||||
if (address)
|
||||
g_object_set (src, "address", address, NULL);
|
||||
|
||||
srcpad = gst_element_get_static_pad (src, "src");
|
||||
gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_BUFFER,
|
||||
(GstPadProbeCallback) client_probe_cb, NULL, NULL);
|
||||
gst_object_unref (srcpad);
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
gint
|
||||
main (gint argc, gchar ** argv)
|
||||
{
|
||||
GstElement *pipeline = NULL;
|
||||
GstStateChangeReturn sret;
|
||||
GError *error = NULL;
|
||||
GOptionContext *option_ctx;
|
||||
gboolean is_server = FALSE;
|
||||
gchar *address = NULL;
|
||||
gboolean ret;
|
||||
static const gchar *tags[] = { NULL };
|
||||
GOptionEntry options[] = {
|
||||
{"server", 0, 0, G_OPTION_ARG_NONE, &is_server,
|
||||
"Launch server process", NULL},
|
||||
{"address", 0, 0, G_OPTION_ARG_STRING, &address,
|
||||
"IPC communication address"},
|
||||
{NULL}
|
||||
};
|
||||
GMainLoop *loop;
|
||||
|
||||
option_ctx = g_option_context_new ("CUDA IPC example");
|
||||
g_option_context_add_main_entries (option_ctx, options, NULL);
|
||||
g_option_context_add_group (option_ctx, gst_init_get_option_group ());
|
||||
ret = g_option_context_parse (option_ctx, &argc, &argv, &error);
|
||||
g_option_context_free (option_ctx);
|
||||
|
||||
if (!ret) {
|
||||
g_printerr ("option parsing failed: %s\n", error->message);
|
||||
g_clear_error (&error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
gst_meta_register_custom ("GstCudaIpcTestMeta", tags, NULL, NULL, NULL);
|
||||
|
||||
if (is_server)
|
||||
pipeline = server_process (address);
|
||||
else
|
||||
pipeline = client_process (address);
|
||||
|
||||
if (!pipeline)
|
||||
return 1;
|
||||
|
||||
sret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
if (sret == GST_STATE_CHANGE_FAILURE) {
|
||||
g_printerr ("Pipeline doesn't want to playing\n");
|
||||
} else {
|
||||
g_main_loop_run (loop);
|
||||
}
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
gst_object_unref (pipeline);
|
||||
g_main_loop_unref (loop);
|
||||
g_free (address);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -4,3 +4,10 @@ executable('nvcodec',
|
|||
dependencies: [gst_dep, gstbase_dep, gstvideo_dep],
|
||||
c_args : gst_plugins_bad_args + ['-DGST_USE_UNSTABLE_API'],
|
||||
install: false)
|
||||
|
||||
executable('cudaipc', ['cudaipc.c'],
|
||||
c_args : gst_plugins_bad_args,
|
||||
include_directories : [configinc],
|
||||
dependencies: [gst_dep, gstbase_dep, gstvideo_dep],
|
||||
install: false)
|
||||
|
||||
|
|
Loading…
Reference in a new issue