• 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_client.h"
17 #include <cmath>
18 #include "avcodec_errors.h"
19 #include "avcodec_trace.h"
20 #include "codec_service_proxy.h"
21 #include "meta/meta_key.h"
22 
23 using namespace OHOS::Media;
24 namespace {
25 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "CodecClient"};
ErrorToStr(int32_t ret)26 inline std::string ErrorToStr(int32_t ret)
27 {
28     return AVCSErrorToString(static_cast<OHOS::MediaAVCodec::AVCodecServiceErrCode>((ret)));
29 }
30 } // namespace
31 namespace OHOS {
32 namespace MediaAVCodec {
Create(const sptr<IStandardCodecService> & ipcProxy,std::shared_ptr<ICodecService> & codec)33 int32_t CodecClient::Create(const sptr<IStandardCodecService> &ipcProxy, std::shared_ptr<ICodecService> &codec)
34 {
35     CHECK_AND_RETURN_RET_LOG(ipcProxy != nullptr, AVCS_ERR_INVALID_VAL, "Ipc proxy is nullptr");
36 
37     std::shared_ptr<CodecClient> codecClient = std::make_shared<CodecClient>(ipcProxy);
38     CHECK_AND_RETURN_RET_LOG(codecClient != nullptr, AVCS_ERR_UNKNOWN, "Codec client is nullptr");
39 
40     int32_t ret = codecClient->CreateListenerObject();
41     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Codec client create failed");
42     codec = codecClient;
43 
44     AVCODEC_LOGI("%{public}s", ErrorToStr(ret).c_str());
45     return AVCS_ERR_OK;
46 }
47 
CodecClient(const sptr<IStandardCodecService> & ipcProxy)48 CodecClient::CodecClient(const sptr<IStandardCodecService> &ipcProxy)
49     : codecProxy_(ipcProxy),
50       converter_(std::make_shared<BufferConverter>()),
51       syncMutex_(std::make_shared<std::recursive_mutex>())
52 {
53     AVCODEC_LOGI_WITH_TAG("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
54 }
55 
~CodecClient()56 CodecClient::~CodecClient()
57 {
58     std::scoped_lock lock(mutex_, *syncMutex_);
59     if (codecProxy_ != nullptr) {
60         (void)codecProxy_->DestroyStub();
61         SetNeedListen(false);
62         circular_.SetIsRunning(false);
63     }
64     AVCODEC_LOGI_WITH_TAG("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
65 }
66 
AVCodecServerDied()67 void CodecClient::AVCodecServerDied()
68 {
69     {
70         std::scoped_lock lock(mutex_, *syncMutex_);
71         codecProxy_ = nullptr;
72         listenerStub_ = nullptr;
73     }
74     OnError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_SERVICE_DIED);
75 }
76 
CreateListenerObject()77 int32_t CodecClient::CreateListenerObject()
78 {
79     std::lock_guard<std::shared_mutex> lock(mutex_);
80     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
81 
82     listenerStub_ = new (std::nothrow) CodecListenerStub();
83     CHECK_AND_RETURN_RET_LOG_WITH_TAG(listenerStub_ != nullptr, AVCS_ERR_NO_MEMORY,
84                                       "Codec listener stub create failed");
85     const std::shared_ptr<MediaCodecCallback> callback = shared_from_this();
86     listenerStub_->SetCallback(callback);
87     listenerStub_->SetMutex(syncMutex_);
88 
89     sptr<IRemoteObject> object = listenerStub_->AsObject();
90     CHECK_AND_RETURN_RET_LOG_WITH_TAG(object != nullptr, AVCS_ERR_NO_MEMORY, "Listener object is nullptr");
91 
92     int32_t ret = codecProxy_->SetListenerObject(object);
93     if (ret == AVCS_ERR_OK) {
94         UpdateGeneration();
95     }
96     auto codecProxy = static_cast<CodecServiceProxy *>(codecProxy_.GetRefPtr());
97     codecProxy->SetListener(listenerStub_);
98     AVCODEC_LOGI_WITH_TAG("%{public}s", ErrorToStr(ret).c_str());
99     return ret;
100 }
101 
Init(AVCodecType type,bool isMimeType,const std::string & name,Meta & callerInfo,API_VERSION apiVersion)102 int32_t CodecClient::Init(AVCodecType type, bool isMimeType, const std::string &name, Meta &callerInfo,
103                           API_VERSION apiVersion)
104 {
105     (void)apiVersion;
106     using namespace OHOS::Media;
107     callerInfo.SetData(Tag::AV_CODEC_CALLER_PID, getprocpid());
108     callerInfo.SetData(Tag::AV_CODEC_CALLER_UID, getuid());
109     callerInfo.SetData(Tag::AV_CODEC_CALLER_PROCESS_NAME, std::string(program_invocation_name));
110 
111     std::lock_guard<std::shared_mutex> lock(mutex_);
112     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr && listenerStub_ != nullptr && converter_ != nullptr,
113                                       AVCS_ERR_NO_MEMORY, "Server not exist");
114     auto codecProxy = static_cast<CodecServiceProxy *>(codecProxy_.GetRefPtr());
115     int32_t ret = codecProxy->Init(type, isMimeType, name, callerInfo);
116     const std::string tag = CreateVideoLogTag(callerInfo);
117     this->SetTag(tag);
118     converter_->SetTag(tag);
119     codecProxy->SetTag(tag);
120     listenerStub_->SetTag(tag);
121     circular_.SetTag(tag);
122     circular_.SetConverter(converter_);
123 
124     converter_->Init(type);
125     listenerStub_->Init();
126     type_ = type;
127     AVCODEC_LOGI_WITH_TAG("%{public}s", ErrorToStr(ret).c_str());
128     return ret;
129 }
130 
Configure(const Format & format)131 int32_t CodecClient::Configure(const Format &format)
132 {
133     std::lock_guard<std::shared_mutex> lock(mutex_);
134     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
135     CHECK_AND_RETURN_RET_LOG_WITH_TAG(!isConfigured_, AVCS_ERR_INVALID_STATE, "Is configured");
136     // check sync mode
137     int32_t enableSyncMode = 0;
138     (void)format.GetIntValue(Tag::AV_CODEC_ENABLE_SYNC_MODE, enableSyncMode);
139     if (enableSyncMode) {
140         CHECK_AND_RETURN_RET_LOG_WITH_TAG(circular_.CanEnableSyncMode(), AVCS_ERR_INVALID_OPERATION,
141                                           "Can not enable sync mode");
142         codecMode_ &= ~CODEC_ENABLE_PARAMETER;
143     }
144     if (codecMode_ & CODEC_ENABLE_PARAMETER) {
145         const_cast<Format &>(format).PutIntValue(Tag::VIDEO_ENCODER_ENABLE_SURFACE_INPUT_CALLBACK, 1);
146     }
147     // notify service to configure
148     int32_t ret = codecProxy_->Configure(format);
149     CHECK_AND_RETURN_RET_LOG_WITH_TAG(ret == AVCS_ERR_OK, ret, "%{public}s", ErrorToStr(ret).c_str());
150     // update client flag
151     enableSyncMode ? circular_.EnableSyncMode() : circular_.EnableAsyncMode();
152     isConfigured_ = true;
153     AVCODEC_LOGI_WITH_TAG("%{public}s", format.Stringify().c_str());
154     AVCODEC_LOGI_WITH_TAG("success. %{public}s mode", enableSyncMode ? "Sync" : "Async");
155     return AVCS_ERR_OK;
156 }
157 
Prepare()158 int32_t CodecClient::Prepare()
159 {
160     std::lock_guard<std::shared_mutex> lock(mutex_);
161     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
162 
163     int32_t ret = codecProxy_->Prepare();
164     AVCODEC_LOGI_WITH_TAG("%{public}s", ErrorToStr(ret).c_str());
165 
166     return ret;
167 }
168 
SetCustomBuffer(std::shared_ptr<AVBuffer> buffer)169 int32_t CodecClient::SetCustomBuffer(std::shared_ptr<AVBuffer> buffer)
170 {
171     std::lock_guard<std::shared_mutex> lock(mutex_);
172     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
173     CHECK_AND_RETURN_RET_LOG_WITH_TAG(buffer != nullptr, AVCS_ERR_INVALID_VAL, "buffer is nullptr");
174 
175     int32_t ret = codecProxy_->SetCustomBuffer(buffer);
176     AVCODEC_LOGI_WITH_TAG("%{public}s", ErrorToStr(ret).c_str());
177     return ret;
178 }
179 
NotifyMemoryExchange(const bool exchangeFlag)180 int32_t CodecClient::NotifyMemoryExchange(const bool exchangeFlag)
181 {
182     std::lock_guard<std::shared_mutex> lock(mutex_);
183     CHECK_AND_RETURN_RET_LOG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
184 
185     int32_t ret = codecProxy_->NotifyMemoryExchange(exchangeFlag);
186     AVCODEC_LOGI_WITH_TAG("%{public}s", ErrorToStr(ret).c_str());
187     return ret;
188 }
189 
Start()190 int32_t CodecClient::Start()
191 {
192     std::lock_guard<std::shared_mutex> lock(mutex_);
193     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
194     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecMode_ != CODEC_ENABLE_PARAMETER, AVCS_ERR_INVALID_STATE,
195                                       "Not get input surface");
196 
197     SetNeedListen(true);
198     circular_.SetIsRunning(true);
199     int32_t ret = codecProxy_->Start();
200     if (ret == AVCS_ERR_OK) {
201         needUpdateGeneration_ = true;
202     } else {
203         bool isRunning = needUpdateGeneration_;
204         SetNeedListen(isRunning);
205         circular_.SetIsRunning(isRunning);
206     }
207     AVCODEC_LOGI_WITH_TAG("%{public}s", ErrorToStr(ret).c_str());
208     return ret;
209 }
210 
Stop()211 int32_t CodecClient::Stop()
212 {
213     {
214         std::scoped_lock lock(mutex_, *syncMutex_);
215         CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
216         int32_t ret = codecProxy_->Stop();
217         CHECK_AND_RETURN_RET_LOG_WITH_TAG(ret == AVCS_ERR_OK, ret, "%{public}s", ErrorToStr(ret).c_str());
218         SetNeedListen(false);
219         circular_.SetIsRunning(false);
220         circular_.ClearCaches();
221     }
222     UpdateGeneration();
223     AVCODEC_LOGI_WITH_TAG("success");
224     return AVCS_ERR_OK;
225 }
226 
Flush()227 int32_t CodecClient::Flush()
228 {
229     {
230         std::scoped_lock lock(mutex_, *syncMutex_);
231         CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
232         int32_t ret = codecProxy_->Flush();
233         CHECK_AND_RETURN_RET_LOG_WITH_TAG(ret == AVCS_ERR_OK, ret, "%{public}s", ErrorToStr(ret).c_str());
234         SetNeedListen(false);
235         circular_.SetIsRunning(false); // current state: FLUSHED
236         circular_.FlushCaches();
237     }
238     UpdateGeneration();
239     AVCODEC_LOGI_WITH_TAG("success");
240     return AVCS_ERR_OK;
241 }
242 
NotifyEos()243 int32_t CodecClient::NotifyEos()
244 {
245     std::lock_guard<std::shared_mutex> lock(mutex_);
246     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
247 
248     int32_t ret = codecProxy_->NotifyEos();
249     CHECK_AND_RETURN_RET_LOG_WITH_TAG(ret == AVCS_ERR_OK, ret, "%{public}s", ErrorToStr(ret).c_str());
250     circular_.NotifyEos();
251     AVCODEC_LOGI_WITH_TAG("success");
252     return AVCS_ERR_OK;
253 }
254 
Reset()255 int32_t CodecClient::Reset()
256 {
257     {
258         std::scoped_lock lock(mutex_, *syncMutex_);
259         CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
260         int32_t ret = codecProxy_->Reset();
261         CHECK_AND_RETURN_RET_LOG_WITH_TAG(ret == AVCS_ERR_OK, ret, "%{public}s", ErrorToStr(ret).c_str());
262         SetNeedListen(false);
263         circular_.SetIsRunning(false);
264         circular_.ClearCaches();
265         circular_.ResetFlag();
266         codecMode_ &= ~CODEC_SURFACE_OUTPUT;
267         isConfigured_ = false;
268         if (converter_ != nullptr) {
269             converter_->NeedToResetFormatOnce();
270         }
271     }
272     UpdateGeneration();
273     AVCODEC_LOGI_WITH_TAG("success");
274     return AVCS_ERR_OK;
275 }
276 
Release()277 int32_t CodecClient::Release()
278 {
279     std::scoped_lock lock(mutex_, *syncMutex_);
280     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
281 
282     int32_t ret = codecProxy_->Release();
283     AVCODEC_LOGI_WITH_TAG("%{public}s", ErrorToStr(ret).c_str());
284     (void)codecProxy_->DestroyStub();
285     SetNeedListen(false);
286     codecProxy_ = nullptr;
287     listenerStub_ = nullptr;
288     return ret;
289 }
290 
GetChannelId(int32_t & channelId)291 int32_t CodecClient::GetChannelId(int32_t &channelId)
292 {
293     std::scoped_lock lock(mutex_, *syncMutex_);
294     CHECK_AND_RETURN_RET_LOG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
295 
296     int32_t ret = codecProxy_->GetChannelId(channelId);
297     EXPECT_AND_LOGI(ret == AVCS_ERR_OK, "Succeed");
298     return ret;
299 }
300 
CreateInputSurface()301 sptr<OHOS::Surface> CodecClient::CreateInputSurface()
302 {
303     std::lock_guard<std::shared_mutex> lock(mutex_);
304     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, nullptr, "Server not exist");
305 
306     auto ret = codecProxy_->CreateInputSurface();
307     AVCODEC_LOGI_WITH_TAG("%{public}s", (ret != nullptr) ? "succeed" : "failed");
308     if (ret != nullptr) {
309         codecMode_ |= CODEC_SURFACE_INPUT;
310     }
311     return ret;
312 }
313 
SetOutputSurface(sptr<Surface> surface)314 int32_t CodecClient::SetOutputSurface(sptr<Surface> surface)
315 {
316     std::lock_guard<std::shared_mutex> lock(mutex_);
317     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
318 
319     int32_t ret = codecProxy_->SetOutputSurface(surface);
320     AVCODEC_LOGI_WITH_TAG("%{public}s", ErrorToStr(ret).c_str());
321     if (ret == AVCS_ERR_OK) {
322         codecMode_ |= CODEC_SURFACE_OUTPUT;
323     }
324     return ret;
325 }
326 
SetLowPowerPlayerMode(bool isLpp)327 int32_t CodecClient::SetLowPowerPlayerMode(bool isLpp)
328 {
329     std::lock_guard<std::shared_mutex> lock(mutex_);
330     CHECK_AND_RETURN_RET_LOG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
331 
332     int32_t ret = codecProxy_->SetLowPowerPlayerMode(isLpp);
333     EXPECT_AND_LOGI(ret == AVCS_ERR_OK, "Succeed");
334     return ret;
335 }
336 
QueueInputBuffer(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag)337 int32_t CodecClient::QueueInputBuffer(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag)
338 {
339     std::shared_lock<std::shared_mutex> lock(mutex_);
340     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
341     CHECK_AND_RETURN_RET_LOG_WITH_TAG(callbackMode_ == MEMORY_CALLBACK, AVCS_ERR_INVALID_STATE,
342                                       "The callback of AVSharedMemory is invalid!");
343     CHECK_AND_RETURN_RET_LOG_WITH_TAG(!(codecMode_ & CODEC_SURFACE_INPUT), AVCS_ERR_INVALID_OPERATION,
344                                       "Input is the surface");
345     int32_t ret = circular_.HandleInputBuffer(index, info, flag);
346     if (ret == AVCS_ERR_OK) {
347         ret = codecProxy_->QueueInputBuffer(index, info, flag);
348     }
349     CHECK_AND_RETURN_RET_LOG_WITH_TAG(ret == AVCS_ERR_OK, ret, "%{public}s.idx:%{public}u", ErrorToStr(ret).c_str(),
350                                       index);
351     circular_.QueueInputBufferDone(index);
352     return AVCS_ERR_OK;
353 }
354 
QueueInputBuffer(uint32_t index)355 int32_t CodecClient::QueueInputBuffer(uint32_t index)
356 {
357     std::shared_lock<std::shared_mutex> lock(mutex_);
358     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
359     CHECK_AND_RETURN_RET_LOG_WITH_TAG(callbackMode_ == BUFFER_CALLBACK || circular_.IsSyncMode(),
360                                       AVCS_ERR_INVALID_STATE, "The callback of AVBuffer is invalid in async mode");
361     CHECK_AND_RETURN_RET_LOG_WITH_TAG(!(codecMode_ & CODEC_SURFACE_INPUT), AVCS_ERR_INVALID_OPERATION,
362                                       "Input is the surface");
363     int32_t ret = circular_.HandleInputBuffer(index);
364     if (ret == AVCS_ERR_OK) {
365         ret = codecProxy_->QueueInputBuffer(index);
366     }
367     CHECK_AND_RETURN_RET_LOG_WITH_TAG(ret == AVCS_ERR_OK, ret, "%{public}s.idx:%{public}u", ErrorToStr(ret).c_str(),
368                                       index);
369     circular_.QueueInputBufferDone(index);
370     return AVCS_ERR_OK;
371 }
372 
QueueInputParameter(uint32_t index)373 int32_t CodecClient::QueueInputParameter(uint32_t index)
374 {
375     std::shared_lock<std::shared_mutex> lock(mutex_);
376     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
377     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecMode_ == CODEC_SURFACE_MODE_WITH_PARAMETER, AVCS_ERR_INVALID_OPERATION,
378                                       "Need to enable input parameter");
379     int32_t ret = circular_.HandleInputBuffer(index);
380     if (ret == AVCS_ERR_OK) {
381         ret = codecProxy_->QueueInputParameter(index);
382     }
383     CHECK_AND_RETURN_RET_LOG_WITH_TAG(ret == AVCS_ERR_OK, ret, "%{public}s.idx:%{public}u", ErrorToStr(ret).c_str(),
384                                       index);
385     circular_.QueueInputBufferDone(index);
386     return AVCS_ERR_OK;
387 }
388 
GetOutputFormat(Format & format)389 int32_t CodecClient::GetOutputFormat(Format &format)
390 {
391     std::lock_guard<std::shared_mutex> lock(mutex_);
392     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
393     int32_t ret = codecProxy_->GetOutputFormat(format);
394     UpdateFormat(format);
395     AVCODEC_LOGD_WITH_TAG("%{public}s", ErrorToStr(ret).c_str());
396     return ret;
397 }
398 
399 #ifdef SUPPORT_DRM
SetDecryptConfig(const sptr<DrmStandard::IMediaKeySessionService> & keySession,const bool svpFlag)400 int32_t CodecClient::SetDecryptConfig(const sptr<DrmStandard::IMediaKeySessionService> &keySession, const bool svpFlag)
401 {
402     std::lock_guard<std::shared_mutex> lock(mutex_);
403     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_INVALID_OPERATION, "Server not exist");
404     CHECK_AND_RETURN_RET_LOG_WITH_TAG(keySession != nullptr, AVCS_ERR_INVALID_OPERATION, "Server not exist");
405 
406     int32_t ret = codecProxy_->SetDecryptConfig(keySession, svpFlag);
407     AVCODEC_LOGI_WITH_TAG("%{public}s", ErrorToStr(ret).c_str());
408     return ret;
409 }
410 #endif
411 
ReleaseOutputBuffer(uint32_t index,bool render)412 int32_t CodecClient::ReleaseOutputBuffer(uint32_t index, bool render)
413 {
414     std::shared_lock<std::shared_mutex> lock(mutex_);
415     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
416     CHECK_AND_RETURN_RET_LOG_WITH_TAG(callbackMode_ != INVALID_CALLBACK || circular_.IsSyncMode(),
417                                       AVCS_ERR_INVALID_STATE, "The callback is invalid!");
418     CHECK_AND_RETURN_RET_LOG_WITH_TAG(!render || (codecMode_ & CODEC_SURFACE_OUTPUT), AVCS_ERR_INVALID_OPERATION,
419                                       "Need to set output surface");
420     int32_t ret = circular_.HandleOutputBuffer(index);
421     if (ret == AVCS_ERR_OK) {
422         ret = codecProxy_->ReleaseOutputBuffer(index, render);
423     }
424     CHECK_AND_RETURN_RET_LOG_WITH_TAG(ret == AVCS_ERR_OK, ret, "%{public}s.idx:%{public}u", ErrorToStr(ret).c_str(),
425                                       index);
426     circular_.ReleaseOutputBufferDone(index);
427     return AVCS_ERR_OK;
428 }
429 
RenderOutputBufferAtTime(uint32_t index,int64_t renderTimestampNs)430 int32_t CodecClient::RenderOutputBufferAtTime(uint32_t index, int64_t renderTimestampNs)
431 {
432     std::shared_lock<std::shared_mutex> lock(mutex_);
433     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
434     CHECK_AND_RETURN_RET_LOG_WITH_TAG(callbackMode_ != INVALID_CALLBACK || circular_.IsSyncMode(),
435                                       AVCS_ERR_INVALID_STATE, "The callback is invalid!");
436     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecMode_ & CODEC_SURFACE_OUTPUT, AVCS_ERR_INVALID_OPERATION,
437                                       "Need to set output surface");
438     CHECK_AND_RETURN_RET_LOG_WITH_TAG(renderTimestampNs >= 0, AVCS_ERR_INVALID_VAL,
439                                       "The renderTimestamp:%{public}" PRId64 " value error", renderTimestampNs);
440     int32_t ret = circular_.HandleOutputBuffer(index);
441     if (ret == AVCS_ERR_OK) {
442         ret = codecProxy_->RenderOutputBufferAtTime(index, renderTimestampNs);
443     }
444     CHECK_AND_RETURN_RET_LOG_WITH_TAG(ret == AVCS_ERR_OK, ret, "%{public}s.idx:%{public}u", ErrorToStr(ret).c_str(),
445                                       index);
446     circular_.ReleaseOutputBufferDone(index);
447     return AVCS_ERR_OK;
448 }
449 
QueryInputBuffer(uint32_t & index,int64_t timeoutUs)450 int32_t CodecClient::QueryInputBuffer(uint32_t &index, int64_t timeoutUs)
451 {
452     {
453         std::shared_lock<std::shared_mutex> lock(mutex_);
454         CHECK_AND_RETURN_RET_LOG_WITH_TAG(!(codecMode_ & CODEC_SURFACE_INPUT), AVCS_ERR_INVALID_OPERATION,
455                                           "Input is the surface");
456     }
457     return circular_.QueryInputBuffer(index, timeoutUs);
458 }
459 
QueryOutputBuffer(uint32_t & index,int64_t timeoutUs)460 int32_t CodecClient::QueryOutputBuffer(uint32_t &index, int64_t timeoutUs)
461 {
462     return circular_.QueryOutputBuffer(index, timeoutUs);
463 }
464 
GetInputBuffer(uint32_t index)465 std::shared_ptr<AVBuffer> CodecClient::GetInputBuffer(uint32_t index)
466 {
467     {
468         std::shared_lock<std::shared_mutex> lock(mutex_);
469         CHECK_AND_RETURN_RET_LOG_WITH_TAG(!(codecMode_ & CODEC_SURFACE_INPUT), nullptr, "Input is the surface");
470     }
471     return circular_.GetInputBuffer(index);
472 }
473 
GetOutputBuffer(uint32_t index)474 std::shared_ptr<AVBuffer> CodecClient::GetOutputBuffer(uint32_t index)
475 {
476     return circular_.GetOutputBuffer(index);
477 }
478 
SetParameter(const Format & format)479 int32_t CodecClient::SetParameter(const Format &format)
480 {
481     std::lock_guard<std::shared_mutex> lock(mutex_);
482     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
483 
484     int32_t ret = codecProxy_->SetParameter(format);
485     AVCODEC_LOGI_WITH_TAG("%{public}s", ErrorToStr(ret).c_str());
486     return ret;
487 }
488 
SetCallback(const std::shared_ptr<AVCodecCallback> & callback)489 int32_t CodecClient::SetCallback(const std::shared_ptr<AVCodecCallback> &callback)
490 {
491     std::scoped_lock lock(mutex_, *syncMutex_);
492     CHECK_AND_RETURN_RET_LOG_WITH_TAG(callback != nullptr, AVCS_ERR_NO_MEMORY, "Callback is nullptr");
493     CHECK_AND_RETURN_RET_LOG_WITH_TAG(callbackMode_ == MEMORY_CALLBACK || callbackMode_ == INVALID_CALLBACK,
494                                       AVCS_ERR_INVALID_STATE, "The callback of AVBuffer is already set!");
495 
496     int32_t ret = circular_.SetCallback(callback);
497     if (ret == AVCS_ERR_OK) {
498         callbackMode_ = MEMORY_CALLBACK;
499     }
500     AVCODEC_LOGI_WITH_TAG("AVSharedMemory callback.%{public}s", ErrorToStr(ret).c_str());
501     return ret;
502 }
503 
SetCallback(const std::shared_ptr<MediaCodecCallback> & callback)504 int32_t CodecClient::SetCallback(const std::shared_ptr<MediaCodecCallback> &callback)
505 {
506     std::scoped_lock lock(mutex_, *syncMutex_);
507     CHECK_AND_RETURN_RET_LOG_WITH_TAG(callback != nullptr, AVCS_ERR_NO_MEMORY, "Callback is nullptr");
508     CHECK_AND_RETURN_RET_LOG_WITH_TAG(callbackMode_ == BUFFER_CALLBACK || callbackMode_ == INVALID_CALLBACK,
509                                       AVCS_ERR_INVALID_STATE, "The callback of AVSharedMemory is already set!");
510 
511     int32_t ret = circular_.SetCallback(callback);
512     if (ret == AVCS_ERR_OK) {
513         callbackMode_ = BUFFER_CALLBACK;
514     }
515     AVCODEC_LOGI_WITH_TAG("AVBuffer callback.%{public}s", ErrorToStr(ret).c_str());
516     return ret;
517 }
518 
SetCallback(const std::shared_ptr<MediaCodecParameterCallback> & callback)519 int32_t CodecClient::SetCallback(const std::shared_ptr<MediaCodecParameterCallback> &callback)
520 {
521     std::scoped_lock lock(mutex_, *syncMutex_);
522     CHECK_AND_RETURN_RET_LOG_WITH_TAG(callback != nullptr, AVCS_ERR_NO_MEMORY, "Callback is nullptr");
523     CHECK_AND_RETURN_RET_LOG_WITH_TAG(!isConfigured_, AVCS_ERR_INVALID_STATE, "Need to be configured before!");
524 
525     int32_t ret = circular_.SetCallback(callback);
526     if (ret == AVCS_ERR_OK) {
527         codecMode_ |= CODEC_ENABLE_PARAMETER;
528     }
529     AVCODEC_LOGI_WITH_TAG("Parameter callback.%{public}s", ErrorToStr(ret).c_str());
530     return ret;
531 }
532 
SetCallback(const std::shared_ptr<MediaCodecParameterWithAttrCallback> & callback)533 int32_t CodecClient::SetCallback(const std::shared_ptr<MediaCodecParameterWithAttrCallback> &callback)
534 {
535     std::scoped_lock lock(mutex_, *syncMutex_);
536     CHECK_AND_RETURN_RET_LOG_WITH_TAG(callback != nullptr, AVCS_ERR_NO_MEMORY, "Callback is nullptr");
537     CHECK_AND_RETURN_RET_LOG_WITH_TAG(!isConfigured_, AVCS_ERR_INVALID_STATE, "Need to configure encoder!");
538 
539     int32_t ret = circular_.SetCallback(callback);
540     if (ret == AVCS_ERR_OK) {
541         codecMode_ |= CODEC_ENABLE_PARAMETER;
542     }
543     AVCODEC_LOGI_WITH_TAG("Parameter callback.%{public}s", ErrorToStr(ret).c_str());
544     return ret;
545 }
546 
GetInputFormat(Format & format)547 int32_t CodecClient::GetInputFormat(Format &format)
548 {
549     std::lock_guard<std::shared_mutex> lock(mutex_);
550     CHECK_AND_RETURN_RET_LOG_WITH_TAG(codecProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Server not exist");
551     int32_t ret = codecProxy_->GetInputFormat(format);
552     UpdateFormat(format);
553     AVCODEC_LOGI_WITH_TAG("%{public}s", ErrorToStr(ret).c_str());
554     return ret;
555 }
556 
UpdateGeneration()557 void CodecClient::UpdateGeneration()
558 {
559     if (listenerStub_ != nullptr && needUpdateGeneration_) {
560         listenerStub_->UpdateGeneration();
561         needUpdateGeneration_ = false;
562     }
563 }
564 
UpdateFormat(Format & format)565 void CodecClient::UpdateFormat(Format &format)
566 {
567     if (callbackMode_ == MEMORY_CALLBACK && converter_ != nullptr) {
568         converter_->SetFormat(format);
569         converter_->GetFormat(format);
570         return;
571     }
572     if (format.ContainKey(Tag::VIDEO_STRIDE) || format.ContainKey(Tag::VIDEO_SLICE_HEIGHT)) {
573         int32_t width = 0;
574         int32_t height = 0;
575         switch (type_) {
576             case AVCODEC_TYPE_VIDEO_ENCODER:
577                 format.GetIntValue(Tag::VIDEO_WIDTH, width);
578                 format.GetIntValue(Tag::VIDEO_HEIGHT, height);
579                 break;
580             case AVCODEC_TYPE_VIDEO_DECODER:
581                 format.GetIntValue(Tag::VIDEO_PIC_WIDTH, width);
582                 format.GetIntValue(Tag::VIDEO_PIC_HEIGHT, height);
583                 break;
584             default:
585                 return;
586         }
587         int32_t wStride = 0;
588         int32_t hStride = 0;
589         format.GetIntValue(Tag::VIDEO_STRIDE, wStride);
590         format.GetIntValue(Tag::VIDEO_SLICE_HEIGHT, hStride);
591         format.PutIntValue(Tag::VIDEO_STRIDE, std::max(width, wStride));
592         format.PutIntValue(Tag::VIDEO_SLICE_HEIGHT, std::max(height, hStride));
593     }
594 }
595 
SetNeedListen(const bool needListen)596 void CodecClient::SetNeedListen(const bool needListen)
597 {
598     if (listenerStub_ != nullptr) {
599         listenerStub_->SetNeedListen(needListen);
600     }
601 }
602 
OnError(AVCodecErrorType errorType,int32_t errorCode)603 void CodecClient::OnError(AVCodecErrorType errorType, int32_t errorCode)
604 {
605     AVCODEC_FUNC_TRACE_WITH_TAG_CLIENT;
606     AVCODEC_LOGW_WITH_TAG("%{public}s", AVCSErrorToString(static_cast<AVCodecServiceErrCode>(errorCode)).c_str());
607     circular_.OnError(errorType, errorCode);
608 }
609 
OnOutputFormatChanged(const Format & format)610 void CodecClient::OnOutputFormatChanged(const Format &format)
611 {
612     AVCODEC_FUNC_TRACE_WITH_TAG_CLIENT;
613     UpdateFormat(const_cast<Format &>(format));
614     AVCODEC_LOGI_WITH_TAG("%{public}s", format.Stringify().c_str());
615     circular_.OnOutputFormatChanged(format);
616 }
617 
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)618 void CodecClient::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
619 {
620     AVCODEC_FUNC_TRACE_WITH_TAG_CLIENT;
621     AVCODEC_LOGD_WITH_TAG("index:%{public}u", index);
622     circular_.OnInputBufferAvailable(index, buffer);
623 }
624 
OnOutputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)625 void CodecClient::OnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
626 {
627     AVCODEC_FUNC_TRACE_WITH_TAG_CLIENT;
628     AVCODEC_LOGD_WITH_TAG("index:%{public}u", index);
629     circular_.OnOutputBufferAvailable(index, buffer);
630 }
631 
OnOutputBufferBinded(std::map<uint32_t,sptr<SurfaceBuffer>> & bufferMap)632 void CodecClient::OnOutputBufferBinded(std::map<uint32_t, sptr<SurfaceBuffer>> &bufferMap)
633 {
634     AVCODEC_FUNC_TRACE_WITH_TAG_CLIENT;
635     circular_.OnOutputBufferBinded(bufferMap);
636 }
637 
OnOutputBufferUnbinded()638 void CodecClient::OnOutputBufferUnbinded()
639 {
640     AVCODEC_FUNC_TRACE_WITH_TAG_CLIENT;
641     circular_.OnOutputBufferUnbinded();
642 }
643 } // namespace MediaAVCodec
644 } // namespace OHOS
645