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