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, size](
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, buffer_data, native_handle](
149                    Status status,
150                    uint32_t outBuffer,
151                    hidl_handle const& outNativeHandle) {
152                fnStatus = toStatusT(status);
153                *buffer = outBuffer;
154                *native_handle = NativeHandle::create(
155                        native_handle_clone(outNativeHandle), true);
156            }));
157    return transStatus == NO_ERROR ? fnStatus : transStatus;
158}
159
160status_t LWOmxNode::useBuffer(
161        OMX_U32 portIndex, const OMXBuffer &omxBuffer, buffer_id *buffer) {
162    CodecBuffer codecBuffer;
163    if (!wrapAs(&codecBuffer, omxBuffer)) {
164        return BAD_VALUE;
165    }
166    status_t fnStatus;
167    status_t transStatus = toStatusT(mBase->useBuffer(
168            portIndex,
169            codecBuffer,
170            [&fnStatus, buffer](Status status, uint32_t outBuffer) {
171                fnStatus = toStatusT(status);
172                *buffer = outBuffer;
173            }));
174    return transStatus == NO_ERROR ? fnStatus : transStatus;
175}
176
177status_t LWOmxNode::freeBuffer(
178        OMX_U32 portIndex, buffer_id buffer) {
179    return toStatusT(mBase->freeBuffer(portIndex, buffer));
180}
181
182status_t LWOmxNode::fillBuffer(
183        buffer_id buffer, const OMXBuffer &omxBuffer, int fenceFd) {
184    CodecBuffer codecBuffer;
185    if (!wrapAs(&codecBuffer, omxBuffer)) {
186        return BAD_VALUE;
187    }
188    native_handle_t* fenceNh = native_handle_create_from_fd(fenceFd);
189    if (!fenceNh) {
190        return NO_MEMORY;
191    }
192    status_t status = toStatusT(mBase->fillBuffer(
193            buffer, codecBuffer, fenceNh));
194    native_handle_close(fenceNh);
195    native_handle_delete(fenceNh);
196    return status;
197}
198
199status_t LWOmxNode::emptyBuffer(
200        buffer_id buffer, const OMXBuffer &omxBuffer,
201        OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
202    CodecBuffer codecBuffer;
203    if (!wrapAs(&codecBuffer, omxBuffer)) {
204        return BAD_VALUE;
205    }
206    native_handle_t* fenceNh = native_handle_create_from_fd(fenceFd);
207    if (!fenceNh) {
208        return NO_MEMORY;
209    }
210    status_t status = toStatusT(mBase->emptyBuffer(
211            buffer,
212            codecBuffer,
213            flags,
214            toRawTicks(timestamp),
215            fenceNh));
216    native_handle_close(fenceNh);
217    native_handle_delete(fenceNh);
218    return status;
219}
220status_t LWOmxNode::getExtensionIndex(
221        const char *parameter_name,
222        OMX_INDEXTYPE *index) {
223    status_t fnStatus;
224    status_t transStatus = toStatusT(mBase->getExtensionIndex(
225            hidl_string(parameter_name),
226            [&fnStatus, index](Status status, uint32_t outIndex) {
227                fnStatus = toStatusT(status);
228                *index = toEnumIndexType(outIndex);
229            }));
230    return transStatus == NO_ERROR ? fnStatus : transStatus;
231}
232
233status_t LWOmxNode::dispatchMessage(const omx_message &lMsg) {
234    Message tMsg;
235    native_handle_t* nh;
236    if (!wrapAs(&tMsg, &nh, lMsg)) {
237        return NO_MEMORY;
238    }
239    status_t status = toStatusT(mBase->dispatchMessage(tMsg));
240    native_handle_close(nh);
241    native_handle_delete(nh);
242    return status;
243}
244
245// TWOmxNode
246TWOmxNode::TWOmxNode(sp<IOMXNode> const& base) : mBase(base) {
247}
248
249Return<Status> TWOmxNode::freeNode() {
250    return toStatus(mBase->freeNode());
251}
252
253Return<Status> TWOmxNode::sendCommand(uint32_t cmd, int32_t param) {
254    return toStatus(mBase->sendCommand(toEnumCommandType(cmd), param));
255}
256
257Return<void> TWOmxNode::getParameter(
258        uint32_t index, hidl_vec<uint8_t> const& inParams,
259        getParameter_cb _hidl_cb) {
260    hidl_vec<uint8_t> params(inParams);
261    Status status = toStatus(mBase->getParameter(
262            toEnumIndexType(index),
263            static_cast<void*>(params.data()),
264            params.size()));
265    _hidl_cb(status, params);
266    return Void();
267}
268
269Return<Status> TWOmxNode::setParameter(
270        uint32_t index, hidl_vec<uint8_t> const& inParams) {
271    hidl_vec<uint8_t> params(inParams);
272    return toStatus(mBase->setParameter(
273            toEnumIndexType(index),
274            static_cast<void const*>(params.data()),
275            params.size()));
276}
277
278Return<void> TWOmxNode::getConfig(
279        uint32_t index, const hidl_vec<uint8_t>& inConfig,
280        getConfig_cb _hidl_cb) {
281    hidl_vec<uint8_t> config(inConfig);
282    Status status = toStatus(mBase->getConfig(
283            toEnumIndexType(index),
284            static_cast<void*>(config.data()),
285            config.size()));
286    _hidl_cb(status, config);
287    return Void();
288}
289
290Return<Status> TWOmxNode::setConfig(
291        uint32_t index, const hidl_vec<uint8_t>& inConfig) {
292    hidl_vec<uint8_t> config(inConfig);
293    return toStatus(mBase->setConfig(
294            toEnumIndexType(index),
295            static_cast<void const*>(config.data()),
296            config.size()));
297}
298
299Return<Status> TWOmxNode::setPortMode(uint32_t portIndex, PortMode mode) {
300    return toStatus(mBase->setPortMode(portIndex, toIOMXPortMode(mode)));
301}
302
303Return<Status> TWOmxNode::prepareForAdaptivePlayback(
304        uint32_t portIndex, bool enable,
305        uint32_t maxFrameWidth, uint32_t maxFrameHeight) {
306    return toStatus(mBase->prepareForAdaptivePlayback(
307            portIndex,
308            toEnumBool(enable),
309            maxFrameWidth,
310            maxFrameHeight));
311}
312
313Return<void> TWOmxNode::configureVideoTunnelMode(
314        uint32_t portIndex, bool tunneled, uint32_t audioHwSync,
315        configureVideoTunnelMode_cb _hidl_cb) {
316    native_handle_t* sidebandHandle = nullptr;
317    Status status = toStatus(mBase->configureVideoTunnelMode(
318            portIndex,
319            toEnumBool(tunneled),
320            audioHwSync,
321            &sidebandHandle));
322    _hidl_cb(status, hidl_handle(sidebandHandle));
323    return Void();
324}
325
326Return<void> TWOmxNode::getGraphicBufferUsage(
327        uint32_t portIndex, getGraphicBufferUsage_cb _hidl_cb) {
328    OMX_U32 usage;
329    Status status = toStatus(mBase->getGraphicBufferUsage(
330            portIndex, &usage));
331    _hidl_cb(status, usage);
332    return Void();
333}
334
335Return<Status> TWOmxNode::setInputSurface(
336        const sp<IOmxBufferSource>& bufferSource) {
337    return toStatus(mBase->setInputSurface(new LWOmxBufferSource(
338            bufferSource)));
339}
340
341Return<void> TWOmxNode::allocateSecureBuffer(
342        uint32_t portIndex, uint64_t size,
343        allocateSecureBuffer_cb _hidl_cb) {
344    IOMX::buffer_id buffer;
345    void* bufferData;
346    sp<NativeHandle> nativeHandle;
347    Status status = toStatus(mBase->allocateSecureBuffer(
348            portIndex,
349            static_cast<size_t>(size),
350            &buffer,
351            &bufferData,
352            &nativeHandle));
353    _hidl_cb(status, buffer, nativeHandle == nullptr ?
354            nullptr : nativeHandle->handle());
355    return Void();
356}
357
358Return<void> TWOmxNode::useBuffer(
359        uint32_t portIndex, const CodecBuffer& codecBuffer,
360        useBuffer_cb _hidl_cb) {
361    IOMX::buffer_id buffer;
362    OMXBuffer omxBuffer;
363    if (!convertTo(&omxBuffer, codecBuffer)) {
364        _hidl_cb(Status::BAD_VALUE, 0);
365        return Void();
366    }
367    Status status = toStatus(mBase->useBuffer(
368            portIndex, omxBuffer, &buffer));
369    _hidl_cb(status, buffer);
370    return Void();
371}
372
373Return<Status> TWOmxNode::freeBuffer(uint32_t portIndex, uint32_t buffer) {
374    return toStatus(mBase->freeBuffer(portIndex, buffer));
375}
376
377Return<Status> TWOmxNode::fillBuffer(
378        uint32_t buffer, const CodecBuffer& codecBuffer,
379        const hidl_handle& fence) {
380    OMXBuffer omxBuffer;
381    if (!convertTo(&omxBuffer, codecBuffer)) {
382        return Status::BAD_VALUE;
383    }
384    return toStatus(mBase->fillBuffer(
385            buffer,
386            omxBuffer,
387            dup(native_handle_read_fd(fence))));
388}
389
390Return<Status> TWOmxNode::emptyBuffer(
391        uint32_t buffer, const CodecBuffer& codecBuffer, uint32_t flags,
392        uint64_t timestampUs, const hidl_handle& fence) {
393    OMXBuffer omxBuffer;
394    if (!convertTo(&omxBuffer, codecBuffer)) {
395        return Status::BAD_VALUE;
396    }
397    return toStatus(mBase->emptyBuffer(
398            buffer,
399            omxBuffer,
400            flags,
401            toOMXTicks(timestampUs),
402            dup(native_handle_read_fd(fence))));
403}
404
405Return<void> TWOmxNode::getExtensionIndex(
406        const hidl_string& parameterName,
407        getExtensionIndex_cb _hidl_cb) {
408    OMX_INDEXTYPE index;
409    Status status = toStatus(mBase->getExtensionIndex(
410            parameterName.c_str(), &index));
411    _hidl_cb(status, toRawIndexType(index));
412    return Void();
413}
414
415Return<Status> TWOmxNode::dispatchMessage(const Message& tMsg) {
416    omx_message lMsg;
417    if (!convertTo(&lMsg, tMsg)) {
418        return Status::BAD_VALUE;
419    }
420    return toStatus(mBase->dispatchMessage(lMsg));
421}
422
423}  // namespace utils
424}  // namespace V1_0
425}  // namespace omx
426}  // namespace media
427}  // namespace hardware
428}  // namespace android
429