Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SBC pod launcher JSON based configuration parser #40

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ docs/_build
_build
gRPC/build
gRPC/unit_test/build
gRPC/config_parser/build
file*.json
.reports
NVMUpdatePackage
Expand Down
9 changes: 9 additions & 0 deletions gRPC/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,17 @@ add_executable(cmd_pass_client cmd_pass_client.cc)
${_GRPC_GRPCPP}
${_PROTOBUF_LIBPROTOBUF})

add_subdirectory(config_parser)

add_executable(FFmpeg_wrapper_service FFmpeg_wrapper_service.cc CmdPassImpl.cc)

target_include_directories(FFmpeg_wrapper_service
PUBLIC
${CMAKE_SOURCE_DIR}/config_parser)

target_link_libraries(FFmpeg_wrapper_service
ffmpegconfig
nlohmann_json::nlohmann_json
hw_grpc_proto
absl::check
absl::flags
Expand Down
3 changes: 3 additions & 0 deletions gRPC/CmdPassImpl.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "CmdPassImpl.h"
#include "ffmpeg_config_processor.h"

void CmdPassImpl::Run(std::string server_address) {
ServerBuilder builder;
Expand Down Expand Up @@ -64,6 +65,8 @@ void CmdPassImpl::CallData::Proceed() {
ss << " -" << cmd.cmd_key() << " " << cmd.cmd_val();
}

ss << " " << processConfigFile(std::getenv("CONFIG_FILE"));

std::string ffmpeg_full_cmd = ss.str();

std::array<char, 128> buffer;
Expand Down
38 changes: 38 additions & 0 deletions gRPC/config_parser/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
cmake_minimum_required(VERSION 3.14)
project(MyFFmpegApp LANGUAGES CXX)

# Set C++ standard to C++20
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Include the JSON for Modern C++ library
include(FetchContent)

FetchContent_Declare(
json
GIT_REPOSITORY https://github.com/nlohmann/json.git
GIT_TAG v3.10.5
)

FetchContent_MakeAvailable(json)

# Add the source files for the static library
set(SOURCES
handlers.cpp
ffmpeg_config_processor.cpp
)

# Add the header files for the static library
set(HEADERS
handlers.h
ffmpeg_config_processor.h
)

# Create the static library
add_library(ffmpegconfig STATIC ${SOURCES} ${HEADERS})

# Link the JSON library to the static library
target_link_libraries(ffmpegconfig PRIVATE nlohmann_json::nlohmann_json)

# Specify include directories
target_include_directories(ffmpegconfig PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
76 changes: 76 additions & 0 deletions gRPC/config_parser/ffmpeg_config_processor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include "ffmpeg_config_processor.h"
#include "handlers.h"
#include <fstream>
#include <sstream>
#include <iostream>

// Function to process appParams section and use handlers to print key-value pairs and collect formatted strings
std::string processAppParams(const json& data) {
std::vector<std::string> commandChunks;
std::ostringstream commandStream;
std::string commandString;
std::string formattedString;

for (const auto& [key, value] : data.items()) {
if (handlers.find(key) != handlers.end()) {
try {
formattedString = handlers[key](key, value);
commandChunks.push_back(formattedString);
} catch (const std::exception& e) {
throw std::runtime_error("error processing key " + key + ": " + e.what());
}
} else {
try {
formattedString = handleKeyValue(key, value);
commandChunks.push_back(formattedString);
} catch (const std::exception& e) {
throw std::runtime_error("error processing key " + key + ": " + e.what());
}
}
}

for (const auto& str : commandChunks) {
commandStream << str << " ";
}

commandString = commandStream.str();
std::cout << "Command String: " << commandString << std::endl;

return commandString;
}

// Function to process the configuration file and return the command string
std::string processConfigFile(const std::string& configFile) {
// Open the JSON configuration file
std::ifstream file(configFile);
if (!file.is_open()) {
throw std::runtime_error("Could not open the configuration file: " + configFile);
}

// Read the JSON configuration file
std::stringstream buffer;
buffer << file.rdbuf();
std::string jsonString = buffer.str();

// Parse the JSON configuration file
json config;
try {
config = json::parse(jsonString);
} catch (const json::parse_error& e) {
throw std::runtime_error("JSON parse error: " + std::string(e.what()));
}

// Extract and process the appParams section
if (config.contains("ffmpegPipelineDefinition")) {
const auto& ffmpegPipelineDefinition = config["ffmpegPipelineDefinition"];
if (ffmpegPipelineDefinition.contains("appParams")) {
const auto& appParams = ffmpegPipelineDefinition["appParams"];
// Construct and return the command string
return processAppParams(appParams);
} else {
throw std::runtime_error("appParams section not found in the configuration file.");
}
} else {
throw std::runtime_error("ffmpegPipelineDefinition section not found in the configuration file.");
}
}
15 changes: 15 additions & 0 deletions gRPC/config_parser/ffmpeg_config_processor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef FFMPEG_CONFIG_PROCESSOR_H
#define FFMPEG_CONFIG_PROCESSOR_H

#include <string>
#include <vector>
#include <nlohmann/json.hpp>

// Alias for convenience
using json = nlohmann::json;

// Function declarations
std::string processAppParams(const json& data);
std::string processConfigFile(const std::string& configFile);

#endif // FFMPEG_CONFIG_PROCESSOR_H
112 changes: 112 additions & 0 deletions gRPC/config_parser/handlers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#include "handlers.h"

// Handlers map definition
std::unordered_map<std::string, HandlerFunc> handlers = {
// per stream options
{"codec", handleCodecKeyValue},
{"filter", handleKeyValue},
{"format", handleFormatKeyValue},

// video options
{"height", handleKeyValue},
{"width", handleKeyValue},

// common options for MCM, MTL
{"payload_type", handleKeyValue},
{"video_size", handleKeyValue},
{"pixel_format", handleKeyValue},

// MCM Muxer/Demuxer
{"ip_addr", handleKeyValue},
{"port", handleKeyValue},
{"protocol_type", handleKeyValue},
{"frame_rate", handleFrameRate},
{"socket_name", handleKeyValue},
{"interface_id", handleKeyValue},

// MTL Device Arguments
{"p_port", handleKeyValue},
{"p_sip", handleKeyValue},
{"dma_dev", handleKeyValue},

// Tx Port Encoding Arguments
{"p_tx_ip", handleKeyValue},
{"udp_port", handleKeyValue},

// Rx Port Decoding Arguments
{"p_rx_ip", handleKeyValue},
{"udp_port", handleKeyValue},

// MTL st20p Muxer/Demuxer
{"fb_cnt", handleKeyValue},
{"pix_fmt", handleKeyValue},
{"fps", handleKeyValue},
{"timeout_s", handleKeyValue},

// MTL st22p Muxer/Demuxer
{"bpp", handleKeyValue},
{"codec_thread_cnt", handleKeyValue},
{"st22_codec", handleKeyValue},

// MTL st30p Muxer/Demuxer
{"at", handleKeyValue},
{"ar", handleKeyValue},
{"ac", handleKeyValue},
{"pcm_fmt", handleKeyValue},

// JPEG XS encoder
{"decomp_v", handleKeyValue},
{"decomp_h", handleKeyValue},
{"threads", handleKeyValue},
{"slice_height", handleKeyValue},
{"quantization", handleKeyValue},
{"coding-signs", handleKeyValue},
{"coding-sigf", handleKeyValue},
{"coding-vpred", handleKeyValue},

// JPEG XS decoder
{"threads", handleKeyValue},
};

// Helper function to handle prefixed key-value pairs
std::string handlePrefixedKeyValue(const std::string& prefix, const std::string& key, const json& value) {
if (value.is_null()) {
throw std::invalid_argument("key " + key + " has no value");
}
std::string valueStr = value.get<std::string>();
if (valueStr.empty()) {
throw std::invalid_argument("key " + key + " has an empty value");
}
std::cout << prefix << ": " << valueStr << std::endl;
return prefix + " " + valueStr;
}

// handleFormatKeyValue handles the key "format", the value passed to ffmpeg as -f <format value>
std::string handleFormatKeyValue(const std::string& key, const json& value) {
return handlePrefixedKeyValue("-f", key, value);
}

// handleCodecKeyValue handles the key "codec", the value passed to ffmpeg as -c <codec value>
std::string handleCodecKeyValue(const std::string& key, const json& value) {
return handlePrefixedKeyValue("-c", key, value);
}

// handleKeyValue handles the key and value, prints them, and returns a formatted string
std::string handleKeyValue(const std::string& key, const json& value) {
return handlePrefixedKeyValue("-" + key, key, value);
}

// handleFrameRate handles the frame_rate key by calculating the frame rate and returning a formatted string
std::string handleFrameRate(const std::string& key, const json& value) {
if (value.is_object()) {
double numerator = value["numerator"].get<double>();
double denominator = value["denominator"].get<double>();
if (denominator != 0) {
int frameRate = static_cast<int>(numerator / denominator);
std::cout << key << ": " << frameRate << std::endl;
return "-" + key + " " + std::to_string(frameRate);
}
throw std::invalid_argument("invalid frame_rate: denominator is zero");
}
throw std::invalid_argument("invalid frame_rate format");
}
27 changes: 27 additions & 0 deletions gRPC/config_parser/handlers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef HANDLERS_H
#define HANDLERS_H

#include <iostream>
#include <string>
#include <unordered_map>
#include <functional>
#include <stdexcept>
#include <sstream>
#include <nlohmann/json.hpp>

// Alias for convenience
using json = nlohmann::json;

// Handler function type
using HandlerFunc = std::function<std::string(const std::string&, const json&)>;

// Handlers map
extern std::unordered_map<std::string, HandlerFunc> handlers;

// Function declarations
std::string handleKeyValue(const std::string& key, const json& value);
std::string handleFrameRate(const std::string& key, const json& value);
std::string handleFormatKeyValue(const std::string& key, const json& value);
std::string handleCodecKeyValue(const std::string& key, const json& value);

#endif // HANDLERS_H
5 changes: 5 additions & 0 deletions gRPC/unit_test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ include_directories(${googletest_SOURCE_DIR}/googletest/include)
include_directories(${googletest_SOURCE_DIR}/googlemock/include)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../build)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../config_parser)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../build/_deps/json-src/include)

# Source files
set(SOURCE_FILES
Expand All @@ -46,8 +48,11 @@ set(SOURCE_FILES
# Add the executable
add_executable(FFmpegWrapperServiceTests ${SOURCE_FILES})

target_link_directories(FFmpegWrapperServiceTests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../build/config_parser)

# Link libraries
target_link_libraries(FFmpegWrapperServiceTests
ffmpegconfig
gRPC::grpc++
protobuf::libprotobuf
absl::check
Expand Down
Loading