• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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