Skip to content

Commit

Permalink
Support Betaflight 4.5 four color fonts (avsaase#35)
Browse files Browse the repository at this point in the history
* First cut on BF 4 page fonts

* Code formatting

* Fix clippy lint

* Refactor font type detection and font splitting

* Add unit tests

* Rename four page -> four color

* Update changelog
  • Loading branch information
avsaase authored Aug 26, 2023
1 parent 6c65c0f commit 2562d55
Show file tree
Hide file tree
Showing 16 changed files with 183 additions and 91 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
## [Unreleased]

### Added

- Load last used OSD font file on startup (@dz0ny).
- Option to render video with a chroma key background instead of the input video so the OSD can be overlayed in a video editor.
- Support for Betaflight 4.5 four color fonts.

### Fixed

- Bug that caused font files with unexpected number of characters to not open.

## [0.2.0] - 2023-04-23

### Added

- Save OSD and SRT options between program runs.
- Custom position and text size of SRT data.
- Option to adjust OSD playback speed to correct for OSD lag with <=32.37.10 firmware.
Expand All @@ -24,56 +28,67 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- Tooltips explaining options and settings.

### Changed

- When loading a SRT file with distance data the distance checkbox doesn't get automatically checked.
- Options sections can be collapsed to save screen space.

## [0.1.0] - 2023-03-31

### Fixed

- Parsing of firmware version 32.37.10 SRT data.

## [0.1.0-beta4] - 2023-03-28

### Added

- Render data from the SRT file on the video. Select which values are rendered.
- Automatically load the matching OSD and SRT files when importing a video (they must be in the same folder and have the same file name).
- Upscale output video to 1440p to get better compression on YouTube.

### Changed

- New UI layout with better support for different screen sizes.
- Many small UI tweaks.

### Fixed

- Show correct number of characters in font file.

## [0.1.0-beta3] - 2023-03-21

### Added

- Open files by dropping them on the window.
- Improve render speed.
- Logging of ffmpeg errors and warnings.
- Option to select undetected encoders (use at your own risk).
- Dark theme (default light, toggle by clicking the sun/moon icon in the top right).

### Changed

- Improved handling of ffmpeg events.

### Fixed

- Issue with non-critical ffmpeg errors stopping the render process.
- Output videos not playable in some video players.

## [0.1.0-beta2] - 2023-03-15

### Added

- Make main window resizable in vertical direction to accomodate retina displays and screens with lower resolutions.
- Display errors from ffmpeg.
- Display tooltip when hovering over start render button when it is disabled.

### Changed

- Improved formatting of "About" window.
- Improved display of render status when rendering is finished or cancelled.

### Fixed

- Check for `hevc_videotoolbox` encoder on MacOS.
- Stop ffmpeg decoder when encoder returns error.
- Fixed version info display.
Expand All @@ -82,4 +97,5 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
## [0.1.0-beta1] - 2023-03-11

### Added

First beta release with limited features.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ serde = { version = "1.0.159", features = ["derive"] }
srtparse = "0.2.0"
thiserror = "1.0.38"
tracing = "0.1.37"

[dev-dependencies]
claims = "0.7.1"
4 changes: 2 additions & 2 deletions backend/src/ffmpeg/encoders.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::{fmt::Display, path::PathBuf, process::Command};

use rayon::prelude::*;
use serde::{Deserialize, Serialize};

use std::{fmt::Display, path::PathBuf, process::Command};

#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub enum Codec {
H264,
Expand Down
3 changes: 1 addition & 2 deletions backend/src/ffmpeg/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,14 @@ use ffmpeg_sidecar::{
event::{FfmpegEvent, LogLevel},
};

use super::{render_settings::RenderSettings, Encoder, FromFfmpegMessage, ToFfmpegMessage, VideoInfo};
use crate::{
font,
osd::{self, OsdOptions},
overlay::FrameOverlayIter,
srt::{self, SrtOptions},
};

use super::{render_settings::RenderSettings, Encoder, FromFfmpegMessage, ToFfmpegMessage, VideoInfo};

#[tracing::instrument(skip(osd_frames, srt_frames, font_file), err)]
pub fn start_video_render(
ffmpeg_path: &PathBuf,
Expand Down
51 changes: 0 additions & 51 deletions backend/src/font/character_size.rs

This file was deleted.

109 changes: 109 additions & 0 deletions backend/src/font/dimensions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use std::fmt::Display;

use super::FontFileError;

pub(crate) const CHARACTER_WIDTH_LARGE: u32 = 36;
pub(crate) const CHARACTER_HEIGHT_LARGE: u32 = 54;
pub(crate) const CHARACTER_WIDTH_SMALL: u32 = 24;
pub(crate) const CHARACTER_HEIGHT_SMALL: u32 = 36;

#[derive(Debug, Clone, PartialEq)]
pub enum CharacterSize {
Large,
Small,
}

impl CharacterSize {
pub fn width(&self) -> u32 {
match self {
CharacterSize::Large => CHARACTER_WIDTH_LARGE,
CharacterSize::Small => CHARACTER_WIDTH_SMALL,
}
}

pub fn height(&self) -> u32 {
match self {
CharacterSize::Large => CHARACTER_HEIGHT_LARGE,
CharacterSize::Small => CHARACTER_HEIGHT_SMALL,
}
}
}

impl Display for CharacterSize {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
CharacterSize::Large => "Large",
CharacterSize::Small => "Small",
}
)
}
}

