Native Platforms Release Notes
Updates to the Native SDK for Android, iOS, macOS, Linux, and Windows applications.
2024-04-25 - 1.8.4
Fixes
- Fixed a bug where invalid metadata information was placed when creating debian packages. The
Architecture
field would always default to amd64. This caused issues when unpacking thedebian11-armv8a
packages. - Introduced a new method to ObjC SDK to allow setting the log levels for the Sdk/Webrtc/Websocket components
+ (void)setLogLevelWithSdk:(MCLogLevel)sdkLogLevel
Webrtc:(MCLogLevel)webrtcLogLevel
Websocket:(MCLogLevel)websocketLogLevel;
- Added auto collection of WebRTC logs in ObjC SDK. This is inline with what was done for Android in the 1.8.2 release.
Fixes
-
Fixed a crash in the Objective C SDK caused by calling the frameType method, which resulted in the NSInvalidArgumentException exception.
-
Introduced a new Native video type (Desktop, Apple, Android) to describe the native frames.
-
Fixed an issue where VideoType incorrectly returned the Unknown type.
2024-04-12 - 1.8.2
Features
Introduced a new API for setting logger callbacks. The API accepts the components for which log callbacks are desired to be received.
/**
* @brief The LogComponent enum describes which components are possible to
* receive logs from in the log callback.
*/
enum class LogComponent { SDK, WEBRTC, WEBSOCKET };
/**
* @brief Sets the object that will receive the logs from the SDK.
* @param f The logger object with first parameter being the description of the
* component the log came from, the second being the message itself, and
* the log level.
* @param components A vector containing the list of components you would like
* to receive log callbacks for.
*/
MILLICAST_API static void set_logger(
std::function<void(const std::string& component,
const std::string& msg,
LogLevel)> f,
std::vector<Logger::LogComponent>&& components);
Fixes
- Fixed an issue on Android where decoding H.264 Simulcast streams would result in low frame rates after layer changes.
- Fixed an issue where applications that set logger callback would not receive logs from WebRTC. The issue was fixed by introducing a new C++ API, as described in the features section.
2024-04-04 - 1.8.1
Fixes
Fixed an issue on Android where calling the connect method on a non-live stream led to unresolved asynchronous operations and hanging the Subscriber until the stream went live, which resulted in blocking subsequent calls to disconnect. The fix maintains the necessity of calling subscribe after connecting and receiving the SubscriberConnectionState.Connected event.
2024-03-20 - 1.8.0
Features
- Introduced a new asynchronous API for all Apple platforms, such as iOS, tvOS, and macOS. This change impacts the way of publishing streams. For more information, see the updated Getting Started document.
- Enabled the use of Simulcast and Scalable Video Coding (SVC) at the same time when using the VP8 codec.
- Reduced the package size of the Android SDK by removing unused NDI library. The total
aar
size is reduced by 7.1 MB. Approximate per-architecture reductions in size:x86_64
: 2.9 MB, the totalaar
size is 6.5 MBx86
: 1.5 MB, the totalaar
size is 6.4 MBarm64-v8a
: 1.3 MB, the totalaar
size is 5.7 MBarmeabi-v7a
: 1.4 MB, the totalaar
size is 4.7 MB
Fixes
- Fixed an issue that blocked applications from enabling SVC when using the AV1 codec. Now applications can use either VP8 with Simulcast and SVC or AV1 with SVC.
- Fixed an issue where elements were unnecessarily prefixed
video/
oraudio/
in the active event's tracks on the subscriber. - Fixed the generation of audio and video source statistics.
- Improved stability.
Breaking changes
Android
- Separated the Subscriber/Publisher connection
com.millicast.clients.state.ConnectionState
states intocom.millicast.subscribers.state.SubscriberConnectionState
andcom.millicast.publishers.state.PublisherConnectionState
. These two state classes now contain the full life cycle. - Removed the NDI library, which means that there are no more NDI references in the Android SDK.
Apple platforms
The new asynchronous API replaced the previous synchronous one, which impacts the way of publishing streams. For more information, see the updated Getting Started document.
2024-03-18 - 1.8.0-beta.1
Features
- Introduced a new asynchronous API for all Apple platforms, such as iOS, tvOS, and macOS. This change impacts the way of publishing streams.
- Enabled the use of Simulcast and Scalable Video Coding (SVC) at the same time when using the VP8 codec.
- Reduced the package size of the Android SDK by removing unused NDI library. The total
aar
size is reduced by 7.1 MB. Approximate per-architecture reductions in size:x86_64
: 2.9 MBx86
: 1.5 MBarm64-v8a
: 1.3 MBarmeabi-v7a
: 1.4 MB
Fixes
- Fixed an issue that blocked applications from enabling SVC when using the AV1 codec. Now applications can use either VP8 with Simulcast and SVC or AV1 with SVC.
- Fixed an issue where elements were unnecessarily prefixed
video/
oraudio/
in the active event's tracks on the subscriber. - Fixed the generation of audio and video source statistics.
- Improved stability.
Breaking changes
Android
- Separated the Subscriber/Publisher connection
com.millicast.clients.state.ConnectionState
states intocom.millicast.subscribers.state.SubscriberConnectionState
andcom.millicast.publishers.state.PublisherConnectionState
. These two state classes now contain the full life cycle. - Removed the NDI library for Android, this means that there are no more NDI references in the Android SDK.
Apple platforms
The new asynchronous API replaced the previous synchronous one.
2024-03-15 - 1.8.0-alpha.2
Features
- Introduced a new asynchronous API for all Apple platforms, such as iOS, tvOS, and macOS. This change impacts the way of publishing streams.
- Enabled the use of Simulcast and Scalable Video Coding (SVC) at the same time when using the VP8 codec.
- Reduced the package size of the Android SDK by removing unused NDI library. The total
aar
size is reduced by 7.1 MB. Approximate per-architecture reductions in size:x86_64
: 2.9 MBx86
: 1.5 MBarm64-v8a
: 1.3 MBarmeabi-v7a
: 1.4 MB
Fixes
- Fixed an issue that blocked applications from enabling SVC when using the AV1 codec. Now applications can use either VP8 with Simulcast and SVC or AV1 with SVC.
- Fixed an issue where elements were unnecessarily prefixed
video/
oraudio/
in the active event's tracks on the subscriber. - Fixed the generation of audio and video source statistics.
- Improved stability.
Breaking changes
Android
- Separated the Subscriber/Publisher connection
com.millicast.clients.state.ConnectionState
states intocom.millicast.subscribers.state.SubscriberConnectionState
andcom.millicast.publishers.state.PublisherConnectionState
. These two state classes now contain the full life cycle. - Removed the NDI library for Android, this means that there are no more NDI references in the Android SDK.
Objective C/Swift SDK
The new asynchronous API replaced the previous synchronous one.
2024-03-14 - 1.8.0-alpha.1
Features
- Introduced a new asynchronous API for all Apple platforms, such as iOS, tvOS, and macOS. This change impacts the way of publishing streams.
- Enabled the use of Simulcast and Scalable Video Coding (SVC) at the same time when using the VP8 codec.
Fixes
- Fixed an issue that blocked applications from enabling SVC when using the AV1 codec. Now applications can use either VP8 with Simulcast and SVC or AV1 with SVC.
- Fixed the generation of audio and video source statistics.
- Improved stability.
2024-03-14 - 1.7.4
Fixes
Fixed a string conversion issue that affected UTF-formatted strings on Android.
2024-02-28 - 1.7.3
Fixes
General
- Fixed a race condition when rendering video tracks.
- Fixed a race condition inside the NDI Video Renderer implementation.
Android
- Fixed an issue with an internal queue that could cause inconsistencies.
- Improved the isConnected, isSubscribed, and isPublishing method to prevent blocking.
- Fixed the missing reset for the subscriber's and publisher's state.
- Modified the release function to prevent suspending it.
2024-02-14 - 1.7.2
Fixes
- Fixed an issue causing a crash when using video rendering on Windows.
- Fixed incorrect Android stats generation.
- Fixed an issue related to the absence of the optional
android.hardware.microphone
requirement. - Fixed an issue where a disconnection did not flush the Subscriber's state object on Android.
Changes
Introduced the addRemoteTrackForResult
Android API to improve the management of the subscriber's tracks. The API is similar to addRemoteTrack but it returns a TrackHolder
directly. The subscriber's state now contains a list of tracks, their activity, and the existing flow.
2024-02-09 - 1.7.1
Fixes
Fixed a race condition leading to a crash on Linux after stopping video capture.
2024-02-08 - 1.7.0
Features
- Refactored the Android SDK to introduce the following changes:
- Prioritization of the Kotlin implementation to make Kotlin the primary language for developing and interacting with the Android SDK.
- Key instantiation for classes instead of builders to streamline the codebase for greater clarity and conciseness.
- A coroutine-based implementation for both Subscriber and Publisher calls that enhances the SDK's responsiveness and efficiency.
- A flow-based eventing system that is useful for handling and reacting to events.
- Introduced macOS and iOS support for H.265.
- Introduced GNU libstdc++ versions of the SDK for the proper Ubuntu compatibility.
- Introduced the debian11-armv8a version of the SDK with no X11 and PulseAudio dependencies, which is useful for publishing from ARM64 Linux boards.
- Added the H.264 hardware encoding support for Raspberry Pi3b+/4/5 boards with the debian11-armv8a package.
- Improved the on_layers event and the respective ViewerLayerData structure to include fields for the
resolution
of the layer. - Upgraded the WebRTC version to 118.
Fixes
- Introduced Simulcast publishing support for macOS and iOS platforms.
- Fixed JNI-related issues on Android.
- Fixed an issue that prevented using the SDK on iOS or tvOS simulators.
- Introduced stability improvements.
Changes
- The SDK now links FFmpeg dynamically on Linux and Windows. The SDK package provides a dynamic FFmpeg library.
- Created macOS universal framework.
Breaking Changes
This release introduces several braking changes and requires familiarizing with the following chapters.
New signature of the on_layers event
The on_layers event has a new signature to accept an array of strings for the inactive layers. The following code presents the current signature of the callback:
virtual void on_layers( const std::string& mid,
const std::vector<ViewerLayerData>& active_layers,
const std::vector<std::string>& inactive_layers) = 0;
This change is propagated to the iOS layer. The following example presents the current signature of the callback for the Objective C SDK:
(void) onLayers: (nonnull NSString*) mid activeLayers:(nonnull NSArray<MCLayerData*>*) activeLayers inactiveLayers:(nonnull NSArray<NSString*>*) inactiveLayers;
The Kotlin SDK is also impacted by this modification and requires applications to listen for the Subscriber's layers Flow:
subscriber.layers.collect { layers ->
// manage the layers object here
}
The following code presents the current signature for the SDK:
data class Layers(
val mid: String,
val activeLayers: Array<LayerData>,
val inactiveLayersEncodingIds: Array<String>
)
Modified values of the ViewerLayerData structure
Values of the ViewerLayerData structure that may not be present for a layer, such as spatial ID or temporal ID, are now optional. The following example presents the new signature of the structure:
struct ViewerLayerData {
struct Resolution {
int width;
int height;
};
std::string encoding_id;
int bitrate = 0;
std::optional<int> temporal_layer_id;
std::optional<int> spatial_layer_id;
std::optional<Resolution> layer_resolution;
std::optional<int> max_temporal_layer_id;
std::optional<int> max_spatial_layer_id;
};
This change is propagated to the iOS layer. The current MCLayerData structure in the Objective C SDK is presented in the following example:
@interface MCLayerResolution : NSObject
@property int height;
@property int width;
@end
MILLICAST_API @interface MCLayerData : NSObject
@property (nonatomic, strong, nonnull) NSString* encodingId;
@property int bitrate;
@property(nonatomic, assign, nullable) NSNumber *spatialLayerId;
@property(nonatomic, assign, nullable) NSNumber *temporalLayerId;
@property(nonatomic, assign, nullable) NSNumber *maxTemporalLayerId;
@property(nonatomic, assign, nullable) NSNumber *maxSpatialLayerId;
@property(nonatomic, assign, nullable) MCLayerResolution* layerResolution;
@end
This change also impacts the Kotlin implementation. The following example presents the new signature of the structure:
data class LayerResolution(
val width: Int = 0,
val height: Int = 0
)
data class LayerData(
val encodingId: String = "",
val bitrate: Int = 0,
val temporalLayerId: Int? = null,
val spatialLayerId: Int? = null,
val maxSpatialLayerId: Int? = null,
val maxTemporalLayerId: Int? = null,
val resolution: LayerResolution? = null
)
Modified Kotlin implementation
In the Kotlin implementation, the getStats method is now removed in favor of enableStats, which emits reports asynchronously via the corresponding SharedFlow.
Using the Kotlin SDK to create a Publisher or Subscriber now requires calling the Core class implementation, as in the following example:
Core.createPublisher()
Core.createSubscriber()
Additionally, the SDK now provides an asynchronous implementation, so to consume the Subscriber and Publisher features, perform coroutines.
The Listener implementation is now removed and replaced with SharedFlow, which is now provided by both main classes. For the Subscriber class, several new SharedFlow events have been introduced:
- state: Provides information about the state of the subscriber.
- signalingError: Provides all propagated errors.
- rtcStatsReport: Provides WebRTC statistics when stats reporting is enabled. The statistics report provides the Stats object based on a Sealed class. Using a
when
statement helps find various statistics. - track: Provides all audio and video track events, including the track itself and its associated Media ID identifier.
- activity: Provides information about the active and inactive states of the subscriber's activity.
- layers: Corresponds to all layers events, providing information about the layers associated with the subscriber.
- vad: Provides voice activity events.
For more information on SharedFlow, see the following example:
data class SubscriberState(
val connectionState: ConnectionState = ConnectionState.Default,
val subscriptionState: SubscriptionState = SubscriptionState.Default,
val viewers: Int = 0
)
sealed class TrackHolder(
val mid: String?,
val track: Track
) {
class AudioTrackHolder(
mid: String?,
val audioTrack: AudioTrack
) : TrackHolder(mid, audioTrack)
class VideoTrackHolder(
mid: String?,
val videoTrack: VideoTrack
) : TrackHolder(mid, videoTrack)
}
sealed class ActivityStream {
data class Active(
val streamId: String,
val track: Array<String>,
val sourceId: String?
) : ActivityStream()
data class Inactive(
val streamId: String,
val sourceId: String?
) : ActivityStream()
}
data class Layers(
val mid: String,
val activeLayers: Array<LayerData>,
val inactiveLayersEncodingIds: Array<String>
)
The auto reconnect property removal
The auto reconnect property is removed from publisher and subscriber options in favour of using connection options. Use ConnectionOptions to set the autoReconnect (Android, iOS, Desktop) property:
//file: millicast-sdk/client.h
struct MILLICAST_API ClientConnectionOptions {
bool auto_reconnect{true};
};
//file: MillicastSDK/client.h
MILLICAST_API @interface MCConnectionOptions: NSObject
@property(nonatomic, assign) BOOL autoReconnect;
@end
package com.millicast.clients;
public class ConnectionOptions {
public boolean autoReconnect;
}
2024-02-04 - 1.7.0-beta.1
Features
- Refactored the Android SDK to introduce the following changes:
- Prioritization of the Kotlin implementation to make Kotlin the primary language for developing and interacting with the Android SDK.
- Key instantiation for classes instead of builders to streamline the codebase for greater clarity and conciseness.
- A coroutine-based implementation for both Subscriber and Publisher calls that enhances the SDK's responsiveness and efficiency.
- A flow-based eventing system that is useful for handling and reacting to events.
- Introduced macOS and iOS support for H.265.
- Introduced
GNU libstdc++
versions of the SDK for the proper Ubuntu compatibility. - Introduced the
debian11-armv8a
version of the SDK with no X11 and PulseAudio dependencies, which is useful for publishing from ARM64 Linux boards. - Added the H.264 hardware encoding support for Raspberry Pi3b+/4/5 boards with the
debian11-armv8a
package. - Improved the
millicast::ViewerListener::on_layers
event and the respectivemillicast::ViewerLayerData
structure to include fields for theresolution
of the layer. - Upgraded the WebRTC version to 118.
Fixes
- Introduced Simulcast publishing support for macOS and iOS platforms.
- Fixed JNI-related issues on Android.
- Fixed an issue that prevented using the SDK on iOS or tvOS simulators.
- Introduced stability improvements.
Changes
- The SDK now links FFmpeg dynamically on Linux and Windows. The SDK package provides a dynamic FFmpeg library.
- Created macOS universal framework.
Breaking Changes
This release introduces several braking changes and requires familiarizing with the following chapters.
New signature of the on_layers event
The millicast::ViewerListener::on_layers
event has a new signature to accept an array of strings for the inactive
layers. The following code presents the current signature of the callback:
virtual void on_layers( const std::string& mid,
const std::vector<ViewerLayerData>& active_layers,
const std::vector<std::string>& inactive_layers) = 0;
This change is propagated to the iOS layer. The following example presents the current signature of the callback for the Objective C SDK:
(void) onLayers: (nonnull NSString*) mid activeLayers:(nonnull NSArray<MCLayerData*>*) activeLayers inactiveLayers:(nonnull NSArray<NSString*>*) inactiveLayers;
The Kotlin SDK is also impacted by this modification and requires applications to listen for the Subscriber's layers Flow:
subscriber.layers.collect { layers ->
// manage the layers object here
}
The following code presents the current signature for the SDK:
data class Layers(
val mid: String,
val activeLayers: Array<LayerData>,
val inactiveLayersEncodingIds: Array<String>
)
Modified values of the ViewerLayerData structure
Values of the millicast::ViewerLayerData
structure that may not be present for a layer, such as spatial ID or temporal ID, are now optional. The following example presents the new signature of the structure:
struct ViewerLayerData {
struct Resolution {
int width;
int height;
};
std::string encoding_id;
int bitrate = 0;
std::optional<int> temporal_layer_id;
std::optional<int> spatial_layer_id;
std::optional<Resolution> layer_resolution;
std::optional<int> max_temporal_layer_id;
std::optional<int> max_spatial_layer_id;
};
This change is propagated to the iOS layer. The current MCLayerData structure in the Objective C SDK is presented in the following example:
@interface MCLayerResolution : NSObject
@property int height;
@property int width;
@end
MILLICAST_API @interface MCLayerData : NSObject
@property (nonatomic, strong, nonnull) NSString* encodingId;
@property int bitrate;
@property(nonatomic, assign, nullable) NSNumber *spatialLayerId;
@property(nonatomic, assign, nullable) NSNumber *temporalLayerId;
@property(nonatomic, assign, nullable) NSNumber *maxTemporalLayerId;
@property(nonatomic, assign, nullable) NSNumber *maxSpatialLayerId;
@property(nonatomic, assign, nullable) MCLayerResolution* layerResolution;
@end
This change also impacts the Kotlin implementation. The following example presents the new signature of the structure:
data class LayerResolution(
val width: Int = 0,
val height: Int = 0
)
data class LayerData(
val encodingId: String = "",
val bitrate: Int = 0,
val temporalLayerId: Int? = null,
val spatialLayerId: Int? = null,
val maxSpatialLayerId: Int? = null,
val maxTemporalLayerId: Int? = null,
val resolution: LayerResolution? = null
)
Modified Kotlin implementation
In the Kotlin implementation, the getStats(boolean)
method is now removed in favor of enableStats(boolean)
, which emits reports asynchronously via the corresponding SharedFlow.
Using the Kotlin SDK to create a Publisher or Subscriber now requires calling the Core class implementation, as in the following example:
Core.createPublisher()
Core.createSubscriber()
Additionally, the SDK now provides an asynchronous implementation, so to consume the Subscriber and Publisher features, perform coroutines.
The Listener implementation is now removed and replaced with SharedFlow, which is now provided by both main classes. For the Subscriber class, several new SharedFlow events have been introduced:
- Subscriber#state: Provides information about the state of the subscriber.
- Subscriber#signalingError: Provides all propagated errors.
- Subscriber#rtcStatsReport: Provides WebRTC statistics when stats reporting is enabled. The statistics report provides the Stats object based on a Sealed class. Using a
when
statement helps find various statistics. - Subscriber#track: Provides all audio and video track events, including the track itself and its associated Media ID identifier.
- Subscriber#activity: Provides information about the active and inactive states of the subscriber's activity.
- Subscriber#layers: Corresponds to all layers events, providing information about the layers associated with the subscriber.
For more information on SharedFlow, see the following example:
data class SubscriberState(
val connectionState: ConnectionState = ConnectionState.Default,
val subscriptionState: SubscriptionState = SubscriptionState.Default,
val viewers: Int = 0
)
sealed class TrackHolder(
val mid: String?,
val track: Track
) {
class AudioTrackHolder(
mid: String?,
val audioTrack: AudioTrack
) : TrackHolder(mid, audioTrack)
class VideoTrackHolder(
mid: String?,
val videoTrack: VideoTrack
) : TrackHolder(mid, videoTrack)
}
sealed class ActivityStream {
data class Active(
val streamId: String,
val track: Array<String>,
val sourceId: String?
) : ActivityStream()
data class Inactive(
val streamId: String,
val sourceId: String?
) : ActivityStream()
}
data class Layers(
val mid: String,
val activeLayers: Array<LayerData>,
val inactiveLayersEncodingIds: Array<String>
)
Setting automatic reconnection
The auto_reconnect
property is no longer available in Publisher and Subscriber options. Use ConnectionOptions
to set the auto_reconnect
property, as in the following examples:
//file: millicast-sdk/client.h
struct MILLICAST_API ClientConnectionOptions {
bool auto_reconnect{true};
};
//file: MillicastSDK/client.h
MILLICAST_API @interface MCConnectionOptions: NSObject
@property(nonatomic, assign) BOOL autoReconnect;
@end
package com.millicast.clients;
public class ConnectionOptions {
public boolean autoReconnect;
}
2023-12-15 - 1.6.0
Features
- Introduced the ability to write macOS applications using the Objective-C/Swift API.
- Introduced a new priority parameter to support setting the priority of each feed when publishing multiple backup feeds.
- Introduced a new recording parameter that you can set to true to record published streams.
- Added support for SwiftUI view and two UIKit views to simplify displaying video tracks and enhance development flexibility.
- Added support for application-level screen sharing on iOS. The following code sample presents how you can use it:
import MillicastSDK import ReplayKit func exampleScreenShareFunc() async { let publisher = MCPublisher.create() let screenShareSource = MCAppShareSource(name: "example-screen-share-source", recorder: RPScreenRecorder.shared()) do { let (audioTrack, videoTrack) = try await screenShareSource.startCapture() if let audioTrack = audioTrack { publisher.add(audioTrack) } if let videoTrack = videoTrack { publisher.add(videoTrack) } // continue with the publisher setup (connection, publishing, etc.) } catch { // Handle error // for example // os_log(.error, log: log, "Could not start capture: %s", error.localizedDescription) } }
Fixes
Introduced general stability and performance improvements.
Deprecations
-
The
setOptions
method is deprecated and replaced with a newconnect
method from theConnectionOptions
class, which connects the SDK with the Millicast platform. Additionally, theautoReconnect
method is deprecated on iOS and desktop platforms. -
The
hardware_support
method is deprecated and no longer supported. -
The
CustomSource
class is deprecated and replaced withCustomVideoSource
andCustomAudioSource
on iOS and desktop platforms. -
The
enableSvcWithMode
anddisableSvc
methods are now deprecated and replaced withsvcMode
from theClientOptions
class. -
The
enableSimulcast
method is deprecated and replaced with thesimulcast
method fromClientOptions
.
2023-09-28 - 1.5.2
Features
Upgraded WebRTC version to 112.
Fixes
Refactored WebSocket timeout to prevent logging overload.
2023-07-04 - 1.5.1
Features
- Added an option to enable and disable bandwidth in OBS WebRTC and the Native SDK. This can be useful when publishing in suboptimal network conditions.
- Added automatic resumption of publishing and subscribing upon recovery from a network disruption.
- The client auto_reconnect option can now be set to false to disable automatic reconnection.
- The Publisher and subscriber listeners now have an onDisconnected callback and their onConnectionError callbacks now include an integer status in addition to the reason.
Fixes
- The onDisconnected event is now triggered much faster and more reliably.
- Fixed an iOS AVAudioEngine crash.
- Fixed an issue where Bluetooth headsets did not work on iPadOS/iOS 16.4.1.
- The Publisher sample application now uses the first listed audio/video device if unable to find the provided audio/video device name.
Known Issues
- When publishing in 4:4:4, the client sends 4:2:0 instead of 4:4:4.
2023-03-16 - 1.5.0
Features
- Added the ability to switch a video source when a stream is in progress.
- Added the ability to render VP9 with 4:4:4 chroma subsampling on Android.
- Added the NV12 video format as a VideoType.
- Upgraded libWebRTC to m108.
Fixes
- Fixed an issue related to a root certificate issue on Windows.
- Fixed an issue where audio did not play when streamed from an external source on iOS.
- Deprecated the possibility to set the maximum bitrate using the client. Instead, we introduced the ability to set the minimum and maximum bitrate using the options structure.
- Improved the stream statistics reporting.
2022-12-09 - 1.4.2
Deprecated APIs
Replaced the SetMaxBitrate API with settings for min, max, and start bitrates via publisher options.
Fixes
- Fixed an issue where a crash occurred after providing YUY2 frames.
- Fixed an issue where a crash occurred after enabling stats reporting.