blob: d4841cd0a61b8b7e4b67987f396df3381b3f3f94 [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öllerf9063782018-02-20 16:09:48 +010018bool VCMDecoderDataBase::DeregisterExternalDecoder(uint8_t payload_type) {
Danil Chapovalov7b78a312021-08-06 12:30:02 +020019 auto it = decoders_.find(payload_type);
20 if (it == decoders_.end()) {
Åsa Persson6cb74fd2018-06-01 15:13:42 +020021 // Not found.
Niels Möllerf9063782018-02-20 16:09:48 +010022 return false;
23 }
24 // We can't use payload_type to check if the decoder is currently in use,
25 // because payload type may be out of date (e.g. before we decode the first
Åsa Persson6cb74fd2018-06-01 15:13:42 +020026 // frame after RegisterReceiveCodec).
Danil Chapovalov7b78a312021-08-06 12:30:02 +020027 if (current_decoder_ && current_decoder_->IsSameDecoder(it->second)) {
Niels Möllerf9063782018-02-20 16:09:48 +010028 // Release it if it was registered and in use.
Danil Chapovalov7b78a312021-08-06 12:30:02 +020029 current_decoder_ = absl::nullopt;
Niels Möllerf9063782018-02-20 16:09:48 +010030 }
Danil Chapovalov7b78a312021-08-06 12:30:02 +020031 decoders_.erase(it);
Niels Möllerf9063782018-02-20 16:09:48 +010032 return true;
33}
34
Åsa Persson6cb74fd2018-06-01 15:13:42 +020035// Add the external decoder object to the list of external decoders.
Niels Möllerf9063782018-02-20 16:09:48 +010036// Won't be registered as a receive codec until RegisterReceiveCodec is called.
Danil Chapovalov7b78a312021-08-06 12:30:02 +020037void VCMDecoderDataBase::RegisterExternalDecoder(
38 uint8_t payload_type,
39 VideoDecoder* external_decoder) {
Åsa Persson6cb74fd2018-06-01 15:13:42 +020040 // If payload value already exists, erase old and insert new.
Niels Möllerf9063782018-02-20 16:09:48 +010041 DeregisterExternalDecoder(payload_type);
Danil Chapovalov7b78a312021-08-06 12:30:02 +020042 decoders_[payload_type] = external_decoder;
Niels Möllerf9063782018-02-20 16:09:48 +010043}
44
Johannes Kron16359f62021-02-18 23:37:22 +010045bool VCMDecoderDataBase::IsExternalDecoderRegistered(
46 uint8_t payload_type) const {
47 return payload_type == current_payload_type_ ||
Danil Chapovalov7b78a312021-08-06 12:30:02 +020048 decoders_.find(payload_type) != decoders_.end();
Johannes Kron16359f62021-02-18 23:37:22 +010049}
50
Niels Möller582102c2020-08-07 16:19:56 +020051bool VCMDecoderDataBase::RegisterReceiveCodec(uint8_t payload_type,
Danil Chapovalov7b78a312021-08-06 12:30:02 +020052 const VideoCodec& receive_codec,
Niels Möller18c83d32020-08-07 14:14:49 +020053 int number_of_cores) {
Niels Möllerf9063782018-02-20 16:09:48 +010054 if (number_of_cores < 0) {
55 return false;
56 }
Åsa Persson6cb74fd2018-06-01 15:13:42 +020057 // If payload value already exists, erase old and insert new.
Danil Chapovalov7b78a312021-08-06 12:30:02 +020058 if (payload_type == current_payload_type_) {
59 current_payload_type_ = absl::nullopt;
60 }
61 auto& entry = decoder_settings_[payload_type];
62 entry.settings = receive_codec;
63 entry.number_of_cores = number_of_cores;
Niels Möllerf9063782018-02-20 16:09:48 +010064 return true;
65}
66
67bool VCMDecoderDataBase::DeregisterReceiveCodec(uint8_t payload_type) {
Danil Chapovalov7b78a312021-08-06 12:30:02 +020068 if (decoder_settings_.erase(payload_type) == 0) {
Niels Möllerf9063782018-02-20 16:09:48 +010069 return false;
70 }
Niels Möller5401bad2020-08-11 12:17:42 +020071 if (payload_type == current_payload_type_) {
Niels Möllerf9063782018-02-20 16:09:48 +010072 // This codec is currently in use.
Danil Chapovalov7b78a312021-08-06 12:30:02 +020073 current_payload_type_ = absl::nullopt;
Niels Möllerf9063782018-02-20 16:09:48 +010074 }
75 return true;
76}
77
78VCMGenericDecoder* VCMDecoderDataBase::GetDecoder(
79 const VCMEncodedFrame& frame,
80 VCMDecodedFrameCallback* decoded_frame_callback) {
81 RTC_DCHECK(decoded_frame_callback->UserReceiveCallback());
82 uint8_t payload_type = frame.PayloadType();
Niels Möller5401bad2020-08-11 12:17:42 +020083 if (payload_type == current_payload_type_ || payload_type == 0) {
Danil Chapovalov7b78a312021-08-06 12:30:02 +020084 return current_decoder_.has_value() ? &*current_decoder_ : nullptr;
Niels Möllerf9063782018-02-20 16:09:48 +010085 }
Åsa Persson6cb74fd2018-06-01 15:13:42 +020086 // If decoder exists - delete.
Danil Chapovalov7b78a312021-08-06 12:30:02 +020087 if (current_decoder_.has_value()) {
88 current_decoder_ = absl::nullopt;
89 current_payload_type_ = absl::nullopt;
Niels Möllerf9063782018-02-20 16:09:48 +010090 }
Danil Chapovalov7b78a312021-08-06 12:30:02 +020091
92 CreateAndInitDecoder(frame);
93 if (current_decoder_ == absl::nullopt) {
Niels Möllerf9063782018-02-20 16:09:48 +010094 return nullptr;
95 }
Danil Chapovalov7b78a312021-08-06 12:30:02 +020096
Niels Möllerf9063782018-02-20 16:09:48 +010097 VCMReceiveCallback* callback = decoded_frame_callback->UserReceiveCallback();
Danil Chapovalov7b78a312021-08-06 12:30:02 +020098 callback->OnIncomingPayloadType(payload_type);
99 if (current_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback) <
Niels Möllerf9063782018-02-20 16:09:48 +0100100 0) {
Danil Chapovalov7b78a312021-08-06 12:30:02 +0200101 current_decoder_ = absl::nullopt;
Niels Möllerf9063782018-02-20 16:09:48 +0100102 return nullptr;
103 }
Danil Chapovalov7b78a312021-08-06 12:30:02 +0200104
105 current_payload_type_ = payload_type;
106 return &*current_decoder_;
Niels Möllerf9063782018-02-20 16:09:48 +0100107}
108
Danil Chapovalov7b78a312021-08-06 12:30:02 +0200109void VCMDecoderDataBase::CreateAndInitDecoder(const VCMEncodedFrame& frame) {
Niels Möllerf9063782018-02-20 16:09:48 +0100110 uint8_t payload_type = frame.PayloadType();
111 RTC_LOG(LS_INFO) << "Initializing decoder with payload type '"
Danil Chapovalov7b78a312021-08-06 12:30:02 +0200112 << int{payload_type} << "'.";
113 auto decoder_item = decoder_settings_.find(payload_type);
114 if (decoder_item == decoder_settings_.end()) {
Niels Möllerf9063782018-02-20 16:09:48 +0100115 RTC_LOG(LS_ERROR) << "Can't find a decoder associated with payload type: "
Danil Chapovalov7b78a312021-08-06 12:30:02 +0200116 << int{payload_type};
117 return;
Niels Möllerf9063782018-02-20 16:09:48 +0100118 }
Danil Chapovalov7b78a312021-08-06 12:30:02 +0200119 auto external_dec_item = decoders_.find(payload_type);
120 if (external_dec_item == decoders_.end()) {
Niels Möllerf9063782018-02-20 16:09:48 +0100121 RTC_LOG(LS_ERROR) << "No decoder of this type exists.";
Danil Chapovalov7b78a312021-08-06 12:30:02 +0200122 return;
Niels Möllerf9063782018-02-20 16:09:48 +0100123 }
Danil Chapovalov7b78a312021-08-06 12:30:02 +0200124 current_decoder_.emplace(external_dec_item->second);
Niels Möllerf9063782018-02-20 16:09:48 +0100125
126 // Copy over input resolutions to prevent codec reinitialization due to
127 // the first frame being of a different resolution than the database values.
128 // This is best effort, since there's no guarantee that width/height have been
129 // parsed yet (and may be zero).
130 if (frame.EncodedImage()._encodedWidth > 0 &&
131 frame.EncodedImage()._encodedHeight > 0) {
Danil Chapovalov7b78a312021-08-06 12:30:02 +0200132 decoder_item->second.settings.width = frame.EncodedImage()._encodedWidth;
133 decoder_item->second.settings.height = frame.EncodedImage()._encodedHeight;
Niels Möllerf9063782018-02-20 16:09:48 +0100134 }
Danil Chapovalov7b78a312021-08-06 12:30:02 +0200135 int err = current_decoder_->InitDecode(&decoder_item->second.settings,
136 decoder_item->second.number_of_cores);
Ilya Nikolaevskiy43c108b2020-05-15 12:24:29 +0200137 if (err < 0) {
Danil Chapovalov7b78a312021-08-06 12:30:02 +0200138 current_decoder_ = absl::nullopt;
Ilya Nikolaevskiy43c108b2020-05-15 12:24:29 +0200139 RTC_LOG(LS_ERROR) << "Failed to initialize decoder. Error code: " << err;
Niels Möllerf9063782018-02-20 16:09:48 +0100140 }
Niels Möllerf9063782018-02-20 16:09:48 +0100141}
142
143} // namespace webrtc