gstreamer/subprojects/gst-plugins-bad/sys/win32ipc/protocol/win32ipcprotocol.cpp
Seungha Yang c6a6c56cdf win32ipc: Add support for zero-copy rendering
* Extend protocol so that client can notify of releasing shared memory
* Server will hold shared memory object until it's released by client
* Add allocator/buffer pool to reuse shared memory objects and buffers

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3765>
2023-01-27 18:55:13 +00:00

292 lines
6.4 KiB
C++

/* GStreamer
* Copyright (C) 2022 Seungha Yang <seungha@centricular.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* SPDX-License-Identifier: MIT
*/
#include "win32ipcprotocol.h"
#include <string.h>
const char *
win32_ipc_pkt_type_to_string (Win32IpcPktType type)
{
switch (type) {
case WIN32_IPC_PKT_NEED_DATA:
return "NEED-DATA";
case WIN32_IPC_PKT_HAVE_DATA:
return "HAVE-DATA";
case WIN32_IPC_PKT_READ_DONE:
return "READ-DONE";
case WIN32_IPC_PKT_RELEASE_DATA:
return "RELEASE-DATA";
default:
break;
}
return "Unknown";
}
Win32IpcPktType
win32_ipc_pkt_type_from_raw (UINT8 type)
{
return (Win32IpcPktType) type;
}
UINT8
win32_ipc_pkt_type_to_raw (Win32IpcPktType type)
{
return (UINT8) type;
}
#define READ_UINT32(d,v) do { \
(*((UINT32 *) v)) = *((UINT32 *) d); \
(d) += sizeof (UINT32); \
} while (0)
#define WRITE_UINT32(d,v) do { \
*((UINT32 *) d) = v; \
(d) += sizeof (UINT32); \
} while (0)
#define READ_UINT64(d,v) do { \
(*((UINT64 *) v)) = *((UINT64 *) d); \
(d) += sizeof (UINT64); \
} while (0)
#define WRITE_UINT64(d,v) do { \
*((UINT64 *) d) = v; \
(d) += sizeof (UINT64); \
} while (0)
UINT32
win32_ipc_pkt_build_need_data (UINT8 * pkt, UINT32 pkt_len, UINT64 seq_num)
{
UINT8 *data = pkt;
if (!pkt || pkt_len < WIN32_IPC_PKT_NEED_DATA_SIZE)
return 0;
data[0] = win32_ipc_pkt_type_to_raw (WIN32_IPC_PKT_NEED_DATA);
data++;
WRITE_UINT64 (data, seq_num);
return WIN32_IPC_PKT_NEED_DATA_SIZE;
}
BOOL
win32_ipc_pkt_parse_need_data (UINT8 * pkt, UINT32 pkt_len, UINT64 * seq_num)
{
UINT8 *data = pkt;
if (!pkt || pkt_len < WIN32_IPC_PKT_NEED_DATA_SIZE)
return FALSE;
if (win32_ipc_pkt_type_from_raw (data[0]) != WIN32_IPC_PKT_NEED_DATA)
return FALSE;
data++;
READ_UINT64 (data, seq_num);
return TRUE;
}
UINT32
win32_ipc_pkt_build_have_data (UINT8 * pkt, UINT32 pkt_size, UINT64 seq_num,
const char * mmf_name, const Win32IpcVideoInfo * info)
{
UINT8 *data = pkt;
size_t len;
if (!pkt || !mmf_name || !info)
return 0;
len = strlen (mmf_name);
if (len == 0)
return 0;
len++;
if (pkt_size < WIN32_IPC_PKT_HAVE_DATA_SIZE + len)
return 0;
data[0] = win32_ipc_pkt_type_to_raw (WIN32_IPC_PKT_HAVE_DATA);
data++;
WRITE_UINT64 (data, seq_num);
strcpy ((char *) data, mmf_name);
data += len;
WRITE_UINT32 (data, info->format);
WRITE_UINT32 (data, info->width);
WRITE_UINT32 (data, info->height);
WRITE_UINT32 (data, info->fps_n);
WRITE_UINT32 (data, info->fps_d);
WRITE_UINT32 (data, info->par_n);
WRITE_UINT32 (data, info->par_d);
WRITE_UINT64 (data, info->size);
for (UINT i = 0; i < 4; i++)
WRITE_UINT64 (data, info->offset[i]);
for (UINT i = 0; i < 4; i++)
WRITE_UINT32 (data, info->stride[i]);
WRITE_UINT64 (data, info->qpc);
return data - pkt;
}
BOOL
win32_ipc_pkt_parse_have_data (UINT8 * pkt, UINT32 pkt_size, UINT64 * seq_num,
char * mmf_name, Win32IpcVideoInfo * info)
{
UINT8 *data = pkt;
size_t len;
if (!pkt || pkt_size < WIN32_IPC_PKT_HAVE_DATA_SIZE)
return FALSE;
if (win32_ipc_pkt_type_from_raw (pkt[0]) != WIN32_IPC_PKT_HAVE_DATA)
return FALSE;
data++;
READ_UINT64 (data, seq_num);
len = strnlen ((const char *) data, pkt_size - (data - pkt));
if (len == 0)
return FALSE;
len++;
if (pkt_size < WIN32_IPC_PKT_HAVE_DATA_SIZE + len)
return FALSE;
strcpy (mmf_name, (const char *) data);
data += len;
READ_UINT32 (data, &info->format);
READ_UINT32 (data, &info->width);
READ_UINT32 (data, &info->height);
READ_UINT32 (data, &info->fps_n);
READ_UINT32 (data, &info->fps_d);
READ_UINT32 (data, &info->par_n);
READ_UINT32 (data, &info->par_d);
READ_UINT64 (data, &info->size);
for (UINT i = 0; i < 4; i++)
READ_UINT64 (data, &info->offset[i]);
for (UINT i = 0; i < 4; i++)
READ_UINT32 (data, &info->stride[i]);
READ_UINT64 (data, &info->qpc);
return TRUE;
}
UINT32
win32_ipc_pkt_build_read_done (UINT8 * pkt, UINT32 pkt_len, UINT64 seq_num)
{
UINT8 *data = pkt;
if (!pkt || pkt_len < WIN32_IPC_PKT_READ_DONE_SIZE)
return 0;
data[0] = win32_ipc_pkt_type_to_raw (WIN32_IPC_PKT_READ_DONE);
data++;
WRITE_UINT64 (data, seq_num);
return WIN32_IPC_PKT_READ_DONE_SIZE;
}
BOOL
win32_ipc_pkt_parse_read_done (UINT8 * pkt, UINT32 pkt_len, UINT64 * seq_num)
{
UINT8 *data = pkt;
if (!pkt || pkt_len < WIN32_IPC_PKT_READ_DONE_SIZE)
return FALSE;
if (win32_ipc_pkt_type_from_raw (data[0]) != WIN32_IPC_PKT_READ_DONE)
return FALSE;
data++;
READ_UINT64 (data, seq_num);
return TRUE;
}
UINT32
win32_ipc_pkt_build_release_data (UINT8 * pkt, UINT32 pkt_size, UINT64 seq_num,
const char * mmf_name)
{
UINT8 *data = pkt;
size_t len;
if (!pkt || !mmf_name)
return 0;
len = strlen (mmf_name);
if (len == 0)
return 0;
len++;
data[0] = win32_ipc_pkt_type_to_raw (WIN32_IPC_PKT_RELEASE_DATA);
data++;
WRITE_UINT64 (data, seq_num);
strcpy ((char *) data, mmf_name);
data += len;
return data - pkt;
}
BOOL
win32_ipc_pkt_parse_release_data (UINT8 * pkt, UINT32 pkt_size,
UINT64 * seq_num, char * mmf_name)
{
UINT8 *data = pkt;
size_t len;
if (win32_ipc_pkt_type_from_raw (pkt[0]) != WIN32_IPC_PKT_RELEASE_DATA)
return FALSE;
data++;
READ_UINT64 (data, seq_num);
len = strnlen ((const char *) data, pkt_size - (data - pkt));
if (len == 0)
return FALSE;
len++;
strcpy (mmf_name, (const char *) data);
data += len;
return TRUE;
}