blob: cd39f68c1a9b4fc32690daef492cfd8571b037b5 [file] [log] [blame]
magjed614d5b72016-11-15 06:30:54 -08001/*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/media/engine/videoencodersoftwarefallbackwrapper.h"
12
13#include "webrtc/base/logging.h"
14#include "webrtc/modules/video_coding/include/video_error_codes.h"
15
16namespace webrtc {
17
18VideoEncoderSoftwareFallbackWrapper::VideoEncoderSoftwareFallbackWrapper(
19 VideoCodecType codec_type,
20 webrtc::VideoEncoder* encoder)
21 : rates_set_(false),
22 channel_parameters_set_(false),
23 encoder_type_(CodecToEncoderType(codec_type)),
24 encoder_(encoder),
25 callback_(nullptr) {}
26
27bool VideoEncoderSoftwareFallbackWrapper::InitFallbackEncoder() {
28 if (!VideoEncoder::IsSupportedSoftware(encoder_type_)) {
29 LOG(LS_WARNING)
30 << "Encoder requesting fallback to codec not supported in software.";
31 return false;
32 }
33 fallback_encoder_.reset(VideoEncoder::Create(encoder_type_));
34 if (fallback_encoder_->InitEncode(&codec_settings_, number_of_cores_,
35 max_payload_size_) !=
36 WEBRTC_VIDEO_CODEC_OK) {
37 LOG(LS_ERROR) << "Failed to initialize software-encoder fallback.";
38 fallback_encoder_->Release();
39 fallback_encoder_.reset();
40 return false;
41 }
42 // Replay callback, rates, and channel parameters.
43 if (callback_)
44 fallback_encoder_->RegisterEncodeCompleteCallback(callback_);
45 if (rates_set_)
46 fallback_encoder_->SetRates(bitrate_, framerate_);
47 if (channel_parameters_set_)
48 fallback_encoder_->SetChannelParameters(packet_loss_, rtt_);
49
50 fallback_implementation_name_ =
51 std::string(fallback_encoder_->ImplementationName()) +
52 " (fallback from: " + encoder_->ImplementationName() + ")";
53 // Since we're switching to the fallback encoder, Release the real encoder. It
54 // may be re-initialized via InitEncode later, and it will continue to get
55 // Set calls for rates and channel parameters in the meantime.
56 encoder_->Release();
57 return true;
58}
59
60int32_t VideoEncoderSoftwareFallbackWrapper::InitEncode(
61 const VideoCodec* codec_settings,
62 int32_t number_of_cores,
63 size_t max_payload_size) {
64 // Store settings, in case we need to dynamically switch to the fallback
65 // encoder after a failed Encode call.
66 codec_settings_ = *codec_settings;
67 number_of_cores_ = number_of_cores;
68 max_payload_size_ = max_payload_size;
69 // Clear stored rate/channel parameters.
70 rates_set_ = false;
71 channel_parameters_set_ = false;
72
73 int32_t ret =
74 encoder_->InitEncode(codec_settings, number_of_cores, max_payload_size);
75 if (ret == WEBRTC_VIDEO_CODEC_OK || encoder_type_ == kUnsupportedCodec) {
76 if (fallback_encoder_)
77 fallback_encoder_->Release();
78 fallback_encoder_.reset();
79 if (callback_)
80 encoder_->RegisterEncodeCompleteCallback(callback_);
81 return ret;
82 }
83 // Try to instantiate software codec.
84 if (InitFallbackEncoder()) {
85 return WEBRTC_VIDEO_CODEC_OK;
86 }
87 // Software encoder failed, use original return code.
88 return ret;
89}
90
91int32_t VideoEncoderSoftwareFallbackWrapper::RegisterEncodeCompleteCallback(
92 EncodedImageCallback* callback) {
93 callback_ = callback;
94 int32_t ret = encoder_->RegisterEncodeCompleteCallback(callback);
95 if (fallback_encoder_)
96 return fallback_encoder_->RegisterEncodeCompleteCallback(callback);
97 return ret;
98}
99
100int32_t VideoEncoderSoftwareFallbackWrapper::Release() {
101 // If the fallback_encoder_ is non-null, it means it was created via
102 // InitFallbackEncoder which has Release()d encoder_, so we should only ever
103 // need to Release() whichever one is active.
104 if (fallback_encoder_)
105 return fallback_encoder_->Release();
106 return encoder_->Release();
107}
108
109int32_t VideoEncoderSoftwareFallbackWrapper::Encode(
110 const VideoFrame& frame,
111 const CodecSpecificInfo* codec_specific_info,
112 const std::vector<FrameType>* frame_types) {
113 if (fallback_encoder_)
114 return fallback_encoder_->Encode(frame, codec_specific_info, frame_types);
115 int32_t ret = encoder_->Encode(frame, codec_specific_info, frame_types);
116 // If requested, try a software fallback.
117 if (ret == WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE && InitFallbackEncoder()) {
118 if (frame.video_frame_buffer()->native_handle() &&
119 !fallback_encoder_->SupportsNativeHandle()) {
120 LOG(LS_WARNING) << "Fallback encoder doesn't support native frames, "
121 << "dropping one frame.";
122 return WEBRTC_VIDEO_CODEC_ERROR;
123 }
124
125 // Fallback was successful, so start using it with this frame.
126 return fallback_encoder_->Encode(frame, codec_specific_info, frame_types);
127 }
128 return ret;
129}
130
131int32_t VideoEncoderSoftwareFallbackWrapper::SetChannelParameters(
132 uint32_t packet_loss,
133 int64_t rtt) {
134 channel_parameters_set_ = true;
135 packet_loss_ = packet_loss;
136 rtt_ = rtt;
137 int32_t ret = encoder_->SetChannelParameters(packet_loss, rtt);
138 if (fallback_encoder_)
139 return fallback_encoder_->SetChannelParameters(packet_loss, rtt);
140 return ret;
141}
142
143int32_t VideoEncoderSoftwareFallbackWrapper::SetRates(uint32_t bitrate,
144 uint32_t framerate) {
145 rates_set_ = true;
146 bitrate_ = bitrate;
147 framerate_ = framerate;
148 int32_t ret = encoder_->SetRates(bitrate, framerate);
149 if (fallback_encoder_)
150 return fallback_encoder_->SetRates(bitrate, framerate);
151 return ret;
152}
153
154void VideoEncoderSoftwareFallbackWrapper::OnDroppedFrame() {
155 if (fallback_encoder_)
156 return fallback_encoder_->OnDroppedFrame();
157 return encoder_->OnDroppedFrame();
158}
159
160bool VideoEncoderSoftwareFallbackWrapper::SupportsNativeHandle() const {
161 if (fallback_encoder_)
162 return fallback_encoder_->SupportsNativeHandle();
163 return encoder_->SupportsNativeHandle();
164}
165
166} // namespace webrtc