1/*
2 * Copyright 2016, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <algorithm>
18
19#include <media/omx/1.0/WOmxNode.h>
20#include <media/omx/1.0/WOmxBufferSource.h>
21#include <media/omx/1.0/Conversion.h>
22
23namespace android {
24namespace hardware {
25namespace media {
26namespace omx {
27namespace V1_0 {
28namespace utils {
29
30using ::android::hardware::Void;
31
32// LWOmxNode
33status_t LWOmxNode::freeNode() {
34    return toStatusT(mBase->freeNode());
35}
36
37status_t LWOmxNode::sendCommand(
38        OMX_COMMANDTYPE cmd, OMX_S32 param) {
39    return toStatusT(mBase->sendCommand(
40            toRawCommandType(cmd), param));
41}
42
43status_t LWOmxNode::getParameter(
44        OMX_INDEXTYPE index, void *params, size_t size) {
45    hidl_vec<uint8_t> tParams = inHidlBytes(params, size);
46    status_t fnStatus;
47    status_t transStatus = toStatusT(mBase->getParameter(
48            toRawIndexType(index),
49            tParams,
50            [&fnStatus, params](
51                    Status status, hidl_vec<uint8_t> const& outParams) {
52                fnStatus = toStatusT(status);
53                std::copy(
54                        outParams.data(),
55                        outParams.data() + outParams.size(),
56                        static_cast<uint8_t*>(params));
57            }));
58    return transStatus == NO_ERROR ? fnStatus : transStatus;
59}
60
61status_t LWOmxNode::setParameter(
62        OMX_INDEXTYPE index, const void *params, size_t size) {
63    hidl_vec<uint8_t> tParams = inHidlBytes(params, size);
64    return toStatusT(mBase->setParameter(
65            toRawIndexType(index), tParams));
66}
67
68status_t LWOmxNode::getConfig(
69        OMX_INDEXTYPE index, void *params, size_t size) {
70    hidl_vec<uint8_t> tParams = inHidlBytes(params, size);
71    status_t fnStatus;
72    status_t transStatus = toStatusT(mBase->getConfig(
73            toRawIndexType(index),
74            tParams,
75            [&fnStatus, params, size](
76                    Status status, hidl_vec<uint8_t> const& outParams) {
77                fnStatus = toStatusT(status);
78                std::copy(
79                        outParams.data(),
80                        outParams.data() + size,
81                        static_cast<uint8_t*>(params));
82            }));
83    return transStatus == NO_ERROR ? fnStatus : transStatus;
84}
85
86status_t LWOmxNode::setConfig(
87        OMX_INDEXTYPE index, const void *params, size_t size) {
88    hidl_vec<uint8_t> tParams = inHidlBytes(params, size);
89    return toStatusT(mBase->setConfig(toRawIndexType(index), tParams));
90}
91
92status_t LWOmxNode::setPortMode(
93        OMX_U32 port_index, IOMX::PortMode mode) {
94    return toStatusT(mBase->setPortMode(port_index, toHardwarePortMode(mode)));
95}
96
97status_t LWOmxNode::prepareForAdaptivePlayback(
98        OMX_U32 portIndex, OMX_BOOL enable,
99        OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) {
100    return toStatusT(mBase->prepareForAdaptivePlayback(
101            portIndex, toRawBool(enable), maxFrameWidth, maxFrameHeight));
102}
103
104status_t LWOmxNode::configureVideoTunnelMode(
105        OMX_U32 portIndex, OMX_BOOL tunneled,
106        OMX_U32 audioHwSync, native_handle_t **sidebandHandle) {
107    status_t fnStatus;
108    status_t transStatus = toStatusT(mBase->configureVideoTunnelMode(
109            portIndex,
110            toRawBool(tunneled),
111            audioHwSync,
112            [&fnStatus, sidebandHandle](
113                    Status status, hidl_handle const& outSidebandHandle) {
114                fnStatus = toStatusT(status);
115                *sidebandHandle = outSidebandHandle == nullptr ?
116                        nullptr : native_handle_clone(outSidebandHandle);
117            }));
118    return transStatus == NO_ERROR ? fnStatus : transStatus;
119}
120
121status_t LWOmxNode::getGraphicBufferUsage(
122        OMX_U32 portIndex, OMX_U32* usage) {
123    status_t fnStatus;
124    status_t transStatus = toStatusT(mBase->getGraphicBufferUsage(
125            portIndex,
126            [&fnStatus, usage](
127                    Status status, uint32_t outUsage) {
128                fnStatus = toStatusT(status);
129                *usage = outUsage;
130            }));
131    return transStatus == NO_ERROR ? fnStatus : transStatus;
132}
133
134status_t LWOmxNode::setInputSurface(
135        const sp<IOMXBufferSource> &bufferSource) {
136    return toStatusT(mBase->setInputSurface(
137            new TWOmxBufferSource(bufferSource)));
138}
139
140status_t LWOmxNode::allocateSecureBuffer(
141        OMX_U32 portIndex, size_t size, buffer_id *buffer,
142        void **buffer_data, sp<NativeHandle> *native_handle) {
143    *buffer_data = nullptr;
144    status_t fnStatus;
145    status_t transStatus = toStatusT(mBase->allocateSecureBuffer(
146            portIndex,
147            static_cast<uint64_t>(size),
148            [&fnStatus, buffer, native_handle](
149                    Status status,
150                    uint32_t outBuffer,
151                    hidl_handle const& outNativeHandle) {
152                fnStatus = toStatusT(status);
153                *buffer = outBuffer;
154                *native_handle = outNativeHandle.getNativeHandle() == nullptr ?
155                        nullptr : NativeHandle::create(
156                        native_handle_clone(outNativeHandle), true);
157            }));
158    return transStatus == NO_ERROR ? fnStatus : transStatus;
159}
160
161status_t LWOmxNode::useBuffer(
162        OMX_U32 portIndex, const OMXBuffer &omxBuffer, buffer_id *buffer) {
163    CodecBuffer codecBuffer;
164    if (!wrapAs(&codecBuffer, omxBuffer)) {
165        return BAD_VALUE;
166    }
167    status_t fnStatus;
168    status_t transStatus = toStatusT(mBase->useBuffer(
169            portIndex,
170            codecBuffer,
171            [&fnStatus, buffer](Status status, uint32_t outBuffer) {
172                fnStatus = toStatusT(status);
173                *buffer = outBuffer;
174            }));
175    return transStatus == NO_ERROR ? fnStatus : transStatus;
176}
177
178status_t LWOmxNode::freeBuffer(
179        OMX_U32 portIndex, buffer_id buffer) {
180    return toStatusT(mBase->freeBuffer(portIndex, buffer));
181}
182
183status_t LWOmxNode::fillBuffer(
184        buffer_id buffer, const OMXBuffer &omxBuffer, int fenceFd) {
185    CodecBuffer codecBuffer;
186    if (!wrapAs(&codecBuffer, omxBuffer)) {
187        return BAD_VALUE;
188    }
189    native_handle_t* fenceNh = native_handle_create_from_fd(fenceFd);
190    if (!fenceNh) {
191        return NO_MEMORY;
192    }
193    status_t status = toStatusT(mBase->fillBuffer(
194            buffer, codecBuffer, fenceNh));
195    native_handle_close(fenceNh);
196    native_handle_delete(fenceNh);
197    return status;
198}
199
200status_t LWOmxNode::emptyBuffer(
201        buffer_id buffer, const OMXBuffer &omxBuffer,
202        OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
203    CodecBuffer codecBuffer;
204    if (!wrapAs(&codecBuffer, omxBuffer)) {
205        return BAD_VALUE;
206    }
207    native_handle_t* fenceNh = native_handle_create_from_fd(fenceFd);
208    if (!fenceNh) {
209        return NO_MEMORY;
210    }
211    status_t status = toStatusT(mBase->emptyBuffer(
212            buffer,
213            codecBuffer,
214            flags,
215            toRawTicks(timestamp),
216            fenceNh));
217    native_handle_close(fenceNh);
218    native_handle_delete(fenceNh);
219    return status;
220}
221status_t LWOmxNode::getExtensionIndex(
222        const char *parameter_name,
223        OMX_INDEXTYPE *index) {
224    status_t fnStatus;
225    status_t transStatus = toStatusT(mBase->getExtensionIndex(
226            hidl_string(parameter_name),
227            [&fnStatus, index](Status status, uint32_t outIndex) {
228                fnStatus = toStatusT(status);
229                *index = toEnumIndexType(outIndex);
230            }));
231    return transStatus == NO_ERROR ? fnStatus : transStatus;
232}
233
234status_t LWOmxNode::dispatchMessage(const omx_message &lMsg) {
235    Message tMsg;
236    native_handle_t* nh;
237    if (!wrapAs(&tMsg, &nh, lMsg)) {
238        return NO_MEMORY;
239    }
240    status_t status = toStatusT(mBase->dispatchMessage(tMsg));
241    native_handle_close(nh);
242    native_handle_delete(nh);
243    return status;
244}
245
246// TWOmxNode
247TWOmxNode::TWOmxNode(sp<IOMXNode> const& base) : mBase(base) {
248}
249
250Return<Status> TWOmxNode::freeNode() {
251    return toStatus(mBase->freeNode());
252}
253
254Return<Status> TWOmxNode::sendCommand(uint32_t cmd, int32_t param) {
255    return toStatus(mBase->sendCommand(toEnumCommandType(cmd), param));
256}
257
258Return<void> TWOmxNode::getParameter(
259        uint32_t index, hidl_vec<uint8_t> const& inParams,
260        getParameter_cb _hidl_cb) {
261    hidl_vec<uint8_t> params(inParams);
262    Status status = toStatus(mBase->getParameter(
263            toEnumIndexType(index),
264            static_cast<void*>(params.data()),
265            params.size()));
266    _hidl_cb(status, params);
267    return Void();
268}
269
270Return<Status> TWOmxNode::setParameter(
271        uint32_t index, hidl_vec<uint8_t> const& inParams) {
272    hidl_vec<uint8_t> params(inParams);
273    return toStatus(mBase->setParameter(
274            toEnumIndexType(index),
275            static_cast<void const*>(params.data()),
276            params.size()));
277}
278
279Return<void> TWOmxNode::getConfig(
280        uint32_t index, const hidl_vec<uint8_t>& inConfig,
281        getConfig_cb _hidl_cb) {
282    hidl_vec<uint8_t> config(inConfig);
283    Status status = toStatus(mBase->getConfig(
284            toEnumIndexType(index),
285            static_cast<void*>(config.data()),
286            config.size()));
287    _hidl_cb(status, config);
288    return Void();
289}
290
291Return<Status> TWOmxNode::setConfig(
292        uint32_t index, const hidl_vec<uint8_t>& inConfig) {
293    hidl_vec<uint8_t> config(inConfig);
294    return toStatus(mBase->setConfig(
295            toEnumIndexType(index),
296            static_cast<void const*>(config.data()),
297            config.size()));
298}
299
300Return<Status> TWOmxNode::setPortMode(uint32_t portIndex, PortMode mode) {
301    return toStatus(mBase->setPortMode(portIndex, toIOMXPortMode(mode)));
302}
303
304Return<Status> TWOmxNode::prepareForAdaptivePlayback(
305        uint32_t portIndex, bool enable,
306        uint32_t maxFrameWidth, uint32_t maxFrameHeight) {
307    return toStatus(mBase->prepareForAdaptivePlayback(
308            portIndex,
309            toEnumBool(enable),
310            maxFrameWidth,
311            maxFrameHeight));
312}
313
314Return<void> TWOmxNode::configureVideoTunnelMode(
315        uint32_t portIndex, bool tunneled, uint32_t audioHwSync,
316        configureVideoTunnelMode_cb _hidl_cb) {
317    native_handle_t* sidebandHandle = nullptr;
318    Status status = toStatus(mBase->configureVideoTunnelMode(
319            portIndex,
320            toEnumBool(tunneled),
321            audioHwSync,
322            &sidebandHandle));
323    _hidl_cb(status, hidl_handle(sidebandHandle));
324    return Void();
325}
326
327Return<void> TWOmxNode::getGraphicBufferUsage(
328        uint32_t portIndex, getGraphicBufferUsage_cb _hidl_cb) {
329    OMX_U32 usage;
330    Status status = toStatus(mBase->getGraphicBufferUsage(
331            portIndex, &usage));
332    _hidl_cb(status, usage);
333    return Void();
334}
335
336Return<Status> TWOmxNode::setInputSurface(
337        const sp<IOmxBufferSource>& bufferSource) {
338    return toStatus(mBase->setInputSurface(new LWOmxBufferSource(
339            bufferSource)));
340}
341
342Return<void> TWOmxNode::allocateSecureBuffer(
343        uint32_t portIndex, uint64_t size,
344        allocateSecureBuffer_cb _hidl_cb) {
345    IOMX::buffer_id buffer;
346    void* bufferData;
347    sp<NativeHandle> nativeHandle;
348    Status status = toStatus(mBase->allocateSecureBuffer(
349            portIndex,
350            static_cast<size_t>(size),
351            &buffer,
352            &bufferData,
353            &nativeHandle));
354    _hidl_cb(status, buffer, nativeHandle == nullptr ?
355            nullptr : nativeHandle->handle());
356    return Void();
357}
358
359Return<void> TWOmxNode::useBuffer(
360        uint32_t portIndex, const CodecBuffer& codecBuffer,
361        useBuffer_cb _hidl_cb) {
362    IOMX::buffer_id buffer;
363    OMXBuffer omxBuffer;
364    if (!convertTo(&omxBuffer, codecBuffer)) {
365        _hidl_cb(Status::BAD_VALUE, 0);
366        return Void();
367    }
368    Status status = toStatus(mBase->useBuffer(
369            portIndex, omxBuffer, &buffer));
370    _hidl_cb(status, buffer);
371    return Void();
372}
373
374Return<Status> TWOmxNode::freeBuffer(uint32_t portIndex, uint32_t buffer) {
375    return toStatus(mBase->freeBuffer(portIndex, buffer));
376}
377
378Return<Status> TWOmxNode::fillBuffer(
379        uint32_t buffer, const CodecBuffer& codecBuffer,
380        const hidl_handle& fence) {
381    OMXBuffer omxBuffer;
382    if (!convertTo(&omxBuffer, codecBuffer)) {
383        return Status::BAD_VALUE;
384    }
385    return toStatus(mBase->fillBuffer(
386            buffer,
387            omxBuffer,
388            dup(native_handle_read_fd(fence))));
389}
390
391Return<Status> TWOmxNode::emptyBuffer(
392        uint32_t buffer, const CodecBuffer& codecBuffer, uint32_t flags,
393        uint64_t timestampUs, const hidl_handle& fence) {
394    OMXBuffer omxBuffer;
395    if (!convertTo(&omxBuffer, codecBuffer)) {
396        return Status::BAD_VALUE;
397    }
398    return toStatus(mBase->emptyBuffer(
399            buffer,
400            omxBuffer,
401            flags,
402            toOMXTicks(timestampUs),
403            dup(native_handle_read_fd(fence))));
404}
405
406Return<void> TWOmxNode::getExtensionIndex(
407        const hidl_string& parameterName,
408        getExtensionIndex_cb _hidl_cb) {
409    OMX_INDEXTYPE index;
410    Status status = toStatus(mBase->getExtensionIndex(
411            parameterName.c_str(), &index));
412    _hidl_cb(status, toRawIndexType(index));
413    return Void();
414}
415
416Return<Status> TWOmxNode::dispatchMessage(const Message& tMsg) {
417    omx_message lMsg;
418    if (!convertTo(&lMsg, tMsg)) {
419        return Status::BAD_VALUE;
420    }
421    return toStatus(mBase->dispatchMessage(lMsg));
422}
423
424}  // namespace utils
425}  // namespace V1_0
426}  // namespace omx
427}  // namespace media
428}  // namespace hardware
429}  // namespace android
430