Skip to content
Closed
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
51 changes: 42 additions & 9 deletions openh264/src/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use crate::formats::YUVSource;
use crate::{Error, OpenH264API, Timestamp};
use openh264_sys2::{
videoFormatI420, ELevelIdc, EProfileIdc, EUsageType, EVideoFormatType, ISVCEncoder, ISVCEncoderVtbl, SEncParamBase,
SEncParamExt, SFrameBSInfo, SLayerBSInfo, SSourcePicture, API, DEBLOCKING_IDC_0, ENCODER_OPTION, ENCODER_OPTION_DATAFORMAT,
ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, ENCODER_OPTION_TRACE_LEVEL, RC_MODES, SM_SINGLE_SLICE, SM_SIZELIMITED_SLICE,
VIDEO_CODING_LAYER, WELS_LOG_DETAIL, WELS_LOG_QUIET,
SEncParamExt, SFrameBSInfo, SLayerBSInfo, SSourcePicture, API, DEBLOCKING_IDC_0, ENCODER_OPTION, ENCODER_OPTION_BITRATE,
ENCODER_OPTION_DATAFORMAT, ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, ENCODER_OPTION_TRACE_LEVEL, RC_MODES, SM_SINGLE_SLICE,
SM_SIZELIMITED_SLICE, VIDEO_CODING_LAYER, WELS_LOG_DETAIL, WELS_LOG_QUIET,
};
use std::os::raw::{c_int, c_uchar, c_void};
use std::ptr::{addr_of_mut, from_mut, null, null_mut};
Expand Down Expand Up @@ -776,17 +776,17 @@ impl Encoder {
}

unsafe {
if self.previous_dimensions.is_none() {
// First time we call initialize_ext
self.raw_api.initialize_ext(&raw const params).ok()?;
self.raw_api.set_option(ENCODER_OPTION_TRACE_LEVEL, addr_of_mut!(self.config.debug).cast()).ok()?;
self.raw_api.set_option(ENCODER_OPTION_DATAFORMAT, addr_of_mut!(self.config.data_format).cast()).ok()?;
} else {
if self.is_initialized() {
// Subsequent times we call SetOption
self.raw_api.set_option(ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, addr_of_mut!(params).cast()).ok()?;

// Start with a new keyframe after dimensions changed.
self.force_intra_frame();
} else {
// First time we call initialize_ext
self.raw_api.initialize_ext(&raw const params).ok()?;
self.raw_api.set_option(ENCODER_OPTION_TRACE_LEVEL, addr_of_mut!(self.config.debug).cast()).ok()?;
self.raw_api.set_option(ENCODER_OPTION_DATAFORMAT, addr_of_mut!(self.config.data_format).cast()).ok()?;
}
}

Expand All @@ -802,6 +802,39 @@ impl Encoder {
}
}

const fn is_initialized(&self) -> bool {
self.previous_dimensions.is_some()
}

/// Sets the target bit rate "runtime".
///
/// If the encoder is already running, this uses the openh264 API to change it without
/// reinitializing the encoder.
///
/// # Errors
///
/// This might error for various reasons, many of which aren't clearly documented in OpenH264.
pub fn set_target_bitrate(&mut self, bps: BitRate) -> Result<(), Error> {
if self.config.target_bitrate == bps {
return Ok(());
}

self.config.target_bitrate = bps;

// If raw_api is already initialized, we do a runtime change, otherwise
// rely on the bitrate being set when calling initialize_ext()
if self.is_initialized() {
unsafe {
let mut bps = bps;
self.raw_api
.set_option(ENCODER_OPTION_BITRATE, from_mut(&mut bps.0).cast())
.ok()?;
}
}

Ok(())
}

/// Obtain the raw API for advanced use cases.
///
/// When resorting to this call, please consider filing an issue / PR.
Expand Down