• 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_stub.h"
17 #include <shared_mutex>
18 #include <sstream>
19 #include <string>
20 #include "avcodec_errors.h"
21 #include "avcodec_parcel.h"
22 #include "avcodec_trace.h"
23 #include "avsharedmemory_ipc.h"
24 #include "buffer/avsharedmemorybase.h"
25 #include "meta/meta.h"
26 namespace {
27 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "CodecListenerStub"};
28 constexpr uint8_t LOG_FREQ = 10;
29 const int32_t MAX_SIZE = 100;
30 } // namespace
31 
32 namespace OHOS {
33 namespace MediaAVCodec {
34 using namespace Media;
35 class CodecListenerStub::CodecBufferCache : public AVCodecDfxComponent, public NoCopyable {
36 public:
CodecBufferCache(bool isOutput)37     explicit CodecBufferCache(bool isOutput) : isOutput_(isOutput) {}
38     ~CodecBufferCache() = default;
39 
ReadFromParcel(uint32_t index,MessageParcel & parcel,std::shared_ptr<AVBuffer> & buffer)40     bool ReadFromParcel(uint32_t index, MessageParcel &parcel, std::shared_ptr<AVBuffer> &buffer)
41     {
42         std::lock_guard<std::shared_mutex> lock(mutex_);
43         auto iter = caches_.find(index);
44         flag_ = static_cast<CacheFlag>(parcel.ReadUint8());
45         if (flag_ == CacheFlag::HIT_CACHE && iter == caches_.end()) {
46             AVCODEC_LOGW_WITH_TAG("Mark hit cache, but can find the index's cache, index: %{public}u", index);
47             flag_ = CacheFlag::UPDATE_CACHE;
48         }
49         if (flag_ == CacheFlag::HIT_CACHE) {
50             isOutput_ ? HitOutputCache(iter->second, parcel) : HitInputCache(iter->second, parcel);
51             buffer = iter->second;
52             return true;
53         }
54         if (flag_ == CacheFlag::UPDATE_CACHE) {
55             isOutput_ ? UpdateOutputCache(buffer, parcel) : UpdateInputCache(buffer, parcel);
56             if (iter == caches_.end()) {
57                 caches_.emplace(index, buffer);
58             } else {
59                 iter->second = buffer;
60             }
61             return true;
62         }
63         // invalidate cache flag_
64         if (iter != caches_.end()) {
65             caches_.erase(iter);
66         }
67         AVCODEC_LOGE_WITH_TAG("Invalidate cache for index: %{public}u, flag: %{public}hhu", index, flag_);
68         return false;
69     }
70 
GetBuffer(uint32_t index,std::shared_ptr<AVBuffer> & buffer)71     void GetBuffer(uint32_t index, std::shared_ptr<AVBuffer> &buffer)
72     {
73         std::shared_lock<std::shared_mutex> lock(mutex_);
74         if (isFirstSend_) {
75             AVCODEC_LOGI_WITH_TAG("first send buffer to service");
76             isFirstSend_ = false;
77         }
78         auto iter = caches_.find(index);
79         if (iter == caches_.end()) {
80             AVCODEC_LOGE_WITH_TAG("Get cache failed, index: %{public}u", index);
81             return;
82         }
83         buffer = iter->second;
84     }
85 
ClearCaches()86     void ClearCaches()
87     {
88         std::lock_guard<std::shared_mutex> lock(mutex_);
89         isFirstReceive_ = true;
90         isFirstSend_ = true;
91         caches_.clear();
92     }
93 
FlushCaches()94     void FlushCaches()
95     {
96         std::lock_guard<std::shared_mutex> lock(mutex_);
97         isFirstReceive_ = true;
98         isFirstSend_ = true;
99     }
100 
101 private:
HitInputCache(std::shared_ptr<AVBuffer> & buffer,MessageParcel & parcel)102     void HitInputCache(std::shared_ptr<AVBuffer> &buffer, MessageParcel &parcel)
103     {
104         CHECK_AND_RETURN_LOG_WITH_TAG(buffer != nullptr, "buffer is nullptr");
105         bool isReadSuc = buffer->ReadFromMessageParcel(parcel);
106         CHECK_AND_RETURN_LOG_WITH_TAG(isReadSuc, "Read buffer from parcel failed");
107         buffer->flag_ = 0;
108         if (buffer->memory_ != nullptr) {
109             buffer->memory_->SetOffset(0);
110             buffer->memory_->SetSize(0);
111         }
112         if (isFirstReceive_) {
113             AVCODEC_LOGI_WITH_TAG("first receive buffer from service");
114             isFirstReceive_ = false;
115         }
116     }
117 
HitOutputCache(std::shared_ptr<AVBuffer> & buffer,MessageParcel & parcel)118     void HitOutputCache(std::shared_ptr<AVBuffer> &buffer, MessageParcel &parcel)
119     {
120         CHECK_AND_RETURN_LOG_WITH_TAG(buffer != nullptr, "buffer is nullptr");
121         bool isReadSuc = buffer->ReadFromMessageParcel(parcel);
122         CHECK_AND_RETURN_LOG_WITH_TAG(isReadSuc, "Read buffer from parcel failed");
123         if (isFirstReceive_) {
124             AVCODEC_LOGI_WITH_TAG("first receive buffer from service");
125             isFirstReceive_ = false;
126         }
127     }
128 
UpdateInputCache(std::shared_ptr<AVBuffer> & buffer,MessageParcel & parcel)129     void UpdateInputCache(std::shared_ptr<AVBuffer> &buffer, MessageParcel &parcel)
130     {
131         buffer = AVBuffer::CreateAVBuffer();
132         bool isReadSuc = (buffer != nullptr) && buffer->ReadFromMessageParcel(parcel);
133         CHECK_AND_RETURN_LOG_WITH_TAG(isReadSuc, "Create buffer from parcel failed");
134         buffer->flag_ = 0;
135         if (buffer->memory_ != nullptr) {
136             buffer->memory_->SetOffset(0);
137             buffer->memory_->SetSize(0);
138         }
139         if (isFirstReceive_) {
140             AVCODEC_LOGI_WITH_TAG("first receive buffer from service");
141             isFirstReceive_ = false;
142         }
143     }
144 
UpdateOutputCache(std::shared_ptr<AVBuffer> & buffer,MessageParcel & parcel)145     void UpdateOutputCache(std::shared_ptr<AVBuffer> &buffer, MessageParcel &parcel)
146     {
147         buffer = AVBuffer::CreateAVBuffer();
148         bool isReadSuc = (buffer != nullptr) && buffer->ReadFromMessageParcel(parcel);
149         CHECK_AND_RETURN_LOG_WITH_TAG(isReadSuc, "Create buffer from parcel failed");
150         if (isFirstReceive_) {
151             AVCODEC_LOGI_WITH_TAG("first receive buffer from service");
152             isFirstReceive_ = false;
153         }
154     }
155 
156     enum class CacheFlag : uint8_t {
157         HIT_CACHE = 1,
158         UPDATE_CACHE,
159         INVALIDATE_CACHE,
160     };
161     bool isOutput_ = false;
162     bool isFirstReceive_ = true;
163     bool isFirstSend_ = true;
164     CacheFlag flag_ = CacheFlag::INVALIDATE_CACHE;
165     std::shared_mutex mutex_;
166     std::unordered_map<uint32_t, std::shared_ptr<AVBuffer>> caches_;
167 };
168 
CodecListenerStub()169 CodecListenerStub::CodecListenerStub()
170 {
171     if (inputBufferCache_ == nullptr) {
172         inputBufferCache_ = std::make_unique<CodecBufferCache>(false);
173     }
174 
175     if (outputBufferCache_ == nullptr) {
176         outputBufferCache_ = std::make_unique<CodecBufferCache>(true);
177     }
178     AVCODEC_LOGD_WITH_TAG("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
179 }
180 
~CodecListenerStub()181 CodecListenerStub::~CodecListenerStub()
182 {
183     inputBufferCache_ = nullptr;
184     outputBufferCache_ = nullptr;
185     AVCODEC_LOGD_WITH_TAG("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
186 }
187 
Init()188 void CodecListenerStub::Init()
189 {
190     const std::string &tag = this->GetTag();
191     inputBufferCache_->SetTag(tag + "[in]");
192     outputBufferCache_->SetTag(tag + "[out]");
193 }
194 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)195 int CodecListenerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
196 {
197     auto remoteDescriptor = data.ReadInterfaceToken();
198     CHECK_AND_RETURN_RET_LOG_WITH_TAG(CodecListenerStub::GetDescriptor() == remoteDescriptor,
199                                       AVCS_ERR_INVALID_OPERATION, "Invalid descriptor");
200     CHECK_AND_RETURN_RET_LOG_WITH_TAG(inputBufferCache_ != nullptr, AVCS_ERR_INVALID_OPERATION,
201                                       "inputBufferCache is nullptr");
202     CHECK_AND_RETURN_RET_LOG_WITH_TAG(outputBufferCache_ != nullptr, AVCS_ERR_INVALID_OPERATION,
203                                       "outputBufferCache is nullptr");
204 
205     CHECK_AND_RETURN_RET_LOG_WITH_TAG(syncMutex_ != nullptr, AVCS_ERR_INVALID_OPERATION, "sync mutex is nullptr");
206     std::lock_guard<std::recursive_mutex> lock(*syncMutex_);
207     if (!needListen_ || !CheckGeneration(data.ReadUint64())) {
208         AVCODEC_LOGW_LIMIT(LOG_FREQ, "abandon message");
209         return AVCS_ERR_OK;
210     }
211     switch (code) {
212         case static_cast<uint32_t>(CodecListenerInterfaceCode::ON_ERROR): {
213             int32_t errorType = data.ReadInt32();
214             int32_t errorCode = data.ReadInt32();
215             OnError(static_cast<AVCodecErrorType>(errorType), errorCode);
216             return AVCS_ERR_OK;
217         }
218         case static_cast<uint32_t>(CodecListenerInterfaceCode::ON_OUTPUT_FORMAT_CHANGED): {
219             Format format;
220             (void)AVCodecParcel::Unmarshalling(data, format);
221             outputBufferCache_->ClearCaches();
222             OnOutputFormatChanged(format);
223             return AVCS_ERR_OK;
224         }
225         case static_cast<uint32_t>(CodecListenerInterfaceCode::ON_INPUT_BUFFER_AVAILABLE): {
226             uint32_t index = data.ReadUint32();
227             OnInputBufferAvailable(index, data);
228             return AVCS_ERR_OK;
229         }
230         case static_cast<uint32_t>(CodecListenerInterfaceCode::ON_OUTPUT_BUFFER_AVAILABLE): {
231             uint32_t index = data.ReadUint32();
232             OnOutputBufferAvailable(index, data);
233             return AVCS_ERR_OK;
234         }
235         default: {
236             return OnRequestExtras(code, data, reply, option);
237         }
238     }
239 }
240 
OnRequestExtras(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)241 int CodecListenerStub::OnRequestExtras(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
242 {
243     switch (code) {
244         case static_cast<uint32_t>(CodecListenerInterfaceCode::ON_OUTPUT_BUFFER_BINDED): {
245             OnOutputBufferBinded(data);
246             return AVCS_ERR_OK;
247         }
248         case static_cast<uint32_t>(CodecListenerInterfaceCode::ON_OUTPUT_BUFFER_UN_BINDED): {
249             OnOutputBufferUnbinded(data);
250             return AVCS_ERR_OK;
251         }
252         default: {
253             AVCODEC_LOGE_WITH_TAG("Default case, please check codec listener stub");
254             return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
255         }
256     }
257 }
258 
OnError(AVCodecErrorType errorType,int32_t errorCode)259 void CodecListenerStub::OnError(AVCodecErrorType errorType, int32_t errorCode)
260 {
261     std::shared_ptr<MediaCodecCallback> vCb = callback_.lock();
262     if (vCb != nullptr) {
263         vCb->OnError(errorType, errorCode);
264         return;
265     }
266 }
267 
OnOutputFormatChanged(const Format & format)268 void CodecListenerStub::OnOutputFormatChanged(const Format &format)
269 {
270     std::shared_ptr<MediaCodecCallback> vCb = callback_.lock();
271     if (vCb != nullptr) {
272         vCb->OnOutputFormatChanged(format);
273         return;
274     }
275 }
276 
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)277 void CodecListenerStub::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
278 {
279     (void)index;
280     (void)buffer;
281 }
282 
OnOutputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)283 void CodecListenerStub::OnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
284 {
285     (void)index;
286     (void)buffer;
287 }
288 
OnOutputBufferBinded(std::map<uint32_t,sptr<SurfaceBuffer>> & bufferMap)289 void CodecListenerStub::OnOutputBufferBinded(std::map<uint32_t, sptr<SurfaceBuffer>> &bufferMap)
290 {
291     (void)bufferMap;
292 }
OnOutputBufferUnbinded()293 void CodecListenerStub::OnOutputBufferUnbinded()
294 {
295 }
296 
OnInputBufferAvailable(uint32_t index,MessageParcel & data)297 void CodecListenerStub::OnInputBufferAvailable(uint32_t index, MessageParcel &data)
298 {
299     std::shared_ptr<AVBuffer> buffer;
300     std::shared_ptr<MediaCodecCallback> mediaCb = callback_.lock();
301     if (mediaCb != nullptr) {
302         bool ret = inputBufferCache_->ReadFromParcel(index, data, buffer);
303         CHECK_AND_RETURN_LOG_WITH_TAG(ret, "read from parel failed");
304         mediaCb->OnInputBufferAvailable(index, buffer);
305         return;
306     }
307 }
308 
OnOutputBufferAvailable(uint32_t index,MessageParcel & data)309 void CodecListenerStub::OnOutputBufferAvailable(uint32_t index, MessageParcel &data)
310 {
311     std::shared_ptr<AVBuffer> buffer;
312     std::shared_ptr<MediaCodecCallback> mediaCb = callback_.lock();
313     if (mediaCb != nullptr) {
314         bool ret = outputBufferCache_->ReadFromParcel(index, data, buffer);
315         CHECK_AND_RETURN_LOG_WITH_TAG(ret, "read from parel failed");
316         mediaCb->OnOutputBufferAvailable(index, buffer);
317         return;
318     }
319 }
320 
OnOutputBufferBinded(MessageParcel & data)321 void CodecListenerStub::OnOutputBufferBinded(MessageParcel &data)
322 {
323     std::shared_ptr<MediaCodecCallback> mediaCb = callback_.lock();
324     if (mediaCb != nullptr) {
325         std::map<uint32_t, sptr<SurfaceBuffer>> bufferMap;
326         const MediaAVCodec::Format format;
327         uint32_t size = data.ReadUint32();
328         if (size > MAX_SIZE) {
329             bufferMap.clear();
330             return;
331         }
332         for (uint32_t i = 0; i < size; i++) {
333             uint32_t key = data.ReadUint32();
334             sptr<SurfaceBuffer> surfaceBuffer = SurfaceBuffer::Create();
335             surfaceBuffer->ReadFromMessageParcel(data);
336             bufferMap.emplace(key, surfaceBuffer);
337         }
338         AVCODEC_LOGI("LowPowerPlayer CodecListenerStub OnOutputBufferBinded Write Map Success");
339         mediaCb->OnOutputBufferBinded(bufferMap);
340         return;
341     }
342 }
343 
OnOutputBufferUnbinded(MessageParcel & data)344 void CodecListenerStub::OnOutputBufferUnbinded(MessageParcel &data)
345 {
346     AVCODEC_LOGI("LowPowerPlayer CodecListenerStub OnOutputBufferUnbinded Enter");
347     std::shared_ptr<MediaCodecCallback> mediaCb = callback_.lock();
348     CHECK_AND_RETURN_LOG(mediaCb != nullptr, "mediaCb is nullptr");
349     mediaCb->OnOutputBufferUnbinded();
350 }
351 
SetCallback(const std::shared_ptr<MediaCodecCallback> & callback)352 void CodecListenerStub::SetCallback(const std::shared_ptr<MediaCodecCallback> &callback)
353 {
354     callback_ = callback;
355 }
356 
ClearListenerCache()357 void CodecListenerStub::ClearListenerCache()
358 {
359     inputBufferCache_->ClearCaches();
360     outputBufferCache_->ClearCaches();
361 }
362 
FlushListenerCache()363 void CodecListenerStub::FlushListenerCache()
364 {
365     inputBufferCache_->FlushCaches();
366     outputBufferCache_->FlushCaches();
367 }
368 
WriteInputBufferToParcel(uint32_t index,MessageParcel & data)369 bool CodecListenerStub::WriteInputBufferToParcel(uint32_t index, MessageParcel &data)
370 {
371     std::shared_ptr<AVBuffer> buffer = nullptr;
372     inputBufferCache_->GetBuffer(index, buffer);
373     CHECK_AND_RETURN_RET_LOG_WITH_TAG(buffer != nullptr, false, "Get buffer is nullptr");
374     CHECK_AND_RETURN_RET_LOG_WITH_TAG(buffer->meta_ != nullptr, false, "Get buffer meta is nullptr");
375     if (buffer->memory_ == nullptr) {
376         return buffer->meta_->ToParcel(data);
377     }
378     return data.WriteInt64(buffer->pts_) && data.WriteInt32(buffer->memory_->GetOffset()) &&
379            data.WriteInt32(buffer->memory_->GetSize()) && data.WriteUint32(buffer->flag_) &&
380            buffer->meta_->ToParcel(data);
381 }
382 
WriteOutputBufferToParcel(uint32_t index,MessageParcel & data)383 bool CodecListenerStub::WriteOutputBufferToParcel(uint32_t index, MessageParcel &data)
384 {
385     (void)data;
386     std::shared_ptr<AVBuffer> buffer = nullptr;
387     outputBufferCache_->GetBuffer(index, buffer);
388     return true;
389 }
390 
CheckGeneration(uint64_t messageGeneration) const391 bool CodecListenerStub::CheckGeneration(uint64_t messageGeneration) const
392 {
393     return messageGeneration >= GetGeneration();
394 }
395 
SetMutex(std::shared_ptr<std::recursive_mutex> & mutex)396 void CodecListenerStub::SetMutex(std::shared_ptr<std::recursive_mutex> &mutex)
397 {
398     syncMutex_ = mutex;
399 }
400 
SetNeedListen(const bool needListen)401 void CodecListenerStub::SetNeedListen(const bool needListen)
402 {
403     needListen_ = needListen;
404 }
405 } // namespace MediaAVCodec
406 } // namespace OHOS
407