blob: 594ca86553c7219ffd8df1a5ccef560dc7163bfd [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 }
59 DeregisterReceiveCodec(payload_type);
60 delete it->second;
61 dec_external_map_.erase(it);
62 return true;
63}
64
Åsa Persson6cb74fd2018-06-01 15:13:42 +020065// Add the external decoder object to the list of external decoders.
Niels Möllerf9063782018-02-20 16:09:48 +010066// Won't be registered as a receive codec until RegisterReceiveCodec is called.
67void VCMDecoderDataBase::RegisterExternalDecoder(VideoDecoder* external_decoder,
68 uint8_t payload_type) {
Åsa Persson6cb74fd2018-06-01 15:13:42 +020069 // If payload value already exists, erase old and insert new.
Niels Möllerf9063782018-02-20 16:09:48 +010070 VCMExtDecoderMapItem* ext_decoder =
71 new VCMExtDecoderMapItem(external_decoder, payload_type);
72 DeregisterExternalDecoder(payload_type);
73 dec_external_map_[payload_type] = ext_decoder;
74}
75
Niels Möller582102c2020-08-07 16:19:56 +020076bool VCMDecoderDataBase::RegisterReceiveCodec(uint8_t payload_type,
77 const VideoCodec* receive_codec,
Niels Möller18c83d32020-08-07 14:14:49 +020078 int number_of_cores) {
Niels Möllerf9063782018-02-20 16:09:48 +010079 if (number_of_cores < 0) {
80 return false;
81 }
Åsa Persson6cb74fd2018-06-01 15:13:42 +020082 // If payload value already exists, erase old and insert new.
Niels Möller582102c2020-08-07 16:19:56 +020083 DeregisterReceiveCodec(payload_type);
Niels Möllerf9063782018-02-20 16:09:48 +010084 VideoCodec* new_receive_codec = new VideoCodec(*receive_codec);
Niels Möller582102c2020-08-07 16:19:56 +020085 dec_map_[payload_type] =
Niels Möller18c83d32020-08-07 14:14:49 +020086 new VCMDecoderMapItem(new_receive_codec, number_of_cores);
Niels Möllerf9063782018-02-20 16:09:48 +010087 return true;
88}
89
90bool VCMDecoderDataBase::DeregisterReceiveCodec(uint8_t payload_type) {
91 DecoderMap::iterator it = dec_map_.find(payload_type);
92 if (it == dec_map_.end()) {
93 return false;
94 }
95 delete it->second;
96 dec_map_.erase(it);
Niels Möller5401bad2020-08-11 12:17:42 +020097 if (payload_type == current_payload_type_) {
Niels Möllerf9063782018-02-20 16:09:48 +010098 // This codec is currently in use.
Danil Chapovalov9f4859e2020-10-16 17:45:41 +020099 receive_codec_ = {};
Niels Möller5401bad2020-08-11 12:17:42 +0200100 current_payload_type_ = 0;
Niels Möllerf9063782018-02-20 16:09:48 +0100101 }
102 return true;
103}
104
105VCMGenericDecoder* VCMDecoderDataBase::GetDecoder(
106 const VCMEncodedFrame& frame,
107 VCMDecodedFrameCallback* decoded_frame_callback) {
108 RTC_DCHECK(decoded_frame_callback->UserReceiveCallback());
109 uint8_t payload_type = frame.PayloadType();
Niels Möller5401bad2020-08-11 12:17:42 +0200110 if (payload_type == current_payload_type_ || payload_type == 0) {
Niels Möllerf9063782018-02-20 16:09:48 +0100111 return ptr_decoder_.get();
112 }
Åsa Persson6cb74fd2018-06-01 15:13:42 +0200113 // If decoder exists - delete.
Niels Möllerf9063782018-02-20 16:09:48 +0100114 if (ptr_decoder_) {
115 ptr_decoder_.reset();
Danil Chapovalov9f4859e2020-10-16 17:45:41 +0200116 receive_codec_ = {};
Niels Möller5401bad2020-08-11 12:17:42 +0200117 current_payload_type_ = 0;
Niels Möllerf9063782018-02-20 16:09:48 +0100118 }
119 ptr_decoder_ = CreateAndInitDecoder(frame, &receive_codec_);
120 if (!ptr_decoder_) {
121 return nullptr;
122 }
Niels Möller5401bad2020-08-11 12:17:42 +0200123 current_payload_type_ = frame.PayloadType();
Niels Möllerf9063782018-02-20 16:09:48 +0100124 VCMReceiveCallback* callback = decoded_frame_callback->UserReceiveCallback();
Niels Möller5401bad2020-08-11 12:17:42 +0200125 callback->OnIncomingPayloadType(current_payload_type_);
Niels Möllerf9063782018-02-20 16:09:48 +0100126 if (ptr_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback) <
127 0) {
128 ptr_decoder_.reset();
Danil Chapovalov9f4859e2020-10-16 17:45:41 +0200129 receive_codec_ = {};
Niels Möller5401bad2020-08-11 12:17:42 +0200130 current_payload_type_ = 0;
Niels Möllerf9063782018-02-20 16:09:48 +0100131 return nullptr;
132 }
133 return ptr_decoder_.get();
134}
135
Niels Möllerf9063782018-02-20 16:09:48 +0100136std::unique_ptr<VCMGenericDecoder> VCMDecoderDataBase::CreateAndInitDecoder(
137 const VCMEncodedFrame& frame,
138 VideoCodec* new_codec) const {
139 uint8_t payload_type = frame.PayloadType();
140 RTC_LOG(LS_INFO) << "Initializing decoder with payload type '"
141 << static_cast<int>(payload_type) << "'.";
142 RTC_DCHECK(new_codec);
143 const VCMDecoderMapItem* decoder_item = FindDecoderItem(payload_type);
144 if (!decoder_item) {
145 RTC_LOG(LS_ERROR) << "Can't find a decoder associated with payload type: "
146 << static_cast<int>(payload_type);
147 return nullptr;
148 }
149 std::unique_ptr<VCMGenericDecoder> ptr_decoder;
150 const VCMExtDecoderMapItem* external_dec_item =
151 FindExternalDecoderItem(payload_type);
152 if (external_dec_item) {
153 // External codec.
154 ptr_decoder.reset(new VCMGenericDecoder(
155 external_dec_item->external_decoder_instance, true));
156 } else {
Niels Möllerf9063782018-02-20 16:09:48 +0100157 RTC_LOG(LS_ERROR) << "No decoder of this type exists.";
Niels Möllerf9063782018-02-20 16:09:48 +0100158 }
159 if (!ptr_decoder)
160 return nullptr;
161
162 // Copy over input resolutions to prevent codec reinitialization due to
163 // the first frame being of a different resolution than the database values.
164 // This is best effort, since there's no guarantee that width/height have been
165 // parsed yet (and may be zero).
166 if (frame.EncodedImage()._encodedWidth > 0 &&
167 frame.EncodedImage()._encodedHeight > 0) {
168 decoder_item->settings->width = frame.EncodedImage()._encodedWidth;
169 decoder_item->settings->height = frame.EncodedImage()._encodedHeight;
170 }
Ilya Nikolaevskiy43c108b2020-05-15 12:24:29 +0200171 int err = ptr_decoder->InitDecode(decoder_item->settings.get(),
172 decoder_item->number_of_cores);
173 if (err < 0) {
174 RTC_LOG(LS_ERROR) << "Failed to initialize decoder. Error code: " << err;
Niels Möllerf9063782018-02-20 16:09:48 +0100175 return nullptr;
176 }
Danil Chapovalov9f4859e2020-10-16 17:45:41 +0200177 *new_codec = *decoder_item->settings.get();
Niels Möllerf9063782018-02-20 16:09:48 +0100178 return ptr_decoder;
179}
180
181const VCMDecoderMapItem* VCMDecoderDataBase::FindDecoderItem(
182 uint8_t payload_type) const {
183 DecoderMap::const_iterator it = dec_map_.find(payload_type);
184 if (it != dec_map_.end()) {
185 return (*it).second;
186 }
187 return nullptr;
188}
189
190const VCMExtDecoderMapItem* VCMDecoderDataBase::FindExternalDecoderItem(
191 uint8_t payload_type) const {
192 ExternalDecoderMap::const_iterator it = dec_external_map_.find(payload_type);
193 if (it != dec_external_map_.end()) {
194 return (*it).second;
195 }
196 return nullptr;
197}
198
199} // namespace webrtc