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 "moving_photo_video_cache.h"
17 #include <cinttypes>
18 #include <unistd.h>
19 #include <chrono>
20 #include <fcntl.h>
21 #include <memory>
22 #include <utility>
23 #include "external_window.h"
24 #include "native_buffer_inner.h"
25 #include "camera_log.h"
26 #include "refbase.h"
27 #include "surface_buffer.h"
28
29 namespace {
30 using namespace std::string_literals;
31 using namespace std::chrono_literals;
32 }
33 namespace OHOS {
34 namespace CameraStandard {
35
~MovingPhotoVideoCache()36 MovingPhotoVideoCache::~MovingPhotoVideoCache()
37 {
38 MEDIA_DEBUG_LOG("~MovingPhotoVideoCache enter");
39 taskManagerLock_.lock();
40 taskManager_ = nullptr;
41 taskManagerLock_.unlock();
42 std::lock_guard<std::mutex> lock(callbackVecLock_);
43 cachedFrameCallbackHandles_.clear();
44 }
45
MovingPhotoVideoCache(sptr<AvcodecTaskManager> taskManager)46 MovingPhotoVideoCache::MovingPhotoVideoCache(sptr<AvcodecTaskManager> taskManager) : taskManager_(taskManager)
47 {
48 }
49
CacheFrame(sptr<FrameRecord> frameRecord)50 void MovingPhotoVideoCache::CacheFrame(sptr<FrameRecord> frameRecord)
51 {
52 MEDIA_DEBUG_LOG("CacheFrame enter");
53 std::lock_guard<std::mutex> lock(taskManagerLock_);
54 if (taskManager_) {
55 frameRecord->SetStatusReadyConvertStatus();
56 auto thisPtr = sptr<MovingPhotoVideoCache>(this);
57 taskManager_->EncodeVideoBuffer(frameRecord, [thisPtr](sptr<FrameRecord> frameRecord, bool encodeResult) {
58 thisPtr->OnImageEncoded(frameRecord, encodeResult);
59 });
60 }
61 }
62
DoMuxerVideo(std::vector<sptr<FrameRecord>> frameRecords,uint64_t taskName,int32_t rotation,int32_t captureId)63 void MovingPhotoVideoCache::DoMuxerVideo(std::vector<sptr<FrameRecord>> frameRecords, uint64_t taskName,
64 int32_t rotation, int32_t captureId)
65 {
66 CAMERA_SYNC_TRACE;
67 MEDIA_INFO_LOG("DoMuxerVideo enter");
68 std::sort(frameRecords.begin(), frameRecords.end(),
69 [](const sptr<FrameRecord>& a, const sptr<FrameRecord>& b) {
70 return a->GetTimeStamp() < b->GetTimeStamp();
71 });
72 std::lock_guard<std::mutex> lock(taskManagerLock_);
73 if (taskManager_) {
74 taskManager_->DoMuxerVideo(frameRecords, taskName, rotation, captureId);
75 auto thisPtr = sptr<MovingPhotoVideoCache>(this);
76 taskManager_->SubmitTask([thisPtr]() {
77 thisPtr->ClearCallbackHandler();
78 });
79 }
80 }
81
82 // Call this function after buffer has been encoded
OnImageEncoded(sptr<FrameRecord> frameRecord,bool encodeResult)83 void MovingPhotoVideoCache::OnImageEncoded(sptr<FrameRecord> frameRecord, bool encodeResult)
84 {
85 CAMERA_SYNC_TRACE;
86 std::lock_guard<std::mutex> lock(callbackVecLock_);
87 for (auto cachedFrameCallbackHandle : cachedFrameCallbackHandles_) {
88 if (cachedFrameCallbackHandle == nullptr) {
89 MEDIA_ERR_LOG("MovingPhotoVideoCache::OnImageEncoded with null cachedFrameCallbackHandle");
90 continue;
91 }
92 cachedFrameCallbackHandle->OnCacheFrameFinish(frameRecord, encodeResult);
93 }
94 }
95
GetFrameCachedResult(std::vector<sptr<FrameRecord>> frameRecords,EncodedEndCbFunc encodedEndCbFunc,uint64_t taskName,int32_t rotation,int32_t captureId)96 void MovingPhotoVideoCache::GetFrameCachedResult(std::vector<sptr<FrameRecord>> frameRecords,
97 EncodedEndCbFunc encodedEndCbFunc, uint64_t taskName, int32_t rotation, int32_t captureId)
98 {
99 callbackVecLock_.lock();
100 MEDIA_INFO_LOG("GetFrameCachedResult enter frameRecords size: %{public}zu", frameRecords.size());
101 sptr<CachedFrameCallbackHandle> cacheFrameHandler =
102 new CachedFrameCallbackHandle(frameRecords, encodedEndCbFunc, taskName, rotation, captureId);
103 cachedFrameCallbackHandles_.push_back(cacheFrameHandler);
104 callbackVecLock_.unlock();
105 for (auto frameRecord : frameRecords) {
106 if (frameRecord->IsFinishCache()) {
107 cacheFrameHandler->OnCacheFrameFinish(frameRecord, frameRecord->IsEncoded());
108 }
109 }
110 }
111
ClearCallbackHandler()112 void MovingPhotoVideoCache::ClearCallbackHandler()
113 {
114 // OnImageEncoded has callbackVecLock_
115 MEDIA_INFO_LOG("ClearCallbackHandler enter");
116 std::lock_guard<std::mutex> lock(callbackVecLock_);
117 MEDIA_DEBUG_LOG("ClearCallbackHandler get callbackVecLock_");
118 cachedFrameCallbackHandles_.erase(std::remove_if(cachedFrameCallbackHandles_.begin(),
119 cachedFrameCallbackHandles_.end(),
120 [](const sptr<CachedFrameCallbackHandle>& obj) {return obj->GetCacheRecord().empty();}),
121 cachedFrameCallbackHandles_.end());
122 }
123
ClearCache()124 void MovingPhotoVideoCache::ClearCache()
125 {
126 MEDIA_INFO_LOG("ClearCache enter");
127 // clear cache and muxer success buffer
128 std::lock_guard<std::mutex> lock(callbackVecLock_);
129 for (auto cachedFrameCallbackHandle : cachedFrameCallbackHandles_) {
130 cachedFrameCallbackHandle->AbortCapture();
131 }
132 cachedFrameCallbackHandles_.clear();
133 }
134
CachedFrameCallbackHandle(std::vector<sptr<FrameRecord>> frameRecords,EncodedEndCbFunc encodedEndCbFunc,uint64_t taskName,int32_t rotation,int32_t captureId)135 CachedFrameCallbackHandle::CachedFrameCallbackHandle(std::vector<sptr<FrameRecord>> frameRecords,
136 EncodedEndCbFunc encodedEndCbFunc, uint64_t taskName, int32_t rotation, int32_t captureId)
137 : encodedEndCbFunc_(encodedEndCbFunc), isAbort_(false), taskName_(taskName), rotation_(rotation),
138 captureId_(captureId)
139 {
140 std::lock_guard<std::mutex> lock(cacheFrameMutex_);
141 cacheRecords_.insert(frameRecords.begin(), frameRecords.end());
142 }
143
~CachedFrameCallbackHandle()144 CachedFrameCallbackHandle::~CachedFrameCallbackHandle()
145 {
146 MEDIA_INFO_LOG("~CachedFrameCallbackHandle enter");
147 }
148
OnCacheFrameFinish(sptr<FrameRecord> frameRecord,bool cachedSuccess)149 void CachedFrameCallbackHandle::OnCacheFrameFinish(sptr<FrameRecord> frameRecord, bool cachedSuccess)
150 {
151 MEDIA_INFO_LOG("OnCacheFrameFinish enter cachedSuccess: %{public}d", cachedSuccess);
152 std::lock_guard<std::mutex> lock(cacheFrameMutex_);
153 if (isAbort_) {
154 // Handle abort
155 MEDIA_INFO_LOG("OnCacheFrameFinish is abort");
156 return;
157 }
158 auto it = cacheRecords_.find(frameRecord);
159 if (it != cacheRecords_.end()) {
160 cacheRecords_.erase(it);
161 if (cachedSuccess && frameRecord != nullptr && frameRecord->encodedBuffer != nullptr) {
162 successCacheRecords_.push_back(frameRecord);
163 } else {
164 errorCacheRecords_.push_back(frameRecord);
165 }
166 if (!cacheRecords_.empty()) {
167 // Still waiting for more cache encoded buffer
168 return;
169 }
170 MEDIA_INFO_LOG("encodedEndCbFunc_ is called success count: %{public}zu", successCacheRecords_.size());
171 // All buffer have been encoded
172 if (encodedEndCbFunc_ != nullptr) {
173 encodedEndCbFunc_(successCacheRecords_, taskName_, rotation_, captureId_);
174 encodedEndCbFunc_ = nullptr;
175 }
176 }
177 }
178
179 // This function is called when prestop capture
AbortCapture()180 void CachedFrameCallbackHandle::AbortCapture()
181 {
182 std::lock_guard<std::mutex> lock(cacheFrameMutex_);
183 isAbort_ = true;
184 cacheRecords_.clear();
185 if (encodedEndCbFunc_ != nullptr) {
186 encodedEndCbFunc_(successCacheRecords_, taskName_, rotation_, captureId_);
187 encodedEndCbFunc_ = nullptr;
188 }
189 }
190
GetCacheRecord()191 CachedFrameSet CachedFrameCallbackHandle::GetCacheRecord()
192 {
193 std::lock_guard<std::mutex> lock(cacheFrameMutex_);
194 return cacheRecords_;
195 }
196
197 } // CameraStandard
198 } // OHOS