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_server.h"
17 #include <malloc.h>
18 #include <map>
19 #include <unistd.h>
20 #include <vector>
21 #include "avcodec_codec_name.h"
22 #include "avcodec_dump_utils.h"
23 #include "avcodec_errors.h"
24 #include "avcodec_log.h"
25 #include "avcodec_sysevent.h"
26 #include "avcodec_trace.h"
27 #include "buffer/avbuffer.h"
28 #include "codec_factory.h"
29 #include "media_description.h"
30 #include "surface_type.h"
31
32 namespace {
33 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "CodecServer"};
34 constexpr uint32_t DUMP_CODEC_INFO_INDEX = 0x01010000;
35 constexpr uint32_t DUMP_STATUS_INDEX = 0x01010100;
36 constexpr uint32_t DUMP_LAST_ERROR_INDEX = 0x01010200;
37 constexpr uint32_t DUMP_OFFSET_8 = 8;
38
39 const std::map<OHOS::MediaAVCodec::CodecServer::CodecStatus, std::string> CODEC_STATE_MAP = {
40 {OHOS::MediaAVCodec::CodecServer::UNINITIALIZED, "uninitialized"},
41 {OHOS::MediaAVCodec::CodecServer::INITIALIZED, "initialized"},
42 {OHOS::MediaAVCodec::CodecServer::CONFIGURED, "configured"},
43 {OHOS::MediaAVCodec::CodecServer::RUNNING, "running"},
44 {OHOS::MediaAVCodec::CodecServer::FLUSHED, "flushed"},
45 {OHOS::MediaAVCodec::CodecServer::END_OF_STREAM, "end of stream"},
46 {OHOS::MediaAVCodec::CodecServer::ERROR, "error"},
47 };
48
49 const std::vector<std::pair<std::string_view, const std::string>> DEFAULT_DUMP_TABLE = {
50 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_CODEC_NAME, "Codec_Name"},
51 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_BITRATE, "Bit_Rate"},
52 };
53
54 const std::vector<std::pair<std::string_view, const std::string>> VIDEO_DUMP_TABLE = {
55 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_CODEC_NAME, "Codec_Name"},
56 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_WIDTH, "Width"},
57 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_HEIGHT, "Height"},
58 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_FRAME_RATE, "Frame_Rate"},
59 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_BITRATE, "Bit_Rate"},
60 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, "Pixel_Format"},
61 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_SCALE_TYPE, "Scale_Type"},
62 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, "Rotation_Angle"},
63 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_MAX_INPUT_SIZE, "Max_Input_Size"},
64 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_MAX_INPUT_BUFFER_COUNT, "Max_Input_Buffer_Count"},
65 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, "Max_Output_Buffer_Count"},
66 };
67
68 const std::vector<std::pair<std::string_view, const std::string>> AUDIO_DUMP_TABLE = {
69 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_CODEC_NAME, "Codec_Name"},
70 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, "Channel_Count"},
71 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_BITRATE, "Bit_Rate"},
72 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_SAMPLE_RATE, "Sample_Rate"},
73 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_MAX_INPUT_SIZE, "Max_Input_Size"},
74 };
75
76 const std::map<OHOS::MediaAVCodec::CodecServer::CodecType, std::vector<std::pair<std::string_view, const std::string>>>
77 CODEC_DUMP_TABLE = {
78 {OHOS::MediaAVCodec::CodecServer::CodecType::CODEC_TYPE_DEFAULT, DEFAULT_DUMP_TABLE},
79 {OHOS::MediaAVCodec::CodecServer::CodecType::CODEC_TYPE_VIDEO, VIDEO_DUMP_TABLE},
80 {OHOS::MediaAVCodec::CodecServer::CodecType::CODEC_TYPE_AUDIO, AUDIO_DUMP_TABLE},
81 };
82
83 const std::map<int32_t, const std::string> PIXEL_FORMAT_STRING_MAP = {
84 {static_cast<int32_t>(OHOS::MediaAVCodec::VideoPixelFormat::YUV420P), "YUV420P"},
85 {static_cast<int32_t>(OHOS::MediaAVCodec::VideoPixelFormat::YUVI420), "YUVI420"},
86 {static_cast<int32_t>(OHOS::MediaAVCodec::VideoPixelFormat::NV12), "NV12"},
87 {static_cast<int32_t>(OHOS::MediaAVCodec::VideoPixelFormat::NV21), "NV21"},
88 {static_cast<int32_t>(OHOS::MediaAVCodec::VideoPixelFormat::SURFACE_FORMAT), "SURFACE_FORMAT"},
89 {static_cast<int32_t>(OHOS::MediaAVCodec::VideoPixelFormat::RGBA), "RGBA"},
90 {static_cast<int32_t>(OHOS::MediaAVCodec::VideoPixelFormat::UNKNOWN), "UNKNOWN_FORMAT"},
91 };
92
93 const std::map<int32_t, const std::string> SCALE_TYPE_STRING_MAP = {
94 {OHOS::ScalingMode::SCALING_MODE_FREEZE, "Freeze"},
95 {OHOS::ScalingMode::SCALING_MODE_SCALE_TO_WINDOW, "Scale_to_window"},
96 {OHOS::ScalingMode::SCALING_MODE_SCALE_CROP, "Scale_crop"},
97 {OHOS::ScalingMode::SCALING_MODE_NO_SCALE_CROP, "No_scale_crop"},
98 };
99 } // namespace
100
101 namespace OHOS {
102 namespace MediaAVCodec {
103 using namespace Media;
Create()104 std::shared_ptr<ICodecService> CodecServer::Create()
105 {
106 std::shared_ptr<CodecServer> server = std::make_shared<CodecServer>();
107
108 int32_t ret = server->InitServer();
109 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, nullptr, "Server init failed, ret: %{public}d!", ret);
110 return server;
111 }
112
CodecServer()113 CodecServer::CodecServer()
114 {
115 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
116 }
117
~CodecServer()118 CodecServer::~CodecServer()
119 {
120 std::unique_ptr<std::thread> thread = std::make_unique<std::thread>(&CodecServer::ExitProcessor, this);
121 if (thread->joinable()) {
122 thread->join();
123 }
124 (void)mallopt(M_FLUSH_THREAD_CACHE, 0);
125 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
126 }
127
ExitProcessor()128 void CodecServer::ExitProcessor()
129 {
130 codecBase_ = nullptr;
131 }
132
InitServer()133 int32_t CodecServer::InitServer()
134 {
135 return AVCS_ERR_OK;
136 }
137
Init(AVCodecType type,bool isMimeType,const std::string & name,API_VERSION apiVersion)138 int32_t CodecServer::Init(AVCodecType type, bool isMimeType, const std::string &name, API_VERSION apiVersion)
139 {
140 std::lock_guard<std::shared_mutex> lock(mutex_);
141 (void)mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE);
142 (void)mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE);
143 std::string codecMimeName = name;
144 codecType_ = type;
145 if (isMimeType) {
146 bool isEncoder = (type == AVCODEC_TYPE_VIDEO_ENCODER) || (type == AVCODEC_TYPE_AUDIO_ENCODER);
147 codecBase_ = CodecFactory::Instance().CreateCodecByMime(isEncoder, codecMimeName, apiVersion);
148 } else {
149 if (name.compare(AVCodecCodecName::AUDIO_DECODER_API9_AAC_NAME) == 0) {
150 codecMimeName = AVCodecCodecName::AUDIO_DECODER_AAC_NAME;
151 } else if (name.compare(AVCodecCodecName::AUDIO_ENCODER_API9_AAC_NAME) == 0) {
152 codecMimeName = AVCodecCodecName::AUDIO_ENCODER_AAC_NAME;
153 }
154 if (codecMimeName.find("Audio") != codecMimeName.npos) {
155 if ((codecMimeName.find("Decoder") != codecMimeName.npos && type != AVCODEC_TYPE_AUDIO_DECODER) ||
156 (codecMimeName.find("Encoder") != codecMimeName.npos && type != AVCODEC_TYPE_AUDIO_ENCODER)) {
157 AVCODEC_LOGE("Codec name:%{public}s invalid", codecMimeName.c_str());
158 return AVCS_ERR_INVALID_OPERATION;
159 }
160 }
161 codecBase_ = CodecFactory::Instance().CreateCodecByName(codecMimeName, apiVersion);
162 }
163 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "CodecBase is nullptr, %{public}s",
164 codecMimeName.c_str());
165 codecName_ = codecMimeName;
166 std::shared_ptr<AVCodecCallback> callback = std::make_shared<CodecBaseCallback>(shared_from_this());
167 int32_t ret = codecBase_->SetCallback(callback);
168 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCS_ERR_INVALID_OPERATION, "CodecBase SetCallback failed");
169
170 std::shared_ptr<MediaCodecCallback> videoCallback = std::make_shared<VCodecBaseCallback>(shared_from_this());
171 ret = codecBase_->SetCallback(videoCallback);
172 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCS_ERR_INVALID_OPERATION, "CodecBase SetCallback failed");
173
174 StatusChanged(INITIALIZED);
175 return AVCS_ERR_OK;
176 }
177
Configure(const Format & format)178 int32_t CodecServer::Configure(const Format &format)
179 {
180 std::lock_guard<std::shared_mutex> lock(mutex_);
181 CHECK_AND_RETURN_RET_LOG(status_ == INITIALIZED, AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s",
182 GetStatusDescription(status_).data());
183 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
184 config_ = format;
185 int32_t ret = codecBase_->Configure(format);
186
187 CodecStatus newStatus = (ret == AVCS_ERR_OK ? CONFIGURED : ERROR);
188 StatusChanged(newStatus);
189 return ret;
190 }
191
Start()192 int32_t CodecServer::Start()
193 {
194 SetFreeStatus(false);
195 std::lock_guard<std::shared_mutex> lock(mutex_);
196 CHECK_AND_RETURN_RET_LOG(status_ == FLUSHED || status_ == CONFIGURED, AVCS_ERR_INVALID_STATE,
197 "In invalid state, %{public}s", GetStatusDescription(status_).data());
198 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
199 int32_t ret = codecBase_->Start();
200
201 CodecStatus newStatus = (ret == AVCS_ERR_OK ? RUNNING : ERROR);
202 StatusChanged(newStatus);
203 if (ret == AVCS_ERR_OK) {
204 isStarted_ = true;
205 CodecDfxInfo codecDfxInfo;
206 GetCodecDfxInfo(codecDfxInfo);
207 CodecStartEventWrite(codecDfxInfo);
208 }
209 return ret;
210 }
211
Stop()212 int32_t CodecServer::Stop()
213 {
214 SetFreeStatus(true);
215 std::lock_guard<std::shared_mutex> lock(mutex_);
216 CHECK_AND_RETURN_RET_LOG(status_ == RUNNING || status_ == END_OF_STREAM || status_ == FLUSHED,
217 AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s",
218 GetStatusDescription(status_).data());
219 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
220 int32_t ret = codecBase_->Stop();
221 CodecStatus newStatus = (ret == AVCS_ERR_OK ? CONFIGURED : ERROR);
222 StatusChanged(newStatus);
223 if (isStarted_ && ret == AVCS_ERR_OK) {
224 isStarted_ = false;
225 CodecStopEventWrite(clientPid_, clientUid_, FAKE_POINTER(this));
226 }
227 return ret;
228 }
229
Flush()230 int32_t CodecServer::Flush()
231 {
232 SetFreeStatus(true);
233 std::lock_guard<std::shared_mutex> lock(mutex_);
234 CHECK_AND_RETURN_RET_LOG(status_ == RUNNING || status_ == END_OF_STREAM, AVCS_ERR_INVALID_STATE,
235 "In invalid state, %{public}s", GetStatusDescription(status_).data());
236 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
237 int32_t ret = codecBase_->Flush();
238 CodecStatus newStatus = (ret == AVCS_ERR_OK ? FLUSHED : ERROR);
239 StatusChanged(newStatus);
240 if (isStarted_ && ret == AVCS_ERR_OK) {
241 isStarted_ = false;
242 CodecStopEventWrite(clientPid_, clientUid_, FAKE_POINTER(this));
243 }
244 return ret;
245 }
246
NotifyEos()247 int32_t CodecServer::NotifyEos()
248 {
249 std::lock_guard<std::shared_mutex> lock(mutex_);
250 CHECK_AND_RETURN_RET_LOG(status_ == RUNNING, AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s",
251 GetStatusDescription(status_).data());
252 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
253 int32_t ret = codecBase_->NotifyEos();
254 if (ret == AVCS_ERR_OK) {
255 CodecStatus newStatus = END_OF_STREAM;
256 StatusChanged(newStatus);
257 if (isStarted_) {
258 isStarted_ = false;
259 CodecStopEventWrite(clientPid_, clientUid_, FAKE_POINTER(this));
260 }
261 }
262 return ret;
263 }
264
Reset()265 int32_t CodecServer::Reset()
266 {
267 SetFreeStatus(true);
268 std::lock_guard<std::shared_mutex> lock(mutex_);
269 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
270 int32_t ret = codecBase_->Reset();
271 CodecStatus newStatus = (ret == AVCS_ERR_OK ? INITIALIZED : ERROR);
272 StatusChanged(newStatus);
273 lastErrMsg_.clear();
274 if (isStarted_ && ret == AVCS_ERR_OK) {
275 isStarted_ = false;
276 CodecStopEventWrite(clientPid_, clientUid_, FAKE_POINTER(this));
277 }
278 return ret;
279 }
280
Release()281 int32_t CodecServer::Release()
282 {
283 SetFreeStatus(true);
284 std::lock_guard<std::shared_mutex> lock(mutex_);
285 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
286 int32_t ret = codecBase_->Release();
287 std::unique_ptr<std::thread> thread = std::make_unique<std::thread>(&CodecServer::ExitProcessor, this);
288 if (thread->joinable()) {
289 thread->join();
290 }
291 if (isStarted_ && ret == AVCS_ERR_OK) {
292 isStarted_ = false;
293 CodecStopEventWrite(clientPid_, clientUid_, FAKE_POINTER(this));
294 }
295 return ret;
296 }
297
CreateInputSurface()298 sptr<Surface> CodecServer::CreateInputSurface()
299 {
300 std::lock_guard<std::shared_mutex> lock(mutex_);
301 CHECK_AND_RETURN_RET_LOG(status_ == CONFIGURED, nullptr, "In invalid state, %{public}s",
302 GetStatusDescription(status_).data());
303 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, nullptr, "Codecbase is nullptr");
304 sptr<Surface> surface = codecBase_->CreateInputSurface();
305 if (surface != nullptr) {
306 isSurfaceMode_ = true;
307 }
308 return surface;
309 }
310
SetInputSurface(sptr<Surface> surface)311 int32_t CodecServer::SetInputSurface(sptr<Surface> surface)
312 {
313 std::lock_guard<std::shared_mutex> lock(mutex_);
314 CHECK_AND_RETURN_RET_LOG(status_ == CONFIGURED, AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s",
315 GetStatusDescription(status_).data());
316 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
317 if (surface != nullptr) {
318 isSurfaceMode_ = true;
319 }
320 return codecBase_->SetInputSurface(surface);
321 }
322
SetOutputSurface(sptr<Surface> surface)323 int32_t CodecServer::SetOutputSurface(sptr<Surface> surface)
324 {
325 std::lock_guard<std::shared_mutex> lock(mutex_);
326 CHECK_AND_RETURN_RET_LOG(status_ == CONFIGURED, AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s",
327 GetStatusDescription(status_).data());
328 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
329 if (surface != nullptr) {
330 isSurfaceMode_ = true;
331 }
332 return codecBase_->SetOutputSurface(surface);
333 }
334
DrmVideoCencDecrypt(uint32_t index)335 void CodecServer::DrmVideoCencDecrypt(uint32_t index)
336 {
337 if (drmDecryptor_ != nullptr) {
338 if (decryptVideoBufs_.find(index) != decryptVideoBufs_.end()) {
339 uint32_t dataSize = decryptVideoBufs_[index].inBuf->memory_->GetSize();
340 decryptVideoBufs_[index].outBuf->pts_ = decryptVideoBufs_[index].inBuf->pts_;
341 decryptVideoBufs_[index].outBuf->dts_ = decryptVideoBufs_[index].inBuf->dts_;
342 decryptVideoBufs_[index].outBuf->duration_ = decryptVideoBufs_[index].inBuf->duration_;
343 decryptVideoBufs_[index].outBuf->flag_ = decryptVideoBufs_[index].inBuf->flag_;
344 if (decryptVideoBufs_[index].inBuf->meta_ != nullptr) {
345 *(decryptVideoBufs_[index].outBuf->meta_) = *(decryptVideoBufs_[index].inBuf->meta_);
346 }
347 drmDecryptor_->SetCodecName(codecName_);
348 drmDecryptor_->DrmCencDecrypt(decryptVideoBufs_[index].inBuf, decryptVideoBufs_[index].outBuf,
349 dataSize);
350 decryptVideoBufs_[index].outBuf->memory_->SetSize(dataSize);
351 }
352 }
353 }
354
QueueInputBuffer(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag)355 int32_t CodecServer::QueueInputBuffer(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag)
356 {
357 std::shared_lock<std::shared_mutex> freeLock(freeMutex_);
358 if (isFree_) {
359 AVCODEC_LOGE("In invalid state, free out");
360 return AVCS_ERR_INVALID_STATE;
361 }
362 int32_t ret = AVCS_ERR_OK;
363 if (((codecType_ == AVCODEC_TYPE_VIDEO_ENCODER) || (codecType_ == AVCODEC_TYPE_VIDEO_DECODER)) &&
364 !((flag & AVCODEC_BUFFER_FLAG_CODEC_DATA) || (flag & AVCODEC_BUFFER_FLAG_EOS))) {
365 AVCodecTrace::TraceBegin("CodecServer::Frame", info.presentationTimeUs);
366 }
367 if (flag & AVCODEC_BUFFER_FLAG_EOS) {
368 std::lock_guard<std::shared_mutex> lock(mutex_);
369 ret = QueueInputBufferIn(index, info, flag);
370 if (ret == AVCS_ERR_OK) {
371 CodecStatus newStatus = END_OF_STREAM;
372 StatusChanged(newStatus);
373 }
374 } else {
375 std::shared_lock<std::shared_mutex> lock(mutex_);
376 ret = QueueInputBufferIn(index, info, flag);
377 }
378 return ret;
379 }
380
QueueInputBufferIn(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag)381 int32_t CodecServer::QueueInputBufferIn(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag)
382 {
383 int32_t ret = AVCS_ERR_OK;
384 CHECK_AND_RETURN_RET_LOG(status_ == RUNNING, AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s",
385 GetStatusDescription(status_).data());
386 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
387 if (videoCb_ != nullptr) {
388 DrmVideoCencDecrypt(index);
389 ret = codecBase_->QueueInputBuffer(index);
390 }
391 if (codecCb_ != nullptr) {
392 ret = codecBase_->QueueInputBuffer(index, info, flag);
393 }
394 return ret;
395 }
396
QueueInputBuffer(uint32_t index)397 int32_t CodecServer::QueueInputBuffer(uint32_t index)
398 {
399 (void)index;
400 return AVCS_ERR_OK;
401 }
402
GetOutputFormat(Format & format)403 int32_t CodecServer::GetOutputFormat(Format &format)
404 {
405 std::lock_guard<std::shared_mutex> lock(mutex_);
406 CHECK_AND_RETURN_RET_LOG(status_ != UNINITIALIZED, AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s",
407 GetStatusDescription(status_).data());
408 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
409 return codecBase_->GetOutputFormat(format);
410 }
411
412 #ifdef SUPPORT_DRM
SetDecryptConfig(const sptr<DrmStandard::IMediaKeySessionService> & keySession,const bool svpFlag)413 int32_t CodecServer::SetDecryptConfig(const sptr<DrmStandard::IMediaKeySessionService> &keySession, const bool svpFlag)
414 {
415 std::lock_guard<std::shared_mutex> lock(mutex_);
416 AVCODEC_LOGI("CodecServer::SetDecryptConfig");
417 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
418 if (drmDecryptor_ == nullptr) {
419 drmDecryptor_ = std::make_shared<CodecDrmDecrypt>();
420 }
421 CHECK_AND_RETURN_RET_LOG(drmDecryptor_ != nullptr, AVCS_ERR_NO_MEMORY, "drmDecryptor is nullptr");
422 drmDecryptor_->SetDecryptConfig(keySession, svpFlag);
423 return AVCS_ERR_OK;
424 }
425 #endif
426
ReleaseOutputBuffer(uint32_t index,bool render)427 int32_t CodecServer::ReleaseOutputBuffer(uint32_t index, bool render)
428 {
429 std::shared_lock<std::shared_mutex> freeLock(freeMutex_);
430 if (isFree_) {
431 AVCODEC_LOGE("In invalid state, free out");
432 return AVCS_ERR_INVALID_STATE;
433 }
434 std::shared_lock<std::shared_mutex> lock(mutex_);
435 CHECK_AND_RETURN_RET_LOG(status_ == RUNNING || status_ == END_OF_STREAM, AVCS_ERR_INVALID_STATE,
436 "In invalid state, %{public}s", GetStatusDescription(status_).data());
437 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
438
439 int32_t ret;
440 if (render) {
441 ret = codecBase_->RenderOutputBuffer(index);
442 } else {
443 ret = codecBase_->ReleaseOutputBuffer(index);
444 }
445 return ret;
446 }
447
SetParameter(const Format & format)448 int32_t CodecServer::SetParameter(const Format &format)
449 {
450 std::lock_guard<std::shared_mutex> lock(mutex_);
451 CHECK_AND_RETURN_RET_LOG(status_ != INITIALIZED && status_ != CONFIGURED, AVCS_ERR_INVALID_STATE,
452 "In invalid state, %{public}s", GetStatusDescription(status_).data());
453 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
454 return codecBase_->SetParameter(format);
455 }
456
SetCallback(const std::shared_ptr<AVCodecCallback> & callback)457 int32_t CodecServer::SetCallback(const std::shared_ptr<AVCodecCallback> &callback)
458 {
459 std::lock_guard<std::shared_mutex> cbLock(cbMutex_);
460 codecCb_ = callback;
461 return AVCS_ERR_OK;
462 }
463
SetCallback(const std::shared_ptr<MediaCodecCallback> & callback)464 int32_t CodecServer::SetCallback(const std::shared_ptr<MediaCodecCallback> &callback)
465 {
466 std::lock_guard<std::shared_mutex> cbLock(cbMutex_);
467 videoCb_ = callback;
468 return AVCS_ERR_OK;
469 }
470
GetInputFormat(Format & format)471 int32_t CodecServer::GetInputFormat(Format &format)
472 {
473 std::lock_guard<std::shared_mutex> lock(mutex_);
474 CHECK_AND_RETURN_RET_LOG(
475 status_ == CONFIGURED || status_ == RUNNING || status_ == FLUSHED || status_ == END_OF_STREAM,
476 AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s", GetStatusDescription(status_).data());
477 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
478 return codecBase_->GetInputFormat(format);
479 }
480
DumpInfo(int32_t fd)481 int32_t CodecServer::DumpInfo(int32_t fd)
482 {
483 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
484 Format codecFormat;
485 int32_t ret = codecBase_->GetOutputFormat(codecFormat);
486 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Get codec format failed.");
487 CodecType codecType = GetCodecType();
488 auto it = CODEC_DUMP_TABLE.find(codecType);
489 const auto &dumpTable = it != CODEC_DUMP_TABLE.end() ? it->second : DEFAULT_DUMP_TABLE;
490 AVCodecDumpControler dumpControler;
491 std::string codecInfo;
492 switch (codecType) {
493 case CODEC_TYPE_VIDEO:
494 codecInfo = "Video_Codec_Info";
495 break;
496 case CODEC_TYPE_DEFAULT:
497 codecInfo = "Codec_Info";
498 break;
499 case CODEC_TYPE_AUDIO:
500 codecInfo = "Audio_Codec_Info";
501 break;
502 }
503 auto statusIt = CODEC_STATE_MAP.find(status_);
504 dumpControler.AddInfo(DUMP_CODEC_INFO_INDEX, codecInfo);
505 dumpControler.AddInfo(DUMP_STATUS_INDEX, "Status", statusIt != CODEC_STATE_MAP.end() ? statusIt->second : "");
506 dumpControler.AddInfo(DUMP_LAST_ERROR_INDEX, "Last_Error", lastErrMsg_.size() ? lastErrMsg_ : "Null");
507
508 int32_t dumpIndex = 3;
509 for (auto iter : dumpTable) {
510 if (iter.first == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT) {
511 dumpControler.AddInfoFromFormatWithMapping(DUMP_CODEC_INFO_INDEX + (dumpIndex << DUMP_OFFSET_8),
512 codecFormat, iter.first, iter.second, PIXEL_FORMAT_STRING_MAP);
513 } else if (iter.first == MediaDescriptionKey::MD_KEY_SCALE_TYPE) {
514 dumpControler.AddInfoFromFormatWithMapping(DUMP_CODEC_INFO_INDEX + (dumpIndex << DUMP_OFFSET_8),
515 codecFormat, iter.first, iter.second, SCALE_TYPE_STRING_MAP);
516 } else {
517 dumpControler.AddInfoFromFormat(DUMP_CODEC_INFO_INDEX + (dumpIndex << DUMP_OFFSET_8), codecFormat,
518 iter.first, iter.second);
519 }
520 dumpIndex++;
521 }
522 std::string dumpString;
523 dumpControler.GetDumpString(dumpString);
524 if (fd != -1) {
525 write(fd, dumpString.c_str(), dumpString.size());
526 }
527 return AVCS_ERR_OK;
528 }
529
SetClientInfo(int32_t clientPid,int32_t clientUid)530 int32_t CodecServer::SetClientInfo(int32_t clientPid, int32_t clientUid)
531 {
532 clientPid_ = clientPid;
533 clientUid_ = clientUid;
534 return 0;
535 }
536
GetStatusDescription(CodecStatus status)537 inline const std::string &CodecServer::GetStatusDescription(CodecStatus status)
538 {
539 if (status < UNINITIALIZED || status >= ERROR) {
540 return CODEC_STATE_MAP.at(ERROR);
541 }
542 return CODEC_STATE_MAP.at(status);
543 }
544
StatusChanged(CodecStatus newStatus)545 inline void CodecServer::StatusChanged(CodecStatus newStatus)
546 {
547 if (status_ == newStatus) {
548 return;
549 }
550 AVCODEC_LOGI("Status %{public}s -> %{public}s",
551 GetStatusDescription(status_).data(), GetStatusDescription(newStatus).data());
552 status_ = newStatus;
553 }
554
OnError(int32_t errorType,int32_t errorCode)555 void CodecServer::OnError(int32_t errorType, int32_t errorCode)
556 {
557 std::lock_guard<std::shared_mutex> lock(cbMutex_);
558 lastErrMsg_ = AVCSErrorToString(static_cast<AVCodecServiceErrCode>(errorCode));
559 FaultEventWrite(FaultType::FAULT_TYPE_INNER_ERROR, lastErrMsg_, "Codec");
560 if (videoCb_ != nullptr) {
561 videoCb_->OnError(static_cast<AVCodecErrorType>(errorType), errorCode);
562 }
563 if (codecCb_ != nullptr) {
564 codecCb_->OnError(static_cast<AVCodecErrorType>(errorType), errorCode);
565 }
566 }
567
OnOutputFormatChanged(const Format & format)568 void CodecServer::OnOutputFormatChanged(const Format &format)
569 {
570 std::lock_guard<std::shared_mutex> lock(cbMutex_);
571 if (videoCb_ != nullptr) {
572 videoCb_->OnOutputFormatChanged(format);
573 }
574 if (codecCb_ != nullptr) {
575 codecCb_->OnOutputFormatChanged(format);
576 }
577 }
578
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVSharedMemory> buffer)579 void CodecServer::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVSharedMemory> buffer)
580 {
581 std::shared_lock<std::shared_mutex> lock(cbMutex_);
582 if (codecCb_ == nullptr) {
583 return;
584 }
585 codecCb_->OnInputBufferAvailable(index, buffer);
586 }
587
OnOutputBufferAvailable(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag,std::shared_ptr<AVSharedMemory> buffer)588 void CodecServer::OnOutputBufferAvailable(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag,
589 std::shared_ptr<AVSharedMemory> buffer)
590 {
591 if (((codecType_ == AVCODEC_TYPE_VIDEO_ENCODER) || (codecType_ == AVCODEC_TYPE_VIDEO_DECODER)) &&
592 !((flag & AVCODEC_BUFFER_FLAG_CODEC_DATA) || (flag & AVCODEC_BUFFER_FLAG_EOS))) {
593 AVCodecTrace::TraceEnd("CodecServer::Frame", info.presentationTimeUs);
594 }
595
596 std::shared_lock<std::shared_mutex> lock(cbMutex_);
597 if (codecCb_ == nullptr) {
598 return;
599 }
600 codecCb_->OnOutputBufferAvailable(index, info, flag, buffer);
601 }
602
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)603 void CodecServer::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
604 {
605 std::shared_lock<std::shared_mutex> lock(cbMutex_);
606 if (videoCb_ == nullptr) {
607 return;
608 }
609 if (drmDecryptor_ != nullptr) {
610 if (decryptVideoBufs_.find(index) != decryptVideoBufs_.end()) {
611 videoCb_->OnInputBufferAvailable(index, decryptVideoBufs_[index].inBuf);
612 return;
613 }
614 DrmDecryptVideoBuf decryptVideoBuf;
615 MemoryFlag memFlag = MEMORY_READ_WRITE;
616 std::shared_ptr<AVAllocator> avAllocator = AVAllocatorFactory::CreateSharedAllocator(memFlag);
617 if (avAllocator == nullptr) {
618 AVCODEC_LOGE("CreateSharedAllocator failed");
619 return;
620 }
621 decryptVideoBuf.inBuf = AVBuffer::CreateAVBuffer(avAllocator,
622 static_cast<int32_t>(buffer->memory_->GetCapacity()));
623 if (decryptVideoBuf.inBuf == nullptr || decryptVideoBuf.inBuf->memory_ == nullptr ||
624 decryptVideoBuf.inBuf->memory_->GetCapacity() != static_cast<int32_t>(buffer->memory_->GetCapacity())) {
625 AVCODEC_LOGE("CreateAVBuffer failed");
626 return;
627 }
628 decryptVideoBuf.outBuf = buffer;
629 decryptVideoBufs_.insert({index, decryptVideoBuf});
630 videoCb_->OnInputBufferAvailable(index, decryptVideoBuf.inBuf);
631 } else {
632 videoCb_->OnInputBufferAvailable(index, buffer);
633 }
634 }
635
OnOutputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)636 void CodecServer::OnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
637 {
638 AVCODEC_LOGD("on output buffer index: %{public}d", index);
639 CHECK_AND_RETURN_LOG(buffer != nullptr, "buffer is nullptr!");
640
641 if (((codecType_ == AVCODEC_TYPE_VIDEO_ENCODER) || (codecType_ == AVCODEC_TYPE_VIDEO_DECODER)) &&
642 !((buffer->flag_ & AVCODEC_BUFFER_FLAG_CODEC_DATA) || (buffer->flag_ & AVCODEC_BUFFER_FLAG_EOS))) {
643 AVCodecTrace::TraceEnd("CodecServer::Frame", buffer->pts_);
644 }
645
646 std::shared_lock<std::shared_mutex> lock(cbMutex_);
647 CHECK_AND_RETURN_LOG(videoCb_ != nullptr, "videoCb_ is nullptr!");
648 videoCb_->OnOutputBufferAvailable(index, buffer);
649 }
650
CodecBaseCallback(const std::shared_ptr<CodecServer> & codec)651 CodecBaseCallback::CodecBaseCallback(const std::shared_ptr<CodecServer> &codec) : codec_(codec)
652 {
653 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
654 }
655
~CodecBaseCallback()656 CodecBaseCallback::~CodecBaseCallback()
657 {
658 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
659 }
660
OnError(AVCodecErrorType errorType,int32_t errorCode)661 void CodecBaseCallback::OnError(AVCodecErrorType errorType, int32_t errorCode)
662 {
663 if (codec_ != nullptr) {
664 codec_->OnError(errorType, errorCode);
665 }
666 }
667
OnOutputFormatChanged(const Format & format)668 void CodecBaseCallback::OnOutputFormatChanged(const Format &format)
669 {
670 if (codec_ != nullptr) {
671 codec_->OnOutputFormatChanged(format);
672 }
673 }
674
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVSharedMemory> buffer)675 void CodecBaseCallback::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVSharedMemory> buffer)
676 {
677 if (codec_ != nullptr) {
678 codec_->OnInputBufferAvailable(index, buffer);
679 }
680 }
681
OnOutputBufferAvailable(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag,std::shared_ptr<AVSharedMemory> buffer)682 void CodecBaseCallback::OnOutputBufferAvailable(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag,
683 std::shared_ptr<AVSharedMemory> buffer)
684 {
685 if (codec_ != nullptr) {
686 codec_->OnOutputBufferAvailable(index, info, flag, buffer);
687 }
688 }
689
VCodecBaseCallback(const std::shared_ptr<CodecServer> & codec)690 VCodecBaseCallback::VCodecBaseCallback(const std::shared_ptr<CodecServer> &codec) : codec_(codec)
691 {
692 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
693 }
694
~VCodecBaseCallback()695 VCodecBaseCallback::~VCodecBaseCallback()
696 {
697 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
698 }
699
OnError(AVCodecErrorType errorType,int32_t errorCode)700 void VCodecBaseCallback::OnError(AVCodecErrorType errorType, int32_t errorCode)
701 {
702 if (codec_ != nullptr) {
703 codec_->OnError(errorType, errorCode);
704 }
705 }
706
OnOutputFormatChanged(const Format & format)707 void VCodecBaseCallback::OnOutputFormatChanged(const Format &format)
708 {
709 if (codec_ != nullptr) {
710 codec_->OnOutputFormatChanged(format);
711 }
712 }
713
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)714 void VCodecBaseCallback::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
715 {
716 if (codec_ != nullptr) {
717 codec_->OnInputBufferAvailable(index, buffer);
718 }
719 }
720
OnOutputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)721 void VCodecBaseCallback::OnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
722 {
723 if (codec_ != nullptr) {
724 codec_->OnOutputBufferAvailable(index, buffer);
725 }
726 }
727
GetCodecType()728 CodecServer::CodecType CodecServer::GetCodecType()
729 {
730 CodecType codecType;
731
732 if ((codecName_.find("Video") != codecName_.npos) || (codecName_.find("video") != codecName_.npos)) {
733 codecType = CodecType::CODEC_TYPE_VIDEO;
734 } else if ((codecName_.find("Audio") != codecName_.npos) || (codecName_.find("audio") != codecName_.npos)) {
735 codecType = CodecType::CODEC_TYPE_AUDIO;
736 } else {
737 codecType = CodecType::CODEC_TYPE_DEFAULT;
738 }
739
740 return codecType;
741 }
742
GetCodecDfxInfo(CodecDfxInfo & codecDfxInfo)743 int32_t CodecServer::GetCodecDfxInfo(CodecDfxInfo &codecDfxInfo)
744 {
745 if (clientPid_ == 0) {
746 clientPid_ = getpid();
747 clientUid_ = getuid();
748 }
749 Format format;
750 codecBase_->GetOutputFormat(format);
751 int32_t videoPixelFormat = static_cast<int32_t>(VideoPixelFormat::UNKNOWN);
752 format.GetIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, videoPixelFormat);
753 videoPixelFormat = PIXEL_FORMAT_STRING_MAP.find(videoPixelFormat) != PIXEL_FORMAT_STRING_MAP.end()
754 ? videoPixelFormat
755 : static_cast<int32_t>(VideoPixelFormat::UNKNOWN);
756 int32_t codecIsVendor = 0;
757 format.GetIntValue("IS_VENDOR", codecIsVendor);
758
759 codecDfxInfo.clientPid = clientPid_;
760 codecDfxInfo.clientUid = clientUid_;
761 codecDfxInfo.codecInstanceId = FAKE_POINTER(this);
762 format.GetStringValue(MediaDescriptionKey::MD_KEY_CODEC_NAME, codecDfxInfo.codecName);
763 codecDfxInfo.codecIsVendor = codecIsVendor == 1 ? "True" : "False";
764 codecDfxInfo.codecMode = isSurfaceMode_ ? "Surface mode" : "Buffer Mode";
765 format.GetLongValue(MediaDescriptionKey::MD_KEY_BITRATE, codecDfxInfo.encoderBitRate);
766 format.GetIntValue(MediaDescriptionKey::MD_KEY_WIDTH, codecDfxInfo.videoWidth);
767 format.GetIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, codecDfxInfo.videoHeight);
768 format.GetDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, codecDfxInfo.videoFrameRate);
769 format.GetIntValue(MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, codecDfxInfo.audioChannelCount);
770 codecDfxInfo.videoPixelFormat =
771 codecDfxInfo.audioChannelCount == 0 ? PIXEL_FORMAT_STRING_MAP.at(videoPixelFormat) : "";
772 format.GetIntValue(MediaDescriptionKey::MD_KEY_SAMPLE_RATE, codecDfxInfo.audioSampleRate);
773 return 0;
774 }
775
Configure(const std::shared_ptr<Media::Meta> & meta)776 int32_t CodecServer::Configure(const std::shared_ptr<Media::Meta> &meta)
777 {
778 std::lock_guard<std::shared_mutex> lock(mutex_);
779 CHECK_AND_RETURN_RET_LOG(meta != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
780
781 CHECK_AND_RETURN_RET_LOG(status_ == INITIALIZED, AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s",
782 GetStatusDescription(status_).data());
783 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
784
785 int32_t ret = codecBase_->Configure(meta);
786
787 CodecStatus newStatus = (ret == AVCS_ERR_OK ? CONFIGURED : ERROR);
788 StatusChanged(newStatus);
789 return ret;
790 }
SetParameter(const std::shared_ptr<Media::Meta> & parameter)791 int32_t CodecServer::SetParameter(const std::shared_ptr<Media::Meta> ¶meter)
792 {
793 std::lock_guard<std::shared_mutex> lock(mutex_);
794 CHECK_AND_RETURN_RET_LOG(parameter != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
795 CHECK_AND_RETURN_RET_LOG(status_ != INITIALIZED && status_ != CONFIGURED, AVCS_ERR_INVALID_STATE,
796 "In invalid state, %{public}s", GetStatusDescription(status_).data());
797 return codecBase_->SetParameter(parameter);
798 }
GetOutputFormat(std::shared_ptr<Media::Meta> & parameter)799 int32_t CodecServer::GetOutputFormat(std::shared_ptr<Media::Meta> ¶meter)
800 {
801 std::lock_guard<std::shared_mutex> lock(mutex_);
802 CHECK_AND_RETURN_RET_LOG(status_ != UNINITIALIZED, AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s",
803 GetStatusDescription(status_).data());
804 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "codecBase is nullptr");
805 return codecBase_->GetOutputFormat(parameter);
806 }
807
SetOutputBufferQueue(const sptr<Media::AVBufferQueueProducer> & bufferQueueProducer)808 int32_t CodecServer::SetOutputBufferQueue(const sptr<Media::AVBufferQueueProducer> &bufferQueueProducer)
809 {
810 std::lock_guard<std::shared_mutex> lock(mutex_);
811 CHECK_AND_RETURN_RET_LOG(bufferQueueProducer != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
812 return codecBase_->SetOutputBufferQueue(bufferQueueProducer);
813 }
Prepare()814 int32_t CodecServer::Prepare()
815 {
816 std::lock_guard<std::shared_mutex> lock(mutex_);
817 return codecBase_->Prepare();
818 }
GetInputBufferQueue()819 sptr<Media::AVBufferQueueProducer> CodecServer::GetInputBufferQueue()
820 {
821 std::lock_guard<std::shared_mutex> lock(mutex_);
822 return codecBase_->GetInputBufferQueue();
823 }
ProcessInputBuffer()824 void CodecServer::ProcessInputBuffer()
825 {
826 std::lock_guard<std::shared_mutex> lock(mutex_);
827 return codecBase_->ProcessInputBuffer();
828 }
829
GetStatus()830 bool CodecServer::GetStatus()
831 {
832 if (status_ == CodecServer::RUNNING) {
833 return true;
834 }
835 return false;
836 }
837
SetFreeStatus(bool isFree)838 void CodecServer::SetFreeStatus(bool isFree)
839 {
840 std::lock_guard<std::shared_mutex> lock(freeMutex_);
841 isFree_ = isFree;
842 }
843 } // namespace MediaAVCodec
844 } // namespace OHOS
845