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 <iostream>
17 #include <set>
18 #include <thread>
19 #include <malloc.h>
20 #include "syspara/parameters.h"
21 #include "securec.h"
22 #include "avcodec_trace.h"
23 #include "avcodec_log.h"
24 #include "utils.h"
25 #include "avcodec_codec_name.h"
26 #include "fcodec.h"
27
28 namespace OHOS {
29 namespace MediaAVCodec {
30 namespace Codec {
31 namespace {
32 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "FCodec"};
33 constexpr uint32_t INDEX_INPUT = 0;
34 constexpr uint32_t INDEX_OUTPUT = 1;
35 constexpr int32_t DEFAULT_IN_BUFFER_CNT = 4;
36 constexpr int32_t DEFAULT_OUT_SURFACE_CNT = 4;
37 constexpr int32_t DEFAULT_OUT_BUFFER_CNT = 3;
38 constexpr int32_t DEFAULT_MIN_BUFFER_CNT = 2;
39 constexpr uint32_t VIDEO_PIX_DEPTH_YUV = 3;
40 constexpr int32_t VIDEO_MIN_BUFFER_SIZE = 1474560;
41 constexpr int32_t VIDEO_MIN_SIZE = 2;
42 constexpr int32_t VIDEO_ALIGNMENT_SIZE = 2;
43 constexpr int32_t VIDEO_MAX_WIDTH_SIZE = 4096;
44 constexpr int32_t VIDEO_MAX_HEIGHT_SIZE = 4096;
45 constexpr int32_t DEFAULT_VIDEO_WIDTH = 1920;
46 constexpr int32_t DEFAULT_VIDEO_HEIGHT = 1080;
47 constexpr uint32_t DEFAULT_TRY_DECODE_TIME = 1;
48 constexpr uint32_t DEFAULT_TRY_REQ_TIME = 10;
49 constexpr uint32_t DEFAULT_DECODE_WAIT_TIME = 200;
50 constexpr int32_t VIDEO_INSTANCE_SIZE = 64;
51 constexpr int32_t VIDEO_BITRATE_MAX_SIZE = 300000000;
52 constexpr int32_t VIDEO_FRAMERATE_MAX_SIZE = 120;
53 constexpr int32_t VIDEO_BLOCKPERFRAME_SIZE = 36864;
54 constexpr int32_t VIDEO_BLOCKPERSEC_SIZE = 983040;
55 constexpr int32_t DEFAULT_THREAD_COUNT = 2;
56 #ifdef BUILD_ENG_VERSION
57 constexpr uint32_t PATH_MAX_LEN = 128;
58 constexpr char DUMP_PATH[] = "/data/misc/fcodecdump";
59 #endif // BUILD_ENG_VERSION
60 constexpr struct {
61 const std::string_view codecName;
62 const std::string_view mimeType;
63 const char *ffmpegCodec;
64 const bool isEncoder;
65 } SUPPORT_VCODEC[] = {
66 {AVCodecCodecName::VIDEO_DECODER_AVC_NAME, CodecMimeType::VIDEO_AVC, "h264", false},
67 };
68 constexpr uint32_t SUPPORT_VCODEC_NUM = sizeof(SUPPORT_VCODEC) / sizeof(SUPPORT_VCODEC[0]);
69 } // namespace
70 using namespace OHOS::Media;
FCodec(const std::string & name)71 FCodec::FCodec(const std::string &name) : codecName_(name), state_(State::UNINITIALIZED)
72 {
73 AVCODEC_SYNC_TRACE;
74 AVCODEC_LOGD("Fcodec entered, state: Uninitialized");
75 }
76
~FCodec()77 FCodec::~FCodec()
78 {
79 ReleaseResource();
80 callback_ = nullptr;
81 #ifdef BUILD_ENG_VERSION
82 if (dumpInFile_ != nullptr) {
83 dumpInFile_->close();
84 }
85 if (dumpOutFile_ != nullptr) {
86 dumpOutFile_->close();
87 }
88 #endif // BUILD_ENG_VERSION
89 mallopt(M_FLUSH_THREAD_CACHE, 0);
90 }
91
92 #ifdef BUILD_ENG_VERSION
OpenDumpFile()93 void FCodec::OpenDumpFile()
94 {
95 std::string dumpModeStr = OHOS::system::GetParameter("fcodec.dump", "0");
96 AVCODEC_LOGI("dumpModeStr %{public}s", dumpModeStr.c_str());
97 CHECK_AND_RETURN_LOG(dumpModeStr.length() == 2, "dumpModeStr length should equal 2"); // 2
98 char fileName[PATH_MAX_LEN] = {0};
99 int ret;
100 if (dumpModeStr[0] == '1') {
101 ret = sprintf_s(fileName, sizeof(fileName), "%s/input_%p.h264", DUMP_PATH, this);
102 CHECK_AND_RETURN_LOG(ret > 0, "Fail to sprintf input fileName");
103 dumpInFile_ = std::make_shared<std::ofstream>();
104 dumpInFile_->open(fileName, std::ios::out | std::ios::binary);
105 if (!dumpInFile_->is_open()) {
106 AVCODEC_LOGW("fail open file %{public}s", fileName);
107 dumpInFile_ = nullptr;
108 }
109 }
110
111 if (dumpModeStr[1] == '1') {
112 ret = sprintf_s(fileName, sizeof(fileName), "%s/output_%p.yuv", DUMP_PATH, this);
113 CHECK_AND_RETURN_LOG(ret > 0, "Fail to sprintf output fileName");
114 dumpOutFile_ = std::make_shared<std::ofstream>();
115 dumpOutFile_->open(fileName, std::ios::out | std::ios::binary);
116 if (!dumpOutFile_->is_open()) {
117 AVCODEC_LOGW("fail open file %{public}s", fileName);
118 dumpOutFile_ = nullptr;
119 }
120 }
121 }
122 #endif // BUILD_ENG_VERSION
123
Initialize()124 int32_t FCodec::Initialize()
125 {
126 AVCODEC_SYNC_TRACE;
127 CHECK_AND_RETURN_RET_LOG(!codecName_.empty(), AVCS_ERR_INVALID_VAL, "Init codec failed: empty name");
128 std::string fcodecName;
129 std::string_view mime;
130 for (uint32_t i = 0; i < SUPPORT_VCODEC_NUM; ++i) {
131 if (SUPPORT_VCODEC[i].codecName == codecName_) {
132 fcodecName = SUPPORT_VCODEC[i].ffmpegCodec;
133 mime = SUPPORT_VCODEC[i].mimeType;
134 break;
135 }
136 }
137 CHECK_AND_RETURN_RET_LOG(!fcodecName.empty(), AVCS_ERR_INVALID_VAL,
138 "Init codec failed: not support name: %{public}s", codecName_.c_str());
139 format_.PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, mime);
140 format_.PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_NAME, codecName_);
141 avCodec_ = std::shared_ptr<AVCodec>(const_cast<AVCodec *>(avcodec_find_decoder_by_name(fcodecName.c_str())),
142 [](void *ptr) {});
143 CHECK_AND_RETURN_RET_LOG(avCodec_ != nullptr, AVCS_ERR_INVALID_VAL,
144 "Init codec failed: cannot find codec with name %{public}s", codecName_.c_str());
145 sendTask_ = std::make_shared<TaskThread>("SendFrame");
146 sendTask_->RegisterHandler([this] { SendFrame(); });
147 receiveTask_ = std::make_shared<TaskThread>("ReceiveFrame");
148 receiveTask_->RegisterHandler([this] { ReceiveFrame(); });
149 #ifdef BUILD_ENG_VERSION
150 OpenDumpFile();
151 #endif // BUILD_ENG_VERSION
152 state_ = State::INITIALIZED;
153 AVCODEC_LOGI("Init codec successful, state: Uninitialized -> Initialized");
154 return AVCS_ERR_OK;
155 }
156
ConfigureDefaultVal(const Format & format,const std::string_view & formatKey,int32_t minVal,int32_t maxVal)157 void FCodec::ConfigureDefaultVal(const Format &format, const std::string_view &formatKey, int32_t minVal,
158 int32_t maxVal)
159 {
160 int32_t val32 = 0;
161 if (format.GetIntValue(formatKey, val32) && val32 >= minVal && val32 <= maxVal) {
162 format_.PutIntValue(formatKey, val32);
163 } else {
164 AVCODEC_LOGW("Set parameter failed: %{public}s, which minimum threshold=%{public}d, "
165 "maximum threshold=%{public}d",
166 std::string(formatKey).c_str(), minVal, maxVal);
167 }
168 }
169
ConfigureSurface(const Format & format,const std::string_view & formatKey,FormatDataType formatType)170 void FCodec::ConfigureSurface(const Format &format, const std::string_view &formatKey, FormatDataType formatType)
171 {
172 CHECK_AND_RETURN_LOG(formatType == FORMAT_TYPE_INT32, "Set parameter failed: type should be int32");
173
174 int32_t val = 0;
175 CHECK_AND_RETURN_LOG(format.GetIntValue(formatKey, val), "Set parameter failed: get value fail");
176
177 if (formatKey == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT) {
178 VideoPixelFormat vpf = static_cast<VideoPixelFormat>(val);
179 CHECK_AND_RETURN_LOG(vpf == VideoPixelFormat::RGBA || vpf == VideoPixelFormat::YUVI420 ||
180 vpf == VideoPixelFormat::NV12 || vpf == VideoPixelFormat::NV21,
181 "Set parameter failed: pixel format value %{public}d invalid", val);
182 outputPixelFmt_ = vpf;
183 format_.PutIntValue(formatKey, val);
184 } else if (formatKey == MediaDescriptionKey::MD_KEY_ROTATION_ANGLE) {
185 VideoRotation sr = static_cast<VideoRotation>(val);
186 CHECK_AND_RETURN_LOG(sr == VideoRotation::VIDEO_ROTATION_0 || sr == VideoRotation::VIDEO_ROTATION_90 ||
187 sr == VideoRotation::VIDEO_ROTATION_180 || sr == VideoRotation::VIDEO_ROTATION_270,
188 "Set parameter failed: rotation angle value %{public}d invalid", val);
189 format_.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, val);
190 } else if (formatKey == MediaDescriptionKey::MD_KEY_SCALE_TYPE) {
191 ScalingMode scaleMode = static_cast<ScalingMode>(val);
192 CHECK_AND_RETURN_LOG(scaleMode == ScalingMode::SCALING_MODE_SCALE_TO_WINDOW ||
193 scaleMode == ScalingMode::SCALING_MODE_SCALE_CROP,
194 "Set parameter failed: scale type value %{public}d invalid", val);
195 format_.PutIntValue(formatKey, val);
196 } else {
197 AVCODEC_LOGW("Set parameter failed: %{public}s, please check your parameter key",
198 std::string(formatKey).c_str());
199 return;
200 }
201 AVCODEC_LOGI("Set parameter %{public}s success, val %{public}d", std::string(formatKey).c_str(), val);
202 }
203
ConfigureContext(const Format & format)204 int32_t FCodec::ConfigureContext(const Format &format)
205 {
206 avCodecContext_ = std::shared_ptr<AVCodecContext>(avcodec_alloc_context3(avCodec_.get()), [](AVCodecContext *p) {
207 if (p != nullptr) {
208 if (p->extradata) {
209 av_free(p->extradata);
210 p->extradata = nullptr;
211 }
212 avcodec_free_context(&p);
213 }
214 });
215 CHECK_AND_RETURN_RET_LOG(avCodecContext_ != nullptr, AVCS_ERR_INVALID_OPERATION,
216 "Configure codec failed: Allocate context error");
217 avCodecContext_->codec_type = AVMEDIA_TYPE_VIDEO;
218 format.GetIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width_);
219 format.GetIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height_);
220 format_.PutIntValue(OHOS::Media::Tag::VIDEO_STRIDE,
221 outputPixelFmt_ == VideoPixelFormat::RGBA ? width_ * VIDEO_PIX_DEPTH_RGBA : width_);
222 format_.PutIntValue(OHOS::Media::Tag::VIDEO_SLICE_HEIGHT, height_);
223 format_.PutIntValue(OHOS::Media::Tag::VIDEO_PIC_WIDTH, width_);
224 format_.PutIntValue(OHOS::Media::Tag::VIDEO_PIC_HEIGHT, height_);
225
226 avCodecContext_->width = width_;
227 avCodecContext_->height = height_;
228 avCodecContext_->thread_count = DEFAULT_THREAD_COUNT;
229 return AVCS_ERR_OK;
230 }
231
Configure(const Format & format)232 int32_t FCodec::Configure(const Format &format)
233 {
234 AVCODEC_SYNC_TRACE;
235 if (state_ == State::UNINITIALIZED) {
236 int32_t ret = Initialize();
237 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Init codec failed");
238 }
239 CHECK_AND_RETURN_RET_LOG((state_ == State::INITIALIZED), AVCS_ERR_INVALID_STATE,
240 "Configure codec failed: not in Initialized state");
241 format_.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, DEFAULT_VIDEO_WIDTH);
242 format_.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, DEFAULT_VIDEO_HEIGHT);
243 format_.PutIntValue(MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, DEFAULT_OUT_BUFFER_CNT);
244 format_.PutIntValue(MediaDescriptionKey::MD_KEY_MAX_INPUT_BUFFER_COUNT, DEFAULT_IN_BUFFER_CNT);
245 for (auto &it : format.GetFormatMap()) {
246 if (it.first == MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT) {
247 isOutBufSetted_ = true;
248 ConfigureDefaultVal(format, it.first, DEFAULT_MIN_BUFFER_CNT);
249 } else if (it.first == MediaDescriptionKey::MD_KEY_MAX_INPUT_BUFFER_COUNT) {
250 ConfigureDefaultVal(format, it.first, DEFAULT_MIN_BUFFER_CNT);
251 } else if (it.first == MediaDescriptionKey::MD_KEY_WIDTH) {
252 ConfigureDefaultVal(format, it.first, VIDEO_MIN_SIZE, VIDEO_MAX_WIDTH_SIZE);
253 } else if (it.first == MediaDescriptionKey::MD_KEY_HEIGHT) {
254 ConfigureDefaultVal(format, it.first, VIDEO_MIN_SIZE, VIDEO_MAX_HEIGHT_SIZE);
255 } else if (it.first == MediaDescriptionKey::MD_KEY_BITRATE) {
256 int64_t val64 = 0;
257 format.GetLongValue(MediaDescriptionKey::MD_KEY_BITRATE, val64);
258 format_.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, val64);
259 } else if (it.first == MediaDescriptionKey::MD_KEY_FRAME_RATE) {
260 double val = 0;
261 format.GetDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, val);
262 format_.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, val);
263 } else if (it.first == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT ||
264 it.first == MediaDescriptionKey::MD_KEY_ROTATION_ANGLE ||
265 it.first == MediaDescriptionKey::MD_KEY_SCALE_TYPE) {
266 ConfigureSurface(format, it.first, it.second.type);
267 } else {
268 AVCODEC_LOGW("Set parameter failed: size:%{public}s, unsupport key", it.first.data());
269 }
270 }
271 AVCODEC_LOGI("current pixel format %{public}d", static_cast<int32_t>(outputPixelFmt_));
272 int32_t ret = ConfigureContext(format);
273
274 state_ = State::CONFIGURED;
275 AVCODEC_LOGI("Configured codec successful: state: Initialized -> Configured");
276 return ret;
277 }
278
IsActive() const279 bool FCodec::IsActive() const
280 {
281 return state_ == State::RUNNING || state_ == State::FLUSHED || state_ == State::EOS;
282 }
283
ResetContext(bool isFlush)284 void FCodec::ResetContext(bool isFlush)
285 {
286 if (avCodecContext_ == nullptr) {
287 return;
288 }
289 if (avCodecContext_->extradata) {
290 av_free(avCodecContext_->extradata);
291 avCodecContext_->extradata = nullptr;
292 }
293 avCodecContext_->coded_width = 0;
294 avCodecContext_->coded_height = 0;
295 avCodecContext_->extradata_size = 0;
296 if (!isFlush) {
297 avCodecContext_->width = 0;
298 avCodecContext_->height = 0;
299 avCodecContext_->get_buffer2 = nullptr;
300 }
301 }
302
Start()303 int32_t FCodec::Start()
304 {
305 AVCODEC_SYNC_TRACE;
306 CHECK_AND_RETURN_RET_LOG(callback_ != nullptr, AVCS_ERR_INVALID_OPERATION, "Start codec failed: callback is null");
307 CHECK_AND_RETURN_RET_LOG((state_ == State::CONFIGURED || state_ == State::FLUSHED), AVCS_ERR_INVALID_STATE,
308 "Start codec failed: not in Configured or Flushed state");
309 if (state_ != State::FLUSHED) {
310 CHECK_AND_RETURN_RET_LOG(avcodec_open2(avCodecContext_.get(), avCodec_.get(), nullptr) == 0, AVCS_ERR_UNKNOWN,
311 "Start codec failed: cannot open avcodec");
312 }
313 if (!isBufferAllocated_) {
314 cachedFrame_ = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame *p) { av_frame_free(&p); });
315 avPacket_ = std::shared_ptr<AVPacket>(av_packet_alloc(), [](AVPacket *p) { av_packet_free(&p); });
316 CHECK_AND_RETURN_RET_LOG((cachedFrame_ != nullptr && avPacket_ != nullptr), AVCS_ERR_UNKNOWN,
317 "Start codec failed: cannot allocate frame or packet");
318 for (int32_t i = 0; i < AV_NUM_DATA_POINTERS; i++) {
319 scaleData_[i] = nullptr;
320 scaleLineSize_[i] = 0;
321 }
322 isConverted_ = false;
323 int32_t ret = AllocateBuffers();
324 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Start codec failed: cannot allocate buffers");
325 isBufferAllocated_ = true;
326 }
327 state_ = State::RUNNING;
328 InitBuffers();
329 isSendEos_ = false;
330 sendTask_->Start();
331 receiveTask_->Start();
332 AVCODEC_LOGI("Start codec successful, state: Running");
333 return AVCS_ERR_OK;
334 }
335
InitBuffers()336 void FCodec::InitBuffers()
337 {
338 inputAvailQue_->SetActive(true);
339 codecAvailQue_->SetActive(true);
340 if (sInfo_.surface != nullptr) {
341 renderAvailQue_->SetActive(true);
342 }
343 if (buffers_[INDEX_INPUT].size() > 0) {
344 for (uint32_t i = 0; i < buffers_[INDEX_INPUT].size(); i++) {
345 buffers_[INDEX_INPUT][i]->owner_ = FBuffer::Owner::OWNED_BY_USER;
346 callback_->OnInputBufferAvailable(i, buffers_[INDEX_INPUT][i]->avBuffer_);
347 AVCODEC_LOGI("OnInputBufferAvailable frame index = %{public}d, owner = %{public}d", i,
348 buffers_[INDEX_INPUT][i]->owner_.load());
349 }
350 }
351 if (buffers_[INDEX_OUTPUT].size() <= 0) {
352 return;
353 }
354 if (sInfo_.surface == nullptr) {
355 for (uint32_t i = 0; i < buffers_[INDEX_OUTPUT].size(); i++) {
356 buffers_[INDEX_OUTPUT][i]->owner_ = FBuffer::Owner::OWNED_BY_CODEC;
357 codecAvailQue_->Push(i);
358 }
359 } else {
360 for (uint32_t i = 0; i < buffers_[INDEX_OUTPUT].size(); i++) {
361 std::shared_ptr<FSurfaceMemory> surfaceMemory = buffers_[INDEX_OUTPUT][i]->sMemory_;
362 if (surfaceMemory->GetSurfaceBuffer() == nullptr) {
363 buffers_[INDEX_OUTPUT][i]->owner_ = FBuffer::Owner::OWNED_BY_SURFACE;
364 renderAvailQue_->Push(i);
365 } else {
366 buffers_[INDEX_OUTPUT][i]->owner_ = FBuffer::Owner::OWNED_BY_CODEC;
367 codecAvailQue_->Push(i);
368 }
369 }
370 }
371 }
372
ResetData()373 void FCodec::ResetData()
374 {
375 if (scaleData_[0] != nullptr) {
376 if (isConverted_) {
377 av_free(scaleData_[0]);
378 isConverted_ = false;
379 scale_.reset();
380 }
381 for (int32_t i = 0; i < AV_NUM_DATA_POINTERS; i++) {
382 scaleData_[i] = nullptr;
383 scaleLineSize_[i] = 0;
384 }
385 }
386 }
387
ResetBuffers()388 void FCodec::ResetBuffers()
389 {
390 inputAvailQue_->Clear();
391 std::unique_lock<std::mutex> iLock(inputMutex_);
392 synIndex_ = std::nullopt;
393 iLock.unlock();
394 codecAvailQue_->Clear();
395 if (sInfo_.surface != nullptr) {
396 renderAvailQue_->Clear();
397 renderSurfaceBufferMap_.clear();
398 }
399 ResetData();
400 av_frame_unref(cachedFrame_.get());
401 av_packet_unref(avPacket_.get());
402 }
403
StopThread()404 void FCodec::StopThread()
405 {
406 if (sendTask_ != nullptr && inputAvailQue_ != nullptr) {
407 std::unique_lock<std::mutex> sLock(sendMutex_);
408 sendCv_.notify_one();
409 sLock.unlock();
410 inputAvailQue_->SetActive(false, false);
411 sendTask_->Stop();
412 }
413 if (receiveTask_ != nullptr && codecAvailQue_ != nullptr) {
414 std::unique_lock<std::mutex> rLock(recvMutex_);
415 recvCv_.notify_one();
416 rLock.unlock();
417 codecAvailQue_->SetActive(false, false);
418 receiveTask_->Stop();
419 }
420 if (sInfo_.surface != nullptr && renderAvailQue_ != nullptr) {
421 renderAvailQue_->SetActive(false, false);
422 }
423 }
424
Stop()425 int32_t FCodec::Stop()
426 {
427 AVCODEC_SYNC_TRACE;
428 CHECK_AND_RETURN_RET_LOG((IsActive()), AVCS_ERR_INVALID_STATE, "Stop codec failed: not in executing state");
429 state_ = State::STOPPING;
430 AVCODEC_LOGI("step into STOPPING status");
431 std::unique_lock<std::mutex> sLock(sendMutex_);
432 sendCv_.notify_one();
433 sLock.unlock();
434 inputAvailQue_->SetActive(false, false);
435 sendTask_->Stop();
436
437 if (sInfo_.surface != nullptr) {
438 renderAvailQue_->SetActive(false, false);
439 }
440 std::unique_lock<std::mutex> rLock(recvMutex_);
441 recvCv_.notify_one();
442 rLock.unlock();
443 codecAvailQue_->SetActive(false, false);
444 receiveTask_->Stop();
445 avcodec_close(avCodecContext_.get());
446 ResetContext(true);
447 ReleaseBuffers();
448 state_ = State::CONFIGURED;
449 AVCODEC_LOGI("Stop codec successful, state: Configured");
450 return AVCS_ERR_OK;
451 }
452
Flush()453 int32_t FCodec::Flush()
454 {
455 AVCODEC_SYNC_TRACE;
456 CHECK_AND_RETURN_RET_LOG((state_ == State::RUNNING || state_ == State::EOS), AVCS_ERR_INVALID_STATE,
457 "Flush codec failed: not in running or Eos state");
458 state_ = State::FLUSHING;
459 AVCODEC_LOGI("step into FLUSHING status");
460 std::unique_lock<std::mutex> sLock(sendMutex_);
461 sendCv_.notify_one();
462 sLock.unlock();
463 inputAvailQue_->SetActive(false, false);
464 sendTask_->Pause();
465
466 if (sInfo_.surface != nullptr) {
467 renderAvailQue_->SetActive(false, false);
468 }
469 std::unique_lock<std::mutex> rLock(recvMutex_);
470 recvCv_.notify_one();
471 rLock.unlock();
472 codecAvailQue_->SetActive(false, false);
473 receiveTask_->Pause();
474
475 avcodec_flush_buffers(avCodecContext_.get());
476 ResetContext(true);
477 ResetBuffers();
478 state_ = State::FLUSHED;
479 AVCODEC_LOGI("Flush codec successful, state: Flushed");
480 return AVCS_ERR_OK;
481 }
482
Reset()483 int32_t FCodec::Reset()
484 {
485 AVCODEC_SYNC_TRACE;
486 AVCODEC_LOGI("Reset codec called");
487 int32_t ret = Release();
488 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Reset codec failed: cannot release codec");
489 ret = Initialize();
490 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Reset codec failed: cannot init codec");
491 AVCODEC_LOGI("Reset codec successful, state: Initialized");
492 return AVCS_ERR_OK;
493 }
494
ReleaseResource()495 void FCodec::ReleaseResource()
496 {
497 StopThread();
498 if (avCodecContext_ != nullptr) {
499 avcodec_close(avCodecContext_.get());
500 ResetContext();
501 }
502 ReleaseBuffers();
503 format_ = Format();
504 if (sInfo_.surface != nullptr) {
505 int ret = UnRegisterListenerToSurface(sInfo_.surface);
506 if (ret != 0) {
507 callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN);
508 state_ = State::ERROR;
509 }
510 }
511 sInfo_.surface = nullptr;
512 }
513
Release()514 int32_t FCodec::Release()
515 {
516 AVCODEC_SYNC_TRACE;
517 state_ = State::STOPPING;
518 AVCODEC_LOGI("step into STOPPING status");
519 ReleaseResource();
520 state_ = State::UNINITIALIZED;
521 AVCODEC_LOGI("Release codec successful, state: Uninitialized");
522 return AVCS_ERR_OK;
523 }
524
SetSurfaceParameter(const Format & format,const std::string_view & formatKey,FormatDataType formatType)525 void FCodec::SetSurfaceParameter(const Format &format, const std::string_view &formatKey, FormatDataType formatType)
526 {
527 CHECK_AND_RETURN_LOG(formatType == FORMAT_TYPE_INT32, "Set parameter failed: type should be int32");
528 int32_t val = 0;
529 CHECK_AND_RETURN_LOG(format.GetIntValue(formatKey, val), "Set parameter failed: get value fail");
530 if (formatKey == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT) {
531 VideoPixelFormat vpf = static_cast<VideoPixelFormat>(val);
532 CHECK_AND_RETURN_LOG(vpf == VideoPixelFormat::RGBA || vpf == VideoPixelFormat::YUVI420 ||
533 vpf == VideoPixelFormat::NV12 || vpf == VideoPixelFormat::NV21,
534 "Set parameter failed: pixel format value %{public}d invalid", val);
535 outputPixelFmt_ = vpf;
536 {
537 std::lock_guard<std::mutex> lock(formatMutex_);
538 format_.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, val);
539 }
540 GraphicPixelFormat surfacePixelFmt = TranslateSurfaceFormat(vpf);
541 std::lock_guard<std::mutex> sLock(surfaceMutex_);
542 sInfo_.requestConfig.format = surfacePixelFmt;
543 } else if (formatKey == MediaDescriptionKey::MD_KEY_ROTATION_ANGLE) {
544 VideoRotation sr = static_cast<VideoRotation>(val);
545 CHECK_AND_RETURN_LOG(sr == VideoRotation::VIDEO_ROTATION_0 || sr == VideoRotation::VIDEO_ROTATION_90 ||
546 sr == VideoRotation::VIDEO_ROTATION_180 || sr == VideoRotation::VIDEO_ROTATION_270,
547 "Set parameter failed: rotation angle value %{public}d invalid", val);
548 {
549 std::lock_guard<std::mutex> lock(formatMutex_);
550 format_.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, val);
551 }
552 std::lock_guard<std::mutex> sLock(surfaceMutex_);
553 sInfo_.surface->SetTransform(TranslateSurfaceRotation(sr));
554 } else if (formatKey == MediaDescriptionKey::MD_KEY_SCALE_TYPE) {
555 ScalingMode scaleMode = static_cast<ScalingMode>(val);
556 CHECK_AND_RETURN_LOG(scaleMode == ScalingMode::SCALING_MODE_SCALE_TO_WINDOW ||
557 scaleMode == ScalingMode::SCALING_MODE_SCALE_CROP,
558 "Set parameter failed: scale type value %{public}d invalid", val);
559 {
560 std::lock_guard<std::mutex> lock(formatMutex_);
561 format_.PutIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE, val);
562 }
563 std::lock_guard<std::mutex> sLock(surfaceMutex_);
564 sInfo_.scalingMode = scaleMode;
565 } else {
566 AVCODEC_LOGW("Set parameter failed: %{public}s", std::string(formatKey).c_str());
567 return;
568 }
569 AVCODEC_LOGI("Set parameter %{public}s success, val %{public}d", std::string(formatKey).c_str(), val);
570 }
571
SetParameter(const Format & format)572 int32_t FCodec::SetParameter(const Format &format)
573 {
574 AVCODEC_SYNC_TRACE;
575 for (auto &it : format.GetFormatMap()) {
576 if (sInfo_.surface != nullptr && it.second.type == FORMAT_TYPE_INT32) {
577 if (it.first == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT ||
578 it.first == MediaDescriptionKey::MD_KEY_ROTATION_ANGLE ||
579 it.first == MediaDescriptionKey::MD_KEY_SCALE_TYPE) {
580 SetSurfaceParameter(format, it.first, it.second.type);
581 }
582 } else {
583 AVCODEC_LOGW("Current Version, %{public}s is not supported", it.first.data());
584 }
585 }
586 AVCODEC_LOGI("Set parameter successful");
587 return AVCS_ERR_OK;
588 }
589
GetOutputFormat(Format & format)590 int32_t FCodec::GetOutputFormat(Format &format)
591 {
592 AVCODEC_SYNC_TRACE;
593 if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_BITRATE)) {
594 if (avCodecContext_ != nullptr) {
595 format_.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, avCodecContext_->bit_rate);
596 }
597 }
598 if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_FRAME_RATE)) {
599 if (avCodecContext_ != nullptr && avCodecContext_->framerate.den > 0) {
600 double value = static_cast<double>(avCodecContext_->framerate.num) /
601 static_cast<double>(avCodecContext_->framerate.den);
602 format_.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, value);
603 }
604 }
605 if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_MAX_INPUT_SIZE)) {
606 int32_t stride = AlignUp(width_, VIDEO_ALIGN_SIZE);
607 int32_t maxInputSize = static_cast<int32_t>((stride * height_ * VIDEO_PIX_DEPTH_YUV) / UV_SCALE_FACTOR);
608 format_.PutIntValue(MediaDescriptionKey::MD_KEY_MAX_INPUT_SIZE, maxInputSize);
609 }
610 {
611 std::lock_guard<std::mutex> lock(formatMutex_);
612 format = format_;
613 }
614 AVCODEC_LOGI("Get outputFormat successful");
615 return AVCS_ERR_OK;
616 }
617
CalculateBufferSize()618 void FCodec::CalculateBufferSize()
619 {
620 int32_t stride = AlignUp(width_, VIDEO_ALIGN_SIZE);
621 outputBufferSize_ = static_cast<int32_t>((stride * height_ * VIDEO_PIX_DEPTH_YUV) / UV_SCALE_FACTOR);
622 inputBufferSize_ = std::max(VIDEO_MIN_BUFFER_SIZE, outputBufferSize_);
623 if (outputPixelFmt_ == VideoPixelFormat::RGBA) {
624 outputBufferSize_ = static_cast<int32_t>(stride * height_ * VIDEO_PIX_DEPTH_RGBA);
625 }
626 AVCODEC_LOGI("width = %{public}d, height = %{public}d, stride = %{public}d, Input buffer size = %{public}d, output "
627 "buffer size=%{public}d",
628 width_, height_, stride, inputBufferSize_, outputBufferSize_);
629 }
630
AllocateInputBuffer(int32_t bufferCnt,int32_t inBufferSize)631 int32_t FCodec::AllocateInputBuffer(int32_t bufferCnt, int32_t inBufferSize)
632 {
633 int32_t valBufferCnt = 0;
634 for (int32_t i = 0; i < bufferCnt; i++) {
635 std::shared_ptr<FBuffer> buf = std::make_shared<FBuffer>();
636 std::shared_ptr<AVAllocator> allocator =
637 AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
638 CHECK_AND_CONTINUE_LOG(allocator != nullptr, "input buffer %{public}d allocator is nullptr", i);
639 buf->avBuffer_ = AVBuffer::CreateAVBuffer(allocator, inBufferSize);
640 CHECK_AND_CONTINUE_LOG(buf->avBuffer_ != nullptr, "Allocate input buffer failed, index=%{public}d", i);
641 AVCODEC_LOGI("Allocate input buffer success: index=%{public}d, size=%{public}d", i,
642 buf->avBuffer_->memory_->GetCapacity());
643 buffers_[INDEX_INPUT].emplace_back(buf);
644 valBufferCnt++;
645 }
646 if (valBufferCnt < DEFAULT_MIN_BUFFER_CNT) {
647 AVCODEC_LOGE("Allocate input buffer failed: only %{public}d buffer is allocated, no memory", valBufferCnt);
648 buffers_[INDEX_INPUT].clear();
649 return AVCS_ERR_NO_MEMORY;
650 }
651 return AVCS_ERR_OK;
652 }
653
SetSurfaceCfg(int32_t bufferCnt)654 int32_t FCodec::SetSurfaceCfg(int32_t bufferCnt)
655 {
656 CHECK_AND_RETURN_RET_LOG(sInfo_.surface->SetQueueSize(bufferCnt) == OHOS::SurfaceError::SURFACE_ERROR_OK,
657 AVCS_ERR_NO_MEMORY, "Surface set QueueSize=%{public}d failed", bufferCnt);
658 if (outputPixelFmt_ == VideoPixelFormat::UNKNOWN) {
659 format_.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, static_cast<int32_t>(VideoPixelFormat::NV12));
660 }
661 int32_t val32 = 0;
662 format_.GetIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, val32);
663 GraphicPixelFormat surfacePixelFmt = TranslateSurfaceFormat(static_cast<VideoPixelFormat>(val32));
664 CHECK_AND_RETURN_RET_LOG(surfacePixelFmt != GraphicPixelFormat::GRAPHIC_PIXEL_FMT_BUTT, AVCS_ERR_UNSUPPORT,
665 "Failed to allocate output buffer: unsupported surface format");
666 sInfo_.requestConfig.width = width_;
667 sInfo_.requestConfig.height = height_;
668 sInfo_.requestConfig.format = surfacePixelFmt;
669
670 format_.GetIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE, val32);
671 sInfo_.scalingMode = static_cast<ScalingMode>(val32);
672 format_.GetIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, val32);
673 sInfo_.surface->SetTransform(TranslateSurfaceRotation(static_cast<VideoRotation>(val32)));
674 return AVCS_ERR_OK;
675 }
676
AllocateOutputBuffer(int32_t bufferCnt,int32_t outBufferSize)677 int32_t FCodec::AllocateOutputBuffer(int32_t bufferCnt, int32_t outBufferSize)
678 {
679 int32_t valBufferCnt = 0;
680 if (sInfo_.surface) {
681 CHECK_AND_RETURN_RET_LOG(SetSurfaceCfg(bufferCnt) == AVCS_ERR_OK, AVCS_ERR_UNKNOWN, "SetSurfaceCfg failed");
682 sInfo_.surface->CleanCache();
683 }
684 for (int i = 0; i < bufferCnt; i++) {
685 std::shared_ptr<FBuffer> buf = std::make_shared<FBuffer>();
686 if (sInfo_.surface == nullptr) {
687 std::shared_ptr<AVAllocator> allocator =
688 AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
689 CHECK_AND_CONTINUE_LOG(allocator != nullptr, "output buffer %{public}d allocator is nullptr", i);
690 buf->avBuffer_ = AVBuffer::CreateAVBuffer(allocator, outBufferSize);
691 AVCODEC_LOGI("Allocate output share buffer success: index=%{public}d, size=%{public}d", i,
692 buf->avBuffer_->memory_->GetCapacity());
693 } else {
694 buf->sMemory_ = std::make_shared<FSurfaceMemory>(&sInfo_);
695 CHECK_AND_CONTINUE_LOG(buf->sMemory_->GetSurfaceBuffer() != nullptr,
696 "output surface memory %{public}d create fail", i);
697 outAVBuffer4Surface_.emplace_back(AVBuffer::CreateAVBuffer());
698 buf->avBuffer_ = AVBuffer::CreateAVBuffer(buf->sMemory_->GetBase(), buf->sMemory_->GetSize());
699 AVCODEC_LOGI("Allocate output surface buffer success: index=%{public}d, size=%{public}d, "
700 "stride=%{public}d",
701 i, buf->sMemory_->GetSize(), buf->sMemory_->GetSurfaceBufferStride());
702 }
703 CHECK_AND_CONTINUE_LOG(buf->avBuffer_ != nullptr, "Allocate output buffer failed, index=%{public}d", i);
704
705 buf->width_ = width_;
706 buf->height_ = height_;
707 buffers_[INDEX_OUTPUT].emplace_back(buf);
708 valBufferCnt++;
709 }
710 if (valBufferCnt < DEFAULT_MIN_BUFFER_CNT) {
711 AVCODEC_LOGE("Allocate output buffer failed: only %{public}d buffer is allocated, no memory", valBufferCnt);
712 buffers_[INDEX_INPUT].clear();
713 buffers_[INDEX_OUTPUT].clear();
714 return AVCS_ERR_NO_MEMORY;
715 }
716 return AVCS_ERR_OK;
717 }
718
AllocateBuffers()719 int32_t FCodec::AllocateBuffers()
720 {
721 AVCODEC_SYNC_TRACE;
722 CalculateBufferSize();
723 CHECK_AND_RETURN_RET_LOG(inputBufferSize_ > 0 && outputBufferSize_ > 0, AVCS_ERR_INVALID_VAL,
724 "Allocate buffer with input size=%{public}d, output size=%{public}d failed",
725 inputBufferSize_, outputBufferSize_);
726 if (sInfo_.surface != nullptr && isOutBufSetted_ == false) {
727 format_.PutIntValue(MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, DEFAULT_OUT_SURFACE_CNT);
728 }
729 int32_t inputBufferCnt = 0;
730 int32_t outputBufferCnt = 0;
731 format_.GetIntValue(MediaDescriptionKey::MD_KEY_MAX_INPUT_BUFFER_COUNT, inputBufferCnt);
732 format_.GetIntValue(MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, outputBufferCnt);
733 inputAvailQue_ = std::make_shared<BlockQueue<uint32_t>>("inputAvailQue", inputBufferCnt);
734 codecAvailQue_ = std::make_shared<BlockQueue<uint32_t>>("codecAvailQue", outputBufferCnt);
735 if (sInfo_.surface != nullptr) {
736 renderAvailQue_ = std::make_shared<BlockQueue<uint32_t>>("renderAvailQue", outputBufferCnt);
737 }
738 if (AllocateInputBuffer(inputBufferCnt, inputBufferSize_) == AVCS_ERR_NO_MEMORY ||
739 AllocateOutputBuffer(outputBufferCnt, outputBufferSize_) == AVCS_ERR_NO_MEMORY) {
740 return AVCS_ERR_NO_MEMORY;
741 }
742 AVCODEC_LOGI("Allocate buffers successful");
743 return AVCS_ERR_OK;
744 }
745
UpdateBuffers(uint32_t index,int32_t bufferSize,uint32_t bufferType)746 int32_t FCodec::UpdateBuffers(uint32_t index, int32_t bufferSize, uint32_t bufferType)
747 {
748 int32_t curBufSize = buffers_[bufferType][index]->avBuffer_->memory_->GetCapacity();
749 if (bufferSize != curBufSize) {
750 std::shared_ptr<FBuffer> buf = std::make_shared<FBuffer>();
751 std::shared_ptr<AVAllocator> allocator =
752 AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
753 CHECK_AND_RETURN_RET_LOG(allocator != nullptr, AVCS_ERR_NO_MEMORY, "buffer %{public}d allocator is nullptr",
754 index);
755 buf->avBuffer_ = AVBuffer::CreateAVBuffer(allocator, bufferSize);
756 CHECK_AND_RETURN_RET_LOG(buf->avBuffer_ != nullptr, AVCS_ERR_NO_MEMORY,
757 "Buffer allocate failed, index=%{public}d", index);
758 AVCODEC_LOGI("update share buffer success: bufferType=%{public}u, index=%{public}d, size=%{public}d",
759 bufferType, index, buf->avBuffer_->memory_->GetCapacity());
760
761 if (bufferType == INDEX_INPUT) {
762 buf->owner_ = FBuffer::Owner::OWNED_BY_USER;
763 } else {
764 buf->owner_ = FBuffer::Owner::OWNED_BY_CODEC;
765 }
766 buffers_[bufferType][index] = buf;
767 }
768 return AVCS_ERR_OK;
769 }
770
UpdateSurfaceMemory(uint32_t index)771 int32_t FCodec::UpdateSurfaceMemory(uint32_t index)
772 {
773 AVCODEC_SYNC_TRACE;
774 std::unique_lock<std::mutex> oLock(outputMutex_);
775 std::shared_ptr<FBuffer> outputBuffer = buffers_[INDEX_OUTPUT][index];
776 oLock.unlock();
777 if (width_ != outputBuffer->width_ || height_ != outputBuffer->height_) {
778 std::shared_ptr<FSurfaceMemory> surfaceMemory = outputBuffer->sMemory_;
779 surfaceMemory->SetNeedRender(false);
780 surfaceMemory->ReleaseSurfaceBuffer();
781 while (state_ == State::RUNNING) {
782 std::unique_lock<std::mutex> sLock(surfaceMutex_);
783 sptr<SurfaceBuffer> surfaceBuffer = surfaceMemory->GetSurfaceBuffer();
784 sLock.unlock();
785 if (surfaceBuffer != nullptr) {
786 break;
787 }
788 std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TRY_REQ_TIME));
789 }
790
791 outputBuffer->avBuffer_ =
792 AVBuffer::CreateAVBuffer(outputBuffer->sMemory_->GetBase(), outputBuffer->sMemory_->GetSize());
793 outputBuffer->width_ = width_;
794 outputBuffer->height_ = height_;
795 }
796
797 return AVCS_ERR_OK;
798 }
799
CheckFormatChange(uint32_t index,int width,int height)800 int32_t FCodec::CheckFormatChange(uint32_t index, int width, int height)
801 {
802 if (width_ != width || height_ != height) {
803 AVCODEC_LOGI("format change, width: %{public}d->%{public}d, height: %{public}d->%{public}d", width_, width,
804 height_, height);
805 width_ = width;
806 height_ = height;
807 ResetData();
808 scale_ = nullptr;
809 CalculateBufferSize();
810 {
811 std::lock_guard<std::mutex> lock(formatMutex_);
812 format_.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width_);
813 format_.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height_);
814 format_.PutIntValue(OHOS::Media::Tag::VIDEO_STRIDE,
815 outputPixelFmt_ == VideoPixelFormat::RGBA ? width_ * VIDEO_PIX_DEPTH_RGBA : width_);
816 format_.PutIntValue(OHOS::Media::Tag::VIDEO_SLICE_HEIGHT, height_);
817 format_.PutIntValue(OHOS::Media::Tag::VIDEO_PIC_WIDTH, width_);
818 format_.PutIntValue(OHOS::Media::Tag::VIDEO_PIC_HEIGHT, height_);
819 }
820 if (sInfo_.surface) {
821 std::lock_guard<std::mutex> sLock(surfaceMutex_);
822 sInfo_.requestConfig.width = width_;
823 sInfo_.requestConfig.height = height_;
824 }
825 callback_->OnOutputFormatChanged(format_);
826 }
827 if (sInfo_.surface == nullptr) {
828 std::lock_guard<std::mutex> oLock(outputMutex_);
829 CHECK_AND_RETURN_RET_LOG((UpdateBuffers(index, outputBufferSize_, INDEX_OUTPUT) == AVCS_ERR_OK),
830 AVCS_ERR_NO_MEMORY, "Update output buffer failed, index=%{public}u", index);
831 } else {
832 CHECK_AND_RETURN_RET_LOG((UpdateSurfaceMemory(index) == AVCS_ERR_OK), AVCS_ERR_NO_MEMORY,
833 "Update buffer failed");
834 }
835 return AVCS_ERR_OK;
836 }
837
ReleaseBuffers()838 void FCodec::ReleaseBuffers()
839 {
840 ResetData();
841 if (!isBufferAllocated_) {
842 return;
843 }
844
845 inputAvailQue_->Clear();
846 std::unique_lock<std::mutex> iLock(inputMutex_);
847 buffers_[INDEX_INPUT].clear();
848 synIndex_ = std::nullopt;
849 iLock.unlock();
850
851 std::unique_lock<std::mutex> oLock(outputMutex_);
852 codecAvailQue_->Clear();
853 if (sInfo_.surface != nullptr) {
854 renderAvailQue_->Clear();
855 renderSurfaceBufferMap_.clear();
856 for (uint32_t i = 0; i < buffers_[INDEX_OUTPUT].size(); i++) {
857 std::shared_ptr<FBuffer> outputBuffer = buffers_[INDEX_OUTPUT][i];
858 if (outputBuffer->owner_ == FBuffer::Owner::OWNED_BY_CODEC) {
859 std::shared_ptr<FSurfaceMemory> surfaceMemory = outputBuffer->sMemory_;
860 surfaceMemory->SetNeedRender(false);
861 surfaceMemory->ReleaseSurfaceBuffer();
862 outputBuffer->owner_ = FBuffer::Owner::OWNED_BY_SURFACE;
863 }
864 }
865 sInfo_.surface->CleanCache();
866 AVCODEC_LOGI("surface cleancache success");
867 }
868 buffers_[INDEX_OUTPUT].clear();
869 outAVBuffer4Surface_.clear();
870 oLock.unlock();
871 isBufferAllocated_ = false;
872 }
873
QueueInputBuffer(uint32_t index)874 int32_t FCodec::QueueInputBuffer(uint32_t index)
875 {
876 AVCODEC_SYNC_TRACE;
877 CHECK_AND_RETURN_RET_LOG(state_ == State::RUNNING, AVCS_ERR_INVALID_STATE,
878 "Queue input buffer failed: not in Running state");
879 CHECK_AND_RETURN_RET_LOG(index < buffers_[INDEX_INPUT].size(), AVCS_ERR_INVALID_VAL,
880 "Queue input buffer failed with bad index, index=%{public}u, buffer_size=%{public}zu",
881 index, buffers_[INDEX_INPUT].size());
882 std::shared_ptr<FBuffer> inputBuffer = buffers_[INDEX_INPUT][index];
883 CHECK_AND_RETURN_RET_LOG(inputBuffer->owner_ == FBuffer::Owner::OWNED_BY_USER, AVCS_ERR_INVALID_OPERATION,
884 "Queue input buffer failed: buffer with index=%{public}u is not available", index);
885
886 inputBuffer->owner_ = FBuffer::Owner::OWNED_BY_CODEC;
887 std::shared_ptr<AVBuffer> &inputAVBuffer = inputBuffer->avBuffer_;
888 if (synIndex_) {
889 const std::shared_ptr<AVBuffer> &curAVBuffer = buffers_[INDEX_INPUT][synIndex_.value()]->avBuffer_;
890 int32_t curAVBufferSize = curAVBuffer->memory_->GetSize();
891 int32_t inputAVBufferSize = inputAVBuffer->memory_->GetSize();
892 if ((curAVBufferSize + inputAVBufferSize <= curAVBuffer->memory_->GetCapacity()) &&
893 memcpy_s(curAVBuffer->memory_->GetAddr() + curAVBufferSize, inputAVBufferSize,
894 inputAVBuffer->memory_->GetAddr(), inputAVBufferSize) == EOK) {
895 curAVBuffer->memory_->SetSize(curAVBufferSize + inputAVBufferSize);
896 curAVBuffer->flag_ = inputAVBuffer->flag_;
897 curAVBuffer->pts_ = inputAVBuffer->pts_;
898
899 if (inputAVBuffer->flag_ != AVCODEC_BUFFER_FLAG_CODEC_DATA &&
900 inputAVBuffer->flag_ != AVCODEC_BUFFER_FLAG_PARTIAL_FRAME) {
901 inputAvailQue_->Push(synIndex_.value());
902 synIndex_ = std::nullopt;
903 }
904 inputBuffer->owner_ = FBuffer::Owner::OWNED_BY_USER;
905 callback_->OnInputBufferAvailable(index, inputAVBuffer);
906 return AVCS_ERR_OK;
907 } else {
908 AVCODEC_LOGE("packet size %{public}d over buffer size %{public}d", curAVBufferSize + inputAVBufferSize,
909 curAVBuffer->memory_->GetCapacity());
910 callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_NO_MEMORY);
911 state_ = State::ERROR;
912 return AVCS_ERR_NO_MEMORY;
913 }
914 } else {
915 if ((inputAVBuffer->flag_ == AVCODEC_BUFFER_FLAG_CODEC_DATA) ||
916 (inputAVBuffer->flag_ == AVCODEC_BUFFER_FLAG_PARTIAL_FRAME)) {
917 synIndex_ = index;
918 } else {
919 inputAvailQue_->Push(index);
920 }
921 }
922
923 return AVCS_ERR_OK;
924 }
925
SendFrame()926 void FCodec::SendFrame()
927 {
928 CHECK_AND_RETURN_LOG(state_ != State::STOPPING && state_ != State::FLUSHING, "Invalid state");
929 if (state_ != State::RUNNING || isSendEos_) {
930 std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TRY_DECODE_TIME));
931 return;
932 }
933 uint32_t index = inputAvailQue_->Front();
934 CHECK_AND_RETURN_LOG(state_ == State::RUNNING, "Not in running state");
935 std::shared_ptr<FBuffer> &inputBuffer = buffers_[INDEX_INPUT][index];
936 std::shared_ptr<AVBuffer> &inputAVBuffer = inputBuffer->avBuffer_;
937 if (inputAVBuffer->flag_ & AVCODEC_BUFFER_FLAG_EOS) {
938 avPacket_->data = nullptr;
939 avPacket_->size = 0;
940 avPacket_->pts = 0;
941 std::unique_lock<std::mutex> sendLock(sendMutex_);
942 isSendEos_ = true;
943 sendCv_.wait_for(sendLock, std::chrono::milliseconds(DEFAULT_DECODE_WAIT_TIME));
944 AVCODEC_LOGI("Send eos end");
945 } else {
946 avPacket_->data = inputAVBuffer->memory_->GetAddr();
947 avPacket_->size = static_cast<int32_t>(inputAVBuffer->memory_->GetSize());
948 avPacket_->pts = inputAVBuffer->pts_;
949 }
950 std::unique_lock<std::mutex> sLock(syncMutex_);
951 int ret = avcodec_send_packet(avCodecContext_.get(), avPacket_.get());
952 sLock.unlock();
953 if (ret == 0 || ret == AVERROR_INVALIDDATA) {
954 EXPECT_AND_LOGW(ret == AVERROR_INVALIDDATA, "ffmpeg ret = %{public}s", AVStrError(ret).c_str());
955 std::unique_lock<std::mutex> recvLock(recvMutex_);
956 recvCv_.notify_one();
957 recvLock.unlock();
958 inputAvailQue_->Pop();
959 inputBuffer->owner_ = FBuffer::Owner::OWNED_BY_USER;
960 #ifdef BUILD_ENG_VERSION
961 if (dumpInFile_ && dumpInFile_->is_open()) {
962 dumpInFile_->write(reinterpret_cast<char *>(inputAVBuffer->memory_->GetAddr()),
963 static_cast<int32_t>(inputAVBuffer->memory_->GetSize()));
964 }
965 #endif // BUILD_ENG_VERSION
966 callback_->OnInputBufferAvailable(index, inputAVBuffer);
967 } else if (ret == AVERROR(EAGAIN)) {
968 std::unique_lock<std::mutex> sendLock(sendMutex_);
969 isSendWait_ = true;
970 sendCv_.wait_for(sendLock, std::chrono::milliseconds(DEFAULT_DECODE_WAIT_TIME));
971 } else {
972 AVCODEC_LOGE("Cannot send frame to codec: ffmpeg ret = %{public}s", AVStrError(ret).c_str());
973 callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN);
974 state_ = State::ERROR;
975 }
976 }
977
FillFrameBuffer(const std::shared_ptr<FBuffer> & frameBuffer)978 int32_t FCodec::FillFrameBuffer(const std::shared_ptr<FBuffer> &frameBuffer)
979 {
980 VideoPixelFormat targetPixelFmt = outputPixelFmt_;
981 if (outputPixelFmt_ == VideoPixelFormat::UNKNOWN) {
982 targetPixelFmt = sInfo_.surface ? VideoPixelFormat::NV12 : ConvertPixelFormatFromFFmpeg(cachedFrame_->format);
983 }
984 AVPixelFormat ffmpegFormat = ConvertPixelFormatToFFmpeg(targetPixelFmt);
985 int32_t ret;
986 if (ffmpegFormat == static_cast<AVPixelFormat>(cachedFrame_->format)) {
987 for (int32_t i = 0; cachedFrame_->linesize[i] > 0; i++) {
988 scaleData_[i] = cachedFrame_->data[i];
989 scaleLineSize_[i] = cachedFrame_->linesize[i];
990 }
991 } else {
992 ret = ConvertVideoFrame(&scale_, cachedFrame_, scaleData_, scaleLineSize_, ffmpegFormat);
993 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Scale video frame failed: %{public}d", ret);
994 isConverted_ = true;
995 }
996 {
997 std::lock_guard<std::mutex> lock(formatMutex_);
998 format_.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, static_cast<int32_t>(targetPixelFmt));
999 }
1000 std::shared_ptr<AVMemory> &bufferMemory = frameBuffer->avBuffer_->memory_;
1001 CHECK_AND_RETURN_RET_LOG(bufferMemory != nullptr, AVCS_ERR_INVALID_VAL, "bufferMemory is nullptr");
1002 bufferMemory->SetSize(0);
1003 if (sInfo_.surface) {
1004 struct SurfaceInfo surfaceInfo;
1005 surfaceInfo.surfaceStride = static_cast<uint32_t>(frameBuffer->sMemory_->GetSurfaceBufferStride());
1006 surfaceInfo.surfaceFence = frameBuffer->sMemory_->GetFence();
1007 surfaceInfo.scaleData = scaleData_;
1008 surfaceInfo.scaleLineSize = scaleLineSize_;
1009 ret = WriteSurfaceData(bufferMemory, surfaceInfo, format_);
1010 } else {
1011 ret = WriteBufferData(bufferMemory, scaleData_, scaleLineSize_, format_);
1012 }
1013 frameBuffer->avBuffer_->pts_ = cachedFrame_->pts;
1014 AVCODEC_LOGD("Fill frame buffer successful");
1015 return ret;
1016 }
1017
FramePostProcess(std::shared_ptr<FBuffer> & frameBuffer,uint32_t index,int32_t status,int ret)1018 void FCodec::FramePostProcess(std::shared_ptr<FBuffer> &frameBuffer, uint32_t index, int32_t status, int ret)
1019 {
1020 if (status == AVCS_ERR_OK) {
1021 codecAvailQue_->Pop();
1022 frameBuffer->owner_ = FBuffer::Owner::OWNED_BY_USER;
1023 if (sInfo_.surface) {
1024 outAVBuffer4Surface_[index]->pts_ = frameBuffer->avBuffer_->pts_;
1025 outAVBuffer4Surface_[index]->flag_ = frameBuffer->avBuffer_->flag_;
1026 }
1027 if (ret == AVERROR_EOF) {
1028 std::unique_lock<std::mutex> sLock(syncMutex_);
1029 avcodec_flush_buffers(avCodecContext_.get());
1030 sLock.unlock();
1031 } else {
1032 if (isSendWait_) {
1033 std::lock_guard<std::mutex> sLock(sendMutex_);
1034 isSendWait_ = false;
1035 sendCv_.notify_one();
1036 }
1037 }
1038 callback_->OnOutputBufferAvailable(index,
1039 sInfo_.surface ? outAVBuffer4Surface_[index] : frameBuffer->avBuffer_);
1040 } else if (status == AVCS_ERR_UNSUPPORT) {
1041 AVCODEC_LOGE("Recevie frame from codec failed: OnError");
1042 callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNSUPPORT);
1043 state_ = State::ERROR;
1044 } else {
1045 AVCODEC_LOGE("Recevie frame from codec failed");
1046 callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN);
1047 state_ = State::ERROR;
1048 }
1049 }
1050
DumpOutputBuffer()1051 void FCodec::DumpOutputBuffer()
1052 {
1053 AVCODEC_LOGD("cur decNum: %{public}u", decNum_);
1054 if (decNum_ == 0) {
1055 callback_->OnOutputFormatChanged(format_);
1056 }
1057 decNum_++;
1058 #ifdef BUILD_ENG_VERSION
1059 if (!dumpOutFile_ || !dumpOutFile_->is_open()) {
1060 return;
1061 }
1062 for (int32_t i = 0; i < cachedFrame_->height; i++) {
1063 dumpOutFile_->write(reinterpret_cast<char *>(cachedFrame_->data[0] + i * cachedFrame_->linesize[0]),
1064 static_cast<int32_t>(cachedFrame_->width));
1065 }
1066 for (int32_t i = 0; i < cachedFrame_->height / 2; i++) { // 2
1067 dumpOutFile_->write(reinterpret_cast<char *>(cachedFrame_->data[1] + i * cachedFrame_->linesize[1]),
1068 static_cast<int32_t>(cachedFrame_->width / 2)); // 2
1069 }
1070 for (int32_t i = 0; i < cachedFrame_->height / 2; i++) { // 2
1071 dumpOutFile_->write(reinterpret_cast<char *>(cachedFrame_->data[2] + i * cachedFrame_->linesize[2]),
1072 static_cast<int32_t>(cachedFrame_->width / 2)); // 2
1073 }
1074 #endif // BUILD_ENG_VERSION
1075 }
1076
ReceiveFrame()1077 void FCodec::ReceiveFrame()
1078 {
1079 if (state_ == State::STOPPING || state_ == State::FLUSHING) {
1080 return;
1081 } else if (state_ != State::RUNNING) {
1082 std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TRY_DECODE_TIME));
1083 return;
1084 }
1085 auto index = codecAvailQue_->Front();
1086 CHECK_AND_RETURN_LOG(state_ == State::RUNNING, "Not in running state");
1087 std::shared_ptr<FBuffer> frameBuffer = buffers_[INDEX_OUTPUT][index];
1088 std::unique_lock<std::mutex> sLock(syncMutex_);
1089 int ret = avcodec_receive_frame(avCodecContext_.get(), cachedFrame_.get());
1090 sLock.unlock();
1091 int32_t status = AVCS_ERR_OK;
1092 CHECK_AND_RETURN_LOG(ret != AVERROR_INVALIDDATA, "ffmpeg ret = %{public}s", AVStrError(ret).c_str());
1093 if (ret >= 0) {
1094 DumpOutputBuffer();
1095 if (CheckFormatChange(index, cachedFrame_->width, cachedFrame_->height) == AVCS_ERR_OK) {
1096 CHECK_AND_RETURN_LOG(state_ == State::RUNNING, "Not in running state");
1097 frameBuffer = buffers_[INDEX_OUTPUT][index];
1098 status = FillFrameBuffer(frameBuffer);
1099 } else {
1100 CHECK_AND_RETURN_LOG(state_ == State::RUNNING, "Not in running state");
1101 callback_->OnError(AVCODEC_ERROR_EXTEND_START, AVCS_ERR_NO_MEMORY);
1102 return;
1103 }
1104 frameBuffer->avBuffer_->flag_ = AVCODEC_BUFFER_FLAG_NONE;
1105 } else if (ret == AVERROR_EOF) {
1106 AVCODEC_LOGI("Receive eos");
1107 frameBuffer->avBuffer_->flag_ = AVCODEC_BUFFER_FLAG_EOS;
1108 frameBuffer->avBuffer_->memory_->SetSize(0);
1109 state_ = State::EOS;
1110 } else if (ret == AVERROR(EAGAIN)) {
1111 std::unique_lock<std::mutex> sendLock(sendMutex_);
1112 if (isSendWait_ || isSendEos_) {
1113 isSendWait_ = false;
1114 sendCv_.notify_one();
1115 }
1116 sendLock.unlock();
1117 std::unique_lock<std::mutex> recvLock(recvMutex_);
1118 recvCv_.wait_for(recvLock, std::chrono::milliseconds(DEFAULT_DECODE_WAIT_TIME));
1119 return;
1120 } else {
1121 AVCODEC_LOGE("Cannot recv frame from codec: ffmpeg ret = %{public}s", AVStrError(ret).c_str());
1122 callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN);
1123 state_ = State::ERROR;
1124 return;
1125 }
1126 FramePostProcess(frameBuffer, index, status, ret);
1127 }
1128
FindAvailIndex(uint32_t index)1129 void FCodec::FindAvailIndex(uint32_t index)
1130 {
1131 uint32_t curQueSize = renderAvailQue_->Size();
1132 for (uint32_t i = 0u; i < curQueSize; i++) {
1133 uint32_t num = renderAvailQue_->Pop();
1134 if (num == index) {
1135 break;
1136 } else {
1137 renderAvailQue_->Push(num);
1138 }
1139 }
1140 }
1141
ReleaseOutputBuffer(uint32_t index)1142 int32_t FCodec::ReleaseOutputBuffer(uint32_t index)
1143 {
1144 AVCODEC_SYNC_TRACE;
1145 std::unique_lock<std::mutex> oLock(outputMutex_);
1146 CHECK_AND_RETURN_RET_LOG(index < buffers_[INDEX_OUTPUT].size(), AVCS_ERR_INVALID_VAL,
1147 "Failed to release output buffer: invalid index");
1148 std::shared_ptr<FBuffer> frameBuffer = buffers_[INDEX_OUTPUT][index];
1149 oLock.unlock();
1150 if (frameBuffer->owner_ == FBuffer::Owner::OWNED_BY_USER) {
1151 frameBuffer->owner_ = FBuffer::Owner::OWNED_BY_CODEC;
1152 codecAvailQue_->Push(index);
1153 return AVCS_ERR_OK;
1154 } else {
1155 AVCODEC_LOGE("Release output buffer failed: check your index=%{public}u", index);
1156 return AVCS_ERR_INVALID_VAL;
1157 }
1158 }
1159
FlushSurfaceMemory(std::shared_ptr<FSurfaceMemory> & surfaceMemory,uint32_t index)1160 int32_t FCodec::FlushSurfaceMemory(std::shared_ptr<FSurfaceMemory> &surfaceMemory, uint32_t index)
1161 {
1162 sptr<SurfaceBuffer> surfaceBuffer = surfaceMemory->GetSurfaceBuffer();
1163 CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, AVCS_ERR_INVALID_VAL,
1164 "Failed to update surface memory: surface buffer is NULL");
1165 OHOS::BufferFlushConfig flushConfig = {{0, 0, surfaceBuffer->GetWidth(), surfaceBuffer->GetHeight()},
1166 outAVBuffer4Surface_[index]->pts_, -1};
1167 surfaceMemory->SetNeedRender(true);
1168 surfaceMemory->UpdateSurfaceBufferScaleMode();
1169 if (outAVBuffer4Surface_[index]->meta_->Find(OHOS::Media::Tag::VIDEO_DECODER_DESIRED_PRESENT_TIMESTAMP) !=
1170 outAVBuffer4Surface_[index]->meta_->end()) {
1171 outAVBuffer4Surface_[index]->meta_->Get<OHOS::Media::Tag::VIDEO_DECODER_DESIRED_PRESENT_TIMESTAMP>(
1172 flushConfig.desiredPresentTimestamp);
1173 outAVBuffer4Surface_[index]->meta_->Remove(OHOS::Media::Tag::VIDEO_DECODER_DESIRED_PRESENT_TIMESTAMP);
1174 }
1175 auto res = sInfo_.surface->FlushBuffer(surfaceBuffer, -1, flushConfig);
1176 if (res != OHOS::SurfaceError::SURFACE_ERROR_OK) {
1177 AVCODEC_LOGW("Failed to update surface memory: %{public}d", res);
1178 surfaceMemory->SetNeedRender(false);
1179 surfaceMemory->ReleaseSurfaceBuffer();
1180 return AVCS_ERR_UNKNOWN;
1181 }
1182 renderSurfaceBufferMap_[index] = std::make_pair(surfaceBuffer, flushConfig);
1183 surfaceMemory->ReleaseSurfaceBuffer();
1184 return AVCS_ERR_OK;
1185 }
1186
RenderOutputBuffer(uint32_t index)1187 int32_t FCodec::RenderOutputBuffer(uint32_t index)
1188 {
1189 AVCODEC_SYNC_TRACE;
1190 CHECK_AND_RETURN_RET_LOG(sInfo_.surface != nullptr, AVCS_ERR_UNSUPPORT,
1191 "RenderOutputBuffer fail, surface is nullptr");
1192 std::unique_lock<std::mutex> oLock(outputMutex_);
1193 CHECK_AND_RETURN_RET_LOG(index < buffers_[INDEX_OUTPUT].size(), AVCS_ERR_INVALID_VAL,
1194 "Failed to render output buffer: invalid index");
1195 std::shared_ptr<FBuffer> frameBuffer = buffers_[INDEX_OUTPUT][index];
1196 oLock.unlock();
1197 std::lock_guard<std::mutex> sLock(surfaceMutex_);
1198 if (frameBuffer->owner_ == FBuffer::Owner::OWNED_BY_USER) {
1199 std::shared_ptr<FSurfaceMemory> surfaceMemory = frameBuffer->sMemory_;
1200 int32_t ret = FlushSurfaceMemory(surfaceMemory, index);
1201 if (ret != AVCS_ERR_OK) {
1202 AVCODEC_LOGW("Update surface memory failed: %{public}d", static_cast<int32_t>(ret));
1203 } else {
1204 AVCODEC_LOGD("Update surface memory successful");
1205 }
1206 frameBuffer->owner_ = FBuffer::Owner::OWNED_BY_SURFACE;
1207 renderAvailQue_->Push(index);
1208 AVCODEC_LOGD("render output buffer with index, index=%{public}u", index);
1209 return AVCS_ERR_OK;
1210 } else {
1211 AVCODEC_LOGE("Failed to render output buffer with bad index, index=%{public}u", index);
1212 return AVCS_ERR_INVALID_VAL;
1213 }
1214 }
1215
ReplaceOutputSurfaceWhenRunning(sptr<Surface> newSurface)1216 int32_t FCodec::ReplaceOutputSurfaceWhenRunning(sptr<Surface> newSurface)
1217 {
1218 CHECK_AND_RETURN_RET_LOG(sInfo_.surface != nullptr, AV_ERR_OPERATE_NOT_PERMIT,
1219 "Not support convert from AVBuffer Mode to Surface Mode");
1220 sptr<Surface> oldSurface = sInfo_.surface;
1221 uint64_t oldId = oldSurface->GetUniqueId();
1222 uint64_t newId = newSurface->GetUniqueId();
1223 AVCODEC_LOGI("surface %{public}" PRIu64 " -> %{public}" PRIu64 "", oldId, newId);
1224 if (oldId == newId) {
1225 return AVCS_ERR_OK;
1226 }
1227 GSError err = RegisterListenerToSurface(newSurface);
1228 CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, AVCS_ERR_UNKNOWN,
1229 "surface %{public}" PRIu64 ", RegisterListenerToSurface failed, GSError=%{public}d", newId, err);
1230 int32_t outputBufferCnt = 0;
1231 format_.GetIntValue(MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, outputBufferCnt);
1232 int32_t ret = SetQueueSize(newSurface, outputBufferCnt);
1233 if (ret != AVCS_ERR_OK) {
1234 UnRegisterListenerToSurface(newSurface);
1235 return ret;
1236 }
1237 std::unique_lock<std::mutex> sLock(surfaceMutex_);
1238 ret = SwitchBetweenSurface(newSurface);
1239 if (ret != AVCS_ERR_OK) {
1240 UnRegisterListenerToSurface(newSurface);
1241 sInfo_.surface = oldSurface;
1242 return ret;
1243 }
1244 sLock.unlock();
1245 return AVCS_ERR_OK;
1246 }
1247
SetQueueSize(const sptr<Surface> & surface,uint32_t targetSize)1248 int32_t FCodec::SetQueueSize(const sptr<Surface> &surface, uint32_t targetSize)
1249 {
1250 int32_t err = surface->SetQueueSize(targetSize);
1251 if (err != 0) {
1252 AVCODEC_LOGE("surface %{public}" PRIu64 ", SetQueueSize to %{public}u failed, GSError=%{public}d",
1253 surface->GetUniqueId(), targetSize, err);
1254 return AVCS_ERR_UNKNOWN;
1255 }
1256 AVCODEC_LOGI("surface %{public}" PRIu64 ", SetQueueSize to %{public}u succ", surface->GetUniqueId(), targetSize);
1257 return AVCS_ERR_OK;
1258 }
1259
SwitchBetweenSurface(const sptr<Surface> & newSurface)1260 int32_t FCodec::SwitchBetweenSurface(const sptr<Surface> &newSurface)
1261 {
1262 sptr<Surface> curSurface = sInfo_.surface;
1263 newSurface->Connect(); // cleancache will work only if the surface is connected by us
1264 newSurface->CleanCache(); // make sure new surface is empty
1265 std::vector<uint32_t> ownedBySurfaceBufferIndex;
1266 uint64_t newId = newSurface->GetUniqueId();
1267 for (uint32_t index = 0; index < buffers_[INDEX_OUTPUT].size(); index++) {
1268 if (buffers_[INDEX_OUTPUT][index]->sMemory_ == nullptr) {
1269 continue;
1270 }
1271 sptr<SurfaceBuffer> surfaceBuffer = nullptr;
1272 if (buffers_[INDEX_OUTPUT][index]->owner_ == FBuffer::Owner::OWNED_BY_SURFACE) {
1273 if (renderSurfaceBufferMap_.count(index)) {
1274 surfaceBuffer = renderSurfaceBufferMap_[index].first;
1275 ownedBySurfaceBufferIndex.push_back(index);
1276 }
1277 } else {
1278 surfaceBuffer = buffers_[INDEX_OUTPUT][index]->sMemory_->GetSurfaceBuffer();
1279 }
1280 if (surfaceBuffer == nullptr) {
1281 AVCODEC_LOGE("Get old surface buffer error!");
1282 return AVCS_ERR_UNKNOWN;
1283 }
1284 int32_t err = newSurface->AttachBufferToQueue(surfaceBuffer);
1285 if (err != 0) {
1286 AVCODEC_LOGE("surface %{public}" PRIu64 ", AttachBufferToQueue(seq=%{public}u) failed, GSError=%{public}d",
1287 newId, surfaceBuffer->GetSeqNum(), err);
1288 return AVCS_ERR_UNKNOWN;
1289 }
1290 }
1291 int32_t videoRotation = 0;
1292 format_.GetIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, videoRotation);
1293 sInfo_.surface->SetTransform(TranslateSurfaceRotation(static_cast<VideoRotation>(videoRotation)));
1294 int32_t scalingMode = 0;
1295 format_.GetIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE, scalingMode);
1296 sInfo_.scalingMode = static_cast<ScalingMode>(scalingMode);
1297 sInfo_.surface = newSurface;
1298
1299 for (uint32_t index: ownedBySurfaceBufferIndex) {
1300 int32_t ret = RenderNewSurfaceWithOldBuffer(newSurface, index);
1301 if (ret != AVCS_ERR_OK) {
1302 return ret;
1303 }
1304 }
1305
1306 int32_t ret = UnRegisterListenerToSurface(curSurface);
1307 if (ret != AVCS_ERR_OK) {
1308 return ret;
1309 }
1310
1311 curSurface->CleanCache(true); // make sure old surface is empty and go black
1312 return AVCS_ERR_OK;
1313 }
1314
RenderNewSurfaceWithOldBuffer(const sptr<Surface> & newSurface,uint32_t index)1315 int32_t FCodec::RenderNewSurfaceWithOldBuffer(const sptr<Surface> &newSurface, uint32_t index)
1316 {
1317 std::shared_ptr<FSurfaceMemory> surfaceMemory = buffers_[INDEX_OUTPUT][index]->sMemory_;
1318 sptr<SurfaceBuffer> surfaceBuffer = renderSurfaceBufferMap_[index].first;
1319 OHOS::BufferFlushConfig flushConfig = renderSurfaceBufferMap_[index].second;
1320 surfaceMemory->SetNeedRender(true);
1321 newSurface->SetScalingMode(surfaceBuffer->GetSeqNum(), sInfo_.scalingMode);
1322 auto res = newSurface->FlushBuffer(surfaceBuffer, -1, flushConfig);
1323 if (res != OHOS::SurfaceError::SURFACE_ERROR_OK) {
1324 AVCODEC_LOGE("Failed to update surface memory: %{public}d", res);
1325 surfaceMemory->SetNeedRender(false);
1326 return AVCS_ERR_UNKNOWN;
1327 }
1328 return AVCS_ERR_OK;
1329 }
1330
RequestBufferFromConsumer()1331 void FCodec::RequestBufferFromConsumer()
1332 {
1333 auto index = renderAvailQue_->Front();
1334 std::shared_ptr<FBuffer> outputBuffer = buffers_[INDEX_OUTPUT][index];
1335 std::shared_ptr<FSurfaceMemory> surfaceMemory = outputBuffer->sMemory_;
1336 sptr<SurfaceBuffer> surfaceBuffer = surfaceMemory->GetSurfaceBuffer();
1337 if (surfaceBuffer == nullptr) {
1338 AVCODEC_LOGE("get buffer failed.");
1339 return;
1340 }
1341 auto queSize = renderAvailQue_->Size();
1342 uint32_t curIndex = 0;
1343 uint32_t i = 0;
1344 for (i = 0; i < queSize; i++) {
1345 curIndex = renderAvailQue_->Pop();
1346 if (surfaceMemory->GetBase() == buffers_[INDEX_OUTPUT][curIndex]->avBuffer_->memory_->GetAddr() &&
1347 surfaceMemory->GetSize() == buffers_[INDEX_OUTPUT][curIndex]->avBuffer_->memory_->GetCapacity()) {
1348 buffers_[INDEX_OUTPUT][index]->sMemory_ = buffers_[INDEX_OUTPUT][curIndex]->sMemory_;
1349 buffers_[INDEX_OUTPUT][curIndex]->sMemory_ = surfaceMemory;
1350 break;
1351 } else {
1352 renderAvailQue_->Push(curIndex);
1353 }
1354 }
1355 if (i == queSize) {
1356 curIndex = index;
1357 outputBuffer->avBuffer_ = AVBuffer::CreateAVBuffer(surfaceMemory->GetBase(), surfaceMemory->GetSize());
1358 outputBuffer->width_ = width_;
1359 outputBuffer->height_ = height_;
1360 FindAvailIndex(curIndex);
1361 }
1362 buffers_[INDEX_OUTPUT][curIndex]->owner_ = FBuffer::Owner::OWNED_BY_CODEC;
1363 codecAvailQue_->Push(curIndex);
1364 if (renderSurfaceBufferMap_.count(curIndex)) {
1365 renderSurfaceBufferMap_.erase(curIndex);
1366 }
1367 AVCODEC_LOGD("Request output buffer success, index = %{public}u, queSize=%{public}zu, i=%{public}d", curIndex,
1368 queSize, i);
1369 }
1370
BufferReleasedByConsumer(uint64_t surfaceId)1371 GSError FCodec::BufferReleasedByConsumer(uint64_t surfaceId)
1372 {
1373 CHECK_AND_RETURN_RET_LOG(state_ == State::RUNNING || state_ == State::EOS, GSERROR_NO_PERMISSION, "In valid state");
1374 std::lock_guard<std::mutex> sLock(surfaceMutex_);
1375 CHECK_AND_RETURN_RET_LOG(renderAvailQue_->Size() > 0, GSERROR_NO_BUFFER, "No available buffer");
1376 CHECK_AND_RETURN_RET_LOG(surfaceId == sInfo_.surface->GetUniqueId(), GSERROR_INVALID_ARGUMENTS,
1377 "Ignore callback from old surface");
1378 RequestBufferFromConsumer();
1379 return GSERROR_OK;
1380 }
1381
UnRegisterListenerToSurface(const sptr<Surface> & surface)1382 int32_t FCodec::UnRegisterListenerToSurface(const sptr<Surface> &surface)
1383 {
1384 GSError err = surface->UnRegisterReleaseListener();
1385 CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, AVCS_ERR_UNKNOWN,
1386 "surface %{public}" PRIu64 ", UnRegisterReleaseListener failed, GSError=%{public}d",
1387 surface->GetUniqueId(), err);
1388 return AVCS_ERR_OK;
1389 }
1390
RegisterListenerToSurface(const sptr<Surface> & surface)1391 GSError FCodec::RegisterListenerToSurface(const sptr<Surface> &surface)
1392 {
1393 uint64_t surfaceId = surface->GetUniqueId();
1394 wptr<FCodec> wp = this;
1395 GSError err = surface->RegisterReleaseListener([wp, surfaceId](sptr<SurfaceBuffer> &) {
1396 sptr<FCodec> codec = wp.promote();
1397 if (!codec) {
1398 AVCODEC_LOGD("decoder is gone");
1399 return GSERROR_OK;
1400 }
1401 return codec->BufferReleasedByConsumer(surfaceId);
1402 });
1403 return err;
1404 }
1405
SetOutputSurface(sptr<Surface> surface)1406 int32_t FCodec::SetOutputSurface(sptr<Surface> surface)
1407 {
1408 AVCODEC_SYNC_TRACE;
1409 CHECK_AND_RETURN_RET_LOG(state_ != State::UNINITIALIZED, AV_ERR_INVALID_VAL,
1410 "set output surface fail: not initialized or configured");
1411 CHECK_AND_RETURN_RET_LOG((state_ == State::CONFIGURED || state_ == State::FLUSHED ||
1412 state_ == State::RUNNING || state_ == State::EOS), AVCS_ERR_INVALID_STATE,
1413 "set output surface fail: state %{public}d not support set output surface",
1414 static_cast<int32_t>(state_.load()));
1415 if (surface == nullptr || surface->IsConsumer()) {
1416 AVCODEC_LOGE("Set surface fail");
1417 return AVCS_ERR_INVALID_VAL;
1418 }
1419 if (state_ == State::FLUSHED || state_ == State::RUNNING || state_ == State::EOS) {
1420 return ReplaceOutputSurfaceWhenRunning(surface);
1421 }
1422 sInfo_.surface = surface;
1423 GSError err = RegisterListenerToSurface(sInfo_.surface);
1424 CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, AVCS_ERR_UNKNOWN,
1425 "surface %{public}" PRIu64 ", RegisterListenerToSurface failed, GSError=%{public}d",
1426 sInfo_.surface->GetUniqueId(), err);
1427 if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_SCALE_TYPE)) {
1428 std::lock_guard<std::mutex> lock(formatMutex_);
1429 format_.PutIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE,
1430 static_cast<int32_t>(ScalingMode::SCALING_MODE_SCALE_TO_WINDOW));
1431 }
1432 if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE)) {
1433 std::lock_guard<std::mutex> lock(formatMutex_);
1434 format_.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE,
1435 static_cast<int32_t>(VideoRotation::VIDEO_ROTATION_0));
1436 }
1437 AVCODEC_LOGI("Set surface success");
1438 return AVCS_ERR_OK;
1439 }
1440
SetCallback(const std::shared_ptr<MediaCodecCallback> & callback)1441 int32_t FCodec::SetCallback(const std::shared_ptr<MediaCodecCallback> &callback)
1442 {
1443 AVCODEC_SYNC_TRACE;
1444 CHECK_AND_RETURN_RET_LOG(callback != nullptr, AVCS_ERR_INVALID_VAL, "Set callback failed: callback is NULL");
1445 callback_ = callback;
1446 return AVCS_ERR_OK;
1447 }
1448
GetCodecCapability(std::vector<CapabilityData> & capaArray)1449 int32_t FCodec::GetCodecCapability(std::vector<CapabilityData> &capaArray)
1450 {
1451 for (uint32_t i = 0; i < SUPPORT_VCODEC_NUM; ++i) {
1452 CapabilityData capsData;
1453 capsData.codecName = static_cast<std::string>(SUPPORT_VCODEC[i].codecName);
1454 capsData.mimeType = static_cast<std::string>(SUPPORT_VCODEC[i].mimeType);
1455 capsData.codecType = SUPPORT_VCODEC[i].isEncoder ? AVCODEC_TYPE_VIDEO_ENCODER : AVCODEC_TYPE_VIDEO_DECODER;
1456 capsData.isVendor = false;
1457 capsData.maxInstance = VIDEO_INSTANCE_SIZE;
1458 capsData.alignment.width = VIDEO_ALIGNMENT_SIZE;
1459 capsData.alignment.height = VIDEO_ALIGNMENT_SIZE;
1460 capsData.width.minVal = VIDEO_MIN_SIZE;
1461 capsData.width.maxVal = VIDEO_MAX_WIDTH_SIZE;
1462 capsData.height.minVal = VIDEO_MIN_SIZE;
1463 capsData.height.maxVal = VIDEO_MAX_HEIGHT_SIZE;
1464 capsData.frameRate.minVal = 0;
1465 capsData.frameRate.maxVal = VIDEO_FRAMERATE_MAX_SIZE;
1466 capsData.bitrate.minVal = 1;
1467 capsData.bitrate.maxVal = VIDEO_BITRATE_MAX_SIZE;
1468 capsData.blockPerFrame.minVal = 1;
1469 capsData.blockPerFrame.maxVal = VIDEO_BLOCKPERFRAME_SIZE;
1470 capsData.blockPerSecond.minVal = 1;
1471 capsData.blockPerSecond.maxVal = VIDEO_BLOCKPERSEC_SIZE;
1472 capsData.blockSize.width = VIDEO_ALIGN_SIZE;
1473 capsData.blockSize.height = VIDEO_ALIGN_SIZE;
1474 if (SUPPORT_VCODEC[i].isEncoder) {
1475 capsData.complexity.minVal = 0;
1476 capsData.complexity.maxVal = 0;
1477 capsData.encodeQuality.minVal = 0;
1478 capsData.encodeQuality.maxVal = 0;
1479 }
1480 capsData.pixFormat = {
1481 static_cast<int32_t>(VideoPixelFormat::YUVI420), static_cast<int32_t>(VideoPixelFormat::NV12),
1482 static_cast<int32_t>(VideoPixelFormat::NV21), static_cast<int32_t>(VideoPixelFormat::RGBA)};
1483 capsData.profiles = {static_cast<int32_t>(AVC_PROFILE_BASELINE), static_cast<int32_t>(AVC_PROFILE_MAIN),
1484 static_cast<int32_t>(AVC_PROFILE_HIGH)};
1485 std::vector<int32_t> levels;
1486 for (int32_t j = 0; j <= static_cast<int32_t>(AVCLevel::AVC_LEVEL_51); ++j) {
1487 levels.emplace_back(j);
1488 }
1489 capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(AVC_PROFILE_MAIN), levels));
1490 capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(AVC_PROFILE_HIGH), levels));
1491 capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(AVC_PROFILE_BASELINE), levels));
1492 capaArray.emplace_back(capsData);
1493 }
1494 return AVCS_ERR_OK;
1495 }
1496 } // namespace Codec
1497 } // namespace MediaAVCodec
1498 } // namespace OHOS
1499