blob: 6aa332eb88a760ef3f9f1c056d6b822197623baf [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"
Jonas Olssona4d87372019-07-05 19:08:33 +020012
Niels Möllerf9063782018-02-20 16:09:48 +010013#include "rtc_base/checks.h"
14#include "rtc_base/logging.h"
15
16namespace webrtc {
17
Niels Möller18c83d32020-08-07 14:14:49 +020018VCMDecoderMapItem::VCMDecoderMapItem(VideoCodec* settings, int number_of_cores)
19 : settings(settings), number_of_cores(number_of_cores) {
Niels Möllerf9063782018-02-20 16:09:48 +010020 RTC_DCHECK_GE(number_of_cores, 0);
21}
22
23VCMExtDecoderMapItem::VCMExtDecoderMapItem(
24 VideoDecoder* external_decoder_instance,
25 uint8_t payload_type)
26 : payload_type(payload_type),
27 external_decoder_instance(external_decoder_instance) {}
28
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020029VCMDecoderMapItem::~VCMDecoderMapItem() {}
30
Niels Möllerf9063782018-02-20 16:09:48 +010031VCMDecoderDataBase::VCMDecoderDataBase()
Niels Möller5401bad2020-08-11 12:17:42 +020032 : current_payload_type_(0),
33 receive_codec_(),
34 dec_map_(),
35 dec_external_map_() {}
Niels Möllerf9063782018-02-20 16:09:48 +010036
37VCMDecoderDataBase::~VCMDecoderDataBase() {
38 ptr_decoder_.reset();
39 for (auto& kv : dec_map_)
40 delete kv.second;
41 for (auto& kv : dec_external_map_)
42 delete kv.second;
43}
44
45bool VCMDecoderDataBase::DeregisterExternalDecoder(uint8_t payload_type) {
46 ExternalDecoderMap::iterator it = dec_external_map_.find(payload_type);
47 if (it == dec_external_map_.end()) {
Åsa Persson6cb74fd2018-06-01 15:13:42 +020048 // Not found.
Niels Möllerf9063782018-02-20 16:09:48 +010049 return false;
50 }
51 // We can't use payload_type to check if the decoder is currently in use,
52 // because payload type may be out of date (e.g. before we decode the first
Åsa Persson6cb74fd2018-06-01 15:13:42 +020053 // frame after RegisterReceiveCodec).
Niels Möllerf9063782018-02-20 16:09:48 +010054 if (ptr_decoder_ &&
55 ptr_decoder_->IsSameDecoder((*it).second->external_decoder_instance)) {
56 // Release it if it was registered and in use.
57 ptr_decoder_.reset();
58 }
Niels Möllerf9063782018-02-20 16:09:48 +010059 delete it->second;
60 dec_external_map_.erase(it);
61 return true;
62}
63
Åsa Persson6cb74fd2018-06-01 15:13:42 +020064// Add the external decoder object to the list of external decoders.
Niels Möllerf9063782018-02-20 16:09:48 +010065// Won't be registered as a receive codec until RegisterReceiveCodec is called.
66void VCMDecoderDataBase::RegisterExternalDecoder(VideoDecoder* external_decoder,
67 uint8_t payload_type) {
Åsa Persson6cb74fd2018-06-01 15:13:42 +020068 // If payload value already exists, erase old and insert new.
Niels Möllerf9063782018-02-20 16:09:48 +010069 VCMExtDecoderMapItem* ext_decoder =
70 new VCMExtDecoderMapItem(external_decoder, payload_type);
71 DeregisterExternalDecoder(payload_type);
72 dec_external_map_[payload_type] = ext_decoder;
73}
74
Johannes Kron16359f62021-02-18 23:37:22 +010075bool VCMDecoderDataBase::IsExternalDecoderRegistered(
76 uint8_t payload_type) const {
77 return payload_type == current_payload_type_ ||
78 FindExternalDecoderItem(payload_type);
79}
80
Niels Möller582102c2020-08-07 16:19:56 +020081bool VCMDecoderDataBase::RegisterReceiveCodec(uint8_t payload_type,
82 const VideoCodec* receive_codec,
Niels Möller18c83d32020-08-07 14:14:49 +020083 int number_of_cores) {
Niels Möllerf9063782018-02-20 16:09:48 +010084 if (number_of_cores < 0) {
85 return false;
86 }
Åsa Persson6cb74fd2018-06-01 15:13:42 +020087 // If payload value already exists, erase old and insert new.
Niels Möller582102c2020-08-07 16:19:56 +020088 DeregisterReceiveCodec(payload_type);
Niels Möllerf9063782018-02-20 16:09:48 +010089 VideoCodec* new_receive_codec = new VideoCodec(*receive_codec);
Niels Möller582102c2020-08-07 16:19:56 +020090 dec_map_[payload_type] =
Niels Möller18c83d32020-08-07 14:14:49 +020091 new VCMDecoderMapItem(new_receive_codec, number_of_cores);
Niels Möllerf9063782018-02-20 16:09:48 +010092 return true;
93}
94
95bool VCMDecoderDataBase::DeregisterReceiveCodec(uint8_t payload_type) {
96 DecoderMap::iterator it = dec_map_.find(payload_type);
97 if (it == dec_map_.end()) {
98 return false;
99 }
100 delete it->second;
101 dec_map_.erase(it);
Niels Möller5401bad2020-08-11 12:17:42 +0200102 if (payload_type == current_payload_type_) {
Niels Möllerf9063782018-02-20 16:09:48 +0100103 // This codec is currently in use.
Danil Chapovalov9f4859e2020-10-16 17:45:41 +0200104 receive_codec_ = {};
Niels Möller5401bad2020-08-11 12:17:42 +0200105 current_payload_type_ = 0;
Niels Möllerf9063782018-02-20 16:09:48 +0100106 }
107 return true;
108}
109
110VCMGenericDecoder* VCMDecoderDataBase::GetDecoder(
111 const VCMEncodedFrame& frame,
112 VCMDecodedFrameCallback* decoded_frame_callback) {
113 RTC_DCHECK(decoded_frame_callback->UserReceiveCallback());
114 uint8_t payload_type = frame.PayloadType();
Niels Möller5401bad2020-08-11 12:17:42 +0200115 if (payload_type == current_payload_type_ || payload_type == 0) {
Niels Möllerf9063782018-02-20 16:09:48 +0100116 return ptr_decoder_.get();
117 }
Åsa Persson6cb74fd2018-06-01 15:13:42 +0200118 // If decoder exists - delete.
Niels Möllerf9063782018-02-20 16:09:48 +0100119 if (ptr_decoder_) {
120 ptr_decoder_.reset();
Danil Chapovalov9f4859e2020-10-16 17:45:41 +0200121 receive_codec_ = {};
Niels Möller5401bad2020-08-11 12:17:42 +0200122 current_payload_type_ = 0;
Niels Möllerf9063782018-02-20 16:09:48 +0100123 }
124 ptr_decoder_ = CreateAndInitDecoder(frame, &receive_codec_);
125 if (!ptr_decoder_) {
126 return nullptr;
127 }
Niels Möller5401bad2020-08-11 12:17:42 +0200128 current_payload_type_ = frame.PayloadType();
Niels Möllerf9063782018-02-20 16:09:48 +0100129 VCMReceiveCallback* callback = decoded_frame_callback->UserReceiveCallback();
Niels Möller5401bad2020-08-11 12:17:42 +0200130 callback->OnIncomingPayloadType(current_payload_type_);
Niels Möllerf9063782018-02-20 16:09:48 +0100131 if (ptr_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback) <
132 0) {
133 ptr_decoder_.reset();
Danil Chapovalov9f4859e2020-10-16 17:45:41 +0200134 receive_codec_ = {};
Niels Möller5401bad2020-08-11 12:17:42 +0200135 current_payload_type_ = 0;
Niels Möllerf9063782018-02-20 16:09:48 +0100136 return nullptr;
137 }
138 return ptr_decoder_.get();
139}
140
Niels Möllerf9063782018-02-20 16:09:48 +0100141std::unique_ptr<VCMGenericDecoder> VCMDecoderDataBase::CreateAndInitDecoder(
142 const VCMEncodedFrame& frame,
143 VideoCodec* new_codec) const {
144 uint8_t payload_type = frame.PayloadType();
145 RTC_LOG(LS_INFO) << "Initializing decoder with payload type '"
146 << static_cast<int>(payload_type) << "'.";
147 RTC_DCHECK(new_codec);
148 const VCMDecoderMapItem* decoder_item = FindDecoderItem(payload_type);
149 if (!decoder_item) {
150 RTC_LOG(LS_ERROR) << "Can't find a decoder associated with payload type: "
151 << static_cast<int>(payload_type);
152 return nullptr;
153 }
154 std::unique_ptr<VCMGenericDecoder> ptr_decoder;
155 const VCMExtDecoderMapItem* external_dec_item =
156 FindExternalDecoderItem(payload_type);
157 if (external_dec_item) {
158 // External codec.
159 ptr_decoder.reset(new VCMGenericDecoder(
160 external_dec_item->external_decoder_instance, true));
161 } else {
Niels Möllerf9063782018-02-20 16:09:48 +0100162 RTC_LOG(LS_ERROR) << "No decoder of this type exists.";
Niels Möllerf9063782018-02-20 16:09:48 +0100163 }
164 if (!ptr_decoder)
165 return nullptr;
166
167 // Copy over input resolutions to prevent codec reinitialization due to
168 // the first frame being of a different resolution than the database values.
169 // This is best effort, since there's no guarantee that width/height have been
170 // parsed yet (and may be zero).
171 if (frame.EncodedImage()._encodedWidth > 0 &&
172 frame.EncodedImage()._encodedHeight > 0) {
173 decoder_item->settings->width = frame.EncodedImage()._encodedWidth;
174 decoder_item->settings->height = frame.EncodedImage()._encodedHeight;
175 }
Ilya Nikolaevskiy43c108b2020-05-15 12:24:29 +0200176 int err = ptr_decoder->InitDecode(decoder_item->settings.get(),
177 decoder_item->number_of_cores);
178 if (err < 0) {
179 RTC_LOG(LS_ERROR) << "Failed to initialize decoder. Error code: " << err;
Niels Möllerf9063782018-02-20 16:09:48 +0100180 return nullptr;
181 }
Danil Chapovalov9f4859e2020-10-16 17:45:41 +0200182 *new_codec = *decoder_item->settings.get();
Niels Möllerf9063782018-02-20 16:09:48 +0100183 return ptr_decoder;
184}
185
186const VCMDecoderMapItem* VCMDecoderDataBase::FindDecoderItem(
187 uint8_t payload_type) const {
188 DecoderMap::const_iterator it = dec_map_.find(payload_type);
189 if (it != dec_map_.end()) {
190 return (*it).second;
191 }
192 return nullptr;
193}
194
195const VCMExtDecoderMapItem* VCMDecoderDataBase::FindExternalDecoderItem(
196 uint8_t payload_type) const {
197 ExternalDecoderMap::const_iterator it = dec_external_map_.find(payload_type);
198 if (it != dec_external_map_.end()) {
199 return (*it).second;
200 }
201 return nullptr;
202}
203
204} // namespace webrtc