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