Skip to content
This repository has been archived by the owner on Oct 25, 2024. It is now read-only.

Commit

Permalink
Rebase all changes for HEVC to M70
Browse files Browse the repository at this point in the history
  • Loading branch information
taste1981 authored and jianjunz committed Aug 19, 2019
1 parent 00de26d commit 6c5fb02
Show file tree
Hide file tree
Showing 41 changed files with 2,421 additions and 17 deletions.
1 change: 1 addition & 0 deletions api/video/builtin_video_bitrate_allocator_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class BuiltinVideoBitrateAllocatorFactory
case kVideoCodecVP9:
rate_allocator.reset(new SvcRateAllocator(codec));
break;
// TODO: add an allocator here for H.265
default:
rate_allocator.reset(new DefaultVideoBitrateAllocator(codec));
}
Expand Down
3 changes: 3 additions & 0 deletions api/video/video_codec_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ enum VideoCodecType {
kVideoCodecVP8,
kVideoCodecVP9,
kVideoCodecH264,
#ifndef DISABLE_H265
kVideoCodecH265,
#endif
kVideoCodecMultiplex,
};

Expand Down
36 changes: 36 additions & 0 deletions api/video_codecs/video_codec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ bool VideoCodecH264::operator==(const VideoCodecH264& other) const {
numberOfTemporalLayers == other.numberOfTemporalLayers);
}

#ifndef DISABLE_H265
bool VideoCodecH265::operator==(const VideoCodecH265& other) const {
return (frameDroppingOn == other.frameDroppingOn &&
keyFrameInterval == other.keyFrameInterval &&
vpsLen == other.vpsLen && spsLen == other.spsLen &&
ppsLen == other.ppsLen &&
(spsLen == 0 || memcmp(spsData, other.spsData, spsLen) == 0) &&
(ppsLen == 0 || memcmp(ppsData, other.ppsData, ppsLen) == 0));
}
#endif

