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