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