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