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