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