1 /*
2 * Copyright (c) 2022-2023 Shenzhen Kaihong DID 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 "codec_share_buffer.h"
17 #include <hdf_base.h>
18 #include <securec.h>
19 #include <unistd.h>
20 #include "codec_log_wrapper.h"
21 using namespace OHOS::HDI::Codec::V4_0;
22 namespace OHOS {
23 namespace Codec {
24 namespace Omx {
25
UseBuffer(OMX_HANDLETYPE comp,uint32_t portIndex,OmxCodecBuffer & codecBuffer,OMX_BUFFERHEADERTYPE * & header,bool doCopy)26 sptr<ICodecBuffer> CodecShareBuffer::UseBuffer(OMX_HANDLETYPE comp, uint32_t portIndex,
27 OmxCodecBuffer &codecBuffer, OMX_BUFFERHEADERTYPE *&header, bool doCopy)
28 {
29 CHECK_AND_RETURN_RET_LOG(comp != nullptr, nullptr, "null component");
30 CHECK_AND_RETURN_RET_LOG(codecBuffer.fd != nullptr, nullptr, "invalid ashmem fd");
31 CODEC_LOGI("port=%{public}u, use ashmem, fd=%{public}d, doCopy=%{public}d",
32 portIndex, codecBuffer.fd->Get(), doCopy);
33
34 int size = OHOS::AshmemGetSize(codecBuffer.fd->Get());
35 CHECK_AND_RETURN_RET_LOG(size > 0, nullptr, "ashmem fd has invalid size");
36 codecBuffer.allocLen = static_cast<uint32_t>(size);
37
38 sptr<Ashmem> shMem = sptr<Ashmem>::MakeSptr(codecBuffer.fd->Release(), size);
39 CHECK_AND_RETURN_RET_LOG(shMem != nullptr, nullptr, "create Ashmem failed");
40
41 bool mapd = shMem->MapReadAndWriteAshmem();
42 CHECK_AND_RETURN_RET_LOG(mapd, nullptr, "MapReadAndWriteAshmem failed");
43
44 OMX_U8 *va = reinterpret_cast<OMX_U8 *>(const_cast<void*>(shMem->ReadFromAshmem(size, 0)));
45 int32_t err = doCopy ? OMX_AllocateBuffer(comp, &header, portIndex, nullptr, size) :
46 OMX_UseBuffer(comp, &header, portIndex, nullptr, size, va);
47 if (err != OMX_ErrorNone) {
48 CODEC_LOGE("OMX_AllocateBuffer or OMX_UseBuffer ret = [%{public}x]", err);
49 return nullptr;
50 }
51 codecBuffer.bufferhandle = nullptr;
52 codecBuffer.fd.reset();
53 codecBuffer.fenceFd.reset();
54 return sptr<ICodecBuffer>(new CodecShareBuffer(
55 InitInfo{comp, portIndex, codecBuffer, header}, shMem, doCopy)
56 );
57 }
58
AllocateBuffer(OMX_HANDLETYPE comp,uint32_t portIndex,OmxCodecBuffer & codecBuffer,OMX_BUFFERHEADERTYPE * & header)59 OHOS::sptr<ICodecBuffer> CodecShareBuffer::AllocateBuffer(OMX_HANDLETYPE comp, uint32_t portIndex,
60 OmxCodecBuffer &codecBuffer, OMX_BUFFERHEADERTYPE *&header)
61 {
62 CHECK_AND_RETURN_RET_LOG(comp != nullptr, nullptr, "null component");
63 CHECK_AND_RETURN_RET_LOG(codecBuffer.allocLen > 0, nullptr, "invalid allocLen");
64 sptr<Ashmem> shMem = Ashmem::CreateAshmem("codechdi", codecBuffer.allocLen);
65 CHECK_AND_RETURN_RET_LOG(shMem != nullptr, nullptr, "create Ashmem failed");
66 CODEC_LOGI("port=%{public}u, allocate ashmem, fd=%{public}d", portIndex, shMem->GetAshmemFd());
67
68 bool mapd = shMem->MapReadAndWriteAshmem();
69 CHECK_AND_RETURN_RET_LOG(mapd, nullptr, "MapReadAndWriteAshmem failed");
70
71 int32_t err = OMX_AllocateBuffer(comp, &header, portIndex, nullptr, codecBuffer.allocLen);
72 if (err != OMX_ErrorNone) {
73 CODEC_LOGE("OMX_AllocateBuffer error, err = %{public}x", err);
74 return nullptr;
75 }
76 codecBuffer.bufferhandle = nullptr;
77 codecBuffer.fd = UniqueFd::Create(shMem->GetAshmemFd(), false);
78 codecBuffer.fenceFd.reset();
79 return sptr<ICodecBuffer>(new CodecShareBuffer(
80 InitInfo{comp, portIndex, codecBuffer, header}, shMem, true)
81 );
82 }
83
EmptyThisBuffer(OmxCodecBuffer & codecBuffer)84 int32_t CodecShareBuffer::EmptyThisBuffer(OmxCodecBuffer &codecBuffer)
85 {
86 if (codecBuffer_.allocLen < codecBuffer.offset ||
87 codecBuffer_.allocLen < codecBuffer.offset + codecBuffer.filledLen) {
88 CODEC_LOGE("invalid param, allocLen %{public}u, offset %{public}u, filledLen %{public}u",
89 codecBuffer_.allocLen, codecBuffer.offset, codecBuffer.filledLen);
90 return OMX_ErrorBadParameter;
91 }
92 if (doCopy_) {
93 void *src = const_cast<void *>(shMem_->ReadFromAshmem(codecBuffer.filledLen, codecBuffer.offset));
94 if (src == nullptr) {
95 CODEC_LOGE("invalid param, allocLen %{public}u, offset %{public}u, filledLen %{public}u",
96 codecBuffer_.allocLen, codecBuffer.offset, codecBuffer.filledLen);
97 return OMX_ErrorBadParameter;
98 }
99 if (omxBufHeader_->pBuffer == nullptr) {
100 CODEC_LOGE("null pBuffer");
101 return OMX_ErrorBadParameter;
102 }
103 auto ret = memcpy_s(omxBufHeader_->pBuffer + codecBuffer.offset, codecBuffer_.allocLen - codecBuffer.offset,
104 src, codecBuffer.filledLen);
105 if (ret != EOK) {
106 CODEC_LOGE("memcpy_s ret [%{public}d]", ret);
107 return OMX_ErrorBadParameter;
108 }
109 }
110 return ICodecBuffer::EmptyThisBuffer(codecBuffer);
111 }
112
FillBufferDone(OMX_BUFFERHEADERTYPE & omxBuffer,OmxCodecBuffer & codecBuffer)113 int32_t CodecShareBuffer::FillBufferDone(OMX_BUFFERHEADERTYPE &omxBuffer, OmxCodecBuffer& codecBuffer)
114 {
115 if (codecBuffer_.allocLen < omxBuffer.nOffset ||
116 codecBuffer_.allocLen < omxBuffer.nOffset + omxBuffer.nFilledLen) {
117 CODEC_LOGE("invalid param, allocLen %{public}u, offset %{public}u, filledLen %{public}u",
118 codecBuffer_.allocLen, omxBuffer.nOffset, omxBuffer.nFilledLen);
119 return OMX_ErrorBadParameter;
120 }
121 if (doCopy_) {
122 if (omxBuffer.pBuffer == nullptr) {
123 CODEC_LOGE("null pBuffer");
124 return OMX_ErrorBadParameter;
125 }
126 if (!shMem_->WriteToAshmem(omxBuffer.pBuffer, omxBuffer.nFilledLen, omxBuffer.nOffset)) {
127 CODEC_LOGE("WriteToAshmem failed");
128 return OMX_ErrorBadParameter;
129 }
130 }
131 return ICodecBuffer::FillBufferDone(omxBuffer, codecBuffer);
132 }
133
134 } // namespace Omx
135 } // namespace Codec
136 } // namespace OHOS