• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <iostream>
17 #include <set>
18 #include <thread>
19 #include <malloc.h>
20 #include "securec.h"
21 #include "avcodec_trace.h"
22 #include "avcodec_log.h"
23 #include "utils.h"
24 #include "avcodec_codec_name.h"
25 #include "fcodec.h"
26 
27 namespace OHOS {
28 namespace MediaAVCodec {
29 namespace Codec {
30 namespace {
31 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "FCodec"};
32 constexpr uint32_t INDEX_INPUT = 0;
33 constexpr uint32_t INDEX_OUTPUT = 1;
34 constexpr int32_t DEFAULT_IN_BUFFER_CNT = 4;
35 constexpr int32_t DEFAULT_OUT_SURFACE_CNT = 4;
36 constexpr int32_t DEFAULT_OUT_BUFFER_CNT = 3;
37 constexpr int32_t DEFAULT_MIN_BUFFER_CNT = 2;
38 constexpr uint32_t VIDEO_PIX_DEPTH_YUV = 3;
39 constexpr uint32_t VIDEO_PIX_DEPTH_RGBA = 4;
40 constexpr int32_t VIDEO_MIN_SIZE = 96;
41 constexpr int32_t VIDEO_ALIGNMENT_SIZE = 2;
42 constexpr int32_t VIDEO_MAX_WIDTH_SIZE = 4096;
43 constexpr int32_t VIDEO_MAX_HEIGHT_SIZE = 2304;
44 constexpr int32_t DEFAULT_VIDEO_WIDTH = 1920;
45 constexpr int32_t DEFAULT_VIDEO_HEIGHT = 1080;
46 constexpr uint32_t DEFAULT_TRY_DECODE_TIME = 1;
47 constexpr uint32_t DEFAULT_DECODE_WAIT_TIME = 33;
48 constexpr int32_t VIDEO_INSTANCE_SIZE = 16;
49 constexpr int32_t VIDEO_BITRATE_MAX_SIZE = 300000000;
50 constexpr int32_t VIDEO_FRAMERATE_MAX_SIZE = 120;
51 constexpr int32_t VIDEO_BLOCKPERFRAME_SIZE = 36864;
52 constexpr int32_t VIDEO_BLOCKPERSEC_SIZE = 983040;
53 constexpr int32_t DEFAULT_THREAD_COUNT = 2;
54 constexpr struct {
55     const std::string_view codecName;
56     const std::string_view mimeType;
57     const char *ffmpegCodec;
58     const bool isEncoder;
59 } SUPPORT_VCODEC[] = {
60     {AVCodecCodecName::VIDEO_DECODER_AVC_NAME, CodecMimeType::VIDEO_AVC, "h264", false},
61 };
62 constexpr uint32_t SUPPORT_VCODEC_NUM = sizeof(SUPPORT_VCODEC) / sizeof(SUPPORT_VCODEC[0]);
63 } // namespace
64 using namespace OHOS::Media;
FCodec(const std::string & name)65 FCodec::FCodec(const std::string &name) : codecName_(name), state_(State::Uninitialized)
66 {
67     AVCODEC_SYNC_TRACE;
68     AVCODEC_LOGD("Fcodec entered, state: Uninitialized");
69 }
70 
~FCodec()71 FCodec::~FCodec()
72 {
73     ReleaseResource();
74     callback_ = nullptr;
75     mallopt(M_FLUSH_THREAD_CACHE, 0);
76 }
77 
Init()78 int32_t FCodec::Init()
79 {
80     AVCODEC_SYNC_TRACE;
81     CHECK_AND_RETURN_RET_LOG(!codecName_.empty(), AVCS_ERR_INVALID_VAL, "Init codec failed:  empty name");
82     std::string fcodecName;
83     std::string_view mime;
84     for (uint32_t i = 0; i < SUPPORT_VCODEC_NUM; ++i) {
85         if (SUPPORT_VCODEC[i].codecName == codecName_) {
86             fcodecName = SUPPORT_VCODEC[i].ffmpegCodec;
87             mime = SUPPORT_VCODEC[i].mimeType;
88             break;
89         }
90     }
91     CHECK_AND_RETURN_RET_LOG(!fcodecName.empty(), AVCS_ERR_INVALID_VAL,
92                              "Init codec failed: not support name: %{public}s", codecName_.c_str());
93     format_.PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, mime);
94     format_.PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_NAME, codecName_);
95     avCodec_ = std::shared_ptr<AVCodec>(const_cast<AVCodec *>(avcodec_find_decoder_by_name(fcodecName.c_str())),
96                                         [](void *ptr) {});
97     CHECK_AND_RETURN_RET_LOG(avCodec_ != nullptr, AVCS_ERR_INVALID_VAL,
98                              "Init codec failed:  cannot find codec with name %{public}s", codecName_.c_str());
99     sendTask_ = std::make_shared<TaskThread>("SendFrame");
100     sendTask_->RegisterHandler([this] { SendFrame(); });
101     receiveTask_ = std::make_shared<TaskThread>("ReceiveFrame");
102     receiveTask_->RegisterHandler([this] { ReceiveFrame(); });
103 
104     state_ = State::Initialized;
105     AVCODEC_LOGI("Init codec successful,  state: Uninitialized -> Initialized");
106     return AVCS_ERR_OK;
107 }
108 
ConfigureDefaultVal(const Format & format,const std::string_view & formatKey,int32_t minVal,int32_t maxVal)109 void FCodec::ConfigureDefaultVal(const Format &format, const std::string_view &formatKey, int32_t minVal,
110                                  int32_t maxVal)
111 {
112     int32_t val32 = 0;
113     if (format.GetIntValue(formatKey, val32) && val32 >= minVal && val32 <= maxVal) {
114         format_.PutIntValue(formatKey, val32);
115     } else {
116         AVCODEC_LOGW("Set parameter failed: %{public}s, which minimum threshold=%{public}d, "
117                      "maximum threshold=%{public}d",
118                      formatKey.data(), minVal, maxVal);
119     }
120 }
121 
ConfigureSurface(const Format & format,const std::string_view & formatKey,uint32_t FORMAT_TYPE)122 void FCodec::ConfigureSurface(const Format &format, const std::string_view &formatKey, uint32_t FORMAT_TYPE)
123 {
124     CHECK_AND_RETURN_LOG(FORMAT_TYPE == FORMAT_TYPE_INT32, "Set parameter failed: type should be int32");
125 
126     int32_t val = 0;
127     CHECK_AND_RETURN_LOG(format.GetIntValue(formatKey, val), "Set parameter failed: get value fail");
128 
129     if (formatKey == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT) {
130         VideoPixelFormat vpf = static_cast<VideoPixelFormat>(val);
131         CHECK_AND_RETURN_LOG(vpf == VideoPixelFormat::RGBA || vpf == VideoPixelFormat::YUV420P ||
132                                  vpf == VideoPixelFormat::NV12 || vpf == VideoPixelFormat::NV21,
133                              "Set parameter failed: pixel format value %{public}d invalid", val);
134         outputPixelFmt_ = vpf;
135         format_.PutIntValue(formatKey, val);
136     } else if (formatKey == MediaDescriptionKey::MD_KEY_ROTATION_ANGLE) {
137         VideoRotation sr = static_cast<VideoRotation>(val);
138         CHECK_AND_RETURN_LOG(sr == VideoRotation::VIDEO_ROTATION_0 || sr == VideoRotation::VIDEO_ROTATION_90 ||
139                                  sr == VideoRotation::VIDEO_ROTATION_180 || sr == VideoRotation::VIDEO_ROTATION_270,
140                              "Set parameter failed: rotation angle value %{public}d invalid", val);
141         format_.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, val);
142     } else if (formatKey == MediaDescriptionKey::MD_KEY_SCALE_TYPE) {
143         ScalingMode scaleMode = static_cast<ScalingMode>(val);
144         CHECK_AND_RETURN_LOG(scaleMode == ScalingMode::SCALING_MODE_SCALE_TO_WINDOW ||
145                                  scaleMode == ScalingMode::SCALING_MODE_SCALE_CROP,
146                              "Set parameter failed: scale type value %{public}d invalid", val);
147         format_.PutIntValue(formatKey, val);
148     } else {
149         AVCODEC_LOGW("Set parameter failed: size: %{public}zu  %{public}s, please check your parameter key",
150                      formatKey.size(), formatKey.data());
151     }
152 }
153 
ConfigureContext(const Format & format)154 int32_t FCodec::ConfigureContext(const Format &format)
155 {
156     avCodecContext_ = std::shared_ptr<AVCodecContext>(avcodec_alloc_context3(avCodec_.get()), [](AVCodecContext *p) {
157         if (p != nullptr) {
158             if (p->extradata) {
159                 av_free(p->extradata);
160                 p->extradata = nullptr;
161             }
162             avcodec_free_context(&p);
163         }
164     });
165     CHECK_AND_RETURN_RET_LOG(avCodecContext_ != nullptr, AVCS_ERR_INVALID_OPERATION,
166                              "Configure codec failed: Allocate context error");
167     avCodecContext_->codec_type = AVMEDIA_TYPE_VIDEO;
168     format.GetIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width_);
169     format.GetIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height_);
170     avCodecContext_->width = width_;
171     avCodecContext_->height = height_;
172     avCodecContext_->thread_count = DEFAULT_THREAD_COUNT;
173     return AVCS_ERR_OK;
174 }
175 
Configure(const Format & format)176 int32_t FCodec::Configure(const Format &format)
177 {
178     AVCODEC_SYNC_TRACE;
179     if (state_ == State::Uninitialized) {
180         int32_t ret = Init();
181         CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Init codec failed");
182     }
183     CHECK_AND_RETURN_RET_LOG((state_ == State::Initialized), AVCS_ERR_INVALID_STATE,
184                              "Configure codec failed:  not in Initialized state");
185     format_.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, DEFAULT_VIDEO_WIDTH);
186     format_.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, DEFAULT_VIDEO_HEIGHT);
187     format_.PutIntValue(MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, DEFAULT_OUT_BUFFER_CNT);
188     format_.PutIntValue(MediaDescriptionKey::MD_KEY_MAX_INPUT_BUFFER_COUNT, DEFAULT_IN_BUFFER_CNT);
189     for (auto &it : format.GetFormatMap()) {
190         if (it.first == MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT) {
191             isOutBufSetted_ = true;
192             ConfigureDefaultVal(format, it.first, DEFAULT_MIN_BUFFER_CNT);
193         } else if (it.first == MediaDescriptionKey::MD_KEY_MAX_INPUT_BUFFER_COUNT) {
194             ConfigureDefaultVal(format, it.first, DEFAULT_MIN_BUFFER_CNT);
195         } else if (it.first == MediaDescriptionKey::MD_KEY_WIDTH) {
196             ConfigureDefaultVal(format, it.first, VIDEO_MIN_SIZE, VIDEO_MAX_WIDTH_SIZE);
197         } else if (it.first == MediaDescriptionKey::MD_KEY_HEIGHT) {
198             ConfigureDefaultVal(format, it.first, VIDEO_MIN_SIZE, VIDEO_MAX_HEIGHT_SIZE);
199         } else if (it.first == MediaDescriptionKey::MD_KEY_BITRATE) {
200             int64_t val64 = 0;
201             format.GetLongValue(MediaDescriptionKey::MD_KEY_BITRATE, val64);
202             format_.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, val64);
203         } else if (it.first == MediaDescriptionKey::MD_KEY_FRAME_RATE) {
204             double val = 0;
205             format.GetDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, val);
206             format_.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, val);
207         } else if (it.first == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT ||
208                    it.first == MediaDescriptionKey::MD_KEY_ROTATION_ANGLE ||
209                    it.first == MediaDescriptionKey::MD_KEY_SCALE_TYPE) {
210             ConfigureSurface(format, it.first, it.second.type);
211         } else {
212             AVCODEC_LOGW("Set parameter failed: size:%{public}s, unsupport key", it.first.data());
213         }
214     }
215 
216     int32_t ret = ConfigureContext(format);
217 
218     state_ = State::Configured;
219     AVCODEC_LOGI("Configured codec successful: state: Initialized -> Configured");
220     return ret;
221 }
222 
IsActive() const223 bool FCodec::IsActive() const
224 {
225     return state_ == State::Running || state_ == State::Flushed || state_ == State::EOS;
226 }
227 
ResetContext(bool isFlush)228 void FCodec::ResetContext(bool isFlush)
229 {
230     if (avCodecContext_ == nullptr) {
231         return;
232     }
233     if (avCodecContext_->extradata) {
234         av_free(avCodecContext_->extradata);
235         avCodecContext_->extradata = nullptr;
236     }
237     avCodecContext_->coded_width = 0;
238     avCodecContext_->coded_height = 0;
239     avCodecContext_->extradata_size = 0;
240     if (!isFlush) {
241         avCodecContext_->width = 0;
242         avCodecContext_->height = 0;
243         avCodecContext_->get_buffer2 = nullptr;
244     }
245 }
246 
Start()247 int32_t FCodec::Start()
248 {
249     AVCODEC_SYNC_TRACE;
250     CHECK_AND_RETURN_RET_LOG(callback_ != nullptr, AVCS_ERR_INVALID_OPERATION, "Start codec failed: callback is null");
251     CHECK_AND_RETURN_RET_LOG((state_ == State::Configured || state_ == State::Flushed), AVCS_ERR_INVALID_STATE,
252                              "Start codec failed: not in Configured or Flushed state");
253     if (state_ != State::Flushed) {
254         CHECK_AND_RETURN_RET_LOG(avcodec_open2(avCodecContext_.get(), avCodec_.get(), nullptr) == 0, AVCS_ERR_UNKNOWN,
255                                  "Start codec failed: cannot open avcodec");
256     }
257     if (!isBufferAllocated_) {
258         cachedFrame_ = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame *p) { av_frame_free(&p); });
259         avPacket_ = std::shared_ptr<AVPacket>(av_packet_alloc(), [](AVPacket *p) { av_packet_free(&p); });
260         CHECK_AND_RETURN_RET_LOG((cachedFrame_ != nullptr && avPacket_ != nullptr), AVCS_ERR_UNKNOWN,
261                                  "Start codec failed: cannot allocate frame or packet");
262         for (int32_t i = 0; i < AV_NUM_DATA_POINTERS; i++) {
263             scaleData_[i] = nullptr;
264             scaleLineSize_[i] = 0;
265         }
266         isConverted_ = false;
267         int32_t ret = AllocateBuffers();
268         CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Start codec failed: cannot allocate buffers");
269         isBufferAllocated_ = true;
270     }
271     state_ = State::Running;
272     InitBuffers();
273     isSendEos_ = false;
274     sendTask_->Start();
275     receiveTask_->Start();
276     if (surface_ != nullptr) {
277         renderTask_->Start();
278     }
279     AVCODEC_LOGI("Start codec successful, state: Running");
280     return AVCS_ERR_OK;
281 }
282 
InitBuffers()283 void FCodec::InitBuffers()
284 {
285     inputAvailQue_->SetActive(true);
286     codecAvailQue_->SetActive(true);
287     if (surface_ != nullptr) {
288         renderAvailQue_->SetActive(true);
289     }
290     if (buffers_[INDEX_INPUT].size() > 0) {
291         for (uint32_t i = 0; i < buffers_[INDEX_INPUT].size(); i++) {
292             buffers_[INDEX_INPUT][i]->owner_ = FBuffer::Owner::OWNED_BY_USER;
293             callback_->OnInputBufferAvailable(i, buffers_[INDEX_INPUT][i]->avBuffer_);
294             AVCODEC_LOGI("OnInputBufferAvailable frame index = %{public}d, owner = %{public}d", i,
295                          buffers_[INDEX_INPUT][i]->owner_.load());
296         }
297     }
298     if (buffers_[INDEX_OUTPUT].size() <= 0) {
299         return;
300     }
301     if (surface_ == nullptr) {
302         for (uint32_t i = 0; i < buffers_[INDEX_OUTPUT].size(); i++) {
303             buffers_[INDEX_OUTPUT][i]->owner_ = FBuffer::Owner::OWNED_BY_CODEC;
304             codecAvailQue_->Push(i);
305         }
306     } else {
307         for (uint32_t i = 0; i < buffers_[INDEX_OUTPUT].size(); i++) {
308             std::shared_ptr<FSurfaceMemory> surfaceMemory = buffers_[INDEX_OUTPUT][i]->sMemory_;
309             if (surfaceMemory->GetSurfaceBuffer() == nullptr) {
310                 buffers_[INDEX_OUTPUT][i]->owner_ = FBuffer::Owner::OWNED_BY_SURFACE;
311                 renderAvailQue_->Push(i);
312             } else {
313                 buffers_[INDEX_OUTPUT][i]->owner_ = FBuffer::Owner::OWNED_BY_CODEC;
314                 codecAvailQue_->Push(i);
315             }
316         }
317     }
318 }
319 
ResetData()320 void FCodec::ResetData()
321 {
322     if (scaleData_[0] != nullptr) {
323         if (isConverted_) {
324             av_free(scaleData_[0]);
325             isConverted_ = false;
326             scale_.reset();
327         }
328         for (int32_t i = 0; i < AV_NUM_DATA_POINTERS; i++) {
329             scaleData_[i] = nullptr;
330             scaleLineSize_[i] = 0;
331         }
332     }
333 }
334 
ResetBuffers()335 void FCodec::ResetBuffers()
336 {
337     inputAvailQue_->Clear();
338     std::unique_lock<std::mutex> iLock(inputMutex_);
339     synIndex_ = std::nullopt;
340     iLock.unlock();
341     codecAvailQue_->Clear();
342     if (surface_ != nullptr) {
343         renderAvailQue_->Clear();
344     }
345     ResetData();
346     av_frame_unref(cachedFrame_.get());
347     av_packet_unref(avPacket_.get());
348 }
349 
StopThread()350 void FCodec::StopThread()
351 {
352     if (sendTask_ != nullptr && inputAvailQue_ != nullptr) {
353         std::unique_lock<std::mutex> sLock(sendMutex_);
354         sendCv_.notify_one();
355         sLock.unlock();
356         inputAvailQue_->SetActive(false, false);
357         sendTask_->Stop();
358     }
359     if (receiveTask_ != nullptr && codecAvailQue_ != nullptr) {
360         std::unique_lock<std::mutex> rLock(recvMutex_);
361         recvCv_.notify_one();
362         rLock.unlock();
363         codecAvailQue_->SetActive(false, false);
364         receiveTask_->Stop();
365     }
366     if (surface_ != nullptr && renderTask_ != nullptr && renderAvailQue_ != nullptr) {
367         renderAvailQue_->SetActive(false, false);
368         renderTask_->Stop();
369     }
370 }
371 
Stop()372 int32_t FCodec::Stop()
373 {
374     AVCODEC_SYNC_TRACE;
375     CHECK_AND_RETURN_RET_LOG((IsActive()), AVCS_ERR_INVALID_STATE, "Stop codec failed: not in executing state");
376     state_ = State::Stopping;
377     std::unique_lock<std::mutex> sLock(sendMutex_);
378     sendCv_.notify_one();
379     sLock.unlock();
380     inputAvailQue_->SetActive(false, false);
381     sendTask_->Stop();
382 
383     if (surface_ != nullptr) {
384         renderAvailQue_->SetActive(false, false);
385         renderTask_->Stop();
386     }
387     std::unique_lock<std::mutex> rLock(recvMutex_);
388     recvCv_.notify_one();
389     rLock.unlock();
390     codecAvailQue_->SetActive(false, false);
391     receiveTask_->Stop();
392     avcodec_close(avCodecContext_.get());
393     ResetContext(true);
394     ResetBuffers();
395     state_ = State::Configured;
396     AVCODEC_LOGI("Stop codec successful, state: Configured");
397     return AVCS_ERR_OK;
398 }
399 
Flush()400 int32_t FCodec::Flush()
401 {
402     AVCODEC_SYNC_TRACE;
403     CHECK_AND_RETURN_RET_LOG((state_ == State::Running || state_ == State::EOS), AVCS_ERR_INVALID_STATE,
404                              "Flush codec failed: not in running or Eos state");
405     state_ = State::Flushing;
406     std::unique_lock<std::mutex> sLock(sendMutex_);
407     sendCv_.notify_one();
408     sLock.unlock();
409     inputAvailQue_->SetActive(false, false);
410     sendTask_->Pause();
411 
412     if (surface_ != nullptr) {
413         renderAvailQue_->SetActive(false, false);
414         renderTask_->Pause();
415     }
416     std::unique_lock<std::mutex> rLock(recvMutex_);
417     recvCv_.notify_one();
418     rLock.unlock();
419     codecAvailQue_->SetActive(false, false);
420     receiveTask_->Pause();
421 
422     avcodec_flush_buffers(avCodecContext_.get());
423     ResetContext(true);
424     ResetBuffers();
425     state_ = State::Flushed;
426     AVCODEC_LOGI("Flush codec successful, state: Flushed");
427     return AVCS_ERR_OK;
428 }
429 
Reset()430 int32_t FCodec::Reset()
431 {
432     AVCODEC_SYNC_TRACE;
433     AVCODEC_LOGI("Reset codec called");
434     int32_t ret = Release();
435     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Reset codec failed: cannot release codec");
436     ret = Init();
437     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Reset codec failed: cannot init codec");
438     AVCODEC_LOGI("Reset codec successful, state: Initialized");
439     return AVCS_ERR_OK;
440 }
441 
ReleaseResource()442 void FCodec::ReleaseResource()
443 {
444     StopThread();
445     if (avCodecContext_ != nullptr) {
446         avcodec_close(avCodecContext_.get());
447         ResetContext();
448     }
449     ReleaseBuffers();
450     format_ = Format();
451     if (surface_ != nullptr) {
452         surface_->CleanCache();
453         AVCODEC_LOGI("surface cleancache success");
454     }
455     surface_ = nullptr;
456 }
457 
Release()458 int32_t FCodec::Release()
459 {
460     AVCODEC_SYNC_TRACE;
461     state_ = State::Stopping;
462     ReleaseResource();
463     state_ = State::Uninitialized;
464     AVCODEC_LOGI("Release codec successful, state: Uninitialized");
465     return AVCS_ERR_OK;
466 }
467 
SetSurfaceParameter(const Format & format,const std::string_view & formatKey,uint32_t FORMAT_TYPE)468 void FCodec::SetSurfaceParameter(const Format &format, const std::string_view &formatKey, uint32_t FORMAT_TYPE)
469 {
470     CHECK_AND_RETURN_LOG(FORMAT_TYPE == FORMAT_TYPE_INT32, "Set parameter failed: type should be int32");
471     int32_t val = 0;
472     CHECK_AND_RETURN_LOG(format.GetIntValue(formatKey, val), "Set parameter failed: get value fail");
473     if (formatKey == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT) {
474         VideoPixelFormat vpf = static_cast<VideoPixelFormat>(val);
475         CHECK_AND_RETURN_LOG(vpf == VideoPixelFormat::RGBA || vpf == VideoPixelFormat::YUV420P ||
476                                  vpf == VideoPixelFormat::NV12 || vpf == VideoPixelFormat::NV21,
477                              "Set parameter failed: pixel format value %{public}d invalid", val);
478         outputPixelFmt_ = vpf;
479         format_.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, val);
480         GraphicPixelFormat surfacePixelFmt = TranslateSurfaceFormat(vpf);
481         std::lock_guard<std::mutex> sLock(surfaceMutex_);
482         FSurfaceMemory::SetConfig(width_, height_, surfacePixelFmt);
483     } else if (formatKey == MediaDescriptionKey::MD_KEY_ROTATION_ANGLE) {
484         VideoRotation sr = static_cast<VideoRotation>(val);
485         CHECK_AND_RETURN_LOG(sr == VideoRotation::VIDEO_ROTATION_0 || sr == VideoRotation::VIDEO_ROTATION_90 ||
486                                  sr == VideoRotation::VIDEO_ROTATION_180 || sr == VideoRotation::VIDEO_ROTATION_270,
487                              "Set parameter failed: rotation angle value %{public}d invalid", val);
488         format_.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, val);
489         std::lock_guard<std::mutex> sLock(surfaceMutex_);
490         surface_->SetTransform(TranslateSurfaceRotation(sr));
491     } else if (formatKey == MediaDescriptionKey::MD_KEY_SCALE_TYPE) {
492         ScalingMode scaleMode = static_cast<ScalingMode>(val);
493         CHECK_AND_RETURN_LOG(scaleMode == ScalingMode::SCALING_MODE_SCALE_TO_WINDOW ||
494                                  scaleMode == ScalingMode::SCALING_MODE_SCALE_CROP,
495                              "Set parameter failed: scale type value %{public}d invalid", val);
496         format_.PutIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE, val);
497         std::lock_guard<std::mutex> sLock(surfaceMutex_);
498         FSurfaceMemory::SetScaleType(scaleMode);
499     } else {
500         AVCODEC_LOGW("Set parameter failed: size: %{public}s", formatKey.data());
501     }
502 }
503 
SetParameter(const Format & format)504 int32_t FCodec::SetParameter(const Format &format)
505 {
506     AVCODEC_SYNC_TRACE;
507     CHECK_AND_RETURN_RET_LOG(IsActive(), AVCS_ERR_INVALID_STATE,
508                              "Set parameter failed: not in Running or Flushed state");
509     for (auto &it : format.GetFormatMap()) {
510         if (surface_ != nullptr && it.second.type == FORMAT_TYPE_INT32) {
511             if (it.first == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT ||
512                 it.first == MediaDescriptionKey::MD_KEY_ROTATION_ANGLE ||
513                 it.first == MediaDescriptionKey::MD_KEY_SCALE_TYPE) {
514                 SetSurfaceParameter(format, it.first, it.second.type);
515             }
516         } else {
517             AVCODEC_LOGW("Current Version, %{public}s is not supported", it.first.data());
518         }
519     }
520     AVCODEC_LOGI("Set parameter successful");
521     return AVCS_ERR_OK;
522 }
523 
GetOutputFormat(Format & format)524 int32_t FCodec::GetOutputFormat(Format &format)
525 {
526     AVCODEC_SYNC_TRACE;
527     if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_BITRATE)) {
528         if (avCodecContext_ != nullptr) {
529             format_.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, avCodecContext_->bit_rate);
530         }
531     }
532     if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_FRAME_RATE)) {
533         if (avCodecContext_ != nullptr && avCodecContext_->framerate.den > 0) {
534             double value = static_cast<double>(avCodecContext_->framerate.num) /
535                            static_cast<double>(avCodecContext_->framerate.den);
536             format_.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, value);
537         }
538     }
539     if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_MAX_INPUT_SIZE)) {
540         int32_t stride = AlignUp(width_, VIDEO_ALIGN_SIZE);
541         int32_t maxInputSize = static_cast<int32_t>((stride * height_ * VIDEO_PIX_DEPTH_YUV) >> 1);
542         format_.PutIntValue(MediaDescriptionKey::MD_KEY_MAX_INPUT_SIZE, maxInputSize);
543     }
544     format = format_;
545     AVCODEC_LOGI("Get outputFormat successful");
546     return AVCS_ERR_OK;
547 }
548 
CalculateBufferSize()549 void FCodec::CalculateBufferSize()
550 {
551     int32_t stride = AlignUp(width_, VIDEO_ALIGN_SIZE);
552     inputBufferSize_ = static_cast<int32_t>((stride * height_ * VIDEO_PIX_DEPTH_YUV) >> 1);
553     outputBufferSize_ = inputBufferSize_;
554     if (outputPixelFmt_ == VideoPixelFormat::RGBA) {
555         outputBufferSize_ = static_cast<int32_t>(stride * height_ * VIDEO_PIX_DEPTH_RGBA);
556     }
557     AVCODEC_LOGI("Input buffer size = %{public}d, output buffer size=%{public}d", inputBufferSize_, outputBufferSize_);
558 }
559 
AllocateInputBuffer(int32_t bufferCnt,int32_t inBufferSize)560 int32_t FCodec::AllocateInputBuffer(int32_t bufferCnt, int32_t inBufferSize)
561 {
562     int32_t valBufferCnt = 0;
563     for (int32_t i = 0; i < bufferCnt; i++) {
564         std::shared_ptr<FBuffer> buf = std::make_shared<FBuffer>();
565         std::shared_ptr<AVAllocator> allocator =
566             AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
567         CHECK_AND_CONTINUE_LOG(allocator != nullptr, "input buffer %{public}d allocator is nullptr", i);
568         buf->avBuffer_ = AVBuffer::CreateAVBuffer(allocator, inBufferSize);
569         CHECK_AND_CONTINUE_LOG(buf->avBuffer_ != nullptr, "Allocate input buffer failed, index=%{public}d", i);
570 
571         buffers_[INDEX_INPUT].emplace_back(buf);
572         valBufferCnt++;
573     }
574     if (valBufferCnt < DEFAULT_MIN_BUFFER_CNT) {
575         AVCODEC_LOGE("Allocate input buffer failed: only %{public}d buffer is allocated, no memory", valBufferCnt);
576         buffers_[INDEX_INPUT].clear();
577         return AVCS_ERR_NO_MEMORY;
578     }
579     return AVCS_ERR_OK;
580 }
581 
AllocateOutputBuffer(int32_t bufferCnt,int32_t outBufferSize)582 int32_t FCodec::AllocateOutputBuffer(int32_t bufferCnt, int32_t outBufferSize)
583 {
584     int32_t valBufferCnt = 0;
585     if (surface_) {
586         CHECK_AND_RETURN_RET_LOG(surface_->SetQueueSize(bufferCnt) == OHOS::SurfaceError::SURFACE_ERROR_OK,
587                                  AVCS_ERR_NO_MEMORY, "Surface set QueueSize=%{public}d failed", bufferCnt);
588         if (outputPixelFmt_ == VideoPixelFormat::UNKNOWN) {
589             format_.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT,
590                                 static_cast<int32_t>(VideoPixelFormat::YUV420P));
591         }
592         int32_t val32 = 0;
593         format_.GetIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, val32);
594         GraphicPixelFormat surfacePixelFmt = TranslateSurfaceFormat(static_cast<VideoPixelFormat>(val32));
595         CHECK_AND_RETURN_RET_LOG(surfacePixelFmt != GraphicPixelFormat::GRAPHIC_PIXEL_FMT_BUTT, AVCS_ERR_UNSUPPORT,
596                                  "Failed to allocate output buffer: unsupported surface format");
597         FSurfaceMemory::SetSurface(surface_);
598         FSurfaceMemory::SetConfig(static_cast<int32_t>(width_), static_cast<int32_t>(height_), surfacePixelFmt);
599 
600         format_.GetIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE, val32);
601         FSurfaceMemory::SetScaleType(static_cast<ScalingMode>(val32));
602         format_.GetIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, val32);
603         surface_->SetTransform(TranslateSurfaceRotation(static_cast<VideoRotation>(val32)));
604     }
605     for (int i = 0; i < bufferCnt; i++) {
606         std::shared_ptr<FBuffer> buf = std::make_shared<FBuffer>();
607         if (surface_ == nullptr) {
608             std::shared_ptr<AVAllocator> allocator =
609                 AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
610             CHECK_AND_CONTINUE_LOG(allocator != nullptr, "output buffer %{public}d allocator is nullptr", i);
611             buf->avBuffer_ = AVBuffer::CreateAVBuffer(allocator, outBufferSize);
612         } else {
613             buf->sMemory_ = FSurfaceMemory::Create();
614             CHECK_AND_CONTINUE_LOG(buf->sMemory_ != nullptr, "output surface memory %{public}d create fail", i);
615             buf->avBuffer_ = AVBuffer::CreateAVBuffer(buf->sMemory_->GetBase(), buf->sMemory_->GetSize());
616         }
617         CHECK_AND_CONTINUE_LOG(buf->avBuffer_ != nullptr, "Allocate output buffer failed, index=%{public}d", i);
618 
619         buf->width_ = width_;
620         buf->height_ = height_;
621         buffers_[INDEX_OUTPUT].emplace_back(buf);
622         valBufferCnt++;
623     }
624     if (valBufferCnt < DEFAULT_MIN_BUFFER_CNT) {
625         AVCODEC_LOGE("Allocate output buffer failed: only %{public}d buffer is allocated, no memory", valBufferCnt);
626         buffers_[INDEX_INPUT].clear();
627         buffers_[INDEX_OUTPUT].clear();
628         return AVCS_ERR_NO_MEMORY;
629     }
630     return AVCS_ERR_OK;
631 }
632 
AllocateBuffers()633 int32_t FCodec::AllocateBuffers()
634 {
635     AVCODEC_SYNC_TRACE;
636     CalculateBufferSize();
637     CHECK_AND_RETURN_RET_LOG(inputBufferSize_ > 0 && outputBufferSize_ > 0, AVCS_ERR_INVALID_VAL,
638                              "Allocate buffer with input size=%{public}d, output size=%{public}d failed",
639                              inputBufferSize_, outputBufferSize_);
640     if (surface_ != nullptr && isOutBufSetted_ == false) {
641         format_.PutIntValue(MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, DEFAULT_OUT_SURFACE_CNT);
642     }
643     int32_t InputBufferCnt = 0;
644     int32_t OutputBufferCnt = 0;
645     format_.GetIntValue(MediaDescriptionKey::MD_KEY_MAX_INPUT_BUFFER_COUNT, InputBufferCnt);
646     format_.GetIntValue(MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, OutputBufferCnt);
647     inputAvailQue_ = std::make_shared<BlockQueue<uint32_t>>("inputAvailQue", InputBufferCnt);
648     codecAvailQue_ = std::make_shared<BlockQueue<uint32_t>>("codecAvailQue", OutputBufferCnt);
649     if (surface_ != nullptr) {
650         renderAvailQue_ = std::make_shared<BlockQueue<uint32_t>>("renderAvailQue", OutputBufferCnt);
651     }
652     if (AllocateInputBuffer(InputBufferCnt, inputBufferSize_) == AVCS_ERR_NO_MEMORY ||
653         AllocateOutputBuffer(OutputBufferCnt, outputBufferSize_) == AVCS_ERR_NO_MEMORY) {
654         return AVCS_ERR_NO_MEMORY;
655     }
656     AVCODEC_LOGI("Allocate buffers successful");
657     return AVCS_ERR_OK;
658 }
659 
UpdateBuffers(uint32_t index,int32_t bufferSize,uint32_t bufferType)660 int32_t FCodec::UpdateBuffers(uint32_t index, int32_t bufferSize, uint32_t bufferType)
661 {
662     int32_t curBufSize = buffers_[bufferType][index]->avBuffer_->memory_->GetCapacity();
663     if (bufferSize != curBufSize) {
664         std::shared_ptr<FBuffer> buf = std::make_shared<FBuffer>();
665         std::shared_ptr<AVAllocator> allocator =
666             AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
667         CHECK_AND_RETURN_RET_LOG(allocator != nullptr, AVCS_ERR_NO_MEMORY, "buffer %{public}d allocator is nullptr",
668                                  index);
669         buf->avBuffer_ = AVBuffer::CreateAVBuffer(allocator, bufferSize);
670         CHECK_AND_RETURN_RET_LOG(buf->avBuffer_ != nullptr, AVCS_ERR_NO_MEMORY,
671                                  "Buffer allocate failed, index=%{public}d", index);
672 
673         if (bufferType == INDEX_INPUT) {
674             buf->owner_ = FBuffer::Owner::OWNED_BY_USER;
675         } else {
676             buf->owner_ = FBuffer::Owner::OWNED_BY_CODEC;
677         }
678         buffers_[bufferType][index] = buf;
679     }
680     return AVCS_ERR_OK;
681 }
682 
UpdateSurfaceMemory(uint32_t index)683 int32_t FCodec::UpdateSurfaceMemory(uint32_t index)
684 {
685     AVCODEC_SYNC_TRACE;
686     std::unique_lock<std::mutex> oLock(outputMutex_);
687     std::shared_ptr<FBuffer> &outputBuffer = buffers_[INDEX_OUTPUT][index];
688     oLock.unlock();
689     if (width_ != outputBuffer->width_ || height_ != outputBuffer->height_) {
690         std::shared_ptr<FSurfaceMemory> surfaceMemory = outputBuffer->sMemory_;
691         surfaceMemory->SetNeedRender(false);
692         surfaceMemory->ReleaseSurfaceBuffer();
693         while (state_ == State::Running) {
694             std::unique_lock<std::mutex> sLock(surfaceMutex_);
695             sptr<SurfaceBuffer> surfaceBuffer = surfaceMemory->GetSurfaceBuffer();
696             sLock.unlock();
697             if (surfaceBuffer != nullptr) {
698                 break;
699             }
700             std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TRY_DECODE_TIME));
701         }
702 
703         outputBuffer->avBuffer_ =
704             AVBuffer::CreateAVBuffer(outputBuffer->sMemory_->GetBase(), outputBuffer->sMemory_->GetSize());
705         outputBuffer->width_ = width_;
706         outputBuffer->height_ = height_;
707     }
708 
709     return AVCS_ERR_OK;
710 }
711 
CheckFormatChange(uint32_t index,int width,int height)712 int32_t FCodec::CheckFormatChange(uint32_t index, int width, int height)
713 {
714     if (width_ != width || height_ != height) {
715         AVCODEC_LOGI("format change, width: %{public}d->%{public}d, height: %{public}d->%{public}d", width_, width,
716                      height_, height);
717         width_ = width;
718         height_ = height;
719         scale_ = nullptr;
720         CalculateBufferSize();
721         format_.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width_);
722         format_.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height_);
723         if (surface_) {
724             int32_t val32 = 0;
725             format_.GetIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, val32);
726             GraphicPixelFormat surfacePixelFmt = TranslateSurfaceFormat(static_cast<VideoPixelFormat>(val32));
727             std::lock_guard<std::mutex> sLock(surfaceMutex_);
728             FSurfaceMemory::SetConfig(static_cast<int32_t>(width_), static_cast<int32_t>(height_), surfacePixelFmt);
729         }
730         callback_->OnOutputFormatChanged(format_);
731     }
732     if (surface_ == nullptr) {
733         std::lock_guard<std::mutex> oLock(outputMutex_);
734         CHECK_AND_RETURN_RET_LOG((UpdateBuffers(index, outputBufferSize_, INDEX_OUTPUT) == AVCS_ERR_OK),
735                                  AVCS_ERR_NO_MEMORY, "Update  output buffer failed, index=%{public}u", index);
736     } else {
737         CHECK_AND_RETURN_RET_LOG((UpdateSurfaceMemory(index) == AVCS_ERR_OK), AVCS_ERR_NO_MEMORY,
738                                  "Update buffer failed");
739     }
740     return AVCS_ERR_OK;
741 }
742 
ReleaseBuffers()743 void FCodec::ReleaseBuffers()
744 {
745     ResetData();
746     if (!isBufferAllocated_) {
747         return;
748     }
749 
750     inputAvailQue_->Clear();
751     std::unique_lock<std::mutex> iLock(inputMutex_);
752     buffers_[INDEX_INPUT].clear();
753     synIndex_ = std::nullopt;
754     iLock.unlock();
755 
756     std::unique_lock<std::mutex> oLock(outputMutex_);
757     codecAvailQue_->Clear();
758     if (surface_ != nullptr) {
759         renderAvailQue_->Clear();
760         for (uint32_t i = 0; i < buffers_[INDEX_OUTPUT].size(); i++) {
761             std::shared_ptr<FBuffer> outputBuffer = buffers_[INDEX_OUTPUT][i];
762             if (outputBuffer->owner_ == FBuffer::Owner::OWNED_BY_CODEC) {
763                 std::shared_ptr<FSurfaceMemory> surfaceMemory = outputBuffer->sMemory_;
764                 surfaceMemory->SetNeedRender(false);
765                 surfaceMemory->ReleaseSurfaceBuffer();
766                 outputBuffer->owner_ = FBuffer::Owner::OWNED_BY_SURFACE;
767             }
768         }
769     }
770     buffers_[INDEX_OUTPUT].clear();
771     oLock.unlock();
772     isBufferAllocated_ = false;
773 }
774 
QueueInputBuffer(uint32_t index)775 int32_t FCodec::QueueInputBuffer(uint32_t index)
776 {
777     AVCODEC_SYNC_TRACE;
778     CHECK_AND_RETURN_RET_LOG(state_ == State::Running, AVCS_ERR_INVALID_STATE,
779                              "Queue input buffer failed: not in Running state");
780     CHECK_AND_RETURN_RET_LOG(index < buffers_[INDEX_INPUT].size(), AVCS_ERR_INVALID_VAL,
781                              "Queue input buffer failed with bad index, index=%{public}u, buffer_size=%{public}zu",
782                              index, buffers_[INDEX_INPUT].size());
783     std::shared_ptr<FBuffer> inputBuffer = buffers_[INDEX_INPUT][index];
784     CHECK_AND_RETURN_RET_LOG(inputBuffer->owner_ == FBuffer::Owner::OWNED_BY_USER, AVCS_ERR_INVALID_OPERATION,
785                              "Queue input buffer failed: buffer with index=%{public}u is not available", index);
786 
787     inputBuffer->owner_ = FBuffer::Owner::OWNED_BY_CODEC;
788     std::shared_ptr<AVBuffer> &inputAVBuffer = inputBuffer->avBuffer_;
789     if (synIndex_) {
790         const std::shared_ptr<AVBuffer> &curAVBuffer = buffers_[INDEX_INPUT][synIndex_.value()]->avBuffer_;
791         int32_t curAVBufferSize = curAVBuffer->memory_->GetSize();
792         int32_t inputAVBufferSize = inputAVBuffer->memory_->GetSize();
793         if ((curAVBufferSize + inputAVBufferSize <= curAVBuffer->memory_->GetCapacity()) &&
794             memcpy_s(curAVBuffer->memory_->GetAddr() + curAVBufferSize, inputAVBufferSize,
795                      inputAVBuffer->memory_->GetAddr(), inputAVBufferSize) == EOK) {
796             curAVBuffer->memory_->SetSize(curAVBufferSize + inputAVBufferSize);
797             curAVBuffer->flag_ = inputAVBuffer->flag_;
798             curAVBuffer->pts_ = inputAVBuffer->pts_;
799 
800             if (!(inputAVBuffer->flag_ & AVCODEC_BUFFER_FLAG_CODEC_DATA) &&
801                 !(inputAVBuffer->flag_ & AVCODEC_BUFFER_FLAG_PARTIAL_FRAME)) {
802                 inputAvailQue_->Push(synIndex_.value());
803                 synIndex_ = std::nullopt;
804             }
805             inputBuffer->owner_ = FBuffer::Owner::OWNED_BY_USER;
806             callback_->OnInputBufferAvailable(index, inputAVBuffer);
807             return AVCS_ERR_OK;
808         } else {
809             AVCODEC_LOGE("packet size %{public}d over buffer size %{public}d", curAVBufferSize + inputAVBufferSize,
810                          curAVBuffer->memory_->GetCapacity());
811             callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_NO_MEMORY);
812             state_ = State::Error;
813             return AVCS_ERR_NO_MEMORY;
814         }
815     } else {
816         if ((inputAVBuffer->flag_ & AVCODEC_BUFFER_FLAG_CODEC_DATA) ||
817             (inputAVBuffer->flag_ & AVCODEC_BUFFER_FLAG_PARTIAL_FRAME)) {
818             synIndex_ = index;
819         } else {
820             inputAvailQue_->Push(index);
821         }
822     }
823 
824     return AVCS_ERR_OK;
825 }
826 
SendFrame()827 void FCodec::SendFrame()
828 {
829     if (state_ == State::Stopping || state_ == State::Flushing) {
830         return;
831     } else if (state_ != State::Running || isSendEos_) {
832         std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TRY_DECODE_TIME));
833         return;
834     }
835     uint32_t index = inputAvailQue_->Front();
836     CHECK_AND_RETURN_LOG(state_ == State::Running, "Not in running state");
837     std::shared_ptr<FBuffer> &inputBuffer = buffers_[INDEX_INPUT][index];
838     std::shared_ptr<AVBuffer> &inputAVBuffer = inputBuffer->avBuffer_;
839     if (inputAVBuffer->flag_ & AVCODEC_BUFFER_FLAG_EOS) {
840         avPacket_->data = nullptr;
841         std::unique_lock<std::mutex> sendLock(sendMutex_);
842         isSendEos_ = true;
843         sendCv_.wait_for(sendLock, std::chrono::milliseconds(DEFAULT_DECODE_WAIT_TIME));
844         AVCODEC_LOGI("Send eos end");
845     } else {
846         avPacket_->data = inputAVBuffer->memory_->GetAddr();
847         avPacket_->size = static_cast<int32_t>(inputAVBuffer->memory_->GetSize());
848         avPacket_->pts = inputAVBuffer->pts_;
849     }
850     std::unique_lock<std::mutex> sLock(syncMutex_);
851     int ret = avcodec_send_packet(avCodecContext_.get(), avPacket_.get());
852     sLock.unlock();
853     if (ret == 0 || ret == AVERROR_INVALIDDATA) {
854         if (ret == AVERROR_INVALIDDATA) {
855             AVCODEC_LOGW("ffmpeg ret = %{public}s", AVStrError(ret).c_str());
856         }
857         std::unique_lock<std::mutex> recvLock(recvMutex_);
858         recvCv_.notify_one();
859         recvLock.unlock();
860         inputAvailQue_->Pop();
861         inputBuffer->owner_ = FBuffer::Owner::OWNED_BY_USER;
862         callback_->OnInputBufferAvailable(index, inputAVBuffer);
863     } else if (ret == AVERROR(EAGAIN)) {
864         std::unique_lock<std::mutex> sendLock(sendMutex_);
865         isSendWait_ = true;
866         sendCv_.wait_for(sendLock, std::chrono::milliseconds(DEFAULT_DECODE_WAIT_TIME));
867     } else {
868         AVCODEC_LOGE("Cannot send frame to codec: ffmpeg ret = %{public}s", AVStrError(ret).c_str());
869         callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN);
870         state_ = State::Error;
871     }
872 }
873 
FillFrameBuffer(const std::shared_ptr<FBuffer> & frameBuffer)874 int32_t FCodec::FillFrameBuffer(const std::shared_ptr<FBuffer> &frameBuffer)
875 {
876     CHECK_AND_RETURN_RET_LOG((cachedFrame_->flags & AV_FRAME_FLAG_CORRUPT) == 0, AVCS_ERR_INVALID_VAL,
877                              "Recevie frame from codec failed: decoded frame is corrupt");
878     VideoPixelFormat targetPixelFmt = outputPixelFmt_;
879     if (outputPixelFmt_ == VideoPixelFormat::UNKNOWN) {
880         targetPixelFmt = surface_ ? VideoPixelFormat::YUV420P : ConvertPixelFormatFromFFmpeg(cachedFrame_->format);
881     }
882     AVPixelFormat ffmpegFormat = ConvertPixelFormatToFFmpeg(targetPixelFmt);
883     int32_t ret;
884     if (ffmpegFormat == static_cast<AVPixelFormat>(cachedFrame_->format)) {
885         for (int32_t i = 0; cachedFrame_->linesize[i] > 0; i++) {
886             scaleData_[i] = cachedFrame_->data[i];
887             scaleLineSize_[i] = cachedFrame_->linesize[i];
888         }
889     } else {
890         ret = ConvertVideoFrame(&scale_, cachedFrame_, scaleData_, scaleLineSize_, ffmpegFormat);
891         CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Scale video frame failed: %{public}d", ret);
892         isConverted_ = true;
893     }
894     format_.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, static_cast<int32_t>(targetPixelFmt));
895     std::shared_ptr<AVMemory> &bufferMemory = frameBuffer->avBuffer_->memory_;
896     CHECK_AND_RETURN_RET_LOG(bufferMemory != nullptr, AVCS_ERR_INVALID_VAL, "bufferMemory is nullptr");
897     bufferMemory->SetSize(0);
898     if (surface_) {
899         struct SurfaceInfo surfaceInfo;
900         surfaceInfo.surfaceStride = frameBuffer->sMemory_->GetSurfaceBufferStride();
901         surfaceInfo.surfaceFence = frameBuffer->sMemory_->GetFence();
902         surfaceInfo.scaleData = scaleData_;
903         surfaceInfo.scaleLineSize = scaleLineSize_;
904         ret = WriteSurfaceData(bufferMemory, surfaceInfo, format_);
905     } else {
906         ret = WriteBufferData(bufferMemory, scaleData_, scaleLineSize_, format_);
907     }
908     frameBuffer->avBuffer_->pts_ = cachedFrame_->pts;
909     AVCODEC_LOGD("Fill frame buffer successful");
910     return ret;
911 }
912 
FramePostProcess(std::shared_ptr<FBuffer> & frameBuffer,uint32_t index,int32_t status,int ret)913 void FCodec::FramePostProcess(std::shared_ptr<FBuffer> &frameBuffer, uint32_t index, int32_t status, int ret)
914 {
915     if (status == AVCS_ERR_OK) {
916         codecAvailQue_->Pop();
917         frameBuffer->owner_ = FBuffer::Owner::OWNED_BY_USER;
918         if (surface_) {
919             outAVBuffer4Surface_->pts_ = frameBuffer->avBuffer_->pts_;
920             outAVBuffer4Surface_->flag_ = frameBuffer->avBuffer_->flag_;
921         }
922         if (ret == AVERROR_EOF) {
923             std::unique_lock<std::mutex> sLock(syncMutex_);
924             avcodec_flush_buffers(avCodecContext_.get());
925             sLock.unlock();
926         } else {
927             if (isSendWait_) {
928                 std::lock_guard<std::mutex> sLock(sendMutex_);
929                 isSendWait_ = false;
930                 sendCv_.notify_one();
931             }
932         }
933         callback_->OnOutputBufferAvailable(index, surface_ ? outAVBuffer4Surface_ : frameBuffer->avBuffer_);
934     } else if (status == AVCS_ERR_UNSUPPORT) {
935         AVCODEC_LOGE("Recevie frame from codec failed: OnError");
936         callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNSUPPORT);
937         state_ = State::Error;
938     } else {
939         AVCODEC_LOGE("Recevie frame from codec failed");
940         callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN);
941         state_ = State::Error;
942     }
943 }
944 
ReceiveFrame()945 void FCodec::ReceiveFrame()
946 {
947     if (state_ == State::Stopping || state_ == State::Flushing) {
948         return;
949     } else if (state_ != State::Running) {
950         std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TRY_DECODE_TIME));
951         return;
952     }
953     auto index = codecAvailQue_->Front();
954     CHECK_AND_RETURN_LOG(state_ == State::Running, "Not in running state");
955     std::shared_ptr<FBuffer> frameBuffer = buffers_[INDEX_OUTPUT][index];
956     std::unique_lock<std::mutex> sLock(syncMutex_);
957     int ret = avcodec_receive_frame(avCodecContext_.get(), cachedFrame_.get());
958     sLock.unlock();
959     int32_t status = AVCS_ERR_OK;
960     CHECK_AND_RETURN_LOG(ret != AVERROR_INVALIDDATA, "ffmpeg ret = %{public}s", AVStrError(ret).c_str());
961     if (ret >= 0) {
962         if (CheckFormatChange(index, cachedFrame_->width, cachedFrame_->height) == AVCS_ERR_OK) {
963             CHECK_AND_RETURN_LOG(state_ == State::Running, "Not in running state");
964             frameBuffer = buffers_[INDEX_OUTPUT][index];
965             status = FillFrameBuffer(frameBuffer);
966         } else {
967             CHECK_AND_RETURN_LOG(state_ == State::Running, "Not in running state");
968             callback_->OnError(AVCODEC_ERROR_EXTEND_START, AVCS_ERR_NO_MEMORY);
969             return;
970         }
971         frameBuffer->avBuffer_->flag_ = AVCODEC_BUFFER_FLAG_NONE;
972     } else if (ret == AVERROR_EOF) {
973         AVCODEC_LOGI("Receive eos");
974         frameBuffer->avBuffer_->flag_ = AVCODEC_BUFFER_FLAG_EOS;
975         state_ = State::EOS;
976     } else if (ret == AVERROR(EAGAIN)) {
977         std::unique_lock<std::mutex> sendLock(sendMutex_);
978         if (isSendWait_ || isSendEos_) {
979             isSendWait_ = false;
980             sendCv_.notify_one();
981         }
982         sendLock.unlock();
983         std::unique_lock<std::mutex> recvLock(recvMutex_);
984         recvCv_.wait_for(recvLock, std::chrono::milliseconds(DEFAULT_DECODE_WAIT_TIME));
985         return;
986     } else {
987         callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN);
988         state_ = State::Error;
989         return;
990     }
991     FramePostProcess(frameBuffer, index, status, ret);
992 }
993 
RenderFrame()994 void FCodec::RenderFrame()
995 {
996     if (state_ == State::Stopping || state_ == State::Flushing) {
997         return;
998     } else if (state_ != State::Running && state_ != State::EOS) {
999         AVCODEC_LOGD("Failed to request frame to codec: not in Running or EOS state");
1000         std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TRY_DECODE_TIME));
1001         return;
1002     }
1003     auto index = renderAvailQue_->Front();
1004     CHECK_AND_RETURN_LOG(state_ == State::Running || state_ == State::EOS, "Not in running state");
1005     std::shared_ptr<FBuffer> outputBuffer = buffers_[INDEX_OUTPUT][index];
1006     std::shared_ptr<FSurfaceMemory> surfaceMemory = outputBuffer->sMemory_;
1007     while (state_ == State::Running || state_ == State::EOS) {
1008         std::unique_lock<std::mutex> sLock(surfaceMutex_);
1009         sptr<SurfaceBuffer> surfaceBuffer = surfaceMemory->GetSurfaceBuffer();
1010         sLock.unlock();
1011         if (surfaceBuffer == nullptr) {
1012             std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TRY_DECODE_TIME));
1013             continue;
1014         }
1015         int queSize = renderAvailQue_->Size();
1016         int curIndex = -1;
1017         int i = 0;
1018         for (i = 0; i < queSize; i++) {
1019             curIndex = renderAvailQue_->Pop();
1020             if (surfaceMemory->GetBase() == buffers_[INDEX_OUTPUT][curIndex]->avBuffer_->memory_->GetAddr() &&
1021                 surfaceMemory->GetSize() == buffers_[INDEX_OUTPUT][curIndex]->avBuffer_->memory_->GetCapacity()) {
1022                 buffers_[INDEX_OUTPUT][index]->sMemory_ = buffers_[INDEX_OUTPUT][curIndex]->sMemory_;
1023                 buffers_[INDEX_OUTPUT][curIndex]->sMemory_ = surfaceMemory;
1024                 break;
1025             } else {
1026                 renderAvailQue_->Push(curIndex);
1027             }
1028         }
1029 
1030         if (i == queSize) {
1031             curIndex = index;
1032             outputBuffer->avBuffer_ = AVBuffer::CreateAVBuffer(surfaceMemory->GetBase(), surfaceMemory->GetSize());
1033             outputBuffer->width_ = width_;
1034             outputBuffer->height_ = height_;
1035             renderAvailQue_->Pop();
1036         }
1037         buffers_[INDEX_OUTPUT][curIndex]->owner_ = FBuffer::Owner::OWNED_BY_CODEC;
1038         codecAvailQue_->Push(curIndex);
1039         AVCODEC_LOGD("Request output buffer success, index = %{public}u, queSize=%{public}d, i=%{public}d", curIndex,
1040                      queSize, i);
1041         break;
1042     }
1043 }
1044 
ReleaseOutputBuffer(uint32_t index)1045 int32_t FCodec::ReleaseOutputBuffer(uint32_t index)
1046 {
1047     AVCODEC_SYNC_TRACE;
1048     std::unique_lock<std::mutex> oLock(outputMutex_);
1049     CHECK_AND_RETURN_RET_LOG(index < buffers_[INDEX_OUTPUT].size(), AVCS_ERR_INVALID_VAL,
1050                              "Failed to release output buffer: invalid index");
1051     std::shared_ptr<FBuffer> frameBuffer = buffers_[INDEX_OUTPUT][index];
1052     oLock.unlock();
1053     if (frameBuffer->owner_ == FBuffer::Owner::OWNED_BY_USER) {
1054         frameBuffer->owner_ = FBuffer::Owner::OWNED_BY_CODEC;
1055         codecAvailQue_->Push(index);
1056         return AVCS_ERR_OK;
1057     } else {
1058         AVCODEC_LOGE("Release output buffer failed: check your index=%{public}u", index);
1059         return AVCS_ERR_INVALID_VAL;
1060     }
1061 }
1062 
FlushSurfaceMemory(std::shared_ptr<FSurfaceMemory> & surfaceMemory,int64_t pts)1063 int32_t FCodec::FlushSurfaceMemory(std::shared_ptr<FSurfaceMemory> &surfaceMemory, int64_t pts)
1064 {
1065     sptr<SurfaceBuffer> surfaceBuffer = surfaceMemory->GetSurfaceBuffer();
1066     CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, AVCS_ERR_INVALID_VAL,
1067                              "Failed to update surface memory: surface buffer is NULL");
1068     OHOS::BufferFlushConfig flushConfig = {{0, 0, surfaceBuffer->GetWidth(), surfaceBuffer->GetHeight()}, pts};
1069     surfaceMemory->SetNeedRender(true);
1070     surfaceMemory->UpdateSurfaceBufferScaleMode();
1071     auto res = surface_->FlushBuffer(surfaceBuffer, -1, flushConfig);
1072     if (res != OHOS::SurfaceError::SURFACE_ERROR_OK) {
1073         AVCODEC_LOGW("Failed to update surface memory: %{public}d", res);
1074         surfaceMemory->SetNeedRender(false);
1075         return AVCS_ERR_UNKNOWN;
1076     }
1077     return AVCS_ERR_OK;
1078 }
1079 
RenderOutputBuffer(uint32_t index)1080 int32_t FCodec::RenderOutputBuffer(uint32_t index)
1081 {
1082     AVCODEC_SYNC_TRACE;
1083     std::unique_lock<std::mutex> oLock(outputMutex_);
1084     CHECK_AND_RETURN_RET_LOG(index < buffers_[INDEX_OUTPUT].size(), AVCS_ERR_INVALID_VAL,
1085                              "Failed to render output buffer: invalid index");
1086     std::shared_ptr<FBuffer> frameBuffer = buffers_[INDEX_OUTPUT][index];
1087     oLock.unlock();
1088     if (frameBuffer->owner_ == FBuffer::Owner::OWNED_BY_USER) {
1089         std::shared_ptr<FSurfaceMemory> surfaceMemory = frameBuffer->sMemory_;
1090         int32_t ret = FlushSurfaceMemory(surfaceMemory, frameBuffer->avBuffer_->pts_);
1091         if (ret != AVCS_ERR_OK) {
1092             AVCODEC_LOGW("Update surface memory failed: %{public}d", static_cast<int32_t>(ret));
1093         } else {
1094             AVCODEC_LOGD("Update surface memory successful");
1095         }
1096         surfaceMemory->ReleaseSurfaceBuffer();
1097         frameBuffer->owner_ = FBuffer::Owner::OWNED_BY_SURFACE;
1098         renderAvailQue_->Push(index);
1099         AVCODEC_LOGD("render output buffer with index, index=%{public}u", index);
1100         return AVCS_ERR_OK;
1101     } else {
1102         AVCODEC_LOGE("Failed to render output buffer with bad index, index=%{public}u", index);
1103         return AVCS_ERR_INVALID_VAL;
1104     }
1105 }
1106 
SetOutputSurface(sptr<Surface> surface)1107 int32_t FCodec::SetOutputSurface(sptr<Surface> surface)
1108 {
1109     AVCODEC_SYNC_TRACE;
1110     surface_ = surface;
1111     if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_SCALE_TYPE)) {
1112         format_.PutIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE,
1113                             static_cast<int32_t>(ScalingMode::SCALING_MODE_SCALE_TO_WINDOW));
1114     }
1115     if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE)) {
1116         format_.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE,
1117                             static_cast<int32_t>(VideoRotation::VIDEO_ROTATION_0));
1118     }
1119 
1120     if (renderTask_ == nullptr) {
1121         renderTask_ = std::make_shared<TaskThread>("RenderFrame");
1122         renderTask_->RegisterHandler([this] { (void)RenderFrame(); });
1123     }
1124     outAVBuffer4Surface_ = AVBuffer::CreateAVBuffer();
1125     AVCODEC_LOGI("Set surface success");
1126     return AVCS_ERR_OK;
1127 }
1128 
SetCallback(const std::shared_ptr<MediaCodecCallback> & callback)1129 int32_t FCodec::SetCallback(const std::shared_ptr<MediaCodecCallback> &callback)
1130 {
1131     AVCODEC_SYNC_TRACE;
1132     CHECK_AND_RETURN_RET_LOG(callback != nullptr, AVCS_ERR_INVALID_VAL, "Set callback failed: callback is NULL");
1133     callback_ = callback;
1134     return AVCS_ERR_OK;
1135 }
1136 
GetCodecCapability(std::vector<CapabilityData> & capaArray)1137 int32_t FCodec::GetCodecCapability(std::vector<CapabilityData> &capaArray)
1138 {
1139     for (uint32_t i = 0; i < SUPPORT_VCODEC_NUM; ++i) {
1140         CapabilityData capsData;
1141         capsData.codecName = static_cast<std::string>(SUPPORT_VCODEC[i].codecName);
1142         capsData.mimeType = static_cast<std::string>(SUPPORT_VCODEC[i].mimeType);
1143         capsData.codecType = SUPPORT_VCODEC[i].isEncoder ? AVCODEC_TYPE_VIDEO_ENCODER : AVCODEC_TYPE_VIDEO_DECODER;
1144         capsData.isVendor = false;
1145         capsData.maxInstance = VIDEO_INSTANCE_SIZE;
1146         capsData.alignment.width = VIDEO_ALIGNMENT_SIZE;
1147         capsData.alignment.height = VIDEO_ALIGNMENT_SIZE;
1148         capsData.width.minVal = VIDEO_MIN_SIZE;
1149         capsData.width.maxVal = VIDEO_MAX_WIDTH_SIZE;
1150         capsData.height.minVal = VIDEO_MIN_SIZE;
1151         capsData.height.maxVal = VIDEO_MAX_HEIGHT_SIZE;
1152         capsData.frameRate.minVal = 0;
1153         capsData.frameRate.maxVal = VIDEO_FRAMERATE_MAX_SIZE;
1154         capsData.bitrate.minVal = 1;
1155         capsData.bitrate.maxVal = VIDEO_BITRATE_MAX_SIZE;
1156         capsData.blockPerFrame.minVal = 1;
1157         capsData.blockPerFrame.maxVal = VIDEO_BLOCKPERFRAME_SIZE;
1158         capsData.blockPerSecond.minVal = 1;
1159         capsData.blockPerSecond.maxVal = VIDEO_BLOCKPERSEC_SIZE;
1160         capsData.blockSize.width = VIDEO_ALIGN_SIZE;
1161         capsData.blockSize.height = VIDEO_ALIGN_SIZE;
1162         if (SUPPORT_VCODEC[i].isEncoder) {
1163             capsData.complexity.minVal = 0;
1164             capsData.complexity.maxVal = 0;
1165             capsData.encodeQuality.minVal = 0;
1166             capsData.encodeQuality.maxVal = 0;
1167         }
1168         capsData.pixFormat = {
1169             static_cast<int32_t>(VideoPixelFormat::YUVI420), static_cast<int32_t>(VideoPixelFormat::NV12),
1170             static_cast<int32_t>(VideoPixelFormat::NV21), static_cast<int32_t>(VideoPixelFormat::RGBA)};
1171         capsData.profiles = {static_cast<int32_t>(AVC_PROFILE_BASELINE), static_cast<int32_t>(AVC_PROFILE_MAIN),
1172                              static_cast<int32_t>(AVC_PROFILE_HIGH)};
1173         std::vector<int32_t> levels;
1174         for (int32_t j = 0; j <= static_cast<int32_t>(AVCLevel::AVC_LEVEL_51); ++j) {
1175             levels.emplace_back(j);
1176         }
1177         capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(AVC_PROFILE_MAIN), levels));
1178         capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(AVC_PROFILE_HIGH), levels));
1179         capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(AVC_PROFILE_BASELINE), levels));
1180         capaArray.emplace_back(capsData);
1181     }
1182     return AVCS_ERR_OK;
1183 }
1184 } // namespace Codec
1185 } // namespace MediaAVCodec
1186 } // namespace OHOS