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