H.264 video codec support using OpenH264 (http://www.openh264.org/) for encoding and FFmpeg (https://www.ffmpeg.org/) for decoding.

It works on all platforms except Android and iOS (FFmpeg limitation).

Implemented behind compile time flags, off by default.
The plan is to have it enabled in Chrome (see bug), but not in Chromium/webrtc by default.

Flags to turn it on:
- rtc_use_h264 = true
- ffmpeg_branding = "Chrome" (or other brand that includes H.264 decoder)

Tests using H264:
- video_loopback --codec=H264
- screenshare_loopback --codec=H264
- video_engine_tests (EndToEndTest.SendsAndReceivesH264)

NOTRY=True
BUG=500605, 468365
BUG=https://bugs.chromium.org/p/webrtc/issues/detail?id=5424

Review URL: https://codereview.webrtc.org/1306813009

Cr-Commit-Position: refs/heads/master@{#11390}
This commit is contained in:
hbos
2016-01-27 01:36:03 -08:00
committed by Commit bot
parent fab0a2886d
commit bab934bffe
24 changed files with 1053 additions and 32 deletions

View File

@ -225,8 +225,10 @@ bool VideoProcessorImpl::ProcessFrame(int frame_number) {
}
}
void VideoProcessorImpl::FrameEncoded(webrtc::VideoCodecType codec,
const EncodedImage& encoded_image) {
void VideoProcessorImpl::FrameEncoded(
webrtc::VideoCodecType codec,
const EncodedImage& encoded_image,
const webrtc::RTPFragmentationHeader* fragmentation) {
// Timestamp is frame number, so this gives us #dropped frames.
int num_dropped_from_prev_encode =
encoded_image._timeStamp - prev_time_stamp_ - 1;
@ -277,14 +279,18 @@ void VideoProcessorImpl::FrameEncoded(webrtc::VideoCodecType codec,
assert(false);
}
}
// Make a raw copy of the |encoded_image| buffer.
size_t copied_buffer_size = encoded_image._length +
EncodedImage::GetBufferPaddingBytes(codec);
rtc::scoped_ptr<uint8_t[]> copied_buffer(new uint8_t[copied_buffer_size]);
memcpy(copied_buffer.get(), encoded_image._buffer, encoded_image._length);
// The image to feed to the decoder.
EncodedImage copied_image;
memcpy(&copied_image, &encoded_image, sizeof(copied_image));
copied_image._size = copied_buffer_size;
copied_image._buffer = copied_buffer.get();
if (!exclude_this_frame) {
stat.packets_dropped =
packet_manipulator_->ManipulatePackets(&copied_image);
@ -415,14 +421,17 @@ int32_t VideoProcessorImpl::VideoProcessorEncodeCompleteCallback::Encoded(
const EncodedImage& encoded_image,
const webrtc::CodecSpecificInfo* codec_specific_info,
const webrtc::RTPFragmentationHeader* fragmentation) {
// Forward to parent class.
RTC_CHECK(codec_specific_info);
video_processor_->FrameEncoded(codec_specific_info->codecType,
encoded_image); // Forward to parent class.
encoded_image,
fragmentation);
return 0;
}
int32_t VideoProcessorImpl::VideoProcessorDecodeCompleteCallback::Decoded(
VideoFrame& image) {
video_processor_->FrameDecoded(image); // Forward to parent class.
// Forward to parent class.
video_processor_->FrameDecoded(image);
return 0;
}

View File

@ -173,7 +173,8 @@ class VideoProcessorImpl : public VideoProcessor {
private:
// Invoked by the callback when a frame has completed encoding.
void FrameEncoded(webrtc::VideoCodecType codec,
const webrtc::EncodedImage& encodedImage);
const webrtc::EncodedImage& encodedImage,
const webrtc::RTPFragmentationHeader* fragmentation);
// Invoked by the callback when a frame has completed decoding.
void FrameDecoded(const webrtc::VideoFrame& image);
// Used for getting a 32-bit integer representing time

View File

@ -15,9 +15,10 @@
#include "webrtc/modules/video_coding/include/video_codec_interface.h"
#include "webrtc/modules/video_coding/codecs/test/packet_manipulator.h"
#include "webrtc/modules/video_coding/codecs/test/videoprocessor.h"
#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
#include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h"
#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
#include "webrtc/modules/video_coding/include/video_coding.h"
#include "webrtc/test/testsupport/fileutils.h"
#include "webrtc/test/testsupport/frame_reader.h"
@ -150,7 +151,11 @@ class VideoProcessorIntegrationTest : public testing::Test {
virtual ~VideoProcessorIntegrationTest() {}
void SetUpCodecConfig() {
if (codec_type_ == kVideoCodecVP8) {
if (codec_type_ == kVideoCodecH264) {
encoder_ = H264Encoder::Create();
decoder_ = H264Decoder::Create();
VideoCodingModule::Codec(kVideoCodecH264, &codec_settings_);
} else if (codec_type_ == kVideoCodecVP8) {
encoder_ = VP8Encoder::Create();
decoder_ = VP8Decoder::Create();
VideoCodingModule::Codec(kVideoCodecVP8, &codec_settings_);
@ -184,6 +189,12 @@ class VideoProcessorIntegrationTest : public testing::Test {
// These features may be set depending on the test.
switch (config_.codec_settings->codecType) {
case kVideoCodecH264:
config_.codec_settings->codecSpecific.H264.frameDroppingOn =
frame_dropper_on_;
config_.codec_settings->codecSpecific.H264.keyFrameInterval =
kBaseKeyFrameInterval;
break;
case kVideoCodecVP8:
config_.codec_settings->codecSpecific.VP8.errorConcealmentOn =
error_concealment_on_;
@ -579,6 +590,37 @@ void SetRateControlMetrics(RateControlMetrics* rc_metrics,
rc_metrics[update_index].num_key_frames = num_key_frames;
}
#if defined(WEBRTC_VIDEOPROCESSOR_H264_TESTS)
// H264: Run with no packet loss and fixed bitrate. Quality should be very high.
// Note(hbos): The PacketManipulatorImpl code used to simulate packet loss in
// these unittests appears to drop "packets" in a way that is not compatible
// with H264. Therefore ProcessXPercentPacketLossH264, X != 0, unittests have
// not been added.
TEST_F(VideoProcessorIntegrationTest, Process0PercentPacketLossH264) {
// Bitrate and frame rate profile.
RateProfile rate_profile;
SetRateProfilePars(&rate_profile, 0, 500, 30, 0);
rate_profile.frame_index_rate_update[1] = kNbrFramesShort + 1;
rate_profile.num_frames = kNbrFramesShort;
// Codec/network settings.
CodecConfigPars process_settings;
SetCodecParameters(&process_settings, kVideoCodecH264, 0.0f, -1, 1, false,
false, true, false);
// Metrics for expected quality.
QualityMetrics quality_metrics;
SetQualityMetrics(&quality_metrics, 35.0, 25.0, 0.93, 0.70);
// Metrics for rate control.
RateControlMetrics rc_metrics[1];
SetRateControlMetrics(rc_metrics, 0, 2, 60, 20, 10, 20, 0, 1);
ProcessFramesAndVerify(quality_metrics,
rate_profile,
process_settings,
rc_metrics);
}
#endif // defined(WEBRTC_VIDEOPROCESSOR_H264_TESTS)
// VP9: Run with no packet loss and fixed bitrate. Quality should be very high.
// One key frame (first frame only) in sequence. Setting |key_frame_interval|
// to -1 below means no periodic key frames in test.