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:
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
Reference in New Issue
Block a user