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 "avcodec/common/frame_record.h"
17 
18 #include "moving_photo/moving_photo_surface_wrapper.h"
19 
20 namespace OHOS {
21 namespace CameraStandard {
22 
FrameRecord(sptr<SurfaceBuffer> videoBuffer,int64_t timestamp,GraphicTransformType type)23 FrameRecord::FrameRecord(sptr<SurfaceBuffer> videoBuffer, int64_t timestamp, GraphicTransformType type)
24     : videoBuffer_(videoBuffer), timestamp_(timestamp), transformType_(type)
25 {
26     frameId_ = std::to_string(timestamp);
27     size = make_shared<Size>();
28     size->width = static_cast<uint32_t>(videoBuffer->GetSurfaceBufferWidth());
29     size->height = static_cast<uint32_t>(videoBuffer->GetSurfaceBufferHeight());
30     bufferSize = videoBuffer->GetSize();
31     format = videoBuffer->GetFormat();
32     usage = videoBuffer->GetUsage();
33 }
34 
~FrameRecord()35 FrameRecord::~FrameRecord()
36 {
37     MEDIA_DEBUG_LOG("FrameRecord::~FrameRecord");
38     if (encodedBuffer) {
39         OH_AVBuffer_Destroy(encodedBuffer);
40     }
41     encodedBuffer = nullptr;
42 }
43 
ReleaseSurfaceBuffer(sptr<MovingPhotoSurfaceWrapper> surfaceWrapper)44 void FrameRecord::ReleaseSurfaceBuffer(sptr<MovingPhotoSurfaceWrapper> surfaceWrapper)
45 {
46     std::unique_lock<std::mutex> lock(mutex_);
47     if (IsReadyConvert()) {
48         MEDIA_DEBUG_LOG("FrameRecord::ReleaseSurfaceBuffer isReadyConvert");
49         auto thisPtr = sptr<FrameRecord>(this);
50         canReleased_.wait_for(lock, std::chrono::milliseconds(BUFFER_RELEASE_EXPIREATION_TIME),
51             [thisPtr] { return thisPtr->IsFinishCache(); });
52         MEDIA_DEBUG_LOG("FrameRecord::ReleaseSurfaceBuffer wait end");
53     }
54     if (videoBuffer_) {
55         if (surfaceWrapper != nullptr) {
56             surfaceWrapper->RecycleBuffer(videoBuffer_);
57         }
58         videoBuffer_ = nullptr;
59         MEDIA_DEBUG_LOG("release buffer end %{public}s", frameId_.c_str());
60     }
61 }
62 
ReleaseMetaBuffer(sptr<Surface> surface,bool reuse)63 void FrameRecord::ReleaseMetaBuffer(sptr<Surface> surface, bool reuse)
64 {
65     std::unique_lock<std::mutex> lock(metaBufferMutex_);
66     sptr<SurfaceBuffer> buffer = nullptr;
67     if (status != STATUS_NONE && metaBuffer_) {
68         buffer = SurfaceBuffer::Create();
69         DeepCopyBuffer(buffer, metaBuffer_);
70     }
71     if (metaBuffer_) {
72         if (reuse) {
73             SurfaceError surfaceRet = surface->AttachBufferToQueue(metaBuffer_);
74             if (surfaceRet != SURFACE_ERROR_OK) {
75                 MEDIA_ERR_LOG("Failed to attach meta buffer %{public}d", surfaceRet);
76                 return;
77             }
78             surfaceRet = surface->ReleaseBuffer(metaBuffer_, -1);
79             if (surfaceRet != SURFACE_ERROR_OK) {
80                 MEDIA_ERR_LOG("Failed to Release meta Buffer %{public}d", surfaceRet);
81                 return;
82             }
83         }
84         metaBuffer_ = buffer;
85         MEDIA_DEBUG_LOG("release meta buffer end %{public}s", frameId_.c_str());
86     }
87 }
88 
NotifyBufferRelease()89 void FrameRecord::NotifyBufferRelease()
90 {
91     MEDIA_DEBUG_LOG("notifyBufferRelease");
92     status = STATUS_FINISH_ENCODE;
93     canReleased_.notify_one();
94 }
95 
DeepCopyBuffer(sptr<SurfaceBuffer> newSurfaceBuffer,sptr<SurfaceBuffer> surfaceBuffer) const96 void FrameRecord::DeepCopyBuffer(sptr<SurfaceBuffer> newSurfaceBuffer, sptr<SurfaceBuffer> surfaceBuffer) const
97 {
98     BufferRequestConfig requestConfig = {
99         .width = surfaceBuffer->GetWidth(),
100         .height = surfaceBuffer->GetHeight(),
101         .strideAlignment = 0x8, // default stride is 8 Bytes.
102         .format = surfaceBuffer->GetFormat(),
103         .usage = surfaceBuffer->GetUsage(),
104         .timeout = 0,
105         .colorGamut = surfaceBuffer->GetSurfaceBufferColorGamut(),
106         .transform = surfaceBuffer->GetSurfaceBufferTransform(),
107     };
108     auto allocErrorCode = newSurfaceBuffer->Alloc(requestConfig);
109     if (allocErrorCode != GSERROR_OK) {
110         MEDIA_ERR_LOG("SurfaceBuffer alloc ret: %d", allocErrorCode);
111         return;
112     }
113     if (memcpy_s(newSurfaceBuffer->GetVirAddr(), newSurfaceBuffer->GetSize(),
114         surfaceBuffer->GetVirAddr(), surfaceBuffer->GetSize()) != EOK) {
115         MEDIA_ERR_LOG("SurfaceBuffer memcpy_s failed");
116     }
117 }
118 } // namespace CameraStandard
119 } // namespace OHOS