Skip to content

Add H.265 video codec support to WebRTC Android SDK #184

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: m137_release
Choose a base branch
from
Open
Show file tree
Hide file tree
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
4 changes: 3 additions & 1 deletion common_video/h264/sps_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,11 @@ std::optional<SpsParser::SpsState> SpsParser::ParseSpsUpToVui(
// to signify resolutions that aren't multiples of 16.
//
// pic_width_in_mbs_minus1: ue(v)
sps.width = 16 * (reader.ReadExponentialGolomb() + 1);
sps.pic_width_in_mbs_minus1 = reader.ReadExponentialGolomb();
sps.width = 16 * (sps.pic_width_in_mbs_minus1 + 1);
// pic_height_in_map_units_minus1: ue(v)
uint32_t pic_height_in_map_units_minus1 = reader.ReadExponentialGolomb();
sps.pic_height_in_map_units_minus1 = pic_height_in_map_units_minus1;
// frame_mbs_only_flag: u(1)
sps.frame_mbs_only_flag = reader.ReadBit();
if (!sps.frame_mbs_only_flag) {
Expand Down
2 changes: 2 additions & 0 deletions common_video/h264/sps_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class RTC_EXPORT SpsParser {
SpsState(const SpsState&);
~SpsState();

uint32_t pic_width_in_mbs_minus1 = 0;
uint32_t pic_height_in_map_units_minus1 = 0;
uint32_t width = 0;
uint32_t height = 0;
uint32_t delta_pic_order_always_zero_flag = 0;
Expand Down
45 changes: 45 additions & 0 deletions common_video/h265/h265_vps_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "common_video/h265/h265_vps_parser.h"

#include "common_video/h265/h265_common.h"
#include "common_video/h265/h265_sps_parser.h"
#include "rtc_base/bit_buffer.h"
#include "rtc_base/bitstream_reader.h"
#include "rtc_base/logging.h"
Expand Down Expand Up @@ -44,6 +45,50 @@ std::optional<H265VpsParser::VpsState> H265VpsParser::ParseInternal(
if (!reader.Ok()) {
return std::nullopt;
}
// vps_base_layer_internal_flag u(1)
reader.ConsumeBits(1);
// vps_base_layer_available_flag u(1)
reader.ConsumeBits(1);
// vps_max_layers_minus1 u(6)
vps.vps_max_sub_layers_minus1 = reader.ReadBits(6);

if (!reader.Ok() || (vps.vps_max_sub_layers_minus1 >= kMaxSubLayers)) {
return std::nullopt;
}

// vps_max_sub_layers_minus1 u(3)
reader.ConsumeBits(3);
// vps_temporal_id_nesting_flag u(1)
reader.ConsumeBits(1);
// vps_reserved_0xffff_16bits u(16)
reader.ConsumeBits(16);

auto profile_tier_level = H265SpsParser::ParseProfileTierLevel(true, vps.vps_max_sub_layers_minus1, reader);
if (!reader.Ok() || !profile_tier_level) {
return std::nullopt;
}

bool vps_sub_layer_ordering_info_present_flag = reader.Read<bool>();
for (uint32_t i = (vps_sub_layer_ordering_info_present_flag != 0) ? 0 : vps.vps_max_sub_layers_minus1; i <= vps.vps_max_sub_layers_minus1; i++) {
// vps_max_dec_pic_buffering_minus1[ i ]: ue(v)
reader.ReadExponentialGolomb();
// vps_max_num_reorder_pics[ i ]: ue(v)
vps.vps_max_num_reorder_pics[i] = reader.ReadExponentialGolomb();
if (!reader.Ok() || (i > 0 && vps.vps_max_num_reorder_pics[i] < vps.vps_max_num_reorder_pics[i - 1])) {
return std::nullopt;
}

// vps_max_latency_increase_plus1: ue(v)
reader.ReadExponentialGolomb();
}
if (!vps_sub_layer_ordering_info_present_flag) {
for (uint32_t i = 0; i < vps.vps_max_sub_layers_minus1; ++i) {
vps.vps_max_num_reorder_pics[i] = vps.vps_max_num_reorder_pics[vps.vps_max_sub_layers_minus1];
}
}
if (!reader.Ok() || !profile_tier_level) {
return std::nullopt;
}

return vps;
}
Expand Down
4 changes: 4 additions & 0 deletions common_video/h265/h265_vps_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,16 @@ namespace webrtc {
// A class for parsing out video parameter set (VPS) data from an H265 NALU.
class RTC_EXPORT H265VpsParser {
public:
static constexpr uint32_t kMaxSubLayers = 7;

// The parsed state of the VPS. Only some select values are stored.
// Add more as they are actually needed.
struct RTC_EXPORT VpsState {
VpsState();

uint32_t id = 0;
uint32_t vps_max_sub_layers_minus1 = 0;
uint32_t vps_max_num_reorder_pics[kMaxSubLayers] = {};
};

// Unpack RBSP and parse VPS state from the supplied buffer.
Expand Down
5 changes: 5 additions & 0 deletions sdk/android/api/org/webrtc/HardwareVideoEncoderFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ private boolean isHardwareSupportedInCurrentSdk(MediaCodecInfo info, VideoCodecM
case H264:
return isHardwareSupportedInCurrentSdkH264(info);
case H265:
return isHardwareSupportedInCurrentSdkH265(info);
case AV1:
return false;
}
Expand Down Expand Up @@ -230,6 +231,10 @@ private boolean isHardwareSupportedInCurrentSdkH264(MediaCodecInfo info) {
return name.startsWith(QCOM_PREFIX) || name.startsWith(EXYNOS_PREFIX);
}

private boolean isHardwareSupportedInCurrentSdkH265(MediaCodecInfo unusedInfo) {
return true;
}

private boolean isMediaCodecAllowed(MediaCodecInfo info) {
if (codecAllowedPredicate == null) {
return true;
Expand Down
2 changes: 2 additions & 0 deletions sdk/android/api/org/webrtc/VideoEncoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ public class CodecSpecificInfoVP9 extends CodecSpecificInfo {}

public class CodecSpecificInfoH264 extends CodecSpecificInfo {}

public class CodecSpecificInfoH265 extends CodecSpecificInfo {}

public class CodecSpecificInfoAV1 extends CodecSpecificInfo {}

/**
Expand Down
4 changes: 4 additions & 0 deletions sdk/android/src/java/org/webrtc/HardwareVideoEncoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,10 @@ public ScalingSettings getScalingSettings() {
final int kLowH264QpThreshold = 24;
final int kHighH264QpThreshold = 37;
return new ScalingSettings(kLowH264QpThreshold, kHighH264QpThreshold);
} else if (codecType == VideoCodecMimeType.H265) {
final int kLowH265QpThreshold = 24;
final int kHighH265QpThreshold = 37;
return new ScalingSettings(kLowH265QpThreshold, kHighH265QpThreshold);
}
}
return ScalingSettings.OFF;
Expand Down
2 changes: 1 addition & 1 deletion webrtc.gni
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ declare_args() {
if (build_with_chromium) {
rtc_use_h265 = enable_hevc_parser_and_hw_decoder
} else {
rtc_use_h265 = proprietary_codecs
rtc_use_h265 = true
}

# Enable this flag to make webrtc::Mutex be implemented by absl::Mutex.
Expand Down