blob: 87609b84ba9591e9d75e36a73bc1e4719186fba5 [file] [log] [blame]
Niels Möllerf9063782018-02-20 16:09:48 +01001/*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "modules/video_coding/decoder_database.h"
12#if defined(USE_BUILTIN_SW_CODECS)
13#include "modules/video_coding/codecs/h264/include/h264.h"
14#include "modules/video_coding/codecs/i420/include/i420.h" // nogncheck
15#include "modules/video_coding/codecs/vp8/include/vp8.h" // nogncheck
16#include "modules/video_coding/codecs/vp9/include/vp9.h" // nogncheck
17#endif
18#include "rtc_base/checks.h"
19#include "rtc_base/logging.h"
20
21namespace webrtc {
22
23#if defined(USE_BUILTIN_SW_CODECS)
24// Create an internal Decoder given a codec type
25static std::unique_ptr<VCMGenericDecoder> CreateDecoder(VideoCodecType type) {
26 switch (type) {
27 case kVideoCodecVP8:
28 return std::unique_ptr<VCMGenericDecoder>(
29 new VCMGenericDecoder(VP8Decoder::Create()));
30 case kVideoCodecVP9:
31 return std::unique_ptr<VCMGenericDecoder>(
32 new VCMGenericDecoder(VP9Decoder::Create()));
33 case kVideoCodecI420:
34 return std::unique_ptr<VCMGenericDecoder>(
35 new VCMGenericDecoder(new I420Decoder()));
36 case kVideoCodecH264:
37 if (H264Decoder::IsSupported()) {
38 return std::unique_ptr<VCMGenericDecoder>(
39 new VCMGenericDecoder(H264Decoder::Create()));
40 }
41 break;
42 default:
43 break;
44 }
45 RTC_LOG(LS_WARNING) << "No internal decoder of this type exists.";
46 return std::unique_ptr<VCMGenericDecoder>();
47}
48#endif
49
50VCMDecoderMapItem::VCMDecoderMapItem(VideoCodec* settings,
51 int number_of_cores,
52 bool require_key_frame)
53 : settings(settings),
54 number_of_cores(number_of_cores),
55 require_key_frame(require_key_frame) {
56 RTC_DCHECK_GE(number_of_cores, 0);
57}
58
59VCMExtDecoderMapItem::VCMExtDecoderMapItem(
60 VideoDecoder* external_decoder_instance,
61 uint8_t payload_type)
62 : payload_type(payload_type),
63 external_decoder_instance(external_decoder_instance) {}
64
65VCMDecoderDataBase::VCMDecoderDataBase()
66 : receive_codec_(), dec_map_(), dec_external_map_() {}
67
68VCMDecoderDataBase::~VCMDecoderDataBase() {
69 ptr_decoder_.reset();
70 for (auto& kv : dec_map_)
71 delete kv.second;
72 for (auto& kv : dec_external_map_)
73 delete kv.second;
74}
75
76bool VCMDecoderDataBase::DeregisterExternalDecoder(uint8_t payload_type) {
77 ExternalDecoderMap::iterator it = dec_external_map_.find(payload_type);
78 if (it == dec_external_map_.end()) {
79 // Not found
80 return false;
81 }
82 // We can't use payload_type to check if the decoder is currently in use,
83 // because payload type may be out of date (e.g. before we decode the first
84 // frame after RegisterReceiveCodec)
85 if (ptr_decoder_ &&
86 ptr_decoder_->IsSameDecoder((*it).second->external_decoder_instance)) {
87 // Release it if it was registered and in use.
88 ptr_decoder_.reset();
89 }
90 DeregisterReceiveCodec(payload_type);
91 delete it->second;
92 dec_external_map_.erase(it);
93 return true;
94}
95
96// Add the external encoder object to the list of external decoders.
97// Won't be registered as a receive codec until RegisterReceiveCodec is called.
98void VCMDecoderDataBase::RegisterExternalDecoder(VideoDecoder* external_decoder,
99 uint8_t payload_type) {
100 // Check if payload value already exists, if so - erase old and insert new.
101 VCMExtDecoderMapItem* ext_decoder =
102 new VCMExtDecoderMapItem(external_decoder, payload_type);
103 DeregisterExternalDecoder(payload_type);
104 dec_external_map_[payload_type] = ext_decoder;
105}
106
107bool VCMDecoderDataBase::DecoderRegistered() const {
108 return !dec_map_.empty();
109}
110
111bool VCMDecoderDataBase::RegisterReceiveCodec(const VideoCodec* receive_codec,
112 int number_of_cores,
113 bool require_key_frame) {
114 if (number_of_cores < 0) {
115 return false;
116 }
117 // Check if payload value already exists, if so - erase old and insert new.
118 DeregisterReceiveCodec(receive_codec->plType);
119 if (receive_codec->codecType == kVideoCodecUnknown) {
120 return false;
121 }
122 VideoCodec* new_receive_codec = new VideoCodec(*receive_codec);
123 dec_map_[receive_codec->plType] = new VCMDecoderMapItem(
124 new_receive_codec, number_of_cores, require_key_frame);
125 return true;
126}
127
128bool VCMDecoderDataBase::DeregisterReceiveCodec(uint8_t payload_type) {
129 DecoderMap::iterator it = dec_map_.find(payload_type);
130 if (it == dec_map_.end()) {
131 return false;
132 }
133 delete it->second;
134 dec_map_.erase(it);
135 if (receive_codec_.plType == payload_type) {
136 // This codec is currently in use.
137 memset(&receive_codec_, 0, sizeof(VideoCodec));
138 }
139 return true;
140}
141
142VCMGenericDecoder* VCMDecoderDataBase::GetDecoder(
143 const VCMEncodedFrame& frame,
144 VCMDecodedFrameCallback* decoded_frame_callback) {
145 RTC_DCHECK(decoded_frame_callback->UserReceiveCallback());
146 uint8_t payload_type = frame.PayloadType();
147 if (payload_type == receive_codec_.plType || payload_type == 0) {
148 return ptr_decoder_.get();
149 }
150 // Check for exisitng decoder, if exists - delete.
151 if (ptr_decoder_) {
152 ptr_decoder_.reset();
153 memset(&receive_codec_, 0, sizeof(VideoCodec));
154 }
155 ptr_decoder_ = CreateAndInitDecoder(frame, &receive_codec_);
156 if (!ptr_decoder_) {
157 return nullptr;
158 }
159 VCMReceiveCallback* callback = decoded_frame_callback->UserReceiveCallback();
160 callback->OnIncomingPayloadType(receive_codec_.plType);
161 if (ptr_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback) <
162 0) {
163 ptr_decoder_.reset();
164 memset(&receive_codec_, 0, sizeof(VideoCodec));
165 return nullptr;
166 }
167 return ptr_decoder_.get();
168}
169
170VCMGenericDecoder* VCMDecoderDataBase::GetCurrentDecoder() {
171 return ptr_decoder_.get();
172}
173
174bool VCMDecoderDataBase::PrefersLateDecoding() const {
175 return ptr_decoder_ ? ptr_decoder_->PrefersLateDecoding() : true;
176}
177
178std::unique_ptr<VCMGenericDecoder> VCMDecoderDataBase::CreateAndInitDecoder(
179 const VCMEncodedFrame& frame,
180 VideoCodec* new_codec) const {
181 uint8_t payload_type = frame.PayloadType();
182 RTC_LOG(LS_INFO) << "Initializing decoder with payload type '"
183 << static_cast<int>(payload_type) << "'.";
184 RTC_DCHECK(new_codec);
185 const VCMDecoderMapItem* decoder_item = FindDecoderItem(payload_type);
186 if (!decoder_item) {
187 RTC_LOG(LS_ERROR) << "Can't find a decoder associated with payload type: "
188 << static_cast<int>(payload_type);
189 return nullptr;
190 }
191 std::unique_ptr<VCMGenericDecoder> ptr_decoder;
192 const VCMExtDecoderMapItem* external_dec_item =
193 FindExternalDecoderItem(payload_type);
194 if (external_dec_item) {
195 // External codec.
196 ptr_decoder.reset(new VCMGenericDecoder(
197 external_dec_item->external_decoder_instance, true));
198 } else {
199#if !defined(USE_BUILTIN_SW_CODECS)
200 RTC_LOG(LS_ERROR) << "No decoder of this type exists.";
201#else
202 // Create decoder.
203 ptr_decoder = CreateDecoder(decoder_item->settings->codecType);
204#endif
205 }
206 if (!ptr_decoder)
207 return nullptr;
208
209 // Copy over input resolutions to prevent codec reinitialization due to
210 // the first frame being of a different resolution than the database values.
211 // This is best effort, since there's no guarantee that width/height have been
212 // parsed yet (and may be zero).
213 if (frame.EncodedImage()._encodedWidth > 0 &&
214 frame.EncodedImage()._encodedHeight > 0) {
215 decoder_item->settings->width = frame.EncodedImage()._encodedWidth;
216 decoder_item->settings->height = frame.EncodedImage()._encodedHeight;
217 }
218 if (ptr_decoder->InitDecode(decoder_item->settings.get(),
219 decoder_item->number_of_cores) < 0) {
220 return nullptr;
221 }
222 memcpy(new_codec, decoder_item->settings.get(), sizeof(VideoCodec));
223 return ptr_decoder;
224}
225
226const VCMDecoderMapItem* VCMDecoderDataBase::FindDecoderItem(
227 uint8_t payload_type) const {
228 DecoderMap::const_iterator it = dec_map_.find(payload_type);
229 if (it != dec_map_.end()) {
230 return (*it).second;
231 }
232 return nullptr;
233}
234
235const VCMExtDecoderMapItem* VCMDecoderDataBase::FindExternalDecoderItem(
236 uint8_t payload_type) const {
237 ExternalDecoderMap::const_iterator it = dec_external_map_.find(payload_type);
238 if (it != dec_external_map_.end()) {
239 return (*it).second;
240 }
241 return nullptr;
242}
243
244} // namespace webrtc