1/*
2 * Copyright (c) 2021-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 "plugin/common/plugin_buffer.h"
17#include "plugin/common/share_memory.h"
18#include "plugin/common/surface_memory.h"
19
20namespace OHOS {
21namespace Media {
22namespace Plugin {
23Memory::Memory(size_t capacity, std::shared_ptr<uint8_t> bufData, size_t align, MemoryType type)
24    : memoryType(type), capacity(capacity), alignment(align),
25      offset(0), size(0), allocator(nullptr), addr(std::move(bufData))
26{
27}
28
29Memory::Memory(size_t capacity, std::shared_ptr<Allocator> allocator, size_t align, MemoryType type, bool allocMem)
30    : memoryType(type), capacity(capacity), alignment(align), offset(0),
31      size(0), allocator(std::move(allocator)), addr(nullptr)
32{
33    if (!allocMem) { // SurfaceMemory alloc mem in subclass
34        return;
35    }
36    size_t allocSize = align ? (capacity + align - 1) : capacity;
37    if (this->allocator) {
38        addr = std::shared_ptr<uint8_t>(static_cast<uint8_t*>(this->allocator->Alloc(allocSize)),
39                                        [this](uint8_t* ptr) { this->allocator->Free(static_cast<void*>(ptr)); });
40    } else {
41        addr = std::shared_ptr<uint8_t>(new uint8_t[allocSize], std::default_delete<uint8_t[]>());
42    }
43    offset = static_cast<size_t>(AlignUp(reinterpret_cast<uintptr_t>(addr.get()), static_cast<uintptr_t>(align)) -
44        reinterpret_cast<uintptr_t>(addr.get()));
45}
46
47size_t Memory::GetCapacity()
48{
49    return capacity;
50}
51
52void Memory::Reset()
53{
54    this->size = 0;
55}
56
57size_t Memory::Write(const uint8_t* in, size_t writeSize, size_t position)
58{
59    size_t start = 0;
60    if (position == INVALID_POSITION) {
61        start = size;
62    } else {
63        start = std::min(position, capacity);
64    }
65    size_t length = std::min(writeSize, capacity - start);
66    if (memcpy_s(GetRealAddr() + start, length, in, length) != EOK) {
67        return 0;
68    }
69    size = start + length;
70    return length;
71}
72
73size_t Memory::Read(uint8_t* out, size_t readSize, size_t position)
74{
75    size_t start = 0;
76    size_t maxLength = size;
77    if (position != INVALID_POSITION) {
78        start = std::min(position, size);
79        maxLength = size - start;
80    }
81    size_t length = std::min(readSize, maxLength);
82    if (memcpy_s(out, length, GetRealAddr() + start, length) != EOK) {
83        return 0;
84    }
85    return length;
86}
87
88const uint8_t* Memory::GetReadOnlyData(size_t position)
89{
90    if (position > capacity) {
91        return nullptr;
92    }
93    return GetRealAddr() + position;
94}
95
96uint8_t* Memory::GetWritableAddr(size_t estimatedWriteSize, size_t position)
97{
98    if (position + estimatedWriteSize > capacity) {
99        return nullptr;
100    }
101    uint8_t* ptr = GetRealAddr() + position;
102    size = (estimatedWriteSize + position);
103    return ptr;
104}
105
106void Memory::UpdateDataSize(size_t realWriteSize, size_t position)
107{
108    if (position + realWriteSize > capacity) {
109        return;
110    }
111    size = (realWriteSize + position);
112}
113
114size_t Memory::GetSize()
115{
116    return size;
117}
118
119uint8_t* Memory::GetRealAddr() const
120{
121    return addr.get() + offset;
122}
123
124MemoryType Memory::GetMemoryType()
125{
126    return memoryType;
127}
128
129BufferMeta::BufferMeta(BufferMetaType type) : type_(type), tags_(std::make_shared<Meta>())
130{
131}
132
133ValueType BufferMeta::GetMeta(Tag tag)
134{
135    if (tags_) {
136        return (*tags_)[tag];
137    }
138    return {};
139}
140
141void BufferMeta::SetMeta(Tag tag, ValueType value)
142{
143    (*tags_)[tag] = value;
144}
145
146BufferMetaType BufferMeta::GetType() const
147{
148    return type_;
149}
150
151bool BufferMeta::IsExist(Tag tag)
152{
153    return tags_->Find(tag) != tags_->end();
154}
155
156void BufferMeta::Update(const BufferMeta& bufferMeta)
157{
158    type_ = bufferMeta.GetType();
159    *tags_ = *bufferMeta.tags_;
160}
161
162std::shared_ptr<BufferMeta> AudioBufferMeta::Clone()
163{
164    auto bufferMeta = std::shared_ptr<AudioBufferMeta>(new AudioBufferMeta());
165    bufferMeta->samples = samples;
166    bufferMeta->sampleFormat = sampleFormat;
167    bufferMeta->sampleRate = sampleRate;
168    bufferMeta->channels = channels;
169    bufferMeta->bytesPreFrame = bytesPreFrame;
170    bufferMeta->channelLayout = channelLayout;
171    bufferMeta->offsets = offsets;
172    bufferMeta->Update(*this);
173    return bufferMeta;
174}
175
176std::shared_ptr<BufferMeta> VideoBufferMeta::Clone()
177{
178    auto bufferMeta = std::shared_ptr<VideoBufferMeta>(new VideoBufferMeta());
179    bufferMeta->videoPixelFormat = videoPixelFormat;
180    bufferMeta->id = id;
181    bufferMeta->width = width;
182    bufferMeta->height = height;
183    bufferMeta->planes = planes;
184    bufferMeta->stride = stride;
185    bufferMeta->offset = offset;
186    bufferMeta->Update(*this);
187    return bufferMeta;
188}
189
190Buffer::Buffer(BufferMetaType type) : trackID(0), pts(0), dts(0), duration(0), flag (0), meta()
191{
192    if (type == BufferMetaType::AUDIO) {
193        meta = std::shared_ptr<AudioBufferMeta>(new AudioBufferMeta());
194    } else if (type == BufferMetaType::VIDEO) {
195        meta = std::shared_ptr<VideoBufferMeta>(new VideoBufferMeta());
196    }
197}
198
199std::shared_ptr<Buffer> Buffer::CreateDefaultBuffer(BufferMetaType type, size_t capacity,
200                                                    std::shared_ptr<Allocator> allocator, size_t align)
201{
202    auto buffer = std::make_shared<Buffer>(type);
203    std::shared_ptr<Memory> memory = std::shared_ptr<Memory>(new Memory(capacity, allocator, align));
204    buffer->data.push_back(memory);
205    return buffer;
206}
207
208std::shared_ptr<Memory> Buffer::WrapMemory(uint8_t* data, size_t capacity, size_t size)
209{
210    auto memory = std::shared_ptr<Memory>(new Memory(capacity, std::shared_ptr<uint8_t>(data, [](void* ptr) {})));
211    memory->size = size;
212    this->data.push_back(memory);
213    return memory;
214}
215
216std::shared_ptr<Memory> Buffer::WrapMemoryPtr(std::shared_ptr<uint8_t> data, size_t capacity, size_t size)
217{
218    auto memory = std::shared_ptr<Memory>(new Memory(capacity, data));
219    memory->size = size;
220    this->data.push_back(memory);
221    return memory;
222}
223
224#if !defined(OHOS_LITE) && defined(VIDEO_SUPPORT)
225std::shared_ptr<Memory> Buffer::WrapSurfaceMemory(sptr<SurfaceBuffer> surfaceBuffer)
226{
227    int32_t bufferSize;
228    auto ret = surfaceBuffer->GetExtraData()->ExtraGet("dataSize", bufferSize);
229    if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK || bufferSize <= 0) {
230        return nullptr;
231    }
232    auto memory = std::shared_ptr<SurfaceMemory>(new SurfaceMemory(surfaceBuffer, bufferSize));
233    this->data.push_back(memory);
234    return memory;
235}
236#endif
237
238std::shared_ptr<Memory> Buffer::AllocMemory(std::shared_ptr<Allocator> allocator, size_t capacity, size_t align)
239{
240    auto type = (allocator != nullptr) ? allocator->GetMemoryType() : MemoryType::VIRTUAL_ADDR;
241    std::shared_ptr<Memory> memory = nullptr;
242    switch (type) {
243        case MemoryType::VIRTUAL_ADDR: {
244            memory = std::shared_ptr<Memory>(new Memory(capacity, allocator, align));
245            break;
246        }
247#if !defined(OHOS_LITE) && defined(VIDEO_SUPPORT)
248        case MemoryType::SURFACE_BUFFER: {
249            memory = std::shared_ptr<Memory>(new SurfaceMemory(capacity, allocator, align));
250            break;
251        }
252        case MemoryType::SHARE_MEMORY:
253            memory = std::shared_ptr<Memory>(new ShareMemory(capacity, allocator, align));
254            break;
255#endif
256        default:
257            break;
258    }
259    if (memory == nullptr) {
260        return nullptr;
261    }
262    data.push_back(memory);
263    return memory;
264}
265
266uint32_t Buffer::GetMemoryCount()
267{
268    return data.size();
269}
270
271std::shared_ptr<Memory> Buffer::GetMemory(uint32_t index)
272{
273    if (data.size() <= index) {
274        return nullptr;
275    }
276    return data[index];
277}
278
279std::shared_ptr<BufferMeta> Buffer::GetBufferMeta()
280{
281    return meta;
282}
283
284void Buffer::UpdateBufferMeta(const BufferMeta& bufferMeta)
285{
286    meta->Update(bufferMeta);
287}
288
289bool Buffer::IsEmpty()
290{
291    return data.empty();
292}
293
294void Buffer::Reset()
295{
296    data[0]->Reset();
297    trackID = 0;
298    pts = 0;
299    dts = 0;
300    duration = 0;
301    flag = 0;
302    BufferMetaType type = meta->GetType();
303    meta.reset();
304    if (type == BufferMetaType::AUDIO) {
305        meta = std::shared_ptr<AudioBufferMeta>(new AudioBufferMeta());
306    } else if (type == BufferMetaType::VIDEO) {
307        meta = std::shared_ptr<VideoBufferMeta>(new VideoBufferMeta());
308    }
309}
310
311void Buffer::ChangeBufferMetaType(BufferMetaType type)
312{
313    meta.reset();
314    if (type == BufferMetaType::AUDIO) {
315        meta = std::shared_ptr<AudioBufferMeta>(new AudioBufferMeta());
316    } else if (type == BufferMetaType::VIDEO) {
317        meta = std::shared_ptr<VideoBufferMeta>(new VideoBufferMeta());
318    }
319}
320
321} // namespace Plugin
322} // namespace Media
323} // namespace OHOS
324