1/* 2 * Copyright (C) 2014 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//#define LOG_NDEBUG 0 18#define LOG_TAG "GraphicBufferListener" 19 20#include <media/stagefright/foundation/ADebug.h> 21#include <media/stagefright/foundation/AMessage.h> 22#include <media/stagefright/MediaErrors.h> 23 24#include <gui/BufferItem.h> 25 26#include "GraphicBufferListener.h" 27 28namespace android { 29 30status_t GraphicBufferListener::init( 31 const sp<AMessage> ¬ify, 32 size_t bufferWidth, size_t bufferHeight, size_t bufferCount) { 33 mNotify = notify; 34 35 String8 name("GraphicBufferListener"); 36 BufferQueue::createBufferQueue(&mProducer, &mConsumer); 37 mConsumer->setConsumerName(name); 38 mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight); 39 mConsumer->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN); 40 41 status_t err = mConsumer->setMaxAcquiredBufferCount(bufferCount); 42 if (err != NO_ERROR) { 43 ALOGE("Unable to set BQ max acquired buffer count to %zu: %d", 44 bufferCount, err); 45 return err; 46 } 47 48 wp<BufferQueue::ConsumerListener> listener = 49 static_cast<BufferQueue::ConsumerListener*>(this); 50 sp<BufferQueue::ProxyConsumerListener> proxy = 51 new BufferQueue::ProxyConsumerListener(listener); 52 53 err = mConsumer->consumerConnect(proxy, false); 54 if (err != NO_ERROR) { 55 ALOGE("Error connecting to BufferQueue: %s (%d)", 56 strerror(-err), err); 57 return err; 58 } 59 60 ALOGV("init() successful."); 61 62 return OK; 63} 64 65void GraphicBufferListener::onFrameAvailable(const BufferItem& /* item */) { 66 ALOGV("onFrameAvailable() called"); 67 68 { 69 Mutex::Autolock autoLock(mMutex); 70 mNumFramesAvailable++; 71 } 72 73 sp<AMessage> notify = mNotify->dup(); 74 mNotify->setWhat(kWhatFrameAvailable); 75 mNotify->post(); 76} 77 78void GraphicBufferListener::onBuffersReleased() { 79 ALOGV("onBuffersReleased() called"); 80 // nothing to do 81} 82 83void GraphicBufferListener::onSidebandStreamChanged() { 84 ALOGW("GraphicBufferListener cannot consume sideband streams."); 85 // nothing to do 86} 87 88BufferItem GraphicBufferListener::getBufferItem() { 89 BufferItem item; 90 91 { 92 Mutex::Autolock autoLock(mMutex); 93 if (mNumFramesAvailable <= 0) { 94 ALOGE("getBuffer() called with no frames available"); 95 return item; 96 } 97 mNumFramesAvailable--; 98 } 99 100 status_t err = mConsumer->acquireBuffer(&item, 0); 101 if (err == BufferQueue::NO_BUFFER_AVAILABLE) { 102 // shouldn't happen, since we track num frames available 103 ALOGE("frame was not available"); 104 item.mBuf = -1; 105 return item; 106 } else if (err != OK) { 107 ALOGE("acquireBuffer returned err=%d", err); 108 item.mBuf = -1; 109 return item; 110 } 111 112 // Wait for it to become available. 113 err = item.mFence->waitForever("GraphicBufferListener::getBufferItem"); 114 if (err != OK) { 115 ALOGW("failed to wait for buffer fence: %d", err); 116 // keep going 117 } 118 119 // If this is the first time we're seeing this buffer, add it to our 120 // slot table. 121 if (item.mGraphicBuffer != NULL) { 122 ALOGV("setting mBufferSlot %d", item.mBuf); 123 mBufferSlot[item.mBuf] = item.mGraphicBuffer; 124 } 125 126 return item; 127} 128 129sp<GraphicBuffer> GraphicBufferListener::getBuffer(BufferItem item) { 130 sp<GraphicBuffer> buf; 131 if (item.mBuf < 0 || item.mBuf >= BufferQueue::NUM_BUFFER_SLOTS) { 132 ALOGE("getBuffer() received invalid BufferItem: mBuf==%d", item.mBuf); 133 return buf; 134 } 135 136 buf = mBufferSlot[item.mBuf]; 137 CHECK(buf.get() != NULL); 138 139 return buf; 140} 141 142status_t GraphicBufferListener::releaseBuffer(BufferItem item) { 143 if (item.mBuf < 0 || item.mBuf >= BufferQueue::NUM_BUFFER_SLOTS) { 144 ALOGE("getBuffer() received invalid BufferItem: mBuf==%d", item.mBuf); 145 return ERROR_OUT_OF_RANGE; 146 } 147 148 mConsumer->releaseBuffer(item.mBuf, item.mFrameNumber, 149 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); 150 151 return OK; 152} 153 154} // namespace android 155