#[derive(Debug, Clone, PartialEq)]
pub enum FontType {
Standard,
FourColor,
}

impl FontType {
pub fn pages(&self) -> u32 {
match self {
FontType::Standard => 1,
FontType::FourColor => 4,
}
}
}

pub fn detect_dimensions(width: u32, height: u32) -> Result<(CharacterSize, FontType, u32), FontFileError> {
let (size, r#type) = if width == CHARACTER_WIDTH_SMALL {
(CharacterSize::Small, FontType::Standard)
} else if width == CHARACTER_WIDTH_LARGE {
(CharacterSize::Large, FontType::Standard)
} else if width == CHARACTER_WIDTH_SMALL * 4 {
(CharacterSize::Small, FontType::FourColor)
} else if width == CHARACTER_WIDTH_LARGE * 4 {
(CharacterSize::Large, FontType::FourColor)
} else {
return Err(FontFileError::InvalidFontFileWidth { width });
};

if height % size.height() != 0 {
return Err(FontFileError::InvalidFontFileHeight { height });
}

let characters_count = height / size.height();

Ok((size, r#type, characters_count))
}

#[cfg(test)]
mod tests {
use claims::{assert_err, assert_ok_eq};

use super::*;

#[test]
fn detect_valid_font_sizes() {
let test_cases = [
(36, 13824, CharacterSize::Large, FontType::Standard, 256),
(24, 18432, CharacterSize::Small, FontType::Standard, 512),
(36, 27648, CharacterSize::Large, FontType::Standard, 512),
(96, 9216, CharacterSize::Small, FontType::FourColor, 256),
(144, 13824, CharacterSize::Large, FontType::FourColor, 256),
];
for test in test_cases {
assert_ok_eq!(detect_dimensions(test.0, test.1), (test.2, test.3, test.4));
}
}

#[test]
fn reject_invalid_font_sizes() {
let test_cases = [(36, 13824 + 1), (24 + 1, 18432), (36 - 12, 27648 - 10)];
for test in test_cases {
assert_err!(detect_dimensions(test.0, test.1));
}
}
}
3 changes: 3 additions & 0 deletions backend/src/font/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ pub enum FontFileError {

#[error("Invalid fond file width {width}")]
InvalidFontFileWidth { width: u32 },

#[error("Invalid fond file height {height}")]
InvalidFontFileHeight { height: u32 },
}
Loading

0 comments on commit 2562d55

Please sign in to comment.