crates/mediafoundation-ffmpeg/README.md
This crate provides utilities for muxing H264 encoded samples from Windows MediaFoundation into container formats using FFmpeg.
When using MediaFoundation for hardware-accelerated H264 encoding, the encoded output needs to be muxed into a container format (MP4, MKV, etc.). This crate bridges MediaFoundation's IMFSample output with FFmpeg's powerful muxing capabilities.
IMFSample objectsuse cap_mediafoundation_ffmpeg::{H264SampleMuxer, MuxerConfig};
use std::path::PathBuf;
// Configure the muxer
let config = MuxerConfig {
width: 1920,
height: 1080,
fps: 30,
bitrate: 5_000_000, // 5 Mbps
};
// Create the muxer
let mut muxer = H264SampleMuxer::new_mp4(
PathBuf::from("output.mp4"),
config,
)?;
// Write MediaFoundation samples
// (assuming you have an encoder producing IMFSample objects)
for sample in encoded_samples {
muxer.write_sample(&sample)?;
}
// Finish muxing
muxer.finish()?;
If you already have extracted H264 data:
muxer.write_h264_data(
&h264_data,
pts, // presentation timestamp in microseconds
dts, // decode timestamp in microseconds
duration, // duration in microseconds
is_keyframe,
)?;
This crate is designed to work with MediaFoundation H264 encoders. After encoding a frame with MediaFoundation:
IMFSample containing H264 datawrite_sample()MediaFoundation uses 100-nanosecond units for timestamps, while FFmpeg typically works with microseconds. This crate automatically handles the conversion:
The muxer automatically detects IDR frames (keyframes) by inspecting the H264 NAL unit types. This ensures proper seeking and playback in the output file.
The crate also includes utility traits for converting FFmpeg audio frames to MediaFoundation samples:
AudioExt: Convert ffmpeg::frame::Audio to IMFSamplePlanarData: Access planar audio dataAll operations return proper error types that can be handled:
match muxer.write_sample(&sample) {
Ok(_) => // Success
Err(e) => eprintln!("Failed to write sample: {}", e),
}
The H264SampleMuxer is not thread-safe and should be used from a single thread. If you need concurrent access, wrap it in appropriate synchronization primitives.