/* GStreamer * Copyright (C) 2022 Seungha Yang * * 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 "win32ipcmmf.h" #include "win32ipcutils.h" #include GST_DEBUG_CATEGORY_EXTERN (gst_win32_ipc_debug); #define GST_CAT_DEFAULT gst_win32_ipc_debug struct Win32IpcMmf { explicit Win32IpcMmf (HANDLE f, void * b, UINT32 s, const std::string & n) : file (f), buffer (b), size (s), name (n), ref_count (1) { } ~Win32IpcMmf () { GST_TRACE ("Freeing %p (%s)", this, name.c_str ()); if (buffer) UnmapViewOfFile (buffer); if (file) CloseHandle (file); } HANDLE file; void *buffer; UINT32 size; std::string name; ULONG ref_count; }; static Win32IpcMmf * win32_pic_mmf_new (HANDLE file, UINT32 size, const char * name) { Win32IpcMmf *self; void *buffer; std::string msg; UINT err_code; buffer = MapViewOfFile (file, FILE_MAP_ALL_ACCESS, 0, 0, size); if (!buffer) { err_code = GetLastError (); msg = win32_ipc_error_message (err_code); GST_ERROR ("MapViewOfFile failed with 0x%x (%s)", err_code, msg.c_str ()); CloseHandle (file); return nullptr; } self = new Win32IpcMmf (file, buffer, size, name); return self; } /** * win32_ipc_mmf_alloc: * @size: Size of memory to allocate * @name: The name of Memory Mapped File * * Creates named shared memory * * Returns: a new Win32IpcMmf object */ Win32IpcMmf * win32_ipc_mmf_alloc (UINT32 size, const char * name) { HANDLE file; std::string msg; UINT err_code; if (!size) { GST_ERROR ("Zero size is not allowed"); return nullptr; } if (!name) { GST_ERROR ("Name must be specified"); return nullptr; } file = CreateFileMappingA (INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE | SEC_COMMIT, 0, size, name); if (!file) { err_code = GetLastError (); msg = win32_ipc_error_message (err_code); GST_ERROR ("CreateFileMappingA failed with 0x%x (%s)", err_code, msg.c_str ()); return nullptr; } /* The name is already occupied, it's caller's fault... */ if (GetLastError () == ERROR_ALREADY_EXISTS) { GST_ERROR ("File already exists"); CloseHandle (file); return nullptr; } return win32_pic_mmf_new (file, size, name); } /** * win32_ipc_mmf_open: * @size: Size of memory to allocate * @name: The name of Memory Mapped File * * Opens named shared memory * * Returns: a new Win32IpcMmf object */ Win32IpcMmf * win32_ipc_mmf_open (UINT32 size, const char * name) { HANDLE file; std::string msg; UINT err_code; if (!size) { GST_ERROR ("Zero size is not allowed"); return nullptr; } if (!name) { GST_ERROR ("Name must be specified"); return nullptr; } file = OpenFileMappingA (FILE_MAP_ALL_ACCESS, FALSE, name); if (!file) { err_code = GetLastError (); msg = win32_ipc_error_message (err_code); GST_ERROR ("OpenFileMappingA failed with 0x%x (%s)", err_code, msg.c_str ()); return nullptr; } return win32_pic_mmf_new (file, size, name); } /** * win32_ipc_mmf_get_name: * @mmf: a Win32IpcMmf object * * Returns: the name of @mmf */ const char * win32_ipc_mmf_get_name (Win32IpcMmf * mmf) { if (!mmf) return nullptr; return mmf->name.c_str (); } /** * win32_ipc_mmf_get_size: * @mmf: a Win32IpcMmf object * * Returns: the size of allocated memory */ UINT32 win32_ipc_mmf_get_size (Win32IpcMmf * mmf) { if (!mmf) return 0; return mmf->size; } /** * win32_ipc_mmf_get_raw: * @mmf: a Win32IpcMmf object * * Returns: the address of allocated memory */ void * win32_ipc_mmf_get_raw (Win32IpcMmf * mmf) { if (!mmf) return nullptr; return mmf->buffer; } /** * win32_ipc_mmf_ref: * @mmf: a Win32IpcMmf object * * Increase ref count */ Win32IpcMmf * win32_ipc_mmf_ref (Win32IpcMmf * mmf) { if (!mmf) return nullptr; InterlockedIncrement (&mmf->ref_count); return mmf; } /** * win32_ipc_mmf_unref: * @mmf: a Win32IpcMmf object * * Decrease ref count */ void win32_ipc_mmf_unref (Win32IpcMmf * mmf) { ULONG count; if (!mmf) return; count = InterlockedDecrement (&mmf->ref_count); if (count == 0) delete mmf; }