Pipe API#
Oasis Pipe supports Inter-Process Communication (IPC).
It utilizes the oasis namespace.
It is specialized for transmitting video or audio data. It is useful when writing video data to a v4l2loopback device.
Oasis Pipe is not dependent on other Oasis components and can be used without oasis::initialize, allowing applications that do not use Oasis to also link with and use the liboasis_pipe.so library.
Header File#
OasisPipe.h
Type Definitions#
The data formats supported by Oasis Pipe are as follows. In the case of video, it is compatible with V4L2 formats.
enum {
kOasisPipeDataTypeUserData = 0,
kOasisPipeDataTypeVideoBGRA,
kOasisPipeDataTypeVideoARGB,
kOasisPipeDataTypeVideoYUYV,
kOasisPipeDataTypeVideoYVYU,
kOasisPipeDataTypeVideoYUV420,
kOasisPipeDataTypeVideoYVU420,
kOasisPipeDataTypeVideoNV12,
kOasisPipeDataTypeVideoNV21,
kOasisPipeDataTypeAudioPCM16LE,
kOasisPipeDataTypeAudioPCM16BE,
//in case of the following types, width_or_sampling_rate, height_or_channels, stride_or_bits_per_sample are ignored.
kOasisPipeDataTypeVideoH264,
kOasisPipeDataTypeVideoH265,
kOasisPipeDataTypeVideoVP8,
kOasisPipeDataTypeVideoVP9,
kOasisPipeDataTypeVideoMJPEG,
};
The conversion maps as follows:
| From | To |
|---|---|
| kOasisPipeDataTypeVideoBGRA | V4L2_PIX_FMT_ABGR32 |
| kOasisPipeDataTypeVideoARGB | V4L2_PIX_FMT_ARGB32 |
| kOasisPipeDataTypeVideoYUYV | V4L2_PIX_FMT_YUYV |
| kOasisPipeDataTypeVideoYVYU | V4L2_PIX_FMT_YYUV |
| kOasisPipeDataTypeVideoYUV420 | V4L2_PIX_FMT_YUV420 |
| kOasisPipeDataTypeVideoYVU420 | V4L2_PIX_FMT_YVU420 |
| kOasisPipeDataTypeVideoNV12 | V4L2_PIX_FMT_NV12 |
| kOasisPipeDataTypeVideoNV21 | V4L2_PIX_FMT_NV21 |
| kOasisPipeDataTypeVideoH264 | V4L2_PIX_FMT_H264 |
| kOasisPipeDataTypeVideoH265 | V4L2_PIX_FMT_H265 |
| kOasisPipeDataTypeVideoVP8 | V4L2_PIX_FMT_VP8 |
| kOasisPipeDataTypeVideoVP9 | V4L2_PIX_FMT_VP9 |
| kOasisPipeDataTypeVideoMJPEG | V4L2_PIX_FMT_MJPEG |
The conversion maps as follows:
| From | To |
|---|---|
| V4L2_PIX_FMT_BGR32 | kOasisPipeDataTypeVideoBGRA |
| V4L2_PIX_FMT_ABGR32 | kOasisPipeDataTypeVideoBGRA |
| V4L2_PIX_FMT_RGB32 | kOasisPipeDataTypeVideoARGB |
| V4L2_PIX_FMT_ARGB32 | kOasisPipeDataTypeVideoARGB |
| V4L2_PIX_FMT_YUYV | kOasisPipeDataTypeVideoYUYV |
| V4L2_PIX_FMT_YYUV | kOasisPipeDataTypeVideoYVYU |
| V4L2_PIX_FMT_YUV420 | kOasisPipeDataTypeVideoYUV420 |
| V4L2_PIX_FMT_YVU420 | kOasisPipeDataTypeVideoYVU420 |
| V4L2_PIX_FMT_NV12 | kOasisPipeDataTypeVideoNV12 |
| V4L2_PIX_FMT_NV21 | kOasisPipeDataTypeVideoNV21 |
| V4L2_PIX_FMT_H264 | kOasisPipeDataTypeVideoH264 |
| V4L2_PIX_FMT_H265 | kOasisPipeDataTypeVideoH265 |
| V4L2_PIX_FMT_VP8 | kOasisPipeDataTypeVideoVP8 |
| V4L2_PIX_FMT_VP9 | kOasisPipeDataTypeVideoVP9 |
| V4L2_PIX_FMT_MJPEG | kOasisPipeDataTypeVideoMJPEG |
Writer#
/dev/video, it is considered a v4l2loopback device, and the writer object is created for the purpose of writing video data.
- 0: Success
- -1: Failure
The error event callback function is as follows:
errno value.
Reader#
The type definition for the read callback function is as follows:
- 0: Success
- -1: Failure
Example#
Below is an example where one process requests an OFFS format via a pipe to another process and receives the response via a pipe.
The JsonCpp library is used for JSON processing.
Command Requesting Process#
Create the read and write pipes and register callbacks for each.
OasisPipeReaderRef pipe_reader_ = pipeReaderOpen("/tmp/oasis-mon-res");
pipeReaderSetCallback(pipe_reader_, std::bind(&onPipeCommandCompleted, _1, _2, _3, _4, _5, _6, _7));
OasisPipeWriterRef pipe_writer_ = pipeWriterOpen("/tmp/oasis-mon-req");
pipeWriterSetErrorCallback(pipe_writer_, std::bind(&onPipeCommandWriteError, _1, _2, _3, _4), nullptr);
The read callback function:
void onPipeCommandCompleted(const void *data, size_t length, int32_t width, int32_t height, int32_t stride, int32_t data_type, uint32_t flags)
{
std::string reply((const char*)data, (const char*)data+length);
Json::Value json_reply;
Json::Reader reader;
bool parsing_ok = reader.parse(reply.c_str(), json_reply);
if(!parsing_ok) {
return;
}
if(json_reply.isMember("result")) {
// Verifies the result.
int32_t result = std::stoi(json_reply["result"].asString());
}
}
The write error event callback function:
void DashApp::onPipeCommandWriteError(int32_t error, const void *data, size_t length, void *user)
{
}
Delivers the OFFS format command to the command executing process.
Json::Value json_req;
json_req["cmd"] = "format";
Json::FastWriter fastWriter;
std::string json_string = fastWriter.write(json_req);
pipeWriterWrite(pipe_writer_, json_string.c_str(), json_string.length(), 0, 0, 0, 0, 0);
Command Executing Process#
Create the read and write pipes and register callbacks for each. The paths used in the command requesting process are switched and used.
// Executes the command and delivers the result to the command requesting process.
OasisPipeWriterRef writer = pipeWriterOpen("/tmp/oasis-mon-res");
// Reads the command request message from the command requesting process.
OasisPipeReaderRef reader = pipeReaderOpen("/tmp/oasis-mon-req");
pipeReaderSetCallback(reader, std::bind(&onCommand, _1, _2, _3, _4, _5, _6, _7));
The command reading callback function:
static void onCommand(const void *data, size_t length, int32_t width, int32_t height, int32_t stride, int32_t data_type, uint32_t flags)
{
if(length == 0) {
//nothing to do
return;
}
std::string cmd((const char *)data, (const char *)data+length);
Json::Value json_req;
Json::Reader reader;
bool parsing_ok = reader.parse(cmd.c_str(), json_req);
if(!parsing_ok) {
fprintf(stdout, "pipe req: json parsing error: %s\n", cmd.c_str());
continue;
}
if(json_req.isMember("cmd") == false) {
fprintf(stdout, "pipe req: \"cmd\" not found!: %s\n", cmd.c_str());
continue;
}
std::string req_cmd = json_req["cmd"].asString();
if(req_cmd == "format") {
// Proceeds with formatting the file system.
char shell_cmd[PATH_MAX];
int32_t req_cmd_result = 0;
sprintf(shell_cmd, "/usr/sbin/mkfs.offs /dev/mmcblk0p1 /etc/offs-format.cfg 32GB_DRV");
err = runCommand(shell_cmd);
if(err) {
req_cmd_result = -err;
}
Json::Value json_reply;
json_reply["result"] = std::to_string(req_cmd_result);
json_reply["cmd"] = req_cmd;
Json::FastWriter fastWriter;
std::string json_string = fastWriter.write(json_reply);
pipeWriterWrite(writer, json_string.c_str(), json_string.length(), 0, 0, 0, 0, 0);
}
}
The function that executes the command using the popen function:
#define MAXLINE 4096
static int32_t runCommand(const char *shell_cmd)
{
char buff[MAXLINE];
FILE *fp;
fp = popen(shell_cmd, "r");
if(fp == NULL) {
fprintf(stderr, "\"%s\" popen error: %d(%s)\n", shell_cmd, errno, strerror(errno));
return -errno;
}
while(fgets(buff, MAXLINE, fp) != NULL) {
fprintf(stdout, "%s", buff);
fflush(stdout);
}
return (int32_t)(int8_t)pclose(fp);
}