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#if !defined(OHOS_LITE) && defined(VIDEO_SUPPORT)
17#include "plugin/common/surface_memory.h"
18#include <utility>
19#include "foundation/log.h"
20#include "plugin/common/surface_allocator.h"
21
22namespace OHOS {
23namespace Media {
24namespace Plugin {
25SurfaceMemory::SurfaceMemory(size_t capacity, std::shared_ptr<Allocator> allocator, size_t align)
26    : Memory(capacity, std::move(allocator), align, MemoryType::SURFACE_BUFFER, false),
27      fence_(-1),
28      stride_(0)
29{
30    MEDIA_LOG_DD("SurfaceMemory ctor.");
31    if (this->allocator != nullptr && this->allocator->GetMemoryType() == MemoryType::SURFACE_BUFFER) {
32        surfaceAllocator_ = ReinterpretPointerCast<SurfaceAllocator>(this->allocator);
33        AllocSurfaceBuffer();
34    }
35}
36
37SurfaceMemory::SurfaceMemory(sptr<SurfaceBuffer> surfaceBuffer, int32_t surfaceCapacity)
38    : Memory(surfaceCapacity, nullptr, 1, MemoryType::SURFACE_BUFFER, false), // align 1
39      surfaceBuffer_(surfaceBuffer), fence_(-1), stride_(0)
40{
41}
42
43SurfaceMemory::~SurfaceMemory()
44{
45    MEDIA_LOG_DD("SurfaceMemory dtor.");
46    ReleaseSurfaceBuffer();
47}
48
49void SurfaceMemory::AllocSurfaceBuffer()
50{
51    if (surfaceAllocator_ == nullptr || surfaceBuffer_ != nullptr) {
52        MEDIA_LOG_E("No need to allocate surface buffer.");
53        return;
54    }
55    surfaceBuffer_ = surfaceAllocator_->AllocSurfaceBuffer();
56    if (surfaceBuffer_ != nullptr) {
57        auto bufferHandle = surfaceBuffer_->GetBufferHandle();
58        if (bufferHandle != nullptr) {
59            stride_ = bufferHandle->stride;
60        }
61        fence_ = -1;
62    } else {
63        // Surface often obtain buffer failed, but doesn't cause any problem.
64        MEDIA_LOG_DD("AllocSurfaceBuffer failed.");
65    }
66}
67
68sptr<SurfaceBuffer> SurfaceMemory::GetSurfaceBuffer()
69{
70    OSAL::ScopedLock l(memMutex_);
71    if (!surfaceBuffer_ || needRender_) {
72        // request surface buffer again when old buffer flush to nullptr
73        surfaceBuffer_ = nullptr;
74        AllocSurfaceBuffer();
75        needRender_ = false;
76    }
77    return surfaceBuffer_;
78}
79
80void SurfaceMemory::ReleaseSurfaceBuffer()
81{
82    OSAL::ScopedLock l(memMutex_);
83    if (surfaceBuffer_ != nullptr && surfaceAllocator_) {
84        surfaceAllocator_->ReleaseSurfaceBuffer(surfaceBuffer_, needRender_);
85    }
86}
87
88int32_t SurfaceMemory::GetFlushFence()
89{
90    OSAL::ScopedLock l(memMutex_);
91    return fence_;
92}
93
94BufferHandle *SurfaceMemory::GetBufferHandle()
95{
96    OSAL::ScopedLock l(memMutex_);
97    if (surfaceBuffer_) {
98        return surfaceBuffer_->GetBufferHandle();
99    }
100    return nullptr;
101}
102
103void SurfaceMemory::SetNeedRender(bool needRender)
104{
105    OSAL::ScopedLock l(memMutex_);
106    needRender_ = needRender;
107}
108
109uint32_t SurfaceMemory::GetSurfaceBufferStride()
110{
111    OSAL::ScopedLock l(memMutex_);
112    return stride_;
113}
114
115uint8_t* SurfaceMemory::GetRealAddr() const
116{
117    OSAL::ScopedLock l(memMutex_);
118    if (surfaceBuffer_) {
119        return static_cast<uint8_t *>(surfaceBuffer_->GetVirAddr());
120    }
121    return nullptr;
122}
123} // namespace Plugin
124} // namespace Media
125} // namespace OHOS
126#endif