blob: 03499f23c958cb2b33d96730eae1aca1b00665bb [file] [log] [blame]
/*
* Copyright 2016, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "WOmxBufferProducer-utils"
#include <utils/Log.h>
#include <media/omx/1.0/WOmxBufferProducer.h>
#include <media/omx/1.0/WOmxProducerListener.h>
#include <media/omx/1.0/Conversion.h>
namespace android {
namespace hardware {
namespace media {
namespace omx {
namespace V1_0 {
namespace utils {
// TWOmxBufferProducer
TWOmxBufferProducer::TWOmxBufferProducer(
sp<IGraphicBufferProducer> const& base):
mBase(base) {
}
Return<void> TWOmxBufferProducer::requestBuffer(
int32_t slot, requestBuffer_cb _hidl_cb) {
sp<GraphicBuffer> buf;
status_t status = mBase->requestBuffer(slot, &buf);
AnwBuffer anwBuffer;
wrapAs(&anwBuffer, *buf);
_hidl_cb(toStatus(status), anwBuffer);
return Void();
}
Return<Status> TWOmxBufferProducer::setMaxDequeuedBufferCount(
int32_t maxDequeuedBuffers) {
return toStatus(mBase->setMaxDequeuedBufferCount(
static_cast<int>(maxDequeuedBuffers)));
}
Return<Status> TWOmxBufferProducer::setAsyncMode(bool async) {
return toStatus(mBase->setAsyncMode(async));
}
Return<void> TWOmxBufferProducer::dequeueBuffer(
uint32_t width, uint32_t height,
PixelFormat format, uint32_t usage,
bool getFrameTimestamps, dequeueBuffer_cb _hidl_cb) {
int slot;
sp<Fence> fence;
::android::FrameEventHistoryDelta outTimestamps;
status_t status = mBase->dequeueBuffer(
&slot, &fence,
width, height,
static_cast<::android::PixelFormat>(format), usage,
getFrameTimestamps ? &outTimestamps : nullptr);
hidl_handle tFence;
FrameEventHistoryDelta tOutTimestamps;
native_handle_t* nh = nullptr;
if ((fence == nullptr) || !wrapAs(&tFence, &nh, *fence)) {
ALOGE("TWOmxBufferProducer::dequeueBuffer - Invalid output fence");
_hidl_cb(toStatus(status),
static_cast<int32_t>(slot),
tFence,
tOutTimestamps);
return Void();
}
std::vector<std::vector<native_handle_t*> > nhAA;
if (getFrameTimestamps && !wrapAs(&tOutTimestamps, &nhAA, outTimestamps)) {
ALOGE("TWOmxBufferProducer::dequeueBuffer - Invalid output timestamps");
_hidl_cb(toStatus(status),
static_cast<int32_t>(slot),
tFence,
tOutTimestamps);
native_handle_delete(nh);
return Void();
}
_hidl_cb(toStatus(status),
static_cast<int32_t>(slot),
tFence,
tOutTimestamps);
native_handle_delete(nh);
if (getFrameTimestamps) {
for (auto& nhA : nhAA) {
for (auto& handle : nhA) {
native_handle_delete(handle);
}
}
}
return Void();
}
Return<Status> TWOmxBufferProducer::detachBuffer(int32_t slot) {
return toStatus(mBase->detachBuffer(slot));
}
Return<void> TWOmxBufferProducer::detachNextBuffer(
detachNextBuffer_cb _hidl_cb) {
sp<GraphicBuffer> outBuffer;
sp<Fence> outFence;
status_t status = mBase->detachNextBuffer(&outBuffer, &outFence);
AnwBuffer tBuffer;
hidl_handle tFence;
if (outBuffer == nullptr) {
ALOGE("TWOmxBufferProducer::detachNextBuffer - Invalid output buffer");
_hidl_cb(toStatus(status), tBuffer, tFence);
return Void();
}
wrapAs(&tBuffer, *outBuffer);
native_handle_t* nh = nullptr;
if ((outFence != nullptr) && !wrapAs(&tFence, &nh, *outFence)) {
ALOGE("TWOmxBufferProducer::detachNextBuffer - Invalid output fence");
_hidl_cb(toStatus(status), tBuffer, tFence);
return Void();
}
_hidl_cb(toStatus(status), tBuffer, tFence);
native_handle_delete(nh);
return Void();
}
Return<void> TWOmxBufferProducer::attachBuffer(
const AnwBuffer& buffer,
attachBuffer_cb _hidl_cb) {
int outSlot;
sp<GraphicBuffer> lBuffer = new GraphicBuffer();
if (!convertTo(lBuffer.get(), buffer)) {
ALOGE("TWOmxBufferProducer::attachBuffer - "
"Invalid input native window buffer");
_hidl_cb(toStatus(BAD_VALUE), -1);
return Void();
}
status_t status = mBase->attachBuffer(&outSlot, lBuffer);
_hidl_cb(toStatus(status), static_cast<int32_t>(outSlot));
return Void();
}
Return<void> TWOmxBufferProducer::queueBuffer(
int32_t slot, const QueueBufferInput& input,
queueBuffer_cb _hidl_cb) {
QueueBufferOutput tOutput;
IGraphicBufferProducer::QueueBufferInput lInput(
0, false, HAL_DATASPACE_UNKNOWN,
::android::Rect(0, 0, 1, 1),
NATIVE_WINDOW_SCALING_MODE_FREEZE,
0, ::android::Fence::NO_FENCE);
if (!convertTo(&lInput, input)) {
ALOGE("TWOmxBufferProducer::queueBuffer - Invalid input");
_hidl_cb(toStatus(BAD_VALUE), tOutput);
return Void();
}
IGraphicBufferProducer::QueueBufferOutput lOutput;
status_t status = mBase->queueBuffer(
static_cast<int>(slot), lInput, &lOutput);
std::vector<std::vector<native_handle_t*> > nhAA;
if (!wrapAs(&tOutput, &nhAA, lOutput)) {
ALOGE("TWOmxBufferProducer::queueBuffer - Invalid output");
_hidl_cb(toStatus(BAD_VALUE), tOutput);
return Void();
}
_hidl_cb(toStatus(status), tOutput);
for (auto& nhA : nhAA) {
for (auto& nh : nhA) {
native_handle_delete(nh);
}
}
return Void();
}
Return<Status> TWOmxBufferProducer::cancelBuffer(
int32_t slot, const hidl_handle& fence) {
sp<Fence> lFence = new Fence();
if (!convertTo(lFence.get(), fence)) {
ALOGE("TWOmxBufferProducer::cancelBuffer - Invalid input fence");
return toStatus(BAD_VALUE);
}
return toStatus(mBase->cancelBuffer(static_cast<int>(slot), lFence));
}
Return<void> TWOmxBufferProducer::query(int32_t what, query_cb _hidl_cb) {
int lValue;
int lReturn = mBase->query(static_cast<int>(what), &lValue);
_hidl_cb(static_cast<int32_t>(lReturn), static_cast<int32_t>(lValue));
return Void();
}
Return<void> TWOmxBufferProducer::connect(
const sp<IOmxProducerListener>& listener,
int32_t api, bool producerControlledByApp, connect_cb _hidl_cb) {
sp<IProducerListener> lListener = listener == nullptr ?
nullptr : new LWOmxProducerListener(listener);
IGraphicBufferProducer::QueueBufferOutput lOutput;
status_t status = mBase->connect(lListener,
static_cast<int>(api),
producerControlledByApp,
&lOutput);
QueueBufferOutput tOutput;
std::vector<std::vector<native_handle_t*> > nhAA;
if (!wrapAs(&tOutput, &nhAA, lOutput)) {
ALOGE("TWOmxBufferProducer::connect - Invalid output");
_hidl_cb(toStatus(status), tOutput);
return Void();
}
_hidl_cb(toStatus(status), tOutput);
for (auto& nhA : nhAA) {
for (auto& nh : nhA) {
native_handle_delete(nh);
}
}
return Void();
}
Return<Status> TWOmxBufferProducer::disconnect(
int32_t api, DisconnectMode mode) {
return toStatus(mBase->disconnect(
static_cast<int>(api),
toGuiDisconnectMode(mode)));
}
Return<Status> TWOmxBufferProducer::setSidebandStream(const hidl_handle& stream) {
return toStatus(mBase->setSidebandStream(NativeHandle::create(
native_handle_clone(stream), true)));
}
Return<void> TWOmxBufferProducer::allocateBuffers(
uint32_t width, uint32_t height, PixelFormat format, uint32_t usage) {
mBase->allocateBuffers(
width, height,
static_cast<::android::PixelFormat>(format),
usage);
return Void();
}
Return<Status> TWOmxBufferProducer::allowAllocation(bool allow) {
return toStatus(mBase->allowAllocation(allow));
}
Return<Status> TWOmxBufferProducer::setGenerationNumber(uint32_t generationNumber) {
return toStatus(mBase->setGenerationNumber(generationNumber));
}
Return<void> TWOmxBufferProducer::getConsumerName(getConsumerName_cb _hidl_cb) {
_hidl_cb(mBase->getConsumerName().string());
return Void();
}
Return<Status> TWOmxBufferProducer::setSharedBufferMode(bool sharedBufferMode) {
return toStatus(mBase->setSharedBufferMode(sharedBufferMode));
}
Return<Status> TWOmxBufferProducer::setAutoRefresh(bool autoRefresh) {
return toStatus(mBase->setAutoRefresh(autoRefresh));
}
Return<Status> TWOmxBufferProducer::setDequeueTimeout(int64_t timeoutNs) {
return toStatus(mBase->setDequeueTimeout(timeoutNs));
}
Return<void> TWOmxBufferProducer::getLastQueuedBuffer(
getLastQueuedBuffer_cb _hidl_cb) {
sp<GraphicBuffer> lOutBuffer = new GraphicBuffer();
sp<Fence> lOutFence = new Fence();
float lOutTransformMatrix[16];
status_t status = mBase->getLastQueuedBuffer(
&lOutBuffer, &lOutFence, lOutTransformMatrix);
AnwBuffer tOutBuffer;
if (lOutBuffer != nullptr) {
wrapAs(&tOutBuffer, *lOutBuffer);
}
hidl_handle tOutFence;
native_handle_t* nh = nullptr;
if ((lOutFence == nullptr) || !wrapAs(&tOutFence, &nh, *lOutFence)) {
ALOGE("TWOmxBufferProducer::getLastQueuedBuffer - "
"Invalid output fence");
_hidl_cb(toStatus(status),
tOutBuffer,
tOutFence,
hidl_array<float, 16>());
return Void();
}
hidl_array<float, 16> tOutTransformMatrix(lOutTransformMatrix);
_hidl_cb(toStatus(status), tOutBuffer, tOutFence, tOutTransformMatrix);
native_handle_delete(nh);
return Void();
}
Return<void> TWOmxBufferProducer::getFrameTimestamps(
getFrameTimestamps_cb _hidl_cb) {
::android::FrameEventHistoryDelta lDelta;
mBase->getFrameTimestamps(&lDelta);
FrameEventHistoryDelta tDelta;
std::vector<std::vector<native_handle_t*> > nhAA;
if (!wrapAs(&tDelta, &nhAA, lDelta)) {
ALOGE("TWOmxBufferProducer::getFrameTimestamps - "
"Invalid output frame timestamps");
_hidl_cb(tDelta);
return Void();
}
_hidl_cb(tDelta);
for (auto& nhA : nhAA) {
for (auto& nh : nhA) {
native_handle_delete(nh);
}
}
return Void();
}
Return<void> TWOmxBufferProducer::getUniqueId(getUniqueId_cb _hidl_cb) {
uint64_t outId;
status_t status = mBase->getUniqueId(&outId);
_hidl_cb(toStatus(status), outId);
return Void();
}
// LWOmxBufferProducer
LWOmxBufferProducer::LWOmxBufferProducer(sp<IOmxBufferProducer> const& base) :
mBase(base) {
}
status_t LWOmxBufferProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
*buf = new GraphicBuffer();
status_t fnStatus;
status_t transStatus = toStatusT(mBase->requestBuffer(
static_cast<int32_t>(slot),
[&fnStatus, &buf] (Status status, AnwBuffer const& buffer) {
fnStatus = toStatusT(status);
if (!convertTo(buf->get(), buffer)) {
fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
}
}));
return transStatus == NO_ERROR ? fnStatus : transStatus;
}
status_t LWOmxBufferProducer::setMaxDequeuedBufferCount(
int maxDequeuedBuffers) {
return toStatusT(mBase->setMaxDequeuedBufferCount(
static_cast<int32_t>(maxDequeuedBuffers)));
}
status_t LWOmxBufferProducer::setAsyncMode(bool async) {
return toStatusT(mBase->setAsyncMode(async));
}
status_t LWOmxBufferProducer::dequeueBuffer(
int* slot, sp<Fence>* fence,
uint32_t w, uint32_t h, ::android::PixelFormat format,
uint32_t usage, FrameEventHistoryDelta* outTimestamps) {
*fence = new Fence();
status_t fnStatus;
status_t transStatus = toStatusT(mBase->dequeueBuffer(
w, h, static_cast<PixelFormat>(format), usage,
outTimestamps != nullptr,
[&fnStatus, slot, fence, outTimestamps] (
Status status,
int32_t tSlot,
hidl_handle const& tFence,
IOmxBufferProducer::FrameEventHistoryDelta const& tTs) {
fnStatus = toStatusT(status);
*slot = tSlot;
if (!convertTo(fence->get(), tFence)) {
ALOGE("LWOmxBufferProducer::dequeueBuffer - "
"Invalid output fence");
fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
}
if (outTimestamps && !convertTo(outTimestamps, tTs)) {
ALOGE("LWOmxBufferProducer::dequeueBuffer - "
"Invalid output timestamps");
fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
}
}));
return transStatus == NO_ERROR ? fnStatus : transStatus;
}
status_t LWOmxBufferProducer::detachBuffer(int slot) {
return toStatusT(mBase->detachBuffer(static_cast<int>(slot)));
}
status_t LWOmxBufferProducer::detachNextBuffer(
sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) {
*outBuffer = new GraphicBuffer();
*outFence = new Fence();
status_t fnStatus;
status_t transStatus = toStatusT(mBase->detachNextBuffer(
[&fnStatus, outBuffer, outFence] (
Status status,
AnwBuffer const& tBuffer,
hidl_handle const& tFence) {
fnStatus = toStatusT(status);
if (!convertTo(outFence->get(), tFence)) {
ALOGE("LWOmxBufferProducer::detachNextBuffer - "
"Invalid output fence");
fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
}
if (!convertTo(outBuffer->get(), tBuffer)) {
ALOGE("LWOmxBufferProducer::detachNextBuffer - "
"Invalid output buffer");
fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
}
}));
return transStatus == NO_ERROR ? fnStatus : transStatus;
}
status_t LWOmxBufferProducer::attachBuffer(
int* outSlot, const sp<GraphicBuffer>& buffer) {
AnwBuffer tBuffer;
wrapAs(&tBuffer, *buffer);
status_t fnStatus;
status_t transStatus = toStatusT(mBase->attachBuffer(tBuffer,
[&fnStatus, outSlot] (Status status, int32_t slot) {
fnStatus = toStatusT(status);
*outSlot = slot;
}));
return transStatus == NO_ERROR ? fnStatus : transStatus;
}
status_t LWOmxBufferProducer::queueBuffer(
int slot,
const QueueBufferInput& input,
QueueBufferOutput* output) {
IOmxBufferProducer::QueueBufferInput tInput;
native_handle_t* nh;
if (!wrapAs(&tInput, &nh, input)) {
ALOGE("LWOmxBufferProducer::queueBuffer - Invalid input");
return BAD_VALUE;
}
status_t fnStatus;
status_t transStatus = toStatusT(mBase->queueBuffer(slot, tInput,
[&fnStatus, output] (
Status status,
IOmxBufferProducer::QueueBufferOutput const& tOutput) {
fnStatus = toStatusT(status);
if (!convertTo(output, tOutput)) {
ALOGE("LWOmxBufferProducer::queueBuffer - "
"Invalid output");
fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
}
}));
native_handle_delete(nh);
return transStatus == NO_ERROR ? fnStatus : transStatus;
}
status_t LWOmxBufferProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
hidl_handle tFence;
native_handle_t* nh = nullptr;
if ((fence == nullptr) || !wrapAs(&tFence, &nh, *fence)) {
ALOGE("LWOmxBufferProducer::cancelBuffer - Invalid input fence");
return BAD_VALUE;
}
status_t status = toStatusT(mBase->cancelBuffer(
static_cast<int32_t>(slot), tFence));
native_handle_delete(nh);
return status;
}
int LWOmxBufferProducer::query(int what, int* value) {
int result;
status_t transStatus = toStatusT(mBase->query(
static_cast<int32_t>(what),
[&result, value] (int32_t tResult, int32_t tValue) {
result = static_cast<int>(tResult);
*value = static_cast<int>(tValue);
}));
return transStatus == NO_ERROR ? result : static_cast<int>(transStatus);
}
status_t LWOmxBufferProducer::connect(
const sp<IProducerListener>& listener, int api,
bool producerControlledByApp, QueueBufferOutput* output) {
sp<IOmxProducerListener> tListener = listener == nullptr ?
nullptr : new TWOmxProducerListener(listener);
status_t fnStatus;
status_t transStatus = toStatusT(mBase->connect(
tListener, static_cast<int32_t>(api), producerControlledByApp,
[&fnStatus, output] (
Status status,
IOmxBufferProducer::QueueBufferOutput const& tOutput) {
fnStatus = toStatusT(status);
if (!convertTo(output, tOutput)) {
ALOGE("LWOmxBufferProducer::connect - Invalid output");
fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
}
}));
return transStatus == NO_ERROR ? fnStatus : transStatus;
}
status_t LWOmxBufferProducer::disconnect(int api, DisconnectMode mode) {
return toStatusT(mBase->disconnect(
static_cast<int32_t>(api), toOmxDisconnectMode(mode)));
}
status_t LWOmxBufferProducer::setSidebandStream(
const sp<NativeHandle>& stream) {
return toStatusT(mBase->setSidebandStream(stream->handle()));
}
void LWOmxBufferProducer::allocateBuffers(uint32_t width, uint32_t height,
::android::PixelFormat format, uint32_t usage) {
mBase->allocateBuffers(
width, height, static_cast<PixelFormat>(format), usage);
}
status_t LWOmxBufferProducer::allowAllocation(bool allow) {
return toStatusT(mBase->allowAllocation(allow));
}
status_t LWOmxBufferProducer::setGenerationNumber(uint32_t generationNumber) {
return toStatusT(mBase->setGenerationNumber(generationNumber));
}
String8 LWOmxBufferProducer::getConsumerName() const {
String8 lName;
mBase->getConsumerName([&lName] (hidl_string const& name) {
lName = name.c_str();
});
return lName;
}
status_t LWOmxBufferProducer::setSharedBufferMode(bool sharedBufferMode) {
return toStatusT(mBase->setSharedBufferMode(sharedBufferMode));
}
status_t LWOmxBufferProducer::setAutoRefresh(bool autoRefresh) {
return toStatusT(mBase->setAutoRefresh(autoRefresh));
}
status_t LWOmxBufferProducer::setDequeueTimeout(nsecs_t timeout) {
return toStatusT(mBase->setDequeueTimeout(static_cast<int64_t>(timeout)));
}
status_t LWOmxBufferProducer::getLastQueuedBuffer(
sp<GraphicBuffer>* outBuffer,
sp<Fence>* outFence,
float outTransformMatrix[16]) {
status_t fnStatus;
status_t transStatus = toStatusT(mBase->getLastQueuedBuffer(
[&fnStatus, outBuffer, outFence, &outTransformMatrix] (
Status status,
AnwBuffer const& buffer,
hidl_handle const& fence,
hidl_array<float, 16> const& transformMatrix) {
fnStatus = toStatusT(status);
*outBuffer = new GraphicBuffer();
if (!convertTo(outBuffer->get(), buffer)) {
ALOGE("LWOmxBufferProducer::getLastQueuedBuffer - "
"Invalid output buffer");
fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
}
*outFence = new Fence();
if (!convertTo(outFence->get(), fence)) {
ALOGE("LWOmxBufferProducer::getLastQueuedBuffer - "
"Invalid output fence");
fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
}
std::copy(transformMatrix.data(),
transformMatrix.data() + 16,
outTransformMatrix);
}));
return transStatus == NO_ERROR ? fnStatus : transStatus;
}
void LWOmxBufferProducer::getFrameTimestamps(FrameEventHistoryDelta* outDelta) {
mBase->getFrameTimestamps([outDelta] (
IOmxBufferProducer::FrameEventHistoryDelta const& tDelta) {
convertTo(outDelta, tDelta);
});
}
status_t LWOmxBufferProducer::getUniqueId(uint64_t* outId) const {
status_t fnStatus;
status_t transStatus = toStatusT(mBase->getUniqueId(
[&fnStatus, outId] (Status status, uint64_t id) {
fnStatus = toStatusT(status);
*outId = id;
}));
return transStatus == NO_ERROR ? fnStatus : transStatus;
}
} // namespace utils
} // namespace V1_0
} // namespace omx
} // namespace media
} // namespace hardware
} // namespace android