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/plugin_buffer.h"
17#include "securec.h"
18
19namespace OHOS {
20namespace Media {
21namespace Plugins {
22Memory::Memory(size_t capacity, std::shared_ptr<uint8_t> bufData, size_t align, MemoryType type)
23    : memoryType(type), capacity(capacity), alignment(align),
24      offset(0), size(0), allocator(nullptr), addr(std::move(bufData))
25{
26}
27
28Memory::Memory(size_t capacity, std::shared_ptr<Allocator> allocator, size_t align, MemoryType type, bool allocMem)
29    : memoryType(type), capacity(capacity), alignment(align), offset(0),
30      size(0), allocator(std::move(allocator)), addr(nullptr)
31{
32    if (!allocMem) { // SurfaceMemory alloc mem in subclass
33        return;
34    }
35    size_t allocSize = align ? (capacity + align - 1) : capacity;
36    if (this->allocator) {
37        addr = std::shared_ptr<uint8_t>(static_cast<uint8_t*>(this->allocator->Alloc(allocSize)),
38                                        [this](uint8_t* ptr) { this->allocator->Free(static_cast<void*>(ptr)); });
39    } else {
40        addr = std::shared_ptr<uint8_t>(new uint8_t[allocSize], std::default_delete<uint8_t[]>());
41    }
42    offset = static_cast<size_t>(AlignUp(reinterpret_cast<uintptr_t>(addr.get()), static_cast<uintptr_t>(align)) -
43        reinterpret_cast<uintptr_t>(addr.get()));
44}
45
46size_t Memory::GetCapacity()
47{
48    return capacity;
49}
50
51void Memory::Reset()
52{
53    this->size = 0;
54}
55
56size_t Memory::Write(const uint8_t* in, size_t writeSize, size_t position)
57{
58    size_t start = 0;
59    if (position == MEM_INVALID_POSITION) {
60        start = size;
61    } else {
62        start = std::min(position, capacity);
63    }
64    size_t length = std::min(writeSize, capacity - start);
65    if (memcpy_s(GetRealAddr() + start, length, in, length) != EOK) {
66        return 0;
67    }
68    size = start + length;
69    return length;
70}
71
72size_t Memory::Read(uint8_t* out, size_t readSize, size_t position)
73{
74    size_t start = 0;
75    size_t maxLength = size;
76    if (position != MEM_INVALID_POSITION) {
77        start = std::min(position, size);
78        maxLength = size - start;
79    }
80    size_t length = std::min(readSize, maxLength);
81    if (memcpy_s(out, length, GetRealAddr() + start, length) != EOK) {
82        return 0;
83    }
84    return length;
85}
86
87const uint8_t* Memory::GetReadOnlyData(size_t position)
88{
89    if (position > capacity) {
90        return nullptr;
91    }
92    return GetRealAddr() + position;
93}
94
95uint8_t* Memory::GetWritableAddr(size_t estimatedWriteSize, size_t position)
96{
97    if (position + estimatedWriteSize > capacity) {
98        return nullptr;
99    }
100    uint8_t* ptr = GetRealAddr() + position;
101    size = (estimatedWriteSize + position);
102    return ptr;
103}
104
105void Memory::UpdateDataSize(size_t realWriteSize, size_t position)
106{
107    if (position + realWriteSize > capacity) {
108        return;
109    }
110    size = (realWriteSize + position);
111}
112
113size_t Memory::GetSize()
114{
115    return size;
116}
117
118uint8_t* Memory::GetRealAddr() const
119{
120    return addr.get() + offset;
121}
122
123MemoryType Memory::GetMemoryType()
124{
125    return memoryType;
126}
127
128Buffer::Buffer() : streamID(0), trackID(0), pts(0), dts(0), duration(0), flag (0)
129{
130}
131
132std::shared_ptr<Buffer> Buffer::CreateDefaultBuffer(size_t capacity, std::shared_ptr<Allocator> allocator, size_t align)
133{
134    auto buffer = std::make_shared<Buffer>();
135    std::shared_ptr<Memory> memory = std::shared_ptr<Memory>(new Memory(capacity, allocator, align));
136    buffer->data.push_back(memory);
137    return buffer;
138}
139
140std::shared_ptr<Memory> Buffer::WrapMemory(uint8_t* data, size_t capacity, size_t size)
141{
142    auto memory = std::shared_ptr<Memory>(new Memory(capacity, std::shared_ptr<uint8_t>(data, [](void* ptr) {})));
143    memory->size = size;
144    this->data.push_back(memory);
145    return memory;
146}
147
148std::shared_ptr<Memory> Buffer::WrapMemoryPtr(std::shared_ptr<uint8_t> data, size_t capacity, size_t size)
149{
150    auto memory = std::shared_ptr<Memory>(new Memory(capacity, data));
151    memory->size = size;
152    this->data.push_back(memory);
153    return memory;
154}
155
156std::shared_ptr<Memory> Buffer::AllocMemory(std::shared_ptr<Allocator> allocator, size_t capacity, size_t align)
157{
158    auto type = (allocator != nullptr) ? allocator->GetMemoryType() : MemoryType::VIRTUAL_MEMORY;
159    std::shared_ptr<Memory> memory = nullptr;
160    switch (type) {
161        case MemoryType::VIRTUAL_MEMORY: {
162            memory = std::shared_ptr<Memory>(new Memory(capacity, allocator, align));
163            break;
164        }
165        default:
166            break;
167    }
168    if (memory == nullptr) {
169        return nullptr;
170    }
171    data.push_back(memory);
172    return memory;
173}
174
175uint32_t Buffer::GetMemoryCount()
176{
177    return data.size();
178}
179
180std::shared_ptr<Memory> Buffer::GetMemory(uint32_t index)
181{
182    if (data.size() <= index) {
183        return nullptr;
184    }
185    return data[index];
186}
187
188bool Buffer::IsEmpty()
189{
190    return data.empty();
191}
192
193void Buffer::Reset()
194{
195    data[0]->Reset();
196    streamID = 0;
197    trackID = 0;
198    pts = 0;
199    dts = 0;
200    duration = 0;
201    flag = 0;
202}
203} // namespace Plugins
204} // namespace Media
205} // namespace OHOS
206