summaryrefslogtreecommitdiff
path: root/media/webrtc/webrtcvideoengine2.cc
diff options
context:
space:
mode:
Diffstat (limited to 'media/webrtc/webrtcvideoengine2.cc')
-rw-r--r--media/webrtc/webrtcvideoengine2.cc236
1 files changed, 127 insertions, 109 deletions
diff --git a/media/webrtc/webrtcvideoengine2.cc b/media/webrtc/webrtcvideoengine2.cc
index ea53596..26e3079 100644
--- a/media/webrtc/webrtcvideoengine2.cc
+++ b/media/webrtc/webrtcvideoengine2.cc
@@ -42,8 +42,7 @@
#include "webrtc/base/logging.h"
#include "webrtc/base/stringutils.h"
#include "webrtc/call.h"
-// TODO(pbos): Move codecs out of modules (webrtc:3070).
-#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
+#include "webrtc/video_encoder.h"
#define UNIMPLEMENTED \
LOG(LS_ERROR) << "Call to unimplemented function " << __FUNCTION__; \
@@ -55,6 +54,8 @@ namespace cricket {
// duration hasn't been implemented.
static const int kNackHistoryMs = 1000;
+static const int kDefaultQpMax = 56;
+
static const int kDefaultRtcpReceiverReportSsrc = 1;
struct VideoCodecPref {
@@ -187,7 +188,7 @@ std::vector<webrtc::VideoStream> WebRtcVideoEncoderFactory2::CreateVideoStreams(
stream.min_bitrate_bps = min_bitrate * 1000;
stream.target_bitrate_bps = stream.max_bitrate_bps = max_bitrate * 1000;
- int max_qp = 56;
+ int max_qp = kDefaultQpMax;
codec.GetParam(kCodecParamMaxQuantization, &max_qp);
stream.max_qp = max_qp;
std::vector<webrtc::VideoStream> streams;
@@ -200,7 +201,7 @@ webrtc::VideoEncoder* WebRtcVideoEncoderFactory2::CreateVideoEncoder(
const VideoOptions& options) {
assert(SupportsCodec(codec));
if (_stricmp(codec.name.c_str(), kVp8CodecName) == 0) {
- return webrtc::VP8Encoder::Create();
+ return webrtc::VideoEncoder::Create(webrtc::VideoEncoder::kVp8);
}
// This shouldn't happen, we should be able to create encoders for all codecs
// we support.
@@ -213,14 +214,9 @@ void* WebRtcVideoEncoderFactory2::CreateVideoEncoderSettings(
const VideoOptions& options) {
assert(SupportsCodec(codec));
if (_stricmp(codec.name.c_str(), kVp8CodecName) == 0) {
- webrtc::VideoCodecVP8* settings = new webrtc::VideoCodecVP8();
- settings->resilience = webrtc::kResilientStream;
- settings->numberOfTemporalLayers = 1;
+ webrtc::VideoCodecVP8* settings = new webrtc::VideoCodecVP8(
+ webrtc::VideoEncoder::GetDefaultVp8Settings());
options.video_noise_reduction.Get(&settings->denoisingOn);
- settings->errorConcealmentOn = false;
- settings->automaticResizeOn = false;
- settings->frameDroppingOn = true;
- settings->keyFrameInterval = 3000;
return settings;
}
return NULL;
@@ -233,13 +229,9 @@ void WebRtcVideoEncoderFactory2::DestroyVideoEncoderSettings(
if (encoder_settings == NULL) {
return;
}
-
if (_stricmp(codec.name.c_str(), kVp8CodecName) == 0) {
delete reinterpret_cast<webrtc::VideoCodecVP8*>(encoder_settings);
- return;
}
- // We should be able to destroy all encoder settings we've allocated.
- assert(false);
}
bool WebRtcVideoEncoderFactory2::SupportsCodec(const VideoCodec& codec) {
@@ -283,37 +275,19 @@ void DefaultUnsignalledSsrcHandler::SetDefaultRenderer(
}
WebRtcVideoEngine2::WebRtcVideoEngine2()
- : default_codec_format_(kDefaultVideoCodecPref.width,
- kDefaultVideoCodecPref.height,
- FPS_TO_INTERVAL(kDefaultFramerate),
- FOURCC_ANY) {
- // Construct without a factory or voice engine.
- Construct(NULL, NULL, new rtc::CpuMonitor(NULL));
-}
-
-WebRtcVideoEngine2::WebRtcVideoEngine2(
- WebRtcVideoChannelFactory* channel_factory)
- : default_codec_format_(kDefaultVideoCodecPref.width,
+ : worker_thread_(NULL),
+ voice_engine_(NULL),
+ video_codecs_(DefaultVideoCodecs()),
+ default_codec_format_(kDefaultVideoCodecPref.width,
kDefaultVideoCodecPref.height,
FPS_TO_INTERVAL(kDefaultFramerate),
- FOURCC_ANY) {
- // Construct without a voice engine.
- Construct(channel_factory, NULL, new rtc::CpuMonitor(NULL));
-}
-
-void WebRtcVideoEngine2::Construct(WebRtcVideoChannelFactory* channel_factory,
- WebRtcVoiceEngine* voice_engine,
- rtc::CpuMonitor* cpu_monitor) {
- LOG(LS_INFO) << "WebRtcVideoEngine2::WebRtcVideoEngine2";
- worker_thread_ = NULL;
- voice_engine_ = voice_engine;
- initialized_ = false;
- capture_started_ = false;
- cpu_monitor_.reset(cpu_monitor);
- channel_factory_ = channel_factory;
-
- video_codecs_ = DefaultVideoCodecs();
-
+ FOURCC_ANY),
+ initialized_(false),
+ cpu_monitor_(new rtc::CpuMonitor(NULL)),
+ channel_factory_(NULL),
+ external_decoder_factory_(NULL),
+ external_encoder_factory_(NULL) {
+ LOG(LS_INFO) << "WebRtcVideoEngine2::WebRtcVideoEngine2()";
rtp_header_extensions_.push_back(
RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension,
kRtpTimestampOffsetHeaderExtensionDefaultId));
@@ -322,6 +296,11 @@ void WebRtcVideoEngine2::Construct(WebRtcVideoChannelFactory* channel_factory,
kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
}
+void WebRtcVideoEngine2::SetChannelFactory(
+ WebRtcVideoChannelFactory* channel_factory) {
+ channel_factory_ = channel_factory;
+}
+
WebRtcVideoEngine2::~WebRtcVideoEngine2() {
LOG(LS_INFO) << "WebRtcVideoEngine2::~WebRtcVideoEngine2";
@@ -355,14 +334,6 @@ void WebRtcVideoEngine2::Terminate() {
int WebRtcVideoEngine2::GetCapabilities() { return VIDEO_RECV | VIDEO_SEND; }
-bool WebRtcVideoEngine2::SetOptions(const VideoOptions& options) {
- // TODO(pbos): Do we need this? This is a no-op in the existing
- // WebRtcVideoEngine implementation.
- LOG(LS_VERBOSE) << "SetOptions: " << options.ToString();
- // options_ = options;
- return true;
-}
-
bool WebRtcVideoEngine2::SetDefaultEncoderConfig(
const VideoEncoderConfig& config) {
const VideoCodec& codec = config.max_codec;
@@ -424,14 +395,32 @@ void WebRtcVideoEngine2::SetLogging(int min_sev, const char* filter) {
}
}
-bool WebRtcVideoEngine2::EnableTimedRender() {
- // TODO(pbos): Figure out whether this can be removed.
- return true;
+void WebRtcVideoEngine2::SetExternalDecoderFactory(
+ WebRtcVideoDecoderFactory* decoder_factory) {
+ external_decoder_factory_ = decoder_factory;
}
-bool WebRtcVideoEngine2::SetLocalRenderer(VideoRenderer* renderer) {
- // TODO(pbos): Implement or remove. Unclear which stream should be rendered
- // locally even.
+void WebRtcVideoEngine2::SetExternalEncoderFactory(
+ WebRtcVideoEncoderFactory* encoder_factory) {
+ if (external_encoder_factory_ == encoder_factory) {
+ return;
+ }
+ if (external_encoder_factory_) {
+ external_encoder_factory_->RemoveObserver(this);
+ }
+ external_encoder_factory_ = encoder_factory;
+ if (external_encoder_factory_) {
+ external_encoder_factory_->AddObserver(this);
+ }
+
+ // Invoke OnCodecAvailable() here in case the list of codecs is already
+ // available when the encoder factory is installed. If not the encoder
+ // factory will invoke the callback later when the codecs become available.
+ OnCodecsAvailable();
+}
+
+bool WebRtcVideoEngine2::EnableTimedRender() {
+ // TODO(pbos): Figure out whether this can be removed.
return true;
}
@@ -517,6 +506,9 @@ WebRtcVideoEncoderFactory2* WebRtcVideoEngine2::GetVideoEncoderFactory() {
return &default_video_encoder_factory_;
}
+void WebRtcVideoEngine2::OnCodecsAvailable() {
+ // TODO(pbos): Implement.
+}
// Thin map between VideoFrame and an existing webrtc::I420VideoFrame
// to avoid having to copy the rendered VideoFrame prematurely.
// This implementation is only safe to use in a const context and should never
@@ -679,8 +671,8 @@ WebRtcVideoChannel2::WebRtcVideoChannel2(
WebRtcVideoEngine2* engine,
VoiceMediaChannel* voice_channel,
WebRtcVideoEncoderFactory2* encoder_factory)
- : encoder_factory_(encoder_factory),
- unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_) {
+ : unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_),
+ encoder_factory_(encoder_factory) {
// TODO(pbos): Connect the video and audio with |voice_channel|.
webrtc::Call::Config config(this);
Construct(webrtc::Call::Create(config), engine);
@@ -690,8 +682,8 @@ WebRtcVideoChannel2::WebRtcVideoChannel2(
webrtc::Call* call,
WebRtcVideoEngine2* engine,
WebRtcVideoEncoderFactory2* encoder_factory)
- : encoder_factory_(encoder_factory),
- unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_) {
+ : unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_),
+ encoder_factory_(encoder_factory) {
Construct(call, engine);
}
@@ -1174,7 +1166,9 @@ void WebRtcVideoChannel2::OnRtcpReceived(
}
void WebRtcVideoChannel2::OnReadyToSend(bool ready) {
- LOG(LS_VERBOSE) << "OnReadySend: " << (ready ? "Ready." : "Not ready.");
+ LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready.");
+ call_->SignalNetworkState(ready ? webrtc::Call::kNetworkUp
+ : webrtc::Call::kNetworkDown);
}
bool WebRtcVideoChannel2::MuteStream(uint32 ssrc, bool mute) {
@@ -1315,10 +1309,10 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream(
const StreamParams& sp,
const std::vector<webrtc::RtpExtension>& rtp_extensions)
: call_(call),
- parameters_(webrtc::VideoSendStream::Config(), options, codec_settings),
encoder_factory_(encoder_factory),
- capturer_(NULL),
stream_(NULL),
+ parameters_(webrtc::VideoSendStream::Config(), options, codec_settings),
+ capturer_(NULL),
sending_(false),
muted_(false) {
parameters_.config.rtp.max_packet_size = kVideoMtu;
@@ -1385,16 +1379,10 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame(
const VideoFrame* frame) {
LOG(LS_VERBOSE) << "InputFrame: " << frame->GetWidth() << "x"
<< frame->GetHeight();
- bool is_screencast = capturer->IsScreencast();
// Lock before copying, can be called concurrently when swapping input source.
rtc::CritScope frame_cs(&frame_lock_);
- if (!muted_) {
- ConvertToI420VideoFrame(*frame, &video_frame_);
- } else {
- // Create a tiny black frame to transmit instead.
- CreateBlackFrame(&video_frame_, 1, 1);
- is_screencast = false;
- }
+ ConvertToI420VideoFrame(*frame, &video_frame_);
+
rtc::CritScope cs(&lock_);
if (stream_ == NULL) {
LOG(LS_WARNING) << "Capturer inputting frames before send codecs are "
@@ -1406,14 +1394,20 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame(
LOG(LS_VERBOSE) << "VideoFormat 0x0 set, Dropping frame.";
return;
}
- // Reconfigure codec if necessary.
- if (is_screencast) {
- SetDimensions(video_frame_.width(), video_frame_.height());
+ if (muted_) {
+ // Create a black frame to transmit instead.
+ CreateBlackFrame(&video_frame_,
+ static_cast<int>(frame->GetWidth()),
+ static_cast<int>(frame->GetHeight()));
}
+ // Reconfigure codec if necessary.
+ SetDimensions(
+ video_frame_.width(), video_frame_.height(), capturer->IsScreencast());
+
LOG(LS_VERBOSE) << "SwapFrame: " << video_frame_.width() << "x"
<< video_frame_.height() << " -> (codec) "
- << parameters_.video_streams.back().width << "x"
- << parameters_.video_streams.back().height;
+ << parameters_.encoder_config.streams.back().width << "x"
+ << parameters_.encoder_config.streams.back().height;
stream_->Input()->SwapFrame(&video_frame_);
}
@@ -1437,7 +1431,7 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetCapturer(
black_frame.CreateEmptyFrame(
width, height, width, half_width, half_width);
SetWebRtcFrameToBlack(&black_frame);
- SetDimensions(width, height);
+ SetDimensions(width, height, false);
stream_->Input()->SwapFrame(&black_frame);
}
@@ -1469,9 +1463,9 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoFormat(
<< parameters_.config.rtp.ssrcs[0] << ".";
} else {
// TODO(pbos): Fix me, this only affects the last stream!
- parameters_.video_streams.back().max_framerate =
+ parameters_.encoder_config.streams.back().max_framerate =
VideoFormat::IntervalToFps(format.interval);
- SetDimensions(format.width, format.height);
+ SetDimensions(format.width, format.height, false);
}
format_ = format;
@@ -1517,7 +1511,7 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodecAndOptions(
if (video_streams.empty()) {
return;
}
- parameters_.video_streams = video_streams;
+ parameters_.encoder_config.streams = video_streams;
format_ = VideoFormat(codec_settings.codec.width,
codec_settings.codec.height,
VideoFormat::FpsToInterval(30),
@@ -1560,35 +1554,55 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpExtensions(
RecreateWebRtcStream();
}
-void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions(int width,
- int height) {
- assert(!parameters_.video_streams.empty());
+void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions(
+ int width,
+ int height,
+ bool override_max) {
+ assert(!parameters_.encoder_config.streams.empty());
LOG(LS_VERBOSE) << "SetDimensions: " << width << "x" << height;
- if (parameters_.video_streams.back().width == width &&
- parameters_.video_streams.back().height == height) {
+
+ VideoCodecSettings codec_settings;
+ parameters_.codec_settings.Get(&codec_settings);
+ // Restrict dimensions according to codec max.
+ if (!override_max) {
+ if (codec_settings.codec.width < width)
+ width = codec_settings.codec.width;
+ if (codec_settings.codec.height < height)
+ height = codec_settings.codec.height;
+ }
+
+ if (parameters_.encoder_config.streams.back().width == width &&
+ parameters_.encoder_config.streams.back().height == height) {
return;
}
- // TODO(pbos): Fix me, this only affects the last stream!
- parameters_.video_streams.back().width = width;
- parameters_.video_streams.back().height = height;
+ webrtc::VideoEncoderConfig encoder_config = parameters_.encoder_config;
+ encoder_config.encoder_specific_settings =
+ encoder_factory_->CreateVideoEncoderSettings(codec_settings.codec,
+ parameters_.options);
- VideoCodecSettings codec_settings;
- parameters_.codec_settings.Get(&codec_settings);
- void* encoder_settings = encoder_factory_->CreateVideoEncoderSettings(
- codec_settings.codec, parameters_.options);
+ VideoCodec codec = codec_settings.codec;
+ codec.width = width;
+ codec.height = height;
+
+ encoder_config.streams = encoder_factory_->CreateVideoStreams(
+ codec, parameters_.options, parameters_.config.rtp.ssrcs.size());
- bool stream_reconfigured = stream_->ReconfigureVideoEncoder(
- parameters_.video_streams, encoder_settings);
+ bool stream_reconfigured = stream_->ReconfigureVideoEncoder(encoder_config);
- encoder_factory_->DestroyVideoEncoderSettings(codec_settings.codec,
- encoder_settings);
+ encoder_factory_->DestroyVideoEncoderSettings(
+ codec_settings.codec,
+ encoder_config.encoder_specific_settings);
+
+ encoder_config.encoder_specific_settings = NULL;
if (!stream_reconfigured) {
LOG(LS_WARNING) << "Failed to reconfigure video encoder for dimensions: "
<< width << "x" << height;
return;
}
+
+ parameters_.encoder_config = encoder_config;
}
void WebRtcVideoChannel2::WebRtcVideoSendStream::Start() {
@@ -1652,9 +1666,9 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() {
info.input_frame_width = last_captured_frame_format.width;
info.input_frame_height = last_captured_frame_format.height;
info.send_frame_width =
- static_cast<int>(parameters_.video_streams.front().width);
+ static_cast<int>(parameters_.encoder_config.streams.front().width);
info.send_frame_height =
- static_cast<int>(parameters_.video_streams.front().height);
+ static_cast<int>(parameters_.encoder_config.streams.front().height);
}
// TODO(pbos): Support or remove the following stats.
@@ -1671,14 +1685,18 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() {
VideoCodecSettings codec_settings;
parameters_.codec_settings.Get(&codec_settings);
- void* encoder_settings = encoder_factory_->CreateVideoEncoderSettings(
- codec_settings.codec, parameters_.options);
+ parameters_.encoder_config.encoder_specific_settings =
+ encoder_factory_->CreateVideoEncoderSettings(codec_settings.codec,
+ parameters_.options);
- stream_ = call_->CreateVideoSendStream(
- parameters_.config, parameters_.video_streams, encoder_settings);
+ stream_ = call_->CreateVideoSendStream(parameters_.config,
+ parameters_.encoder_config);
- encoder_factory_->DestroyVideoEncoderSettings(codec_settings.codec,
- encoder_settings);
+ encoder_factory_->DestroyVideoEncoderSettings(
+ codec_settings.codec,
+ parameters_.encoder_config.encoder_specific_settings);
+
+ parameters_.encoder_config.encoder_specific_settings = NULL;
if (sending_) {
stream_->Start();
@@ -1690,11 +1708,11 @@ WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream(
const webrtc::VideoReceiveStream::Config& config,
const std::vector<VideoCodecSettings>& recv_codecs)
: call_(call),
- config_(config),
stream_(NULL),
+ config_(config),
+ renderer_(NULL),
last_width_(-1),
- last_height_(-1),
- renderer_(NULL) {
+ last_height_(-1) {
config_.renderer = this;
// SetRecvCodecs will also reset (start) the VideoReceiveStream.
SetRecvCodecs(recv_codecs);