1 /*
2 * Copyright (c) 2024-2024 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 "video_encoder.h"
17 #include <cstdint>
18 #include <string>
19 #include <unordered_map>
20 #include "frame_record.h"
21 #include "surface_type.h"
22 #include "external_window.h"
23 #include "avcodec_common.h"
24 #include "native_avbuffer.h"
25 #include "camera_log.h"
26 #include <chrono>
27 #include <fcntl.h>
28 #include <cinttypes>
29 #include <unistd.h>
30 #include <memory>
31 #include <sync_fence.h>
32 #include "native_mfmagic.h"
33 #include "media_description.h"
34
35 namespace OHOS {
36 namespace CameraStandard {
37
~VideoEncoder()38 VideoEncoder::~VideoEncoder()
39 {
40 MEDIA_INFO_LOG("~VideoEncoder enter");
41 Release();
42 }
43
VideoEncoder(VideoCodecType type,ColorSpace colorSpace)44 VideoEncoder::VideoEncoder(VideoCodecType type, ColorSpace colorSpace) : videoCodecType_(type),
45 isHdr_(IsHdr(colorSpace))
46 {
47 MEDIA_INFO_LOG("VideoEncoder enter");
48 }
49
IsHdr(ColorSpace colorSpace)50 bool VideoEncoder::IsHdr(ColorSpace colorSpace)
51 {
52 std::vector<ColorSpace> hdrColorSpaces = {BT2020_HLG, BT2020_PQ, BT2020_HLG_LIMIT,
53 BT2020_PQ_LIMIT};
54 auto it = std::find(hdrColorSpaces.begin(), hdrColorSpaces.end(), colorSpace);
55 return it != hdrColorSpaces.end();
56 }
57
Create(const std::string & codecMime)58 int32_t VideoEncoder::Create(const std::string &codecMime)
59 {
60 std::lock_guard<std::mutex> lock(encoderMutex_);
61 encoder_ = VideoEncoderFactory::CreateByMime(codecMime);
62 CHECK_ERROR_RETURN_RET_LOG(encoder_ == nullptr, 1, "Create failed");
63 return 0;
64 }
65
Config()66 int32_t VideoEncoder::Config()
67 {
68 std::lock_guard<std::mutex> lock(encoderMutex_);
69 CHECK_ERROR_RETURN_RET_LOG(encoder_ == nullptr, 1, "Encoder is null");
70 std::unique_lock<std::mutex> contextLock(contextMutex_);
71 context_ = new VideoCodecUserData;
72 // Configure video encoder
73 int32_t ret = Configure();
74 CHECK_ERROR_RETURN_RET_LOG(ret != AV_ERR_OK, 1, "Configure failed");
75 // SetCallback for video encoder
76 ret = SetCallback();
77 CHECK_ERROR_RETURN_RET_LOG(ret != AV_ERR_OK, 1, "Set callback failed");
78 contextLock.unlock();
79 return 0;
80 }
81
Start()82 int32_t VideoEncoder::Start()
83 {
84 std::lock_guard<std::mutex> lock(encoderMutex_);
85 CHECK_ERROR_RETURN_RET_LOG(encoder_ == nullptr, 1, "Encoder is null");
86 // Prepare video encoder
87 int ret = encoder_->Prepare();
88 CHECK_ERROR_RETURN_RET_LOG(ret != AV_ERR_OK, 1, "Prepare failed, ret: %{public}d", ret);
89 // Start video encoder
90 ret = encoder_->Start();
91 CHECK_ERROR_RETURN_RET_LOG(ret != AV_ERR_OK, 1, "Start failed, ret: %{public}d", ret);
92 isStarted_ = true;
93 return 0;
94 }
95
GetSurface()96 int32_t VideoEncoder::GetSurface()
97 {
98 std::lock_guard<std::mutex> lock(encoderMutex_);
99 CHECK_ERROR_RETURN_RET_LOG(encoder_ == nullptr, 1, "Encoder is null");
100 std::lock_guard<std::mutex> surfaceLock(surfaceMutex_);
101 codecSurface_ = encoder_->CreateInputSurface();
102 CHECK_ERROR_RETURN_RET_LOG(codecSurface_ == nullptr, 1, "Surface is null");
103 return 0;
104 }
105
ReleaseSurfaceBuffer(sptr<FrameRecord> frameRecord)106 int32_t VideoEncoder::ReleaseSurfaceBuffer(sptr<FrameRecord> frameRecord)
107 {
108 CAMERA_SYNC_TRACE;
109 CHECK_ERROR_RETURN_RET_LOG(frameRecord->GetSurfaceBuffer() == nullptr, 1,
110 "SurfaceBuffer is released %{public}s", frameRecord->GetFrameId().c_str());
111 sptr<SurfaceBuffer> releaseBuffer;
112 int32_t ret = DetachCodecBuffer(releaseBuffer, frameRecord);
113 CHECK_ERROR_RETURN_RET_LOG(ret != SURFACE_ERROR_OK, ret, " %{public}s ReleaseSurfaceBuffer failed",
114 frameRecord->GetFrameId().c_str());
115 frameRecord->SetSurfaceBuffer(releaseBuffer);
116 // after request surfaceBuffer
117 frameRecord->NotifyBufferRelease();
118 MEDIA_INFO_LOG("release codec surface buffer end");
119 return 0;
120 }
121
DetachCodecBuffer(sptr<SurfaceBuffer> & surfaceBuffer,sptr<FrameRecord> frameRecord)122 int32_t VideoEncoder::DetachCodecBuffer(sptr<SurfaceBuffer> &surfaceBuffer, sptr<FrameRecord> frameRecord)
123 {
124 CHECK_ERROR_RETURN_RET_LOG(frameRecord == nullptr, 1, "frameRecord is null");
125 std::lock_guard<std::mutex> lock(surfaceMutex_);
126 CHECK_ERROR_RETURN_RET_LOG(codecSurface_ == nullptr, 1, "codecSurface_ is null");
127 sptr<SyncFence> syncFence = SyncFence::INVALID_FENCE;
128 BufferRequestConfig requestConfig = {
129 .width = frameRecord->GetFrameSize()->width,
130 .height = frameRecord->GetFrameSize()->height,
131 .strideAlignment = 0x8, // default stride is 8 Bytes.
132 .format = frameRecord->GetFormat(),
133 .usage = frameRecord->GetUsage(),
134 .timeout = 0,
135 };
136 SurfaceError ret = codecSurface_->RequestBuffer(surfaceBuffer, syncFence, requestConfig);
137 CHECK_ERROR_RETURN_RET_LOG(ret != SURFACE_ERROR_OK, ret, "RequestBuffer failed. %{public}d", ret);
138 constexpr uint32_t waitForEver = -1;
139 (void)syncFence->Wait(waitForEver);
140 CHECK_ERROR_RETURN_RET_LOG(surfaceBuffer == nullptr, ret, "Failed to request codec Buffer");
141 ret = codecSurface_->DetachBufferFromQueue(surfaceBuffer);
142 CHECK_ERROR_RETURN_RET_LOG(ret != SURFACE_ERROR_OK, ret, "Failed to detach buffer %{public}d", ret);
143 return ret;
144 }
145
PushInputData(sptr<CodecAVBufferInfo> info)146 int32_t VideoEncoder::PushInputData(sptr<CodecAVBufferInfo> info)
147 {
148 std::lock_guard<std::mutex> lock(encoderMutex_);
149 CHECK_ERROR_RETURN_RET_LOG(encoder_ == nullptr, 1, "Decoder is null");
150 int32_t ret = AV_ERR_OK;
151 ret = OH_AVBuffer_SetBufferAttr(info->buffer, &info->attr);
152 CHECK_ERROR_RETURN_RET_LOG(ret != AV_ERR_OK, 1, "Set avbuffer attr failed, ret: %{public}d", ret);
153 ret = encoder_->QueueInputBuffer(info->bufferIndex);
154 CHECK_ERROR_RETURN_RET_LOG(ret != AV_ERR_OK, 1, "Push input data failed, ret: %{public}d", ret);
155 return 0;
156 }
157
NotifyEndOfStream()158 int32_t VideoEncoder::NotifyEndOfStream()
159 {
160 std::lock_guard<std::mutex> lock(encoderMutex_);
161 CHECK_ERROR_RETURN_RET_LOG(encoder_ == nullptr, 1, "Encoder is null");
162 int32_t ret = encoder_->NotifyEos();
163 CHECK_ERROR_RETURN_RET_LOG(ret != AV_ERR_OK, 1,
164 "Notify end of stream failed, ret: %{public}d", ret);
165 return 0;
166 }
167
FreeOutputData(uint32_t bufferIndex)168 int32_t VideoEncoder::FreeOutputData(uint32_t bufferIndex)
169 {
170 int32_t ret = encoder_->ReleaseOutputBuffer(bufferIndex);
171 CHECK_ERROR_RETURN_RET_LOG(ret != AV_ERR_OK, 1,
172 "Free output data failed, ret: %{public}d", ret);
173 return 0;
174 }
175
Stop()176 int32_t VideoEncoder::Stop()
177 {
178 CAMERA_SYNC_TRACE;
179 std::lock_guard<std::mutex> lock(encoderMutex_);
180 CHECK_ERROR_RETURN_RET_LOG(encoder_ == nullptr, 1, "Encoder is null");
181 int ret = encoder_->Stop();
182 CHECK_ERROR_RETURN_RET_LOG(ret != AV_ERR_OK, 1, "Stop failed, ret: %{public}d", ret);
183 isStarted_ = false;
184 return 0;
185 }
186
RestartVideoCodec(shared_ptr<Size> size,int32_t rotation)187 void VideoEncoder::RestartVideoCodec(shared_ptr<Size> size, int32_t rotation)
188 {
189 Release();
190 size_ = size;
191 rotation_ = rotation;
192 MEDIA_INFO_LOG("VideoEncoder videoCodecType_ = %{public}d", videoCodecType_);
193 if (videoCodecType_ == VideoCodecType::VIDEO_ENCODE_TYPE_AVC) {
194 Create(MIME_VIDEO_AVC.data());
195 } else if (videoCodecType_ == VideoCodecType::VIDEO_ENCODE_TYPE_HEVC) {
196 Create(MIME_VIDEO_HEVC.data());
197 }
198 Config();
199 GetSurface();
200 Start();
201 }
202
EnqueueBuffer(sptr<FrameRecord> frameRecord,int32_t keyFrameInterval)203 bool VideoEncoder::EnqueueBuffer(sptr<FrameRecord> frameRecord, int32_t keyFrameInterval)
204 {
205 CHECK_EXECUTE(!isStarted_ || encoder_ == nullptr || size_ == nullptr,
206 RestartVideoCodec(frameRecord->GetFrameSize(), frameRecord->GetRotation()));
207 if (keyFrameInterval == KEY_FRAME_INTERVAL) {
208 std::lock_guard<std::mutex> lock(encoderMutex_);
209 MediaAVCodec::Format format = MediaAVCodec::Format();
210 format.PutIntValue(MediaDescriptionKey::MD_KEY_REQUEST_I_FRAME, true);
211 encoder_->SetParameter(format);
212 }
213 sptr<SurfaceBuffer> buffer = frameRecord->GetSurfaceBuffer();
214 CHECK_ERROR_RETURN_RET_LOG(buffer == nullptr, false, "Enqueue video buffer is empty");
215 std::lock_guard<std::mutex> lock(surfaceMutex_);
216 CHECK_ERROR_RETURN_RET_LOG(codecSurface_ == nullptr, false, "codecSurface_ is null");
217 SurfaceError surfaceRet = codecSurface_->AttachBufferToQueue(buffer);
218 if (surfaceRet != SURFACE_ERROR_OK) {
219 MEDIA_ERR_LOG("Failed to attach buffer, surfaceRet: %{public}d", surfaceRet);
220 // notify release buffer when attach failed
221 frameRecord->NotifyBufferRelease();
222 return false;
223 }
224 constexpr int32_t invalidFence = -1;
225 BufferFlushConfig flushConfig = {
226 .damage = {
227 .w = buffer->GetWidth(),
228 .h = buffer->GetHeight(),
229 },
230 .timestamp = frameRecord->GetTimeStamp(),
231 };
232 surfaceRet = codecSurface_->FlushBuffer(buffer, invalidFence, flushConfig);
233 CHECK_ERROR_RETURN_RET_LOG(surfaceRet != 0, false, "FlushBuffer failed");
234 MEDIA_DEBUG_LOG("Success frame id is : %{public}s", frameRecord->GetFrameId().c_str());
235 return true;
236 }
237
EncodeSurfaceBuffer(sptr<FrameRecord> frameRecord)238 bool VideoEncoder::EncodeSurfaceBuffer(sptr<FrameRecord> frameRecord)
239 {
240 if (frameRecord->GetTimeStamp() - preFrameTimestamp_ > NANOSEC_RANGE) {
241 keyFrameInterval_ = KEY_FRAME_INTERVAL;
242 } else {
243 keyFrameInterval_ = (keyFrameInterval_ == 0 ? KEY_FRAME_INTERVAL : keyFrameInterval_);
244 }
245 preFrameTimestamp_ = frameRecord->GetTimeStamp();
246 CHECK_ERROR_RETURN_RET(!EnqueueBuffer(frameRecord, keyFrameInterval_), false);
247 keyFrameInterval_--;
248 int32_t retryCount = 5;
249 while (retryCount > 0) {
250 retryCount--;
251 std::unique_lock<std::mutex> contextLock(contextMutex_);
252 CHECK_ERROR_RETURN_RET_LOG(context_ == nullptr, false, "VideoEncoder has been released");
253 std::unique_lock<std::mutex> lock(context_->outputMutex_);
254 bool condRet = context_->outputCond_.wait_for(lock, std::chrono::milliseconds(BUFFER_ENCODE_EXPIREATION_TIME),
255 [this]() { return !isStarted_ || !context_->outputBufferInfoQueue_.empty(); });
256 CHECK_WARNING_CONTINUE_LOG(context_->outputBufferInfoQueue_.empty(),
257 "Buffer queue is empty, continue, cond ret: %{public}d", condRet);
258 sptr<VideoCodecAVBufferInfo> bufferInfo = context_->outputBufferInfoQueue_.front();
259 CHECK_ERROR_RETURN_RET_LOG(bufferInfo->buffer->memory_ == nullptr, false, "memory is alloced failed!");
260 MEDIA_INFO_LOG("Out buffer count: %{public}u, size: %{public}d, flag: %{public}u, pts:%{public}" PRIu64 ", "
261 "timestamp:%{public}" PRIu64, context_->outputFrameCount_, bufferInfo->buffer->memory_->GetSize(),
262 bufferInfo->buffer->flag_, bufferInfo->buffer->pts_, frameRecord->GetTimeStamp());
263 context_->outputBufferInfoQueue_.pop();
264 context_->outputFrameCount_++;
265 lock.unlock();
266 contextLock.unlock();
267 std::lock_guard<std::mutex> encodeLock(encoderMutex_);
268 CHECK_ERROR_RETURN_RET_LOG(!isStarted_ || encoder_ == nullptr, false, "EncodeSurfaceBuffer when encoder stop!");
269 if (bufferInfo->buffer->flag_ == AVCODEC_BUFFER_FLAGS_CODEC_DATA) {
270 // first return IDR frame
271 std::shared_ptr<Media::AVBuffer> IDRBuffer = bufferInfo->GetCopyAVBuffer();
272 frameRecord->CacheBuffer(IDRBuffer);
273 frameRecord->SetIDRProperty(true);
274 successFrame_ = false;
275 } else if (bufferInfo->buffer->flag_ == AVCODEC_BUFFER_FLAGS_SYNC_FRAME) {
276 // then return I frame
277 std::shared_ptr<Media::AVBuffer> tempBuffer = bufferInfo->AddCopyAVBuffer(frameRecord->encodedBuffer);
278 if (tempBuffer != nullptr) {
279 frameRecord->encodedBuffer = tempBuffer;
280 }
281 successFrame_ = true;
282 } else if (bufferInfo->buffer->flag_ == AVCODEC_BUFFER_FLAGS_NONE) {
283 // return P frame
284 std::shared_ptr<Media::AVBuffer> PBuffer = bufferInfo->GetCopyAVBuffer();
285 frameRecord->CacheBuffer(PBuffer);
286 frameRecord->SetIDRProperty(false);
287 successFrame_ = true;
288 } else {
289 MEDIA_ERR_LOG("Flag is not acceptted number: %{public}u", bufferInfo->buffer->flag_);
290 int32_t ret = FreeOutputData(bufferInfo->bufferIndex);
291 CHECK_WARNING_BREAK_LOG(ret != 0, "FreeOutputData failed");
292 continue;
293 }
294 int32_t ret = FreeOutputData(bufferInfo->bufferIndex);
295 CHECK_WARNING_BREAK_LOG(ret != 0, "FreeOutputData failed");
296 if (successFrame_) {
297 MEDIA_DEBUG_LOG("Success frame id is : %{public}s, refCount: %{public}d",
298 frameRecord->GetFrameId().c_str(), frameRecord->GetSptrRefCount());
299 return true;
300 }
301 }
302 MEDIA_ERR_LOG("Failed frame id is : %{public}s", frameRecord->GetFrameId().c_str());
303 return false;
304 }
305
Release()306 int32_t VideoEncoder::Release()
307 {
308 {
309 std::lock_guard<std::mutex> lock(encoderMutex_);
310 if (encoder_ != nullptr) {
311 encoder_->Release();
312 }
313 }
314 std::unique_lock<std::mutex> contextLock(contextMutex_);
315 isStarted_ = false;
316 return 0;
317 }
318
OnError(AVCodecErrorType errorType,int32_t errorCode)319 void VideoEncoder::CallBack::OnError(AVCodecErrorType errorType, int32_t errorCode)
320 {
321 (void)errorCode;
322 MEDIA_ERR_LOG("On decoder error, error code: %{public}d", errorCode);
323 }
324
OnOutputFormatChanged(const Format & format)325 void VideoEncoder::CallBack::OnOutputFormatChanged(const Format &format)
326 {
327 MEDIA_ERR_LOG("OnCodecFormatChange");
328 }
329
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)330 void VideoEncoder::CallBack::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
331 {
332 MEDIA_DEBUG_LOG("OnInputBufferAvailable");
333 }
334
OnOutputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)335 void VideoEncoder::CallBack::OnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
336 {
337 MEDIA_DEBUG_LOG("OnOutputBufferAvailable");
338 auto encoder = videoEncoder_.lock();
339 CHECK_ERROR_RETURN_LOG(encoder == nullptr, "encoder is nullptr");
340 CHECK_ERROR_RETURN_LOG(encoder->context_ == nullptr, "encoder context is nullptr");
341 std::unique_lock<std::mutex> lock(encoder->context_->outputMutex_);
342 encoder->context_->outputBufferInfoQueue_.emplace(new VideoCodecAVBufferInfo(index, buffer));
343 encoder->context_->outputCond_.notify_all();
344 }
345
SetCallback()346 int32_t VideoEncoder::SetCallback()
347 {
348 int32_t ret = AV_ERR_OK;
349 auto callback = make_shared<CallBack>(weak_from_this());
350 ret = encoder_->SetCallback(callback);
351 CHECK_ERROR_RETURN_RET_LOG(ret != AV_ERR_OK, 1, "Set callback failed, ret: %{public}d", ret);
352 return 0;
353 }
354
Configure()355 int32_t VideoEncoder::Configure()
356 {
357 MediaAVCodec::Format format = MediaAVCodec::Format();
358 int32_t bitrate = static_cast<int32_t>(pow(float(size_->width) * float(size_->height) / DEFAULT_SIZE,
359 VIDEO_BITRATE_CONSTANT) * BITRATE_22M);
360 bitrate_ = videoCodecType_ == VideoCodecType::VIDEO_ENCODE_TYPE_AVC
361 ? static_cast<int32_t>(bitrate * HEVC_TO_AVC_FACTOR) : bitrate;
362 MEDIA_INFO_LOG("Current resolution is : %{public}d*%{public}d, encode type : %{public}d, set bitrate : %{public}d",
363 size_->width, size_->height, videoCodecType_, bitrate_);
364 format.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, size_->width);
365 format.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, size_->height);
366 format.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, rotation_);
367 format.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, VIDEO_FRAME_RATE);
368 format.PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, VBR);
369 format.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, bitrate_);
370 format.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, VIDOE_PIXEL_FORMAT);
371 format.PutIntValue(MediaDescriptionKey::MD_KEY_I_FRAME_INTERVAL, INT_MAX);
372 if (videoCodecType_ == VideoCodecType::VIDEO_ENCODE_TYPE_HEVC && isHdr_) {
373 format.PutIntValue(MediaDescriptionKey::MD_KEY_PROFILE, HEVC_PROFILE_MAIN_10);
374 }
375 int ret = encoder_->Configure(format);
376 CHECK_ERROR_RETURN_RET_LOG(ret != AV_ERR_OK, 1, "Config failed, ret: %{public}d", ret);
377 return 0;
378 }
379 } // CameraStandard
380 } // OHOS