Skip to content

Commit a01fa97

Browse files
authored
gRPC POC service and client for FFmpeg wrapper (#22)
* [1] adding gRPC protocol service definition this commit is solely introcduce service defintion .proto file is used to generate anthor dependecy files which contains C++ defenitions for gRPC service. this file presents : - simple service with name CmdPass which acts as a wrapper for ffmpeg commandline utility. - CmdMsg strcture/message which represent block of message serialized, and it presents one parameter [key][value] i.e [udp_port][20000] for ffmpeg commandline utility. - FFmpeg_srvc_res strcture/message which returns back to client the same value returned by ffmpeg commandline tool. Signed-off-by: Aly, Walid <[email protected]> * [2] add service implementation service expects two simple command line args file formated using clangd i.e ./FFmpeg_wrapper_service [interface] [port] Signed-off-by: Aly, Walid <[email protected]> * [3] add FFmpeg wrapper client or agent the class is compiled as a static library which provides the interface to initialize and serialize messages to and from service. simply, CmdPassClient constructor is intializing the channel. and ffpmeg_cmd_exec submit commands and recieve status and FFmpeg tool return code. Signed-off-by: Aly, Walid <[email protected]> * [4] add CMakeList.txt and compiling bash script add CMakeList.txt beside single commenad compiling script and very simple app for client that link and call FFmpeg wrapper client functions. Signed-off-by: Aly, Walid <[email protected]> * service overview & explanation add service overview & explanation Signed-off-by: Aly, Walid <[email protected]> * client overview add client overview Signed-off-by: Aly, Walid <[email protected]> --------- Signed-off-by: Aly, Walid <[email protected]>
1 parent 5641239 commit a01fa97

File tree

9 files changed

+692
-0
lines changed

9 files changed

+692
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
docs/_build
22
_build
3+
gRPC/build
34
file*.json
45
.reports
56
NVMUpdatePackage

gRPC/CMakeLists.txt

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation
2+
#
3+
#SPDX-License-Identifier: BSD-3-Clause
4+
5+
cmake_minimum_required(VERSION 3.8)
6+
7+
project(ffmpeg_cmd_wrap C CXX)
8+
9+
10+
set(CMAKE_CXX_STANDARD 20)
11+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
12+
13+
set(protobuf_MODULE_COMPATIBLE TRUE)
14+
find_package(Protobuf CONFIG REQUIRED)
15+
message(STATUS "Using protobuf ${Protobuf_VERSION}")
16+
17+
set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)
18+
set(_REFLECTION gRPC::grpc++_reflection)
19+
20+
if(CMAKE_CROSSCOMPILING)
21+
find_program(_PROTOBUF_PROTOC protoc)
22+
else()
23+
set(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)
24+
endif()
25+
26+
# Find gRPC installation
27+
# Looks for gRPCConfig.cmake file installed by gRPC's cmake installation.
28+
find_package(gRPC CONFIG REQUIRED)
29+
message(STATUS "Using gRPC ${gRPC_VERSION}")
30+
31+
set(_GRPC_GRPCPP gRPC::grpc++)
32+
if(CMAKE_CROSSCOMPILING)
33+
find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin)
34+
else()
35+
set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_cpp_plugin>)
36+
endif()
37+
38+
# Proto file
39+
get_filename_component(hw_proto "./ffmpeg_cmd_wrap.proto" ABSOLUTE)
40+
get_filename_component(hw_proto_path "${hw_proto}" PATH)
41+
42+
# Generated sources
43+
set(hw_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/ffmpeg_cmd_wrap.pb.cc")
44+
set(hw_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/ffmpeg_cmd_wrap.pb.h")
45+
set(hw_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/ffmpeg_cmd_wrap.grpc.pb.cc")
46+
set(hw_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/ffmpeg_cmd_wrap.grpc.pb.h")
47+
add_custom_command(
48+
OUTPUT "${hw_proto_srcs}" "${hw_proto_hdrs}" "${hw_grpc_srcs}" "${hw_grpc_hdrs}"
49+
COMMAND ${_PROTOBUF_PROTOC}
50+
ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}"
51+
--cpp_out "${CMAKE_CURRENT_BINARY_DIR}"
52+
-I "${hw_proto_path}"
53+
--plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}"
54+
"${hw_proto}"
55+
DEPENDS "${hw_proto}")
56+
57+
# Include generated *.pb.h files
58+
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
59+
60+
# hw_grpc_proto
61+
add_library(hw_grpc_proto
62+
${hw_grpc_srcs}
63+
${hw_grpc_hdrs}
64+
${hw_proto_srcs}
65+
${hw_proto_hdrs})
66+
target_link_libraries(hw_grpc_proto
67+
absl::check
68+
${_REFLECTION}
69+
${_GRPC_GRPCPP}
70+
${_PROTOBUF_LIBPROTOBUF})
71+
72+
add_library(FFmpeg_wrapper_client FFmpeg_wrapper_client.cc FFmpeg_wrapper_client.h)
73+
target_link_libraries(FFmpeg_wrapper_client
74+
absl::check
75+
${_REFLECTION}
76+
${_GRPC_GRPCPP}
77+
${_PROTOBUF_LIBPROTOBUF})
78+
79+
add_executable(cmd_pass_client cmd_pass_client.cc)
80+
target_link_libraries(cmd_pass_client
81+
FFmpeg_wrapper_client
82+
hw_grpc_proto
83+
absl::check
84+
absl::flags
85+
absl::flags_parse
86+
absl::log
87+
${_REFLECTION}
88+
${_GRPC_GRPCPP}
89+
${_PROTOBUF_LIBPROTOBUF})
90+
91+
add_executable(FFmpeg_wrapper_service FFmpeg_wrapper_service.cc)
92+
target_link_libraries(FFmpeg_wrapper_service
93+
hw_grpc_proto
94+
absl::check
95+
absl::flags
96+
absl::flags_parse
97+
absl::log
98+
${_REFLECTION}
99+
${_GRPC_GRPCPP}
100+
${_PROTOBUF_LIBPROTOBUF})

gRPC/FFmpeg_wrapper_client.cc

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#include "FFmpeg_wrapper_client.h"
8+
#include "build/ffmpeg_cmd_wrap.pb.h"
9+
#include <sstream>
10+
#include <utility>
11+
#include <string>
12+
13+
CmdPassClient::CmdPassClient(std::string interface, std::string port) : pending_requests_(0) {
14+
std::cout << "------ [start] initiate channel --------" << std::endl;
15+
16+
std::stringstream ss;
17+
std::string channel_config;
18+
19+
ss << interface << ":" << port;
20+
21+
channel_config = ss.str();
22+
23+
std::shared_ptr<Channel> channel = grpc::CreateChannel(channel_config, grpc::InsecureChannelCredentials());
24+
25+
stub_ = CmdPass::NewStub(channel);
26+
27+
std::cout << "------ [done] initiate channel --------" << std::endl;
28+
29+
// Start the thread to process the completion queue
30+
cq_thread_ = std::thread(&CmdPassClient::AsyncCompleteRpc, this);
31+
}
32+
33+
CmdPassClient::~CmdPassClient() {
34+
cq_.Shutdown();
35+
cq_thread_.join();
36+
}
37+
38+
void CmdPassClient::FFmpegCmdExec(std::vector<std::pair<std::string, std::string>>& cmd_pairs) {
39+
40+
ReqCmds req_obj;
41+
CmdMsg *cmd_msg;
42+
43+
for (const auto& cmd_pair : cmd_pairs) {
44+
cmd_msg = req_obj.add_obj();
45+
cmd_msg->set_cmd_key(cmd_pair.first);
46+
cmd_msg->set_cmd_val(cmd_pair.second);
47+
}
48+
49+
auto* call = new AsyncClientCall;
50+
51+
++pending_requests_;
52+
53+
// Initiate the asynchronous RPC call
54+
call->response_reader = stub_->PrepareAsyncFFmpegCmdExec(&call->context, req_obj, &cq_);
55+
call->response_reader->StartCall();
56+
call->response_reader->Finish(&call->response, &call->status, (void*)call);
57+
}
58+
59+
void CmdPassClient::AsyncCompleteRpc() {
60+
void* got_tag;
61+
bool ok = false;
62+
63+
while (cq_.Next(&got_tag, &ok)) {
64+
auto* call = static_cast<AsyncClientCall*>(got_tag);
65+
66+
if (ok) {
67+
if (call->status.ok()) {
68+
std::cout << "FFmpeg command executed successfully: " << call->status.error_code() << std::endl;
69+
}
70+
else {
71+
std::cout << "FFmpeg command execution failed:" << std::endl;
72+
std::cout << "Status = " << call->status.error_code() << std::endl;
73+
std::cout << "Message = " << call->status.error_message() << std::endl;
74+
std::cout << "Details = " << call->status.error_details() << std::endl;
75+
}
76+
}
77+
else {
78+
std::cout << "RPC failed" << std::endl;
79+
}
80+
81+
delete call;
82+
83+
if (--pending_requests_ == 0) {
84+
all_tasks_completed = true;
85+
all_tasks_completed.notify_one();
86+
}
87+
}
88+
}
89+
90+
void CmdPassClient::WaitForAllRequests() {
91+
all_tasks_completed.wait(false);
92+
}

gRPC/FFmpeg_wrapper_client.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#ifndef _CMD_PASS_CLIENT_H_
8+
#define _CMD_PASS_CLIENT_H_
9+
10+
#include <iostream>
11+
#include <memory>
12+
#include <ostream>
13+
#include <random>
14+
#include <string>
15+
#include <thread>
16+
#include <utility>
17+
#include <vector>
18+
#include <atomic>
19+
#include "build/ffmpeg_cmd_wrap.pb.h"
20+
21+
#include <grpc/grpc.h>
22+
#include <grpcpp/channel.h>
23+
#include <grpcpp/client_context.h>
24+
#include <grpcpp/create_channel.h>
25+
#include <grpcpp/security/credentials.h>
26+
#include "build/ffmpeg_cmd_wrap.grpc.pb.h"
27+
28+
using grpc::Channel;
29+
using grpc::ClientContext;
30+
using grpc::CompletionQueue;
31+
using grpc::Status;
32+
33+
class CmdPassClient {
34+
public:
35+
CmdPassClient(std::string interface, std::string port);
36+
~CmdPassClient();
37+
38+
void FFmpegCmdExec(std::vector<std::pair<std::string, std::string>>& cmd_pairs);
39+
void WaitForAllRequests();
40+
41+
private:
42+
void AsyncCompleteRpc();
43+
44+
// Create a new call object
45+
struct AsyncClientCall {
46+
FFmpegServiceRes response;
47+
ClientContext context;
48+
Status status;
49+
std::unique_ptr<grpc::ClientAsyncResponseReader<FFmpegServiceRes>> response_reader;
50+
};
51+
52+
std::unique_ptr<CmdPass::Stub> stub_;
53+
CompletionQueue cq_;
54+
std::thread cq_thread_;
55+
std::atomic<int> pending_requests_{0};
56+
std::atomic<bool> all_tasks_completed{false};
57+
};
58+
59+
#endif

0 commit comments

Comments
 (0)