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