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

[Don't Merge!!!] Test SonarQube #1

Open
wants to merge 17 commits into
base: master
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
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ jobs:
- name: build
id: build
run: |
sed -i 's/option(BMF_ENABLE_PYTHON "Enable build with python support" OFF)/option(BMF_ENABLE_PYTHON "Enable build with python support" ON)/' CMakeLists.txt
sed -i 's/option(BMF_ENABLE_TEST "Compile examples and tests" OFF)/option(BMF_ENABLE_TEST "Compile examples and tests" ON)/' CMakeLists.txt
./build.sh debug

- name: set envs
Expand Down Expand Up @@ -78,6 +80,10 @@ jobs:
# test hmp
(cd bmf/hml/tests/data && ./gen.sh $(pwd)/../../../../output/files)
(cd bmf/hml/tests && pytest)

- name: Setup tmate session
if: ${{ failure() }}
uses: mxschmitt/action-tmate@v3
Comment on lines +84 to +86
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Security Risk: Remove tmate session before merging.

The tmate session provides SSH access to the CI environment, which could expose sensitive information. This should not be merged into production as it poses a security risk.

Consider using GitHub's built-in debugging features or artifact uploads instead.


build_and_test_win:
name: build and test win
Expand Down
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@
*.so
*.sym
/build*/
CMakeFiles
_deps
bmf/files*
bmf/demo/transcode/*.mp4
bmf/test/distributed_node/build/*
bmf/demo/transcode/*.json
bmf/demo/transcode/test_cb
bmf/demo/transcode/test_cb.d*
!build.gradle
bmf/c_module_sdk/build
bmf/c_module_sdk/cmake-build-debug
Expand Down
6 changes: 3 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ set(BMF_BUILD_COMMIT "" CACHE STRING "BMF commit")

option(BMF_LOCAL_DEPENDENCIES "Build dependencies locally" ON)
option(BMF_ENABLE_BREAKPAD "Enable build with breakpad support" OFF)
option(BMF_ENABLE_CUDA "Enable CUDA support" ON)
option(BMF_ENABLE_CUDA "Enable CUDA support" OFF)
option(BMF_ENABLE_TORCH "Enable CUDA support" OFF)
option(BMF_ENABLE_PYTHON "Enable build with python support" ON)
option(BMF_ENABLE_PYTHON "Enable build with python support" OFF)
option(BMF_ENABLE_GLOG "Enable build with glog support" OFF)
option(BMF_ENABLE_JNI "Enable build with JNI support" OFF)
option(BMF_ENABLE_FFMPEG "Enable build with ffmpeg support" ON)
option(BMF_ENABLE_MOBILE "Enable build for mobile platform" OFF)
option(BMF_ENABLE_TEST "Compile examples and tests" ON)
option(BMF_ENABLE_TEST "Compile examples and tests" OFF)
option(BMF_ENABLE_FUZZTEST "Enable fuzz tests" OFF)
option(FUZZTEST_ENABLE_FUZZING_MODE "Enable fuzz tests in fuzzing mode" OFF)
option(CMAKE_EXPORT_COMPILE_COMMANDS "Export compiler commands" OFF)
Expand Down
10 changes: 10 additions & 0 deletions activate_env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash
# set the environment variables for bmf
export C_INCLUDE_PATH=${C_INCLUDE_PATH}:$(pwd)/output/bmf/include
export CPLUS_INCLUDE_PATH=${CPLUS_INCLUDE_PATH}:$(pwd)/output/bmf/include
export LIBRARY_PATH=${LIBRARY_PATH}:$(pwd)/output/bmf/lib
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:$(pwd)/output/bmf/lib
Comment on lines +3 to +6
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Fix potential masking of return values in export statements.

The current inline export assignments could mask return values. Consider separating the declaration and assignment.

Apply this diff to fix the issue:

-export C_INCLUDE_PATH=${C_INCLUDE_PATH}:$(pwd)/output/bmf/include
-export CPLUS_INCLUDE_PATH=${CPLUS_INCLUDE_PATH}:$(pwd)/output/bmf/include
-export LIBRARY_PATH=${LIBRARY_PATH}:$(pwd)/output/bmf/lib
-export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:$(pwd)/output/bmf/lib
-export PYTHONPATH=$(pwd)/output/bmf/lib:$(pwd)/output
+C_INCLUDE_PATH=${C_INCLUDE_PATH}:$(pwd)/output/bmf/include
+CPLUS_INCLUDE_PATH=${CPLUS_INCLUDE_PATH}:$(pwd)/output/bmf/include
+LIBRARY_PATH=${LIBRARY_PATH}:$(pwd)/output/bmf/lib
+LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:$(pwd)/output/bmf/lib
+PYTHONPATH=$(pwd)/output/bmf/lib:$(pwd)/output
+export C_INCLUDE_PATH CPLUS_INCLUDE_PATH LIBRARY_PATH LD_LIBRARY_PATH PYTHONPATH

Also applies to: 9-9

🧰 Tools
🪛 Shellcheck (0.10.0)

[warning] 3-3: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 4-4: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 5-5: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 6-6: Declare and assign separately to avoid masking return values.

(SC2155)


# only set if you want to use BMF in python
export PYTHONPATH=$(pwd)/output/bmf/lib:$(pwd)/output
export DYLD_LIBRARY_PATH=~/Documents/Programs/Git/Github/bmf/output/bmf/lib
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove hard-coded path and add directory validation.

The script contains a hard-coded path that won't work on other systems. Additionally, the script should validate that required directories exist.

Apply this diff to fix the issues:

-export DYLD_LIBRARY_PATH=~/Documents/Programs/Git/Github/bmf/output/bmf/lib
+# Check if BMF directories exist
+BMF_OUTPUT_DIR="$(pwd)/output/bmf"
+if [ ! -d "$BMF_OUTPUT_DIR" ]; then
+    echo "Error: BMF output directory not found: $BMF_OUTPUT_DIR"
+    return 1
+fi
+
+# Set DYLD_LIBRARY_PATH relative to current directory
+DYLD_LIBRARY_PATH=${BMF_OUTPUT_DIR}/lib
+export DYLD_LIBRARY_PATH
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export DYLD_LIBRARY_PATH=~/Documents/Programs/Git/Github/bmf/output/bmf/lib
# Check if BMF directories exist
BMF_OUTPUT_DIR="$(pwd)/output/bmf"
if [ ! -d "$BMF_OUTPUT_DIR" ]; then
echo "Error: BMF output directory not found: $BMF_OUTPUT_DIR"
return 1
fi
# Set DYLD_LIBRARY_PATH relative to current directory
DYLD_LIBRARY_PATH=${BMF_OUTPUT_DIR}/lib
export DYLD_LIBRARY_PATH

1 change: 1 addition & 0 deletions bmf/builder/bmf_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,7 @@ def generate_meta_info_config(pre_module, callback_dict):
# set callback function
for key, callback in callback_dict.items():
callback_binding = "{}:{}".format(key, callback[0])
print(callback_binding)
meta_info_config.add_callback_binding(callback_binding)

return meta_info_config
Expand Down
5 changes: 5 additions & 0 deletions bmf/c_modules/include/ffmpeg_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ class CFFDecoder : public Module {

int orig_pts_time_ = 0;

std::function<CBytes(int64_t, CBytes)> callback_endpoint_;

int process_raw_stream_packet(Task &task, BMFAVPacket &bmf_pkt, bool eof);

int process_input_bmf_av_packet(Task &task);
Expand Down Expand Up @@ -234,6 +236,9 @@ class CFFDecoder : public Module {
int read_packet(uint8_t *buf, int buf_size);

int pkt_ts(AVPacket *pkt, int index);

void set_callback(
std::function<CBytes(int64_t, CBytes)> callback_endpoint) override;
};
/** @page ModuleDecoder Build-in Decode Module
* @ingroup DecM
Expand Down
2 changes: 2 additions & 0 deletions bmf/c_modules/include/ffmpeg_encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ class CFFEncoder : public Module {
CurrentImage2Buffer current_image_buffer_ = {0};
bool copy_ts_ = false;
bool has_complex_filtergraph_ = false;
// use for callback to get the frame number
int frame_number = 0;

public:
CFFEncoder(int node_id, JsonParam option);
Expand Down
11 changes: 11 additions & 0 deletions bmf/c_modules/src/ffmpeg_decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2468,6 +2468,12 @@ int CFFDecoder::process(Task &task) {
init_input(dec_opts_);
}

if (callback_endpoint_ != nullptr) {
std::string info = "total frame number: " + std::to_string(video_stream_->nb_frames);
auto para = CBytes::make((uint8_t *)info.c_str(), info.size());
callback_endpoint_(0, para);
}

if (!input_fmt_ctx_) {
BMFLOG_NODE(BMF_WARNING, node_id_)
<< "decoder input_fmt_ctx_ is not ready or might be free";
Expand Down Expand Up @@ -2524,6 +2530,11 @@ int CFFDecoder::process(Task &task) {
return PROCESS_OK;
}

void CFFDecoder::set_callback(
std::function<CBytes(int64_t, CBytes)> callback_endpoint) {
callback_endpoint_ = callback_endpoint;
}

REGISTER_MODULE_CLASS(CFFDecoder)
REGISTER_MODULE_INFO(CFFDecoder, info) {
info.module_description = "Builtin FFmpeg-based decoding module.";
Expand Down
18 changes: 10 additions & 8 deletions bmf/c_modules/src/ffmpeg_encoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -411,14 +411,16 @@ int CFFEncoder::handle_output(AVPacket *hpkt, int idx) {
AVPacket *pkt = hpkt;

if (idx == 0) {
if (callback_endpoint_ != NULL) {
float curr_time =
(in_stream_tbs_[0].den > 0 && in_stream_tbs_[0].num > 0)
? float(pkt->pts * in_stream_tbs_[0].num /
in_stream_tbs_[0].den)
: 0;

std::string info = "pts: " + std::to_string(curr_time);
if (callback_endpoint_ != nullptr) {
// float curr_time =
// (in_stream_tbs_[0].den > 0 && in_stream_tbs_[0].num > 0)
// ? float(pkt->pts * in_stream_tbs_[0].num /
// in_stream_tbs_[0].den)
// : 0;

// std::string info = "pts: " + std::to_string(curr_time);
std::string info = "pts: " + std::to_string(pkt->pts) + " dts: " + std::to_string(pkt->dts)
+" frame number: "+ std::to_string(++frame_number);
auto para = CBytes::make((uint8_t *)info.c_str(), info.size());
callback_endpoint_(0, para);
}
Expand Down
2 changes: 2 additions & 0 deletions bmf/demo/transcode/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
g++ -std=c++17 -g -o test_cb test_cb.cpp -L/Users/jacklau/Documents/Programs/Git/Github/bmf/output/bmf/lib -lengine -lbmf_module_sdk -lhmp
146 changes: 146 additions & 0 deletions bmf/demo/transcode/test_cb.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
#include "builder.hpp"
#include "nlohmann/json.hpp"
#include "connector.hpp"

#include <regex>

// Global variable or pass-by-reference as needed
int frame_number_total = 0;
int frame_number_global = 0;

int process_number = 0;
double rest_time = 0;

std::chrono::system_clock::time_point last_encoder_call; // Track last call time
bool first_encoder_call = true; // Flag for first call

Comment on lines +14 to +16
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove or unify duplicate encoder timing variables.
You have a global last_encoder_call and first_encoder_call, but also a static local last_encoder_call_time in line 73. This duplication can cause confusion or errors. Consider removing the unused global variables or consolidating them into a single approach for tracking encoder call times.

-std::chrono::system_clock::time_point last_encoder_call; // Possibly remove
-bool first_encoder_call = true; // Possibly remove
...
 static auto last_encoder_call_time = std::chrono::system_clock::now();

Also applies to: 73-73

std::vector<double> duration_history; // Store recent durations for averaging
constexpr size_t max_history_size = 20; // Limit for the number of durations tracked
constexpr double min_duration_threshold = 10.0; // Ignore durations < 10 ms

double compute_smooth_duration(double new_duration) {
if (new_duration >= min_duration_threshold) {
duration_history.push_back(new_duration);
if (duration_history.size() > max_history_size) {
duration_history.erase(duration_history.begin());
}
}
return duration_history.empty() ? 0.0 :
std::accumulate(duration_history.begin(), duration_history.end(), 0.0) / duration_history.size();
}

// std::string format_time(const std::tm& tm) {
// char buffer[20]; // Buffer to hold formatted time string
// std::snprintf(buffer, sizeof(buffer), "%04d-%02d-%02d %02d:%02d:%02d",
// tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
// tm.tm_hour, tm.tm_min, tm.tm_sec);
// return std::string(buffer);
// }

bmf_sdk::CBytes decoder_callback(bmf_sdk::CBytes input) {
std::string strInfo;
strInfo.assign(reinterpret_cast<const char*>(input.buffer), input.size);
// BMFLOG(BMF_INFO) << "====Callback==== " << strInfo;


std::regex frame_regex(R"(\btotal frame number:\s*(\d+))");
std::smatch match;

if (std::regex_search(strInfo, match, frame_regex) && match.size() > 1) {
std::istringstream(match[1]) >> frame_number_total; // Convert to int
BMFLOG(BMF_DEBUG) << "Extracted Frame Number: " << frame_number_total;
} else {
BMFLOG(BMF_WARNING) << "Failed to extract frame number";
}

uint8_t bytes[] = {97, 98, 99, 100, 101, 0};
return bmf_sdk::CBytes{bytes, 6};
}

bmf_sdk::CBytes encoder_callback(bmf_sdk::CBytes input) {
std::string strInfo;
strInfo.assign(reinterpret_cast<const char*>(input.buffer), input.size);
// BMFLOG(BMF_INFO) << "====Callback==== " << strInfo;

std::regex frame_regex(R"(\bframe number:\s*(\d+))");
std::smatch match;

if (std::regex_search(strInfo, match, frame_regex) && match.size() > 1) {
std::istringstream(match[1]) >> frame_number_global; // Convert to int
BMFLOG(BMF_DEBUG) << "Extracted Total Frame Number: " << frame_number_global;
process_number = frame_number_global * 100 / frame_number_total;

static auto last_encoder_call_time = std::chrono::system_clock::now();
auto now = std::chrono::system_clock::now();

auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now - last_encoder_call_time).count();
last_encoder_call_time = now;

double smooth_duration = compute_smooth_duration(duration);
if (frame_number_global > 0 && frame_number_total > 0) {
// double progress = static_cast<double>(frame_number_global) / frame_number_total;
rest_time = smooth_duration * (frame_number_total-frame_number_global) / 1000;
}

BMFLOG(BMF_INFO) << "Process Number (percentage): " << process_number << "%\t"
<< "Current duration (milliseconds): " << duration << "\t"
<< "Smoothed Duration: " << smooth_duration << " ms\t"
<< "Estimated Rest Time (seconds): " << rest_time;



if (frame_number_global == frame_number_total) {
BMFLOG(BMF_INFO) << "====Callback==== Finish";
}

} else {
BMFLOG(BMF_WARNING) << "Failed to extract frame number";
}

uint8_t bytes[] = {97, 98, 99, 100, 101, 0};
return bmf_sdk::CBytes{bytes, 6};
}

int main() {
std::string output_file = "./cb.mp4";

std::function<bmf_sdk::CBytes(bmf_sdk::CBytes)> de_callback = decoder_callback;
std::function<bmf_sdk::CBytes(bmf_sdk::CBytes)> en_callback = encoder_callback;

nlohmann::json graph_para = {
{"dump_graph", 0}
};
auto graph = bmf::builder::Graph(bmf::builder::NormalMode,
bmf_sdk::JsonParam(graph_para));

nlohmann::json decode_para = {
{"input_path", "../../files/big_bunny_10s_30fps.mp4"},
};
auto video = graph.Decode(bmf_sdk::JsonParam(decode_para));
video.AddCallback(0, std::function<bmf_sdk::CBytes(bmf_sdk::CBytes)>(decoder_callback));

nlohmann::json encode_para = {
{"output_path", output_file},
{"video_params", {
{"codec", "h264"},
{"crf", 23},
{"preset", "veryslow"}
}},
{"audio_params", {
{"codec", "aac"},
{"bit_rate", 128000},
{"sample_rate", 44100},
{"channels", 2}
}}
};



auto node = graph.Encode(video["video"], video["audio"],
bmf_sdk::JsonParam(encode_para));

node.AddCallback(0, en_callback);

graph.Run();

}
20 changes: 12 additions & 8 deletions bmf/demo/transcode/transcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,22 +148,23 @@ def test_video():


def test_cb():
input_video_path = "../../files/img.mp4"
input_video_path = "../../files/big_bunny_10s_30fps.mp4"
output_path = "./cb.mp4"
expect_result = '../transcode/cb.mp4|240|320|7.615000|MOV,MP4,M4A,3GP,3G2,MJ2|366635|348991|h264|' \
'{"fps": "30.0662251656"}'
# create graph
graph = bmf.graph()

def cb(para):
print(para)

graph.add_user_callback(bmf.BmfCallBackType.LATEST_TIMESTAMP, cb)
print("====CallBack====", para.decode('UTF-8'))
return bytes("OK", "ASCII")

# decode
video = graph.decode({"input_path": input_video_path})

(bmf.encode(
video.node_.add_user_callback(bmf.BmfCallBackType.LATEST_TIMESTAMP, cb)

bmf.encode(
video['video'], video['audio'], {
"output_path": output_path,
"video_params": {
Expand All @@ -173,7 +174,10 @@ def cb(para):
"crf": "23",
"preset": "veryfast"
}
}).run())
}).node_.add_user_callback(bmf.BmfCallBackType.LATEST_TIMESTAMP, cb)

graph.option_["dump_graph"] = 1
graph.run()


def compareProfile(graph_file):
Expand Down Expand Up @@ -235,5 +239,5 @@ def compare():
# test_simple()
# test_audio()
# test_video()
# test_cb()
compare()
test_cb()
# compare()
6 changes: 6 additions & 0 deletions bmf/engine/connector/include/builder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ class RealNode : public std::enable_shared_from_this<RealNode> {

void AddCallback(long long key, bmf::BMFCallback callbackInstance);

void AddCallback(long long key,
std::function<bmf_sdk::CBytes(bmf_sdk::CBytes)> callback);

nlohmann::json Dump();

std::shared_ptr<RealNode>
Expand Down Expand Up @@ -451,6 +454,9 @@ class BMF_ENGINE_API Node {
void AddCallback(long long key,
const bmf::BMFCallback &callbackInstance);

void AddCallback(long long key,
std::function<bmf_sdk::CBytes(bmf_sdk::CBytes)> callback);

void Start();

Node Module(
Expand Down
Loading
Loading