blob: 129d404bbab8d5e478646ea0983fc55b8967bfdf [file] [log] [blame]
/**
* Copyright (C) 2019 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.
*/
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <binder/Binder.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <binder/MemoryBase.h>
#include <binder/MemoryDealer.h>
#include <binder/MemoryHeapBase.h>
#include <media/IMediaPlayerService.h>
#include <media/IOMX.h>
#include <media/OMXBuffer.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
#include <media/omx/1.0/WOmx.h>
#include <cutils/properties.h>
#include "OMX_Component.h" // OMX_PARAM_PORTDEFINITIONTYPE
#include <binder/MemoryBase.h>
#include <binder/MemoryDealer.h>
#include <binder/MemoryHeapBase.h>
using namespace android;
using namespace android::binder;
template <class T>
static void InitOMXParams(T *params) {
params->nSize = sizeof(T);
params->nVersion.s.nVersionMajor = 1;
params->nVersion.s.nVersionMinor = 0;
params->nVersion.s.nRevision = 0;
params->nVersion.s.nStep = 0;
}
struct DummyOMXObserver : public BnOMXObserver {
public:
DummyOMXObserver() {}
virtual void onMessages(const std::list<omx_message> &messages) {
if (messages.empty()) {
return;
}
}
protected:
virtual ~DummyOMXObserver() {}
};
static bool connectOMX(sp<IOMX> &omx) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("media.player"));
sp<IMediaPlayerService> mediaPlayerService =
interface_cast<IMediaPlayerService>(binder);
if (mediaPlayerService == NULL) {
// cannot get the media player service
return false;
}
omx = mediaPlayerService->getOMX();
if (omx == NULL) {
// cannot get the OMX interface
return false;
}
return true;
}
int main() {
android::ProcessState::self()->startThreadPool();
sp<IOMX> omx;
if (connectOMX(omx) == false) {
return EXIT_FAILURE;
}
status_t err;
sp<IOMXNode> node;
sp<DummyOMXObserver> observer = new DummyOMXObserver();
const char *codecName = "OMX.Nvidia.h265.decode.secure";
err = omx->allocateNode(codecName, observer, &node);
if (err != OK) {
// node allocation fails
return EXIT_FAILURE;
}
int fenceFd = -1;
int inMemSize;
int inBufferCnt;
int inBufferSize;
int outMemSize;
int outBufferCnt;
int outBufferSize;
sp<MemoryDealer> dealerIn;
sp<MemoryDealer> dealerOut;
IOMX::buffer_id *inBufferId;
IOMX::buffer_id *outBufferId;
OMX_INDEXTYPE omx_indextype;
OMX_PARAM_PORTDEFINITIONTYPE defInput;
OMX_PARAM_PORTDEFINITIONTYPE defOutput;
{
omx_indextype = OMX_IndexParamPortDefinition;
// get input port parameters
InitOMXParams(&defInput);
defInput.nPortIndex = 0;
err = node->getParameter(omx_indextype, &defInput, sizeof(defInput));
// get output port parameters
InitOMXParams(&defOutput);
defOutput.nPortIndex = 1;
err = node->getParameter(omx_indextype, &defOutput, sizeof(defOutput));
}
err = node->setPortMode(0, IOMX::kPortModePresetSecureBuffer);
inMemSize = defInput.nBufferCountActual * defInput.nBufferSize;
inBufferCnt = defInput.nBufferCountActual;
inBufferSize = inMemSize / inBufferCnt;
// prepare input port buffers
dealerIn = new MemoryDealer(inMemSize);
inBufferId = new IOMX::buffer_id[inBufferCnt];
// change state from loaded to idle
err = node->sendCommand(OMX_CommandStateSet, 2);
usleep(300000);
for (int i = 0; i < inBufferCnt; i++) {
sp<IMemory> memory = dealerIn->allocate(inBufferSize);
for (int i = 0; i < inBufferSize / 4; i++) {
*((int *)memory->pointer() + i) = 0x12345678;
}
OMXBuffer omxBuf(memory);
void *buffer_data = NULL;
sp<NativeHandle> native_handle;
err = node->allocateSecureBuffer(0, inBufferSize, &inBufferId[i],
&buffer_data, &native_handle);
}
// prepare output port buffers
outMemSize = defOutput.nBufferCountActual * defOutput.nBufferSize;
outBufferCnt = defOutput.nBufferCountActual;
outBufferSize = outMemSize / outBufferCnt;
// prepare output port buffers
dealerOut = new MemoryDealer(outMemSize);
outBufferId = new IOMX::buffer_id[outBufferCnt];
for (int i = 0; i < outBufferCnt; i++) {
sp<IMemory> memory = dealerOut->allocate(outBufferSize);
memset(memory->pointer(), 0x66, outBufferSize);
OMXBuffer omxBuf(memory);
err = node->useBuffer(1, omxBuf, &outBufferId[i]);
}
// change state from idle to executing
err = node->sendCommand(OMX_CommandStateSet, 3);
usleep(300000);
for (int i = 0; i < inBufferCnt; i++) {
OMXBuffer omxBuf(0, inBufferSize);
err = node->emptyBuffer(inBufferId[i], omxBuf, 0, 0, fenceFd);
}
for (int i = 0; i < outBufferCnt; i++) {
OMXBuffer omxBuf(0, outBufferSize);
err = node->fillBuffer(outBufferId[i], omxBuf, fenceFd);
}
return EXIT_SUCCESS;
}