bool SpatialLayer::operator==(const SpatialLayer& other) const {
return (width == other.width && height == other.height &&
numberOfTemporalLayers == other.numberOfTemporalLayers &&
Expand Down Expand Up @@ -103,9 +114,25 @@ const VideoCodecH264& VideoCodec::H264() const {
return codec_specific_.H264;
}

#ifndef DISABLE_H265
VideoCodecH265* VideoCodec::H265() {
RTC_DCHECK_EQ(codecType, kVideoCodecH265);
return &codec_specific_.H265;
}

const VideoCodecH265& VideoCodec::H265() const {
RTC_DCHECK_EQ(codecType, kVideoCodecH265);
return codec_specific_.H265;
}
#endif

static const char* kPayloadNameVp8 = "VP8";
static const char* kPayloadNameVp9 = "VP9";
static const char* kPayloadNameH264 = "H264";
#ifndef DISABLE_H265
static const char* kPayloadNameH265 = "H265";
#endif
static const char* kPayloadNameI420 = "I420";
static const char* kPayloadNameGeneric = "Generic";
static const char* kPayloadNameMultiplex = "Multiplex";

Expand All @@ -117,6 +144,10 @@ const char* CodecTypeToPayloadString(VideoCodecType type) {
return kPayloadNameVp9;
case kVideoCodecH264:
return kPayloadNameH264;
#ifndef DISABLE_H265
case kVideoCodecH265:
return kPayloadNameH265;
#endif
// Other codecs default to generic.
default:
return kPayloadNameGeneric;
Expand All @@ -132,6 +163,11 @@ VideoCodecType PayloadStringToCodecType(const std::string& name) {
return kVideoCodecH264;
if (absl::EqualsIgnoreCase(name, kPayloadNameMultiplex))
return kVideoCodecMultiplex;
#ifndef DISABLE_H265
if (absl::EqualsIgnoreCase(name, kPayloadNameH265))
return kVideoCodecH265;
#endif
return kVideoCodecMultiplex;
return kVideoCodecGeneric;
}

Expand Down
24 changes: 24 additions & 0 deletions api/video_codecs/video_codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,23 @@ struct VideoCodecH264 {
uint8_t numberOfTemporalLayers;
};

#ifndef DISABLE_H265
struct VideoCodecH265 {
bool operator==(const VideoCodecH265& other) const;
bool operator!=(const VideoCodecH265& other) const {
return !(*this == other);
}
bool frameDroppingOn;
int keyFrameInterval;
const uint8_t* vpsData;
size_t vpsLen;
const uint8_t* spsData;
size_t spsLen;
const uint8_t* ppsData;
size_t ppsLen;
};
#endif

// Translates from name of codec to codec type and vice versa.
RTC_EXPORT const char* CodecTypeToPayloadString(VideoCodecType type);
RTC_EXPORT VideoCodecType PayloadStringToCodecType(const std::string& name);
Expand All @@ -90,6 +107,9 @@ union VideoCodecUnion {
VideoCodecVP8 VP8;
VideoCodecVP9 VP9;
VideoCodecH264 H264;
#ifndef DISABLE_H265
VideoCodecH265 H265;
#endif
};

enum class VideoCodecMode { kRealtimeVideo, kScreensharing };
Expand Down Expand Up @@ -151,6 +171,10 @@ class RTC_EXPORT VideoCodec {
const VideoCodecVP9& VP9() const;
VideoCodecH264* H264();
const VideoCodecH264& H264() const;
#ifndef DISABLE_H265
VideoCodecH265* H265();
const VideoCodecH265& H265() const;
#endif

private:
// TODO(hta): Consider replacing the union with a pointer type.
Expand Down
17 changes: 17 additions & 0 deletions api/video_codecs/video_encoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,23 @@ VideoCodecH264 VideoEncoder::GetDefaultH264Settings() {
return h264_settings;
}

#ifndef DISABLE_H265
VideoCodecH265 VideoEncoder::GetDefaultH265Settings() {
VideoCodecH265 h265_settings;
memset(&h265_settings, 0, sizeof(h265_settings));

// h265_settings.profile = kProfileBase;
h265_settings.frameDroppingOn = true;
h265_settings.keyFrameInterval = 3000;
h265_settings.spsData = nullptr;
h265_settings.spsLen = 0;
h265_settings.ppsData = nullptr;
h265_settings.ppsLen = 0;

return h265_settings;
}
#endif

VideoEncoder::ScalingSettings::ScalingSettings() = default;

VideoEncoder::ScalingSettings::ScalingSettings(KOff) : ScalingSettings() {}
Expand Down
4 changes: 3 additions & 1 deletion api/video_codecs/video_encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,9 @@ class RTC_EXPORT VideoEncoder {
static VideoCodecVP8 GetDefaultVp8Settings();
static VideoCodecVP9 GetDefaultVp9Settings();
static VideoCodecH264 GetDefaultH264Settings();

#ifndef DISABLE_H265
static VideoCodecH265 GetDefaultH265Settings();
#endif
virtual ~VideoEncoder() {}

// Initialize the encoder with the information from the codecSettings
Expand Down
11 changes: 11 additions & 0 deletions api/video_codecs/video_encoder_config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ void VideoEncoderConfig::EncoderSpecificSettings::FillEncoderSpecificSettings(
FillVideoCodecVp8(codec->VP8());
} else if (codec->codecType == kVideoCodecVP9) {
FillVideoCodecVp9(codec->VP9());
#ifndef DISABLE_H265
} else if (codec->codecType == kVideoCodecH265) {
FillVideoCodecH265(codec->H265());
#endif
} else {
RTC_NOTREACHED() << "Encoder specifics set/used for unknown codec type.";
}
Expand All @@ -102,6 +106,13 @@ void VideoEncoderConfig::EncoderSpecificSettings::FillVideoCodecH264(
RTC_NOTREACHED();
}

#ifndef DISABLE_H265
void VideoEncoderConfig::EncoderSpecificSettings::FillVideoCodecH265(
VideoCodecH265* h265_settings) const {
RTC_NOTREACHED();
}
#endif

void VideoEncoderConfig::EncoderSpecificSettings::FillVideoCodecVp8(
VideoCodecVP8* vp8_settings) const {
RTC_NOTREACHED();
Expand Down
14 changes: 13 additions & 1 deletion api/video_codecs/video_encoder_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ class VideoEncoderConfig {
virtual void FillVideoCodecVp8(VideoCodecVP8* vp8_settings) const;
virtual void FillVideoCodecVp9(VideoCodecVP9* vp9_settings) const;
virtual void FillVideoCodecH264(VideoCodecH264* h264_settings) const;

#ifndef DISABLE_H265
virtual void FillVideoCodecH265(VideoCodecH265* h265_settings) const;
#endif
private:
~EncoderSpecificSettings() override {}
friend class VideoEncoderConfig;
Expand All @@ -79,6 +81,16 @@ class VideoEncoderConfig {
VideoCodecH264 specifics_;
};

#ifndef DISABLE_H265
class H265EncoderSpecificSettings : public EncoderSpecificSettings {
public:
explicit H265EncoderSpecificSettings(const VideoCodecH265& specifics);
void FillVideoCodecH265(VideoCodecH265* h265_settings) const override;

private:
VideoCodecH264 specifics_;
};
#endif
class Vp8EncoderSpecificSettings : public EncoderSpecificSettings {
public:
explicit Vp8EncoderSpecificSettings(const VideoCodecVP8& specifics);
Expand Down
13 changes: 13 additions & 0 deletions common_video/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@ rtc_static_library("common_video") {
"video_render_frames.h",
]

if (rtc_use_h265) {
sources += [
"h265/h265_common.cc",
"h265/h265_common.h",
"h265/h265_pps_parser.cc",
"h265/h265_pps_parser.h",
"h265/h265_sps_parser.cc",
"h265/h265_sps_parser.h",
"h265/h265_vps_parser.cc",
"h265/h265_vps_parser.h",
]
}

deps = [
"../api:scoped_refptr",
"../api/task_queue",
Expand Down
110 changes: 110 additions & 0 deletions common_video/h265/h265_common.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/

#include "common_video/h265/h265_common.h"

namespace webrtc {
namespace H265 {

const uint8_t kNaluTypeMask = 0x7E;

std::vector<NaluIndex> FindNaluIndices(const uint8_t* buffer,
size_t buffer_size) {
// This is sorta like Boyer-Moore, but with only the first optimization step:
// given a 3-byte sequence we're looking at, if the 3rd byte isn't 1 or 0,
// skip ahead to the next 3-byte sequence. 0s and 1s are relatively rare, so
// this will skip the majority of reads/checks.
std::vector<NaluIndex> sequences;
if (buffer_size < kNaluShortStartSequenceSize)
return sequences;

const size_t end = buffer_size - kNaluShortStartSequenceSize;
for (size_t i = 0; i < end;) {
if (buffer[i + 2] > 1) {
i += 3;
} else if (buffer[i + 2] == 1 && buffer[i + 1] == 0 && buffer[i] == 0) {
// We found a start sequence, now check if it was a 3 of 4 byte one.
NaluIndex index = {i, i + 3, 0};
if (index.start_offset > 0 && buffer[index.start_offset - 1] == 0)
--index.start_offset;

// Update length of previous entry.
auto it = sequences.rbegin();
if (it != sequences.rend())
it->payload_size = index.start_offset - it->payload_start_offset;

sequences.push_back(index);

i += 3;
} else {
++i;
}
}

// Update length of last entry, if any.
auto it = sequences.rbegin();
if (it != sequences.rend())
it->payload_size = buffer_size - it->payload_start_offset;

return sequences;
}

NaluType ParseNaluType(uint8_t data) {
return static_cast<NaluType>((data & kNaluTypeMask) >> 1);
}

std::vector<uint8_t> ParseRbsp(const uint8_t* data, size_t length) {
std::vector<uint8_t> out;
out.reserve(length);

for (size_t i = 0; i < length;) {
// Be careful about over/underflow here. byte_length_ - 3 can underflow, and
// i + 3 can overflow, but byte_length_ - i can't, because i < byte_length_
// above, and that expression will produce the number of bytes left in
// the stream including the byte at i.
if (length - i >= 3 && !data[i] && !data[i + 1] && data[i + 2] == 3) {
// Two rbsp bytes.
out.push_back(data[i++]);
out.push_back(data[i++]);
// Skip the emulation byte.
i++;
} else {
// Single rbsp byte.
out.push_back(data[i++]);
}
}
return out;
}

void WriteRbsp(const uint8_t* bytes, size_t length, rtc::Buffer* destination) {
static const uint8_t kZerosInStartSequence = 2;
static const uint8_t kEmulationByte = 0x03u;
size_t num_consecutive_zeros = 0;
destination->EnsureCapacity(destination->size() + length);

for (size_t i = 0; i < length; ++i) {
uint8_t byte = bytes[i];
if (byte <= kEmulationByte &&
num_consecutive_zeros >= kZerosInStartSequence) {
// Need to escape.
destination->AppendData(kEmulationByte);
num_consecutive_zeros = 0;
}
destination->AppendData(byte);
if (byte == 0) {
++num_consecutive_zeros;
} else {
num_consecutive_zeros = 0;
}
}
}

} // namespace H265
} // namespace webrtc
Loading

0 comments on commit 6c5fb02

Please sign in to comment.