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