1/*
2 * Copyright (C) 2023 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/avbuffer.h"
17#include <atomic>
18#include <iomanip>
19#include <sstream>
20#include "avbuffer_utils.h"
21#include "common/log.h"
22#include "common/status.h"
23#include "surface_buffer.h"
24#include "surface_type.h"
25#include "unistd.h"
26
27namespace {
28constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_FOUNDATION, "AVBuffer" };
29}
30
31namespace OHOS {
32namespace Media {
33AVBuffer::AVBuffer() : pts_(0), dts_(0), duration_(0), flag_(0), meta_(nullptr), memory_(nullptr) {}
34
35AVBuffer::~AVBuffer() {}
36
37std::shared_ptr<AVBuffer> AVBuffer::CreateAVBuffer(const AVBufferConfig &config)
38{
39    std::shared_ptr<AVAllocator> allocator = nullptr;
40    int32_t capacity = std::max(config.size, config.capacity);
41    MemoryFlag memflag = MemoryFlag::MEMORY_READ_WRITE;
42    switch (config.memoryType) {
43        case MemoryType::VIRTUAL_MEMORY: {
44            allocator = AVAllocatorFactory::CreateVirtualAllocator();
45            break;
46        }
47        case MemoryType::SHARED_MEMORY: {
48            memflag = config.memoryFlag;
49            allocator = AVAllocatorFactory::CreateSharedAllocator(config.memoryFlag);
50            break;
51        }
52        case MemoryType::SURFACE_MEMORY: {
53            allocator = AVAllocatorFactory::CreateSurfaceAllocator(*(config.surfaceBufferConfig));
54            break;
55        }
56        case MemoryType::HARDWARE_MEMORY: {
57            memflag = config.memoryFlag;
58            allocator = AVAllocatorFactory::CreateHardwareAllocator(config.dmaFd, capacity, config.memoryFlag);
59            break;
60        }
61        default:
62            return nullptr;
63    }
64    auto buffer = CreateAVBuffer(allocator, capacity, config.align);
65    if (buffer != nullptr) {
66        buffer->config_ = config;
67        buffer->config_.capacity = capacity;
68        buffer->config_.memoryFlag = memflag;
69    }
70    return buffer;
71}
72
73const AVBufferConfig &AVBuffer::GetConfig()
74{
75    FALSE_RETURN_V(memory_ != nullptr, config_);
76    config_.size = memory_->GetSize();
77    if (config_.memoryType == MemoryType::UNKNOWN_MEMORY) {
78        config_.memoryType = memory_->GetMemoryType();
79        config_.capacity = memory_->GetCapacity();
80        config_.align = memory_->align_;
81        config_.memoryFlag = memory_->GetMemoryFlag();
82        switch (config_.memoryType) {
83            case MemoryType::VIRTUAL_MEMORY: {
84                break;
85            }
86            case MemoryType::SHARED_MEMORY: {
87                break;
88            }
89            case MemoryType::HARDWARE_MEMORY: {
90                config_.dmaFd = memory_->GetFileDescriptor();
91                break;
92            }
93            case MemoryType::SURFACE_MEMORY: {
94                auto surfaceBuffer = memory_->GetSurfaceBuffer();
95                config_.surfaceBufferConfig->width = surfaceBuffer->GetWidth();
96                config_.surfaceBufferConfig->height = surfaceBuffer->GetHeight();
97                config_.surfaceBufferConfig->strideAlignment = surfaceBuffer->GetStride();
98                config_.surfaceBufferConfig->format = surfaceBuffer->GetFormat();
99                config_.surfaceBufferConfig->usage = surfaceBuffer->GetUsage();
100                config_.surfaceBufferConfig->colorGamut = surfaceBuffer->GetSurfaceBufferColorGamut();
101                config_.surfaceBufferConfig->transform = surfaceBuffer->GetSurfaceBufferTransform();
102                break;
103            }
104            default:
105                break;
106        }
107    }
108    return config_;
109}
110
111std::shared_ptr<AVBuffer> AVBuffer::CreateAVBuffer(std::shared_ptr<AVAllocator> allocator, int32_t capacity,
112                                                   int32_t align)
113{
114    FALSE_RETURN_V_MSG_E(allocator != nullptr, nullptr, "allocator is nullptr");
115    FALSE_RETURN_V_MSG_E(capacity >= 0, nullptr, "capacity is invalid");
116    FALSE_RETURN_V_MSG_E(align >= 0, nullptr, "align is invalid");
117
118    auto buffer = std::shared_ptr<AVBuffer>(new AVBuffer());
119    FALSE_RETURN_V_MSG_E(buffer != nullptr, nullptr, "Create AVBuffer failed, no memory");
120
121    Status ret = buffer->Init(allocator, capacity, align);
122    FALSE_RETURN_V_MSG_E(ret == Status::OK, nullptr, "Init AVBuffer failed");
123
124    buffer->meta_ = std::make_shared<Meta>();
125    FALSE_RETURN_V_MSG_E(buffer->meta_ != nullptr, nullptr, "Create meta_ failed, no memory");
126    return buffer;
127}
128
129std::shared_ptr<AVBuffer> AVBuffer::CreateAVBuffer(uint8_t *ptr, int32_t capacity, int32_t size)
130{
131    FALSE_RETURN_V_MSG_E(ptr != nullptr, nullptr, "ptr is nullptr");
132    FALSE_RETURN_V_MSG_E(capacity >= 0, nullptr, "capacity is invalid");
133    FALSE_RETURN_V_MSG_E((0 <= size) && (size <= capacity), nullptr, "size is invalid");
134
135    auto buffer = std::shared_ptr<AVBuffer>(new AVBuffer());
136    FALSE_RETURN_V_MSG_E(buffer != nullptr, nullptr, "Create AVBuffer failed, no memory");
137
138    buffer->meta_ = std::make_shared<Meta>();
139    FALSE_RETURN_V_MSG_E(buffer->meta_ != nullptr, nullptr, "Create meta_ failed, no memory");
140
141    Status ret = buffer->Init(ptr, capacity, size);
142    FALSE_RETURN_V_MSG_E(ret == Status::OK, nullptr, "Init AVBuffer failed");
143    return buffer;
144}
145
146std::shared_ptr<AVBuffer> AVBuffer::CreateAVBuffer(sptr<SurfaceBuffer> surfaceBuffer)
147{
148    FALSE_RETURN_V_MSG_E(surfaceBuffer != nullptr, nullptr, "surfaceBuffer is nullptr");
149    FALSE_RETURN_V_MSG_E(surfaceBuffer->GetSptrRefCount() > 0, nullptr, "GetSptrRefCount is invalid, count:%{public}d",
150                         surfaceBuffer->GetSptrRefCount());
151
152    auto buffer = std::shared_ptr<AVBuffer>(new AVBuffer());
153    FALSE_RETURN_V_MSG_E(buffer != nullptr, nullptr, "Create AVBuffer failed, no memory");
154
155    buffer->meta_ = std::make_shared<Meta>();
156    FALSE_RETURN_V_MSG_E(buffer->meta_ != nullptr, nullptr, "Create meta_ failed, no memory");
157
158    Status ret = buffer->Init(surfaceBuffer);
159    FALSE_RETURN_V_MSG_E(ret == Status::OK, nullptr, "Init AVBuffer failed");
160    return buffer;
161}
162
163std::shared_ptr<AVBuffer> AVBuffer::CreateAVBuffer()
164{
165    auto buffer = std::shared_ptr<AVBuffer>(new AVBuffer());
166    FALSE_RETURN_V_MSG_E(buffer != nullptr, nullptr, "Create AVBuffer failed, no memory");
167
168    buffer->meta_ = std::make_shared<Meta>();
169    FALSE_RETURN_V_MSG_E(buffer->meta_ != nullptr, nullptr, "Create meta_ failed, no memory");
170    return buffer;
171}
172
173Status AVBuffer::Init(std::shared_ptr<AVAllocator> allocator, int32_t capacity, int32_t align)
174{
175    memory_ = AVMemory::CreateAVMemory(allocator, capacity, align);
176    FALSE_RETURN_V_MSG_E(memory_ != nullptr, Status::ERROR_UNKNOWN, "Create memory failed");
177    return Status::OK;
178}
179
180Status AVBuffer::Init(uint8_t *ptr, int32_t capacity, int32_t size)
181{
182    memory_ = AVMemory::CreateAVMemory(ptr, capacity, size);
183    FALSE_RETURN_V_MSG_E(memory_ != nullptr, Status::ERROR_UNKNOWN, "Create memory failed");
184    return Status::OK;
185}
186
187Status AVBuffer::Init(sptr<SurfaceBuffer> surfaceBuffer)
188{
189    memory_ = AVMemory::CreateAVMemory(surfaceBuffer);
190    FALSE_RETURN_V_MSG_E(memory_ != nullptr, Status::ERROR_UNKNOWN, "Create memory failed");
191    return Status::OK;
192}
193
194uint64_t AVBuffer::GetUniqueId()
195{
196    if (memory_ == nullptr) {
197        return 0;
198    }
199    return memory_->uid_;
200}
201
202bool AVBuffer::WriteToMessageParcel(MessageParcel &parcel)
203{
204#ifdef MEDIA_OHOS
205    MessageParcel bufferParcel;
206    bool ret = bufferParcel.WriteUint64(GetUniqueId()) && bufferParcel.WriteInt64(pts_) &&
207               bufferParcel.WriteInt64(dts_) && bufferParcel.WriteInt64(duration_) && bufferParcel.WriteUint32(flag_) &&
208               meta_->ToParcel(bufferParcel);
209
210    if (memory_ != nullptr) {
211        MemoryType type = memory_->GetMemoryType();
212        FALSE_RETURN_V_MSG_E(type != MemoryType::VIRTUAL_MEMORY, false, "Virtual memory not support");
213
214        ret = ret && bufferParcel.WriteUint8(static_cast<uint8_t>(type)) &&
215              memory_->WriteCommonToMessageParcel(bufferParcel) && memory_->WriteToMessageParcel(bufferParcel);
216    }
217    if (ret) {
218        parcel.Append(bufferParcel);
219    }
220    return ret;
221#else
222    return false;
223#endif
224}
225
226bool AVBuffer::ReadFromMessageParcel(MessageParcel &parcel, bool isSurfaceBuffer)
227{
228#ifdef MEDIA_OHOS
229    if (isSurfaceBuffer) {
230        FALSE_RETURN_V(memory_ == nullptr, false);
231        memory_ = AVMemory::CreateAVMemory(parcel, true);
232        FALSE_RETURN_V_MSG_E(memory_ != nullptr, false, "Create memory failed");
233        return true;
234    }
235    // 1. 不同buffer更新attr:  memroy != nullptr,uid != fromParcel, 返回错误
236    // 2. 相同buffer更新attr:  memroy != nullptr,uid == fromParcel,不创建memory,更新attr + memory的attr
237    // 3. 初始化buffer:        memroy == nullptr,fromParcel != 0,创建memory
238    // 4. 只传buffer的attr:    memroy == nullptr,fromParcel == 0,更新attr
239    uint64_t uid = 0;
240    int64_t pts = 0;
241    int64_t dts = 0;
242    int64_t duration = 0;
243    uint32_t flag = 0;
244    Meta meta;
245    bool ret = parcel.ReadUint64(uid) && parcel.ReadInt64(pts) && parcel.ReadInt64(dts) &&
246               parcel.ReadInt64(duration) && parcel.ReadUint32(flag) && meta.FromParcel(parcel);
247    FALSE_RETURN_V_MSG_E(ret, false, "Unmarshalling buffer info failed");
248
249    if (memory_ != nullptr) {
250        FALSE_RETURN_V_MSG_E(GetUniqueId() == uid, false, "Can't read message parcel from other AVBuffer object!");
251        (void)parcel.ReadUint8();
252        ret = memory_->SkipCommonFromMessageParcel(parcel) && memory_->ReadFromMessageParcel(parcel);
253        FALSE_RETURN_V_MSG_E(ret, false, "Update memory info failed");
254    } else if (uid != 0) {
255        memory_ = AVMemory::CreateAVMemory(parcel, false);
256        FALSE_RETURN_V_MSG_E(memory_ != nullptr, false, "Create memory failed");
257        memory_->uid_ = uid;
258    }
259    pts_ = pts;
260    dts_ = dts;
261    duration_ = duration;
262    flag_ = flag;
263    if (meta_ == nullptr) {
264        meta_ = std::make_shared<Meta>();
265    }
266    *meta_ = std::move(meta);
267#endif
268    return true;
269}
270} // namespace Media
271} // namespace OHOS