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