Prepare iOS H264 HW encoder for High Profile
BUG=webrtc:6337 Review-Url: https://codereview.webrtc.org/2484493002 Cr-Commit-Position: refs/heads/master@{#15091}
This commit is contained in:
parent
4aecc5885a
commit
5d54e185d5
@ -16,6 +16,7 @@
|
||||
#include "webrtc/common_video/h264/h264_bitstream_parser.h"
|
||||
#include "webrtc/common_video/include/bitrate_adjuster.h"
|
||||
#include "webrtc/common_video/rotation.h"
|
||||
#include "webrtc/media/base/codec.h"
|
||||
#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
|
||||
#include "webrtc/modules/video_coding/utility/quality_scaler.h"
|
||||
|
||||
@ -31,7 +32,7 @@ namespace webrtc {
|
||||
|
||||
class H264VideoToolboxEncoder : public H264Encoder {
|
||||
public:
|
||||
H264VideoToolboxEncoder();
|
||||
explicit H264VideoToolboxEncoder(const cricket::VideoCodec& codec);
|
||||
|
||||
~H264VideoToolboxEncoder() override;
|
||||
|
||||
@ -82,6 +83,7 @@ class H264VideoToolboxEncoder : public H264Encoder {
|
||||
uint32_t encoder_bitrate_bps_;
|
||||
int32_t width_;
|
||||
int32_t height_;
|
||||
const CFStringRef profile_;
|
||||
|
||||
rtc::CriticalSection quality_scaler_crit_;
|
||||
QualityScaler quality_scaler_ GUARDED_BY(quality_scaler_crit_);
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
#include "libyuv/convert_from.h"
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/common_video/h264/profile_level_id.h"
|
||||
#include "webrtc/common_video/include/corevideo_frame_buffer.h"
|
||||
#include "webrtc/sdk/objc/Framework/Classes/h264_video_toolbox_nalu.h"
|
||||
#include "webrtc/system_wrappers/include/clock.h"
|
||||
@ -224,6 +225,112 @@ void VTCompressionOutputCallback(void* encoder,
|
||||
encode_params->rotation);
|
||||
}
|
||||
|
||||
// Extract VideoToolbox profile out of the cricket::VideoCodec. If there is no
|
||||
// specific VideoToolbox profile for the specified level, AutoLevel will be
|
||||
// returned. The user must initialize the encoder with a resolution and
|
||||
// framerate conforming to the selected H264 level regardless.
|
||||
CFStringRef ExtractProfile(const cricket::VideoCodec& codec) {
|
||||
const rtc::Optional<webrtc::H264::ProfileLevelId> profile_level_id =
|
||||
webrtc::H264::ParseSdpProfileLevelId(codec.params);
|
||||
RTC_DCHECK(profile_level_id);
|
||||
switch (profile_level_id->profile) {
|
||||
case webrtc::H264::kProfileConstrainedBaseline:
|
||||
case webrtc::H264::kProfileBaseline:
|
||||
switch (profile_level_id->level) {
|
||||
case webrtc::H264::kLevel3:
|
||||
return kVTProfileLevel_H264_Baseline_3_0;
|
||||
case webrtc::H264::kLevel3_1:
|
||||
return kVTProfileLevel_H264_Baseline_3_1;
|
||||
case webrtc::H264::kLevel3_2:
|
||||
return kVTProfileLevel_H264_Baseline_3_2;
|
||||
case webrtc::H264::kLevel4:
|
||||
return kVTProfileLevel_H264_Baseline_4_0;
|
||||
case webrtc::H264::kLevel4_1:
|
||||
return kVTProfileLevel_H264_Baseline_4_1;
|
||||
case webrtc::H264::kLevel4_2:
|
||||
return kVTProfileLevel_H264_Baseline_4_2;
|
||||
case webrtc::H264::kLevel5:
|
||||
return kVTProfileLevel_H264_Baseline_5_0;
|
||||
case webrtc::H264::kLevel5_1:
|
||||
return kVTProfileLevel_H264_Baseline_5_1;
|
||||
case webrtc::H264::kLevel5_2:
|
||||
return kVTProfileLevel_H264_Baseline_5_2;
|
||||
case webrtc::H264::kLevel1:
|
||||
case webrtc::H264::kLevel1_b:
|
||||
case webrtc::H264::kLevel1_1:
|
||||
case webrtc::H264::kLevel1_2:
|
||||
case webrtc::H264::kLevel1_3:
|
||||
case webrtc::H264::kLevel2:
|
||||
case webrtc::H264::kLevel2_1:
|
||||
case webrtc::H264::kLevel2_2:
|
||||
return kVTProfileLevel_H264_Baseline_AutoLevel;
|
||||
}
|
||||
|
||||
case webrtc::H264::kProfileMain:
|
||||
switch (profile_level_id->level) {
|
||||
case webrtc::H264::kLevel3:
|
||||
return kVTProfileLevel_H264_Main_3_0;
|
||||
case webrtc::H264::kLevel3_1:
|
||||
return kVTProfileLevel_H264_Main_3_1;
|
||||
case webrtc::H264::kLevel3_2:
|
||||
return kVTProfileLevel_H264_Main_3_2;
|
||||
case webrtc::H264::kLevel4:
|
||||
return kVTProfileLevel_H264_Main_4_0;
|
||||
case webrtc::H264::kLevel4_1:
|
||||
return kVTProfileLevel_H264_Main_4_1;
|
||||
case webrtc::H264::kLevel4_2:
|
||||
return kVTProfileLevel_H264_Main_4_2;
|
||||
case webrtc::H264::kLevel5:
|
||||
return kVTProfileLevel_H264_Main_5_0;
|
||||
case webrtc::H264::kLevel5_1:
|
||||
return kVTProfileLevel_H264_Main_5_1;
|
||||
case webrtc::H264::kLevel5_2:
|
||||
return kVTProfileLevel_H264_Main_5_2;
|
||||
case webrtc::H264::kLevel1:
|
||||
case webrtc::H264::kLevel1_b:
|
||||
case webrtc::H264::kLevel1_1:
|
||||
case webrtc::H264::kLevel1_2:
|
||||
case webrtc::H264::kLevel1_3:
|
||||
case webrtc::H264::kLevel2:
|
||||
case webrtc::H264::kLevel2_1:
|
||||
case webrtc::H264::kLevel2_2:
|
||||
return kVTProfileLevel_H264_Main_AutoLevel;
|
||||
}
|
||||
|
||||
case webrtc::H264::kProfileConstrainedHigh:
|
||||
case webrtc::H264::kProfileHigh:
|
||||
switch (profile_level_id->level) {
|
||||
case webrtc::H264::kLevel3:
|
||||
return kVTProfileLevel_H264_High_3_0;
|
||||
case webrtc::H264::kLevel3_1:
|
||||
return kVTProfileLevel_H264_High_3_1;
|
||||
case webrtc::H264::kLevel3_2:
|
||||
return kVTProfileLevel_H264_High_3_2;
|
||||
case webrtc::H264::kLevel4:
|
||||
return kVTProfileLevel_H264_High_4_0;
|
||||
case webrtc::H264::kLevel4_1:
|
||||
return kVTProfileLevel_H264_High_4_1;
|
||||
case webrtc::H264::kLevel4_2:
|
||||
return kVTProfileLevel_H264_High_4_2;
|
||||
case webrtc::H264::kLevel5:
|
||||
return kVTProfileLevel_H264_High_5_0;
|
||||
case webrtc::H264::kLevel5_1:
|
||||
return kVTProfileLevel_H264_High_5_1;
|
||||
case webrtc::H264::kLevel5_2:
|
||||
return kVTProfileLevel_H264_High_5_2;
|
||||
case webrtc::H264::kLevel1:
|
||||
case webrtc::H264::kLevel1_b:
|
||||
case webrtc::H264::kLevel1_1:
|
||||
case webrtc::H264::kLevel1_2:
|
||||
case webrtc::H264::kLevel1_3:
|
||||
case webrtc::H264::kLevel2:
|
||||
case webrtc::H264::kLevel2_1:
|
||||
case webrtc::H264::kLevel2_2:
|
||||
return kVTProfileLevel_H264_High_AutoLevel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
namespace webrtc {
|
||||
@ -235,10 +342,13 @@ namespace webrtc {
|
||||
// drastically reduced bitrate, so we want to avoid that. In steady state
|
||||
// conditions, 0.95 seems to give us better overall bitrate over long periods
|
||||
// of time.
|
||||
H264VideoToolboxEncoder::H264VideoToolboxEncoder()
|
||||
H264VideoToolboxEncoder::H264VideoToolboxEncoder(
|
||||
const cricket::VideoCodec& codec)
|
||||
: callback_(nullptr),
|
||||
compression_session_(nullptr),
|
||||
bitrate_adjuster_(Clock::GetRealTimeClock(), .5, .95) {
|
||||
bitrate_adjuster_(Clock::GetRealTimeClock(), .5, .95),
|
||||
profile_(internal::ExtractProfile(codec)) {
|
||||
LOG(LS_INFO) << "Using profile " << internal::CFStringToString(profile_);
|
||||
}
|
||||
|
||||
H264VideoToolboxEncoder::~H264VideoToolboxEncoder() {
|
||||
@ -496,7 +606,7 @@ void H264VideoToolboxEncoder::ConfigureCompressionSession() {
|
||||
kVTCompressionPropertyKey_RealTime, true);
|
||||
internal::SetVTSessionProperty(compression_session_,
|
||||
kVTCompressionPropertyKey_ProfileLevel,
|
||||
kVTProfileLevel_H264_Baseline_AutoLevel);
|
||||
profile_);
|
||||
internal::SetVTSessionProperty(compression_session_,
|
||||
kVTCompressionPropertyKey_AllowFrameReordering,
|
||||
false);
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include "webrtc/sdk/objc/Framework/Classes/videotoolboxvideocodecfactory.h"
|
||||
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/common_video/h264/profile_level_id.h"
|
||||
#include "webrtc/media/base/codec.h"
|
||||
#if defined(WEBRTC_IOS)
|
||||
#include "webrtc/sdk/objc/Framework/Classes/h264_video_toolbox_encoder.h"
|
||||
@ -38,7 +39,19 @@ namespace webrtc {
|
||||
VideoToolboxVideoEncoderFactory::VideoToolboxVideoEncoderFactory() {
|
||||
// Hardware H264 encoding only supported on iOS for now.
|
||||
#if defined(WEBRTC_IOS)
|
||||
supported_codecs_.push_back(cricket::VideoCodec(cricket::kH264CodecName));
|
||||
// TODO(magjed): Push Constrained High profile as well when negotiation is
|
||||
// ready, http://crbug/webrtc/6337.
|
||||
cricket::VideoCodec constrained_baseline(cricket::kH264CodecName);
|
||||
// TODO(magjed): Enumerate actual level instead of using hardcoded level 3.1.
|
||||
// Level 3.1 is 1280x720@30fps which is enough for now.
|
||||
const H264::ProfileLevelId constrained_baseline_profile(
|
||||
H264::kProfileConstrainedBaseline, H264::kLevel3_1);
|
||||
constrained_baseline.SetParam(
|
||||
cricket::kH264FmtpProfileLevelId,
|
||||
*H264::ProfileLevelIdToString(constrained_baseline_profile));
|
||||
constrained_baseline.SetParam(cricket::kH264FmtpLevelAsymmetryAllowed, "1");
|
||||
constrained_baseline.SetParam(cricket::kH264FmtpPacketizationMode, "1");
|
||||
supported_codecs_.push_back(constrained_baseline);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -49,7 +62,7 @@ VideoEncoder* VideoToolboxVideoEncoderFactory::CreateVideoEncoder(
|
||||
#if defined(WEBRTC_IOS)
|
||||
if (FindMatchingCodec(supported_codecs_, codec)) {
|
||||
LOG(LS_INFO) << "Creating HW encoder for " << codec.name;
|
||||
return new H264VideoToolboxEncoder();
|
||||
return new H264VideoToolboxEncoder(codec);
|
||||
}
|
||||
#endif
|
||||
LOG(LS_INFO) << "No HW encoder found for codec " << codec.name;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user