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 #include "video_key_info.h"
19
20 namespace {
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(std::shared_ptr<OHOS::Surface> & producer)31 RetCode StreamTunnel::AttachBufferQueue(std::shared_ptr<OHOS::Surface>& producer)
32 {
33 CHECK_IF_PTR_NULL_RETURN_VALUE(producer, RC_ERROR);
34 bufferQueue_ = 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 index = -1;
56 }
57
GetBuffer()58 std::shared_ptr<IBuffer> StreamTunnel::GetBuffer()
59 {
60 CHECK_IF_PTR_NULL_RETURN_VALUE(bufferQueue_, nullptr);
61 OHOS::SurfaceBuffer *sb = nullptr;
62 do {
63 sb = bufferQueue_->RequestBuffer();
64 if (sb == nullptr) {
65 std::unique_lock<std::mutex> l(waitLock_);
66 waitCV_.wait(l, [this] { return wakeup_ == true; });
67 }
68 stats_.RequestBufferResult(sb);
69 } while (!stop_ && sb == nullptr);
70 wakeup_ = false;
71
72 if (stop_) {
73 if (sb != nullptr) {
74 int ret = bufferQueue_->CancelBuffer(sb);
75 stats_.CancelBufferResult(ret);
76 }
77 return nullptr;
78 }
79
80 std::shared_ptr<IBuffer> cb = nullptr;
81 {
82 std::lock_guard<std::mutex> l(lock_);
83 for (auto it = buffers.begin(); it != buffers.end(); it++) {
84 if (it->second == sb) {
85 cb = it->first;
86 }
87 }
88 }
89 if (cb == nullptr) {
90 cb = std::make_shared<ImageBuffer>(CAMERA_BUFFER_SOURCE_TYPE_EXTERNAL);
91 RetCode rc = BufferAdapter::SurfaceBufferToCameraBuffer(sb, bufferQueue_, cb);
92 if (rc != RC_OK || cb == nullptr) {
93 CAMERA_LOGE("create tunnel buffer failed.");
94 return nullptr;
95 }
96
97 cb->SetIndex(++index);
98 {
99 std::lock_guard<std::mutex> l(lock_);
100 buffers[cb] = sb;
101 }
102 } else {
103 cb->SetBufferStatus(CAMERA_BUFFER_STATUS_OK);
104 }
105 restBuffers++;
106 return cb;
107 }
108
PutBuffer(const std::shared_ptr<IBuffer> & buffer)109 RetCode StreamTunnel::PutBuffer(const std::shared_ptr<IBuffer>& buffer)
110 {
111 CHECK_IF_PTR_NULL_RETURN_VALUE(buffer, RC_ERROR);
112 CHECK_IF_PTR_NULL_RETURN_VALUE(bufferQueue_, RC_ERROR);
113 OHOS::SurfaceBuffer *sb = nullptr;
114 {
115 std::lock_guard<std::mutex> l(lock_);
116 auto it = buffers.find(buffer);
117 if (it == buffers.end()) {
118 CAMERA_LOGE("buffer [%{public}d] doesn't belong to this tunnel.", buffer->GetIndex());
119 return RC_ERROR;
120 }
121 sb = it->second;
122 }
123
124 if (buffer->GetBufferStatus() == CAMERA_BUFFER_STATUS_OK) {
125 EsFrameInfo esInfo = buffer->GetEsFrameInfo();
126 if (esInfo.size != -1 && esInfo.timestamp != -1) {
127 sb->SetInt32(OHOS::Camera::VIDEO_KEY_INFO_DATA_SIZE, esInfo.size);
128 sb->SetInt32(OHOS::Camera::VIDEO_KEY_INFO_IS_KEY_FRAME, esInfo.isKey);
129 sb->SetInt64(OHOS::Camera::VIDEO_KEY_INFO_TIMESTAMP, esInfo.timestamp);
130 }
131 int ret = bufferQueue_->FlushBuffer(sb);
132 stats_.FlushBufferResult(ret);
133 frameCount_++;
134 } else {
135 int ret = bufferQueue_->CancelBuffer(sb);
136 stats_.CancelBufferResult(ret);
137 }
138
139 {
140 restBuffers--;
141 std::unique_lock<std::mutex> l(finishLock_);
142 finishCV_.notify_all();
143 }
144 {
145 std::unique_lock<std::mutex> l(waitLock_);
146 wakeup_ = true;
147 waitCV_.notify_one();
148 }
149 return RC_OK;
150 }
151
SetBufferCount(const int32_t n)152 RetCode StreamTunnel::SetBufferCount(const int32_t n)
153 {
154 CHECK_IF_PTR_NULL_RETURN_VALUE(bufferQueue_, RC_ERROR);
155 bufferQueue_->SetQueueSize(n);
156 return RC_OK;
157 }
158
Config(const TunnelConfig & config)159 RetCode StreamTunnel::Config(const TunnelConfig& config)
160 {
161 bufferQueue_->SetWidthAndHeight(config.width, config.height);
162 bufferQueue_->SetFormat(BufferAdapter::CameraFormatToPixelFormat(config.format));
163 bufferQueue_->SetStrideAlignment(STRIDE_ALIGNMENT);
164
165 return RC_OK;
166 }
167
GetFrameCount() const168 uint64_t StreamTunnel::GetFrameCount() const
169 {
170 return frameCount_;
171 }
172
NotifyStop()173 void StreamTunnel::NotifyStop()
174 {
175 std::unique_lock<std::mutex> l(waitLock_);
176 wakeup_ = true;
177 stop_ = true;
178 waitCV_.notify_one();
179 }
180
NotifyStart()181 void StreamTunnel::NotifyStart()
182 {
183 stop_ = false;
184 }
185
WaitForAllBufferReturned()186 void StreamTunnel::WaitForAllBufferReturned()
187 {
188 std::unique_lock<std::mutex> l(finishLock_);
189 finishCV_.wait(l, [this] {
190 return restBuffers == 0;
191 });
192
193 return;
194 }
195
DumpStats(int interval)196 void StreamTunnel::DumpStats(int interval)
197 {
198 stats_.DumpStats(interval);
199 }
200
SetStreamId(int32_t streamId)201 void StreamTunnel::SetStreamId(int32_t streamId)
202 {
203 streamId_ = streamId;
204 stats_.SetStreamId(streamId);
205 }
206 } // namespace OHOS::Camera
207