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 "sample_callback.h"
18 #include "camera_log.h"
19 #include <sync_fence.h>
20 #include "native_window.h"
21 
22 namespace OHOS {
23 namespace CameraStandard {
24 
~VideoEncoder()25 VideoEncoder::~VideoEncoder()
26 {
27     MEDIA_INFO_LOG("~VideoEncoder enter");
28     if (codecSurface_) {
29         MEDIA_INFO_LOG("codecSurface refCount %{public}d", codecSurface_->GetSptrRefCount());
30     }
31     Release();
32 }
33 
VideoEncoder(VideoCodecType type)34 VideoEncoder::VideoEncoder(VideoCodecType type) : videoCodecType_(type)
35 {
36     rotation_ = 0;
37     MEDIA_INFO_LOG("VideoEncoder enter");
38 }
39 
Create(const std::string & codecMime)40 int32_t VideoEncoder::Create(const std::string &codecMime)
41 {
42     std::lock_guard<std::mutex> lock(encoderMutex_);
43     encoder_ = OH_VideoEncoder_CreateByMime(codecMime.data());
44     CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, 1, "Create failed");
45     return 0;
46 }
47 
Config()48 int32_t VideoEncoder::Config()
49 {
50     std::lock_guard<std::mutex> lock(encoderMutex_);
51     CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, 1, "Encoder is null");
52     std::unique_lock<std::mutex> contextLock(contextMutex_);
53     context_ = new CodecUserData;
54     // Configure video encoder
55     int32_t ret = Configure();
56     CHECK_AND_RETURN_RET_LOG(ret == 0, 1, "Configure failed");
57     // SetCallback for video encoder
58     ret = SetCallback(context_);
59     CHECK_AND_RETURN_RET_LOG(ret == 0, 1, "Set callback failed");
60     contextLock.unlock();
61     return 0;
62 }
63 
Start()64 int32_t VideoEncoder::Start()
65 {
66     std::lock_guard<std::mutex> lock(encoderMutex_);
67     CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, 1, "Encoder is null");
68      // Prepare video encoder
69     int ret = OH_VideoEncoder_Prepare(encoder_);
70     CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1, "Prepare failed, ret: %{public}d", ret);
71     // Start video encoder
72     ret = OH_VideoEncoder_Start(encoder_);
73     CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1, "Start failed, ret: %{public}d", ret);
74     isStarted_ = true;
75     return 0;
76 }
77 
GetSurface()78 int32_t VideoEncoder::GetSurface()
79 {
80     std::lock_guard<std::mutex> lock(encoderMutex_);
81     OHNativeWindow *nativeWindow;
82     CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, 1, "Encoder is null");
83     int ret = OH_VideoEncoder_GetSurface(encoder_, &nativeWindow);
84     CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1, "Get surface failed, ret: %{public}d", ret);
85     surfaceMutex_.lock();
86     codecSurface_ = nativeWindow->surface;
87     OH_NativeWindow_DestroyNativeWindow(nativeWindow);
88     CHECK_AND_RETURN_RET_LOG(codecSurface_ != nullptr, 1, "Surface is null");
89     surfaceMutex_.unlock();
90     return 0;
91 }
92 
ReleaseSurfaceBuffer(sptr<FrameRecord> frameRecord)93 int32_t VideoEncoder::ReleaseSurfaceBuffer(sptr<FrameRecord> frameRecord)
94 {
95     CAMERA_SYNC_TRACE;
96     CHECK_AND_RETURN_RET_LOG(frameRecord->GetSurfaceBuffer() != nullptr, 1,
97         "SurfaceBuffer is released %{public}s", frameRecord->GetFrameId().c_str());
98     sptr<SyncFence> syncFence = SyncFence::INVALID_FENCE;
99     BufferRequestConfig requestConfig = {
100         .width = frameRecord->GetFrameSize()->width,
101         .height = frameRecord->GetFrameSize()->height,
102         .strideAlignment = 0x8, // default stride is 8 Bytes.
103         .format = frameRecord->GetFormat(),
104         .usage = frameRecord->GetUsage(),
105         .timeout = 0,
106     };
107     sptr<SurfaceBuffer> releaseBuffer;
108     {
109         std::lock_guard<std::mutex> lock(surfaceMutex_);
110         CHECK_AND_RETURN_RET_LOG(codecSurface_ != nullptr, 1, "codecSurface_ is null");
111         SurfaceError ret = codecSurface_->RequestBuffer(releaseBuffer, syncFence, requestConfig);
112         if (ret != SURFACE_ERROR_OK) {
113             MEDIA_ERR_LOG("RequestBuffer failed. %{public}d", ret);
114             return ret;
115         }
116         constexpr uint32_t waitForEver = -1;
117         (void)syncFence->Wait(waitForEver);
118 
119         if (!releaseBuffer) {
120             MEDIA_ERR_LOG("Failed to requestBuffer, %{public}s", frameRecord->GetFrameId().c_str());
121             return ret;
122         }
123         ret = codecSurface_->DetachBufferFromQueue(releaseBuffer);
124         if (ret != SURFACE_ERROR_OK) {
125             MEDIA_ERR_LOG("Failed to detach buffer");
126             return ret;
127         }
128     }
129     frameRecord->SetSurfaceBuffer(releaseBuffer);
130     // after request surfaceBuffer
131     frameRecord->NotifyBufferRelease();
132     MEDIA_INFO_LOG("release codec surface buffer end");
133     return 0;
134 }
135 
PushInputData(sptr<CodecAVBufferInfo> info)136 int32_t VideoEncoder::PushInputData(sptr<CodecAVBufferInfo> info)
137 {
138     std::lock_guard<std::mutex> lock(encoderMutex_);
139     CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, 1, "Decoder is null");
140     int32_t ret = AV_ERR_OK;
141     ret = OH_AVBuffer_SetBufferAttr(info->buffer, &info->attr);
142     CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1, "Set avbuffer attr failed, ret: %{public}d", ret);
143     ret = OH_VideoEncoder_PushInputBuffer(encoder_, info->bufferIndex);
144     CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1, "Push input data failed, ret: %{public}d", ret);
145     return 0;
146 }
147 
NotifyEndOfStream()148 int32_t VideoEncoder::NotifyEndOfStream()
149 {
150     std::lock_guard<std::mutex> lock(encoderMutex_);
151     CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, 1, "Encoder is null");
152     int32_t ret = OH_VideoEncoder_NotifyEndOfStream(encoder_);
153     CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1,
154         "Notify end of stream failed, ret: %{public}d", ret);
155     return 0;
156 }
157 
FreeOutputData(uint32_t bufferIndex)158 int32_t VideoEncoder::FreeOutputData(uint32_t bufferIndex)
159 {
160     std::lock_guard<std::mutex> lock(encoderMutex_);
161     CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, 1, "Encoder is null");
162     int32_t ret = OH_VideoEncoder_FreeOutputBuffer(encoder_, bufferIndex);
163     CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1,
164         "Free output data failed, ret: %{public}d", ret);
165     return 0;
166 }
167 
Stop()168 int32_t VideoEncoder::Stop()
169 {
170     CAMERA_SYNC_TRACE;
171     std::lock_guard<std::mutex> lock(encoderMutex_);
172     CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, 1, "Encoder is null");
173     int ret = OH_VideoEncoder_Stop(encoder_);
174     CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1, "Stop failed, ret: %{public}d", ret);
175     isStarted_ = false;
176     return 0;
177 }
178 
RestartVideoCodec(shared_ptr<Size> size,int32_t rotation)179 void VideoEncoder::RestartVideoCodec(shared_ptr<Size> size, int32_t rotation)
180 {
181     Release();
182     size_ = size;
183     rotation_ = rotation;
184     MEDIA_INFO_LOG("VideoEncoder videoCodecType_ = %{public}d", videoCodecType_);
185     if (videoCodecType_ == VideoCodecType::VIDEO_ENCODE_TYPE_AVC) {
186         Create(MIME_VIDEO_AVC.data());
187     } else if (videoCodecType_ == VideoCodecType::VIDEO_ENCODE_TYPE_HEVC) {
188         Create(MIME_VIDEO_HEVC.data());
189     }
190     Config();
191     GetSurface();
192     Start();
193 }
194 
EnqueueBuffer(sptr<FrameRecord> frameRecord,int32_t keyFrameInterval)195 bool VideoEncoder::EnqueueBuffer(sptr<FrameRecord> frameRecord, int32_t keyFrameInterval)
196 {
197     if (!isStarted_ || encoder_ == nullptr || size_ == nullptr) {
198         RestartVideoCodec(frameRecord->GetFrameSize(), frameRecord->GetRotation());
199     }
200     if (keyFrameInterval == KEY_FRAME_INTERVAL) {
201         std::lock_guard<std::mutex> lock(encoderMutex_);
202         OH_AVFormat *format = OH_AVFormat_Create();
203         OH_AVFormat_SetIntValue(format, OH_MD_KEY_REQUEST_I_FRAME, true);
204         OH_VideoEncoder_SetParameter(encoder_, format);
205         OH_AVFormat_Destroy(format);
206     }
207     sptr<SurfaceBuffer> buffer = frameRecord->GetSurfaceBuffer();
208     if (buffer == nullptr) {
209         MEDIA_ERR_LOG("Enqueue video buffer is empty");
210         return false;
211     }
212     std::lock_guard<std::mutex> lock(surfaceMutex_);
213     CHECK_AND_RETURN_RET_LOG(codecSurface_ != nullptr, false, "codecSurface_ is null");
214     SurfaceError surfaceRet = codecSurface_->AttachBufferToQueue(buffer);
215     if (surfaceRet != SURFACE_ERROR_OK) {
216         MEDIA_ERR_LOG("Failed to attach buffer, surfaceRet: %{public}d", surfaceRet);
217         // notify release buffer when attach failed
218         frameRecord->NotifyBufferRelease();
219         return false;
220     }
221     constexpr int32_t invalidFence = -1;
222     BufferFlushConfig flushConfig = {
223         .damage = {
224             .w = buffer->GetWidth(),
225             .h = buffer->GetHeight(),
226         },
227         .timestamp = frameRecord->GetTimeStamp(),
228     };
229     surfaceRet = codecSurface_->FlushBuffer(buffer, invalidFence, flushConfig);
230     CHECK_AND_RETURN_RET_LOG(surfaceRet == 0, false, "FlushBuffer failed");
231     MEDIA_DEBUG_LOG("Success frame id is : %{public}s", frameRecord->GetFrameId().c_str());
232     return true;
233 }
234 
EncodeSurfaceBuffer(sptr<FrameRecord> frameRecord)235 bool VideoEncoder::EncodeSurfaceBuffer(sptr<FrameRecord> frameRecord)
236 {
237     if (frameRecord->GetTimeStamp() - preFrameTimestamp_ > NANOSEC_RANGE) {
238         keyFrameInterval_ = KEY_FRAME_INTERVAL;
239     } else {
240         keyFrameInterval_ = (keyFrameInterval_ == 0 ? KEY_FRAME_INTERVAL : keyFrameInterval_);
241     }
242     preFrameTimestamp_ = frameRecord->GetTimeStamp();
243     if (!EnqueueBuffer(frameRecord, keyFrameInterval_)) {
244         return false;
245     }
246     keyFrameInterval_--;
247     int32_t retryCount = 5;
248     while (retryCount > 0) {
249         retryCount--;
250         std::unique_lock<std::mutex> contextLock(contextMutex_);
251         CHECK_AND_RETURN_RET_LOG(context_ != nullptr, false, "VideoEncoder has been released");
252         std::unique_lock<std::mutex> lock(context_->outputMutex_);
253         bool condRet = context_->outputCond_.wait_for(lock, std::chrono::milliseconds(BUFFER_ENCODE_EXPIREATION_TIME),
254             [this]() { return !isStarted_ || !context_->outputBufferInfoQueue_.empty(); });
255         CHECK_AND_CONTINUE_LOG(!context_->outputBufferInfoQueue_.empty(),
256             "Buffer queue is empty, continue, cond ret: %{public}d", condRet);
257         sptr<CodecAVBufferInfo> bufferInfo = context_->outputBufferInfoQueue_.front();
258         MEDIA_INFO_LOG("Out buffer count: %{public}u, size: %{public}d, flag: %{public}u, pts:%{public}" PRIu64 ", "
259             "timestamp:%{public}" PRIu64, context_->outputFrameCount_, bufferInfo->attr.size, bufferInfo->attr.flags,
260             bufferInfo->attr.pts, frameRecord->GetTimeStamp());
261         context_->outputBufferInfoQueue_.pop();
262         context_->outputFrameCount_++;
263         lock.unlock();
264         contextLock.unlock();
265         if (bufferInfo->attr.flags == AVCODEC_BUFFER_FLAGS_CODEC_DATA) {
266             // first return IDR frame
267             OH_AVBuffer *IDRBuffer = bufferInfo->GetCopyAVBuffer();
268             frameRecord->CacheBuffer(IDRBuffer);
269             frameRecord->SetIDRProperty(true);
270             successFrame_ = false;
271         } else if (bufferInfo->attr.flags == AVCODEC_BUFFER_FLAGS_SYNC_FRAME) {
272             // then return I frame
273             OH_AVBuffer *tempBuffer = bufferInfo->AddCopyAVBuffer(frameRecord->encodedBuffer);
274             if (tempBuffer != nullptr) {
275                 frameRecord->encodedBuffer = tempBuffer;
276             }
277             successFrame_ = true;
278         } else if (bufferInfo->attr.flags == AVCODEC_BUFFER_FLAGS_NONE) {
279             // return P frame
280             OH_AVBuffer *PBuffer = bufferInfo->GetCopyAVBuffer();
281             frameRecord->CacheBuffer(PBuffer);
282             frameRecord->SetIDRProperty(false);
283             successFrame_ = true;
284         } else {
285             MEDIA_ERR_LOG("Flag is not acceptted number: %{public}u", bufferInfo->attr.flags);
286             int32_t ret = FreeOutputData(bufferInfo->bufferIndex);
287             CHECK_AND_BREAK_LOG(ret == 0, "FreeOutputData failed");
288             continue;
289         }
290         int32_t ret = FreeOutputData(bufferInfo->bufferIndex);
291         CHECK_AND_BREAK_LOG(ret == 0, "FreeOutputData failed");
292         if (successFrame_) {
293             MEDIA_DEBUG_LOG("Success frame id is : %{public}s, refCount: %{public}d",
294                 frameRecord->GetFrameId().c_str(), frameRecord->GetSptrRefCount());
295             return true;
296         }
297     }
298     MEDIA_ERR_LOG("Failed frame id is : %{public}s", frameRecord->GetFrameId().c_str());
299     return false;
300 }
301 
Release()302 int32_t VideoEncoder::Release()
303 {
304     {
305         std::lock_guard<std::mutex> lock(encoderMutex_);
306         if (encoder_ != nullptr) {
307             OH_VideoEncoder_Destroy(encoder_);
308             encoder_ = nullptr;
309         }
310     }
311     std::unique_lock<std::mutex> contextLock(contextMutex_);
312     if (context_ != nullptr) {
313         delete context_;
314         context_ = nullptr;
315     }
316     isStarted_ = false;
317     return 0;
318 }
319 
SetCallback(CodecUserData * codecUserData)320 int32_t VideoEncoder::SetCallback(CodecUserData *codecUserData)
321 {
322     int32_t ret = AV_ERR_OK;
323     ret = OH_VideoEncoder_RegisterCallback(encoder_,
324         {SampleCallback::OnCodecError, SampleCallback::OnCodecFormatChange,
325          SampleCallback::OnNeedInputBuffer, SampleCallback::OnNewOutputBuffer}, codecUserData);
326     CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1, "Set callback failed, ret: %{public}d", ret);
327     return 0;
328 }
329 
Configure()330 int32_t VideoEncoder::Configure()
331 {
332     OH_AVFormat *format = OH_AVFormat_Create();
333     CHECK_AND_RETURN_RET_LOG(format != nullptr, 1, "AVFormat create failed");
334     int32_t bitrate = static_cast<int32_t>(pow(float(size_->width) * float(size_->height) / DEFAULT_SIZE,
335         VIDEO_BITRATE_CONSTANT) * BITRATE_22M);
336     bitrate_ = (videoCodecType_ == VideoCodecType::VIDEO_ENCODE_TYPE_AVC
337         ? static_cast<int32_t>(bitrate * HEVC_TO_AVC_FACTOR) : bitrate);
338     MEDIA_INFO_LOG("Current resolution is : %{public}d*%{public}d, encode type : %{public}d, set bitrate : %{public}d",
339         size_->width, size_->height, videoCodecType_, bitrate_);
340 
341     OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, size_->width);
342     OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, size_->height);
343     OH_AVFormat_SetIntValue(format, OH_MD_KEY_ROTATION, rotation_);
344     OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, VIDEO_FRAME_RATE);
345     OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, VBR);
346     OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, bitrate_);
347     OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, VIDOE_PIXEL_FORMAT);
348     OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, INT_MAX);
349     int ret = OH_VideoEncoder_Configure(encoder_, format);
350     OH_AVFormat_Destroy(format);
351     format = nullptr;
352     CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1, "Config failed, ret: %{public}d", ret);
353 
354     return 0;
355 }
356 } // CameraStandard
357 } // OHOS