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