• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "fcodec.h"
17 #include <iostream>
18 #include <set>
19 #include <thread>
20 #include <malloc.h>
21 #include "syspara/parameters.h"
22 #include "securec.h"
23 #include "avcodec_trace.h"
24 #include "avcodec_log.h"
25 #include "utils.h"
26 #include "avcodec_codec_name.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 VIDEO_MAX_WIDTH_H263_SIZE = 2048;
46 constexpr int32_t VIDEO_MAX_HEIGHT_H263_SIZE = 1152;
47 constexpr int32_t VIDEO_MIN_WIDTH_H263_SIZE = 20;
48 constexpr int32_t VIDEO_MIN_HEIGHT_H263_SIZE = 20;
49 constexpr int32_t DEFAULT_VIDEO_WIDTH = 1920;
50 constexpr int32_t DEFAULT_VIDEO_HEIGHT = 1080;
51 constexpr uint32_t DEFAULT_TRY_DECODE_TIME = 1;
52 constexpr uint32_t DEFAULT_DECODE_WAIT_TIME = 200;
53 constexpr uint32_t LOG_FREQUENCE = 200;
54 constexpr int32_t VIDEO_INSTANCE_SIZE = 64;
55 constexpr int32_t VIDEO_BITRATE_MAX_SIZE = 300000000;
56 constexpr int32_t VIDEO_FRAMERATE_MAX_SIZE = 120;
57 constexpr int32_t VIDEO_FRAMERATE_DEFAULT_SIZE = 60;
58 constexpr int32_t VIDEO_BLOCKPERFRAME_SIZE = 139264;
59 constexpr int32_t VIDEO_BLOCKPERSEC_SIZE = 983040;
60 constexpr int32_t DEFAULT_THREAD_COUNT = 2;
61 #ifdef BUILD_ENG_VERSION
62 constexpr uint32_t PATH_MAX_LEN = 128;
63 constexpr char DUMP_PATH[] = "/data/misc/fcodecdump";
64 #endif // BUILD_ENG_VERSION
65 constexpr struct {
66     const std::string_view codecName;
67     const std::string_view mimeType;
68     const char *ffmpegCodec;
69 } SUPPORT_VCODEC[] = {
70     {AVCodecCodecName::VIDEO_DECODER_AVC_NAME, CodecMimeType::VIDEO_AVC, "h264"},
71     {AVCodecCodecName::VIDEO_DECODER_H263_NAME, CodecMimeType::VIDEO_H263, "h263"},
72     {AVCodecCodecName::VIDEO_DECODER_MPEG2_NAME, CodecMimeType::VIDEO_MPEG2, "mpeg2video"},
73     {AVCodecCodecName::VIDEO_DECODER_MPEG4_NAME, CodecMimeType::VIDEO_MPEG4, "mpeg4"},
74 #ifdef SUPPORT_CODEC_RV
75     {AVCodecCodecName::VIDEO_DECODER_RV30_NAME, CodecMimeType::VIDEO_RV30, "rv30"},
76     {AVCodecCodecName::VIDEO_DECODER_RV40_NAME, CodecMimeType::VIDEO_RV40, "rv40"},
77 #endif
78 };
79 constexpr uint32_t SUPPORT_VCODEC_NUM = sizeof(SUPPORT_VCODEC) / sizeof(SUPPORT_VCODEC[0]);
80 } // namespace
81 using namespace OHOS::Media;
82 
FCodec(const std::string & name)83 FCodec::FCodec(const std::string &name) : codecName_(name), state_(State::UNINITIALIZED) {}
84 
~FCodec()85 FCodec::~FCodec()
86 {
87     ReleaseResource();
88     callback_ = nullptr;
89 #ifdef BUILD_ENG_VERSION
90     if (dumpInFile_ != nullptr) {
91         dumpInFile_->close();
92     }
93     if (dumpOutFile_ != nullptr) {
94         dumpOutFile_->close();
95     }
96 #endif // BUILD_ENG_VERSION
97     mallopt(M_FLUSH_THREAD_CACHE, 0);
98 }
99 
Init(Meta & callerInfo)100 int32_t FCodec::Init(Meta &callerInfo)
101 {
102     if (callerInfo.GetData(Tag::AV_CODEC_FORWARD_CALLER_PID, fDecInfo_.pid) &&
103         callerInfo.GetData(Tag::AV_CODEC_FORWARD_CALLER_PROCESS_NAME, fDecInfo_.processName)) {
104         fDecInfo_.calledByAvcodec = false;
105     } else if (callerInfo.GetData(Tag::AV_CODEC_CALLER_PID, fDecInfo_.pid) &&
106                callerInfo.GetData(Tag::AV_CODEC_CALLER_PROCESS_NAME, fDecInfo_.processName)) {
107         fDecInfo_.calledByAvcodec = true;
108     }
109     callerInfo.GetData("av_codec_event_info_instance_id", instanceId_);
110     int32_t ret = Initialize();
111     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Failed to initialize");
112     return AVCS_ERR_OK;
113 }
114 
115 #ifdef BUILD_ENG_VERSION
OpenDumpFile()116 void FCodec::OpenDumpFile()
117 {
118     std::string dumpModeStr = OHOS::system::GetParameter("fcodec.dump", "0");
119     AVCODEC_LOGI("dumpModeStr %{public}s", dumpModeStr.c_str());
120     CHECK_AND_RETURN_LOG(dumpModeStr.length() == 2, "dumpModeStr length should equal 2"); // 2
121     char fileName[PATH_MAX_LEN] = {0};
122     int ret;
123     if (dumpModeStr[0] == '1') {
124         ret = sprintf_s(fileName, sizeof(fileName), "%s/input_%p.h264", DUMP_PATH, this);
125         CHECK_AND_RETURN_LOG(ret > 0, "Fail to sprintf input fileName");
126         dumpInFile_ = std::make_shared<std::ofstream>();
127         dumpInFile_->open(fileName, std::ios::out | std::ios::binary);
128         if (!dumpInFile_->is_open()) {
129             AVCODEC_LOGW("fail open file %{public}s", fileName);
130             dumpInFile_ = nullptr;
131         }
132     }
133 
134     if (dumpModeStr[1] == '1') {
135         ret = sprintf_s(fileName, sizeof(fileName), "%s/output_%p.yuv", DUMP_PATH, this);
136         CHECK_AND_RETURN_LOG(ret > 0, "Fail to sprintf output fileName");
137         dumpOutFile_ = std::make_shared<std::ofstream>();
138         dumpOutFile_->open(fileName, std::ios::out | std::ios::binary);
139         if (!dumpOutFile_->is_open()) {
140             AVCODEC_LOGW("fail open file %{public}s", fileName);
141             dumpOutFile_ = nullptr;
142         }
143     }
144 }
145 #endif // BUILD_ENG_VERSION
146 
Initialize()147 int32_t FCodec::Initialize()
148 {
149     AVCODEC_SYNC_TRACE;
150     fDecInfo_.instanceId = std::to_string(instanceId_);
151     decName_ = "fdecoder_[" + std::to_string(instanceId_) + "]";
152     AVCODEC_LOGI("current codec name: %{public}s", decName_.c_str());
153     CHECK_AND_RETURN_RET_LOG(!codecName_.empty(), AVCS_ERR_INVALID_VAL, "Init codec failed:  empty name");
154     pid_ = getpid();
155     std::string fcodecName;
156     std::string_view mime;
157     for (uint32_t i = 0; i < SUPPORT_VCODEC_NUM; ++i) {
158         if (SUPPORT_VCODEC[i].codecName == codecName_) {
159             fcodecName = SUPPORT_VCODEC[i].ffmpegCodec;
160             mime = SUPPORT_VCODEC[i].mimeType;
161             break;
162         }
163     }
164     CHECK_AND_RETURN_RET_LOG(!fcodecName.empty(), AVCS_ERR_INVALID_VAL,
165                              "Init codec failed: not support name: %{public}s", codecName_.c_str());
166     format_.PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, mime);
167     format_.PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_NAME, codecName_);
168     fDecInfo_.mimeType = mime;
169     avCodec_ = std::shared_ptr<AVCodec>(const_cast<AVCodec *>(avcodec_find_decoder_by_name(fcodecName.c_str())),
170                                         [](void *ptr) {});
171     CHECK_AND_RETURN_RET_LOG(avCodec_ != nullptr, AVCS_ERR_INVALID_VAL,
172                              "Init codec failed:  cannot find codec with name %{public}s", codecName_.c_str());
173     sendTask_ = std::make_shared<TaskThread>("SendFrame");
174     sendTask_->RegisterHandler([this] { SendFrame(); });
175     receiveTask_ = std::make_shared<TaskThread>("ReceiveFrame");
176     receiveTask_->RegisterHandler([this] { ReceiveFrame(); });
177 #ifdef BUILD_ENG_VERSION
178     OpenDumpFile();
179 #endif // BUILD_ENG_VERSION
180     state_ = State::INITIALIZED;
181     AVCODEC_LOGI("Init codec successful,  state: Uninitialized -> Initialized");
182     return AVCS_ERR_OK;
183 }
184 
ConfigureDefaultVal(const Format & format,const std::string_view & formatKey,int32_t minVal,int32_t maxVal)185 void FCodec::ConfigureDefaultVal(const Format &format, const std::string_view &formatKey, int32_t minVal,
186                                  int32_t maxVal)
187 {
188     int32_t val32 = 0;
189     if (format.GetIntValue(formatKey, val32) && val32 >= minVal && val32 <= maxVal) {
190         format_.PutIntValue(formatKey, val32);
191     } else {
192         AVCODEC_LOGW("Set parameter failed: %{public}s, which minimum threshold=%{public}d, "
193                      "maximum threshold=%{public}d",
194                      std::string(formatKey).c_str(), minVal, maxVal);
195     }
196 }
197 
ConfigureSurface(const Format & format,const std::string_view & formatKey,FormatDataType formatType)198 void FCodec::ConfigureSurface(const Format &format, const std::string_view &formatKey, FormatDataType formatType)
199 {
200     CHECK_AND_RETURN_LOG(formatType == FORMAT_TYPE_INT32, "Set parameter failed: type should be int32");
201 
202     int32_t val = 0;
203     CHECK_AND_RETURN_LOG(format.GetIntValue(formatKey, val), "Set parameter failed: get value fail");
204 
205     if (formatKey == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT) {
206         VideoPixelFormat vpf = static_cast<VideoPixelFormat>(val);
207         CHECK_AND_RETURN_LOG(vpf == VideoPixelFormat::RGBA || vpf == VideoPixelFormat::YUVI420 ||
208                              vpf == VideoPixelFormat::NV12 || vpf == VideoPixelFormat::NV21,
209                              "Set parameter failed: pixel format value %{public}d invalid", val);
210         outputPixelFmt_ = vpf;
211         format_.PutIntValue(formatKey, val);
212     } else if (formatKey == MediaDescriptionKey::MD_KEY_ROTATION_ANGLE) {
213         VideoRotation sr = static_cast<VideoRotation>(val);
214         CHECK_AND_RETURN_LOG(sr == VideoRotation::VIDEO_ROTATION_0 || sr == VideoRotation::VIDEO_ROTATION_90 ||
215                              sr == VideoRotation::VIDEO_ROTATION_180 || sr == VideoRotation::VIDEO_ROTATION_270,
216                              "Set parameter failed: rotation angle value %{public}d invalid", val);
217         format_.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, val);
218     } else {
219         ScalingMode scaleMode = static_cast<ScalingMode>(val);
220         CHECK_AND_RETURN_LOG(scaleMode == ScalingMode::SCALING_MODE_SCALE_TO_WINDOW ||
221                              scaleMode == ScalingMode::SCALING_MODE_SCALE_CROP,
222                              "Set parameter failed: scale type value %{public}d invalid", val);
223         format_.PutIntValue(formatKey, val);
224     }
225     AVCODEC_LOGI("Set parameter %{public}s success, val %{public}d", std::string(formatKey).c_str(), val);
226 }
227 
ConfigureContext(const Format & format)228 int32_t FCodec::ConfigureContext(const Format &format)
229 {
230     avCodecContext_ = std::shared_ptr<AVCodecContext>(avcodec_alloc_context3(avCodec_.get()), [](AVCodecContext *p) {
231         if (p != nullptr) {
232             if (p->extradata) {
233                 av_free(p->extradata);
234                 p->extradata = nullptr;
235             }
236             avcodec_free_context(&p);
237         }
238     });
239     CHECK_AND_RETURN_RET_LOG(avCodecContext_ != nullptr, AVCS_ERR_INVALID_OPERATION,
240                              "Configure codec failed: Allocate context error");
241     avCodecContext_->codec_type = AVMEDIA_TYPE_VIDEO;
242     CHECK_AND_RETURN_RET_LOG(format.GetIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width_) &&
243                              width_ >= VIDEO_MIN_SIZE && width_ <= VIDEO_MAX_WIDTH_SIZE,
244                              AVCS_ERR_INVALID_VAL, "Invalid width %{public}d!", width_);
245     CHECK_AND_RETURN_RET_LOG(format.GetIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height_) &&
246                              height_ >= VIDEO_MIN_SIZE && height_ <= VIDEO_MAX_HEIGHT_SIZE,
247                              AVCS_ERR_INVALID_VAL, "Invalid height %{public}d!", height_);
248     format_.PutIntValue(OHOS::Media::Tag::VIDEO_STRIDE,
249                         outputPixelFmt_ == VideoPixelFormat::RGBA ? width_ * VIDEO_PIX_DEPTH_RGBA : width_);
250     format_.PutIntValue(OHOS::Media::Tag::VIDEO_SLICE_HEIGHT, height_);
251     format_.PutIntValue(OHOS::Media::Tag::VIDEO_PIC_WIDTH, width_);
252     format_.PutIntValue(OHOS::Media::Tag::VIDEO_PIC_HEIGHT, height_);
253 
254     avCodecContext_->width = width_;
255     avCodecContext_->height = height_;
256     avCodecContext_->thread_count = DEFAULT_THREAD_COUNT;
257 #if (defined SUPPORT_CODEC_RV) || (defined SUPPORT_CODEC_MP4V_ES)
258     return SetCodecExtradata(format);
259 #else
260     return AVCS_ERR_OK;
261 #endif
262 }
263 
264 #if (defined SUPPORT_CODEC_RV) || (defined SUPPORT_CODEC_MP4V_ES)
SetCodecExtradata(const Format & format)265 int32_t FCodec::SetCodecExtradata(const Format &format)
266 {
267     size_t extraSize = 0;
268     uint8_t *extraData = nullptr;
269     if (format.GetBuffer(MediaDescriptionKey::MD_KEY_CODEC_CONFIG, &extraData, extraSize)) {
270         if (extraData == nullptr || extraSize == 0) {
271             AVCODEC_LOGE("extradata getBufer failed!");
272             return AVCS_ERR_INVALID_VAL;
273         }
274         avCodecContext_->extradata = static_cast<uint8_t *>(av_mallocz(extraSize + AV_INPUT_BUFFER_PADDING_SIZE));
275         if (avCodecContext_->extradata == nullptr) {
276             AVCODEC_LOGE("extradata malloc failed!");
277             return AVCS_ERR_INVALID_VAL;
278         }
279         avCodecContext_->extradata_size = static_cast<int>(extraSize);
280         errno_t rc = memcpy_s(avCodecContext_->extradata, extraSize, extraData, extraSize);
281         if (rc != EOK) {
282             AVCODEC_LOGE("extradata memcpy_s failed.");
283             return AVCodecServiceErrCode::AVCS_ERR_INVALID_VAL;
284         }
285         rc = memset_s(avCodecContext_->extradata + extraSize, AV_INPUT_BUFFER_PADDING_SIZE, 0,
286                       AV_INPUT_BUFFER_PADDING_SIZE);
287         if (rc != EOK) {
288             AVCODEC_LOGE("extradata memset_s failed.");
289             return AVCodecServiceErrCode::AVCS_ERR_INVALID_VAL;
290         }
291     }
292     return AVCS_ERR_OK;
293 }
294 #endif
295 
Configure(const Format & format)296 int32_t FCodec::Configure(const Format &format)
297 {
298     AVCODEC_SYNC_TRACE;
299     CHECK_AND_RETURN_RET_LOG((state_ == State::INITIALIZED), AVCS_ERR_INVALID_STATE,
300                              "Configure codec failed: not in Initialized state");
301     format_.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, DEFAULT_VIDEO_WIDTH);
302     format_.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, DEFAULT_VIDEO_HEIGHT);
303     format_.PutIntValue(MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, DEFAULT_OUT_BUFFER_CNT);
304     format_.PutIntValue(MediaDescriptionKey::MD_KEY_MAX_INPUT_BUFFER_COUNT, DEFAULT_IN_BUFFER_CNT);
305     for (auto &it : format.GetFormatMap()) {
306         if (it.first == MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT) {
307             isOutBufSetted_ = true;
308             ConfigureDefaultVal(format, it.first, DEFAULT_MIN_BUFFER_CNT);
309         } else if (it.first == MediaDescriptionKey::MD_KEY_MAX_INPUT_BUFFER_COUNT) {
310             ConfigureDefaultVal(format, it.first, DEFAULT_MIN_BUFFER_CNT);
311         } else if (it.first == MediaDescriptionKey::MD_KEY_WIDTH) {
312             ConfigureDefaultVal(format, it.first, VIDEO_MIN_SIZE, VIDEO_MAX_WIDTH_SIZE);
313         } else if (it.first == MediaDescriptionKey::MD_KEY_HEIGHT) {
314             ConfigureDefaultVal(format, it.first, VIDEO_MIN_SIZE, VIDEO_MAX_HEIGHT_SIZE);
315         } else if (it.first == MediaDescriptionKey::MD_KEY_BITRATE) {
316             int64_t val64 = 0L;
317             CHECK_AND_RETURN_RET_LOG(format.GetLongValue(MediaDescriptionKey::MD_KEY_BITRATE, val64) && val64 > 0L,
318                                      AVCS_ERR_INVALID_VAL, "Cannot get bit rate!");
319             format_.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, val64);
320         } else if (it.first == MediaDescriptionKey::MD_KEY_FRAME_RATE) {
321             double val = 0;
322             CHECK_AND_RETURN_RET_LOG(format.GetDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, val) && val > 0.0f,
323                                      AVCS_ERR_INVALID_VAL, "Cannot get frame rate!");
324             format_.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, val);
325         } else if (it.first == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT ||
326                    it.first == MediaDescriptionKey::MD_KEY_ROTATION_ANGLE ||
327                    it.first == MediaDescriptionKey::MD_KEY_SCALE_TYPE) {
328             ConfigureSurface(format, it.first, it.second.type);
329         } else {
330             AVCODEC_LOGW("Set parameter failed: %{public}s, unsupport key", it.first.data());
331         }
332     }
333     AVCODEC_LOGI("current pixel format %{public}d", static_cast<int32_t>(outputPixelFmt_));
334     int32_t ret = ConfigureContext(format);
335 
336     state_ = State::CONFIGURED;
337     AVCODEC_LOGI("Configured codec successful: state: Initialized -> Configured");
338     return ret;
339 }
340 
IsActive() const341 bool FCodec::IsActive() const
342 {
343     return state_ == State::RUNNING || state_ == State::FLUSHED || state_ == State::EOS;
344 }
345 
ResetContext(bool isFlush)346 void FCodec::ResetContext(bool isFlush)
347 {
348     CHECK_AND_RETURN_LOG(avCodecContext_ != nullptr, "Avcodec context is nullptr");
349     if (avCodecContext_->extradata) {
350         av_free(avCodecContext_->extradata);
351         avCodecContext_->extradata = nullptr;
352     }
353     avCodecContext_->coded_width = 0;
354     avCodecContext_->coded_height = 0;
355     avCodecContext_->extradata_size = 0;
356     if (!isFlush) {
357         avCodecContext_->width = 0;
358         avCodecContext_->height = 0;
359         avCodecContext_->get_buffer2 = nullptr;
360     }
361 }
362 
Start()363 int32_t FCodec::Start()
364 {
365     AVCODEC_SYNC_TRACE;
366     CHECK_AND_RETURN_RET_LOG(callback_ != nullptr, AVCS_ERR_INVALID_OPERATION, "Start codec failed: callback is null");
367     CHECK_AND_RETURN_RET_LOG((state_ == State::CONFIGURED || state_ == State::FLUSHED), AVCS_ERR_INVALID_STATE,
368                              "Start codec failed: not in Configured or Flushed state");
369     if (state_ != State::FLUSHED) {
370         CHECK_AND_RETURN_RET_LOG(avcodec_open2(avCodecContext_.get(), avCodec_.get(), nullptr) == 0, AVCS_ERR_UNKNOWN,
371                                  "Start codec failed: cannot open avcodec");
372     }
373     if (!isBufferAllocated_) {
374         cachedFrame_ = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame *p) { av_frame_free(&p); });
375         avPacket_ = std::shared_ptr<AVPacket>(av_packet_alloc(), [](AVPacket *p) { av_packet_free(&p); });
376         CHECK_AND_RETURN_RET_LOG((cachedFrame_ != nullptr && avPacket_ != nullptr), AVCS_ERR_UNKNOWN,
377                                  "Start codec failed: cannot allocate frame or packet");
378         for (int32_t i = 0; i < AV_NUM_DATA_POINTERS; i++) {
379             scaleData_[i] = nullptr;
380             scaleLineSize_[i] = 0;
381         }
382         isConverted_ = false;
383         int32_t ret = AllocateBuffers();
384         CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Start codec failed: cannot allocate buffers");
385         isBufferAllocated_ = true;
386     }
387     InitBuffers();
388     isSendEos_ = false;
389     sendTask_->Start();
390     receiveTask_->Start();
391     state_ = State::RUNNING;
392     AVCODEC_LOGI("%{public}s Start codec successful, state: Running", decName_.c_str());
393     return AVCS_ERR_OK;
394 }
395 
InitBuffers()396 void FCodec::InitBuffers()
397 {
398     inputAvailQue_->SetActive(true);
399     codecAvailQue_->SetActive(true);
400     if (sInfo_.surface != nullptr) {
401         renderAvailQue_->SetActive(true);
402         requestSurfaceBufferQue_->SetActive(true);
403     }
404     CHECK_AND_RETURN_LOG(buffers_[INDEX_INPUT].size() > 0, "Input buffers is null!");
405     for (uint32_t i = 0u; i < buffers_[INDEX_INPUT].size(); i++) {
406         buffers_[INDEX_INPUT][i]->owner_ = Owner::OWNED_BY_USER;
407         callback_->OnInputBufferAvailable(i, buffers_[INDEX_INPUT][i]->avBuffer_);
408         AVCODEC_LOGI("%{public}s OnInputBufferAvailable frame index = %{public}u, owner = %{public}d",
409                      decName_.c_str(), i, buffers_[INDEX_INPUT][i]->owner_.load());
410     }
411     CHECK_AND_RETURN_LOG(buffers_[INDEX_OUTPUT].size() > 0, "Output buffers is null!");
412     // for buffer mode or state is CONFIGURED
413     if (sInfo_.surface == nullptr || state_ == State::CONFIGURED) {
414         for (uint32_t i = 0u; i < buffers_[INDEX_OUTPUT].size(); i++) {
415             buffers_[INDEX_OUTPUT][i]->owner_ = Owner::OWNED_BY_CODEC;
416             codecAvailQue_->Push(i);
417         }
418         return;
419     }
420     // for surface mode on FlUSHED
421     std::lock_guard<std::mutex> sLock(surfaceMutex_);
422     for (uint32_t i = 0u; i < buffers_[INDEX_OUTPUT].size(); i++) {
423         if (buffers_[INDEX_OUTPUT][i]->owner_ != Owner::OWNED_BY_SURFACE) {
424             buffers_[INDEX_OUTPUT][i]->owner_ = Owner::OWNED_BY_CODEC;
425             codecAvailQue_->Push(i);
426         }
427     }
428 }
429 
ResetData()430 void FCodec::ResetData()
431 {
432     if (scaleData_[0] != nullptr) {
433         if (isConverted_) {
434             av_free(scaleData_[0]);
435             isConverted_ = false;
436             scale_.reset();
437         }
438         for (int32_t i = 0; i < AV_NUM_DATA_POINTERS; i++) {
439             scaleData_[i] = nullptr;
440             scaleLineSize_[i] = 0;
441         }
442     }
443 }
444 
FlushBuffers()445 void FCodec::FlushBuffers()
446 {
447     inputAvailQue_->Clear();
448     std::unique_lock<std::mutex> iLock(inputMutex_);
449     synIndex_ = std::nullopt;
450     iLock.unlock();
451     codecAvailQue_->Clear();
452     ResetData();
453     av_frame_unref(cachedFrame_.get());
454     av_packet_unref(avPacket_.get());
455 }
456 
StopThread()457 void FCodec::StopThread()
458 {
459     if (sendTask_ != nullptr && inputAvailQue_ != nullptr) {
460         std::unique_lock<std::mutex> sLock(sendMutex_);
461         sendCv_.notify_one();
462         sLock.unlock();
463         inputAvailQue_->SetActive(false, false);
464         sendTask_->Stop();
465     }
466     if (receiveTask_ != nullptr && codecAvailQue_ != nullptr) {
467         std::unique_lock<std::mutex> rLock(recvMutex_);
468         recvCv_.notify_one();
469         rLock.unlock();
470         codecAvailQue_->SetActive(false, false);
471         receiveTask_->Stop();
472     }
473     if (sInfo_.surface != nullptr) {
474         if (renderAvailQue_ != nullptr) {
475             renderAvailQue_->SetActive(false, false);
476         }
477         if (requestSurfaceBufferQue_ != nullptr) {
478             requestSurfaceBufferQue_->SetActive(false, false);
479         }
480     }
481 }
482 
Stop()483 int32_t FCodec::Stop()
484 {
485     AVCODEC_SYNC_TRACE;
486     CHECK_AND_RETURN_RET_LOG((IsActive()), AVCS_ERR_INVALID_STATE, "Stop codec failed: not in executing state");
487     state_ = State::STOPPING;
488     AVCODEC_LOGI("step into STOPPING status");
489     StopThread();
490     avcodec_close(avCodecContext_.get());
491     ResetContext(true);
492     ReleaseBuffers();
493     state_ = State::CONFIGURED;
494     AVCODEC_LOGI("Stop codec successful, state: Configured");
495     return AVCS_ERR_OK;
496 }
497 
Flush()498 int32_t FCodec::Flush()
499 {
500     AVCODEC_SYNC_TRACE;
501     CHECK_AND_RETURN_RET_LOG((state_ == State::RUNNING || state_ == State::EOS), AVCS_ERR_INVALID_STATE,
502                              "%{public}s Flush codec failed: not in running or Eos state", decName_.c_str());
503     state_ = State::FLUSHING;
504     AVCODEC_LOGI("%{public}s step into FLUSHING status", decName_.c_str());
505     std::unique_lock<std::mutex> sLock(sendMutex_);
506     sendCv_.notify_one();
507     sLock.unlock();
508     inputAvailQue_->SetActive(false, false);
509     sendTask_->Pause();
510 
511     std::unique_lock<std::mutex> rLock(recvMutex_);
512     recvCv_.notify_one();
513     rLock.unlock();
514     codecAvailQue_->SetActive(false, false);
515     receiveTask_->Pause();
516 
517     avcodec_flush_buffers(avCodecContext_.get());
518     ResetContext(true);
519     FlushBuffers();
520     state_ = State::FLUSHED;
521     AVCODEC_LOGI("%{public}s Flush codec successful, state: Flushed", decName_.c_str());
522     return AVCS_ERR_OK;
523 }
524 
Reset()525 int32_t FCodec::Reset()
526 {
527     AVCODEC_SYNC_TRACE;
528     AVCODEC_LOGI("Reset codec called");
529     int32_t ret = Release();
530     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Reset codec failed: cannot release codec");
531     ret = Initialize();
532     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Reset codec failed: cannot init codec");
533     AVCODEC_LOGI("Reset codec successful, state: Initialized");
534     return AVCS_ERR_OK;
535 }
536 
ReleaseResource()537 void FCodec::ReleaseResource()
538 {
539     StopThread();
540     if (avCodecContext_ != nullptr) {
541         avcodec_close(avCodecContext_.get());
542         ResetContext();
543     }
544     ReleaseBuffers();
545     format_ = Format();
546     CHECK_AND_RETURN_LOG(sInfo_.surface != nullptr, "Surface is nullptr!");
547     UnRegisterListenerToSurface(sInfo_.surface);
548     sInfo_.surface = nullptr;
549     StopRequestSurfaceBufferThread();
550 }
551 
Release()552 int32_t FCodec::Release()
553 {
554     AVCODEC_SYNC_TRACE;
555     state_ = State::STOPPING;
556     AVCODEC_LOGI("step into STOPPING status");
557     ReleaseResource();
558     state_ = State::UNINITIALIZED;
559     AVCODEC_LOGI("Release codec successful, state: Uninitialized");
560     return AVCS_ERR_OK;
561 }
562 
SetSurfaceParameter(const Format & format,const std::string_view & formatKey,FormatDataType formatType)563 void FCodec::SetSurfaceParameter(const Format &format, const std::string_view &formatKey, FormatDataType formatType)
564 {
565     CHECK_AND_RETURN_LOG(formatType == FORMAT_TYPE_INT32, "Set parameter failed: type should be int32");
566     int32_t val = 0;
567     CHECK_AND_RETURN_LOG(format.GetIntValue(formatKey, val), "Set parameter failed: get value fail");
568     if (formatKey == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT) {
569         VideoPixelFormat vpf = static_cast<VideoPixelFormat>(val);
570         CHECK_AND_RETURN_LOG(vpf == VideoPixelFormat::RGBA || vpf == VideoPixelFormat::YUVI420 ||
571                              vpf == VideoPixelFormat::NV12 || vpf == VideoPixelFormat::NV21,
572                              "Set parameter failed: pixel format value %{public}d invalid", val);
573         outputPixelFmt_ = vpf;
574         {
575             std::lock_guard<std::mutex> lock(formatMutex_);
576             format_.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, val);
577         }
578         GraphicPixelFormat surfacePixelFmt = TranslateSurfaceFormat(vpf);
579         std::lock_guard<std::mutex> sLock(surfaceMutex_);
580         sInfo_.requestConfig.format = surfacePixelFmt;
581     } else if (formatKey == MediaDescriptionKey::MD_KEY_ROTATION_ANGLE) {
582         VideoRotation sr = static_cast<VideoRotation>(val);
583         CHECK_AND_RETURN_LOG(sr == VideoRotation::VIDEO_ROTATION_0 || sr == VideoRotation::VIDEO_ROTATION_90 ||
584                              sr == VideoRotation::VIDEO_ROTATION_180 || sr == VideoRotation::VIDEO_ROTATION_270,
585                              "Set parameter failed: rotation angle value %{public}d invalid", val);
586         {
587             std::lock_guard<std::mutex> lock(formatMutex_);
588             format_.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, val);
589         }
590         std::lock_guard<std::mutex> sLock(surfaceMutex_);
591         sInfo_.surface->SetTransform(TranslateSurfaceRotation(sr));
592     } else {
593         ScalingMode scaleMode = static_cast<ScalingMode>(val);
594         CHECK_AND_RETURN_LOG(scaleMode == ScalingMode::SCALING_MODE_SCALE_TO_WINDOW ||
595                              scaleMode == ScalingMode::SCALING_MODE_SCALE_CROP,
596                              "Set parameter failed: scale type value %{public}d invalid", val);
597         {
598             std::lock_guard<std::mutex> lock(formatMutex_);
599             format_.PutIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE, val);
600         }
601         std::lock_guard<std::mutex> sLock(surfaceMutex_);
602         sInfo_.scalingMode = val;
603         sInfo_.surface->SetScalingMode(scaleMode);
604     }
605     AVCODEC_LOGI("Set parameter %{public}s success, val %{public}d", std::string(formatKey).c_str(), val);
606 }
607 
SetParameter(const Format & format)608 int32_t FCodec::SetParameter(const Format &format)
609 {
610     AVCODEC_SYNC_TRACE;
611     for (auto &it : format.GetFormatMap()) {
612         if (sInfo_.surface != nullptr && it.second.type == FORMAT_TYPE_INT32) {
613             if (it.first == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT ||
614                 it.first == MediaDescriptionKey::MD_KEY_ROTATION_ANGLE ||
615                 it.first == MediaDescriptionKey::MD_KEY_SCALE_TYPE) {
616                 SetSurfaceParameter(format, it.first, it.second.type);
617             }
618         } else {
619             AVCODEC_LOGW("Current Version, %{public}s is not supported", it.first.data());
620         }
621     }
622     AVCODEC_LOGI("Set parameter successful");
623     return AVCS_ERR_OK;
624 }
625 
GetOutputFormat(Format & format)626 int32_t FCodec::GetOutputFormat(Format &format)
627 {
628     AVCODEC_SYNC_TRACE;
629     if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_BITRATE)) {
630         if (avCodecContext_ != nullptr) {
631             std::lock_guard<std::mutex> lock(formatMutex_);
632             format_.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, avCodecContext_->bit_rate);
633         }
634     }
635     if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_FRAME_RATE)) {
636         if (avCodecContext_ != nullptr && avCodecContext_->framerate.den > 0) {
637             double value = static_cast<double>(avCodecContext_->framerate.num) /
638                            static_cast<double>(avCodecContext_->framerate.den);
639             std::lock_guard<std::mutex> lock(formatMutex_);
640             format_.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, value);
641         }
642     }
643     if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_MAX_INPUT_SIZE)) {
644         int32_t stride = AlignUp(width_, VIDEO_ALIGN_SIZE);
645         int32_t maxInputSize = static_cast<int32_t>((stride * height_ * VIDEO_PIX_DEPTH_YUV) / UV_SCALE_FACTOR);
646         std::lock_guard<std::mutex> lock(formatMutex_);
647         format_.PutIntValue(MediaDescriptionKey::MD_KEY_MAX_INPUT_SIZE, maxInputSize);
648     }
649     {
650         std::lock_guard<std::mutex> lock(formatMutex_);
651         format = format_;
652     }
653     AVCODEC_LOGI("Get outputFormat successful");
654     return AVCS_ERR_OK;
655 }
656 
CalculateBufferSize()657 void FCodec::CalculateBufferSize()
658 {
659     int32_t stride = AlignUp(width_, VIDEO_ALIGN_SIZE);
660     outputBufferSize_ = static_cast<int32_t>((stride * height_ * VIDEO_PIX_DEPTH_YUV) / UV_SCALE_FACTOR);
661     inputBufferSize_ = std::max(VIDEO_MIN_BUFFER_SIZE, outputBufferSize_);
662     if (outputPixelFmt_ == VideoPixelFormat::RGBA) {
663         outputBufferSize_ = static_cast<int32_t>(stride * height_ * VIDEO_PIX_DEPTH_RGBA);
664     }
665     AVCODEC_LOGI("width = %{public}d, height = %{public}d, stride = %{public}d, Input buffer size = %{public}d, output "
666                  "buffer size=%{public}d",
667                  width_, height_, stride, inputBufferSize_, outputBufferSize_);
668 }
669 
AllocateInputBuffer(int32_t bufferCnt,int32_t inBufferSize)670 int32_t FCodec::AllocateInputBuffer(int32_t bufferCnt, int32_t inBufferSize)
671 {
672     int32_t valBufferCnt = 0;
673     for (int32_t i = 0; i < bufferCnt; i++) {
674         std::shared_ptr<FBuffer> buf = std::make_shared<FBuffer>();
675         std::shared_ptr<AVAllocator> allocator =
676             AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
677         CHECK_AND_CONTINUE_LOG(allocator != nullptr, "input buffer %{public}d allocator is nullptr", i);
678         buf->avBuffer_ = AVBuffer::CreateAVBuffer(allocator, inBufferSize);
679         CHECK_AND_CONTINUE_LOG(buf->avBuffer_ != nullptr && buf->avBuffer_->memory_ != nullptr,
680                                "Allocate input buffer failed, index=%{public}d", i);
681         AVCODEC_LOGI("Allocate input buffer success: index=%{public}d, size=%{public}d",
682                      i, buf->avBuffer_->memory_->GetCapacity());
683         buffers_[INDEX_INPUT].emplace_back(buf);
684         valBufferCnt++;
685     }
686     CHECK_AND_RETURN_RET_LOGD(valBufferCnt < DEFAULT_MIN_BUFFER_CNT, AVCS_ERR_OK, "Allocate input buffers successful");
687     AVCODEC_LOGE("Allocate input buffer failed: only %{public}d buffer is allocated, no memory", valBufferCnt);
688     buffers_[INDEX_INPUT].clear();
689     return AVCS_ERR_NO_MEMORY;
690 }
691 
SetSurfaceCfg()692 int32_t FCodec::SetSurfaceCfg()
693 {
694     if (outputPixelFmt_ == VideoPixelFormat::UNKNOWN) {
695         format_.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, static_cast<int32_t>(VideoPixelFormat::NV12));
696     }
697     int32_t val32 = 0;
698     format_.GetIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, val32);
699     GraphicPixelFormat surfacePixelFmt = TranslateSurfaceFormat(static_cast<VideoPixelFormat>(val32));
700     CHECK_AND_RETURN_RET_LOG(surfacePixelFmt != GraphicPixelFormat::GRAPHIC_PIXEL_FMT_BUTT, AVCS_ERR_UNSUPPORT,
701                              "Failed to allocate output buffer: unsupported surface format");
702     sInfo_.requestConfig.width = width_;
703     sInfo_.requestConfig.height = height_;
704     sInfo_.requestConfig.format = surfacePixelFmt;
705     if (format_.ContainKey(MediaDescriptionKey::MD_KEY_SCALE_TYPE)) {
706         CHECK_AND_RETURN_RET_LOG(format_.GetIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE, val32) && val32 >= 0 &&
707                                  val32 <= static_cast<int32_t>(ScalingMode::SCALING_MODE_SCALE_FIT),
708                                  AVCS_ERR_INVALID_VAL, "Invalid scaling mode %{public}d", val32);
709         sInfo_.scalingMode = val32;
710         sInfo_.surface->SetScalingMode(static_cast<ScalingMode>(val32));
711     }
712     if (format_.ContainKey(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE)) {
713         CHECK_AND_RETURN_RET_LOG(format_.GetIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, val32) && val32 >= 0 &&
714                                  val32 <= static_cast<int32_t>(VideoRotation::VIDEO_ROTATION_270),
715                                  AVCS_ERR_INVALID_VAL, "Invalid rotation angle %{public}d", val32);
716         sInfo_.surface->SetTransform(TranslateSurfaceRotation(static_cast<VideoRotation>(val32)));
717     }
718     return AVCS_ERR_OK;
719 }
720 
RequestSurfaceBufferThread()721 void FCodec::RequestSurfaceBufferThread()
722 {
723     while (!requestBufferThreadExit_.load()) {
724         std::unique_lock<std::mutex> lck(requestBufferMutex_);
725         requestBufferCV_.wait(lck, [this]() {
726             return requestBufferThreadExit_.load() || !requestBufferFinished_.load();
727         });
728         if (requestBufferThreadExit_.load()) {
729             requestBufferFinished_ = true;
730             requestBufferOnceDoneCV_.notify_one();
731             break;
732         }
733         auto index = requestSurfaceBufferQue_->Front();
734         requestSurfaceBufferQue_->Pop();
735         std::shared_ptr<FBuffer> outputBuffer = buffers_[INDEX_OUTPUT][index];
736         std::shared_ptr<FSurfaceMemory> surfaceMemory = outputBuffer->sMemory_;
737         sptr<SurfaceBuffer> surfaceBuffer = surfaceMemory->GetSurfaceBuffer();
738         if (surfaceBuffer == nullptr) {
739             AVCODEC_LOGE("Get surface buffer failed, index=%{public}u", index);
740         } else {
741             requestSucceed_ = true;
742         }
743         requestBufferFinished_ = true;
744         requestBufferOnceDoneCV_.notify_one();
745     }
746     AVCODEC_LOGI("RequestSurfaceBufferThread exit.");
747 }
748 
StartRequestSurfaceBufferThread()749 void FCodec::StartRequestSurfaceBufferThread()
750 {
751     if (!mRequestSurfaceBufferThread_.joinable()) {
752         requestBufferThreadExit_ = false;
753         requestBufferFinished_ = true;
754         mRequestSurfaceBufferThread_ = std::thread(&FCodec::RequestSurfaceBufferThread, this);
755     }
756 }
757 
StopRequestSurfaceBufferThread()758 void FCodec::StopRequestSurfaceBufferThread()
759 {
760     if (mRequestSurfaceBufferThread_.joinable()) {
761         requestBufferThreadExit_ = true;
762         requestBufferFinished_ = false;
763         requestBufferCV_.notify_all();
764         requestBufferFinished_ = true;
765         requestBufferOnceDoneCV_.notify_all();
766         mRequestSurfaceBufferThread_.join();
767     }
768 }
769 
RequestSurfaceBufferOnce(uint32_t index)770 bool FCodec::RequestSurfaceBufferOnce(uint32_t index)
771 {
772     CHECK_AND_RETURN_RET_LOG(!requestBufferThreadExit_.load(), false, "request surfacebuffer thread exited!");
773     std::unique_lock<std::mutex> lck(requestBufferMutex_);
774     requestSucceed_ = false;
775     requestBufferFinished_ = false;
776     requestSurfaceBufferQue_->Push(index);
777     requestBufferCV_.notify_one();
778     requestBufferOnceDoneCV_.wait(lck, [this]() { return requestBufferFinished_.load(); });
779     CHECK_AND_RETURN_RET_LOG(requestSucceed_.load(), false, "fbuffer(%{public}u) request buffer failed!", index);
780     return true;
781 }
782 
AllocateOutputBuffer(int32_t bufferCnt,int32_t outBufferSize)783 int32_t FCodec::AllocateOutputBuffer(int32_t bufferCnt, int32_t outBufferSize)
784 {
785     CHECK_AND_RETURN_RET_LOG(sInfo_.surface == nullptr, AVCS_ERR_UNKNOWN, "Not in buffer mode!");
786     int32_t valBufferCnt = 0;
787     for (int i = 0; i < bufferCnt; i++) {
788         std::shared_ptr<FBuffer> buf = std::make_shared<FBuffer>();
789         buf->width_ = width_;
790         buf->height_ = height_;
791         std::shared_ptr<AVAllocator> allocator =
792             AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
793         CHECK_AND_CONTINUE_LOG(allocator != nullptr, "Output buffer %{public}d allocator is nullptr!", i);
794         buf->avBuffer_ = AVBuffer::CreateAVBuffer(allocator, outBufferSize);
795         CHECK_AND_CONTINUE_LOG(buf->avBuffer_ != nullptr && buf->avBuffer_->memory_ != nullptr,
796                                "Allocate output buffer failed, index=%{public}d", i);
797         AVCODEC_LOGI("Allocate output share buffer success: index=%{public}d, size=%{public}d", i,
798                      buf->avBuffer_->memory_->GetCapacity());
799         CHECK_AND_CONTINUE_LOG(buf->avBuffer_ != nullptr, "Allocate output buffer failed, index=%{public}d", i);
800         buffers_[INDEX_OUTPUT].emplace_back(buf);
801         valBufferCnt++;
802     }
803     CHECK_AND_RETURN_RET_LOGD(valBufferCnt < DEFAULT_MIN_BUFFER_CNT, AVCS_ERR_OK, "Allocate output buffers successful");
804     AVCODEC_LOGE("Allocate output buffer failed: only %{public}d buffer is allocated, no memory", valBufferCnt);
805     buffers_[INDEX_INPUT].clear();
806     buffers_[INDEX_OUTPUT].clear();
807     return AVCS_ERR_NO_MEMORY;
808 }
809 
ClearSurfaceAndSetQueueSize(const sptr<Surface> & surface,int32_t bufferCnt)810 int32_t FCodec::ClearSurfaceAndSetQueueSize(const sptr<Surface> &surface, int32_t bufferCnt)
811 {
812     surface->Connect();
813     surface->CleanCache(); // clean cache will work only if the surface is connected by us.
814     int32_t ret = SetQueueSize(surface, bufferCnt);
815     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Set surface queue size failed!");
816     ret = SetSurfaceCfg();
817     surface->Disconnect();
818     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Set surface cfg failed!");
819     CHECK_AND_RETURN_RET_LOGD(buffers_[INDEX_OUTPUT].size() > 0u, AVCS_ERR_OK, "Set surface cfg & queue size success.");
820     int32_t valBufferCnt = 0;
821     for (auto &it : buffers_[INDEX_OUTPUT]) {
822         std::shared_ptr<FSurfaceMemory> surfaceMemory = it->sMemory_;
823         surfaceMemory->isAttached = false;
824         valBufferCnt++;
825     }
826     CHECK_AND_RETURN_RET_LOG(valBufferCnt == bufferCnt, AVCS_ERR_UNKNOWN, "Outbuf cnt(%{public}d) != %{public}d",
827                              valBufferCnt, bufferCnt);
828     return AVCS_ERR_OK;
829 }
830 
AllocateOutputBuffersFromSurface(int32_t bufferCnt)831 int32_t FCodec::AllocateOutputBuffersFromSurface(int32_t bufferCnt)
832 {
833     CHECK_AND_RETURN_RET_LOG(sInfo_.surface != nullptr, AVCS_ERR_UNKNOWN, "Not in surface mode!");
834     int32_t ret = ClearSurfaceAndSetQueueSize(sInfo_.surface, bufferCnt);
835     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Clean surface and set queue size failed!");
836     requestSurfaceBufferQue_->Clear();
837     requestSurfaceBufferQue_->SetActive(true);
838     StartRequestSurfaceBufferThread();
839     for (int32_t i = 0; i < bufferCnt; i++) {
840         std::shared_ptr<FSurfaceMemory> surfaceMemory = std::make_shared<FSurfaceMemory>(&sInfo_, fDecInfo_);
841         CHECK_AND_RETURN_RET_LOG(surfaceMemory != nullptr, AVCS_ERR_UNKNOWN, "Creata surface memory failed!");
842         ret = surfaceMemory->AllocSurfaceBuffer(width_, height_);
843         CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Alloc surface buffer failed!");
844         sptr<SurfaceBuffer> surfaceBuffer = surfaceMemory->GetSurfaceBuffer();
845         CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, AVCS_ERR_UNKNOWN, "surface buf(%{public}u) is null.", i);
846         ret = Attach(surfaceBuffer);
847         CHECK_AND_CONTINUE_LOG(ret == AVCS_ERR_OK, "surface buf(%{public}u) attach to surface failed.", i);
848         surfaceMemory->isAttached = true;
849         std::shared_ptr<FBuffer> buf = std::make_shared<FBuffer>();
850         CHECK_AND_RETURN_RET_LOG(buf != nullptr, AVCS_ERR_UNKNOWN, "Creata output buffer failed!");
851         buf->sMemory_ = surfaceMemory;
852         buf->height_ = height_;
853         buf->width_ = width_;
854         outAVBuffer4Surface_.emplace_back(AVBuffer::CreateAVBuffer());
855         buf->avBuffer_ = AVBuffer::CreateAVBuffer(buf->sMemory_->GetBase(), buf->sMemory_->GetSize());
856         AVCODEC_LOGI("Allocate output surface buffer success, index=%{public}d, size=%{public}d, stride=%{public}d", i,
857                      buf->sMemory_->GetSize(), buf->sMemory_->GetSurfaceBufferStride());
858         buffers_[INDEX_OUTPUT].emplace_back(buf);
859     }
860     int32_t outputBufferNum = static_cast<int32_t>(buffers_[INDEX_OUTPUT].size());
861     CHECK_AND_RETURN_RET_LOG(outputBufferNum == bufferCnt, AVCS_ERR_UNKNOWN,
862                              "Only alloc %{public}d buffers, less %{public}d", outputBufferNum, bufferCnt);
863     return AVCS_ERR_OK;
864 }
865 
AllocateBuffers()866 int32_t FCodec::AllocateBuffers()
867 {
868     AVCODEC_SYNC_TRACE;
869     CalculateBufferSize();
870     CHECK_AND_RETURN_RET_LOG(inputBufferSize_ > 0 && outputBufferSize_ > 0, AVCS_ERR_INVALID_VAL,
871                              "Allocate buffer with input size=%{public}d, output size=%{public}d failed",
872                              inputBufferSize_, outputBufferSize_);
873     if (sInfo_.surface != nullptr && isOutBufSetted_ == false) {
874         format_.PutIntValue(MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, DEFAULT_OUT_SURFACE_CNT);
875     }
876     CHECK_AND_RETURN_RET_LOG(
877         format_.GetIntValue(MediaDescriptionKey::MD_KEY_MAX_INPUT_BUFFER_COUNT, inputBufferCnt_) &&
878         inputBufferCnt_ >= DEFAULT_MIN_BUFFER_CNT, AVCS_ERR_INVALID_VAL,
879         "Invalid input buffer cnt: %{public}d", inputBufferCnt_);
880     CHECK_AND_RETURN_RET_LOG(
881         format_.GetIntValue(MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, outputBufferCnt_) &&
882         outputBufferCnt_ >= DEFAULT_MIN_BUFFER_CNT, AVCS_ERR_INVALID_VAL,
883         "Invalid output buffer cnt: %{public}d", outputBufferCnt_);
884     inputAvailQue_ = std::make_shared<BlockQueue<uint32_t>>("inputAvailQue", inputBufferCnt_);
885     codecAvailQue_ = std::make_shared<BlockQueue<uint32_t>>("codecAvailQue", outputBufferCnt_);
886     if (sInfo_.surface != nullptr) {
887         renderAvailQue_ = std::make_shared<BlockQueue<uint32_t>>("renderAvailQue", outputBufferCnt_);
888         requestSurfaceBufferQue_ = std::make_shared<BlockQueue<uint32_t>>("requestSurfaceBufferQue", outputBufferCnt_);
889     }
890     int32_t ret = AllocateInputBuffer(inputBufferCnt_, inputBufferSize_);
891     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Allocate input buffers failed!");
892     ret = sInfo_.surface ? AllocateOutputBuffersFromSurface(outputBufferCnt_)
893                          : AllocateOutputBuffer(outputBufferCnt_, outputBufferSize_);
894     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Allocate output buffers failed!");
895     return AVCS_ERR_OK;
896 }
897 
UpdateBuffers(uint32_t index,int32_t bufferSize,uint32_t bufferType)898 int32_t FCodec::UpdateBuffers(uint32_t index, int32_t bufferSize, uint32_t bufferType)
899 {
900     int32_t curBufSize = buffers_[bufferType][index]->avBuffer_->memory_->GetCapacity();
901     if (bufferSize != curBufSize) {
902         std::shared_ptr<FBuffer> buf = std::make_shared<FBuffer>();
903         std::shared_ptr<AVAllocator> allocator =
904             AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
905         CHECK_AND_RETURN_RET_LOG(allocator != nullptr, AVCS_ERR_NO_MEMORY, "buffer %{public}d allocator is nullptr",
906                                  index);
907         buf->avBuffer_ = AVBuffer::CreateAVBuffer(allocator, bufferSize);
908         CHECK_AND_RETURN_RET_LOG(buf->avBuffer_ != nullptr, AVCS_ERR_NO_MEMORY,
909                                  "Buffer allocate failed, index=%{public}d", index);
910         AVCODEC_LOGI("update share buffer success: bufferType=%{public}u, index=%{public}d, size=%{public}d",
911                      bufferType, index, buf->avBuffer_->memory_->GetCapacity());
912 
913         if (bufferType == INDEX_INPUT) {
914             buf->owner_ = Owner::OWNED_BY_USER;
915         } else {
916             buf->owner_ = Owner::OWNED_BY_CODEC;
917         }
918         buffers_[bufferType][index] = buf;
919     }
920     return AVCS_ERR_OK;
921 }
922 
UpdateSurfaceMemory(uint32_t index)923 int32_t FCodec::UpdateSurfaceMemory(uint32_t index)
924 {
925     AVCODEC_SYNC_TRACE;
926     std::unique_lock<std::mutex> oLock(outputMutex_);
927     std::shared_ptr<FBuffer> outputBuffer = buffers_[INDEX_OUTPUT][index];
928     oLock.unlock();
929     if (width_ != outputBuffer->width_ || height_ != outputBuffer->height_) {
930         std::shared_ptr<FSurfaceMemory> surfaceMemory = outputBuffer->sMemory_;
931         CHECK_AND_RETURN_RET_LOG(surfaceMemory != nullptr, AVCS_ERR_UNKNOWN, "Surface memory is nullptr!");
932         AVCODEC_LOGI("Update surface memory, width=%{public}d, height=%{public}d", width_, height_);
933         std::lock_guard<std::mutex> sLock(surfaceMutex_);
934         if (surfaceMemory->isAttached) {
935             sptr<SurfaceBuffer> surfaceBuffer = surfaceMemory->GetSurfaceBuffer();
936             CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, AVCS_ERR_UNKNOWN, "Get surface buffer failed!");
937             int32_t ret = Detach(surfaceBuffer);
938             CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Surface buffer detach failed!");
939             surfaceMemory->isAttached = false;
940         }
941         surfaceMemory->ReleaseSurfaceBuffer();
942         int32_t ret = surfaceMemory->AllocSurfaceBuffer(width_, height_);
943         CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Alloc surface buffer failed!");
944         sptr<SurfaceBuffer> newSurfaceBuffer = surfaceMemory->GetSurfaceBuffer();
945         CHECK_AND_RETURN_RET_LOG(newSurfaceBuffer != nullptr, AVCS_ERR_UNKNOWN, "Alloc surface buffer failed!");
946         ret = Attach(newSurfaceBuffer);
947         CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Surface buffer attach failed!");
948         surfaceMemory->isAttached = true;
949         outputBuffer->avBuffer_ =
950             AVBuffer::CreateAVBuffer(outputBuffer->sMemory_->GetBase(), outputBuffer->sMemory_->GetSize());
951         outputBuffer->width_ = width_;
952         outputBuffer->height_ = height_;
953     }
954     return AVCS_ERR_OK;
955 }
956 
CheckFormatChange(uint32_t index,int width,int height)957 int32_t FCodec::CheckFormatChange(uint32_t index, int width, int height)
958 {
959     if (width_ != width || height_ != height) {
960         AVCODEC_LOGI("format change, width: %{public}d->%{public}d, height: %{public}d->%{public}d", width_, width,
961                      height_, height);
962         width_ = width;
963         height_ = height;
964         ResetData();
965         scale_ = nullptr;
966         CalculateBufferSize();
967         {
968             std::lock_guard<std::mutex> lock(formatMutex_);
969             format_.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width_);
970             format_.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height_);
971             format_.PutIntValue(OHOS::Media::Tag::VIDEO_STRIDE,
972                                 outputPixelFmt_ == VideoPixelFormat::RGBA ? width_ * VIDEO_PIX_DEPTH_RGBA : width_);
973             format_.PutIntValue(OHOS::Media::Tag::VIDEO_SLICE_HEIGHT, height_);
974             format_.PutIntValue(OHOS::Media::Tag::VIDEO_PIC_WIDTH, width_);
975             format_.PutIntValue(OHOS::Media::Tag::VIDEO_PIC_HEIGHT, height_);
976         }
977         if (sInfo_.surface) {
978             std::lock_guard<std::mutex> sLock(surfaceMutex_);
979             sInfo_.requestConfig.width = width_;
980             sInfo_.requestConfig.height = height_;
981         }
982         callback_->OnOutputFormatChanged(format_);
983     }
984     if (sInfo_.surface == nullptr) {
985         std::lock_guard<std::mutex> oLock(outputMutex_);
986         CHECK_AND_RETURN_RET_LOG((UpdateBuffers(index, outputBufferSize_, INDEX_OUTPUT) == AVCS_ERR_OK),
987                                  AVCS_ERR_NO_MEMORY, "Update  output buffer failed, index=%{public}u", index);
988     } else {
989         CHECK_AND_RETURN_RET_LOG((UpdateSurfaceMemory(index) == AVCS_ERR_OK), AVCS_ERR_NO_MEMORY,
990                                  "Update buffer failed");
991     }
992     return AVCS_ERR_OK;
993 }
994 
ReleaseBuffers()995 void FCodec::ReleaseBuffers()
996 {
997     ResetData();
998     if (!isBufferAllocated_) {
999         return;
1000     }
1001 
1002     inputAvailQue_->Clear();
1003     std::unique_lock<std::mutex> iLock(inputMutex_);
1004     buffers_[INDEX_INPUT].clear();
1005     inputBufferCnt_ = 0;
1006     synIndex_ = std::nullopt;
1007     iLock.unlock();
1008 
1009     codecAvailQue_->Clear();
1010     if (sInfo_.surface != nullptr) {
1011         StopRequestSurfaceBufferThread();
1012         renderAvailQue_->Clear();
1013         requestSurfaceBufferQue_->Clear();
1014         std::unique_lock<std::mutex> mLock(renderBufferMapMutex_);
1015         renderSurfaceBufferMap_.clear();
1016         mLock.unlock();
1017         std::lock_guard<std::mutex> oLock(outputMutex_);
1018         for (uint32_t i = 0; i < buffers_[INDEX_OUTPUT].size(); i++) {
1019             std::shared_ptr<FBuffer> outputBuffer = buffers_[INDEX_OUTPUT][i];
1020             if (outputBuffer->owner_ == Owner::OWNED_BY_CODEC) {
1021                 std::shared_ptr<FSurfaceMemory> surfaceMemory = outputBuffer->sMemory_;
1022                 surfaceMemory->ReleaseSurfaceBuffer();
1023                 outputBuffer->owner_ = Owner::OWNED_BY_SURFACE;
1024             }
1025         }
1026         sInfo_.surface->CleanCache();
1027         AVCODEC_LOGI("surface cleancache success");
1028     }
1029     std::unique_lock<std::mutex> oLock(outputMutex_);
1030     buffers_[INDEX_OUTPUT].clear();
1031     outAVBuffer4Surface_.clear();
1032     outputBufferCnt_ = 0;
1033     oLock.unlock();
1034     isBufferAllocated_ = false;
1035 }
1036 
QueueInputBuffer(uint32_t index)1037 int32_t FCodec::QueueInputBuffer(uint32_t index)
1038 {
1039     AVCODEC_SYNC_TRACE;
1040     CHECK_AND_RETURN_RET_LOG(state_ == State::RUNNING, AVCS_ERR_INVALID_STATE,
1041                              "Queue input buffer failed: not in Running state");
1042     CHECK_AND_RETURN_RET_LOG(index < buffers_[INDEX_INPUT].size(), AVCS_ERR_INVALID_VAL,
1043                              "Queue input buffer failed with bad index, index=%{public}u, buffer_size=%{public}zu",
1044                              index, buffers_[INDEX_INPUT].size());
1045     std::shared_ptr<FBuffer> inputBuffer = buffers_[INDEX_INPUT][index];
1046     CHECK_AND_RETURN_RET_LOG(inputBuffer->owner_ == Owner::OWNED_BY_USER, AVCS_ERR_INVALID_OPERATION,
1047                              "Queue input buffer failed: buffer with index=%{public}u is not available", index);
1048 
1049     inputBuffer->owner_ = Owner::OWNED_BY_CODEC;
1050     std::shared_ptr<AVBuffer> &inputAVBuffer = inputBuffer->avBuffer_;
1051     if (synIndex_) {
1052         const std::shared_ptr<AVBuffer> &curAVBuffer = buffers_[INDEX_INPUT][synIndex_.value()]->avBuffer_;
1053         int32_t curAVBufferSize = curAVBuffer->memory_->GetSize();
1054         int32_t inputAVBufferSize = inputAVBuffer->memory_->GetSize();
1055         if ((curAVBufferSize + inputAVBufferSize <= curAVBuffer->memory_->GetCapacity()) &&
1056             memcpy_s(curAVBuffer->memory_->GetAddr() + curAVBufferSize, inputAVBufferSize,
1057                      inputAVBuffer->memory_->GetAddr(), inputAVBufferSize) == EOK) {
1058             curAVBuffer->memory_->SetSize(curAVBufferSize + inputAVBufferSize);
1059             curAVBuffer->flag_ = inputAVBuffer->flag_;
1060             curAVBuffer->pts_ = inputAVBuffer->pts_;
1061 
1062             if (inputAVBuffer->flag_ != AVCODEC_BUFFER_FLAG_CODEC_DATA &&
1063                 inputAVBuffer->flag_ != AVCODEC_BUFFER_FLAG_PARTIAL_FRAME) {
1064                 inputAvailQue_->Push(synIndex_.value());
1065                 synIndex_ = std::nullopt;
1066             }
1067             inputBuffer->owner_ = Owner::OWNED_BY_USER;
1068             callback_->OnInputBufferAvailable(index, inputAVBuffer);
1069             return AVCS_ERR_OK;
1070         } else {
1071             AVCODEC_LOGE("packet size %{public}d over buffer size %{public}d", curAVBufferSize + inputAVBufferSize,
1072                          curAVBuffer->memory_->GetCapacity());
1073             callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_NO_MEMORY);
1074             state_ = State::ERROR;
1075             return AVCS_ERR_NO_MEMORY;
1076         }
1077     } else {
1078         if ((inputAVBuffer->flag_ == AVCODEC_BUFFER_FLAG_CODEC_DATA) ||
1079             (inputAVBuffer->flag_ == AVCODEC_BUFFER_FLAG_PARTIAL_FRAME)) {
1080             synIndex_ = index;
1081         } else {
1082             inputAvailQue_->Push(index);
1083         }
1084     }
1085 
1086     return AVCS_ERR_OK;
1087 }
1088 
SendFrame()1089 void FCodec::SendFrame()
1090 {
1091     CHECK_AND_RETURN_LOG_LIMIT(state_ != State::STOPPING && state_ != State::FLUSHING, LOG_FREQUENCE, "Invalid state");
1092     if (state_ != State::RUNNING || isSendEos_) {
1093         std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TRY_DECODE_TIME));
1094         return;
1095     }
1096     uint32_t index = inputAvailQue_->Front();
1097     CHECK_AND_RETURN_LOG(state_ == State::RUNNING, "Not in running state");
1098     std::shared_ptr<FBuffer> &inputBuffer = buffers_[INDEX_INPUT][index];
1099     std::shared_ptr<AVBuffer> &inputAVBuffer = inputBuffer->avBuffer_;
1100     if (inputAVBuffer->flag_ & AVCODEC_BUFFER_FLAG_EOS) {
1101         avPacket_->data = nullptr;
1102         avPacket_->size = 0;
1103         avPacket_->pts = 0;
1104         std::unique_lock<std::mutex> sendLock(sendMutex_);
1105         isSendEos_ = true;
1106         sendCv_.wait_for(sendLock, std::chrono::milliseconds(DEFAULT_DECODE_WAIT_TIME));
1107         AVCODEC_LOGI("Send eos end");
1108     } else {
1109         avPacket_->data = inputAVBuffer->memory_->GetAddr();
1110         avPacket_->size = static_cast<int32_t>(inputAVBuffer->memory_->GetSize());
1111         avPacket_->pts = inputAVBuffer->pts_;
1112     }
1113     std::unique_lock<std::mutex> sLock(syncMutex_);
1114     int ret = avcodec_send_packet(avCodecContext_.get(), avPacket_.get());
1115     sLock.unlock();
1116     if (ret == 0 || ret == AVERROR_INVALIDDATA) {
1117         EXPECT_AND_LOGW(ret == AVERROR_INVALIDDATA, "ffmpeg ret = %{public}s", AVStrError(ret).c_str());
1118         std::unique_lock<std::mutex> recvLock(recvMutex_);
1119         recvCv_.notify_one();
1120         recvLock.unlock();
1121         inputAvailQue_->Pop();
1122         inputBuffer->owner_ = Owner::OWNED_BY_USER;
1123 #ifdef BUILD_ENG_VERSION
1124         if (dumpInFile_ && dumpInFile_->is_open()) {
1125             dumpInFile_->write(reinterpret_cast<char *>(inputAVBuffer->memory_->GetAddr()),
1126                                static_cast<int32_t>(inputAVBuffer->memory_->GetSize()));
1127         }
1128 #endif // BUILD_ENG_VERSION
1129         callback_->OnInputBufferAvailable(index, inputAVBuffer);
1130     } else if (ret == AVERROR(EAGAIN)) {
1131         std::unique_lock<std::mutex> sendLock(sendMutex_);
1132         isSendWait_ = true;
1133         sendCv_.wait_for(sendLock, std::chrono::milliseconds(DEFAULT_DECODE_WAIT_TIME));
1134     } else {
1135         AVCODEC_LOGE("Cannot send frame to codec: ffmpeg ret = %{public}s", AVStrError(ret).c_str());
1136         callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN);
1137         state_ = State::ERROR;
1138     }
1139 }
1140 
FillFrameBuffer(const std::shared_ptr<FBuffer> & frameBuffer)1141 int32_t FCodec::FillFrameBuffer(const std::shared_ptr<FBuffer> &frameBuffer)
1142 {
1143     VideoPixelFormat targetPixelFmt = outputPixelFmt_;
1144     if (outputPixelFmt_ == VideoPixelFormat::UNKNOWN) {
1145         targetPixelFmt = sInfo_.surface ? VideoPixelFormat::NV12 : ConvertPixelFormatFromFFmpeg(cachedFrame_->format);
1146     }
1147     AVPixelFormat ffmpegFormat = ConvertPixelFormatToFFmpeg(targetPixelFmt);
1148     int32_t ret;
1149     if (ffmpegFormat == static_cast<AVPixelFormat>(cachedFrame_->format)) {
1150         for (int32_t i = 0; i < AV_NUM_DATA_POINTERS && cachedFrame_->linesize[i] > 0; i++) {
1151             scaleData_[i] = cachedFrame_->data[i];
1152             scaleLineSize_[i] = cachedFrame_->linesize[i];
1153         }
1154     } else {
1155         ret = ConvertVideoFrame(&scale_, cachedFrame_, scaleData_, scaleLineSize_, ffmpegFormat);
1156         CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Scale video frame failed: %{public}d", ret);
1157         isConverted_ = true;
1158     }
1159     {
1160         std::lock_guard<std::mutex> lock(formatMutex_);
1161         format_.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, static_cast<int32_t>(targetPixelFmt));
1162     }
1163     std::shared_ptr<AVMemory> &bufferMemory = frameBuffer->avBuffer_->memory_;
1164     CHECK_AND_RETURN_RET_LOG(bufferMemory != nullptr, AVCS_ERR_INVALID_VAL, "bufferMemory is nullptr");
1165     bufferMemory->SetSize(0);
1166     if (sInfo_.surface) {
1167         struct SurfaceInfo surfaceInfo;
1168         surfaceInfo.surfaceStride = static_cast<uint32_t>(frameBuffer->sMemory_->GetSurfaceBufferStride());
1169         surfaceInfo.surfaceFence = frameBuffer->sMemory_->GetFence();
1170         surfaceInfo.scaleData = scaleData_;
1171         surfaceInfo.scaleLineSize = scaleLineSize_;
1172         ret = WriteSurfaceData(bufferMemory, surfaceInfo, format_);
1173     } else {
1174         ret = WriteBufferData(bufferMemory, scaleData_, scaleLineSize_, format_);
1175     }
1176     frameBuffer->avBuffer_->pts_ = cachedFrame_->pts;
1177     AVCODEC_LOGD("Fill frame buffer successful");
1178     return ret;
1179 }
1180 
FramePostProcess(std::shared_ptr<FBuffer> & frameBuffer,uint32_t index,int32_t status,int ret)1181 void FCodec::FramePostProcess(std::shared_ptr<FBuffer> &frameBuffer, uint32_t index, int32_t status, int ret)
1182 {
1183     if (status == AVCS_ERR_OK) {
1184         codecAvailQue_->Pop();
1185         frameBuffer->owner_ = Owner::OWNED_BY_USER;
1186         if (sInfo_.surface) {
1187             outAVBuffer4Surface_[index]->pts_ = frameBuffer->avBuffer_->pts_;
1188             outAVBuffer4Surface_[index]->flag_ = frameBuffer->avBuffer_->flag_;
1189         }
1190         if (ret == AVERROR_EOF) {
1191             std::unique_lock<std::mutex> sLock(syncMutex_);
1192             avcodec_flush_buffers(avCodecContext_.get());
1193             sLock.unlock();
1194         } else {
1195             if (isSendWait_) {
1196                 std::lock_guard<std::mutex> sLock(sendMutex_);
1197                 isSendWait_ = false;
1198                 sendCv_.notify_one();
1199             }
1200         }
1201         callback_->OnOutputBufferAvailable(index,
1202                                            sInfo_.surface ? outAVBuffer4Surface_[index] : frameBuffer->avBuffer_);
1203     } else if (status == AVCS_ERR_UNSUPPORT) {
1204         AVCODEC_LOGE("Recevie frame from codec failed: OnError");
1205         callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNSUPPORT);
1206         state_ = State::ERROR;
1207     } else {
1208         AVCODEC_LOGE("Recevie frame from codec failed");
1209         callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN);
1210         state_ = State::ERROR;
1211     }
1212 }
1213 
DumpOutputBuffer()1214 void FCodec::DumpOutputBuffer()
1215 {
1216     AVCODEC_LOGD("cur decNum: %{public}u", decNum_);
1217     if (decNum_ == 0) {
1218         callback_->OnOutputFormatChanged(format_);
1219     }
1220     decNum_++;
1221 #ifdef BUILD_ENG_VERSION
1222     if (!dumpOutFile_ || !dumpOutFile_->is_open()) {
1223         return;
1224     }
1225     for (int32_t i = 0; i < cachedFrame_->height; i++) {
1226         dumpOutFile_->write(reinterpret_cast<char *>(cachedFrame_->data[0] + i * cachedFrame_->linesize[0]),
1227                             static_cast<int32_t>(cachedFrame_->width));
1228     }
1229     for (int32_t i = 0; i < cachedFrame_->height / 2; i++) { // 2
1230         dumpOutFile_->write(reinterpret_cast<char *>(cachedFrame_->data[1] + i * cachedFrame_->linesize[1]),
1231                             static_cast<int32_t>(cachedFrame_->width / 2)); // 2
1232     }
1233     for (int32_t i = 0; i < cachedFrame_->height / 2; i++) { // 2
1234         dumpOutFile_->write(reinterpret_cast<char *>(cachedFrame_->data[2] + i * cachedFrame_->linesize[2]),
1235                             static_cast<int32_t>(cachedFrame_->width / 2)); // 2
1236     }
1237 #endif // BUILD_ENG_VERSION
1238 }
1239 
ReceiveFrame()1240 void FCodec::ReceiveFrame()
1241 {
1242     CHECK_AND_RETURN_LOG_LIMIT(state_ != State::STOPPING && state_ != State::FLUSHING, LOG_FREQUENCE, "Invalid state");
1243     if (state_ != State::RUNNING || codecAvailQue_->Size() == 0u) {
1244         std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TRY_DECODE_TIME));
1245         return;
1246     }
1247     auto index = codecAvailQue_->Front();
1248     CHECK_AND_RETURN_LOG(state_ == State::RUNNING, "Not in running state");
1249     std::shared_ptr<FBuffer> frameBuffer = buffers_[INDEX_OUTPUT][index];
1250     std::unique_lock<std::mutex> sLock(syncMutex_);
1251     int ret = avcodec_receive_frame(avCodecContext_.get(), cachedFrame_.get());
1252     sLock.unlock();
1253     int32_t status = AVCS_ERR_OK;
1254     CHECK_AND_RETURN_LOG(ret != AVERROR_INVALIDDATA, "ffmpeg ret = %{public}s", AVStrError(ret).c_str());
1255     if (ret >= 0) {
1256         DumpOutputBuffer();
1257         if (CheckFormatChange(index, cachedFrame_->width, cachedFrame_->height) == AVCS_ERR_OK) {
1258             CHECK_AND_RETURN_LOG(state_ == State::RUNNING, "Not in running state");
1259             frameBuffer = buffers_[INDEX_OUTPUT][index];
1260             status = FillFrameBuffer(frameBuffer);
1261         } else {
1262             CHECK_AND_RETURN_LOG(state_ == State::RUNNING, "Not in running state");
1263             callback_->OnError(AVCODEC_ERROR_EXTEND_START, AVCS_ERR_NO_MEMORY);
1264             return;
1265         }
1266         frameBuffer->avBuffer_->flag_ = AVCODEC_BUFFER_FLAG_NONE;
1267     } else if (ret == AVERROR_EOF) {
1268         AVCODEC_LOGI("Receive eos");
1269         frameBuffer->avBuffer_->flag_ = AVCODEC_BUFFER_FLAG_EOS;
1270         frameBuffer->avBuffer_->memory_->SetSize(0);
1271         state_ = State::EOS;
1272     } else if (ret == AVERROR(EAGAIN)) {
1273         std::unique_lock<std::mutex> sendLock(sendMutex_);
1274         if (isSendWait_ || isSendEos_) {
1275             isSendWait_ = false;
1276             sendCv_.notify_one();
1277         }
1278         sendLock.unlock();
1279         std::unique_lock<std::mutex> recvLock(recvMutex_);
1280         recvCv_.wait_for(recvLock, std::chrono::milliseconds(DEFAULT_DECODE_WAIT_TIME));
1281         return;
1282     } else {
1283         AVCODEC_LOGE("Cannot recv frame from codec: ffmpeg ret = %{public}s", AVStrError(ret).c_str());
1284         callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN);
1285         state_ = State::ERROR;
1286         return;
1287     }
1288     FramePostProcess(frameBuffer, index, status, ret);
1289 }
1290 
FindAvailIndex(uint32_t index)1291 void FCodec::FindAvailIndex(uint32_t index)
1292 {
1293     uint32_t curQueSize = renderAvailQue_->Size();
1294     for (uint32_t i = 0u; i < curQueSize; i++) {
1295         uint32_t num = renderAvailQue_->Pop();
1296         if (num == index) {
1297             break;
1298         } else {
1299             renderAvailQue_->Push(num);
1300         }
1301     }
1302 }
1303 
ReleaseOutputBuffer(uint32_t index)1304 int32_t FCodec::ReleaseOutputBuffer(uint32_t index)
1305 {
1306     AVCODEC_SYNC_TRACE;
1307     std::unique_lock<std::mutex> oLock(outputMutex_);
1308     CHECK_AND_RETURN_RET_LOG(index < buffers_[INDEX_OUTPUT].size(), AVCS_ERR_INVALID_VAL,
1309                              "Failed to release output buffer: invalid index");
1310     std::shared_ptr<FBuffer> frameBuffer = buffers_[INDEX_OUTPUT][index];
1311     oLock.unlock();
1312     if (frameBuffer->owner_ == Owner::OWNED_BY_USER) {
1313         frameBuffer->owner_ = Owner::OWNED_BY_CODEC;
1314         codecAvailQue_->Push(index);
1315         return AVCS_ERR_OK;
1316     } else {
1317         AVCODEC_LOGE("Release output buffer failed: check your index=%{public}u", index);
1318         return AVCS_ERR_INVALID_VAL;
1319     }
1320 }
1321 
Attach(sptr<SurfaceBuffer> surfaceBuffer)1322 int32_t FCodec::Attach(sptr<SurfaceBuffer> surfaceBuffer)
1323 {
1324     int32_t err = sInfo_.surface->AttachBufferToQueue(surfaceBuffer);
1325     CHECK_AND_RETURN_RET_LOG(
1326         err == 0, err, "Surface(%{public}" PRIu64 "), attach buffer(%{public}u) to queue failed, GSError=%{public}d",
1327         sInfo_.surface->GetUniqueId(), surfaceBuffer->GetSeqNum(), err);
1328     return AVCS_ERR_OK;
1329 }
1330 
Detach(sptr<SurfaceBuffer> surfaceBuffer)1331 int32_t FCodec::Detach(sptr<SurfaceBuffer> surfaceBuffer)
1332 {
1333     int32_t err = sInfo_.surface->DetachBufferFromQueue(surfaceBuffer);
1334     CHECK_AND_RETURN_RET_LOG(
1335         err == 0, err, "Surface(%{public}" PRIu64 "), detach buffer(%{public}u) to queue failed, GSError=%{public}d",
1336         sInfo_.surface->GetUniqueId(), surfaceBuffer->GetSeqNum(), err);
1337     return AVCS_ERR_OK;
1338 }
1339 
FlushSurfaceMemory(std::shared_ptr<FSurfaceMemory> & surfaceMemory,uint32_t index)1340 int32_t FCodec::FlushSurfaceMemory(std::shared_ptr<FSurfaceMemory> &surfaceMemory, uint32_t index)
1341 {
1342     sptr<SurfaceBuffer> surfaceBuffer = surfaceMemory->GetSurfaceBuffer();
1343     CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, AVCS_ERR_UNKNOWN, "Get surface buffer failed!");
1344     if (!surfaceMemory->isAttached) {
1345         int32_t ret = Attach(surfaceBuffer);
1346         CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Surface buffer attach failed!");
1347         surfaceMemory->isAttached = true;
1348     }
1349     OHOS::BufferFlushConfig flushConfig = {{0, 0, surfaceBuffer->GetWidth(), surfaceBuffer->GetHeight()},
1350         outAVBuffer4Surface_[index]->pts_, -1};
1351     if (outAVBuffer4Surface_[index]->meta_->Find(OHOS::Media::Tag::VIDEO_DECODER_DESIRED_PRESENT_TIMESTAMP) !=
1352         outAVBuffer4Surface_[index]->meta_->end()) {
1353         outAVBuffer4Surface_[index]->meta_->Get<OHOS::Media::Tag::VIDEO_DECODER_DESIRED_PRESENT_TIMESTAMP>(
1354             flushConfig.desiredPresentTimestamp);
1355         outAVBuffer4Surface_[index]->meta_->Remove(OHOS::Media::Tag::VIDEO_DECODER_DESIRED_PRESENT_TIMESTAMP);
1356     }
1357     auto res = sInfo_.surface->FlushBuffer(surfaceBuffer, -1, flushConfig);
1358     if (res == GSERROR_BUFFER_NOT_INCACHE) {
1359         AVCODEC_LOGW("Surface(%{public}" PRIu64 "), flush buffer(seq=%{public}u) failed, try to recover",
1360                      sInfo_.surface->GetUniqueId(), surfaceBuffer->GetSeqNum());
1361         int32_t ret = ClearSurfaceAndSetQueueSize(sInfo_.surface, outputBufferCnt_);
1362         CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Clean surface and set queue size failed!");
1363         ret = Attach(surfaceBuffer);
1364         CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Surface buffer attach failed!");
1365         surfaceMemory->isAttached = true;
1366         res = sInfo_.surface->FlushBuffer(surfaceBuffer, -1, flushConfig);
1367     }
1368     surfaceMemory->owner = Owner::OWNED_BY_SURFACE;
1369     if (res != OHOS::SurfaceError::SURFACE_ERROR_OK) {
1370         AVCODEC_LOGW("Failed to update surface memory: %{public}d", res);
1371         return AVCS_ERR_UNKNOWN;
1372     }
1373     {
1374         std::lock_guard<std::mutex> mLock(renderBufferMapMutex_);
1375         renderSurfaceBufferMap_[index] = std::make_pair(surfaceBuffer, flushConfig);
1376     }
1377     renderAvailQue_->Push(index);
1378     return AVCS_ERR_OK;
1379 }
1380 
RenderOutputBuffer(uint32_t index)1381 int32_t FCodec::RenderOutputBuffer(uint32_t index)
1382 {
1383     AVCODEC_SYNC_TRACE;
1384     CHECK_AND_RETURN_RET_LOG(sInfo_.surface != nullptr, AVCS_ERR_UNSUPPORT,
1385                              "Render output buffer failed, surface is nullptr!");
1386     std::unique_lock<std::mutex> oLock(outputMutex_);
1387     CHECK_AND_RETURN_RET_LOG(index < buffers_[INDEX_OUTPUT].size(), AVCS_ERR_INVALID_VAL,
1388                              "Failed to render output buffer: invalid index");
1389     std::shared_ptr<FBuffer> frameBuffer = buffers_[INDEX_OUTPUT][index];
1390     oLock.unlock();
1391     std::lock_guard<std::mutex> sLock(surfaceMutex_);
1392     std::shared_ptr<AVMemory> &bufferMemory = frameBuffer->avBuffer_->memory_;
1393     CHECK_AND_RETURN_RET_LOG(bufferMemory != nullptr, AVCS_ERR_INVALID_VAL, "bufferMemory is nullptr");
1394     int32_t size = bufferMemory->GetSize();
1395     CHECK_AND_RETURN_RET_LOGW(size > 0, AVCS_ERR_OK, "buf(%{public}u) size=%{public}d", index, size);
1396     if (frameBuffer->owner_ == Owner::OWNED_BY_USER) {
1397         std::shared_ptr<FSurfaceMemory> surfaceMemory = frameBuffer->sMemory_;
1398         int32_t ret = FlushSurfaceMemory(surfaceMemory, index);
1399         EXPECT_AND_LOGW(ret != AVCS_ERR_OK, "Flush surface memory(index=%{public}u) failed: %{public}d", index, ret);
1400         frameBuffer->owner_ = Owner::OWNED_BY_SURFACE;
1401         AVCODEC_LOGD("Render output buffer with index, index=%{public}u", index);
1402         return AVCS_ERR_OK;
1403     } else {
1404         AVCODEC_LOGE("Failed to render output buffer with bad index, index=%{public}u", index);
1405         return AVCS_ERR_INVALID_VAL;
1406     }
1407 }
1408 
ReplaceOutputSurfaceWhenRunning(sptr<Surface> newSurface)1409 int32_t FCodec::ReplaceOutputSurfaceWhenRunning(sptr<Surface> newSurface)
1410 {
1411     CHECK_AND_RETURN_RET_LOG(sInfo_.surface != nullptr, AV_ERR_OPERATE_NOT_PERMIT,
1412                              "Not support convert from AVBuffer Mode to Surface Mode");
1413     sptr<Surface> oldSurface = sInfo_.surface;
1414     uint64_t oldId = oldSurface->GetUniqueId();
1415     uint64_t newId = newSurface->GetUniqueId();
1416     AVCODEC_LOGI("Begin to switch surface %{public}" PRIu64 " -> %{public}" PRIu64 ".", oldId, newId);
1417     if (oldId == newId) {
1418         return AVCS_ERR_OK;
1419     }
1420     int32_t ret = RegisterListenerToSurface(newSurface);
1421     CHECK_AND_RETURN_RET_LOG(ret == GSERROR_OK, ret,
1422         "surface %{public}" PRIu64 ", RegisterListenerToSurface failed, GSError=%{public}d", newId, ret);
1423     int32_t outputBufferCnt = 0;
1424     CHECK_AND_RETURN_RET_LOG(
1425         format_.GetIntValue(MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, outputBufferCnt) &&
1426         outputBufferCnt >= DEFAULT_MIN_BUFFER_CNT, AVCS_ERR_INVALID_VAL,
1427         "Invalid output buffer cnt: %{public}d", outputBufferCnt);
1428     ret = SetQueueSize(newSurface, outputBufferCnt);
1429     if (ret != AVCS_ERR_OK) {
1430         UnRegisterListenerToSurface(newSurface);
1431         return ret;
1432     }
1433     std::unique_lock<std::mutex> sLock(surfaceMutex_);
1434     ret = SwitchBetweenSurface(newSurface);
1435     if (ret != AVCS_ERR_OK) {
1436         UnRegisterListenerToSurface(newSurface);
1437         sInfo_.surface = oldSurface;
1438         CombineConsumerUsage();
1439         return ret;
1440     }
1441     sLock.unlock();
1442     AVCODEC_LOGI("Switch surface %{public}" PRIu64 " -> %{public}" PRIu64 ".", oldId, newId);
1443     return AVCS_ERR_OK;
1444 }
1445 
SetQueueSize(const sptr<Surface> & surface,uint32_t targetSize)1446 int32_t FCodec::SetQueueSize(const sptr<Surface> &surface, uint32_t targetSize)
1447 {
1448     uint64_t surfaceId = surface->GetUniqueId();
1449     int32_t err = surface->SetQueueSize(targetSize);
1450     CHECK_AND_RETURN_RET_LOG(err == 0, err,
1451                              "Surface(%{public}" PRIu64 ") set queue size %{public}u failed, GSError=%{public}d",
1452                              surfaceId, targetSize, err);
1453     AVCODEC_LOGI("Surface(%{public}" PRIu64 ") set queue size %{public}u succss.", surfaceId, targetSize);
1454     return AVCS_ERR_OK;
1455 }
1456 
SwitchBetweenSurface(const sptr<Surface> & newSurface)1457 int32_t FCodec::SwitchBetweenSurface(const sptr<Surface> &newSurface)
1458 {
1459     sptr<Surface> curSurface = sInfo_.surface;
1460     newSurface->Connect(); // cleancache will work only if the surface is connected by us
1461     newSurface->CleanCache(); // make sure new surface is empty
1462     newSurface->Disconnect();
1463     std::vector<uint32_t> ownedBySurfaceBufferIndex;
1464     uint64_t newId = newSurface->GetUniqueId();
1465     for (uint32_t index = 0; index < buffers_[INDEX_OUTPUT].size(); index++) {
1466         if (buffers_[INDEX_OUTPUT][index]->sMemory_ == nullptr) {
1467             continue;
1468         }
1469         sptr<SurfaceBuffer> surfaceBuffer = nullptr;
1470         if (buffers_[INDEX_OUTPUT][index]->owner_ == Owner::OWNED_BY_SURFACE) {
1471             if (renderSurfaceBufferMap_.count(index)) {
1472                 surfaceBuffer = renderSurfaceBufferMap_[index].first;
1473                 ownedBySurfaceBufferIndex.push_back(index);
1474             }
1475         } else {
1476             RequestSurfaceBufferOnce(index);
1477             surfaceBuffer = buffers_[INDEX_OUTPUT][index]->sMemory_->GetSurfaceBuffer();
1478         }
1479         CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, AVCS_ERR_UNKNOWN, "Get old surface buffer error!");
1480         int32_t err = newSurface->AttachBufferToQueue(surfaceBuffer);
1481         CHECK_AND_RETURN_RET_LOG(
1482             err == 0, err, "surface(%{public}" PRIu64 ")attach buffer(seq=%{public}u) to queue failed,"
1483             "GSError=%{public}d", newId, surfaceBuffer->GetSeqNum(), err);
1484         buffers_[INDEX_OUTPUT][index]->sMemory_->isAttached = true;
1485     }
1486     int32_t val32 = 0;
1487     if (format_.ContainKey(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE)) {
1488         CHECK_AND_RETURN_RET_LOG(format_.GetIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, val32) && val32 >= 0 &&
1489                                  val32 <= static_cast<int32_t>(VideoRotation::VIDEO_ROTATION_270),
1490                                  AVCS_ERR_INVALID_VAL, "Invalid rotation angle %{public}d", val32);
1491         sInfo_.surface->SetTransform(TranslateSurfaceRotation(static_cast<VideoRotation>(val32)));
1492     }
1493     sInfo_.surface = newSurface;
1494     CombineConsumerUsage();
1495     for (uint32_t index: ownedBySurfaceBufferIndex) {
1496         int32_t ret = RenderNewSurfaceWithOldBuffer(newSurface, index);
1497         CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Old surface buffer render failed!");
1498     }
1499     UnRegisterListenerToSurface(curSurface);
1500     curSurface->CleanCache(true); // make sure old surface is empty and go black
1501     return AVCS_ERR_OK;
1502 }
1503 
RenderNewSurfaceWithOldBuffer(const sptr<Surface> & newSurface,uint32_t index)1504 int32_t FCodec::RenderNewSurfaceWithOldBuffer(const sptr<Surface> &newSurface, uint32_t index)
1505 {
1506     std::shared_ptr<FSurfaceMemory> surfaceMemory = buffers_[INDEX_OUTPUT][index]->sMemory_;
1507     sptr<SurfaceBuffer> surfaceBuffer = renderSurfaceBufferMap_[index].first;
1508     OHOS::BufferFlushConfig flushConfig = renderSurfaceBufferMap_[index].second;
1509     if (sInfo_.scalingMode >= 0) {
1510         newSurface->SetScalingMode(surfaceBuffer->GetSeqNum(), static_cast<ScalingMode>(sInfo_.scalingMode));
1511     }
1512     auto res = newSurface->FlushBuffer(surfaceBuffer, -1, flushConfig);
1513     if (res != OHOS::SurfaceError::SURFACE_ERROR_OK) {
1514         AVCODEC_LOGE("Failed to update surface memory: %{public}d", res);
1515         return AVCS_ERR_UNKNOWN;
1516     }
1517     return AVCS_ERR_OK;
1518 }
1519 
BufferReleasedByConsumer(uint64_t surfaceId)1520 GSError FCodec::BufferReleasedByConsumer(uint64_t surfaceId)
1521 {
1522     CHECK_AND_RETURN_RET_LOG(state_ == State::RUNNING || state_ == State::EOS || state_ == State::FLUSHING ||
1523                              state_ == State::FLUSHED, GSERROR_NO_PERMISSION, "Invalid state");
1524     std::unique_lock<std::mutex> sLock(surfaceMutex_);
1525     CHECK_AND_RETURN_RET_LOG(renderAvailQue_->Size() > 0, GSERROR_NO_BUFFER, "No available buffer");
1526     CHECK_AND_RETURN_RET_LOG(surfaceId == sInfo_.surface->GetUniqueId(), GSERROR_INVALID_ARGUMENTS,
1527                              "Ignore callback from old surface");
1528     auto index = renderAvailQue_->Front();
1529     RequestSurfaceBufferOnce(index);
1530     std::shared_ptr<FBuffer> outputBuffer = buffers_[INDEX_OUTPUT][index];
1531     std::shared_ptr<FSurfaceMemory> surfaceMemory = outputBuffer->sMemory_;
1532     auto queSize = renderAvailQue_->Size();
1533     uint32_t curIndex = 0;
1534     uint32_t i = 0;
1535     for (i = 0; i < queSize; i++) {
1536         curIndex = renderAvailQue_->Pop();
1537         if (surfaceMemory->GetBase() == buffers_[INDEX_OUTPUT][curIndex]->avBuffer_->memory_->GetAddr() &&
1538             surfaceMemory->GetSize() == buffers_[INDEX_OUTPUT][curIndex]->avBuffer_->memory_->GetCapacity()) {
1539             buffers_[INDEX_OUTPUT][index]->sMemory_ = buffers_[INDEX_OUTPUT][curIndex]->sMemory_;
1540             buffers_[INDEX_OUTPUT][curIndex]->sMemory_ = surfaceMemory;
1541             break;
1542         } else {
1543             renderAvailQue_->Push(curIndex);
1544         }
1545     }
1546     if (i == queSize) {
1547         curIndex = index;
1548         outputBuffer->avBuffer_ = AVBuffer::CreateAVBuffer(surfaceMemory->GetBase(), surfaceMemory->GetSize());
1549         outputBuffer->width_ = width_;
1550         outputBuffer->height_ = height_;
1551         FindAvailIndex(curIndex);
1552     }
1553     buffers_[INDEX_OUTPUT][curIndex]->owner_ = Owner::OWNED_BY_CODEC;
1554     if (state_ == State::RUNNING || state_ == State::EOS) {
1555         codecAvailQue_->Push(curIndex);
1556     }
1557     sLock.unlock();
1558     if (renderSurfaceBufferMap_.count(curIndex)) {
1559         std::lock_guard<std::mutex> mLock(renderBufferMapMutex_);
1560         renderSurfaceBufferMap_.erase(curIndex);
1561     }
1562     AVCODEC_LOGD("Request output buffer success, available index = %{public}u, queSize=%{public}zu, i=%{public}d",
1563                  curIndex, queSize, i);
1564     return GSERROR_OK;
1565 }
1566 
UnRegisterListenerToSurface(const sptr<Surface> & surface)1567 void FCodec::UnRegisterListenerToSurface(const sptr<Surface> &surface)
1568 {
1569     CHECK_AND_RETURN_LOG(surface != nullptr, "Surface is null, not need to unregister listener.");
1570     SurfaceTools::GetInstance().ReleaseSurface(instanceId_, surface, false);
1571 }
1572 
RegisterListenerToSurface(const sptr<Surface> & surface)1573 int32_t FCodec::RegisterListenerToSurface(const sptr<Surface> &surface)
1574 {
1575     uint64_t surfaceId = surface->GetUniqueId();
1576     wptr<FCodec> wp = this;
1577     bool ret =
1578         SurfaceTools::GetInstance().RegisterReleaseListener(instanceId_, surface,
1579             [wp, surfaceId](sptr<SurfaceBuffer> &) {
1580                 sptr<FCodec> codec = wp.promote();
1581                 if (!codec) {
1582                     AVCODEC_LOGD("decoder is nullptr");
1583                     return GSERROR_OK;
1584                 }
1585                 return codec->BufferReleasedByConsumer(surfaceId);
1586             });
1587     CHECK_AND_RETURN_RET_LOG(ret, AVCS_ERR_UNKNOWN, "surface(%" PRIu64 ") register listener failed", surfaceId);
1588     StartRequestSurfaceBufferThread();
1589     return AVCS_ERR_OK;
1590 }
1591 
CombineConsumerUsage()1592 void FCodec::CombineConsumerUsage()
1593 {
1594     uint64_t defaultUsage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA;
1595     uint64_t consumerUsage = sInfo_.surface->GetDefaultUsage();
1596     uint64_t cfgedUsage = sInfo_.requestConfig.usage;
1597     uint64_t finalUsage = defaultUsage | consumerUsage | cfgedUsage;
1598     sInfo_.requestConfig.usage = finalUsage;
1599     AVCODEC_LOGI("Usage: default(0x%{public}" PRIu64 ") | consumer(0x%{public}" PRIu64 ") | cfged(0x%{public}" PRIu64
1600                  ") -> final(0x%{public}" PRIu64 ").",
1601                  defaultUsage, consumerUsage, cfgedUsage, finalUsage);
1602 }
1603 
SetOutputSurface(sptr<Surface> surface)1604 int32_t FCodec::SetOutputSurface(sptr<Surface> surface)
1605 {
1606     AVCODEC_SYNC_TRACE;
1607     CHECK_AND_RETURN_RET_LOG(state_ != State::UNINITIALIZED, AV_ERR_INVALID_VAL,
1608                              "set output surface fail: not initialized or configured");
1609     CHECK_AND_RETURN_RET_LOG((state_ == State::CONFIGURED || state_ == State::FLUSHED ||
1610         state_ == State::RUNNING || state_ == State::EOS), AVCS_ERR_INVALID_STATE,
1611         "set output surface fail: state %{public}d not support set output surface",
1612         static_cast<int32_t>(state_.load()));
1613     if (surface == nullptr || surface->IsConsumer()) {
1614         AVCODEC_LOGE("Set surface fail");
1615         return AVCS_ERR_INVALID_VAL;
1616     }
1617     if (state_ == State::FLUSHED || state_ == State::RUNNING || state_ == State::EOS) {
1618         return ReplaceOutputSurfaceWhenRunning(surface);
1619     }
1620     UnRegisterListenerToSurface(sInfo_.surface);
1621     uint64_t surfaceId = surface->GetUniqueId();
1622     sInfo_.surface = surface;
1623     CombineConsumerUsage();
1624     int32_t ret = RegisterListenerToSurface(sInfo_.surface);
1625     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret,
1626                              "surface(%{public}" PRIu64 ") register listener to surface failed, GSError=%{public}d",
1627                              sInfo_.surface->GetUniqueId(), ret);
1628     AVCODEC_LOGI("%{public}s Set surface(%{public}" PRIu64 ") success.", decName_.c_str(), surfaceId);
1629     return AVCS_ERR_OK;
1630 }
1631 
SetCallback(const std::shared_ptr<MediaCodecCallback> & callback)1632 int32_t FCodec::SetCallback(const std::shared_ptr<MediaCodecCallback> &callback)
1633 {
1634     AVCODEC_SYNC_TRACE;
1635     CHECK_AND_RETURN_RET_LOG(callback != nullptr, AVCS_ERR_INVALID_VAL, "Set callback failed: callback is NULL");
1636     callback_ = callback;
1637     return AVCS_ERR_OK;
1638 }
1639 
1640 // for memory recycle
CanSwapOut(bool isOutputBuffer,std::shared_ptr<FBuffer> & fBuffer)1641 bool FCodec::CanSwapOut(bool isOutputBuffer, std::shared_ptr<FBuffer> &fBuffer)
1642 {
1643     if (!isOutputBuffer) {
1644         AVCODEC_LOGD("Current buffers unsupport.");
1645         return false;
1646     }
1647     std::shared_ptr<FSurfaceMemory> surfaceMemory = fBuffer->sMemory_;
1648     CHECK_AND_RETURN_RET_LOGD(surfaceMemory != nullptr, false, "Current buffer->sMemory error!");
1649     Owner ownerValue = surfaceMemory->owner;
1650     AVCODEC_LOGD("Buffer type: [%{public}u], fBuffer->owner_: [%{public}d], fBuffer->hasSwapedOut_: [%{public}d].",
1651                  isOutputBuffer, ownerValue, fBuffer->hasSwapedOut_);
1652     return !(ownerValue == Owner::OWNED_BY_SURFACE || fBuffer->hasSwapedOut_);
1653 }
1654 
SwapOutBuffers(bool isOutputBuffer,State curState)1655 int32_t FCodec::SwapOutBuffers(bool isOutputBuffer, State curState)
1656 {
1657     uint32_t bufferType = isOutputBuffer ? INDEX_OUTPUT : INDEX_INPUT;
1658     CHECK_AND_RETURN_RET_LOGD(bufferType == INDEX_OUTPUT, AVCS_ERR_OK, "Input buffers can't be swapped out!");
1659     for (uint32_t i = 0u; i < buffers_[bufferType].size(); i++) {
1660         std::shared_ptr<FBuffer> fBuffer = buffers_[bufferType][i];
1661         if (!CanSwapOut(isOutputBuffer, fBuffer)) {
1662             AVCODEC_LOGW("Buf: [%{public}u] can't freeze, owner: [%{public}d] swaped out: [%{public}d]!", i,
1663                          fBuffer->owner_.load(), fBuffer->hasSwapedOut_);
1664             continue;
1665         }
1666         std::shared_ptr<FSurfaceMemory> surfaceMemory = fBuffer->sMemory_;
1667         CHECK_AND_RETURN_RET_LOG(surfaceMemory != nullptr, AVCS_ERR_UNKNOWN, "Buf[%{public}u]->sMemory error!", i);
1668         sptr<SurfaceBuffer> surfaceBuffer = surfaceMemory->GetSurfaceBuffer();
1669         CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, AVCS_ERR_UNKNOWN, "Buf[%{public}u]->surfaceBuf error!", i);
1670         int32_t fd = surfaceBuffer->GetFileDescriptor();
1671         int32_t ret = DmaSwaper::GetInstance().SwapOutDma(pid_, fd);
1672         if (ret != AVCS_ERR_OK) {
1673             AVCODEC_LOGE("Buffer type[%{public}u] bufferId[%{public}u], fd[%{public}d], pid[%{public}d] freeze failed!",
1674                          bufferType, i, fd, pid_);
1675             int32_t errCode = ActiveBuffers();
1676             state_ = curState;
1677             CHECK_AND_RETURN_RET_LOG(errCode == AVCS_ERR_OK, errCode, "Active buffers failed!");
1678             return ret;
1679         }
1680         AVCODEC_LOGI("Buf[%{public}u] fd[%{public}u] swap out success!", i, fd);
1681         fBuffer->hasSwapedOut_ = true;
1682     }
1683     return AVCS_ERR_OK;
1684 }
1685 
SwapInBuffers(bool isOutputBuffer)1686 int32_t FCodec::SwapInBuffers(bool isOutputBuffer)
1687 {
1688     uint32_t bufferType = isOutputBuffer ? INDEX_OUTPUT : INDEX_INPUT;
1689     CHECK_AND_RETURN_RET_LOGD(bufferType == INDEX_OUTPUT, AVCS_ERR_OK, "Input buffers can't be swapped in!");
1690     for (uint32_t i = 0u; i < buffers_[bufferType].size(); i++) {
1691         std::shared_ptr<FBuffer> fBuffer = buffers_[bufferType][i];
1692         if (!fBuffer->hasSwapedOut_) {
1693             continue;
1694         }
1695         std::shared_ptr<FSurfaceMemory> surfaceMemory = fBuffer->sMemory_;
1696         CHECK_AND_CONTINUE_LOG(surfaceMemory != nullptr, "Buf[%{public}u]->sMemory error!", i);
1697         sptr<SurfaceBuffer> surfaceBuffer = surfaceMemory->GetSurfaceBuffer();
1698         CHECK_AND_CONTINUE_LOG(surfaceBuffer != nullptr, "Buf[%{public}u]->surfaceBuf error!", i);
1699         int32_t fd = surfaceBuffer->GetFileDescriptor();
1700         int32_t ret = DmaSwaper::GetInstance().SwapInDma(pid_, fd);
1701         CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Buf[%{public}u] fd[%{public}u] swap in error!", i, fd);
1702         AVCODEC_LOGI("Buf[%{public}u] fd[%{public}u] swap in success!", i, fd);
1703         fBuffer->hasSwapedOut_ = false;
1704     }
1705     return AVCS_ERR_OK;
1706 }
1707 
FreezeBuffers(State curState)1708 int32_t FCodec::FreezeBuffers(State curState)
1709 {
1710     CHECK_AND_RETURN_RET_LOGD(state_ != State::FROZEN, AVCS_ERR_OK, "FCodec had been frozen!");
1711     std::lock_guard<std::mutex> sLock(surfaceMutex_);
1712     int32_t ret = SwapOutBuffers(INDEX_INPUT, curState);
1713     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Input buffers swap out failed!");
1714     ret = SwapOutBuffers(INDEX_OUTPUT, curState);
1715     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Output buffers swap out failed!");
1716     return AVCS_ERR_OK;
1717 }
1718 
ActiveBuffers()1719 int32_t FCodec::ActiveBuffers()
1720 {
1721     CHECK_AND_RETURN_RET_LOGD(state_ == State::FREEZING || state_ == State::FROZEN, AVCS_ERR_INVALID_STATE,
1722                               "Only freezing or frozen state can swap in dma buffer!");
1723     int32_t ret = SwapInBuffers(INDEX_INPUT);
1724     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Input buffers swap in failed!");
1725     ret = SwapInBuffers(INDEX_OUTPUT);
1726     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Output buffers swap in failed!");
1727     return AVCS_ERR_OK;
1728 }
1729 
NotifyMemoryRecycle()1730 int32_t FCodec::NotifyMemoryRecycle()
1731 {
1732     CHECK_AND_RETURN_RET_LOG(sInfo_.surface != nullptr, AVCS_ERR_UNKNOWN, "Only surface mode support!");
1733     CHECK_AND_RETURN_RET_LOG(!disableDmaSwap_, 0, "FCodec dma swap has been diabled!");
1734     CHECK_AND_RETURN_RET_LOGD(state_ == State::RUNNING || state_ == State::FLUSHED || state_ == State::EOS,
1735                               AVCS_ERR_INVALID_STATE, "Current state can't recycle memory!");
1736     AVCODEC_LOGI("Begin to freeze this codec!");
1737     State currentState = state_;
1738     state_ = State::FREEZING;
1739     int32_t errCode = FreezeBuffers(currentState);
1740     CHECK_AND_RETURN_RET_LOG(errCode == AVCS_ERR_OK, errCode, "Fcodec freeze buffers failed!");
1741     state_ = State::FROZEN;
1742     return AVCS_ERR_OK;
1743 }
1744 
NotifyMemoryWriteBack()1745 int32_t FCodec::NotifyMemoryWriteBack()
1746 {
1747     CHECK_AND_RETURN_RET_LOG(sInfo_.surface != nullptr, AVCS_ERR_UNKNOWN, "Only surface mode support!");
1748     AVCODEC_LOGI("Begin to active this codec!");
1749     int32_t errCode = ActiveBuffers();
1750     CHECK_AND_RETURN_RET_LOG(errCode == AVCS_ERR_OK, errCode, "Fcodec active buffers failed!");
1751     state_ = State::RUNNING;
1752     return AVCS_ERR_OK;
1753 }
1754 
GetMpeg2CapProf(std::vector<CapabilityData> & capaArray)1755 void FCodec::GetMpeg2CapProf(std::vector<CapabilityData> &capaArray)
1756 {
1757     if (!capaArray.empty()) {
1758         CapabilityData& capsData = capaArray.back();
1759         capsData.profiles = {static_cast<int32_t>(MPEG2_PROFILE_422), static_cast<int32_t>(MPEG2_PROFILE_HIGH),
1760                             static_cast<int32_t>(MPEG2_PROFILE_MAIN), static_cast<int32_t>(MPEG2_PROFILE_SNR),
1761                             static_cast<int32_t>(MPEG2_PROFILE_SIMPLE), static_cast<int32_t>(MPEG2_PROFILE_SPATIAL)};
1762         std::vector<int32_t> levels_sp;
1763         std::vector<int32_t> levels_mp;
1764         std::vector<int32_t> levels_snr;
1765         std::vector<int32_t> levels_422p;
1766         for (int32_t j = 0; j <= static_cast<int32_t>(MPEG2Level::MPEG2_LEVEL_ML); ++j) {
1767             levels_sp.emplace_back(j);
1768         }
1769         for (int32_t j = 0; j <= static_cast<int32_t>(MPEG2Level::MPEG2_LEVEL_HL); ++j) {
1770             levels_mp.emplace_back(j);
1771         }
1772         for (int32_t j = 0; j <= static_cast<int32_t>(MPEG2Level::MPEG2_LEVEL_H14); ++j) {
1773             levels_snr.emplace_back(j);
1774         }
1775         for (int32_t j = static_cast<int32_t>(MPEG2Level::MPEG2_LEVEL_ML);
1776                 j <= static_cast<int32_t>(MPEG2Level::MPEG2_LEVEL_HL); ++j) {
1777             levels_422p.emplace_back(j);
1778         }
1779         capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(MPEG2_PROFILE_SIMPLE), levels_sp));
1780         capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(MPEG2_PROFILE_MAIN), levels_mp));
1781         capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(MPEG2_PROFILE_SNR), levels_snr));
1782         capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(MPEG2_PROFILE_SPATIAL), levels_mp));
1783         capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(MPEG2_PROFILE_HIGH), levels_mp));
1784         capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(MPEG2_PROFILE_422), levels_422p));
1785     }
1786 }
1787 
SetMpeg4Profiles(CapabilityData & capsData)1788 void FCodec::SetMpeg4Profiles(CapabilityData& capsData)
1789 {
1790     capsData.profiles = {
1791         static_cast<int32_t>(MPEG4_PROFILE_SIMPLE),
1792         static_cast<int32_t>(MPEG4_PROFILE_SIMPLE_SCALABLE),
1793         static_cast<int32_t>(MPEG4_PROFILE_CORE),
1794         static_cast<int32_t>(MPEG4_PROFILE_MAIN),
1795         static_cast<int32_t>(MPEG4_PROFILE_NBIT),
1796         static_cast<int32_t>(MPEG4_PROFILE_HYBRID),
1797         static_cast<int32_t>(MPEG4_PROFILE_BASIC_ANIMATED_TEXTURE),
1798         static_cast<int32_t>(MPEG4_PROFILE_SCALABLE_TEXTURE),
1799         static_cast<int32_t>(MPEG4_PROFILE_SIMPLE_FA),
1800         static_cast<int32_t>(MPEG4_PROFILE_ADVANCED_REAL_TIME_SIMPLE),
1801         static_cast<int32_t>(MPEG4_PROFILE_CORE_SCALABLE),
1802         static_cast<int32_t>(MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY),
1803         static_cast<int32_t>(MPEG4_PROFILE_ADVANCED_CORE),
1804         static_cast<int32_t>(MPEG4_PROFILE_ADVANCED_SCALABLE_TEXTURE),
1805         static_cast<int32_t>(MPEG4_PROFILE_ADVANCED_SIMPLE),
1806     };
1807 }
1808 
SetMpeg4LevelsProfileGroup1(CapabilityData & capsData)1809 void FCodec::SetMpeg4LevelsProfileGroup1(CapabilityData& capsData)
1810 {
1811     capsData.profileLevelsMap = {
1812         {static_cast<int32_t>(MPEG4_PROFILE_SIMPLE), {
1813             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_0), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_0B),
1814             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_1), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_2),
1815             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_3), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_4A),
1816             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_5), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_6)
1817         }},
1818         {static_cast<int32_t>(MPEG4_PROFILE_SIMPLE_SCALABLE), {
1819             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_0), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_1),
1820             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_2)
1821         }},
1822         {static_cast<int32_t>(MPEG4_PROFILE_CORE), {
1823             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_1), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_2)
1824         }},
1825         {static_cast<int32_t>(MPEG4_PROFILE_MAIN), {
1826             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_2), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_3),
1827             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_4)
1828         }},
1829         {static_cast<int32_t>(MPEG4_PROFILE_NBIT), {
1830             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_2)
1831         }},
1832         {static_cast<int32_t>(MPEG4_PROFILE_HYBRID), {
1833             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_1), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_2)
1834         }},
1835         {static_cast<int32_t>(MPEG4_PROFILE_BASIC_ANIMATED_TEXTURE), {
1836             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_1), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_2)
1837         }},
1838         {static_cast<int32_t>(MPEG4_PROFILE_SCALABLE_TEXTURE), {
1839             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_1)
1840         }}
1841     };
1842 }
1843 
SetMpeg4LevelsProfileGroup2(CapabilityData & capsData)1844 void FCodec::SetMpeg4LevelsProfileGroup2(CapabilityData& capsData)
1845 {
1846     capsData.profileLevelsMap.insert({
1847         {static_cast<int32_t>(MPEG4_PROFILE_SIMPLE_FA), {
1848             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_1), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_2)
1849         }},
1850         {static_cast<int32_t>(MPEG4_PROFILE_ADVANCED_REAL_TIME_SIMPLE), {
1851             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_1), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_2),
1852             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_3), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_4)
1853         }},
1854         {static_cast<int32_t>(MPEG4_PROFILE_CORE_SCALABLE), {
1855             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_1), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_2),
1856             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_3)
1857         }},
1858         {static_cast<int32_t>(MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY), {
1859             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_1), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_2),
1860             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_3), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_4)
1861         }},
1862         {static_cast<int32_t>(MPEG4_PROFILE_ADVANCED_CORE), {
1863             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_1), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_2)
1864         }},
1865         {static_cast<int32_t>(MPEG4_PROFILE_ADVANCED_SCALABLE_TEXTURE), {
1866             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_1), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_2),
1867             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_3)
1868         }},
1869         {static_cast<int32_t>(MPEG4_PROFILE_ADVANCED_SIMPLE), {
1870             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_0), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_1),
1871             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_2), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_3),
1872             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_3B), static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_4),
1873             static_cast<int32_t>(MPEG4Level::MPEG4_LEVEL_5)
1874         }}
1875     });
1876 }
1877 
GetMpeg4esCapProf(std::vector<CapabilityData> & capaArray)1878 void FCodec::GetMpeg4esCapProf(std::vector<CapabilityData>& capaArray)
1879 {
1880     if (!capaArray.empty()) {
1881         CapabilityData& capsData = capaArray.back();
1882         SetMpeg4Profiles(capsData);
1883         SetMpeg4LevelsProfileGroup1(capsData);
1884         SetMpeg4LevelsProfileGroup2(capsData);
1885     }
1886 }
1887 
GetH263CapProf(std::vector<CapabilityData> & capaArray)1888 void FCodec::GetH263CapProf(std::vector<CapabilityData> &capaArray)
1889 {
1890     if (!capaArray.empty()) {
1891         CapabilityData& capsData = capaArray.back();
1892         capsData.profiles = {static_cast<int32_t>(H263_PROFILE_BASELINE),
1893                              static_cast<int32_t>(H263_PROFILE_VERSION_1_BACKWARD_COMPATIBILITY)};
1894         std::vector<int32_t> levels;
1895         for (int32_t j = 0; j <= static_cast<int32_t>(H263Level::H263_LEVEL_70); ++j) {
1896             levels.emplace_back(j);
1897         }
1898         capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(H263_PROFILE_BASELINE), levels));
1899         capsData.profileLevelsMap.insert(
1900             std::make_pair(static_cast<int32_t>(H263_PROFILE_VERSION_1_BACKWARD_COMPATIBILITY), levels));
1901     }
1902     return;
1903 }
1904 
GetAvcCapProf(std::vector<CapabilityData> & capaArray)1905 void FCodec::GetAvcCapProf(std::vector<CapabilityData> &capaArray)
1906 {
1907     if (!capaArray.empty()) {
1908         CapabilityData& capsData = capaArray.back();
1909         capsData.profiles = {static_cast<int32_t>(AVC_PROFILE_BASELINE), static_cast<int32_t>(AVC_PROFILE_MAIN),
1910                                     static_cast<int32_t>(AVC_PROFILE_HIGH)};
1911         std::vector<int32_t> levels;
1912         for (int32_t j = 0; j <= static_cast<int32_t>(AVCLevel::AVC_LEVEL_62); ++j) {
1913             levels.emplace_back(j);
1914         }
1915         capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(AVC_PROFILE_MAIN), levels));
1916         capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(AVC_PROFILE_HIGH), levels));
1917         capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(AVC_PROFILE_BASELINE), levels));
1918     }
1919 }
1920 
GetCodecCapability(std::vector<CapabilityData> & capaArray)1921 int32_t FCodec::GetCodecCapability(std::vector<CapabilityData> &capaArray)
1922 {
1923     for (uint32_t i = 0; i < SUPPORT_VCODEC_NUM; ++i) {
1924         CapabilityData capsData;
1925         capsData.codecName = static_cast<std::string>(SUPPORT_VCODEC[i].codecName);
1926         capsData.mimeType = static_cast<std::string>(SUPPORT_VCODEC[i].mimeType);
1927         capsData.codecType = AVCODEC_TYPE_VIDEO_DECODER;
1928         capsData.isVendor = false;
1929         capsData.maxInstance = VIDEO_INSTANCE_SIZE;
1930         capsData.alignment.width = VIDEO_ALIGNMENT_SIZE;
1931         capsData.alignment.height = VIDEO_ALIGNMENT_SIZE;
1932         capsData.width.minVal = capsData.mimeType == "video/h263" ? VIDEO_MIN_WIDTH_H263_SIZE : VIDEO_MIN_SIZE;
1933         capsData.height.minVal = capsData.mimeType == "video/h263" ? VIDEO_MIN_HEIGHT_H263_SIZE : VIDEO_MIN_SIZE;
1934         capsData.width.maxVal = capsData.mimeType == "video/h263" ? VIDEO_MAX_WIDTH_H263_SIZE : VIDEO_MAX_WIDTH_SIZE;
1935         capsData.height.maxVal = capsData.mimeType == "video/h263" ? VIDEO_MAX_HEIGHT_H263_SIZE : VIDEO_MAX_HEIGHT_SIZE;
1936         capsData.frameRate.minVal = 0;
1937         capsData.frameRate.maxVal = VIDEO_FRAMERATE_DEFAULT_SIZE;
1938         capsData.bitrate.minVal = 1;
1939         capsData.bitrate.maxVal = VIDEO_BITRATE_MAX_SIZE;
1940         capsData.blockPerFrame.minVal = 1;
1941         capsData.blockPerFrame.maxVal = VIDEO_BLOCKPERFRAME_SIZE;
1942         capsData.blockPerSecond.minVal = 1;
1943         capsData.blockPerSecond.maxVal = VIDEO_BLOCKPERSEC_SIZE;
1944         capsData.blockSize.width = VIDEO_ALIGN_SIZE;
1945         capsData.blockSize.height = VIDEO_ALIGN_SIZE;
1946         capsData.pixFormat = {
1947             static_cast<int32_t>(VideoPixelFormat::YUVI420), static_cast<int32_t>(VideoPixelFormat::NV12),
1948             static_cast<int32_t>(VideoPixelFormat::NV21), static_cast<int32_t>(VideoPixelFormat::RGBA)};
1949         if (capsData.mimeType == "video/mpeg2") {
1950             capaArray.emplace_back(capsData);
1951             GetMpeg2CapProf(capaArray);
1952         } else if (capsData.mimeType == "video/mp4v-es") {
1953             capaArray.emplace_back(capsData);
1954             GetMpeg4esCapProf(capaArray);
1955         } else if (capsData.mimeType == "video/h263") {
1956             capaArray.emplace_back(capsData);
1957             GetH263CapProf(capaArray);
1958         } else {
1959             capsData.frameRate.maxVal = VIDEO_FRAMERATE_MAX_SIZE;
1960             capaArray.emplace_back(capsData);
1961             GetAvcCapProf(capaArray);
1962         }
1963     }
1964     return AVCS_ERR_OK;
1965 }
1966 } // namespace Codec
1967 } // namespace MediaAVCodec
1968 } // namespace OHOS
1969