1470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* 24ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * 4470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * Use of this source code is governed by a BSD-style license 5470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * that can be found in the LICENSE file in the root of the source 6470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * tree. An additional intellectual property rights grant can be found 7470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * in the file PATENTS. All contributing project authors may 8470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * be found in the AUTHORS file in the root of the source tree. 9470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */ 108d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.org 11e07c661a29058aac858f99c5d0701a52969dfbe4mikhal@webrtc.org#include "webrtc/modules/video_coding/codecs/vp8/vp8_impl.h" 12470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 13470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include <stdlib.h> 14470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include <string.h> 15470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include <time.h> 169115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org#include <algorithm> 17470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 189115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org// NOTE(ajm): Path provided by gyp. 19cce46fc108a70336f0477fd58d41f38e547eeb25philipel#include "libyuv/scale.h" // NOLINT 2073d763e71f5c77cac82aa65d737e64d893f190a0magjed@webrtc.org#include "libyuv/convert.h" // NOLINT 21470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 22e155dbeae972f788b8766b4d0d2cefde2e952a10magjed@webrtc.org#include "webrtc/base/checks.h" 23e4f96501fc5b3e6de0d1ccd262372afcda1f5b4ftommi#include "webrtc/base/trace_event.h" 245500d93fe55702af0b254e5718fcc085298c99abandresp@webrtc.org#include "webrtc/common.h" 259115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org#include "webrtc/common_types.h" 26e07c661a29058aac858f99c5d0701a52969dfbe4mikhal@webrtc.org#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" 27ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/include/module_common_types.h" 282557b86e7648ffebc5781df9f093ca5a84efc219Henrik Kjellander#include "webrtc/modules/video_coding/include/video_codec_interface.h" 299115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org#include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h" 309115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org#include "webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h" 315500d93fe55702af0b254e5718fcc085298c99abandresp@webrtc.org#include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h" 3298f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/tick_util.h" 338d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.org 349115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.orgnamespace webrtc { 359115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.orgnamespace { 369115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 371af915d8aeba410ad13f857eb89686dd0f0686d0mikhal@webrtc.orgenum { kVp8ErrorPropagationTh = 30 }; 389115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.orgenum { kVp832ByteAlign = 32 }; 399115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 409115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org// VP8 denoiser states. 419115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.orgenum denoiserState { 429115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org kDenoiserOff, 439115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org kDenoiserOnYOnly, 449115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org kDenoiserOnYUV, 459115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org kDenoiserOnYUVAggressive, 469115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Adaptive mode defaults to kDenoiserOnYUV on key frame, but may switch 479115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // to kDenoiserOnYUVAggressive based on a computed noise metric. 489115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org kDenoiserOnAdaptive 499115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org}; 509115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 519115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org// Greatest common divisior 529115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.orgint GCD(int a, int b) { 539115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org int c = a % b; 549115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org while (c != 0) { 559115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org a = b; 569115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org b = c; 579115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org c = a % b; 589115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 599115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return b; 609115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org} 61470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 621b9add9df9cdab004a11e75900a341a346ce2049Peter Boströmstd::vector<int> GetStreamBitratesKbps(const VideoCodec& codec, 631b9add9df9cdab004a11e75900a341a346ce2049Peter Boström int bitrate_to_allocate_kbps) { 641b9add9df9cdab004a11e75900a341a346ce2049Peter Boström if (codec.numberOfSimulcastStreams <= 1) { 651b9add9df9cdab004a11e75900a341a346ce2049Peter Boström return std::vector<int>(1, bitrate_to_allocate_kbps); 661b9add9df9cdab004a11e75900a341a346ce2049Peter Boström } 671b9add9df9cdab004a11e75900a341a346ce2049Peter Boström 681b9add9df9cdab004a11e75900a341a346ce2049Peter Boström std::vector<int> bitrates_kbps(codec.numberOfSimulcastStreams); 691b9add9df9cdab004a11e75900a341a346ce2049Peter Boström // Allocate min -> target bitrates as long as we have bitrate to spend. 701b9add9df9cdab004a11e75900a341a346ce2049Peter Boström size_t last_active_stream = 0; 71cce46fc108a70336f0477fd58d41f38e547eeb25philipel for (size_t i = 0; i < static_cast<size_t>(codec.numberOfSimulcastStreams) && 72cce46fc108a70336f0477fd58d41f38e547eeb25philipel bitrate_to_allocate_kbps >= 73cce46fc108a70336f0477fd58d41f38e547eeb25philipel static_cast<int>(codec.simulcastStream[i].minBitrate); 741b9add9df9cdab004a11e75900a341a346ce2049Peter Boström ++i) { 751b9add9df9cdab004a11e75900a341a346ce2049Peter Boström last_active_stream = i; 761b9add9df9cdab004a11e75900a341a346ce2049Peter Boström int allocated_bitrate_kbps = 771b9add9df9cdab004a11e75900a341a346ce2049Peter Boström std::min(static_cast<int>(codec.simulcastStream[i].targetBitrate), 781b9add9df9cdab004a11e75900a341a346ce2049Peter Boström bitrate_to_allocate_kbps); 791b9add9df9cdab004a11e75900a341a346ce2049Peter Boström bitrates_kbps[i] = allocated_bitrate_kbps; 801b9add9df9cdab004a11e75900a341a346ce2049Peter Boström bitrate_to_allocate_kbps -= allocated_bitrate_kbps; 811b9add9df9cdab004a11e75900a341a346ce2049Peter Boström } 821b9add9df9cdab004a11e75900a341a346ce2049Peter Boström 831b9add9df9cdab004a11e75900a341a346ce2049Peter Boström // Spend additional bits on the highest-quality active layer, up to max 841b9add9df9cdab004a11e75900a341a346ce2049Peter Boström // bitrate. 851b9add9df9cdab004a11e75900a341a346ce2049Peter Boström // TODO(pbos): Consider spending additional bits on last_active_stream-1 down 861b9add9df9cdab004a11e75900a341a346ce2049Peter Boström // to 0 and not just the top layer when we have additional bitrate to spend. 871b9add9df9cdab004a11e75900a341a346ce2049Peter Boström int allocated_bitrate_kbps = std::min( 881b9add9df9cdab004a11e75900a341a346ce2049Peter Boström static_cast<int>(codec.simulcastStream[last_active_stream].maxBitrate - 891b9add9df9cdab004a11e75900a341a346ce2049Peter Boström bitrates_kbps[last_active_stream]), 901b9add9df9cdab004a11e75900a341a346ce2049Peter Boström bitrate_to_allocate_kbps); 911b9add9df9cdab004a11e75900a341a346ce2049Peter Boström bitrates_kbps[last_active_stream] += allocated_bitrate_kbps; 921b9add9df9cdab004a11e75900a341a346ce2049Peter Boström bitrate_to_allocate_kbps -= allocated_bitrate_kbps; 931b9add9df9cdab004a11e75900a341a346ce2049Peter Boström 941b9add9df9cdab004a11e75900a341a346ce2049Peter Boström // Make sure we can always send something. Suspending below min bitrate is 951b9add9df9cdab004a11e75900a341a346ce2049Peter Boström // controlled outside the codec implementation and is not overriden by this. 961b9add9df9cdab004a11e75900a341a346ce2049Peter Boström if (bitrates_kbps[0] < static_cast<int>(codec.simulcastStream[0].minBitrate)) 971b9add9df9cdab004a11e75900a341a346ce2049Peter Boström bitrates_kbps[0] = static_cast<int>(codec.simulcastStream[0].minBitrate); 981b9add9df9cdab004a11e75900a341a346ce2049Peter Boström 991b9add9df9cdab004a11e75900a341a346ce2049Peter Boström return bitrates_kbps; 1009115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org} 1019115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 1029115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.orguint32_t SumStreamMaxBitrate(int streams, const VideoCodec& codec) { 1039115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org uint32_t bitrate_sum = 0; 1049115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org for (int i = 0; i < streams; ++i) { 1059115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org bitrate_sum += codec.simulcastStream[i].maxBitrate; 1069115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 1079115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return bitrate_sum; 1089115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org} 1099115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 1109115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.orgint NumberOfStreams(const VideoCodec& codec) { 1119115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org int streams = 1129115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org codec.numberOfSimulcastStreams < 1 ? 1 : codec.numberOfSimulcastStreams; 1139115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org uint32_t simulcast_max_bitrate = SumStreamMaxBitrate(streams, codec); 1149115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (simulcast_max_bitrate == 0) { 1159115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org streams = 1; 1169115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 1179115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return streams; 1189115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org} 1199115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 1209115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.orgbool ValidSimulcastResolutions(const VideoCodec& codec, int num_streams) { 1219115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (codec.width != codec.simulcastStream[num_streams - 1].width || 1229115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org codec.height != codec.simulcastStream[num_streams - 1].height) { 1239115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return false; 1249115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 1259115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org for (int i = 0; i < num_streams; ++i) { 1269115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (codec.width * codec.simulcastStream[i].height != 1279115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org codec.height * codec.simulcastStream[i].width) { 1289115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return false; 1299115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 1309115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 1319115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return true; 1329115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org} 133da535c405597864b8396b2029dec70ab9fb76e8basapersson 134cce46fc108a70336f0477fd58d41f38e547eeb25philipelint NumStreamsDisabled(const std::vector<bool>& streams) { 135da535c405597864b8396b2029dec70ab9fb76e8basapersson int num_disabled = 0; 136da535c405597864b8396b2029dec70ab9fb76e8basapersson for (bool stream : streams) { 137da535c405597864b8396b2029dec70ab9fb76e8basapersson if (!stream) 138da535c405597864b8396b2029dec70ab9fb76e8basapersson ++num_disabled; 139da535c405597864b8396b2029dec70ab9fb76e8basapersson } 140da535c405597864b8396b2029dec70ab9fb76e8basapersson return num_disabled; 141da535c405597864b8396b2029dec70ab9fb76e8basapersson} 1429115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org} // namespace 1439115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 1449115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.orgconst float kTl1MaxTimeToDropFrames = 20.0f; 145470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1468d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.orgVP8EncoderImpl::VP8EncoderImpl() 1479115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org : encoded_complete_callback_(NULL), 1484ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org inited_(false), 1494ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org timestamp_(0), 1504ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org feedback_mode_(false), 1519115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org qp_max_(56), // Setting for max quantizer. 1526daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org cpu_speed_default_(-6), 1534ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org rc_max_intra_target_(0), 1544ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org token_partitions_(VP8_ONE_TOKENPARTITION), 1559115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org down_scale_requested_(false), 1569115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org down_scale_bitrate_(0), 1579115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org tl0_frame_dropper_(), 1589115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org tl1_frame_dropper_(kTl1MaxTimeToDropFrames), 1594306fc70d778887d8a2ea71b6f4bc6a12d1d9447asapersson key_frame_request_(kMaxSimulcastStreams, false), 1604306fc70d778887d8a2ea71b6f4bc6a12d1d9447asapersson quality_scaler_enabled_(false) { 1614ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org uint32_t seed = static_cast<uint32_t>(TickTime::MillisecondTimestamp()); 1624ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org srand(seed); 1639115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 1649115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org picture_id_.reserve(kMaxSimulcastStreams); 1659115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org last_key_frame_picture_id_.reserve(kMaxSimulcastStreams); 1669115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org temporal_layers_.reserve(kMaxSimulcastStreams); 1679115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org raw_images_.reserve(kMaxSimulcastStreams); 1689115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org encoded_images_.reserve(kMaxSimulcastStreams); 1699115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org send_stream_.reserve(kMaxSimulcastStreams); 1709115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org cpu_speed_.assign(kMaxSimulcastStreams, -6); // Set default to -6. 1719115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org encoders_.reserve(kMaxSimulcastStreams); 1729115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_.reserve(kMaxSimulcastStreams); 1739115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org downsampling_factors_.reserve(kMaxSimulcastStreams); 174470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1768d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.orgVP8EncoderImpl::~VP8EncoderImpl() { 1774ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org Release(); 178470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 179470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1808d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.orgint VP8EncoderImpl::Release() { 1819115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org int ret_val = WEBRTC_VIDEO_CODEC_OK; 1829115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 1839115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org while (!encoded_images_.empty()) { 1849115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org EncodedImage& image = encoded_images_.back(); 185cce46fc108a70336f0477fd58d41f38e547eeb25philipel delete[] image._buffer; 1869115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org encoded_images_.pop_back(); 1874ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 1889115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org while (!encoders_.empty()) { 1899115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org vpx_codec_ctx_t& encoder = encoders_.back(); 1909115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (vpx_codec_destroy(&encoder)) { 1919115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org ret_val = WEBRTC_VIDEO_CODEC_MEMORY; 192470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1939115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org encoders_.pop_back(); 1944ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 1959115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_.clear(); 1969115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org send_stream_.clear(); 1979115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org cpu_speed_.clear(); 1989115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org while (!raw_images_.empty()) { 1999115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org vpx_img_free(&raw_images_.back()); 2009115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org raw_images_.pop_back(); 2014ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 2029115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org while (!temporal_layers_.empty()) { 2039115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org delete temporal_layers_.back(); 2049115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org temporal_layers_.pop_back(); 2054ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 2064ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org inited_ = false; 2079115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return ret_val; 208470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 209470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2108d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.orgint VP8EncoderImpl::SetRates(uint32_t new_bitrate_kbit, 2111b9add9df9cdab004a11e75900a341a346ce2049Peter Boström uint32_t new_framerate) { 2124ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (!inited_) { 2134ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 2144ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 2159115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (encoders_[0].err) { 2164ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERROR; 2174ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 2184ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (new_framerate < 1) { 2194ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 2204ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 2214ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (codec_.maxBitrate > 0 && new_bitrate_kbit > codec_.maxBitrate) { 2224ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org new_bitrate_kbit = codec_.maxBitrate; 2234ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 2249115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (new_bitrate_kbit < codec_.minBitrate) { 2259115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org new_bitrate_kbit = codec_.minBitrate; 2269115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 2279115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (codec_.numberOfSimulcastStreams > 0 && 2289115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org new_bitrate_kbit < codec_.simulcastStream[0].minBitrate) { 2299115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org new_bitrate_kbit = codec_.simulcastStream[0].minBitrate; 2309115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 2314ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org codec_.maxFramerate = new_framerate; 232470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2339115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (encoders_.size() == 1) { 2349115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // 1:1. 2359115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Calculate a rough limit for when to trigger a potental down scale. 2369115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org uint32_t k_pixels_per_frame = codec_.width * codec_.height / 1000; 2379115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // TODO(pwestin): we currently lack CAMA, this is a temporary fix to work 2389115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // around the current limitations. 2399115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Only trigger keyframes if we are allowed to scale down. 2409115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (configurations_[0].rc_resize_allowed) { 2419115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (!down_scale_requested_) { 2429115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (k_pixels_per_frame > new_bitrate_kbit) { 2439115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org down_scale_requested_ = true; 2449115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org down_scale_bitrate_ = new_bitrate_kbit; 2459115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org key_frame_request_[0] = true; 2469115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 2479115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } else { 2489115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (new_bitrate_kbit > (2 * down_scale_bitrate_) || 2499115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org new_bitrate_kbit < (down_scale_bitrate_ / 2)) { 2509115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org down_scale_requested_ = false; 2519115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 2529115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 2539115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 2549115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } else { 2559115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // If we have more than 1 stream, reduce the qp_max for the low resolution 2569115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // stream if frame rate is not too low. The trade-off with lower qp_max is 2579115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // possibly more dropped frames, so we only do this if the frame rate is 2589115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // above some threshold (base temporal layer is down to 1/4 for 3 layers). 2599115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // We may want to condition this on bitrate later. 2609115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (new_framerate > 20) { 2619115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[encoders_.size() - 1].rc_max_quantizer = 45; 2629115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } else { 2639115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Go back to default value set in InitEncode. 2649115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[encoders_.size() - 1].rc_max_quantizer = qp_max_; 2659115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 2669115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 2679115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 2681b9add9df9cdab004a11e75900a341a346ce2049Peter Boström std::vector<int> stream_bitrates = 2691b9add9df9cdab004a11e75900a341a346ce2049Peter Boström GetStreamBitratesKbps(codec_, new_bitrate_kbit); 2709115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org size_t stream_idx = encoders_.size() - 1; 2719115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org for (size_t i = 0; i < encoders_.size(); ++i, --stream_idx) { 2721b9add9df9cdab004a11e75900a341a346ce2049Peter Boström if (encoders_.size() > 1) 2731b9add9df9cdab004a11e75900a341a346ce2049Peter Boström SetStreamState(stream_bitrates[stream_idx] > 0, stream_idx); 2749115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 2751b9add9df9cdab004a11e75900a341a346ce2049Peter Boström unsigned int target_bitrate = stream_bitrates[stream_idx]; 2769115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org unsigned int max_bitrate = codec_.maxBitrate; 2779115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org int framerate = new_framerate; 2789115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // TODO(holmer): This is a temporary hack for screensharing, where we 2799115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // interpret the startBitrate as the encoder target bitrate. This is 2809115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // to allow for a different max bitrate, so if the codec can't meet 2819115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // the target we still allow it to overshoot up to the max before dropping 2829115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // frames. This hack should be improved. 2839115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (codec_.targetBitrate > 0 && 2849115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org (codec_.codecSpecific.VP8.numberOfTemporalLayers == 2 || 2859115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org codec_.simulcastStream[0].numberOfTemporalLayers == 2)) { 2869115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org int tl0_bitrate = std::min(codec_.targetBitrate, target_bitrate); 2879115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org max_bitrate = std::min(codec_.maxBitrate, target_bitrate); 2889115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org target_bitrate = tl0_bitrate; 2899115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 2909115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[i].rc_target_bitrate = target_bitrate; 291cce46fc108a70336f0477fd58d41f38e547eeb25philipel temporal_layers_[stream_idx]->ConfigureBitrates( 292cce46fc108a70336f0477fd58d41f38e547eeb25philipel target_bitrate, max_bitrate, framerate, &configurations_[i]); 2939115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (vpx_codec_enc_config_set(&encoders_[i], &configurations_[i])) { 2949115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return WEBRTC_VIDEO_CODEC_ERROR; 2959115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 2964ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 2979115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org quality_scaler_.ReportFramerate(new_framerate); 2984ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_OK; 299470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 300470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 301b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boströmconst char* VP8EncoderImpl::ImplementationName() const { 302b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström return "libvpx"; 303b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström} 304b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström 3059115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.orgvoid VP8EncoderImpl::SetStreamState(bool send_stream, 3069115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org int stream_idx) { 3079115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (send_stream && !send_stream_[stream_idx]) { 3089115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Need a key frame if we have not sent this stream before. 3099115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org key_frame_request_[stream_idx] = true; 3109115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 3119115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org send_stream_[stream_idx] = send_stream; 3129115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org} 3139115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 3149115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.orgvoid VP8EncoderImpl::SetupTemporalLayers(int num_streams, 315cce46fc108a70336f0477fd58d41f38e547eeb25philipel int num_temporal_layers, 316cce46fc108a70336f0477fd58d41f38e547eeb25philipel const VideoCodec& codec) { 3179115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org const Config default_options; 3189115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org const TemporalLayers::Factory& tl_factory = 3199115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org (codec.extra_options ? codec.extra_options : &default_options) 3209115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org ->Get<TemporalLayers::Factory>(); 3219115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (num_streams == 1) { 3229115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (codec.mode == kScreensharing) { 3239115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Special mode when screensharing on a single stream. 3242c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng temporal_layers_.push_back( 3252c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng new ScreenshareLayers(num_temporal_layers, rand())); 3269115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } else { 3279115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org temporal_layers_.push_back( 3289115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org tl_factory.Create(num_temporal_layers, rand())); 3299115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 3309115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } else { 3319115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org for (int i = 0; i < num_streams; ++i) { 3329115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // TODO(andresp): crash if layers is invalid. 3339115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org int layers = codec.simulcastStream[i].numberOfTemporalLayers; 334cce46fc108a70336f0477fd58d41f38e547eeb25philipel if (layers < 1) 335cce46fc108a70336f0477fd58d41f38e547eeb25philipel layers = 1; 3369115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org temporal_layers_.push_back(tl_factory.Create(layers, rand())); 3379115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 3389115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 3399115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org} 3409115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 3418d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.orgint VP8EncoderImpl::InitEncode(const VideoCodec* inst, 342cce46fc108a70336f0477fd58d41f38e547eeb25philipel int number_of_cores, 343cce46fc108a70336f0477fd58d41f38e547eeb25philipel size_t /*maxPayloadSize */) { 3444ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (inst == NULL) { 3454ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 3464ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 3474ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (inst->maxFramerate < 1) { 3484ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 3494ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 3504ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // allow zero to represent an unspecified maxBitRate 3514ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (inst->maxBitrate > 0 && inst->startBitrate > inst->maxBitrate) { 3524ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 3534ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 3549115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (inst->width <= 1 || inst->height <= 1) { 3554ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 3564ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 3574ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (number_of_cores < 1) { 3584ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 3594ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 3609115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (inst->codecSpecific.VP8.feedbackModeOn && 3619115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org inst->numberOfSimulcastStreams > 1) { 3629115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 3639115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 3649115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (inst->codecSpecific.VP8.automaticResizeOn && 3659115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org inst->numberOfSimulcastStreams > 1) { 3669115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 3679115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 3684ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org int retVal = Release(); 3694ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (retVal < 0) { 3704ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return retVal; 3714ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 372470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3739115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org int number_of_streams = NumberOfStreams(*inst); 3749115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org bool doing_simulcast = (number_of_streams > 1); 3759115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 3769115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (doing_simulcast && !ValidSimulcastResolutions(*inst, number_of_streams)) { 3779115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 378d25b602dc0e70282e1f0223e5909534fa81053f0pbos@webrtc.org } 379470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 380cce46fc108a70336f0477fd58d41f38e547eeb25philipel int num_temporal_layers = 381cce46fc108a70336f0477fd58d41f38e547eeb25philipel doing_simulcast ? inst->simulcastStream[0].numberOfTemporalLayers 382cce46fc108a70336f0477fd58d41f38e547eeb25philipel : inst->codecSpecific.VP8.numberOfTemporalLayers; 3839115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 3849115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // TODO(andresp): crash if num temporal layers is bananas. 385cce46fc108a70336f0477fd58d41f38e547eeb25philipel if (num_temporal_layers < 1) 386cce46fc108a70336f0477fd58d41f38e547eeb25philipel num_temporal_layers = 1; 3879115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org SetupTemporalLayers(number_of_streams, num_temporal_layers, *inst); 3889115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 3899115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org feedback_mode_ = inst->codecSpecific.VP8.feedbackModeOn; 3909115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 3919115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org timestamp_ = 0; 3929115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org codec_ = *inst; 3939115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 3949115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Code expects simulcastStream resolutions to be correct, make sure they are 3959115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // filled even when there are no simulcast layers. 3969115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (codec_.numberOfSimulcastStreams == 0) { 3979115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org codec_.simulcastStream[0].width = codec_.width; 3989115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org codec_.simulcastStream[0].height = codec_.height; 3999115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 4009115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 4019115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org picture_id_.resize(number_of_streams); 4029115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org last_key_frame_picture_id_.resize(number_of_streams); 4039115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org encoded_images_.resize(number_of_streams); 4049115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org encoders_.resize(number_of_streams); 4059115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_.resize(number_of_streams); 4069115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org downsampling_factors_.resize(number_of_streams); 4079115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org raw_images_.resize(number_of_streams); 4089115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org send_stream_.resize(number_of_streams); 4099115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org send_stream_[0] = true; // For non-simulcast case. 4109115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org cpu_speed_.resize(number_of_streams); 4119115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org std::fill(key_frame_request_.begin(), key_frame_request_.end(), false); 4129115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 4139115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org int idx = number_of_streams - 1; 4149115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org for (int i = 0; i < (number_of_streams - 1); ++i, --idx) { 4159115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org int gcd = GCD(inst->simulcastStream[idx].width, 416cce46fc108a70336f0477fd58d41f38e547eeb25philipel inst->simulcastStream[idx - 1].width); 4179115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org downsampling_factors_[i].num = inst->simulcastStream[idx].width / gcd; 4189115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org downsampling_factors_[i].den = inst->simulcastStream[idx - 1].width / gcd; 4199115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org send_stream_[i] = false; 4209115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 4219115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (number_of_streams > 1) { 4229115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org send_stream_[number_of_streams - 1] = false; 4239115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org downsampling_factors_[number_of_streams - 1].num = 1; 4249115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org downsampling_factors_[number_of_streams - 1].den = 1; 4259115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 4269115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org for (int i = 0; i < number_of_streams; ++i) { 4279115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Random start, 16 bits is enough. 428cce46fc108a70336f0477fd58d41f38e547eeb25philipel picture_id_[i] = static_cast<uint16_t>(rand()) & 0x7FFF; // NOLINT 4299115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org last_key_frame_picture_id_[i] = -1; 4309115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // allocate memory for encoded image 4319115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (encoded_images_[i]._buffer != NULL) { 432cce46fc108a70336f0477fd58d41f38e547eeb25philipel delete[] encoded_images_[i]._buffer; 4339115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 434cce46fc108a70336f0477fd58d41f38e547eeb25philipel encoded_images_[i]._size = 435cce46fc108a70336f0477fd58d41f38e547eeb25philipel CalcBufferSize(kI420, codec_.width, codec_.height); 4369115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org encoded_images_[i]._buffer = new uint8_t[encoded_images_[i]._size]; 4379115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org encoded_images_[i]._completeFrame = true; 4389115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 4394ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // populate encoder configuration with default values 440cce46fc108a70336f0477fd58d41f38e547eeb25philipel if (vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &configurations_[0], 441cce46fc108a70336f0477fd58d41f38e547eeb25philipel 0)) { 4424ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERROR; 4434ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 4444ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // setting the time base of the codec 4459115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].g_timebase.num = 1; 4469115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].g_timebase.den = 90000; 4479115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].g_lag_in_frames = 0; // 0- no frame lagging 4484ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org 4494ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Set the error resilience mode according to user settings. 4504ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org switch (inst->codecSpecific.VP8.resilience) { 4514ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org case kResilienceOff: 4529115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // TODO(marpan): We should set keep error resilience off for this mode, 4539115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // independent of temporal layer settings, and make sure we set 4549115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // |codecSpecific.VP8.resilience| = |kResilientStream| at higher level 4559115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // code if we want to get error resilience on. 4569115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].g_error_resilient = 1; 4574ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org break; 4584ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org case kResilientStream: 4599115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].g_error_resilient = 1; // TODO(holmer): Replace with 4604ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // VPX_ERROR_RESILIENT_DEFAULT when we 4614ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // drop support for libvpx 9.6.0. 4624ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org break; 4634ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org case kResilientFrames: 464c3d891059e117357011e414263af0f519313d440stefan@webrtc.org#ifdef INDEPENDENT_PARTITIONS 465cce46fc108a70336f0477fd58d41f38e547eeb25philipel configurations_[0] - g_error_resilient = 466cce46fc108a70336f0477fd58d41f38e547eeb25philipel VPX_ERROR_RESILIENT_DEFAULT | VPX_ERROR_RESILIENT_PARTITIONS; 4674ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org break; 468c3d891059e117357011e414263af0f519313d440stefan@webrtc.org#else 4694ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; // Not supported 470c3d891059e117357011e414263af0f519313d440stefan@webrtc.org#endif 4714ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 472a4a88f90c44c6ee287baccae10c7f7ff556dcb20stefan@webrtc.org 4734ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // rate control settings 4749115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].rc_dropframe_thresh = 4759115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org inst->codecSpecific.VP8.frameDroppingOn ? 30 : 0; 4769115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].rc_end_usage = VPX_CBR; 4779115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].g_pass = VPX_RC_ONE_PASS; 4789115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // TODO(hellner): investigate why the following two lines produce 4799115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // automaticResizeOn value of 3 when running 4809115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // WebRtcVideoMediaChannelTest.GetStatsMultipleSendStreams inside the talk 4819115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // framework. 4829115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // configurations_[0].rc_resize_allowed = 4839115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // inst->codecSpecific.VP8.automaticResizeOn ? 1 : 0; 4849115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].rc_resize_allowed = 0; 4859115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Handle resizing outside of libvpx when doing single-stream. 4869115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (inst->codecSpecific.VP8.automaticResizeOn && number_of_streams > 1) { 4879115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].rc_resize_allowed = 1; 4889115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 4899115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].rc_min_quantizer = 2; 4909115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (inst->qpMax >= configurations_[0].rc_min_quantizer) { 4919115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org qp_max_ = inst->qpMax; 4929115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 4939115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].rc_max_quantizer = qp_max_; 4949115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].rc_undershoot_pct = 100; 4959115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].rc_overshoot_pct = 15; 4969115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].rc_buf_initial_sz = 500; 4979115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].rc_buf_optimal_sz = 600; 4989115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].rc_buf_sz = 1000; 4999115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 5009115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Set the maximum target size of any key-frame. 5019115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org rc_max_intra_target_ = MaxIntraTarget(configurations_[0].rc_buf_optimal_sz); 5024ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org 5034ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (feedback_mode_) { 5044ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Disable periodic key frames if we get feedback from the decoder 5054ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // through SLI and RPSI. 5069115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].kf_mode = VPX_KF_DISABLED; 5079115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } else if (inst->codecSpecific.VP8.keyFrameInterval > 0) { 5089115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].kf_mode = VPX_KF_AUTO; 5099115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].kf_max_dist = inst->codecSpecific.VP8.keyFrameInterval; 510e07c661a29058aac858f99c5d0701a52969dfbe4mikhal@webrtc.org } else { 5119115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].kf_mode = VPX_KF_DISABLED; 5124ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 5139115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 5149115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Allow the user to set the complexity for the base stream. 5154ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org switch (inst->codecSpecific.VP8.complexity) { 5164ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org case kComplexityHigh: 5179115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org cpu_speed_[0] = -5; 5184ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org break; 5194ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org case kComplexityHigher: 5209115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org cpu_speed_[0] = -4; 5214ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org break; 5224ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org case kComplexityMax: 5239115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org cpu_speed_[0] = -3; 5244ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org break; 5254ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org default: 5269115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org cpu_speed_[0] = -6; 5274ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org break; 5284ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 5296daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org cpu_speed_default_ = cpu_speed_[0]; 5306daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org // Set encoding complexity (cpu_speed) based on resolution and/or platform. 5316daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org cpu_speed_[0] = SetCpuSpeed(inst->width, inst->height); 5329115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org for (int i = 1; i < number_of_streams; ++i) { 5336daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org cpu_speed_[i] = 5346daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org SetCpuSpeed(inst->simulcastStream[number_of_streams - 1 - i].width, 5356daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org inst->simulcastStream[number_of_streams - 1 - i].height); 5369115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 5379115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].g_w = inst->width; 5389115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].g_h = inst->height; 5399115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 5409115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Determine number of threads based on the image size and #cores. 5419115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // TODO(fbarchard): Consider number of Simulcast layers. 542cce46fc108a70336f0477fd58d41f38e547eeb25philipel configurations_[0].g_threads = NumberOfThreads( 543cce46fc108a70336f0477fd58d41f38e547eeb25philipel configurations_[0].g_w, configurations_[0].g_h, number_of_cores); 5449115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 5459115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Creating a wrapper to the image - setting image data to NULL. 5469115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Actual pointer will be set in encode. Setting align to 1, as it 5479115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // is meaningless (no memory allocation is done here). 548cce46fc108a70336f0477fd58d41f38e547eeb25philipel vpx_img_wrap(&raw_images_[0], VPX_IMG_FMT_I420, inst->width, inst->height, 1, 549cce46fc108a70336f0477fd58d41f38e547eeb25philipel NULL); 5509115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 5519115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (encoders_.size() == 1) { 5529115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].rc_target_bitrate = inst->startBitrate; 553cce46fc108a70336f0477fd58d41f38e547eeb25philipel temporal_layers_[0]->ConfigureBitrates(inst->startBitrate, inst->maxBitrate, 5549115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org inst->maxFramerate, 5559115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org &configurations_[0]); 5569115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } else { 5579115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Note the order we use is different from webm, we have lowest resolution 5589115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // at position 0 and they have highest resolution at position 0. 5599115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org int stream_idx = encoders_.size() - 1; 5601b9add9df9cdab004a11e75900a341a346ce2049Peter Boström std::vector<int> stream_bitrates = 5611b9add9df9cdab004a11e75900a341a346ce2049Peter Boström GetStreamBitratesKbps(codec_, inst->startBitrate); 5621b9add9df9cdab004a11e75900a341a346ce2049Peter Boström SetStreamState(stream_bitrates[stream_idx] > 0, stream_idx); 5631b9add9df9cdab004a11e75900a341a346ce2049Peter Boström configurations_[0].rc_target_bitrate = stream_bitrates[stream_idx]; 5641b9add9df9cdab004a11e75900a341a346ce2049Peter Boström temporal_layers_[stream_idx]->ConfigureBitrates( 5651b9add9df9cdab004a11e75900a341a346ce2049Peter Boström stream_bitrates[stream_idx], inst->maxBitrate, inst->maxFramerate, 5661b9add9df9cdab004a11e75900a341a346ce2049Peter Boström &configurations_[0]); 5679115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org --stream_idx; 5689115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org for (size_t i = 1; i < encoders_.size(); ++i, --stream_idx) { 5699115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org memcpy(&configurations_[i], &configurations_[0], 5709115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org sizeof(configurations_[0])); 5719115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 5729115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[i].g_w = inst->simulcastStream[stream_idx].width; 5739115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[i].g_h = inst->simulcastStream[stream_idx].height; 5749115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 5759115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Use 1 thread for lower resolutions. 5769115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[i].g_threads = 1; 5779115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 5789115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Setting alignment to 32 - as that ensures at least 16 for all 5799115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // planes (32 for Y, 16 for U,V). Libvpx sets the requested stride for 5809115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // the y plane, but only half of it to the u and v planes. 5819115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org vpx_img_alloc(&raw_images_[i], VPX_IMG_FMT_I420, 5829115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org inst->simulcastStream[stream_idx].width, 5839115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org inst->simulcastStream[stream_idx].height, kVp832ByteAlign); 5841b9add9df9cdab004a11e75900a341a346ce2049Peter Boström SetStreamState(stream_bitrates[stream_idx] > 0, stream_idx); 5851b9add9df9cdab004a11e75900a341a346ce2049Peter Boström configurations_[i].rc_target_bitrate = stream_bitrates[stream_idx]; 5861b9add9df9cdab004a11e75900a341a346ce2049Peter Boström temporal_layers_[stream_idx]->ConfigureBitrates( 5871b9add9df9cdab004a11e75900a341a346ce2049Peter Boström stream_bitrates[stream_idx], inst->maxBitrate, inst->maxFramerate, 5881b9add9df9cdab004a11e75900a341a346ce2049Peter Boström &configurations_[i]); 5899115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 5909115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 5919115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 5929115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org rps_.Init(); 59317417707428816ffb88d9c71dcc8a5d492cf9fdfPeter Boström // Disable both high-QP limits and framedropping. Both are handled by libvpx 59417417707428816ffb88d9c71dcc8a5d492cf9fdfPeter Boström // internally. 59517417707428816ffb88d9c71dcc8a5d492cf9fdfPeter Boström const int kDisabledBadQpThreshold = 64; 5966e2ce6e1ae41d8eeb0f233cbd26087daa03ab702jackychen quality_scaler_.Init(codec_.qpMax / QualityScaler::kDefaultLowQpDenominator, 59717417707428816ffb88d9c71dcc8a5d492cf9fdfPeter Boström kDisabledBadQpThreshold, false); 598a0d7827b1631fa8e2cf8957a76736ab159cb962apbos@webrtc.org quality_scaler_.ReportFramerate(codec_.maxFramerate); 5999115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 6004306fc70d778887d8a2ea71b6f4bc6a12d1d9447asapersson // Only apply scaling to improve for single-layer streams. The scaling metrics 6014306fc70d778887d8a2ea71b6f4bc6a12d1d9447asapersson // use frame drops as a signal and is only applicable when we drop frames. 6024306fc70d778887d8a2ea71b6f4bc6a12d1d9447asapersson quality_scaler_enabled_ = encoders_.size() == 1 && 6034306fc70d778887d8a2ea71b6f4bc6a12d1d9447asapersson configurations_[0].rc_dropframe_thresh > 0 && 6044306fc70d778887d8a2ea71b6f4bc6a12d1d9447asapersson codec_.codecSpecific.VP8.automaticResizeOn; 6054306fc70d778887d8a2ea71b6f4bc6a12d1d9447asapersson 6069115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return InitAndSetControlSettings(); 6079115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org} 6089115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 6096daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.orgint VP8EncoderImpl::SetCpuSpeed(int width, int height) { 610e87d48719f8478148fc6ec28c3b3663709d585a4Stefan Holmer#if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) 6116daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org // On mobile platform, always set to -12 to leverage between cpu usage 6126daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org // and video quality. 6136daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org return -12; 6146daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org#else 6156daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org // For non-ARM, increase encoding complexity (i.e., use lower speed setting) 6166daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org // if resolution is below CIF. Otherwise, keep the default/user setting 6176daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org // (|cpu_speed_default_|) set on InitEncode via codecSpecific.VP8.complexity. 6186daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org if (width * height < 352 * 288) 6196daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org return (cpu_speed_default_ < -4) ? -4 : cpu_speed_default_; 6206daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org else 6216daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org return cpu_speed_default_; 6226daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org#endif 6236daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org} 6246daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org 6259115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.orgint VP8EncoderImpl::NumberOfThreads(int width, int height, int cpus) { 6269115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (width * height >= 1920 * 1080 && cpus > 8) { 6279115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return 8; // 8 threads for 1080p on high perf machines. 6289115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } else if (width * height > 1280 * 960 && cpus >= 6) { 6299115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // 3 threads for 1080p. 6309115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return 3; 6319115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } else if (width * height > 640 * 480 && cpus >= 3) { 6329115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // 2 threads for qHD/HD. 6339115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return 2; 6349115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } else { 6359115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // 1 thread for VGA or less. 6369115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return 1; 6379115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 638470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 639470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 6409115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.orgint VP8EncoderImpl::InitAndSetControlSettings() { 6414ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org vpx_codec_flags_t flags = 0; 6424ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org flags |= VPX_CODEC_USE_OUTPUT_PARTITION; 6439115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 6449115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (encoders_.size() > 1) { 645cce46fc108a70336f0477fd58d41f38e547eeb25philipel int error = vpx_codec_enc_init_multi(&encoders_[0], vpx_codec_vp8_cx(), 646cce46fc108a70336f0477fd58d41f38e547eeb25philipel &configurations_[0], encoders_.size(), 647cce46fc108a70336f0477fd58d41f38e547eeb25philipel flags, &downsampling_factors_[0]); 6489115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (error) { 6499115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 6509115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 6519115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } else { 652cce46fc108a70336f0477fd58d41f38e547eeb25philipel if (vpx_codec_enc_init(&encoders_[0], vpx_codec_vp8_cx(), 653cce46fc108a70336f0477fd58d41f38e547eeb25philipel &configurations_[0], flags)) { 6549115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 6559115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 6564ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 6579115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Enable denoising for the highest resolution stream, and for 6589115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // the second highest resolution if we are doing more than 2 6599115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // spatial layers/streams. 6609115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // TODO(holmer): Investigate possibility of adding a libvpx API 6619115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // for getting the denoised frame from the encoder and using that 6629115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // when encoding lower resolution streams. Would it work with the 6639115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // multi-res encoding feature? 6649115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org denoiserState denoiser_state = kDenoiserOnYOnly; 665e87d48719f8478148fc6ec28c3b3663709d585a4Stefan Holmer#if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) 6669115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org denoiser_state = kDenoiserOnYOnly; 6679115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org#else 6689115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org denoiser_state = kDenoiserOnAdaptive; 669662651ac958ccc785c638f7bcf44e08f11eb95a8fbarchard@google.com#endif 670cce46fc108a70336f0477fd58d41f38e547eeb25philipel vpx_codec_control( 671cce46fc108a70336f0477fd58d41f38e547eeb25philipel &encoders_[0], VP8E_SET_NOISE_SENSITIVITY, 672cce46fc108a70336f0477fd58d41f38e547eeb25philipel codec_.codecSpecific.VP8.denoisingOn ? denoiser_state : kDenoiserOff); 6739115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (encoders_.size() > 2) { 674cce46fc108a70336f0477fd58d41f38e547eeb25philipel vpx_codec_control( 675cce46fc108a70336f0477fd58d41f38e547eeb25philipel &encoders_[1], VP8E_SET_NOISE_SENSITIVITY, 676cce46fc108a70336f0477fd58d41f38e547eeb25philipel codec_.codecSpecific.VP8.denoisingOn ? denoiser_state : kDenoiserOff); 6779115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 6789115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org for (size_t i = 0; i < encoders_.size(); ++i) { 679fb30c1b5d1effcc82a96fdf40814a03baf0727bfsprang // Allow more screen content to be detected as static. 680fb30c1b5d1effcc82a96fdf40814a03baf0727bfsprang vpx_codec_control(&(encoders_[i]), VP8E_SET_STATIC_THRESHOLD, 681fb30c1b5d1effcc82a96fdf40814a03baf0727bfsprang codec_.mode == kScreensharing ? 300 : 1); 6829115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org vpx_codec_control(&(encoders_[i]), VP8E_SET_CPUUSED, cpu_speed_[i]); 6839115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org vpx_codec_control(&(encoders_[i]), VP8E_SET_TOKEN_PARTITIONS, 6849115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org static_cast<vp8e_token_partitions>(token_partitions_)); 6859115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org vpx_codec_control(&(encoders_[i]), VP8E_SET_MAX_INTRA_BITRATE_PCT, 6869115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org rc_max_intra_target_); 6872c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng // VP8E_SET_SCREEN_CONTENT_MODE 2 = screen content with more aggressive 6882c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng // rate control (drop frames on large target bitrate overshoot) 6899115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org vpx_codec_control(&(encoders_[i]), VP8E_SET_SCREEN_CONTENT_MODE, 6902c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng codec_.mode == kScreensharing ? 2 : 0); 6919115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 6924ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org inited_ = true; 6934ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_OK; 694470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 695470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 6968d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.orguint32_t VP8EncoderImpl::MaxIntraTarget(uint32_t optimalBuffersize) { 6974ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Set max to the optimal buffer level (normalized by target BR), 6984ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // and scaled by a scalePar. 6994ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Max target size = scalePar * optimalBufferSize * targetBR[Kbps]. 7004ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // This values is presented in percentage of perFrameBw: 7014ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // perFrameBw = targetBR[Kbps] * 1000 / frameRate. 7024ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // The target in % is as follows: 7034ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org 7044ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org float scalePar = 0.5; 7054ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org uint32_t targetPct = optimalBuffersize * scalePar * codec_.maxFramerate / 10; 7064ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org 7074ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Don't go below 3 times the per frame bandwidth. 7084ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org const uint32_t minIntraTh = 300; 709cce46fc108a70336f0477fd58d41f38e547eeb25philipel return (targetPct < minIntraTh) ? minIntraTh : targetPct; 710470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 711470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 7124765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchezint VP8EncoderImpl::Encode(const VideoFrame& frame, 7134765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchez const CodecSpecificInfo* codec_specific_info, 71422993e1a0c114122fc1b9de0fc74d4096ec868bdpbos const std::vector<FrameType>* frame_types) { 7152c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng if (!inited_) 7164ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 7172c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng if (frame.IsZeroSize()) 7184ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 7192c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng if (encoded_complete_callback_ == NULL) 7204ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 72126762e3e40f682d37f33fd797383de1c7562f855marpan@webrtc.org 7224306fc70d778887d8a2ea71b6f4bc6a12d1d9447asapersson if (quality_scaler_enabled_) 7236e2ce6e1ae41d8eeb0f233cbd26087daa03ab702jackychen quality_scaler_.OnEncodeFrame(frame); 7244765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchez const VideoFrame& input_image = 7254306fc70d778887d8a2ea71b6f4bc6a12d1d9447asapersson quality_scaler_enabled_ ? quality_scaler_.GetScaledFrame(frame) : frame; 726c5300436841092d6d2b01eae1179a2c1eb373f1bstefan@webrtc.org 7274306fc70d778887d8a2ea71b6f4bc6a12d1d9447asapersson if (quality_scaler_enabled_ && (input_image.width() != codec_.width || 728cce46fc108a70336f0477fd58d41f38e547eeb25philipel input_image.height() != codec_.height)) { 7299115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org int ret = UpdateCodecFrameSize(input_image); 7309115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (ret < 0) 7319115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return ret; 7329115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 733a0d7827b1631fa8e2cf8957a76736ab159cb962apbos@webrtc.org 734e155dbeae972f788b8766b4d0d2cefde2e952a10magjed@webrtc.org // Since we are extracting raw pointers from |input_image| to 735e155dbeae972f788b8766b4d0d2cefde2e952a10magjed@webrtc.org // |raw_images_[0]|, the resolution of these frames must match. Note that 736e155dbeae972f788b8766b4d0d2cefde2e952a10magjed@webrtc.org // |input_image| might be scaled from |frame|. In that case, the resolution of 737e155dbeae972f788b8766b4d0d2cefde2e952a10magjed@webrtc.org // |raw_images_[0]| should have been updated in UpdateCodecFrameSize. 73891d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK_EQ(input_image.width(), static_cast<int>(raw_images_[0].d_w)); 73991d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK_EQ(input_image.height(), static_cast<int>(raw_images_[0].d_h)); 740e155dbeae972f788b8766b4d0d2cefde2e952a10magjed@webrtc.org 7419115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Image in vpx_image_t format. 7429115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Input image is const. VP8's raw image is not defined as const. 7439115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org raw_images_[0].planes[VPX_PLANE_Y] = 744cce46fc108a70336f0477fd58d41f38e547eeb25philipel const_cast<uint8_t*>(input_image.buffer(kYPlane)); 7459115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org raw_images_[0].planes[VPX_PLANE_U] = 746cce46fc108a70336f0477fd58d41f38e547eeb25philipel const_cast<uint8_t*>(input_image.buffer(kUPlane)); 7479115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org raw_images_[0].planes[VPX_PLANE_V] = 748cce46fc108a70336f0477fd58d41f38e547eeb25philipel const_cast<uint8_t*>(input_image.buffer(kVPlane)); 7499115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 7509115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org raw_images_[0].stride[VPX_PLANE_Y] = input_image.stride(kYPlane); 7519115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org raw_images_[0].stride[VPX_PLANE_U] = input_image.stride(kUPlane); 7529115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org raw_images_[0].stride[VPX_PLANE_V] = input_image.stride(kVPlane); 7539115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 7549115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org for (size_t i = 1; i < encoders_.size(); ++i) { 7559115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Scale the image down a number of times by downsampling factor 7569115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org libyuv::I420Scale( 757cce46fc108a70336f0477fd58d41f38e547eeb25philipel raw_images_[i - 1].planes[VPX_PLANE_Y], 758cce46fc108a70336f0477fd58d41f38e547eeb25philipel raw_images_[i - 1].stride[VPX_PLANE_Y], 759cce46fc108a70336f0477fd58d41f38e547eeb25philipel raw_images_[i - 1].planes[VPX_PLANE_U], 760cce46fc108a70336f0477fd58d41f38e547eeb25philipel raw_images_[i - 1].stride[VPX_PLANE_U], 761cce46fc108a70336f0477fd58d41f38e547eeb25philipel raw_images_[i - 1].planes[VPX_PLANE_V], 762cce46fc108a70336f0477fd58d41f38e547eeb25philipel raw_images_[i - 1].stride[VPX_PLANE_V], raw_images_[i - 1].d_w, 763cce46fc108a70336f0477fd58d41f38e547eeb25philipel raw_images_[i - 1].d_h, raw_images_[i].planes[VPX_PLANE_Y], 764cce46fc108a70336f0477fd58d41f38e547eeb25philipel raw_images_[i].stride[VPX_PLANE_Y], raw_images_[i].planes[VPX_PLANE_U], 765cce46fc108a70336f0477fd58d41f38e547eeb25philipel raw_images_[i].stride[VPX_PLANE_U], raw_images_[i].planes[VPX_PLANE_V], 766cce46fc108a70336f0477fd58d41f38e547eeb25philipel raw_images_[i].stride[VPX_PLANE_V], raw_images_[i].d_w, 767cce46fc108a70336f0477fd58d41f38e547eeb25philipel raw_images_[i].d_h, libyuv::kFilterBilinear); 7689115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 7699115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org vpx_enc_frame_flags_t flags[kMaxSimulcastStreams]; 7709115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org for (size_t i = 0; i < encoders_.size(); ++i) { 7719115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org int ret = temporal_layers_[i]->EncodeFlags(input_image.timestamp()); 77226762e3e40f682d37f33fd797383de1c7562f855marpan@webrtc.org if (ret < 0) { 7739115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Drop this frame. 7749115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return WEBRTC_VIDEO_CODEC_OK; 77526762e3e40f682d37f33fd797383de1c7562f855marpan@webrtc.org } 7769115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org flags[i] = ret; 77726762e3e40f682d37f33fd797383de1c7562f855marpan@webrtc.org } 7789115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org bool send_key_frame = false; 7799115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org for (size_t i = 0; i < key_frame_request_.size() && i < send_stream_.size(); 7809115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org ++i) { 7819115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (key_frame_request_[i] && send_stream_[i]) { 7829115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org send_key_frame = true; 7839115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org break; 7849115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 7859115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 7869115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (!send_key_frame && frame_types) { 7879115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org for (size_t i = 0; i < frame_types->size() && i < send_stream_.size(); 7889115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org ++i) { 78949e196af4060624d620297a6bc017699daa33550Peter Boström if ((*frame_types)[i] == kVideoFrameKey && send_stream_[i]) { 7909115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org send_key_frame = true; 7919115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org break; 7929115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 7939115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 7949115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 7959115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // The flag modification below (due to forced key frame, RPS, etc.,) for now 7969115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // will be the same for all encoders/spatial layers. 7979115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // TODO(marpan/holmer): Allow for key frame request to be set per encoder. 7989115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org bool only_predict_from_key_frame = false; 7999115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (send_key_frame) { 8009115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Adapt the size of the key frame when in screenshare with 1 temporal 8019115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // layer. 802cce46fc108a70336f0477fd58d41f38e547eeb25philipel if (encoders_.size() == 1 && codec_.mode == kScreensharing && 803cce46fc108a70336f0477fd58d41f38e547eeb25philipel codec_.codecSpecific.VP8.numberOfTemporalLayers <= 1) { 8049115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org const uint32_t forceKeyFrameIntraTh = 100; 8059115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org vpx_codec_control(&(encoders_[0]), VP8E_SET_MAX_INTRA_BITRATE_PCT, 8069115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org forceKeyFrameIntraTh); 8079115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 8084ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Key frame request from caller. 8094ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Will update both golden and alt-ref. 8109115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org for (size_t i = 0; i < encoders_.size(); ++i) { 8119115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org flags[i] = VPX_EFLAG_FORCE_KF; 8129115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 8139115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org std::fill(key_frame_request_.begin(), key_frame_request_.end(), false); 8149115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } else if (codec_specific_info && 815cce46fc108a70336f0477fd58d41f38e547eeb25philipel codec_specific_info->codecType == kVideoCodecVP8) { 8169115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (feedback_mode_) { 8179115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Handle RPSI and SLI messages and set up the appropriate encode flags. 8189115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org bool sendRefresh = false; 8194ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (codec_specific_info->codecSpecific.VP8.hasReceivedRPSI) { 820cce46fc108a70336f0477fd58d41f38e547eeb25philipel rps_.ReceivedRPSI(codec_specific_info->codecSpecific.VP8.pictureIdRPSI); 8214ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 8224ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (codec_specific_info->codecSpecific.VP8.hasReceivedSLI) { 8239115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org sendRefresh = rps_.ReceivedSLI(input_image.timestamp()); 8249115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 8259115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org for (size_t i = 0; i < encoders_.size(); ++i) { 8269115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org flags[i] = rps_.EncodeFlags(picture_id_[i], sendRefresh, 8279115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org input_image.timestamp()); 8289115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 8299115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } else { 8309115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (codec_specific_info->codecSpecific.VP8.hasReceivedRPSI) { 8319115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Is this our last key frame? If not ignore. 8329115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // |picture_id_| is defined per spatial stream/layer, so check that 8339115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // |RPSI| matches the last key frame from any of the spatial streams. 8349115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // If so, then all spatial streams for this encoding will predict from 8359115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // its long-term reference (last key frame). 8369115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org int RPSI = codec_specific_info->codecSpecific.VP8.pictureIdRPSI; 8379115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org for (size_t i = 0; i < encoders_.size(); ++i) { 8389115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (last_key_frame_picture_id_[i] == RPSI) { 8399115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Request for a long term reference frame. 8409115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Note 1: overwrites any temporal settings. 8419115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Note 2: VP8_EFLAG_NO_UPD_ENTROPY is not needed as that flag is 8429115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // set by error_resilient mode. 8439115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org for (size_t j = 0; j < encoders_.size(); ++j) { 8449115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org flags[j] = VP8_EFLAG_NO_UPD_ARF; 8459115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org flags[j] |= VP8_EFLAG_NO_REF_GF; 8469115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org flags[j] |= VP8_EFLAG_NO_REF_LAST; 8479115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 8489115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org only_predict_from_key_frame = true; 8499115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org break; 8509115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 8519115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 852a4a88f90c44c6ee287baccae10c7f7ff556dcb20stefan@webrtc.org } 853470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 8544ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 8559115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Set the encoder frame flags and temporal layer_id for each spatial stream. 8569115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Note that |temporal_layers_| are defined starting from lowest resolution at 8579115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // position 0 to highest resolution at position |encoders_.size() - 1|, 8589115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // whereas |encoder_| is from highest to lowest resolution. 8599115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org size_t stream_idx = encoders_.size() - 1; 8609115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org for (size_t i = 0; i < encoders_.size(); ++i, --stream_idx) { 8612c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng // Allow the layers adapter to temporarily modify the configuration. This 8622c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng // change isn't stored in configurations_ so change will be discarded at 8632c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng // the next update. 8642c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng vpx_codec_enc_cfg_t temp_config; 8652c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng memcpy(&temp_config, &configurations_[i], sizeof(vpx_codec_enc_cfg_t)); 8662c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng if (temporal_layers_[stream_idx]->UpdateConfiguration(&temp_config)) { 8672c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng if (vpx_codec_enc_config_set(&encoders_[i], &temp_config)) 8682c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng return WEBRTC_VIDEO_CODEC_ERROR; 8692c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng } 8702c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng 8719115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org vpx_codec_control(&encoders_[i], VP8E_SET_FRAME_FLAGS, flags[stream_idx]); 872cce46fc108a70336f0477fd58d41f38e547eeb25philipel vpx_codec_control(&encoders_[i], VP8E_SET_TEMPORAL_LAYER_ID, 8739115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org temporal_layers_[stream_idx]->CurrentLayerId()); 8749115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 8754ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // TODO(holmer): Ideally the duration should be the timestamp diff of this 8764ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // frame and the next frame to be encoded, which we don't have. Instead we 8774ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // would like to use the duration of the previous frame. Unfortunately the 8784ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // rate control seems to be off with that setup. Using the average input 8794ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // frame rate to calculate an average duration for now. 8804ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org assert(codec_.maxFramerate > 0); 8814ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org uint32_t duration = 90000 / codec_.maxFramerate; 8829115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org 8839115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Note we must pass 0 for |flags| field in encode call below since they are 8849115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // set above in |vpx_codec_control| function for each encoder/spatial layer. 8859115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org int error = vpx_codec_encode(&encoders_[0], &raw_images_[0], timestamp_, 8869115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org duration, 0, VPX_DL_REALTIME); 8879115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Reset specific intra frame thresholds, following the key frame. 8889115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (send_key_frame) { 8899115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org vpx_codec_control(&(encoders_[0]), VP8E_SET_MAX_INTRA_BITRATE_PCT, 890cce46fc108a70336f0477fd58d41f38e547eeb25philipel rc_max_intra_target_); 8919115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 8922c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng if (error) 8934ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERROR; 8944ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org timestamp_ += duration; 8959115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org return GetEncodedPartitions(input_image, only_predict_from_key_frame); 896c3d891059e117357011e414263af0f519313d440stefan@webrtc.org} 897c3d891059e117357011e414263af0f519313d440stefan@webrtc.org 8989115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org// TODO(pbos): Make sure this works for properly for >1 encoders. 8994765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchezint VP8EncoderImpl::UpdateCodecFrameSize(const VideoFrame& input_image) { 9003263a7a61610c9029ef9bcec6dddf50fcacd1c27mikhal@webrtc.org codec_.width = input_image.width(); 9013263a7a61610c9029ef9bcec6dddf50fcacd1c27mikhal@webrtc.org codec_.height = input_image.height(); 902110443c1ec40b764db81a6b9679885aec3e4a218Asa Persson if (codec_.numberOfSimulcastStreams <= 1) { 903110443c1ec40b764db81a6b9679885aec3e4a218Asa Persson // For now scaling is only used for single-layer streams. 904110443c1ec40b764db81a6b9679885aec3e4a218Asa Persson codec_.simulcastStream[0].width = input_image.width(); 905110443c1ec40b764db81a6b9679885aec3e4a218Asa Persson codec_.simulcastStream[0].height = input_image.height(); 906110443c1ec40b764db81a6b9679885aec3e4a218Asa Persson } 9076daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org // Update the cpu_speed setting for resolution change. 908cce46fc108a70336f0477fd58d41f38e547eeb25philipel vpx_codec_control(&(encoders_[0]), VP8E_SET_CPUUSED, 9096daacbc8aea2e3e14a320b28502c4dc1db21d175marpan@webrtc.org SetCpuSpeed(codec_.width, codec_.height)); 9109115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org raw_images_[0].w = codec_.width; 9119115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org raw_images_[0].h = codec_.height; 9129115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org raw_images_[0].d_w = codec_.width; 9139115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org raw_images_[0].d_h = codec_.height; 9149115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org vpx_img_set_rect(&raw_images_[0], 0, 0, codec_.width, codec_.height); 91526762e3e40f682d37f33fd797383de1c7562f855marpan@webrtc.org 91626762e3e40f682d37f33fd797383de1c7562f855marpan@webrtc.org // Update encoder context for new frame size. 91726762e3e40f682d37f33fd797383de1c7562f855marpan@webrtc.org // Change of frame size will automatically trigger a key frame. 9189115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].g_w = codec_.width; 9199115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org configurations_[0].g_h = codec_.height; 9209115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (vpx_codec_enc_config_set(&encoders_[0], &configurations_[0])) { 92126762e3e40f682d37f33fd797383de1c7562f855marpan@webrtc.org return WEBRTC_VIDEO_CODEC_ERROR; 92226762e3e40f682d37f33fd797383de1c7562f855marpan@webrtc.org } 92326762e3e40f682d37f33fd797383de1c7562f855marpan@webrtc.org return WEBRTC_VIDEO_CODEC_OK; 92426762e3e40f682d37f33fd797383de1c7562f855marpan@webrtc.org} 92526762e3e40f682d37f33fd797383de1c7562f855marpan@webrtc.org 9269115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.orgvoid VP8EncoderImpl::PopulateCodecSpecific( 9279115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org CodecSpecificInfo* codec_specific, 9289115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org const vpx_codec_cx_pkt_t& pkt, 9299115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org int stream_idx, 9309115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org uint32_t timestamp, 9319115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org bool only_predicting_from_key_frame) { 932c3d891059e117357011e414263af0f519313d440stefan@webrtc.org assert(codec_specific != NULL); 933c3d891059e117357011e414263af0f519313d440stefan@webrtc.org codec_specific->codecType = kVideoCodecVP8; 9349115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org CodecSpecificInfoVP8* vp8Info = &(codec_specific->codecSpecific.VP8); 9359115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org vp8Info->pictureId = picture_id_[stream_idx]; 9369115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (pkt.data.frame.flags & VPX_FRAME_IS_KEY) { 9379115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org last_key_frame_picture_id_[stream_idx] = picture_id_[stream_idx]; 9389115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 9399115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org vp8Info->simulcastIdx = stream_idx; 940859626570a75caa06346e112d1b6b2628f11074fhenrik.lundin@webrtc.org vp8Info->keyIdx = kNoKeyIdx; // TODO(hlundin) populate this 941cce46fc108a70336f0477fd58d41f38e547eeb25philipel vp8Info->nonReference = 942cce46fc108a70336f0477fd58d41f38e547eeb25philipel (pkt.data.frame.flags & VPX_FRAME_IS_DROPPABLE) ? true : false; 9439115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org bool base_layer_sync_point = (pkt.data.frame.flags & VPX_FRAME_IS_KEY) || 944cce46fc108a70336f0477fd58d41f38e547eeb25philipel only_predicting_from_key_frame; 9459115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org temporal_layers_[stream_idx]->PopulateCodecSpecific(base_layer_sync_point, 946cce46fc108a70336f0477fd58d41f38e547eeb25philipel vp8Info, timestamp); 9479115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Prepare next. 9489115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org picture_id_[stream_idx] = (picture_id_[stream_idx] + 1) & 0x7FFF; 949c3d891059e117357011e414263af0f519313d440stefan@webrtc.org} 950c3d891059e117357011e414263af0f519313d440stefan@webrtc.org 9514765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchezint VP8EncoderImpl::GetEncodedPartitions(const VideoFrame& input_image, 9524765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchez bool only_predicting_from_key_frame) { 953da535c405597864b8396b2029dec70ab9fb76e8basapersson int bw_resolutions_disabled = 954da535c405597864b8396b2029dec70ab9fb76e8basapersson (encoders_.size() > 1) ? NumStreamsDisabled(send_stream_) : -1; 955da535c405597864b8396b2029dec70ab9fb76e8basapersson 9569115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org int stream_idx = static_cast<int>(encoders_.size()) - 1; 9572c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng int result = WEBRTC_VIDEO_CODEC_OK; 9589115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org for (size_t encoder_idx = 0; encoder_idx < encoders_.size(); 959cce46fc108a70336f0477fd58d41f38e547eeb25philipel ++encoder_idx, --stream_idx) { 9609115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org vpx_codec_iter_t iter = NULL; 9619115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org int part_idx = 0; 9629115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org encoded_images_[encoder_idx]._length = 0; 96349e196af4060624d620297a6bc017699daa33550Peter Boström encoded_images_[encoder_idx]._frameType = kVideoFrameDelta; 9649115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org RTPFragmentationHeader frag_info; 9659115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // token_partitions_ is number of bits used. 966cce46fc108a70336f0477fd58d41f38e547eeb25philipel frag_info.VerifyAndAllocateFragmentationHeader((1 << token_partitions_) + 967cce46fc108a70336f0477fd58d41f38e547eeb25philipel 1); 9689115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org CodecSpecificInfo codec_specific; 969cce46fc108a70336f0477fd58d41f38e547eeb25philipel const vpx_codec_cx_pkt_t* pkt = NULL; 970cce46fc108a70336f0477fd58d41f38e547eeb25philipel while ((pkt = vpx_codec_get_cx_data(&encoders_[encoder_idx], &iter)) != 971cce46fc108a70336f0477fd58d41f38e547eeb25philipel NULL) { 9729115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org switch (pkt->kind) { 9739115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org case VPX_CODEC_CX_FRAME_PKT: { 9749115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org uint32_t length = encoded_images_[encoder_idx]._length; 9759115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org memcpy(&encoded_images_[encoder_idx]._buffer[length], 976cce46fc108a70336f0477fd58d41f38e547eeb25philipel pkt->data.frame.buf, pkt->data.frame.sz); 9779115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org frag_info.fragmentationOffset[part_idx] = length; 978cce46fc108a70336f0477fd58d41f38e547eeb25philipel frag_info.fragmentationLength[part_idx] = pkt->data.frame.sz; 9799115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org frag_info.fragmentationPlType[part_idx] = 0; // not known here 9809115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org frag_info.fragmentationTimeDiff[part_idx] = 0; 9819115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org encoded_images_[encoder_idx]._length += pkt->data.frame.sz; 9829115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org assert(length <= encoded_images_[encoder_idx]._size); 9839115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org ++part_idx; 9849115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org break; 9859115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 9869115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org default: 9879115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org break; 988c3d891059e117357011e414263af0f519313d440stefan@webrtc.org } 9899115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // End of frame 9909115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if ((pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT) == 0) { 9919115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // check if encoded frame is a key frame 9929115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) { 99349e196af4060624d620297a6bc017699daa33550Peter Boström encoded_images_[encoder_idx]._frameType = kVideoFrameKey; 9949115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org rps_.EncodedKeyFrame(picture_id_[stream_idx]); 9959115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 9969115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org PopulateCodecSpecific(&codec_specific, *pkt, stream_idx, 9979115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org input_image.timestamp(), 9989115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org only_predicting_from_key_frame); 999c3d891059e117357011e414263af0f519313d440stefan@webrtc.org break; 1000c3d891059e117357011e414263af0f519313d440stefan@webrtc.org } 1001c3d891059e117357011e414263af0f519313d440stefan@webrtc.org } 10029115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org encoded_images_[encoder_idx]._timeStamp = input_image.timestamp(); 10039115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org encoded_images_[encoder_idx].capture_time_ms_ = 10049115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org input_image.render_time_ms(); 10052c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng 10062c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng int qp = -1; 10072c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng vpx_codec_control(&encoders_[encoder_idx], VP8E_GET_LAST_QUANTIZER_64, &qp); 10089115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org temporal_layers_[stream_idx]->FrameEncoded( 10099115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org encoded_images_[encoder_idx]._length, 10102c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng encoded_images_[encoder_idx]._timeStamp, qp); 10119115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (send_stream_[stream_idx]) { 10129115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (encoded_images_[encoder_idx]._length > 0) { 10139115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org TRACE_COUNTER_ID1("webrtc", "EncodedFrameSize", encoder_idx, 10149115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org encoded_images_[encoder_idx]._length); 10159115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org encoded_images_[encoder_idx]._encodedHeight = 10169115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org codec_.simulcastStream[stream_idx].height; 10179115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org encoded_images_[encoder_idx]._encodedWidth = 10189115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org codec_.simulcastStream[stream_idx].width; 10194306fc70d778887d8a2ea71b6f4bc6a12d1d9447asapersson encoded_images_[encoder_idx] 10204306fc70d778887d8a2ea71b6f4bc6a12d1d9447asapersson .adapt_reason_.quality_resolution_downscales = 10214306fc70d778887d8a2ea71b6f4bc6a12d1d9447asapersson quality_scaler_enabled_ ? quality_scaler_.downscale_shift() : -1; 1022da535c405597864b8396b2029dec70ab9fb76e8basapersson // Report once per frame (lowest stream always sent). 1023da535c405597864b8396b2029dec70ab9fb76e8basapersson encoded_images_[encoder_idx].adapt_reason_.bw_resolutions_disabled = 1024da535c405597864b8396b2029dec70ab9fb76e8basapersson (stream_idx == 0) ? bw_resolutions_disabled : -1; 10259115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org encoded_complete_callback_->Encoded(encoded_images_[encoder_idx], 10269115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org &codec_specific, &frag_info); 10272c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng } else if (codec_.mode == kScreensharing) { 10282c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng result = WEBRTC_VIDEO_CODEC_TARGET_BITRATE_OVERSHOOT; 1029c3d891059e117357011e414263af0f519313d440stefan@webrtc.org } 1030c3d891059e117357011e414263af0f519313d440stefan@webrtc.org } 1031c3d891059e117357011e414263af0f519313d440stefan@webrtc.org } 10329115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (encoders_.size() == 1 && send_stream_[0]) { 10339115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (encoded_images_[0]._length > 0) { 10349115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org int qp; 10359115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org vpx_codec_control(&encoders_[0], VP8E_GET_LAST_QUANTIZER_64, &qp); 103698d8cf58ee8c7c7b0672ce7955313a31824d6f3ajackychen quality_scaler_.ReportQP(qp); 10379115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } else { 10389115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org quality_scaler_.ReportDroppedFrame(); 10399115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 10400c2adf0b75e74bbd0af0970c913f240b3b4947c3stefan@webrtc.org } 10412c4c9148191a10c0e82c9a209d454c6b1ebbaf20Erik Språng return result; 1042c3d891059e117357011e414263af0f519313d440stefan@webrtc.org} 1043c3d891059e117357011e414263af0f519313d440stefan@webrtc.org 104416825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.orgint VP8EncoderImpl::SetChannelParameters(uint32_t packetLoss, int64_t rtt) { 10459115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org rps_.SetRtt(rtt); 1046a4a88f90c44c6ee287baccae10c7f7ff556dcb20stefan@webrtc.org return WEBRTC_VIDEO_CODEC_OK; 1047470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1048470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 10498d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.orgint VP8EncoderImpl::RegisterEncodeCompleteCallback( 10504ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org EncodedImageCallback* callback) { 10514ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org encoded_complete_callback_ = callback; 10524ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_OK; 1053470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1054470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 10558d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.orgVP8DecoderImpl::VP8DecoderImpl() 10564ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org : decode_complete_callback_(NULL), 10574ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org inited_(false), 10584ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org feedback_mode_(false), 10594ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org decoder_(NULL), 10604ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org last_keyframe_(), 10614ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org image_format_(VPX_IMG_FMT_NONE), 10624ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org ref_frame_(NULL), 10634ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org propagation_cnt_(-1), 10649115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org last_frame_width_(0), 10659115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org last_frame_height_(0), 1066cce46fc108a70336f0477fd58d41f38e547eeb25philipel key_frame_required_(true) {} 1067470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 10688d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.orgVP8DecoderImpl::~VP8DecoderImpl() { 10698d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.org inited_ = true; // in order to do the actual release 10704ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org Release(); 1071470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1072470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 10738d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.orgint VP8DecoderImpl::Reset() { 10744ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (!inited_) { 10754ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 10764ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 10774ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org InitDecode(&codec_, 1); 10784ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org propagation_cnt_ = -1; 10794ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_OK; 10804ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org} 1081470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1082cce46fc108a70336f0477fd58d41f38e547eeb25philipelint VP8DecoderImpl::InitDecode(const VideoCodec* inst, int number_of_cores) { 10834ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org int ret_val = Release(); 10848d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.org if (ret_val < 0) { 10854ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return ret_val; 10864ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 10874ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (decoder_ == NULL) { 10889115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org decoder_ = new vpx_codec_ctx_t; 10894ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 10909115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (inst && inst->codecType == kVideoCodecVP8) { 10914ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org feedback_mode_ = inst->codecSpecific.VP8.feedbackModeOn; 10924ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 1093cce46fc108a70336f0477fd58d41f38e547eeb25philipel vpx_codec_dec_cfg_t cfg; 10944ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Setting number of threads to a constant value (1) 10954ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org cfg.threads = 1; 10968d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.org cfg.h = cfg.w = 0; // set after decode 1097470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1098cce46fc108a70336f0477fd58d41f38e547eeb25philipel vpx_codec_flags_t flags = 0; 1099e87d48719f8478148fc6ec28c3b3663709d585a4Stefan Holmer#if !defined(WEBRTC_ARCH_ARM) && !defined(WEBRTC_ARCH_ARM64) 1100dc257b578188c0bd4a3ee153b42cc7558f725bb9stefan@webrtc.org flags = VPX_CODEC_USE_POSTPROC; 1101c3d891059e117357011e414263af0f519313d440stefan@webrtc.org#ifdef INDEPENDENT_PARTITIONS 11024ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org flags |= VPX_CODEC_USE_INPUT_PARTITION; 1103c3d891059e117357011e414263af0f519313d440stefan@webrtc.org#endif 11046724cf8183f30408a483639db4c622456b94f656mikhal@webrtc.org#endif 11052cdc7b94d2784121c57aa4e7062c5a3468f3a701holmer@google.com 11064ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (vpx_codec_dec_init(decoder_, vpx_codec_vp8_dx(), &cfg, flags)) { 11074ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_MEMORY; 11084ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 1109470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 11109115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Save VideoCodec instance for later; mainly for duplicating the decoder. 11119115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (&codec_ != inst) 1112d25b602dc0e70282e1f0223e5909534fa81053f0pbos@webrtc.org codec_ = *inst; 11134ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org propagation_cnt_ = -1; 1114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 11154ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org inited_ = true; 1116b2c28c3699f701e2e3e51ea1d361a2f66cf5f4e2mikhal@webrtc.org 1117b2c28c3699f701e2e3e51ea1d361a2f66cf5f4e2mikhal@webrtc.org // Always start with a complete key frame. 1118b2c28c3699f701e2e3e51ea1d361a2f66cf5f4e2mikhal@webrtc.org key_frame_required_ = true; 11194ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_OK; 1120470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1121470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 11228d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.orgint VP8DecoderImpl::Decode(const EncodedImage& input_image, 1123cce46fc108a70336f0477fd58d41f38e547eeb25philipel bool missing_frames, 1124cce46fc108a70336f0477fd58d41f38e547eeb25philipel const RTPFragmentationHeader* fragmentation, 1125cce46fc108a70336f0477fd58d41f38e547eeb25philipel const CodecSpecificInfo* codec_specific_info, 1126cce46fc108a70336f0477fd58d41f38e547eeb25philipel int64_t /*render_time_ms*/) { 11274ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (!inited_) { 11284ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 11294ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 11304ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (decode_complete_callback_ == NULL) { 11314ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 11324ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 11334ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (input_image._buffer == NULL && input_image._length > 0) { 11344ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Reset to avoid requesting key frames too often. 11354ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (propagation_cnt_ > 0) 11364ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org propagation_cnt_ = 0; 11374ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 11384ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 11394c059d87b3cd38495479d649ce716054815ecfc8stefan@webrtc.org 1140c3d891059e117357011e414263af0f519313d440stefan@webrtc.org#ifdef INDEPENDENT_PARTITIONS 11414ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (fragmentation == NULL) { 11424ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 11434ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 1144c3d891059e117357011e414263af0f519313d440stefan@webrtc.org#endif 1145a1ec48dec2ec49dfa0f3e84a6d4362fcb478bcf0marpan@google.com 1146e87d48719f8478148fc6ec28c3b3663709d585a4Stefan Holmer#if !defined(WEBRTC_ARCH_ARM) && !defined(WEBRTC_ARCH_ARM64) 11479115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org vp8_postproc_cfg_t ppcfg; 11489115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // MFQE enabled to reduce key frame popping. 11499115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org ppcfg.post_proc_flag = VP8_MFQE | VP8_DEBLOCK; 11509115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // For VGA resolutions and lower, enable the demacroblocker postproc. 11519115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (last_frame_width_ * last_frame_height_ <= 640 * 360) { 11529115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org ppcfg.post_proc_flag |= VP8_DEMACROBLOCK; 11531bb1da4c30ca92c7164fbfa4447f94eaacd60852stefan@webrtc.org } 11549115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Strength of deblocking filter. Valid range:[0,16] 11559115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org ppcfg.deblocking_level = 3; 11569115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org vpx_codec_control(decoder_, VP8_SET_POSTPROC, &ppcfg); 11571bb1da4c30ca92c7164fbfa4447f94eaacd60852stefan@webrtc.org#endif 11581bb1da4c30ca92c7164fbfa4447f94eaacd60852stefan@webrtc.org 1159b2c28c3699f701e2e3e51ea1d361a2f66cf5f4e2mikhal@webrtc.org // Always start with a complete key frame. 1160b2c28c3699f701e2e3e51ea1d361a2f66cf5f4e2mikhal@webrtc.org if (key_frame_required_) { 116149e196af4060624d620297a6bc017699daa33550Peter Boström if (input_image._frameType != kVideoFrameKey) 1162b2c28c3699f701e2e3e51ea1d361a2f66cf5f4e2mikhal@webrtc.org return WEBRTC_VIDEO_CODEC_ERROR; 1163b2c28c3699f701e2e3e51ea1d361a2f66cf5f4e2mikhal@webrtc.org // We have a key frame - is it complete? 1164b2c28c3699f701e2e3e51ea1d361a2f66cf5f4e2mikhal@webrtc.org if (input_image._completeFrame) { 1165b2c28c3699f701e2e3e51ea1d361a2f66cf5f4e2mikhal@webrtc.org key_frame_required_ = false; 1166b2c28c3699f701e2e3e51ea1d361a2f66cf5f4e2mikhal@webrtc.org } else { 1167b2c28c3699f701e2e3e51ea1d361a2f66cf5f4e2mikhal@webrtc.org return WEBRTC_VIDEO_CODEC_ERROR; 1168b2c28c3699f701e2e3e51ea1d361a2f66cf5f4e2mikhal@webrtc.org } 1169b2c28c3699f701e2e3e51ea1d361a2f66cf5f4e2mikhal@webrtc.org } 11704ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Restrict error propagation using key frame requests. Disabled when 11714ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // the feedback mode is enabled (RPS). 11724ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Reset on a key frame refresh. 11734ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (!feedback_mode_) { 117449e196af4060624d620297a6bc017699daa33550Peter Boström if (input_image._frameType == kVideoFrameKey && 117549e196af4060624d620297a6bc017699daa33550Peter Boström input_image._completeFrame) { 11764ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org propagation_cnt_ = -1; 1177cce46fc108a70336f0477fd58d41f38e547eeb25philipel // Start count on first loss. 11789115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } else if ((!input_image._completeFrame || missing_frames) && 1179cce46fc108a70336f0477fd58d41f38e547eeb25philipel propagation_cnt_ == -1) { 11804ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org propagation_cnt_ = 0; 11819115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 11829115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (propagation_cnt_ >= 0) { 11834ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org propagation_cnt_++; 11849115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 11854ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 1186ffd28f95c5f7a7c23a14cecb82f02b4b85eda658stefan@webrtc.org 1187f5d934dfd8e25c8ac1fdecb1f2b829d175f436a9stefan@webrtc.org vpx_codec_iter_t iter = NULL; 11884ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org vpx_image_t* img; 11894ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org int ret; 11904ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org 11914ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Check for missing frames. 11924ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (missing_frames) { 11934ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Call decoder with zero data length to signal missing frames. 11944ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (vpx_codec_decode(decoder_, NULL, 0, 0, VPX_DL_REALTIME)) { 11954ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Reset to avoid requesting key frames too often. 11964ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (propagation_cnt_ > 0) 11974ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org propagation_cnt_ = 0; 11984ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERROR; 1199470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 12009115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org img = vpx_codec_get_frame(decoder_, &iter); 12014ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org iter = NULL; 12024ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 1203470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1204c3d891059e117357011e414263af0f519313d440stefan@webrtc.org#ifdef INDEPENDENT_PARTITIONS 12054ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (DecodePartitions(inputImage, fragmentation)) { 12064ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Reset to avoid requesting key frames too often. 12074ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (propagation_cnt_ > 0) { 12084ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org propagation_cnt_ = 0; 1209c3d891059e117357011e414263af0f519313d440stefan@webrtc.org } 12104ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERROR; 12114ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 1212c3d891059e117357011e414263af0f519313d440stefan@webrtc.org#else 12134ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org uint8_t* buffer = input_image._buffer; 12144ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (input_image._length == 0) { 12158d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.org buffer = NULL; // Triggers full frame concealment. 12164ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 12179115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (vpx_codec_decode(decoder_, buffer, input_image._length, 0, 12184ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org VPX_DL_REALTIME)) { 12194ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Reset to avoid requesting key frames too often. 12209115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (propagation_cnt_ > 0) { 12214ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org propagation_cnt_ = 0; 12229115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 12234ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERROR; 12244ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 1225c3d891059e117357011e414263af0f519313d440stefan@webrtc.org#endif 1226470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 12274ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Store encoded frame if key frame. (Used in Copy method.) 122849e196af4060624d620297a6bc017699daa33550Peter Boström if (input_image._frameType == kVideoFrameKey && input_image._buffer != NULL) { 12294ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org const uint32_t bytes_to_copy = input_image._length; 12304ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (last_keyframe_._size < bytes_to_copy) { 1231cce46fc108a70336f0477fd58d41f38e547eeb25philipel delete[] last_keyframe_._buffer; 12324ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org last_keyframe_._buffer = NULL; 12334ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org last_keyframe_._size = 0; 12344ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 12358d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.org uint8_t* temp_buffer = last_keyframe_._buffer; // Save buffer ptr. 1236cce46fc108a70336f0477fd58d41f38e547eeb25philipel uint32_t temp_size = last_keyframe_._size; // Save size. 1237cce46fc108a70336f0477fd58d41f38e547eeb25philipel last_keyframe_ = input_image; // Shallow copy. 1238cce46fc108a70336f0477fd58d41f38e547eeb25philipel last_keyframe_._buffer = temp_buffer; // Restore buffer ptr. 1239cce46fc108a70336f0477fd58d41f38e547eeb25philipel last_keyframe_._size = temp_size; // Restore buffer size. 12404ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (!last_keyframe_._buffer) { 12414ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Allocate memory. 12424ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org last_keyframe_._size = bytes_to_copy; 12434ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org last_keyframe_._buffer = new uint8_t[last_keyframe_._size]; 12444ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 12454ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Copy encoded frame. 12464ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org memcpy(last_keyframe_._buffer, input_image._buffer, bytes_to_copy); 12474ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org last_keyframe_._length = bytes_to_copy; 12484ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 1249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 12504ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org img = vpx_codec_get_frame(decoder_, &iter); 12516c75c989648018a1537bb29d41fbcb730b143c15wu@webrtc.org ret = ReturnFrame(img, input_image._timeStamp, input_image.ntp_time_ms_); 12524ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (ret != 0) { 12534ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Reset to avoid requesting key frames too often. 12544ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (ret < 0 && propagation_cnt_ > 0) 12554ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org propagation_cnt_ = 0; 12564ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return ret; 12574ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 12584ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (feedback_mode_) { 12594ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Whenever we receive an incomplete key frame all reference buffers will 12604ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // be corrupt. If that happens we must request new key frames until we 12619115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // decode a complete key frame. 126249e196af4060624d620297a6bc017699daa33550Peter Boström if (input_image._frameType == kVideoFrameKey && !input_image._completeFrame) 12634ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERROR; 12644ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Check for reference updates and last reference buffer corruption and 12654ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // signal successful reference propagation or frame corruption to the 12664ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // encoder. 12674ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org int reference_updates = 0; 12684ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (vpx_codec_control(decoder_, VP8D_GET_LAST_REF_UPDATES, 12694ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org &reference_updates)) { 12704ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Reset to avoid requesting key frames too often. 12719115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org if (propagation_cnt_ > 0) { 12724ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org propagation_cnt_ = 0; 12739115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org } 12744ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERROR; 12754ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 12764ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org int corrupted = 0; 12774ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (vpx_codec_control(decoder_, VP8D_GET_FRAME_CORRUPTED, &corrupted)) { 12784ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Reset to avoid requesting key frames too often. 12794ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (propagation_cnt_ > 0) 12804ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org propagation_cnt_ = 0; 12814ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERROR; 12824ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 12834ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org int16_t picture_id = -1; 12844ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (codec_specific_info) { 12854ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org picture_id = codec_specific_info->codecSpecific.VP8.pictureId; 12864ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 12874ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (picture_id > -1) { 12884ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (((reference_updates & VP8_GOLD_FRAME) || 1289cce46fc108a70336f0477fd58d41f38e547eeb25philipel (reference_updates & VP8_ALTR_FRAME)) && 1290cce46fc108a70336f0477fd58d41f38e547eeb25philipel !corrupted) { 12914ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org decode_complete_callback_->ReceivedDecodedReferenceFrame(picture_id); 1292a4a88f90c44c6ee287baccae10c7f7ff556dcb20stefan@webrtc.org } 12934ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org decode_complete_callback_->ReceivedDecodedFrame(picture_id); 1294470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 12954ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (corrupted) { 12964ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // we can decode but with artifacts 12974ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_REQUEST_SLI; 1298ffd28f95c5f7a7c23a14cecb82f02b4b85eda658stefan@webrtc.org } 12994ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 13004ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Check Vs. threshold 13014ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (propagation_cnt_ > kVp8ErrorPropagationTh) { 13024ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Reset to avoid requesting key frames too often. 13034ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org propagation_cnt_ = 0; 13044ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_ERROR; 13054ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 13064ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_OK; 1307c3d891059e117357011e414263af0f519313d440stefan@webrtc.org} 1308c3d891059e117357011e414263af0f519313d440stefan@webrtc.org 13098d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.orgint VP8DecoderImpl::DecodePartitions( 13104ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org const EncodedImage& input_image, 13114ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org const RTPFragmentationHeader* fragmentation) { 1312c3d891059e117357011e414263af0f519313d440stefan@webrtc.org for (int i = 0; i < fragmentation->fragmentationVectorSize; ++i) { 1313cce46fc108a70336f0477fd58d41f38e547eeb25philipel const uint8_t* partition = 1314cce46fc108a70336f0477fd58d41f38e547eeb25philipel input_image._buffer + fragmentation->fragmentationOffset[i]; 1315cce46fc108a70336f0477fd58d41f38e547eeb25philipel const uint32_t partition_length = fragmentation->fragmentationLength[i]; 1316cce46fc108a70336f0477fd58d41f38e547eeb25philipel if (vpx_codec_decode(decoder_, partition, partition_length, 0, 1317c3d891059e117357011e414263af0f519313d440stefan@webrtc.org VPX_DL_REALTIME)) { 13184c059d87b3cd38495479d649ce716054815ecfc8stefan@webrtc.org return WEBRTC_VIDEO_CODEC_ERROR; 1319c3d891059e117357011e414263af0f519313d440stefan@webrtc.org } 1320c3d891059e117357011e414263af0f519313d440stefan@webrtc.org } 13214c059d87b3cd38495479d649ce716054815ecfc8stefan@webrtc.org // Signal end of frame data. If there was no frame data this will trigger 13224c059d87b3cd38495479d649ce716054815ecfc8stefan@webrtc.org // a full frame concealment. 13234ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (vpx_codec_decode(decoder_, NULL, 0, 0, VPX_DL_REALTIME)) 1324c3d891059e117357011e414263af0f519313d440stefan@webrtc.org return WEBRTC_VIDEO_CODEC_ERROR; 1325c3d891059e117357011e414263af0f519313d440stefan@webrtc.org return WEBRTC_VIDEO_CODEC_OK; 132693d216c23faaa509b798dc8f2d2b58b30714cd1estefan@webrtc.org} 132793d216c23faaa509b798dc8f2d2b58b30714cd1estefan@webrtc.org 13286c75c989648018a1537bb29d41fbcb730b143c15wu@webrtc.orgint VP8DecoderImpl::ReturnFrame(const vpx_image_t* img, 1329cce46fc108a70336f0477fd58d41f38e547eeb25philipel uint32_t timestamp, 1330cce46fc108a70336f0477fd58d41f38e547eeb25philipel int64_t ntp_time_ms) { 13314ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (img == NULL) { 13324ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Decoder OK and NULL image => No show frame 13334ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_NO_OUTPUT; 13344ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 13359115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org last_frame_width_ = img->d_w; 13369115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org last_frame_height_ = img->d_h; 13379115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.org // Allocate memory for decoded image. 13384765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchez VideoFrame decoded_image(buffer_pool_.CreateBuffer(img->d_w, img->d_h), 13394765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchez timestamp, 0, kVideoRotation_0); 1340cce46fc108a70336f0477fd58d41f38e547eeb25philipel libyuv::I420Copy(img->planes[VPX_PLANE_Y], img->stride[VPX_PLANE_Y], 1341cce46fc108a70336f0477fd58d41f38e547eeb25philipel img->planes[VPX_PLANE_U], img->stride[VPX_PLANE_U], 1342cce46fc108a70336f0477fd58d41f38e547eeb25philipel img->planes[VPX_PLANE_V], img->stride[VPX_PLANE_V], 1343cce46fc108a70336f0477fd58d41f38e547eeb25philipel decoded_image.buffer(kYPlane), decoded_image.stride(kYPlane), 1344cce46fc108a70336f0477fd58d41f38e547eeb25philipel decoded_image.buffer(kUPlane), decoded_image.stride(kUPlane), 1345cce46fc108a70336f0477fd58d41f38e547eeb25philipel decoded_image.buffer(kVPlane), decoded_image.stride(kVPlane), 1346cce46fc108a70336f0477fd58d41f38e547eeb25philipel img->d_w, img->d_h); 134773d763e71f5c77cac82aa65d737e64d893f190a0magjed@webrtc.org decoded_image.set_ntp_time_ms(ntp_time_ms); 134873d763e71f5c77cac82aa65d737e64d893f190a0magjed@webrtc.org int ret = decode_complete_callback_->Decoded(decoded_image); 13494ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (ret != 0) 13504ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return ret; 13514ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org 13524ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // Remember image format for later 13534ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org image_format_ = img->fmt; 13544ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_OK; 1355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1356470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 13578d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.orgint VP8DecoderImpl::RegisterDecodeCompleteCallback( 13584ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org DecodedImageCallback* callback) { 13594ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org decode_complete_callback_ = callback; 13604ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_OK; 1361470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1362470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 13638d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.orgint VP8DecoderImpl::Release() { 13644ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (last_keyframe_._buffer != NULL) { 1365cce46fc108a70336f0477fd58d41f38e547eeb25philipel delete[] last_keyframe_._buffer; 13664ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org last_keyframe_._buffer = NULL; 13674ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 13684ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (decoder_ != NULL) { 13698d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.org if (vpx_codec_destroy(decoder_)) { 13704ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_MEMORY; 1371470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 13724ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org delete decoder_; 13734ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org decoder_ = NULL; 13744ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 13754ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org if (ref_frame_ != NULL) { 13764ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org vpx_img_free(&ref_frame_->img); 13774ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org delete ref_frame_; 13784ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org ref_frame_ = NULL; 13794ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 1380a3209a2b27b7bf2059f8119a126a1b1be9f0377fpbos@webrtc.org buffer_pool_.Release(); 13814ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org inited_ = false; 13824ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return WEBRTC_VIDEO_CODEC_OK; 1383470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1385b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boströmconst char* VP8DecoderImpl::ImplementationName() const { 1386b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström return "libvpx"; 1387b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström} 1388b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström 13899115cde6c9c8f5d749b349d7d10a570e4cb32803pbos@webrtc.orgint VP8DecoderImpl::CopyReference(VP8DecoderImpl* copy) { 13904ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // The type of frame to copy should be set in ref_frame_->frame_type 13914ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org // before the call to this function. 1392cce46fc108a70336f0477fd58d41f38e547eeb25philipel if (vpx_codec_control(decoder_, VP8_COPY_REFERENCE, ref_frame_) != 1393cce46fc108a70336f0477fd58d41f38e547eeb25philipel VPX_CODEC_OK) { 13944ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return -1; 13954ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 1396cce46fc108a70336f0477fd58d41f38e547eeb25philipel if (vpx_codec_control(copy->decoder_, VP8_SET_REFERENCE, ref_frame_) != 1397cce46fc108a70336f0477fd58d41f38e547eeb25philipel VPX_CODEC_OK) { 13984ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return -1; 13994ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org } 14004ea57e5e26eb91812826903753e7260654bd42d9pwestin@webrtc.org return 0; 1401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1402470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 14038d89b58d65f1b59f5ea758142ae28de323276229pwestin@webrtc.org} // namespace webrtc 1404