• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "codec_listener_proxy.h"
17 #include <shared_mutex>
18 #include "avcodec_errors.h"
19 #include "avcodec_log.h"
20 #include "avcodec_parcel.h"
21 #include "avsharedmemory_ipc.h"
22 #include "buffer/avbuffer.h"
23 #include "meta/meta.h"
24 
25 namespace {
26 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "CodecListenerProxy"};
27 }
28 
29 namespace OHOS {
30 namespace MediaAVCodec {
31 class CodecListenerProxy::CodecBufferCache : public NoCopyable {
32 public:
33     CodecBufferCache() = default;
34     ~CodecBufferCache() = default;
35 
WriteToParcel(uint32_t index,const std::shared_ptr<AVBuffer> & buffer,MessageParcel & parcel)36     bool WriteToParcel(uint32_t index, const std::shared_ptr<AVBuffer> &buffer, MessageParcel &parcel)
37     {
38         std::lock_guard<std::shared_mutex> lock(mutex_);
39         CacheFlag flag = CacheFlag::UPDATE_CACHE;
40         if (buffer == nullptr) {
41             AVCODEC_LOGD("Invalid buffer for index: %{public}u", index);
42             flag = CacheFlag::INVALIDATE_CACHE;
43             parcel.WriteUint8(static_cast<uint8_t>(flag));
44             auto iter = caches_.find(index);
45             if (iter != caches_.end()) {
46                 iter->second = std::shared_ptr<AVBuffer>(nullptr);
47                 caches_.erase(iter);
48             }
49             return true;
50         }
51 
52         auto iter = caches_.find(index);
53         if (iter != caches_.end() && iter->second.lock() == buffer) {
54             flag = CacheFlag::HIT_CACHE;
55             parcel.WriteUint8(static_cast<uint8_t>(flag));
56             return buffer->WriteToMessageParcel(parcel);
57         }
58 
59         if (iter == caches_.end()) {
60             AVCODEC_LOGD("Add cache codec buffer, index: %{public}u", index);
61             caches_.emplace(index, buffer);
62         } else {
63             AVCODEC_LOGD("Update cache codec buffer, index: %{public}u", index);
64             iter->second = buffer;
65         }
66 
67         parcel.WriteUint8(static_cast<uint8_t>(flag));
68 
69         return buffer->WriteToMessageParcel(parcel);
70     }
71 
FindBufferFromIndex(uint32_t index)72     std::shared_ptr<AVBuffer> FindBufferFromIndex(uint32_t index)
73     {
74         std::shared_lock<std::shared_mutex> lock(mutex_);
75         auto iter = caches_.find(index);
76         if (iter != caches_.end()) {
77             return iter->second.lock();
78         }
79         return nullptr;
80     }
81 
ClearCaches()82     void ClearCaches()
83     {
84         std::lock_guard<std::shared_mutex> lock(mutex_);
85         for (auto iter = caches_.begin(); iter != caches_.end();) {
86             if (iter->second.expired()) {
87                 iter = caches_.erase(iter);
88             } else {
89                 ++iter;
90             }
91         }
92     }
93 
94 private:
95     std::shared_mutex mutex_;
96     enum class CacheFlag : uint8_t {
97         HIT_CACHE = 1,
98         UPDATE_CACHE,
99         INVALIDATE_CACHE,
100     };
101 
102     std::unordered_map<uint32_t, std::weak_ptr<AVBuffer>> caches_;
103 };
104 
CodecListenerProxy(const sptr<IRemoteObject> & impl)105 CodecListenerProxy::CodecListenerProxy(const sptr<IRemoteObject> &impl) : IRemoteProxy<IStandardCodecListener>(impl)
106 {
107     if (inputBufferCache_ == nullptr) {
108         inputBufferCache_ = std::make_unique<CodecBufferCache>();
109     }
110     if (outputBufferCache_ == nullptr) {
111         outputBufferCache_ = std::make_unique<CodecBufferCache>();
112     }
113     AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
114 }
115 
~CodecListenerProxy()116 CodecListenerProxy::~CodecListenerProxy()
117 {
118     inputBufferCache_ = nullptr;
119     outputBufferCache_ = nullptr;
120     AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
121 }
122 
OnError(AVCodecErrorType errorType,int32_t errorCode)123 void CodecListenerProxy::OnError(AVCodecErrorType errorType, int32_t errorCode)
124 {
125     MessageParcel data;
126     MessageParcel reply;
127     MessageOption option(MessageOption::TF_ASYNC);
128     bool token = data.WriteInterfaceToken(CodecListenerProxy::GetDescriptor());
129     CHECK_AND_RETURN_LOG(token, "Write descriptor failed!");
130 
131     data.WriteUint64(GetGeneration());
132     data.WriteInt32(static_cast<int32_t>(errorType));
133     data.WriteInt32(errorCode);
134     int error = Remote()->SendRequest(static_cast<uint32_t>(CodecListenerInterfaceCode::ON_ERROR), data, reply, option);
135     CHECK_AND_RETURN_LOG(error == AVCS_ERR_OK, "Send request failed");
136 }
137 
OnOutputFormatChanged(const Format & format)138 void CodecListenerProxy::OnOutputFormatChanged(const Format &format)
139 {
140     MessageParcel data;
141     MessageParcel reply;
142     MessageOption option(MessageOption::TF_ASYNC);
143     bool token = data.WriteInterfaceToken(CodecListenerProxy::GetDescriptor());
144     CHECK_AND_RETURN_LOG(token, "Write descriptor failed!");
145 
146     data.WriteUint64(GetGeneration());
147     (void)AVCodecParcel::Marshalling(data, format);
148     CHECK_AND_RETURN_LOG(outputBufferCache_ != nullptr, "Output buffer cache is nullptr");
149     outputBufferCache_->ClearCaches();
150     int error = Remote()->SendRequest(static_cast<uint32_t>(CodecListenerInterfaceCode::ON_OUTPUT_FORMAT_CHANGED), data,
151                                       reply, option);
152     CHECK_AND_RETURN_LOG(error == AVCS_ERR_OK, "Send request failed");
153 }
154 
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)155 void CodecListenerProxy::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
156 {
157     CHECK_AND_RETURN_LOG(inputBufferCache_ != nullptr, "Input buffer cache is nullptr");
158     MessageParcel data;
159     MessageParcel reply;
160     MessageOption option(MessageOption::TF_ASYNC);
161     bool token = data.WriteInterfaceToken(CodecListenerProxy::GetDescriptor());
162     CHECK_AND_RETURN_LOG(token, "Write descriptor failed!");
163 
164     uint64_t currentGeneration = GetGeneration();
165     if (inputBufferGeneration_ != currentGeneration) {
166         inputBufferCache_->ClearCaches();
167         inputBufferGeneration_ = currentGeneration;
168     }
169 
170     data.WriteUint64(inputBufferGeneration_);
171     data.WriteUint32(index);
172     if (buffer != nullptr && buffer->meta_ != nullptr) {
173         buffer->meta_->Clear();
174     }
175     bool ret = inputBufferCache_->WriteToParcel(index, buffer, data);
176     CHECK_AND_RETURN_LOG(ret, "InputBufferCache write parcel failed");
177     int error = Remote()->SendRequest(static_cast<uint32_t>(CodecListenerInterfaceCode::ON_INPUT_BUFFER_AVAILABLE),
178                                       data, reply, option);
179     CHECK_AND_RETURN_LOG(error == AVCS_ERR_OK, "Send request failed");
180 }
181 
OnOutputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)182 void CodecListenerProxy::OnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
183 {
184     CHECK_AND_RETURN_LOG(outputBufferCache_ != nullptr, "Output buffer cache is nullptr");
185     MessageParcel data;
186     MessageParcel reply;
187     MessageOption option(MessageOption::TF_ASYNC);
188     bool token = data.WriteInterfaceToken(CodecListenerProxy::GetDescriptor());
189     CHECK_AND_RETURN_LOG(token, "Write descriptor failed!");
190 
191     uint64_t currentGeneration = GetGeneration();
192     if (outputBufferGeneration_ != currentGeneration) {
193         outputBufferCache_->ClearCaches();
194         outputBufferGeneration_ = currentGeneration;
195     }
196 
197     data.WriteUint64(outputBufferGeneration_);
198     data.WriteUint32(index);
199     bool ret = outputBufferCache_->WriteToParcel(index, buffer, data);
200     CHECK_AND_RETURN_LOG(ret, "OutputBufferCache write parcel failed");
201     int error = Remote()->SendRequest(static_cast<uint32_t>(CodecListenerInterfaceCode::ON_OUTPUT_BUFFER_AVAILABLE),
202                                       data, reply, option);
203     CHECK_AND_RETURN_LOG(error == AVCS_ERR_OK, "Send request failed");
204 }
205 
InputBufferInfoFromParcel(uint32_t index,AVCodecBufferInfo & info,AVCodecBufferFlag & flag,MessageParcel & data)206 bool CodecListenerProxy::InputBufferInfoFromParcel(uint32_t index, AVCodecBufferInfo &info, AVCodecBufferFlag &flag,
207                                                    MessageParcel &data)
208 {
209     std::shared_ptr<AVBuffer> buffer = inputBufferCache_->FindBufferFromIndex(index);
210     CHECK_AND_RETURN_RET_LOG(buffer != nullptr, false, "Input buffer in cache is nullptr");
211     CHECK_AND_RETURN_RET_LOG(buffer->meta_ != nullptr, false, "buffer meta is nullptr");
212     if (buffer->memory_ == nullptr) {
213         return buffer->meta_->FromParcel(data);
214     }
215     uint32_t flagTemp = 0;
216     bool ret = data.ReadInt64(info.presentationTimeUs) && data.ReadInt32(info.offset) && data.ReadInt32(info.size) &&
217                data.ReadUint32(flagTemp);
218     flag = static_cast<AVCodecBufferFlag>(flagTemp);
219     buffer->pts_ = info.presentationTimeUs;
220     buffer->flag_ = flag;
221     buffer->memory_->SetOffset(info.offset);
222     buffer->memory_->SetSize(info.size);
223     return ret && buffer->meta_->FromParcel(data);
224 }
225 
SetOutputBufferRenderTimestamp(uint32_t index,int64_t renderTimestampNs)226 bool CodecListenerProxy::SetOutputBufferRenderTimestamp(uint32_t index, int64_t renderTimestampNs)
227 {
228     std::shared_ptr<AVBuffer> buffer = outputBufferCache_->FindBufferFromIndex(index);
229     CHECK_AND_RETURN_RET_LOG(buffer != nullptr, false, "Input buffer in cache is nullptr");
230     buffer->meta_->SetData(Media::Tag::VIDEO_DECODER_DESIRED_PRESENT_TIMESTAMP, renderTimestampNs);
231     return true;
232 }
233 
ClearListenerCache()234 void CodecListenerProxy::ClearListenerCache()
235 {
236     inputBufferCache_->ClearCaches();
237     outputBufferCache_->ClearCaches();
238 }
239 
CodecListenerCallback(const sptr<IStandardCodecListener> & listener)240 CodecListenerCallback::CodecListenerCallback(const sptr<IStandardCodecListener> &listener) : listener_(listener)
241 {
242     AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
243 }
244 
~CodecListenerCallback()245 CodecListenerCallback::~CodecListenerCallback()
246 {
247     AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
248 }
249 
OnError(AVCodecErrorType errorType,int32_t errorCode)250 void CodecListenerCallback::OnError(AVCodecErrorType errorType, int32_t errorCode)
251 {
252     if (listener_ != nullptr) {
253         listener_->OnError(errorType, errorCode);
254     }
255 }
256 
OnOutputFormatChanged(const Format & format)257 void CodecListenerCallback::OnOutputFormatChanged(const Format &format)
258 {
259     if (listener_ != nullptr) {
260         listener_->OnOutputFormatChanged(format);
261     }
262 }
263 
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)264 void CodecListenerCallback::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
265 {
266     if (listener_ != nullptr) {
267         listener_->OnInputBufferAvailable(index, buffer);
268     }
269 }
270 
OnOutputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)271 void CodecListenerCallback::OnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
272 {
273     if (listener_ != nullptr) {
274         listener_->OnOutputBufferAvailable(index, buffer);
275     }
276 }
277 } // namespace MediaAVCodec
278 } // namespace OHOS
279