Skip to content
Merged
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
98 changes: 98 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
name: ci

on:
push:
branches: [main]
pull_request:

permissions:
contents: read

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
linux:
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- uses: actions/checkout@v4

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
cmake ninja-build pkg-config \
qt6-base-dev qt6-multimedia-dev \
libavformat-dev libavcodec-dev libavutil-dev \
libswscale-dev libswresample-dev

- name: Configure
run: cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug

- name: Build
run: cmake --build build

- name: Test
env:
QT_QPA_PLATFORM: offscreen
run: ctest --test-dir build --output-on-failure

macos:
runs-on: macos-15
timeout-minutes: 30
steps:
- uses: actions/checkout@v4

- name: Install dependencies
run: brew install cmake ninja qt ffmpeg pkg-config

- name: Configure
run: >-
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
-DCMAKE_PREFIX_PATH="$(brew --prefix)"

- name: Build
run: cmake --build build

- name: Test
env:
QT_QPA_PLATFORM: offscreen
run: ctest --test-dir build --output-on-failure

windows:
runs-on: windows-latest
timeout-minutes: 30
defaults:
run:
shell: msys2 {0}
steps:
- uses: actions/checkout@v4

- uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
update: true
install: >-
mingw-w64-x86_64-cmake
mingw-w64-x86_64-gcc
mingw-w64-x86_64-ninja
mingw-w64-x86_64-pkgconf
mingw-w64-x86_64-qt6-base
mingw-w64-x86_64-qt6-multimedia
mingw-w64-x86_64-ffmpeg
git

- name: Configure
run: >-
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
-DCMAKE_PREFIX_PATH=/mingw64

- name: Build
run: cmake --build build

- name: Test
env:
QT_QPA_PLATFORM: offscreen
run: ctest --test-dir build --output-on-failure
1 change: 1 addition & 0 deletions test/test_platform_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ TEST(MappedFileTest, MapsExistingFile) {
file.ReleaseResidentPages(); // must not crash and must keep the data valid
EXPECT_EQ(std::memcmp(file.data(), payload, sizeof(payload)), 0);

file.close();
std::filesystem::remove(path);
}

Expand Down
97 changes: 47 additions & 50 deletions test/tools/gen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ extern "C" {
#include <stdlib.h>
#include <string.h>

#include <cstring>

static const uint8_t FONT5x7[][5] = {
{0x00, 0x00, 0x00, 0x00, 0x00}, // ' '
{0x00, 0x00, 0x5F, 0x00, 0x00}, // '!'
Expand Down Expand Up @@ -194,7 +196,7 @@ static void draw_filled_rect_yuv(AVFrame* frame, int x, int y, int w, int h,
static void format_number(char* buf, int n, int width) {
char tmp[32];
snprintf(tmp, sizeof(tmp), "%d", n);
int len = (int)strlen(tmp);
int len = (int)std::strlen(tmp);
int pad = width - len;
int pos = 0;
for (int i = 0; i < pad; i++) {
Expand All @@ -204,28 +206,23 @@ static void format_number(char* buf, int n, int width) {
buf[pos + len] = '\0';
}


bool parseInt(const char* s, int& out, int min_val, int max_val)
{
try
{
size_t pos{};
long v = std::stol(s, &pos);
if (pos != std::strlen(s))
{return false;}
if (v < min_val || v > max_val)
{return false;}
out = static_cast<int>(v);
return true;
bool parseInt(const char* s, int& out, int min_val, int max_val) {
try {
size_t pos{};
long v = std::stol(s, &pos);
if (pos != std::strlen(s)) {
return false;
}
catch (...)
{
return false;
if (v < min_val || v > max_val) {
return false;
}
out = static_cast<int>(v);
return true;
} catch (...) {
return false;
}
}



int main(int argc, char** argv) {
int width = 352;
int height = 288;
Expand All @@ -235,42 +232,42 @@ int main(int argc, char** argv) {
const char* codec_name = "libx264";
const char* output_path = "output.h264";

if (argc >= 2) {
if (!parseInt(argv[1], width, 16, 8192)) {
fprintf(stderr, "invalid width: %s\n", argv[1]);
return 1;
}
}
if (argc >= 3) {
if (!parseInt(argv[2], height, 16, 8192)) {
fprintf(stderr, "invalid height: %s\n", argv[2]);
return 1;
}
}
if (argc >= 4) {
if (!parseInt(argv[3], fps, 1, 240)) {
fprintf(stderr, "invalid fps: %s\n", argv[3]);
return 1;
}
if (argc >= 2) {
if (!parseInt(argv[1], width, 16, 8192)) {
fprintf(stderr, "invalid width: %s\n", argv[1]);
return 1;
}
if (argc >= 5) {
if (!parseInt(argv[4], total_frames, 1, 100000)) { // 至少1帧
fprintf(stderr, "invalid total_frames: %s\n", argv[4]);
return 1;
}
}
if (argc >= 3) {
if (!parseInt(argv[2], height, 16, 8192)) {
fprintf(stderr, "invalid height: %s\n", argv[2]);
return 1;
}
if (argc >= 6) {
if (!parseInt(argv[5], keyint, 1, 1000)) {
fprintf(stderr, "invalid keyint: %s\n", argv[5]);
return 1;
}
}
if (argc >= 4) {
if (!parseInt(argv[3], fps, 1, 240)) {
fprintf(stderr, "invalid fps: %s\n", argv[3]);
return 1;
}
if (argc >= 7) {
codec_name = argv[6];
}
if (argc >= 5) {
if (!parseInt(argv[4], total_frames, 1, 100000)) { // 至少1帧
fprintf(stderr, "invalid total_frames: %s\n", argv[4]);
return 1;
}
if (argc >= 8) {
output_path = argv[7];
}
if (argc >= 6) {
if (!parseInt(argv[5], keyint, 1, 1000)) {
fprintf(stderr, "invalid keyint: %s\n", argv[5]);
return 1;
}
}
if (argc >= 7) {
codec_name = argv[6];
}
if (argc >= 8) {
output_path = argv[7];
}

int is_h265 = (strstr(codec_name, "265") != nullptr);
// int codec_id = is_h265 ? AV_CODEC_ID_HEVC : AV_CODEC_ID_H264;
Expand Down
Loading