• 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 "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