Complete Phase 1: add clock utility, unit test, build targets, and docs
This commit is contained in:
+4
-6
@@ -4,12 +4,10 @@ Last updated: initial scaffold.
|
||||
|
||||
## Project state
|
||||
|
||||
- Empty project scaffolded with Meson build, C++20, module headers, and agent
|
||||
workflow files.
|
||||
- No implementation yet; headers are placeholders.
|
||||
- Phase plan is in `docs/PHASES.md`. Agents are now explicitly instructed in
|
||||
`AGENTS.md` to read `docs/PHASES.md` before planning and not to start work
|
||||
belonging to a later phase unless requested.
|
||||
- Phase 1 complete: Meson build, C++20 module headers, agent workflow, clock
|
||||
utility, and a passing unit test.
|
||||
- Active phase is now Phase 2 (software H.264 encode/decode).
|
||||
- No implementation yet for capture/codec/network/render.
|
||||
|
||||
## Decisions
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ A native Linux peer-to-peer screencast application.
|
||||
Requirements:
|
||||
|
||||
- C++20 compiler (GCC 12+, Clang 16+)
|
||||
- Meson + Ninja
|
||||
- Meson >= 0.63
|
||||
- Ninja
|
||||
- (later phases) FFmpeg dev packages, PipeWire dev, SDL2/3 dev
|
||||
|
||||
Build and run tests:
|
||||
@@ -25,6 +26,12 @@ meson compile -C build
|
||||
meson test -C build --print-errorlogs
|
||||
```
|
||||
|
||||
Run with verbose test output:
|
||||
|
||||
```sh
|
||||
meson test -C build -v
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
See `docs/ARCHITECTURE.md` for module boundaries and design rules.
|
||||
@@ -33,7 +40,7 @@ See `docs/ARCHITECTURE.md` for module boundaries and design rules.
|
||||
|
||||
Development is split into phases in `docs/PHASES.md`.
|
||||
|
||||
Current phase: **Phase 1 — project skeleton**.
|
||||
Current phase: **Phase 2 — software H.264 encode / decode**.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
+3
-3
@@ -10,8 +10,8 @@ previous one is validated.
|
||||
|
||||
- [x] Meson build files (`meson.build`, `meson_options.txt`).
|
||||
- [x] Public module headers with `namespace sc`.
|
||||
- [ ] Unit test that exercises a trivial utility function.
|
||||
- [ ] `README.md` with build instructions.
|
||||
- [x] Unit test that exercises a trivial utility function.
|
||||
- [x] `README.md` with build instructions.
|
||||
|
||||
**Validation**: `meson setup build && meson compile -C build && meson test -C build`.
|
||||
|
||||
@@ -89,4 +89,4 @@ where available.
|
||||
|
||||
## Current phase
|
||||
|
||||
Phase 1 — skeleton and tooling.
|
||||
Phase 2 — software H.264 encode/decode.
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace sc {
|
||||
|
||||
// RTP clock rate for video is 90 kHz. Convert a monotonic nanosecond timestamp
|
||||
// into a 32-bit RTP timestamp. Overflows wrap around intentionally.
|
||||
constexpr uint32_t rtp_timestamp_from_ns ( uint64_t nanoseconds ) noexcept {
|
||||
// (nanoseconds * 90_000) / 1_000_000_000
|
||||
// Simplify: 90_000 / 1_000_000_000 = 9 / 100_000
|
||||
return static_cast<uint32_t> ( ( nanoseconds * 9ULL ) / 100'000ULL );
|
||||
}
|
||||
|
||||
static_assert ( rtp_timestamp_from_ns ( 0 ) == 0 );
|
||||
static_assert ( rtp_timestamp_from_ns ( 1'000'000'000ULL ) == 90'000 );
|
||||
static_assert ( rtp_timestamp_from_ns ( 500'000'000ULL ) == 45'000 );
|
||||
|
||||
} // namespace sc
|
||||
+1
-2
@@ -10,8 +10,7 @@ project('screen_cast', 'cpp',
|
||||
# Public and private include directories
|
||||
inc = include_directories('include')
|
||||
|
||||
# Build the core static library first; dependencies will be added later as
|
||||
# phases require them.
|
||||
# Core public headers / include dependency defined in src/meson.build.
|
||||
subdir('src')
|
||||
|
||||
# Tests
|
||||
|
||||
+6
-2
@@ -1,2 +1,6 @@
|
||||
# Empty stub: implementation files will be added phase by phase.
|
||||
# For now the project configures successfully with no targets.
|
||||
# Core public API is currently header-only. Source files will be added as
|
||||
# modules are implemented in later phases.
|
||||
|
||||
# Declare an include-only dependency so that tests and executables can depend on
|
||||
# the public headers consistently.
|
||||
sc_core_inc = include_directories('../include')
|
||||
|
||||
+5
-1
@@ -1 +1,5 @@
|
||||
# Empty stub: tests will be added as modules land.
|
||||
test_clock = executable('test_clock',
|
||||
'utils/test_clock.cpp',
|
||||
include_directories : sc_core_inc)
|
||||
|
||||
test('clock utils', test_clock)
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "screencast/utils/clock.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
int main () {
|
||||
assert ( sc::rtp_timestamp_from_ns ( 0 ) == 0u );
|
||||
assert ( sc::rtp_timestamp_from_ns ( 1'000'000'000ULL ) == 90'000u );
|
||||
assert ( sc::rtp_timestamp_from_ns ( 500'000'000ULL ) == 45'000u );
|
||||
assert ( sc::rtp_timestamp_from_ns ( 16'666'667ULL ) == 1'500u );
|
||||
|
||||
// A multiple of the wrap period should wrap back to zero.
|
||||
// Period in ns = ceil(2^32 * 100_000 / 9) because the helper uses
|
||||
// integer floor division (ns * 9 / 100_000).
|
||||
constexpr uint64_t period_ns = ( ( 1ULL << 32 ) * 100'000ULL + 9ULL - 1ULL ) / 9ULL;
|
||||
static_assert ( sc::rtp_timestamp_from_ns ( period_ns ) == 0u );
|
||||
static_assert ( sc::rtp_timestamp_from_ns ( period_ns + 1'000'000'000ULL ) == 90'000u );
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user