• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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