1 /*
2  * Copyright (c) 2020-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 "buffer_source.h"
17 #include "securec.h"
18 #include "media_log.h"
19 
20 #ifdef __cplusplus
21 #if __cplusplus
22 extern "C" {
23 #endif
24 #endif /* __cplusplus */
25 
26 const int32_t EOS_LEN = 4; /* set eos len 4, ensure the eos flag can be read */
27 const uint32_t BUFFER_SOURCE_FLAG_EOS = 4; /* STREAM_FLAG_EOS */
28 
29 #define CHK_NULL_RETURN( ptr) \
30 do { \
31     if (ptr == nullptr) { \
32         MEDIA_ERR_LOG("input param null"); \
33         return -1; \
34     } \
35 } while (0)
36 
BufferSource(void)37 BufferSource::BufferSource(void)
38 {
39     inited_ = false;
40 
41     idleBuffer_.clear();
42     filledBuffer_.clear();
43     if (memset_s(buffer_, sizeof(BufferInfo) * QUEUE_SIZE, 0, sizeof(BufferInfo) * QUEUE_SIZE) != 0)  {
44         MEDIA_ERR_LOG("BufferSource memset_s failed");
45     }
46 }
47 
~BufferSource(void)48 BufferSource::~BufferSource(void)
49 {
50     int i;
51     if (inited_ == false) {
52         return;
53     }
54     idleBuffer_.clear();
55     filledBuffer_.clear();
56     for (i = 0; i < QUEUE_SIZE; i++) {
57         if (buffer_[i].virAddr != nullptr) {
58             free(buffer_[i].virAddr);
59             buffer_[i].virAddr = nullptr;
60         }
61     }
62     inited_ = false;
63 }
64 
Init(void)65 int BufferSource::Init(void)
66 {
67     int i;
68 
69     for (i = 0; i < QUEUE_SIZE; i++) {
70         buffer_[i].virAddr = malloc(BUFFER_SIZE);
71         if (buffer_[i].virAddr == nullptr) {
72             MEDIA_ERR_LOG("BufferSource::Init, malloc failed\n");
73             goto failed;
74         }
75         buffer_[i].phyAddr = 0;
76         buffer_[i].fd = -1;
77         buffer_[i].bufLen = BUFFER_SIZE;
78         buffer_[i].offset = 0;
79         buffer_[i].size = BUFFER_SIZE;
80         buffer_[i].idx = i;
81 
82         QueBuffer buffer;
83         buffer.idx = i;
84         buffer.flag = 0;
85         buffer.offset = 0;
86         buffer.size = 0;
87         buffer.timestamp = 0;
88         QueIdleBuffer(&buffer);
89     }
90     inited_ = true;
91     MEDIA_INFO_LOG("idleQue size:%d",idleBuffer_.size());
92     return 0;
93 failed:
94     for (i = 0; i < QUEUE_SIZE; i++) {
95         if (buffer_[i].virAddr != nullptr) {
96             free(buffer_[i].virAddr);
97             buffer_[i].virAddr = nullptr;
98         }
99     }
100     idleBuffer_.clear();
101     return -1;
102 }
103 
GetQueSize(void)104 int BufferSource::GetQueSize(void)
105 {
106     return QUEUE_SIZE;
107 }
108 
GetBufferInfo(int idx,BufferInfo * info)109 int BufferSource::GetBufferInfo(int idx, BufferInfo* info)
110 {
111     CHK_NULL_RETURN(info);
112     if (idx < 0 || idx >= QUEUE_SIZE) {
113         return -1;
114     }
115     *info = buffer_[idx];
116     return 0;
117 }
118 
QueIdleBuffer(const QueBuffer * buffer)119 int BufferSource::QueIdleBuffer(const QueBuffer *buffer)
120 {
121     std::lock_guard<std::mutex> lock(idleQueMutex_);
122     CHK_NULL_RETURN(buffer);
123     idleBuffer_.push_back(*buffer);
124     return 0;
125 }
126 
DequeIdleBuffer(QueBuffer * buffer,int timeOut)127 int BufferSource::DequeIdleBuffer(QueBuffer* buffer, int timeOut)
128 {
129     std::lock_guard<std::mutex> lock(idleQueMutex_);
130     CHK_NULL_RETURN(buffer);
131     if (idleBuffer_.empty() != 0) {
132         return -1;
133     }
134     *buffer = idleBuffer_[0];
135     idleBuffer_.erase(idleBuffer_.begin());
136     return 0;
137 }
138 
GetIdleQueSize(void)139 size_t BufferSource::GetIdleQueSize(void)
140 {
141     size_t size;
142     std::lock_guard<std::mutex> lock(idleQueMutex_);
143     size = idleBuffer_.size();
144     return size;
145 }
146 
QueFilledBuffer(const QueBuffer * buffer)147 int BufferSource::QueFilledBuffer(const QueBuffer *buffer)
148 {
149     std::lock_guard<std::mutex> lock(filledQueMutex_);
150     CHK_NULL_RETURN(buffer);
151     filledBuffer_.push_back(*buffer);
152     return 0;
153 }
154 
DequeFilledBuffer(QueBuffer * buffer,int timeOut)155 int BufferSource::DequeFilledBuffer(QueBuffer* buffer, int timeOut)
156 {
157     std::lock_guard<std::mutex> lock(filledQueMutex_);
158     CHK_NULL_RETURN(buffer);
159     if (filledBuffer_.empty() != 0) {
160         return -1;
161     }
162     *buffer = filledBuffer_[0];
163     filledBuffer_.erase(filledBuffer_.begin());
164     return 0;
165 }
166 
GetFilledQueSize(void)167 size_t BufferSource::GetFilledQueSize(void)
168 {
169     size_t size;
170     std::lock_guard<std::mutex> lock(filledQueMutex_);
171     size = filledBuffer_.size();
172     return size;
173 }
174 
GetFilledQueDataSize(void)175 int32_t BufferSource::GetFilledQueDataSize(void)
176 {
177     uint32_t i;
178     size_t size;
179     int32_t len = 0;
180     std::lock_guard<std::mutex> lock(filledQueMutex_);
181     size = filledBuffer_.size();
182     for (i = 0; i < size; i++) {
183         len += filledBuffer_[i].size;
184     }
185     /* fix the issue last buffer have not been read, when the buffer only include a eos flag */
186     if (size == 1 && len == 0 && filledBuffer_[0].flag == BUFFER_SOURCE_FLAG_EOS) {
187         len = EOS_LEN;
188     }
189     return len;
190 }
191 
GetFilledBuffer(size_t idx,QueBuffer * buffer)192 int BufferSource::GetFilledBuffer(size_t idx, QueBuffer* buffer)
193 {
194     std::lock_guard<std::mutex> lock(filledQueMutex_);
195     size_t queSize;
196     CHK_NULL_RETURN(buffer);
197     queSize = filledBuffer_.size();
198     if (queSize <= idx) {
199         return -1;
200     }
201     *buffer = filledBuffer_[idx];
202     return 0;
203 }
204 
205 #ifdef __cplusplus
206 #if __cplusplus
207 }
208 #endif
209 #endif /* __cplusplus */
210