• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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