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 ResetBuffers();
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 sInfo_.surface->CleanCache();
506 AVCODEC_LOGI("surface cleancache success");
507 int ret = UnRegisterListenerToSurface(sInfo_.surface);
508 if (ret != 0) {
509 callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN);
510 state_ = State::ERROR;
511 }
512 }
513 sInfo_.surface = nullptr;
514 }
515
Release()516 int32_t FCodec::Release()
517 {
518 AVCODEC_SYNC_TRACE;
519 state_ = State::STOPPING;
520 AVCODEC_LOGI("step into STOPPING status");
521 ReleaseResource();
522 state_ = State::UNINITIALIZED;
523 AVCODEC_LOGI("Release codec successful, state: Uninitialized");
524 return AVCS_ERR_OK;
525 }
526
SetSurfaceParameter(const Format &format, const std::string_view &formatKey, FormatDataType formatType)527 void FCodec::SetSurfaceParameter(const Format &format, const std::string_view &formatKey, FormatDataType formatType)
528 {
529 CHECK_AND_RETURN_LOG(formatType == FORMAT_TYPE_INT32, "Set parameter failed: type should be int32");
530 int32_t val = 0;
531 CHECK_AND_RETURN_LOG(format.GetIntValue(formatKey, val), "Set parameter failed: get value fail");
532 if (formatKey == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT) {
533 VideoPixelFormat vpf = static_cast<VideoPixelFormat>(val);
534 CHECK_AND_RETURN_LOG(vpf == VideoPixelFormat::RGBA || vpf == VideoPixelFormat::YUVI420 ||
535 vpf == VideoPixelFormat::NV12 || vpf == VideoPixelFormat::NV21,
536 "Set parameter failed: pixel format value %{public}d invalid", val);
537 outputPixelFmt_ = vpf;
538 {
539 std::lock_guard<std::mutex> lock(formatMutex_);
540 format_.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, val);
541 }
542 GraphicPixelFormat surfacePixelFmt = TranslateSurfaceFormat(vpf);
543 std::lock_guard<std::mutex> sLock(surfaceMutex_);
544 sInfo_.requestConfig.format = surfacePixelFmt;
545 } else if (formatKey == MediaDescriptionKey::MD_KEY_ROTATION_ANGLE) {
546 VideoRotation sr = static_cast<VideoRotation>(val);
547 CHECK_AND_RETURN_LOG(sr == VideoRotation::VIDEO_ROTATION_0 || sr == VideoRotation::VIDEO_ROTATION_90 ||
548 sr == VideoRotation::VIDEO_ROTATION_180 || sr == VideoRotation::VIDEO_ROTATION_270,
549 "Set parameter failed: rotation angle value %{public}d invalid", val);
550 {
551 std::lock_guard<std::mutex> lock(formatMutex_);
552 format_.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, val);
553 }
554 std::lock_guard<std::mutex> sLock(surfaceMutex_);
555 sInfo_.surface->SetTransform(TranslateSurfaceRotation(sr));
556 } else if (formatKey == MediaDescriptionKey::MD_KEY_SCALE_TYPE) {
557 ScalingMode scaleMode = static_cast<ScalingMode>(val);
558 CHECK_AND_RETURN_LOG(scaleMode == ScalingMode::SCALING_MODE_SCALE_TO_WINDOW ||
559 scaleMode == ScalingMode::SCALING_MODE_SCALE_CROP,
560 "Set parameter failed: scale type value %{public}d invalid", val);
561 {
562 std::lock_guard<std::mutex> lock(formatMutex_);
563 format_.PutIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE, val);
564 }
565 std::lock_guard<std::mutex> sLock(surfaceMutex_);
566 sInfo_.scalingMode = scaleMode;
567 } else {
568 AVCODEC_LOGW("Set parameter failed: %{public}s", std::string(formatKey).c_str());
569 return;
570 }
571 AVCODEC_LOGI("Set parameter %{public}s success, val %{public}d", std::string(formatKey).c_str(), val);
572 }
573
SetParameter(const Format &format)574 int32_t FCodec::SetParameter(const Format &format)
575 {
576 AVCODEC_SYNC_TRACE;
577 for (auto &it : format.GetFormatMap()) {
578 if (sInfo_.surface != nullptr && it.second.type == FORMAT_TYPE_INT32) {
579 if (it.first == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT ||
580 it.first == MediaDescriptionKey::MD_KEY_ROTATION_ANGLE ||
581 it.first == MediaDescriptionKey::MD_KEY_SCALE_TYPE) {
582 SetSurfaceParameter(format, it.first, it.second.type);
583 }
584 } else {
585 AVCODEC_LOGW("Current Version, %{public}s is not supported", it.first.data());
586 }
587 }
588 AVCODEC_LOGI("Set parameter successful");
589 return AVCS_ERR_OK;
590 }
591
GetOutputFormat(Format &format)592 int32_t FCodec::GetOutputFormat(Format &format)
593 {
594 AVCODEC_SYNC_TRACE;
595 if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_BITRATE)) {
596 if (avCodecContext_ != nullptr) {
597 format_.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, avCodecContext_->bit_rate);
598 }
599 }
600 if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_FRAME_RATE)) {
601 if (avCodecContext_ != nullptr && avCodecContext_->framerate.den > 0) {
602 double value = static_cast<double>(avCodecContext_->framerate.num) /
603 static_cast<double>(avCodecContext_->framerate.den);
604 format_.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, value);
605 }
606 }
607 if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_MAX_INPUT_SIZE)) {
608 int32_t stride = AlignUp(width_, VIDEO_ALIGN_SIZE);
609 int32_t maxInputSize = static_cast<int32_t>((stride * height_ * VIDEO_PIX_DEPTH_YUV) / UV_SCALE_FACTOR);
610 format_.PutIntValue(MediaDescriptionKey::MD_KEY_MAX_INPUT_SIZE, maxInputSize);
611 }
612 {
613 std::lock_guard<std::mutex> lock(formatMutex_);
614 format = format_;
615 }
616 AVCODEC_LOGI("Get outputFormat successful");
617 return AVCS_ERR_OK;
618 }
619
CalculateBufferSize()620 void FCodec::CalculateBufferSize()
621 {
622 int32_t stride = AlignUp(width_, VIDEO_ALIGN_SIZE);
623 outputBufferSize_ = static_cast<int32_t>((stride * height_ * VIDEO_PIX_DEPTH_YUV) / UV_SCALE_FACTOR);
624 inputBufferSize_ = std::max(VIDEO_MIN_BUFFER_SIZE, outputBufferSize_);
625 if (outputPixelFmt_ == VideoPixelFormat::RGBA) {
626 outputBufferSize_ = static_cast<int32_t>(stride * height_ * VIDEO_PIX_DEPTH_RGBA);
627 }
628 AVCODEC_LOGI("width = %{public}d, height = %{public}d, stride = %{public}d, Input buffer size = %{public}d, output "
629 "buffer size=%{public}d",
630 width_, height_, stride, inputBufferSize_, outputBufferSize_);
631 }
632
AllocateInputBuffer(int32_t bufferCnt, int32_t inBufferSize)633 int32_t FCodec::AllocateInputBuffer(int32_t bufferCnt, int32_t inBufferSize)
634 {
635 int32_t valBufferCnt = 0;
636 for (int32_t i = 0; i < bufferCnt; i++) {
637 std::shared_ptr<FBuffer> buf = std::make_shared<FBuffer>();
638 std::shared_ptr<AVAllocator> allocator =
639 AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
640 CHECK_AND_CONTINUE_LOG(allocator != nullptr, "input buffer %{public}d allocator is nullptr", i);
641 buf->avBuffer_ = AVBuffer::CreateAVBuffer(allocator, inBufferSize);
642 CHECK_AND_CONTINUE_LOG(buf->avBuffer_ != nullptr, "Allocate input buffer failed, index=%{public}d", i);
643 AVCODEC_LOGI("Allocate input buffer success: index=%{public}d, size=%{public}d", i,
644 buf->avBuffer_->memory_->GetCapacity());
645 buffers_[INDEX_INPUT].emplace_back(buf);
646 valBufferCnt++;
647 }
648 if (valBufferCnt < DEFAULT_MIN_BUFFER_CNT) {
649 AVCODEC_LOGE("Allocate input buffer failed: only %{public}d buffer is allocated, no memory", valBufferCnt);
650 buffers_[INDEX_INPUT].clear();
651 return AVCS_ERR_NO_MEMORY;
652 }
653 return AVCS_ERR_OK;
654 }
655
SetSurfaceCfg(int32_t bufferCnt)656 int32_t FCodec::SetSurfaceCfg(int32_t bufferCnt)
657 {
658 CHECK_AND_RETURN_RET_LOG(sInfo_.surface->SetQueueSize(bufferCnt) == OHOS::SurfaceError::SURFACE_ERROR_OK,
659 AVCS_ERR_NO_MEMORY, "Surface set QueueSize=%{public}d failed", bufferCnt);
660 if (outputPixelFmt_ == VideoPixelFormat::UNKNOWN) {
661 format_.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, static_cast<int32_t>(VideoPixelFormat::NV12));
662 }
663 int32_t val32 = 0;
664 format_.GetIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, val32);
665 GraphicPixelFormat surfacePixelFmt = TranslateSurfaceFormat(static_cast<VideoPixelFormat>(val32));
666 CHECK_AND_RETURN_RET_LOG(surfacePixelFmt != GraphicPixelFormat::GRAPHIC_PIXEL_FMT_BUTT, AVCS_ERR_UNSUPPORT,
667 "Failed to allocate output buffer: unsupported surface format");
668 sInfo_.requestConfig.width = width_;
669 sInfo_.requestConfig.height = height_;
670 sInfo_.requestConfig.format = surfacePixelFmt;
671
672 format_.GetIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE, val32);
673 sInfo_.scalingMode = static_cast<ScalingMode>(val32);
674 format_.GetIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, val32);
675 sInfo_.surface->SetTransform(TranslateSurfaceRotation(static_cast<VideoRotation>(val32)));
676 return AVCS_ERR_OK;
677 }
678
AllocateOutputBuffer(int32_t bufferCnt, int32_t outBufferSize)679 int32_t FCodec::AllocateOutputBuffer(int32_t bufferCnt, int32_t outBufferSize)
680 {
681 int32_t valBufferCnt = 0;
682 if (sInfo_.surface) {
683 CHECK_AND_RETURN_RET_LOG(SetSurfaceCfg(bufferCnt) == AVCS_ERR_OK, AVCS_ERR_UNKNOWN, "SetSurfaceCfg failed");
684 }
685 for (int i = 0; i < bufferCnt; i++) {
686 std::shared_ptr<FBuffer> buf = std::make_shared<FBuffer>();
687 if (sInfo_.surface == nullptr) {
688 std::shared_ptr<AVAllocator> allocator =
689 AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
690 CHECK_AND_CONTINUE_LOG(allocator != nullptr, "output buffer %{public}d allocator is nullptr", i);
691 buf->avBuffer_ = AVBuffer::CreateAVBuffer(allocator, outBufferSize);
692 AVCODEC_LOGI("Allocate output share buffer success: index=%{public}d, size=%{public}d", i,
693 buf->avBuffer_->memory_->GetCapacity());
694 } else {
695 buf->sMemory_ = std::make_shared<FSurfaceMemory>(&sInfo_);
696 CHECK_AND_CONTINUE_LOG(buf->sMemory_->GetSurfaceBuffer() != nullptr,
697 "output surface memory %{public}d create fail", i);
698 outAVBuffer4Surface_.emplace_back(AVBuffer::CreateAVBuffer());
699 buf->avBuffer_ = AVBuffer::CreateAVBuffer(buf->sMemory_->GetBase(), buf->sMemory_->GetSize());
700 AVCODEC_LOGI("Allocate output surface buffer success: index=%{public}d, size=%{public}d, "
701 "stride=%{public}d",
702 i, buf->sMemory_->GetSize(), buf->sMemory_->GetSurfaceBufferStride());
703 }
704 CHECK_AND_CONTINUE_LOG(buf->avBuffer_ != nullptr, "Allocate output buffer failed, index=%{public}d", i);
705
706 buf->width_ = width_;
707 buf->height_ = height_;
708 buffers_[INDEX_OUTPUT].emplace_back(buf);
709 valBufferCnt++;
710 }
711 if (valBufferCnt < DEFAULT_MIN_BUFFER_CNT) {
712 AVCODEC_LOGE("Allocate output buffer failed: only %{public}d buffer is allocated, no memory", valBufferCnt);
713 buffers_[INDEX_INPUT].clear();
714 buffers_[INDEX_OUTPUT].clear();
715 return AVCS_ERR_NO_MEMORY;
716 }
717 return AVCS_ERR_OK;
718 }
719
AllocateBuffers()720 int32_t FCodec::AllocateBuffers()
721 {
722 AVCODEC_SYNC_TRACE;
723 CalculateBufferSize();
724 CHECK_AND_RETURN_RET_LOG(inputBufferSize_ > 0 && outputBufferSize_ > 0, AVCS_ERR_INVALID_VAL,
725 "Allocate buffer with input size=%{public}d, output size=%{public}d failed",
726 inputBufferSize_, outputBufferSize_);
727 if (sInfo_.surface != nullptr && isOutBufSetted_ == false) {
728 format_.PutIntValue(MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, DEFAULT_OUT_SURFACE_CNT);
729 }
730 int32_t inputBufferCnt = 0;
731 int32_t outputBufferCnt = 0;
732 format_.GetIntValue(MediaDescriptionKey::MD_KEY_MAX_INPUT_BUFFER_COUNT, inputBufferCnt);
733 format_.GetIntValue(MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, outputBufferCnt);
734 inputAvailQue_ = std::make_shared<BlockQueue<uint32_t>>("inputAvailQue", inputBufferCnt);
735 codecAvailQue_ = std::make_shared<BlockQueue<uint32_t>>("codecAvailQue", outputBufferCnt);
736 if (sInfo_.surface != nullptr) {
737 renderAvailQue_ = std::make_shared<BlockQueue<uint32_t>>("renderAvailQue", outputBufferCnt);
738 }
739 if (AllocateInputBuffer(inputBufferCnt, inputBufferSize_) == AVCS_ERR_NO_MEMORY ||
740 AllocateOutputBuffer(outputBufferCnt, outputBufferSize_) == AVCS_ERR_NO_MEMORY) {
741 return AVCS_ERR_NO_MEMORY;
742 }
743 AVCODEC_LOGI("Allocate buffers successful");
744 return AVCS_ERR_OK;
745 }
746
UpdateBuffers(uint32_t index, int32_t bufferSize, uint32_t bufferType)747 int32_t FCodec::UpdateBuffers(uint32_t index, int32_t bufferSize, uint32_t bufferType)
748 {
749 int32_t curBufSize = buffers_[bufferType][index]->avBuffer_->memory_->GetCapacity();
750 if (bufferSize != curBufSize) {
751 std::shared_ptr<FBuffer> buf = std::make_shared<FBuffer>();
752 std::shared_ptr<AVAllocator> allocator =
753 AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
754 CHECK_AND_RETURN_RET_LOG(allocator != nullptr, AVCS_ERR_NO_MEMORY, "buffer %{public}d allocator is nullptr",
755 index);
756 buf->avBuffer_ = AVBuffer::CreateAVBuffer(allocator, bufferSize);
757 CHECK_AND_RETURN_RET_LOG(buf->avBuffer_ != nullptr, AVCS_ERR_NO_MEMORY,
758 "Buffer allocate failed, index=%{public}d", index);
759 AVCODEC_LOGI("update share buffer success: bufferType=%{public}u, index=%{public}d, size=%{public}d",
760 bufferType, index, buf->avBuffer_->memory_->GetCapacity());
761
762 if (bufferType == INDEX_INPUT) {
763 buf->owner_ = FBuffer::Owner::OWNED_BY_USER;
764 } else {
765 buf->owner_ = FBuffer::Owner::OWNED_BY_CODEC;
766 }
767 buffers_[bufferType][index] = buf;
768 }
769 return AVCS_ERR_OK;
770 }
771
UpdateSurfaceMemory(uint32_t index)772 int32_t FCodec::UpdateSurfaceMemory(uint32_t index)
773 {
774 AVCODEC_SYNC_TRACE;
775 std::unique_lock<std::mutex> oLock(outputMutex_);
776 std::shared_ptr<FBuffer> outputBuffer = buffers_[INDEX_OUTPUT][index];
777 oLock.unlock();
778 if (width_ != outputBuffer->width_ || height_ != outputBuffer->height_) {
779 std::shared_ptr<FSurfaceMemory> surfaceMemory = outputBuffer->sMemory_;
780 surfaceMemory->SetNeedRender(false);
781 surfaceMemory->ReleaseSurfaceBuffer();
782 while (state_ == State::RUNNING) {
783 std::unique_lock<std::mutex> sLock(surfaceMutex_);
784 sptr<SurfaceBuffer> surfaceBuffer = surfaceMemory->GetSurfaceBuffer();
785 sLock.unlock();
786 if (surfaceBuffer != nullptr) {
787 break;
788 }
789 std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TRY_REQ_TIME));
790 }
791
792 outputBuffer->avBuffer_ =
793 AVBuffer::CreateAVBuffer(outputBuffer->sMemory_->GetBase(), outputBuffer->sMemory_->GetSize());
794 outputBuffer->width_ = width_;
795 outputBuffer->height_ = height_;
796 }
797
798 return AVCS_ERR_OK;
799 }
800
CheckFormatChange(uint32_t index, int width, int height)801 int32_t FCodec::CheckFormatChange(uint32_t index, int width, int height)
802 {
803 if (width_ != width || height_ != height) {
804 AVCODEC_LOGI("format change, width: %{public}d->%{public}d, height: %{public}d->%{public}d", width_, width,
805 height_, height);
806 width_ = width;
807 height_ = height;
808 ResetData();
809 scale_ = nullptr;
810 CalculateBufferSize();
811 {
812 std::lock_guard<std::mutex> lock(formatMutex_);
813 format_.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width_);
814 format_.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height_);
815 format_.PutIntValue(OHOS::Media::Tag::VIDEO_STRIDE,
816 outputPixelFmt_ == VideoPixelFormat::RGBA ? width_ * VIDEO_PIX_DEPTH_RGBA : width_);
817 format_.PutIntValue(OHOS::Media::Tag::VIDEO_SLICE_HEIGHT, height_);
818 format_.PutIntValue(OHOS::Media::Tag::VIDEO_PIC_WIDTH, width_);
819 format_.PutIntValue(OHOS::Media::Tag::VIDEO_PIC_HEIGHT, height_);
820 }
821 if (sInfo_.surface) {
822 std::lock_guard<std::mutex> sLock(surfaceMutex_);
823 sInfo_.requestConfig.width = width_;
824 sInfo_.requestConfig.height = height_;
825 }
826 callback_->OnOutputFormatChanged(format_);
827 }
828 if (sInfo_.surface == nullptr) {
829 std::lock_guard<std::mutex> oLock(outputMutex_);
830 CHECK_AND_RETURN_RET_LOG((UpdateBuffers(index, outputBufferSize_, INDEX_OUTPUT) == AVCS_ERR_OK),
831 AVCS_ERR_NO_MEMORY, "Update output buffer failed, index=%{public}u", index);
832 } else {
833 CHECK_AND_RETURN_RET_LOG((UpdateSurfaceMemory(index) == AVCS_ERR_OK), AVCS_ERR_NO_MEMORY,
834 "Update buffer failed");
835 }
836 return AVCS_ERR_OK;
837 }
838
ReleaseBuffers()839 void FCodec::ReleaseBuffers()
840 {
841 ResetData();
842 if (!isBufferAllocated_) {
843 return;
844 }
845
846 inputAvailQue_->Clear();
847 std::unique_lock<std::mutex> iLock(inputMutex_);
848 buffers_[INDEX_INPUT].clear();
849 synIndex_ = std::nullopt;
850 iLock.unlock();
851
852 std::unique_lock<std::mutex> oLock(outputMutex_);
853 codecAvailQue_->Clear();
854 if (sInfo_.surface != nullptr) {
855 renderAvailQue_->Clear();
856 renderSurfaceBufferMap_.clear();
857 for (uint32_t i = 0; i < buffers_[INDEX_OUTPUT].size(); i++) {
858 std::shared_ptr<FBuffer> outputBuffer = buffers_[INDEX_OUTPUT][i];
859 if (outputBuffer->owner_ == FBuffer::Owner::OWNED_BY_CODEC) {
860 std::shared_ptr<FSurfaceMemory> surfaceMemory = outputBuffer->sMemory_;
861 surfaceMemory->SetNeedRender(false);
862 surfaceMemory->ReleaseSurfaceBuffer();
863 outputBuffer->owner_ = FBuffer::Owner::OWNED_BY_SURFACE;
864 }
865 }
866 }
867 buffers_[INDEX_OUTPUT].clear();
868 outAVBuffer4Surface_.clear();
869 oLock.unlock();
870 isBufferAllocated_ = false;
871 }
872
QueueInputBuffer(uint32_t index)873 int32_t FCodec::QueueInputBuffer(uint32_t index)
874 {
875 AVCODEC_SYNC_TRACE;
876 CHECK_AND_RETURN_RET_LOG(state_ == State::RUNNING, AVCS_ERR_INVALID_STATE,
877 "Queue input buffer failed: not in Running state");
878 CHECK_AND_RETURN_RET_LOG(index < buffers_[INDEX_INPUT].size(), AVCS_ERR_INVALID_VAL,
879 "Queue input buffer failed with bad index, index=%{public}u, buffer_size=%{public}zu",
880 index, buffers_[INDEX_INPUT].size());
881 std::shared_ptr<FBuffer> inputBuffer = buffers_[INDEX_INPUT][index];
882 CHECK_AND_RETURN_RET_LOG(inputBuffer->owner_ == FBuffer::Owner::OWNED_BY_USER, AVCS_ERR_INVALID_OPERATION,
883 "Queue input buffer failed: buffer with index=%{public}u is not available", index);
884
885 inputBuffer->owner_ = FBuffer::Owner::OWNED_BY_CODEC;
886 std::shared_ptr<AVBuffer> &inputAVBuffer = inputBuffer->avBuffer_;
887 if (synIndex_) {
888 const std::shared_ptr<AVBuffer> &curAVBuffer = buffers_[INDEX_INPUT][synIndex_.value()]->avBuffer_;
889 int32_t curAVBufferSize = curAVBuffer->memory_->GetSize();
890 int32_t inputAVBufferSize = inputAVBuffer->memory_->GetSize();
891 if ((curAVBufferSize + inputAVBufferSize <= curAVBuffer->memory_->GetCapacity()) &&
892 memcpy_s(curAVBuffer->memory_->GetAddr() + curAVBufferSize, inputAVBufferSize,
893 inputAVBuffer->memory_->GetAddr(), inputAVBufferSize) == EOK) {
894 curAVBuffer->memory_->SetSize(curAVBufferSize + inputAVBufferSize);
895 curAVBuffer->flag_ = inputAVBuffer->flag_;
896 curAVBuffer->pts_ = inputAVBuffer->pts_;
897
898 if (inputAVBuffer->flag_ != AVCODEC_BUFFER_FLAG_CODEC_DATA &&
899 inputAVBuffer->flag_ != AVCODEC_BUFFER_FLAG_PARTIAL_FRAME) {
900 inputAvailQue_->Push(synIndex_.value());
901 synIndex_ = std::nullopt;
902 }
903 inputBuffer->owner_ = FBuffer::Owner::OWNED_BY_USER;
904 callback_->OnInputBufferAvailable(index, inputAVBuffer);
905 return AVCS_ERR_OK;
906 } else {
907 AVCODEC_LOGE("packet size %{public}d over buffer size %{public}d", curAVBufferSize + inputAVBufferSize,
908 curAVBuffer->memory_->GetCapacity());
909 callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_NO_MEMORY);
910 state_ = State::ERROR;
911 return AVCS_ERR_NO_MEMORY;
912 }
913 } else {
914 if ((inputAVBuffer->flag_ == AVCODEC_BUFFER_FLAG_CODEC_DATA) ||
915 (inputAVBuffer->flag_ == AVCODEC_BUFFER_FLAG_PARTIAL_FRAME)) {
916 synIndex_ = index;
917 } else {
918 inputAvailQue_->Push(index);
919 }
920 }
921
922 return AVCS_ERR_OK;
923 }
924
SendFrame()925 void FCodec::SendFrame()
926 {
927 CHECK_AND_RETURN_LOG(state_ != State::STOPPING && state_ != State::FLUSHING, "Invalid state");
928 if (state_ != State::RUNNING || isSendEos_) {
929 std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TRY_DECODE_TIME));
930 return;
931 }
932 uint32_t index = inputAvailQue_->Front();
933 CHECK_AND_RETURN_LOG(state_ == State::RUNNING, "Not in running state");
934 std::shared_ptr<FBuffer> &inputBuffer = buffers_[INDEX_INPUT][index];
935 std::shared_ptr<AVBuffer> &inputAVBuffer = inputBuffer->avBuffer_;
936 if (inputAVBuffer->flag_ & AVCODEC_BUFFER_FLAG_EOS) {
937 avPacket_->data = nullptr;
938 avPacket_->size = 0;
939 avPacket_->pts = 0;
940 std::unique_lock<std::mutex> sendLock(sendMutex_);
941 isSendEos_ = true;
942 sendCv_.wait_for(sendLock, std::chrono::milliseconds(DEFAULT_DECODE_WAIT_TIME));
943 AVCODEC_LOGI("Send eos end");
944 } else {
945 avPacket_->data = inputAVBuffer->memory_->GetAddr();
946 avPacket_->size = static_cast<int32_t>(inputAVBuffer->memory_->GetSize());
947 avPacket_->pts = inputAVBuffer->pts_;
948 }
949 std::unique_lock<std::mutex> sLock(syncMutex_);
950 int ret = avcodec_send_packet(avCodecContext_.get(), avPacket_.get());
951 sLock.unlock();
952 if (ret == 0 || ret == AVERROR_INVALIDDATA) {
953 EXPECT_AND_LOGW(ret == AVERROR_INVALIDDATA, "ffmpeg ret = %{public}s", AVStrError(ret).c_str());
954 std::unique_lock<std::mutex> recvLock(recvMutex_);
955 recvCv_.notify_one();
956 recvLock.unlock();
957 inputAvailQue_->Pop();
958 inputBuffer->owner_ = FBuffer::Owner::OWNED_BY_USER;
959 #ifdef BUILD_ENG_VERSION
960 if (dumpInFile_ && dumpInFile_->is_open()) {
961 dumpInFile_->write(reinterpret_cast<char *>(inputAVBuffer->memory_->GetAddr()),
962 static_cast<int32_t>(inputAVBuffer->memory_->GetSize()));
963 }
964 #endif // BUILD_ENG_VERSION
965 callback_->OnInputBufferAvailable(index, inputAVBuffer);
966 } else if (ret == AVERROR(EAGAIN)) {
967 std::unique_lock<std::mutex> sendLock(sendMutex_);
968 isSendWait_ = true;
969 sendCv_.wait_for(sendLock, std::chrono::milliseconds(DEFAULT_DECODE_WAIT_TIME));
970 } else {
971 AVCODEC_LOGE("Cannot send frame to codec: ffmpeg ret = %{public}s", AVStrError(ret).c_str());
972 callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN);
973 state_ = State::ERROR;
974 }
975 }
976
FillFrameBuffer(const std::shared_ptr<FBuffer> &frameBuffer)977 int32_t FCodec::FillFrameBuffer(const std::shared_ptr<FBuffer> &frameBuffer)
978 {
979 VideoPixelFormat targetPixelFmt = outputPixelFmt_;
980 if (outputPixelFmt_ == VideoPixelFormat::UNKNOWN) {
981 targetPixelFmt = sInfo_.surface ? VideoPixelFormat::NV12 : ConvertPixelFormatFromFFmpeg(cachedFrame_->format);
982 }
983 AVPixelFormat ffmpegFormat = ConvertPixelFormatToFFmpeg(targetPixelFmt);
984 int32_t ret;
985 if (ffmpegFormat == static_cast<AVPixelFormat>(cachedFrame_->format)) {
986 for (int32_t i = 0; cachedFrame_->linesize[i] > 0; i++) {
987 scaleData_[i] = cachedFrame_->data[i];
988 scaleLineSize_[i] = cachedFrame_->linesize[i];
989 }
990 } else {
991 ret = ConvertVideoFrame(&scale_, cachedFrame_, scaleData_, scaleLineSize_, ffmpegFormat);
992 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Scale video frame failed: %{public}d", ret);
993 isConverted_ = true;
994 }
995 {
996 std::lock_guard<std::mutex> lock(formatMutex_);
997 format_.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, static_cast<int32_t>(targetPixelFmt));
998 }
999 std::shared_ptr<AVMemory> &bufferMemory = frameBuffer->avBuffer_->memory_;
1000 CHECK_AND_RETURN_RET_LOG(bufferMemory != nullptr, AVCS_ERR_INVALID_VAL, "bufferMemory is nullptr");
1001 bufferMemory->SetSize(0);
1002 if (sInfo_.surface) {
1003 struct SurfaceInfo surfaceInfo;
1004 surfaceInfo.surfaceStride = static_cast<uint32_t>(frameBuffer->sMemory_->GetSurfaceBufferStride());
1005 surfaceInfo.surfaceFence = frameBuffer->sMemory_->GetFence();
1006 surfaceInfo.scaleData = scaleData_;
1007 surfaceInfo.scaleLineSize = scaleLineSize_;
1008 ret = WriteSurfaceData(bufferMemory, surfaceInfo, format_);
1009 } else {
1010 ret = WriteBufferData(bufferMemory, scaleData_, scaleLineSize_, format_);
1011 }
1012 frameBuffer->avBuffer_->pts_ = cachedFrame_->pts;
1013 AVCODEC_LOGD("Fill frame buffer successful");
1014 return ret;
1015 }
1016
FramePostProcess(std::shared_ptr<FBuffer> &frameBuffer, uint32_t index, int32_t status, int ret)1017 void FCodec::FramePostProcess(std::shared_ptr<FBuffer> &frameBuffer, uint32_t index, int32_t status, int ret)
1018 {
1019 if (status == AVCS_ERR_OK) {
1020 codecAvailQue_->Pop();
1021 frameBuffer->owner_ = FBuffer::Owner::OWNED_BY_USER;
1022 if (sInfo_.surface) {
1023 outAVBuffer4Surface_[index]->pts_ = frameBuffer->avBuffer_->pts_;
1024 outAVBuffer4Surface_[index]->flag_ = frameBuffer->avBuffer_->flag_;
1025 }
1026 if (ret == AVERROR_EOF) {
1027 std::unique_lock<std::mutex> sLock(syncMutex_);
1028 avcodec_flush_buffers(avCodecContext_.get());
1029 sLock.unlock();
1030 } else {
1031 if (isSendWait_) {
1032 std::lock_guard<std::mutex> sLock(sendMutex_);
1033 isSendWait_ = false;
1034 sendCv_.notify_one();
1035 }
1036 }
1037 callback_->OnOutputBufferAvailable(index,
1038 sInfo_.surface ? outAVBuffer4Surface_[index] : frameBuffer->avBuffer_);
1039 } else if (status == AVCS_ERR_UNSUPPORT) {
1040 AVCODEC_LOGE("Recevie frame from codec failed: OnError");
1041 callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNSUPPORT);
1042 state_ = State::ERROR;
1043 } else {
1044 AVCODEC_LOGE("Recevie frame from codec failed");
1045 callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN);
1046 state_ = State::ERROR;
1047 }
1048 }
1049
DumpOutputBuffer()1050 void FCodec::DumpOutputBuffer()
1051 {
1052 AVCODEC_LOGD("cur decNum: %{public}u", decNum_);
1053 if (decNum_ == 0) {
1054 callback_->OnOutputFormatChanged(format_);
1055 }
1056 decNum_++;
1057 #ifdef BUILD_ENG_VERSION
1058 if (!dumpOutFile_ || !dumpOutFile_->is_open()) {
1059 return;
1060 }
1061 for (int32_t i = 0; i < cachedFrame_->height; i++) {
1062 dumpOutFile_->write(reinterpret_cast<char *>(cachedFrame_->data[0] + i * cachedFrame_->linesize[0]),
1063 static_cast<int32_t>(cachedFrame_->width));
1064 }
1065 for (int32_t i = 0; i < cachedFrame_->height / 2; i++) { // 2
1066 dumpOutFile_->write(reinterpret_cast<char *>(cachedFrame_->data[1] + i * cachedFrame_->linesize[1]),
1067 static_cast<int32_t>(cachedFrame_->width / 2)); // 2
1068 }
1069 for (int32_t i = 0; i < cachedFrame_->height / 2; i++) { // 2
1070 dumpOutFile_->write(reinterpret_cast<char *>(cachedFrame_->data[2] + i * cachedFrame_->linesize[2]),
1071 static_cast<int32_t>(cachedFrame_->width / 2)); // 2
1072 }
1073 #endif // BUILD_ENG_VERSION
1074 }
1075
ReceiveFrame()1076 void FCodec::ReceiveFrame()
1077 {
1078 if (state_ == State::STOPPING || state_ == State::FLUSHING) {
1079 return;
1080 } else if (state_ != State::RUNNING) {
1081 std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TRY_DECODE_TIME));
1082 return;
1083 }
1084 auto index = codecAvailQue_->Front();
1085 CHECK_AND_RETURN_LOG(state_ == State::RUNNING, "Not in running state");
1086 std::shared_ptr<FBuffer> frameBuffer = buffers_[INDEX_OUTPUT][index];
1087 std::unique_lock<std::mutex> sLock(syncMutex_);
1088 int ret = avcodec_receive_frame(avCodecContext_.get(), cachedFrame_.get());
1089 sLock.unlock();
1090 int32_t status = AVCS_ERR_OK;
1091 CHECK_AND_RETURN_LOG(ret != AVERROR_INVALIDDATA, "ffmpeg ret = %{public}s", AVStrError(ret).c_str());
1092 if (ret >= 0) {
1093 DumpOutputBuffer();
1094 if (CheckFormatChange(index, cachedFrame_->width, cachedFrame_->height) == AVCS_ERR_OK) {
1095 CHECK_AND_RETURN_LOG(state_ == State::RUNNING, "Not in running state");
1096 frameBuffer = buffers_[INDEX_OUTPUT][index];
1097 status = FillFrameBuffer(frameBuffer);
1098 } else {
1099 CHECK_AND_RETURN_LOG(state_ == State::RUNNING, "Not in running state");
1100 callback_->OnError(AVCODEC_ERROR_EXTEND_START, AVCS_ERR_NO_MEMORY);
1101 return;
1102 }
1103 frameBuffer->avBuffer_->flag_ = AVCODEC_BUFFER_FLAG_NONE;
1104 } else if (ret == AVERROR_EOF) {
1105 AVCODEC_LOGI("Receive eos");
1106 frameBuffer->avBuffer_->flag_ = AVCODEC_BUFFER_FLAG_EOS;
1107 frameBuffer->avBuffer_->memory_->SetSize(0);
1108 state_ = State::EOS;
1109 } else if (ret == AVERROR(EAGAIN)) {
1110 std::unique_lock<std::mutex> sendLock(sendMutex_);
1111 if (isSendWait_ || isSendEos_) {
1112 isSendWait_ = false;
1113 sendCv_.notify_one();
1114 }
1115 sendLock.unlock();
1116 std::unique_lock<std::mutex> recvLock(recvMutex_);
1117 recvCv_.wait_for(recvLock, std::chrono::milliseconds(DEFAULT_DECODE_WAIT_TIME));
1118 return;
1119 } else {
1120 AVCODEC_LOGE("Cannot recv frame from codec: ffmpeg ret = %{public}s", AVStrError(ret).c_str());
1121 callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN);
1122 state_ = State::ERROR;
1123 return;
1124 }
1125 FramePostProcess(frameBuffer, index, status, ret);
1126 }
1127
FindAvailIndex(uint32_t index)1128 void FCodec::FindAvailIndex(uint32_t index)
1129 {
1130 uint32_t curQueSize = renderAvailQue_->Size();
1131 for (uint32_t i = 0u; i < curQueSize; i++) {
1132 uint32_t num = renderAvailQue_->Pop();
1133 if (num == index) {
1134 break;
1135 } else {
1136 renderAvailQue_->Push(num);
1137 }
1138 }
1139 }
1140
ReleaseOutputBuffer(uint32_t index)1141 int32_t FCodec::ReleaseOutputBuffer(uint32_t index)
1142 {
1143 AVCODEC_SYNC_TRACE;
1144 std::unique_lock<std::mutex> oLock(outputMutex_);
1145 CHECK_AND_RETURN_RET_LOG(index < buffers_[INDEX_OUTPUT].size(), AVCS_ERR_INVALID_VAL,
1146 "Failed to release output buffer: invalid index");
1147 std::shared_ptr<FBuffer> frameBuffer = buffers_[INDEX_OUTPUT][index];
1148 oLock.unlock();
1149 if (frameBuffer->owner_ == FBuffer::Owner::OWNED_BY_USER) {
1150 frameBuffer->owner_ = FBuffer::Owner::OWNED_BY_CODEC;
1151 codecAvailQue_->Push(index);
1152 return AVCS_ERR_OK;
1153 } else {
1154 AVCODEC_LOGE("Release output buffer failed: check your index=%{public}u", index);
1155 return AVCS_ERR_INVALID_VAL;
1156 }
1157 }
1158
FlushSurfaceMemory(std::shared_ptr<FSurfaceMemory> &surfaceMemory, uint32_t index)1159 int32_t FCodec::FlushSurfaceMemory(std::shared_ptr<FSurfaceMemory> &surfaceMemory, uint32_t index)
1160 {
1161 sptr<SurfaceBuffer> surfaceBuffer = surfaceMemory->GetSurfaceBuffer();
1162 CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, AVCS_ERR_INVALID_VAL,
1163 "Failed to update surface memory: surface buffer is NULL");
1164 OHOS::BufferFlushConfig flushConfig = {{0, 0, surfaceBuffer->GetWidth(), surfaceBuffer->GetHeight()},
1165 outAVBuffer4Surface_[index]->pts_, -1};
1166 surfaceMemory->SetNeedRender(true);
1167 surfaceMemory->UpdateSurfaceBufferScaleMode();
1168 if (outAVBuffer4Surface_[index]->meta_->Find(OHOS::Media::Tag::VIDEO_DECODER_DESIRED_PRESENT_TIMESTAMP) !=
1169 outAVBuffer4Surface_[index]->meta_->end()) {
1170 outAVBuffer4Surface_[index]->meta_->Get<OHOS::Media::Tag::VIDEO_DECODER_DESIRED_PRESENT_TIMESTAMP>(
1171 flushConfig.desiredPresentTimestamp);
1172 outAVBuffer4Surface_[index]->meta_->Remove(OHOS::Media::Tag::VIDEO_DECODER_DESIRED_PRESENT_TIMESTAMP);
1173 }
1174 auto res = sInfo_.surface->FlushBuffer(surfaceBuffer, -1, flushConfig);
1175 if (res != OHOS::SurfaceError::SURFACE_ERROR_OK) {
1176 AVCODEC_LOGW("Failed to update surface memory: %{public}d", res);
1177 surfaceMemory->SetNeedRender(false);
1178 surfaceMemory->ReleaseSurfaceBuffer();
1179 return AVCS_ERR_UNKNOWN;
1180 }
1181 renderSurfaceBufferMap_[index] = std::make_pair(surfaceBuffer, flushConfig);
1182 surfaceMemory->ReleaseSurfaceBuffer();
1183 return AVCS_ERR_OK;
1184 }
1185
RenderOutputBuffer(uint32_t index)1186 int32_t FCodec::RenderOutputBuffer(uint32_t index)
1187 {
1188 AVCODEC_SYNC_TRACE;
1189 CHECK_AND_RETURN_RET_LOG(sInfo_.surface != nullptr, AVCS_ERR_UNSUPPORT,
1190 "RenderOutputBuffer fail, surface is nullptr");
1191 std::unique_lock<std::mutex> oLock(outputMutex_);
1192 CHECK_AND_RETURN_RET_LOG(index < buffers_[INDEX_OUTPUT].size(), AVCS_ERR_INVALID_VAL,
1193 "Failed to render output buffer: invalid index");
1194 std::shared_ptr<FBuffer> frameBuffer = buffers_[INDEX_OUTPUT][index];
1195 oLock.unlock();
1196 std::lock_guard<std::mutex> sLock(surfaceMutex_);
1197 if (frameBuffer->owner_ == FBuffer::Owner::OWNED_BY_USER) {
1198 std::shared_ptr<FSurfaceMemory> surfaceMemory = frameBuffer->sMemory_;
1199 int32_t ret = FlushSurfaceMemory(surfaceMemory, index);
1200 if (ret != AVCS_ERR_OK) {
1201 AVCODEC_LOGW("Update surface memory failed: %{public}d", static_cast<int32_t>(ret));
1202 } else {
1203 AVCODEC_LOGD("Update surface memory successful");
1204 }
1205 frameBuffer->owner_ = FBuffer::Owner::OWNED_BY_SURFACE;
1206 renderAvailQue_->Push(index);
1207 AVCODEC_LOGD("render output buffer with index, index=%{public}u", index);
1208 return AVCS_ERR_OK;
1209 } else {
1210 AVCODEC_LOGE("Failed to render output buffer with bad index, index=%{public}u", index);
1211 return AVCS_ERR_INVALID_VAL;
1212 }
1213 }
1214
ReplaceOutputSurfaceWhenRunning(sptr<Surface> newSurface)1215 int32_t FCodec::ReplaceOutputSurfaceWhenRunning(sptr<Surface> newSurface)
1216 {
1217 CHECK_AND_RETURN_RET_LOG(sInfo_.surface != nullptr, AV_ERR_OPERATE_NOT_PERMIT,
1218 "Not support convert from AVBuffer Mode to Surface Mode");
1219 sptr<Surface> oldSurface = sInfo_.surface;
1220 uint64_t oldId = oldSurface->GetUniqueId();
1221 uint64_t newId = newSurface->GetUniqueId();
1222 AVCODEC_LOGI("surface %{public}" PRIu64 " -> %{public}" PRIu64 "", oldId, newId);
1223 if (oldId == newId) {
1224 return AVCS_ERR_OK;
1225 }
1226 GSError err = RegisterListenerToSurface(newSurface);
1227 CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, AVCS_ERR_UNKNOWN,
1228 "surface %{public}" PRIu64 ", RegisterListenerToSurface failed, GSError=%{public}d", newId, err);
1229 int32_t outputBufferCnt = 0;
1230 format_.GetIntValue(MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, outputBufferCnt);
1231 int32_t ret = SetQueueSize(newSurface, outputBufferCnt);
1232 if (ret != AVCS_ERR_OK) {
1233 UnRegisterListenerToSurface(newSurface);
1234 return ret;
1235 }
1236 std::unique_lock<std::mutex> sLock(surfaceMutex_);
1237 ret = SwitchBetweenSurface(newSurface);
1238 if (ret != AVCS_ERR_OK) {
1239 UnRegisterListenerToSurface(newSurface);
1240 sInfo_.surface = oldSurface;
1241 return ret;
1242 }
1243 sLock.unlock();
1244 return AVCS_ERR_OK;
1245 }
1246
SetQueueSize(const sptr<Surface> &surface, uint32_t targetSize)1247 int32_t FCodec::SetQueueSize(const sptr<Surface> &surface, uint32_t targetSize)
1248 {
1249 int32_t err = surface->SetQueueSize(targetSize);
1250 if (err != 0) {
1251 AVCODEC_LOGE("surface %{public}" PRIu64 ", SetQueueSize to %{public}u failed, GSError=%{public}d",
1252 surface->GetUniqueId(), targetSize, err);
1253 return AVCS_ERR_UNKNOWN;
1254 }
1255 AVCODEC_LOGI("surface %{public}" PRIu64 ", SetQueueSize to %{public}u succ", surface->GetUniqueId(), targetSize);
1256 return AVCS_ERR_OK;
1257 }
1258
SwitchBetweenSurface(const sptr<Surface> &newSurface)1259 int32_t FCodec::SwitchBetweenSurface(const sptr<Surface> &newSurface)
1260 {
1261 sptr<Surface> curSurface = sInfo_.surface;
1262 newSurface->Connect(); // cleancache will work only if the surface is connected by us
1263 newSurface->CleanCache(); // make sure new surface is empty
1264 std::vector<uint32_t> ownedBySurfaceBufferIndex;
1265 uint64_t newId = newSurface->GetUniqueId();
1266 for (uint32_t index = 0; index < buffers_[INDEX_OUTPUT].size(); index++) {
1267 if (buffers_[INDEX_OUTPUT][index]->sMemory_ == nullptr) {
1268 continue;
1269 }
1270 sptr<SurfaceBuffer> surfaceBuffer = nullptr;
1271 if (buffers_[INDEX_OUTPUT][index]->owner_ == FBuffer::Owner::OWNED_BY_SURFACE) {
1272 if (renderSurfaceBufferMap_.count(index)) {
1273 surfaceBuffer = renderSurfaceBufferMap_[index].first;
1274 ownedBySurfaceBufferIndex.push_back(index);
1275 }
1276 } else {
1277 surfaceBuffer = buffers_[INDEX_OUTPUT][index]->sMemory_->GetSurfaceBuffer();
1278 }
1279 if (surfaceBuffer == nullptr) {
1280 AVCODEC_LOGE("Get old surface buffer error!");
1281 return AVCS_ERR_UNKNOWN;
1282 }
1283 int32_t err = newSurface->AttachBufferToQueue(surfaceBuffer);
1284 if (err != 0) {
1285 AVCODEC_LOGE("surface %{public}" PRIu64 ", AttachBufferToQueue(seq=%{public}u) failed, GSError=%{public}d",
1286 newId, surfaceBuffer->GetSeqNum(), err);
1287 return AVCS_ERR_UNKNOWN;
1288 }
1289 }
1290 int32_t videoRotation = 0;
1291 format_.GetIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, videoRotation);
1292 sInfo_.surface->SetTransform(TranslateSurfaceRotation(static_cast<VideoRotation>(videoRotation)));
1293 int32_t scalingMode = 0;
1294 format_.GetIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE, scalingMode);
1295 sInfo_.scalingMode = static_cast<ScalingMode>(scalingMode);
1296 sInfo_.surface = newSurface;
1297
1298 for (uint32_t index: ownedBySurfaceBufferIndex) {
1299 int32_t ret = RenderNewSurfaceWithOldBuffer(newSurface, index);
1300 if (ret != AVCS_ERR_OK) {
1301 return ret;
1302 }
1303 }
1304
1305 int32_t ret = UnRegisterListenerToSurface(curSurface);
1306 if (ret != AVCS_ERR_OK) {
1307 return ret;
1308 }
1309
1310 curSurface->CleanCache(true); // make sure old surface is empty and go black
1311 return AVCS_ERR_OK;
1312 }
1313
RenderNewSurfaceWithOldBuffer(const sptr<Surface> &newSurface, uint32_t index)1314 int32_t FCodec::RenderNewSurfaceWithOldBuffer(const sptr<Surface> &newSurface, uint32_t index)
1315 {
1316 std::shared_ptr<FSurfaceMemory> surfaceMemory = buffers_[INDEX_OUTPUT][index]->sMemory_;
1317 sptr<SurfaceBuffer> surfaceBuffer = renderSurfaceBufferMap_[index].first;
1318 OHOS::BufferFlushConfig flushConfig = renderSurfaceBufferMap_[index].second;
1319 surfaceMemory->SetNeedRender(true);
1320 newSurface->SetScalingMode(surfaceBuffer->GetSeqNum(), sInfo_.scalingMode);
1321 auto res = newSurface->FlushBuffer(surfaceBuffer, -1, flushConfig);
1322 if (res != OHOS::SurfaceError::SURFACE_ERROR_OK) {
1323 AVCODEC_LOGE("Failed to update surface memory: %{public}d", res);
1324 surfaceMemory->SetNeedRender(false);
1325 return AVCS_ERR_UNKNOWN;
1326 }
1327 return AVCS_ERR_OK;
1328 }
1329
RequestBufferFromConsumer()1330 void FCodec::RequestBufferFromConsumer()
1331 {
1332 auto index = renderAvailQue_->Front();
1333 std::shared_ptr<FBuffer> outputBuffer = buffers_[INDEX_OUTPUT][index];
1334 std::shared_ptr<FSurfaceMemory> surfaceMemory = outputBuffer->sMemory_;
1335 sptr<SurfaceBuffer> surfaceBuffer = surfaceMemory->GetSurfaceBuffer();
1336 if (surfaceBuffer == nullptr) {
1337 AVCODEC_LOGE("get buffer failed.");
1338 return;
1339 }
1340 auto queSize = renderAvailQue_->Size();
1341 uint32_t curIndex = 0;
1342 uint32_t i = 0;
1343 for (i = 0; i < queSize; i++) {
1344 curIndex = renderAvailQue_->Pop();
1345 if (surfaceMemory->GetBase() == buffers_[INDEX_OUTPUT][curIndex]->avBuffer_->memory_->GetAddr() &&
1346 surfaceMemory->GetSize() == buffers_[INDEX_OUTPUT][curIndex]->avBuffer_->memory_->GetCapacity()) {
1347 buffers_[INDEX_OUTPUT][index]->sMemory_ = buffers_[INDEX_OUTPUT][curIndex]->sMemory_;
1348 buffers_[INDEX_OUTPUT][curIndex]->sMemory_ = surfaceMemory;
1349 break;
1350 } else {
1351 renderAvailQue_->Push(curIndex);
1352 }
1353 }
1354 if (i == queSize) {
1355 curIndex = index;
1356 outputBuffer->avBuffer_ = AVBuffer::CreateAVBuffer(surfaceMemory->GetBase(), surfaceMemory->GetSize());
1357 outputBuffer->width_ = width_;
1358 outputBuffer->height_ = height_;
1359 FindAvailIndex(curIndex);
1360 }
1361 buffers_[INDEX_OUTPUT][curIndex]->owner_ = FBuffer::Owner::OWNED_BY_CODEC;
1362 codecAvailQue_->Push(curIndex);
1363 if (renderSurfaceBufferMap_.count(curIndex)) {
1364 renderSurfaceBufferMap_.erase(curIndex);
1365 }
1366 AVCODEC_LOGD("Request output buffer success, index = %{public}u, queSize=%{public}zu, i=%{public}d", curIndex,
1367 queSize, i);
1368 }
1369
BufferReleasedByConsumer(uint64_t surfaceId)1370 GSError FCodec::BufferReleasedByConsumer(uint64_t surfaceId)
1371 {
1372 CHECK_AND_RETURN_RET_LOG(state_ == State::RUNNING || state_ == State::EOS, GSERROR_NO_PERMISSION, "In valid state");
1373 std::lock_guard<std::mutex> sLock(surfaceMutex_);
1374 CHECK_AND_RETURN_RET_LOG(renderAvailQue_->Size() > 0, GSERROR_NO_BUFFER, "No available buffer");
1375 CHECK_AND_RETURN_RET_LOG(surfaceId == sInfo_.surface->GetUniqueId(), GSERROR_INVALID_ARGUMENTS,
1376 "Ignore callback from old surface");
1377 RequestBufferFromConsumer();
1378 return GSERROR_OK;
1379 }
1380
UnRegisterListenerToSurface(const sptr<Surface> &surface)1381 int32_t FCodec::UnRegisterListenerToSurface(const sptr<Surface> &surface)
1382 {
1383 GSError err = surface->UnRegisterReleaseListener();
1384 CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, AVCS_ERR_UNKNOWN,
1385 "surface %{public}" PRIu64 ", UnRegisterReleaseListener failed, GSError=%{public}d",
1386 surface->GetUniqueId(), err);
1387 return AVCS_ERR_OK;
1388 }
1389
RegisterListenerToSurface(const sptr<Surface> &surface)1390 GSError FCodec::RegisterListenerToSurface(const sptr<Surface> &surface)
1391 {
1392 uint64_t surfaceId = surface->GetUniqueId();
1393 wptr<FCodec> wp = this;
1394 GSError err = surface->RegisterReleaseListener([wp, surfaceId](sptr<SurfaceBuffer> &) {
1395 sptr<FCodec> codec = wp.promote();
1396 if (!codec) {
1397 AVCODEC_LOGD("decoder is gone");
1398 return GSERROR_OK;
1399 }
1400 return codec->BufferReleasedByConsumer(surfaceId);
1401 });
1402 return err;
1403 }
1404
SetOutputSurface(sptr<Surface> surface)1405 int32_t FCodec::SetOutputSurface(sptr<Surface> surface)
1406 {
1407 AVCODEC_SYNC_TRACE;
1408 CHECK_AND_RETURN_RET_LOG(state_ != State::UNINITIALIZED, AV_ERR_INVALID_VAL,
1409 "set output surface fail: not initialized or configured");
1410 CHECK_AND_RETURN_RET_LOG((state_ == State::CONFIGURED || state_ == State::FLUSHED ||
1411 state_ == State::RUNNING || state_ == State::EOS), AVCS_ERR_INVALID_STATE,
1412 "set output surface fail: state %{public}d not support set output surface",
1413 static_cast<int32_t>(state_.load()));
1414 if (surface == nullptr || surface->IsConsumer()) {
1415 AVCODEC_LOGE("Set surface fail");
1416 return AVCS_ERR_INVALID_VAL;
1417 }
1418 if (state_ == State::FLUSHED || state_ == State::RUNNING || state_ == State::EOS) {
1419 return ReplaceOutputSurfaceWhenRunning(surface);
1420 }
1421 sInfo_.surface = surface;
1422 GSError err = RegisterListenerToSurface(sInfo_.surface);
1423 CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, AVCS_ERR_UNKNOWN,
1424 "surface %{public}" PRIu64 ", RegisterListenerToSurface failed, GSError=%{public}d",
1425 sInfo_.surface->GetUniqueId(), err);
1426 if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_SCALE_TYPE)) {
1427 std::lock_guard<std::mutex> lock(formatMutex_);
1428 format_.PutIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE,
1429 static_cast<int32_t>(ScalingMode::SCALING_MODE_SCALE_TO_WINDOW));
1430 }
1431 if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE)) {
1432 std::lock_guard<std::mutex> lock(formatMutex_);
1433 format_.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE,
1434 static_cast<int32_t>(VideoRotation::VIDEO_ROTATION_0));
1435 }
1436 AVCODEC_LOGI("Set surface success");
1437 return AVCS_ERR_OK;
1438 }
1439
SetCallback(const std::shared_ptr<MediaCodecCallback> &callback)1440 int32_t FCodec::SetCallback(const std::shared_ptr<MediaCodecCallback> &callback)
1441 {
1442 AVCODEC_SYNC_TRACE;
1443 CHECK_AND_RETURN_RET_LOG(callback != nullptr, AVCS_ERR_INVALID_VAL, "Set callback failed: callback is NULL");
1444 callback_ = callback;
1445 return AVCS_ERR_OK;
1446 }
1447
GetCodecCapability(std::vector<CapabilityData> &capaArray)1448 int32_t FCodec::GetCodecCapability(std::vector<CapabilityData> &capaArray)
1449 {
1450 for (uint32_t i = 0; i < SUPPORT_VCODEC_NUM; ++i) {
1451 CapabilityData capsData;
1452 capsData.codecName = static_cast<std::string>(SUPPORT_VCODEC[i].codecName);
1453 capsData.mimeType = static_cast<std::string>(SUPPORT_VCODEC[i].mimeType);
1454 capsData.codecType = SUPPORT_VCODEC[i].isEncoder ? AVCODEC_TYPE_VIDEO_ENCODER : AVCODEC_TYPE_VIDEO_DECODER;
1455 capsData.isVendor = false;
1456 capsData.maxInstance = VIDEO_INSTANCE_SIZE;
1457 capsData.alignment.width = VIDEO_ALIGNMENT_SIZE;
1458 capsData.alignment.height = VIDEO_ALIGNMENT_SIZE;
1459 capsData.width.minVal = VIDEO_MIN_SIZE;
1460 capsData.width.maxVal = VIDEO_MAX_WIDTH_SIZE;
1461 capsData.height.minVal = VIDEO_MIN_SIZE;
1462 capsData.height.maxVal = VIDEO_MAX_HEIGHT_SIZE;
1463 capsData.frameRate.minVal = 0;
1464 capsData.frameRate.maxVal = VIDEO_FRAMERATE_MAX_SIZE;
1465 capsData.bitrate.minVal = 1;
1466 capsData.bitrate.maxVal = VIDEO_BITRATE_MAX_SIZE;
1467 capsData.blockPerFrame.minVal = 1;
1468 capsData.blockPerFrame.maxVal = VIDEO_BLOCKPERFRAME_SIZE;
1469 capsData.blockPerSecond.minVal = 1;
1470 capsData.blockPerSecond.maxVal = VIDEO_BLOCKPERSEC_SIZE;
1471 capsData.blockSize.width = VIDEO_ALIGN_SIZE;
1472 capsData.blockSize.height = VIDEO_ALIGN_SIZE;
1473 if (SUPPORT_VCODEC[i].isEncoder) {
1474 capsData.complexity.minVal = 0;
1475 capsData.complexity.maxVal = 0;
1476 capsData.encodeQuality.minVal = 0;
1477 capsData.encodeQuality.maxVal = 0;
1478 }
1479 capsData.pixFormat = {
1480 static_cast<int32_t>(VideoPixelFormat::YUVI420), static_cast<int32_t>(VideoPixelFormat::NV12),
1481 static_cast<int32_t>(VideoPixelFormat::NV21), static_cast<int32_t>(VideoPixelFormat::RGBA)};
1482 capsData.profiles = {static_cast<int32_t>(AVC_PROFILE_BASELINE), static_cast<int32_t>(AVC_PROFILE_MAIN),
1483 static_cast<int32_t>(AVC_PROFILE_HIGH)};
1484 std::vector<int32_t> levels;
1485 for (int32_t j = 0; j <= static_cast<int32_t>(AVCLevel::AVC_LEVEL_51); ++j) {
1486 levels.emplace_back(j);
1487 }
1488 capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(AVC_PROFILE_MAIN), levels));
1489 capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(AVC_PROFILE_HIGH), levels));
1490 capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(AVC_PROFILE_BASELINE), levels));
1491 capaArray.emplace_back(capsData);
1492 }
1493 return AVCS_ERR_OK;
1494 }
1495 } // namespace Codec
1496 } // namespace MediaAVCodec
1497 } // namespace OHOS
1498