Files
oak-editor/src/audio/rust/src/bridge/ffmpeg.rs
T
Mike-Solar 4b24aa9d67 feat(rust): first green Rust crates — oakcore-rs, oakundo, oakcommon, oaktimeline, oakaudio
- oakcore-rs: Rational/TimeRange/TimeRangeList/PixelFormat/SampleFormat
  mirroring oakcore C++ semantics (91.6% coverage)
- oakundo: UndoCommand/UndoStack with vtable commands (99.6%)
- oakcommon: config/XML/VideoParams/logging etc. (89.8%, 516 tests);
  XML via quick-xml, logging via the log facade
- oaktimeline: markers/workarea/edit commands (95.4%)
- oakaudio: processor/manager/sync/waveform/levelmeter (88.4%)
- unified -MMCCCC error codes across all C ABI headers (registry in
  include/common/error.h; pass-through rule)
- olive::Variant moved node -> common (cross-module value type)
- oakcommon_videoparams_set_is_3d added to the C ABI
- M11 (oakplugin Rust rewrite) plan + notes.md freeze line for the
  inter-module C ABI wiring
2026-08-09 04:24:28 +08:00

217 lines
7.6 KiB
Rust

// Oak Video Editor - Non-Linear Video Editor
// Copyright (C) 2026 Oak Team
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//! ffmpeg_bridge C ABI imports (audio filter graph, frames, decoder). The
//! graph converts/resamples/time-stretches planar audio; used by the
//! [`crate::processor`] resampler and the [`crate::waveform`] extractor.
use std::ffi::{c_char, c_int, c_void};
/// `FBSampleFormat` — mirrors `AVSampleFormat` (values cross the C ABI as
/// `int`). `fltp` (planar f32) is the natural exchange format for oakaudio.
///
/// `// CPP-PARITY: ffmpeg_bridge/include/ffmpeg_bridge/ffmpeg_bridge.h:117`.
#[repr(i32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SampleFormat {
/// No format.
None = -1,
/// Unsigned 8-bit, packed.
U8 = 0,
/// Signed 16-bit, packed.
S16 = 1,
/// Signed 32-bit, packed.
S32 = 2,
/// 32-bit float, packed.
Flt = 3,
/// 64-bit float, packed.
Dbl = 4,
/// Unsigned 8-bit, planar.
U8Planar = 5,
/// Signed 16-bit, planar.
S16Planar = 6,
/// Signed 32-bit, planar.
S32Planar = 7,
/// 32-bit float, planar.
Fltp = 8,
/// 64-bit float, planar.
Dblp = 9,
/// Signed 64-bit, packed.
S64 = 10,
/// Signed 64-bit, planar.
S64Planar = 11,
}
/// `FBAudioGraphConfig` — source graph input/output spec.
///
/// `// CPP-PARITY: ffmpeg_bridge/include/ffmpeg_bridge/ffmpeg_bridge.h:510`.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct AudioGraphConfig {
/// Input sample rate in Hz.
pub in_sample_rate: c_int,
/// Input channel layout mask (`0` = derive from `in_channels`).
pub in_channel_layout_mask: u64,
/// Input sample format (`FBSampleFormat`; planar float in).
pub in_sample_format: c_int,
/// Input channel count.
pub in_channels: c_int,
/// Output sample rate in Hz.
pub out_sample_rate: c_int,
/// Output channel layout mask (`0` = derive from `out_channels`).
pub out_channel_layout_mask: u64,
/// Output sample format (`FBSampleFormat`).
pub out_sample_format: c_int,
/// Output channel count.
pub out_channels: c_int,
/// Whether the output is planar.
pub out_is_planar: c_int,
/// Time-stretch tempo multiplier.
pub tempo: f64,
}
/// Opaque audio filter graph.
pub type AudioGraph = c_void;
/// Opaque frame.
pub type Frame = c_void;
/// Opaque packet.
pub type Packet = c_void;
/// Opaque decoder.
pub type Decoder = c_void;
/// `FBStreamInfo` — decoded stream metadata, mirroring the same-named
/// struct in ffmpeg_bridge/include/ffmpeg_bridge/ffmpeg_bridge.h. Only the
/// audio fields are consumed by oakaudio; the video/container fields are
/// kept to preserve layout.
///
/// `// CPP-PARITY: ffmpeg_bridge/include/ffmpeg_bridge/ffmpeg_bridge.h:335`.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct FBStreamInfo {
/// Stream index.
pub index: c_int,
/// Media type (`FBMediaType`).
pub codec_type: c_int,
/// Opaque FFmpeg codec id.
pub codec_id: c_int,
/// Non-zero if a decoder exists for this stream.
pub has_decoder: c_int,
/// Video width.
pub width: c_int,
/// Video height.
pub height: c_int,
/// Video pixel format (`FBPixelFormat`).
pub pixel_format: c_int,
/// Video field order (`FBFieldOrder`).
pub field_order: c_int,
/// Video color range (`FBColorRange`).
pub color_range: c_int,
/// Raw `AVColorPrimaries` value.
pub color_primaries: c_int,
/// Raw `AVColorTransferCharacteristic` value.
pub color_trc: c_int,
/// Sample rate in Hz.
pub sample_rate: c_int,
/// Sample format (`FBSampleFormat`).
pub sample_format: c_int,
/// Channel layout mask (never zero for valid audio).
pub channel_layout_mask: u64,
/// Stream start time.
pub start_time: i64,
/// Stream duration.
pub duration: i64,
/// Stream time base numerator.
pub time_base_num: c_int,
/// Stream time base denominator.
pub time_base_den: c_int,
/// Average frame rate numerator.
pub avg_frame_rate_num: c_int,
/// Average frame rate denominator.
pub avg_frame_rate_den: c_int,
}
extern "C" {
/// `fb_audio_graph_create` — build a graph from `config`.
pub fn fb_audio_graph_create(config: *const AudioGraphConfig) -> *mut AudioGraph;
/// `fb_audio_graph_free`.
pub fn fb_audio_graph_free(graph: *mut *mut AudioGraph);
/// `fb_audio_graph_push` — push planar samples; `channel_data == NULL`
/// flushes the graph.
pub fn fb_audio_graph_push(
graph: *mut AudioGraph,
channel_data: *const *const u8,
nb_samples: c_int,
) -> c_int;
/// `fb_audio_graph_pull` — pull converted samples. 1 = frame produced,
/// 0 = need more input, negative = error.
pub fn fb_audio_graph_pull(graph: *mut AudioGraph, out_frame: *mut Frame) -> c_int;
/// `fb_channel_layout_get_channels` — channel count of a mask.
pub fn fb_channel_layout_get_channels(mask: u64) -> c_int;
/// `fb_channel_layout_default` — default layout mask for `nb_channels`.
pub fn fb_channel_layout_default(nb_channels: c_int) -> u64;
/// `fb_frame_alloc`.
pub fn fb_frame_alloc() -> *mut Frame;
/// `fb_frame_free`.
pub fn fb_frame_free(frame: *mut *mut Frame);
/// `fb_frame_unref`.
pub fn fb_frame_unref(frame: *mut Frame);
/// `fb_frame_get_nb_samples`.
pub fn fb_frame_get_nb_samples(frame: *const Frame) -> c_int;
/// `fb_frame_set_nb_samples`.
pub fn fb_frame_set_nb_samples(frame: *mut Frame, nb_samples: c_int);
/// `fb_frame_get_sample_rate`.
pub fn fb_frame_get_sample_rate(frame: *const Frame) -> c_int;
/// `fb_frame_get_format`.
pub fn fb_frame_get_format(frame: *const Frame) -> c_int;
/// `fb_frame_get_channel_layout_mask`.
pub fn fb_frame_get_channel_layout_mask(frame: *const Frame) -> u64;
/// `fb_frame_get_data` — writable plane data.
pub fn fb_frame_get_data(frame: *mut Frame, plane: c_int) -> *mut u8;
/// `fb_frame_get_data_const` — read-only plane data.
pub fn fb_frame_get_data_const(frame: *const Frame, plane: c_int) -> *const u8;
/// `fb_frame_get_linesize`.
pub fn fb_frame_get_linesize(frame: *const Frame, plane: c_int) -> c_int;
/// `fb_packet_alloc`.
pub fn fb_packet_alloc() -> *mut Packet;
/// `fb_packet_free`.
pub fn fb_packet_free(packet: *mut *mut Packet);
/// `fb_packet_unref`.
pub fn fb_packet_unref(packet: *mut Packet);
/// `fb_decoder_create`.
pub fn fb_decoder_create() -> *mut Decoder;
/// `fb_decoder_free`.
pub fn fb_decoder_free(decoder: *mut *mut Decoder);
/// `fb_decoder_open` — open stream `stream_index` of `filename`.
pub fn fb_decoder_open(decoder: *mut Decoder, filename: *const c_char, stream_index: c_int)
-> c_int;
/// `fb_decoder_close`.
pub fn fb_decoder_close(decoder: *mut Decoder);
/// `fb_decoder_get_frame` — decode one frame from `packet`.
pub fn fb_decoder_get_frame(decoder: *mut Decoder, packet: *mut Packet, frame: *mut Frame) -> c_int;
/// `fb_decoder_get_packet` — read one packet.
pub fn fb_decoder_get_packet(decoder: *mut Decoder, packet: *mut Packet) -> c_int;
/// `fb_decoder_get_stream_info` — copy stream info into `out`.
pub fn fb_decoder_get_stream_info(decoder: *const Decoder, out: *mut FBStreamInfo) -> c_int;
/// `fb_decoder_get_format_start_time`.
pub fn fb_decoder_get_format_start_time(decoder: *const Decoder) -> i64;
/// `fb_decoder_get_format_duration`.
pub fn fb_decoder_get_format_duration(decoder: *const Decoder) -> i64;
}