1 /*
2 * Copyright (c) 2021 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 "offline_stream.h"
17 #include "offline_pipeline_manager.h"
18
19 namespace OHOS::Camera {
OfflineStream(int32_t id,const OHOS::sptr<IStreamOperatorVdiCallback> & callback)20 OfflineStream::OfflineStream(int32_t id, const OHOS::sptr<IStreamOperatorVdiCallback>& callback)
21 {
22 streamId_ = id;
23 callback_ = callback;
24 }
25
~OfflineStream()26 OfflineStream::~OfflineStream()
27 {
28 context_->restRequests.clear();
29 context_->tunnel->CleanBuffers();
30 context_->bufferPool->ClearBuffers();
31 }
32
GetStreamId() const33 int32_t OfflineStream::GetStreamId() const
34 {
35 return streamId_;
36 }
37
Init(std::shared_ptr<OfflineStreamContext> & context)38 RetCode OfflineStream::Init(std::shared_ptr<OfflineStreamContext>& context)
39 {
40 context_ = context;
41 CHECK_IF_PTR_NULL_RETURN_VALUE(context_, RC_ERROR);
42
43 auto callback = [this](MessageGroup& m) { HandleMessage(m); };
44 messenger_ = std::make_shared<CaptureMessageOperator>(callback);
45 CHECK_IF_PTR_NULL_RETURN_VALUE(messenger_, RC_ERROR);
46 messenger_->StartProcess();
47
48 for (auto it : context_->restRequests) {
49 it->DisableSync();
50 }
51
52 OfflinePipelineManager& manager = OfflinePipelineManager::GetInstance();
53 std::shared_ptr<IStreamPipelineCore> pipeline = context_->pipeline.lock();
54 auto cb = [this](std::shared_ptr<IBuffer>& buffer) { ReceiveOfflineBuffer(buffer); };
55 RetCode ret = manager.SwitchToOfflinePipeline(streamId_, context_->streamInfo.type, pipeline, cb);
56 if (ret != RC_OK) {
57 CAMERA_LOGE("switch to offline stream failed.");
58 return RC_ERROR;
59 }
60
61 return RC_OK;
62 }
63
CancelCapture(int32_t captureId)64 RetCode OfflineStream::CancelCapture(int32_t captureId)
65 {
66 OfflinePipelineManager& manager = OfflinePipelineManager::GetInstance();
67 RetCode ret = manager.CancelCapture(streamId_, captureId);
68 if (ret != RC_OK) {
69 CAMERA_LOGE("cancel capture %{public}d failed", captureId);
70 return RC_ERROR;
71 }
72
73 return RC_OK;
74 }
75
Release()76 RetCode OfflineStream::Release()
77 {
78 {
79 std::lock_guard<std::mutex> l(lock_);
80 for (auto it : context_->restRequests) {
81 CancelCapture(it->GetCaptureId());
82 }
83 }
84
85 context_->tunnel->WaitForAllBufferReturned();
86 OfflinePipelineManager& manager = OfflinePipelineManager::GetInstance();
87 RetCode ret = manager.DestoryOfflinePipeline(streamId_);
88 if (ret != RC_OK) {
89 CAMERA_LOGE("release offline pipeline %{public}d failed", streamId_);
90 return RC_ERROR;
91 }
92
93 return RC_OK;
94 }
95
ReceiveOfflineBuffer(std::shared_ptr<IBuffer> & buffer)96 void OfflineStream::ReceiveOfflineBuffer(std::shared_ptr<IBuffer>& buffer)
97 {
98 if (context_ == nullptr) {
99 return;
100 }
101
102 if (buffer == nullptr) {
103 CAMERA_LOGE("fatal error, buffer should not be null");
104 return;
105 }
106
107 ReturnBuffer(buffer);
108 return;
109 }
110
ReturnBuffer(std::shared_ptr<IBuffer> & buffer)111 RetCode OfflineStream::ReturnBuffer(std::shared_ptr<IBuffer>& buffer)
112 {
113 auto tunnel = context_->tunnel;
114 auto bufferPool = context_->bufferPool;
115
116 CHECK_IF_PTR_NULL_RETURN_VALUE(buffer, RC_ERROR);
117 if (buffer->GetBufferStatus() == CAMERA_BUFFER_STATUS_INVALID) {
118 CAMERA_LOGI("offline stream [id:%{public}d], this buffer(index:%{public}d) has nothing to do with request.",
119 streamId_, buffer->GetIndex());
120 tunnel->PutBuffer(buffer);
121 bufferPool->ReturnBuffer(buffer);
122 return RC_OK;
123 }
124
125 int32_t captureId = buffer->GetCaptureId();
126
127 std::shared_ptr<CaptureRequest> request = nullptr;
128 {
129 std::lock_guard<std::mutex> l(lock_);
130 auto it = std::find_if(
131 context_->restRequests.begin(), context_->restRequests.end(),
132 [captureId](const std::shared_ptr<CaptureRequest>& r) { return r->GetCaptureId() == captureId; });
133 if (it == context_->restRequests.end()) {
134 CAMERA_LOGE("fatal error, offline stream [%{public}d] reveived a wrong buffer, index:%{public}d.",
135 streamId_, buffer->GetIndex());
136 return RC_ERROR;
137 }
138 request = *it;
139 context_->restRequests.erase(it);
140 }
141
142 CameraBufferStatus status = buffer->GetBufferStatus();
143 if (status != CAMERA_BUFFER_STATUS_OK) {
144 if (status != CAMERA_BUFFER_STATUS_DROP) {
145 std::shared_ptr<ICaptureMessage> errorMessage =
146 std::make_shared<CaptureErrorMessage>(streamId_, request->GetCaptureId(), request->GetEndTime(),
147 request->GetOwnerCount(), static_cast<VdiStreamError>(status));
148 messenger_->SendMessage(errorMessage);
149 }
150 }
151
152 if (request->NeedShutterCallback()) {
153 std::shared_ptr<ICaptureMessage> shutterMessage = std::make_shared<FrameShutterMessage>(
154 streamId_, request->GetCaptureId(), request->GetEndTime(), request->GetOwnerCount());
155 messenger_->SendMessage(shutterMessage);
156 }
157
158 std::shared_ptr<ICaptureMessage> endMessage = std::make_shared<CaptureEndedMessage>(
159 streamId_, request->GetCaptureId(), request->GetEndTime(), request->GetOwnerCount(), tunnel->GetFrameCount());
160 messenger_->SendMessage(endMessage);
161
162 CAMERA_LOGI("offline stream [id:%{public}d] dequeue buffer index:%{public}d, status:%{public}d",
163 streamId_, buffer->GetIndex(),
164 buffer->GetBufferStatus());
165 bufferPool->ReturnBuffer(buffer);
166 tunnel->PutBuffer(buffer);
167
168 return RC_OK;
169 }
170
CheckCaptureIdExist(int32_t captureId)171 bool OfflineStream::CheckCaptureIdExist(int32_t captureId)
172 {
173 std::lock_guard<std::mutex> l(lock_);
174 auto it =
175 std::find_if(context_->restRequests.begin(), context_->restRequests.end(),
176 [captureId](const std::shared_ptr<CaptureRequest>& r) { return r->GetCaptureId() == captureId; });
177 if (it != context_->restRequests.end()) {
178 return true;
179 }
180 return false;
181 }
182
HandleMessage(MessageGroup & message)183 void OfflineStream::HandleMessage(MessageGroup& message)
184 {
185 if (message.empty()) {
186 return;
187 }
188 CHECK_IF_PTR_NULL_RETURN_VOID(message[0]);
189 CaptureMessageType type = message[0]->GetMessageType();
190 switch (type) {
191 case CAPTURE_MESSAGE_TYPE_ON_ERROR: {
192 std::vector<VdiCaptureErrorInfo> info = {};
193 for (const auto& cm : message) {
194 auto m = std::static_pointer_cast<CaptureErrorMessage>(cm);
195 CHECK_IF_PTR_NULL_RETURN_VOID(m);
196 VdiCaptureErrorInfo edi = {0};
197 edi.streamId_ = m->GetStreamId();
198 edi.error_ = m->GetStreamError();
199 info.push_back(edi);
200 }
201 OnCaptureError(message[0]->GetCaptureId(), info);
202 break;
203 }
204 case CAPTURE_MESSAGE_TYPE_ON_ENDED: {
205 std::vector<VdiCaptureEndedInfo> info = {};
206 for (const auto& cm : message) {
207 auto m = std::static_pointer_cast<CaptureEndedMessage>(cm);
208 CHECK_IF_PTR_NULL_RETURN_VOID(m);
209 VdiCaptureEndedInfo edi = {0};
210 edi.streamId_ = m->GetStreamId();
211 edi.frameCount_ = (int32_t)(m->GetFrameCount());
212 info.push_back(edi);
213 }
214 OnCaptureEnded(message[0]->GetCaptureId(), info);
215 break;
216 }
217 default:
218 break;
219 }
220 return;
221 }
222
OnCaptureEnded(int32_t captureId,const std::vector<VdiCaptureEndedInfo> & infos)223 void OfflineStream::OnCaptureEnded(int32_t captureId, const std::vector<VdiCaptureEndedInfo>& infos)
224 {
225 CHECK_IF_EQUAL_RETURN_VOID(callback_, nullptr);
226 callback_->OnCaptureEnded(captureId, infos);
227 }
228
OnCaptureError(int32_t captureId,const std::vector<VdiCaptureErrorInfo> & infos)229 void OfflineStream::OnCaptureError(int32_t captureId, const std::vector<VdiCaptureErrorInfo>& infos)
230 {
231 CHECK_IF_EQUAL_RETURN_VOID(callback_, nullptr);
232 callback_->OnCaptureError(captureId, infos);
233 }
234 } // namespace OHOS::Camera
235