blob: c113239fbf6d1b0fe5e92125bb59b7e8131196ef [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"
Niels Möllerf9063782018-02-20 16:09:48 +010012#include "rtc_base/checks.h"
13#include "rtc_base/logging.h"
14
15namespace webrtc {
16
Niels Möllerf9063782018-02-20 16:09:48 +010017VCMDecoderMapItem::VCMDecoderMapItem(VideoCodec* settings,
18 int number_of_cores,
19 bool require_key_frame)
20 : settings(settings),
21 number_of_cores(number_of_cores),
22 require_key_frame(require_key_frame) {
23 RTC_DCHECK_GE(number_of_cores, 0);
24}
25
26VCMExtDecoderMapItem::VCMExtDecoderMapItem(
27 VideoDecoder* external_decoder_instance,
28 uint8_t payload_type)
29 : payload_type(payload_type),
30 external_decoder_instance(external_decoder_instance) {}
31
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020032VCMDecoderMapItem::~VCMDecoderMapItem() {}
33
Niels Möllerf9063782018-02-20 16:09:48 +010034VCMDecoderDataBase::VCMDecoderDataBase()
35 : receive_codec_(), dec_map_(), dec_external_map_() {}
36
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öllerf9063782018-02-20 16:09:48 +010076bool VCMDecoderDataBase::RegisterReceiveCodec(const VideoCodec* receive_codec,
77 int number_of_cores,
78 bool require_key_frame) {
79 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öllerf9063782018-02-20 16:09:48 +010083 DeregisterReceiveCodec(receive_codec->plType);
Niels Möllerf9063782018-02-20 16:09:48 +010084 VideoCodec* new_receive_codec = new VideoCodec(*receive_codec);
85 dec_map_[receive_codec->plType] = new VCMDecoderMapItem(
86 new_receive_codec, number_of_cores, require_key_frame);
87 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);
97 if (receive_codec_.plType == payload_type) {
98 // This codec is currently in use.
99 memset(&receive_codec_, 0, sizeof(VideoCodec));
100 }
101 return true;
102}
103
104VCMGenericDecoder* VCMDecoderDataBase::GetDecoder(
105 const VCMEncodedFrame& frame,
106 VCMDecodedFrameCallback* decoded_frame_callback) {
107 RTC_DCHECK(decoded_frame_callback->UserReceiveCallback());
108 uint8_t payload_type = frame.PayloadType();
109 if (payload_type == receive_codec_.plType || payload_type == 0) {
110 return ptr_decoder_.get();
111 }
Åsa Persson6cb74fd2018-06-01 15:13:42 +0200112 // If decoder exists - delete.
Niels Möllerf9063782018-02-20 16:09:48 +0100113 if (ptr_decoder_) {
114 ptr_decoder_.reset();
115 memset(&receive_codec_, 0, sizeof(VideoCodec));
116 }
117 ptr_decoder_ = CreateAndInitDecoder(frame, &receive_codec_);
118 if (!ptr_decoder_) {
119 return nullptr;
120 }
121 VCMReceiveCallback* callback = decoded_frame_callback->UserReceiveCallback();
122 callback->OnIncomingPayloadType(receive_codec_.plType);
123 if (ptr_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback) <
124 0) {
125 ptr_decoder_.reset();
126 memset(&receive_codec_, 0, sizeof(VideoCodec));
127 return nullptr;
128 }
129 return ptr_decoder_.get();
130}
131
Niels Möllerf9063782018-02-20 16:09:48 +0100132bool VCMDecoderDataBase::PrefersLateDecoding() const {
133 return ptr_decoder_ ? ptr_decoder_->PrefersLateDecoding() : true;
134}
135
136std::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 }
171 if (ptr_decoder->InitDecode(decoder_item->settings.get(),
172 decoder_item->number_of_cores) < 0) {
173 return nullptr;
174 }
175 memcpy(new_codec, decoder_item->settings.get(), sizeof(VideoCodec));
176 return ptr_decoder;
177}
178
179const VCMDecoderMapItem* VCMDecoderDataBase::FindDecoderItem(
180 uint8_t payload_type) const {
181 DecoderMap::const_iterator it = dec_map_.find(payload_type);
182 if (it != dec_map_.end()) {
183 return (*it).second;
184 }
185 return nullptr;
186}
187
188const VCMExtDecoderMapItem* VCMDecoderDataBase::FindExternalDecoderItem(
189 uint8_t payload_type) const {
190 ExternalDecoderMap::const_iterator it = dec_external_map_.find(payload_type);
191 if (it != dec_external_map_.end()) {
192 return (*it).second;
193 }
194 return nullptr;
195}
196
197} // namespace webrtc