• 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 #include "stream_tunnel.h"
16 #include "buffer_adapter.h"
17 #include "image_buffer.h"
18 
19 namespace {
20 constexpr uint32_t REQUEST_TIMEOUT = 0;
21 constexpr uint32_t STRIDE_ALIGNMENT = 8;
22 } // namespace
23 
24 namespace OHOS::Camera {
~StreamTunnel()25 StreamTunnel::~StreamTunnel()
26 {
27     CAMERA_LOGV("enter");
28     DetachBufferQueue();
29 }
30 
AttachBufferQueue(OHOS::sptr<OHOS::IBufferProducer> & producer)31 RetCode StreamTunnel::AttachBufferQueue(OHOS::sptr<OHOS::IBufferProducer>& producer)
32 {
33     CHECK_IF_PTR_NULL_RETURN_VALUE(producer, RC_ERROR);
34     bufferQueue_ = OHOS::Surface::CreateSurfaceAsProducer(producer);
35     CHECK_IF_PTR_NULL_RETURN_VALUE(bufferQueue_, RC_ERROR);
36     return RC_OK;
37 }
38 
DetachBufferQueue()39 RetCode StreamTunnel::DetachBufferQueue()
40 {
41     bufferQueue_ = nullptr;
42     return RC_OK;
43 }
44 
CleanBuffers()45 void StreamTunnel::CleanBuffers()
46 {
47     if (stop_ == false) {
48         return;
49     }
50     wakeup_ = true;
51     waitCV_.notify_one();
52 
53     std::lock_guard<std::mutex> l(lock_);
54     buffers.clear();
55     bufferQueue_->CleanCache();
56     index = -1;
57 }
58 
GetBuffer()59 std::shared_ptr<IBuffer> StreamTunnel::GetBuffer()
60 {
61     CHECK_IF_PTR_NULL_RETURN_VALUE(bufferQueue_, nullptr);
62     OHOS::sptr<OHOS::SurfaceBuffer> sb = nullptr;
63     int32_t fence = 0;
64     OHOS::SurfaceError sfError = OHOS::SURFACE_ERROR_OK;
65     do {
66         sfError = bufferQueue_->RequestBuffer(sb, fence, requestConfig_);
67         if (sfError == OHOS::SURFACE_ERROR_NO_BUFFER) {
68             std::unique_lock<std::mutex> l(waitLock_);
69             waitCV_.wait(l, [this] { return wakeup_ == true; });
70         }
71     } while (!stop_ && sfError == OHOS::SURFACE_ERROR_NO_BUFFER);
72     wakeup_ = false;
73 
74     if (stop_) {
75         if (sb != nullptr) {
76             bufferQueue_->CancelBuffer(sb);
77         }
78         return nullptr;
79     }
80 
81     if (sfError != OHOS::SURFACE_ERROR_OK) {
82         CAMERA_LOGE("get producer buffer failed, error:%{public}s", SurfaceErrorStr(sfError).c_str());
83         return nullptr;
84     }
85 
86     std::shared_ptr<IBuffer> cb = nullptr;
87     {
88         std::lock_guard<std::mutex> l(lock_);
89         for (auto it = buffers.begin(); it != buffers.end(); it++) {
90             if (it->second == sb) {
91                 cb = it->first;
92             }
93         }
94     }
95     if (cb == nullptr) {
96         cb = std::make_shared<ImageBuffer>(CAMERA_BUFFER_SOURCE_TYPE_EXTERNAL);
97         RetCode rc = BufferAdapter::SurfaceBufferToCameraBuffer(sb, cb);
98         if (rc != RC_OK || cb == nullptr) {
99             CAMERA_LOGE("create tunnel buffer failed.");
100             return nullptr;
101         }
102 
103         cb->SetIndex(++index);
104         {
105             std::lock_guard<std::mutex> l(lock_);
106             buffers[cb] = sb;
107         }
108     } else {
109         cb->SetBufferStatus(CAMERA_BUFFER_STATUS_OK);
110     }
111     restBuffers++;
112     return cb;
113 }
114 
PutBuffer(const std::shared_ptr<IBuffer> & buffer)115 RetCode StreamTunnel::PutBuffer(const std::shared_ptr<IBuffer>& buffer)
116 {
117     CHECK_IF_PTR_NULL_RETURN_VALUE(buffer, RC_ERROR);
118     CHECK_IF_PTR_NULL_RETURN_VALUE(bufferQueue_, RC_ERROR);
119     OHOS::sptr<OHOS::SurfaceBuffer> sb = nullptr;
120     {
121         std::lock_guard<std::mutex> l(lock_);
122         auto it = buffers.find(buffer);
123         if (it == buffers.end()) {
124             CAMERA_LOGE("buffer [%{public}d] doesn't belong to this tunnel.", buffer->GetIndex());
125             return RC_ERROR;
126         }
127         sb = it->second;
128     }
129 
130     if (buffer->GetBufferStatus() == CAMERA_BUFFER_STATUS_OK) {
131         int32_t fence = 0;
132         EsFrmaeInfo esInfo = buffer->GetEsFrameInfo();
133         if (esInfo.size != -1 && esInfo.timestamp != -1) {
134             sb->ExtraSet("dataSize", esInfo.size);
135             sb->ExtraSet("isKeyFrame", esInfo.isKey);
136             sb->ExtraSet("timeStamp", esInfo.timestamp);
137             sb->ExtraSet("frameNum", esInfo.frameNum);
138         }
139         bufferQueue_->FlushBuffer(sb, fence, flushConfig_);
140         frameCount_++;
141     } else {
142         bufferQueue_->CancelBuffer(sb);
143     }
144 
145     {
146         restBuffers--;
147         std::unique_lock<std::mutex> l(finishLock_);
148         finishCV_.notify_all();
149     }
150     {
151         std::unique_lock<std::mutex> l(waitLock_);
152         wakeup_ = true;
153         waitCV_.notify_one();
154     }
155     return RC_OK;
156 }
157 
SetBufferCount(const int32_t n)158 RetCode StreamTunnel::SetBufferCount(const int32_t n)
159 {
160     CHECK_IF_PTR_NULL_RETURN_VALUE(bufferQueue_, RC_ERROR);
161     bufferQueue_->SetQueueSize(n);
162     return RC_OK;
163 }
164 
Config(const TunnelConfig config)165 RetCode StreamTunnel::Config(const TunnelConfig config)
166 {
167     requestConfig_.width = config.width;
168     requestConfig_.height = config.height;
169     requestConfig_.format = BufferAdapter::CameraFormatToPixelFormat(config.format);
170     requestConfig_.usage = BufferAdapter::CameraUsageToGrallocUsage(config.usage);
171     requestConfig_.strideAlignment = STRIDE_ALIGNMENT;
172     requestConfig_.timeout = REQUEST_TIMEOUT;
173 
174     flushConfig_.damage.w = config.width;
175     flushConfig_.damage.h = config.height;
176 
177     return RC_OK;
178 }
179 
GetFrameCount() const180 uint64_t StreamTunnel::GetFrameCount() const
181 {
182     return frameCount_;
183 }
184 
NotifyStop()185 void StreamTunnel::NotifyStop()
186 {
187     std::unique_lock<std::mutex> l(waitLock_);
188     wakeup_ = true;
189     stop_ = true;
190     waitCV_.notify_one();
191 }
192 
NotifyStart()193 void StreamTunnel::NotifyStart()
194 {
195     stop_ = false;
196 }
197 
WaitForAllBufferReturned()198 void StreamTunnel::WaitForAllBufferReturned()
199 {
200     std::unique_lock<std::mutex> l(finishLock_);
201     finishCV_.wait(l, [this] {
202         return restBuffers == 0;
203         });
204 
205     return;
206 }
207 } // namespace OHOS::Camera
208