Android Camera数据流分析全程记录(overlay方式)
这篇文章接着上一篇文章继续:
http://blog.chinaunix.net/uid-26765074-id-3568436.html
上一篇文章overlay这个过程已经走了一遍,但是根本是这个流程还没有走完,由上一篇文章知道,最后调用了postFrame方法,
postFrame这个方法都实现了什么样的功能呢???他是怎样是的从driver获得的数据最终显示成图像的呢??
这个问题我一直在寻求答案,不过很悲催啊??这个postFrame方法我始终没有理解清楚,这里有多少说多少自己的看法,希望有大神能指点指点
这里就从postFrame入手了:
-
status_t ANativeWindowDisplayAdapter::PostFrame(ANativeWindowDisplayAdapter::DisplayFrame &dispFrame)
-
{
-
status_t ret = NO_ERROR;
-
uint32_t actualFramesWithDisplay = 0;
-
android_native_buffer_t *buffer = NULL;
-
GraphicBufferMapper &mapper = GraphicBufferMapper::get();
-
int i;
-
-
///@todo Do cropping based on the stabilized frame coordinates
-
///@todo Insert logic to drop frames here based on refresh rate of
-
///display or rendering rate whichever is lower
-
///Queue the buffer to overlay
-
-
if ( NULL == mANativeWindow ) {
-
return NO_INIT;
-
}
-
-
if (!mBuffers || !dispFrame.mBuffer) {
-
CAMHAL_LOGEA("NULL sent to PostFrame");
-
return BAD_VALUE;
-
}
-
-
for ( i = 0; i < mBufferCount; i++ )
-
{
-
if ( dispFrame.mBuffer == &mBuffers[i] )
-
{
-
break;
-
}
-
}
-
-
-
mFramesType.add( (int)mBuffers[i].opaque ,dispFrame.mType );
-
-
if ( mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED &&
-
(!mPaused || CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType) &&
-
!mSuspend)
-
{
-
Mutex::Autolock lock(mLock);
-
uint32_t xOff = (dispFrame.mOffset% PAGE_SIZE);
-
uint32_t yOff = (dispFrame.mOffset / PAGE_SIZE);
-
-
// Set crop only if current x and y offsets do not match with frame offsets
-
if((mXOff!=xOff) || (mYOff!=yOff))
-
{
-
CAMHAL_LOGDB("Offset %d xOff = %d, yOff = %d", dispFrame.mOffset, xOff, yOff);
-
uint8_t bytesPerPixel;
-
///Calculate bytes per pixel based on the pixel format
-
if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0)
-
{
-
bytesPerPixel = 2;
-
}
-
else if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0)
-
{
-
bytesPerPixel = 2;
-
}
-
else if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0)
-
{
-
bytesPerPixel = 1;
-
}
-
else
-
{
-
bytesPerPixel = 1;
-
}
-
-
CAMHAL_LOGVB(" crop.left = %d crop.top = %d crop.right = %d crop.bottom = %d",
-
xOff/bytesPerPixel, yOff , (xOff/bytesPerPixel)+mPreviewWidth, yOff+mPreviewHeight);
-
// We'll ignore any errors here, if the surface is
-
// already invalid, we'll know soon enough.
-
mANativeWindow->set_crop(mANativeWindow, xOff/bytesPerPixel, yOff,
-
(xOff/bytesPerPixel)+mPreviewWidth, yOff+mPreviewHeight);
-
-
///Update the current x and y offsets
-
mXOff = xOff;
-
mYOff = yOff;
-
}
-
//这里说说自己对以上代码的理解,上面通过传入的displayFrame类型变量check,传入的配置是否与系统此时实际显示属性一致,不一致,则从新进行裁剪,配置显示大小,位置等
-
{
-
buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque;
-
// unlock buffer before sending to display
-
mapper.unlock(*handle);
-
ret = mANativeWindow->enqueue_buffer(mANativeWindow, handle);//这里将buffer入栈,下面会分析道这个函数的由来
-
}
-
if ( NO_ERROR != ret ) {
-
CAMHAL_LOGE("Surface::queueBuffer returned error %d", ret);
-
}
-
-
mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) dispFrame.mBuffer->opaque);
-
-
-
// HWComposer has not minimum buffer requirement. We should be able to dequeue
-
// the buffer immediately
-
TIUTILS::Message msg;
-
mDisplayQ.put(&msg);
-
-
-
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
-
-
if ( mMeasureStandby )
-
{
-
CameraHal::PPM("Standby to first shot: Sensor Change completed - ", &mStandbyToShot);
-
mMeasureStandby = false;
-
}
-
else if (CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType)
-
{
-
CameraHal::PPM("Shot to snapshot: ", &mStartCapture);
-
mShotToShot = true;
-
}
-
else if ( mShotToShot )
-
{
-
CameraHal::PPM("Shot to shot: ", &mStartCapture);
-
mShotToShot = false;
-
}
-
#endif
-
-
}
-
else
-
{
-
Mutex::Autolock lock(mLock);
-
buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque;
-
-
// unlock buffer before giving it up
-
mapper.unlock(*handle);
-
-
// cancel buffer and dequeue another one
-
ret = mANativeWindow->cancel_buffer(mANativeWindow, handle);
-
if ( NO_ERROR != ret ) {
-
CAMHAL_LOGE("Surface::cancelBuffer returned error %d", ret);
-
}
-
-
mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) dispFrame.mBuffer->opaque);
-
-
TIUTILS::Message msg;
-
mDisplayQ.put(&msg);
-
ret = NO_ERROR;
-
}
-
-
return ret;
-
}
我们还是着重分析一下这个方法吧:
mANativeWindow->enqueue_buffer(mANativeWindow, handle)
首先要找的mANativewindow这个变量类型的定义,找了好久才找到的,悲催:system\core\include\system\Window.h
-
struct ANativeWindow
-
{
-
#ifdef __cplusplus
-
ANativeWindow()
-
: flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0)
-
{
-
common.magic = ANDROID_NATIVE_WINDOW_MAGIC;
-
common.version = sizeof(ANativeWindow);
-
memset(common.reserved, 0, sizeof(common.reserved));
-
}
-
-
/* Implement the methods that sp<ANativeWindow> expects so that it
-
can be used to automatically refcount ANativeWindow's. */
-
void incStrong(const void* id) const {
-
common.incRef(const_cast<android_native_base_t*>(&common));
-
}
-
void decStrong(const void* id) const {
-
common.decRef(const_cast<android_native_base_t*>(&common));
-
}
-
#endif
-
-
struct android_native_base_t common;
-
-
/* flags describing some attributes of this surface or its updater */
-
const uint32_t flags;
-
-
/* min swap interval supported by this updated */
-
const int minSwapInterval;
-
-
/* max swap interval supported by this updated */
-
const int maxSwapInterval;
-
-
/* horizontal and vertical resolution in DPI */
-
const float xdpi;
-
const float ydpi;
-
-
/* Some storage reserved for the OEM's driver. */
-
intptr_t oem[4];
-
-
/*
-
* Set the swap interval for this surface.
-
*
-
* Returns 0 on success or -errno on error.
-
*/
-
int (*setSwapInterval)(struct ANativeWindow* window, int interval);
-
-
/*
-
* hook called by EGL to acquire a buffer. After this call, the buffer
-
* is not locked, so its content cannot be modified.
-
* this call may block if no buffers are available.
-
*
-
* Returns 0 on success or -errno on error.
-
*/
-
int (*dequeueBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer** buffer);
-
-
/*
-
* hook called by EGL to lock a buffer. This MUST be called before modifying
-
* the content of a buffer. The buffer must have been acquired with
-
* dequeueBuffer first.
-
*
-
* Returns 0 on success or -errno on error.
-
*/
-
int (*lockBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer);
-
/*
-
* hook called by EGL when modifications to the render buffer are done.
-
* This unlocks and post the buffer.
-
*
-
* Buffers MUST be queued in the same order than they were dequeued.
-
*
-
* Returns 0 on success or -errno on error.
-
*/
-
int (*queueBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer);
-
-
/*
-
* hook used to retrieve information about the native window.
-
*
-
* Returns 0 on success or -errno on error.
-
*/
-
int (*query)(const struct ANativeWindow* window, int what, int* value);
-
-
/*
-
* hook used to perform various operations on the surface.
-
* (*perform)() is a generic mechanism to add functionality to
-
* ANativeWindow while keeping backward binary compatibility.
-
*
-
* DO NOT CALL THIS HOOK DIRECTLY. Instead, use the helper functions
-
* defined below.
-
*
-
* (*perform)() returns -ENOENT if the 'what' parameter is not supported
-
* by the surface's implementation.
-
*
-
* The valid operations are:
-
* NATIVE_WINDOW_SET_USAGE
-
* NATIVE_WINDOW_CONNECT (deprecated)
-
* NATIVE_WINDOW_DISCONNECT (deprecated)
-
* NATIVE_WINDOW_SET_CROP
-
* NATIVE_WINDOW_SET_BUFFER_COUNT
-
* NATIVE_WINDOW_SET_BUFFERS_GEOMETRY (deprecated)
-
* NATIVE_WINDOW_SET_BUFFERS_TRANSFORM
-
* NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP
-
* NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS
-
* NATIVE_WINDOW_SET_BUFFERS_FORMAT
-
* NATIVE_WINDOW_SET_SCALING_MODE
-
* NATIVE_WINDOW_LOCK (private)
-
* NATIVE_WINDOW_UNLOCK_AND_POST (private)
-
* NATIVE_WINDOW_API_CONNECT (private)
-
* NATIVE_WINDOW_API_DISCONNECT (private)
-
*
-
*/
-
-
int (*perform)(struct ANativeWindow* window, int operation, ... );
-
-
/*
-
* hook used to cancel a buffer that has been dequeued.
-
* No synchronization is performed between dequeue() and cancel(), so
-
* either external synchronization is needed, or these functions must be
-
* called from the same thread.
-
*/
-
int (*cancelBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer);
-
-
-
void* reserved_proc[2];
-
};
既然上面调用了这个对象的方法,那么必然你要找到他的方法是在什么地方实现的,怎么实现的
我们首先看看
mANativewindow到底前身是什么,我们调用的这个方法到底是在哪里实现的,首先我们看一下他是从哪里引入进来的??
-
int ANativeWindowDisplayAdapter::setPreviewWindow(preview_stream_ops_t* window)
-
{
-
LOG_FUNCTION_NAME;
-
///Note that Display Adapter cannot work without a valid window object
-
if ( !window)
-
{
-
CAMHAL_LOGEA("NULL window object passed to DisplayAdapter");
-
LOG_FUNCTION_NAME_EXIT;
-
return BAD_VALUE;
-
}
-
-
if ( window == mANativeWindow ) {
-
return ALREADY_EXISTS;
-
}
-
-
///Destroy the existing window object, if it exists
-
destroy();
-
-
///Move to new window obj
-
mANativeWindow = window;
-
-
LOG_FUNCTION_NAME_EXIT;
-
-
return NO_ERROR;
-
}
这个window参数最终要往上层追溯,我们这里直接说了,其实window的初始化定义在hardware interface那里,和camera service在一个目录下
-
/** Set the ANativeWindow to which preview frames are sent */
-
status_t setPreviewWindow(const sp<ANativeWindow>& buf)
-
{
-
LOGV("%s(%s) buf %p", __FUNCTION__, mName.string(), buf.get());
-
-
if (mDevice->ops->set_preview_window) {
-
mPreviewWindow = buf;
-
#ifdef OMAP_ENHANCEMENT_CPCAM
-
mHalPreviewWindow.user = mPreviewWindow.get();
-
#else
-
mHalPreviewWindow.user = this;
-
#endif
-
LOGV("%s &mHalPreviewWindow %p mHalPreviewWindow.user %p", __FUNCTION__,
-
&mHalPreviewWindow, mHalPreviewWindow.user);
-
return mDevice->ops->set_preview_window(mDevice, buf.get() ? &mHalPreviewWindow.nw : 0);
-
}
-
return INVALID_OPERATION;
-
}
上面我们看到,window通过mHalPreviewWindow传入到底层,我们还是要看看mHalPreviewWindow这个变量的初始化和实现在哪里??
-
status_t initialize(hw_module_t *module)
-
{
-
LOGI("Opening camera %s", mName.string());
-
int rc = module->methods->open(module, mName.string(),
-
(hw_device_t **)&mDevice);
-
if (rc != OK) {
-
LOGE("Could not open camera %s: %d", mName.string(), rc);
-
return rc;
-
}
-
#ifdef OMAP_ENHANCEMENT_CPCAM
-
initHalPreviewWindow(&mHalPreviewWindow);
-
initHalPreviewWindow(&mHalTapin);
-
initHalPreviewWindow(&mHalTapout);
-
#else
-
initHalPreviewWindow();
-
#endif
-
return rc;
-
}
在最初打开camera的时候会调用上面initialize方法,通过initHalPreviewWindow这个方法实现mHalPrevieWindow的初始化以及hal层需要方法是实现
-
void initHalPreviewWindow(struct camera_preview_window *window)
-
{
-
-
window->nw.cancel_buffer = __cancel_buffer;
-
window->nw.lock_buffer = __lock_buffer;
-
window->nw.dequeue_buffer = __dequeue_buffer;
-
window->nw.enqueue_buffer = __enqueue_buffer;
-
window->nw.set_buffer_count = __set_buffer_count;
-
window->nw.set_buffers_geometry = __set_buffers_geometry;
-
window->nw.set_crop = __set_crop;
-
window->nw.set_metadata = __set_metadata;
-
window->nw.set_usage = __set_usage;
-
window->nw.set_swap_interval = __set_swap_interval;
-
window->nw.update_and_get_buffer = __update_and_get_buffer;
-
window->nw.get_metadata = __get_metadata;
-
window->nw.get_buffer_dimension = __get_buffer_dimension;
-
window->nw.get_buffer_format = __get_buffer_format;
-
-
window->nw.get_min_undequeued_buffer_count =
-
__get_min_undequeued_buffer_count;
-
}
这里进行了填充,我们就看看cancel_buffer方法的实现吧
-
static int __cancel_buffer(struct preview_stream_ops* w,
-
buffer_handle_t* buffer)
-
{
-
ANativeWindow *a = anw(w);
-
return a->cancelBuffer(a,container_of(buffer, ANativeWindowBuffer, handle));
-
}
这里只是作为一个转接点,没有做任何事情,而是直接去调用了其他实现了的方法实现操作
这里通过anm这个方法转换而来的ANativeWindow类型的变量a其实就是我们在上面initialize方式中初始化的mPreviewWindow
而这个mPreviewWindow 就是上层传下来的的surface
这里是camera service层,个人认为是在这里对window这个参数进行了配置,连接api...还有其他的操作
-
status_t CameraService::Client::setPreviewWindow(const sp<IBinder>& binder,
-
const sp<ANativeWindow>& window) {
-
Mutex::Autolock lock(mLock);
-
status_t result = checkPidAndHardware();
-
if (result != NO_ERROR) return result;
-
-
// return if no change in surface.
-
if (binder == mSurface) {
-
return NO_ERROR;
-
}
-
-
if (window != 0) {
-
result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA);
-
if (result != NO_ERROR) {
-
LOGE("native_window_api_connect failed: %s (%d)", strerror(-result),
-
result);
-
return result;
-
}
-
}
-
-
// If preview has been already started, register preview buffers now.
-
if (mHardware->previewEnabled()) {
-
if (window != 0) {
-
native_window_set_scaling_mode(window.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
-
native_window_set_buffers_transform(window.get(), mOrientation);
-
result = mHardware->setPreviewWindow(window);
-
}
-
}
-
-
if (result == NO_ERROR) {
-
// Everything has succeeded. Disconnect the old window and remember the
-
// new window.
-
disconnectWindow(mPreviewWindow);
-
mSurface = binder;
-
mPreviewWindow = window;
-
} else {
-
// Something went wrong after we connected to the new window, so
-
// disconnect here.
-
disconnectWindow(window);
-
}
-
-
return result;
-
}
这里我还是暂时不做说明吧,始终不是很理解这里为什么要这样做,一直以来上面调用的cancelBuffer方法到底是在哪里实现的,这个问题纠结了我很久
这里先说说现在的想法,自己的理解,maybe wrong
这里跳度很大,看看下面的方法,来源:frameworks\base\libs\gui\SurfaceTextureClient.cpp
说的是SurfaceTextureClient类的构造方法
-
SurfaceTextureClient::SurfaceTextureClient(
-
const sp<ISurfaceTexture>& surfaceTexture)
-
{
-
SurfaceTextureClient::init();
-
SurfaceTextureClient::setISurfaceTexture(surfaceTexture);
-
}
先看看init方法:
-
void SurfaceTextureClient::init() {
-
// Initialize the ANativeWindow function pointers.
-
ANativeWindow::setSwapInterval = hook_setSwapInterval;
-
ANativeWindow::dequeueBuffer = hook_dequeueBuffer;
-
ANativeWindow::cancelBuffer = hook_cancelBuffer;
-
ANativeWindow::lockBuffer = hook_lockBuffer;
-
ANativeWindow::queueBuffer = hook_queueBuffer;
-
ANativeWindow::query = hook_query;
-
ANativeWindow::perform = hook_perform;
-
-
const_cast<int&>(ANativeWindow::minSwapInterval) = 0;
-
const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
-
-
mReqWidth = 0;
-
mReqHeight = 0;
-
mReqFormat = 0;
-
mReqUsage = 0;
-
mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
-
mDefaultWidth = 0;
-
mDefaultHeight = 0;
-
mTransformHint = 0;
-
mConnectedToCpu = false;
-
}
重点是上面我标注出来的部分,就现在的理解,这里就是上面说的cancelBuffer方法的归宿了,另外包括其他的所有方法,方法基本相同,这里为方便分析理解
我们以dequeueBuffer为例进行讲解,那就先看看hook_dequeueBuffer的实现
-
int SurfaceTextureClient::hook_dequeueBuffer(ANativeWindow* window,
-
ANativeWindowBuffer** buffer) {
-
SurfaceTextureClient* c = getSelf(window);
-
return c->dequeueBuffer(buffer);
-
}
接着调用SurfaceTextureClient类的dequeueBuffer方法
-
int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) {
-
LOGV("SurfaceTextureClient::dequeueBuffer");
-
Mutex::Autolock lock(mMutex);
-
int buf = -1;
-
status_t result = mSurfaceTexture->dequeueBuffer(&buf, mReqWidth, mReqHeight,mReqFormat, mReqUsage);
-
if (result < 0) {
-
LOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer(%d, %d, %d, %d)"
-
"failed: %d", mReqWidth, mReqHeight, mReqFormat, mReqUsage,
-
result);
-
return result;
-
}
-
sp<GraphicBuffer>& gbuf(mSlots[buf]);
-
if (result & ISurfaceTexture::RELEASE_ALL_BUFFERS) {
-
freeAllBuffers();
-
}
-
-
if ((result & ISurfaceTexture::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
-
result = mSurfaceTexture->requestBuffer(buf, &gbuf);
-
if (result != NO_ERROR) {
-
LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed: %d",
-
result);
-
return result;
-
}
-
}
-
*buffer = gbuf.get();
-
return OK;
-
}
我们需要先找到mSurfaceTexture是在哪里定义的:system\media\mca\filterpacks\videosrc\java\CameraSource.java
private SurfaceTexture mSurfaceTexture;
接下来看看他是在哪里实例化的
-
@Override
-
public void open(FilterContext context) {
-
if (mLogVerbose) Log.v(TAG, "Opening");
-
// Open camera
-
mCamera = Camera.open(mCameraId);
-
-
// Set parameters
-
getCameraParameters();
-
mCamera.setParameters(mCameraParameters);
-
-
// Create frame formats
-
createFormats();
-
-
// Bind it to our camera frame
-
mCameraFrame = (GLFrame)context.getFrameManager().newBoundFrame(mOutputFormat,
-
GLFrame.EXTERNAL_TEXTURE,
-
0);
-
mSurfaceTexture = new SurfaceTexture(mCameraFrame.getTextureId());
-
try {
-
mCamera.setPreviewTexture(mSurfaceTexture);
-
} catch (IOException e) {
-
throw new RuntimeException("Could not bind camera surface texture: " +
-
e.getMessage() + "!");
-
}
-
-
// Connect SurfaceTexture to callback
-
mSurfaceTexture.setOnFrameAvailableListener(onCameraFrameAvailableListener);
-
// Start the preview
-
mNewFrameAvailable = false;
-
mCamera.startPreview();
-
}
其他方法先不做过多分析,这里实例化了SurfaceTexture的对象,看看他的构造函数:frameworks\base\libs\gui\SurfaceTexture.cpp
-
SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
-
GLenum texTarget) :
-
mDefaultWidth(1),
-
mDefaultHeight(1),
-
mPixelFormat(PIXEL_FORMAT_RGBA_8888),
-
mBufferCount(MIN_ASYNC_BUFFER_SLOTS),
-
mClientBufferCount(0),
-
mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
-
mCurrentTexture(INVALID_BUFFER_SLOT),
-
mCurrentTransform(0),
-
mCurrentTimestamp(0),
-
mNextTransform(0),
-
mNextScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
-
mTexName(tex),
-
mSynchronousMode(false),
-
mAllowSynchronousMode(allowSynchronousMode),
-
mConnectedApi(NO_CONNECTED_API),
-
mAbandoned(false),
-
mTexTarget(texTarget) {
-
// Choose a name using the PID and a process-unique ID.
-
mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
-
-
ST_LOGV("SurfaceTexture::SurfaceTexture");
-
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
-
mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
-
mNextCrop.makeInvalid();
-
memcpy(mCurrentTransformMatrix, mtxIdentity,
-
sizeof(mCurrentTransformMatrix));
-
}
我们接着往下看,mSurfaceTexture->dequeueBuffer(&buf, mReqWidth, mReqHeight,mReqFormat, mReqUsage);
这里调用了类SurfaceTexture的方法dequeueBuffer
-
status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
-
uint32_t format, uint32_t usage) {
-
ST_LOGV("SurfaceTexture::dequeueBuffer");
-
-
if ((w && !h) || (!w && h)) {
-
ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
-
return BAD_VALUE;
-
}
-
-
Mutex::Autolock lock(mMutex);
-
-
status_t returnFlags(OK);
-
-
int found, foundSync;
-
int dequeuedCount = 0;
-
bool tryAgain = true;
-
while (tryAgain) {
-
if (mAbandoned) {
-
ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
-
return NO_INIT;
-
}
-
-
// We need to wait for the FIFO to drain if the number of buffer
-
// needs to change.
-
//
-
// The condition "number of buffers needs to change" is true if
-
// - the client doesn't care about how many buffers there are
-
// - AND the actual number of buffer is different from what was
-
// set in the last setBufferCountServer()
-
// - OR -
-
// setBufferCountServer() was set to a value incompatible with
-
// the synchronization mode (for instance because the sync mode
-
// changed since)
-
//
-
// As long as this condition is true AND the FIFO is not empty, we
-
// wait on mDequeueCondition.
-
-
const int minBufferCountNeeded = mSynchronousMode ?
-
MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
-
-
const bool numberOfBuffersNeedsToChange = !mClientBufferCount &&
-
((mServerBufferCount != mBufferCount) ||
-
(mServerBufferCount < minBufferCountNeeded));
-
-
if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) {
-
// wait for the FIFO to drain
-
mDequeueCondition.wait(mMutex);
-
// NOTE: we continue here because we need to reevaluate our
-
// whole state (eg: we could be abandoned or disconnected)
-
continue;
-
}
-
-
if (numberOfBuffersNeedsToChange) {
-
// here we're guaranteed that mQueue is empty
-
freeAllBuffersLocked();
-
mBufferCount = mServerBufferCount;
-
if (mBufferCount < minBufferCountNeeded)
-
mBufferCount = minBufferCountNeeded;
-
mCurrentTexture = INVALID_BUFFER_SLOT;
-
returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
-
}
-
-
// look for a free buffer to give to the client
-
found = INVALID_BUFFER_SLOT;
-
foundSync = INVALID_BUFFER_SLOT;
-
dequeuedCount = 0;
-
for (int i = 0; i < mBufferCount; i++) {
-
const int state = mSlots[i].mBufferState;
-
if (state == BufferSlot::DEQUEUED) {
-
dequeuedCount++;
-
}
-
-
// if buffer is FREE it CANNOT be current
-
LOGW_IF((state == BufferSlot::FREE) && (mCurrentTexture==i),
-
"dequeueBuffer: buffer %d is both FREE and current!", i);
-
-
if (ALLOW_DEQUEUE_CURRENT_BUFFER) {
-
if (state == BufferSlot::FREE || i == mCurrentTexture) {
-
foundSync = i;
-
if (i != mCurrentTexture) {
-
found = i;
-
break;
-
}
-
}
-
} else {
-
if (state == BufferSlot::FREE) {
-
foundSync = i;
-
found = i;
-
break;
-
}
-
}
-
}
-
-
// clients are not allowed to dequeue more than one buffer
-
// if they didn't set a buffer count.
-
if (!mClientBufferCount && dequeuedCount) {
-
return -EINVAL;
-
}
-
-
// See whether a buffer has been queued since the last setBufferCount so
-
// we know whether to perform the MIN_UNDEQUEUED_BUFFERS check below.
-
bool bufferHasBeenQueued = mCurrentTexture != INVALID_BUFFER_SLOT;
-
if (bufferHasBeenQueued) {
-
// make sure the client is not trying to dequeue more buffers
-
// than allowed.
-
const int avail = mBufferCount - (dequeuedCount+1);
-
if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
-
ST_LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded "
-
"(dequeued=%d)",
-
MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
-
dequeuedCount);
-
return -EBUSY;
-
}
-
}
-
-
// we're in synchronous mode and didn't find a buffer, we need to wait
-
// for some buffers to be consumed
-
tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
-
if (tryAgain) {
-
mDequeueCondition.wait(mMutex);
-
}
-
}
-
-
if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
-
// foundSync guaranteed to be != INVALID_BUFFER_SLOT
-
found = foundSync;
-
}
-
-
if (found == INVALID_BUFFER_SLOT) {
-
return -EBUSY;
-
}
-
-
const int buf = found;
-
*outBuf = found;
-
-
const bool useDefaultSize = !w && !h;
-
if (useDefaultSize) {
-
// use the default size
-
w = mDefaultWidth;
-
h = mDefaultHeight;
-
}
-
-
const bool updateFormat = (format != 0);
-
if (!updateFormat) {
-
// keep the current (or default) format
-
format = mPixelFormat;
-
}
-
-
// buffer is now in DEQUEUED (but can also be current at the same time,
-
// if we're in synchronous mode)
-
mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
-
-
const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
-
if ((buffer == NULL) ||
-
(uint32_t(buffer->width) != w) ||
-
(uint32_t(buffer->height) != h) ||
-
(uint32_t(buffer->format) != format) ||
-
((uint32_t(buffer->usage) & usage) != usage))
-
{
-
usage |= GraphicBuffer::USAGE_HW_TEXTURE;
-
status_t error;
-
sp<GraphicBuffer> graphicBuffer(
-
mGraphicBufferAlloc->createGraphicBuffer(
-
w, h, format, usage, &error));
-
if (graphicBuffer == 0) {
-
ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
-
"failed");
-
return error;
-
}
-
if (updateFormat) {
-
mPixelFormat = format;
-
}
-
mSlots[buf].mGraphicBuffer = graphicBuffer;
-
mSlots[buf].mRequestBufferCalled = false;
-
if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
-
eglDestroyImageKHR(mSlots[buf].mEglDisplay, mSlots[buf].mEglImage);
-
mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
-
mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
-
}
-
returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
-
}
-
return returnFlags;
-
}
到这里为止,其实底层调用的那些方法最终在这里都有实现,应该也已经走到了系统的ui层,本想到此为止,我还是深入看看这个方法吧
很纠结啊,看的
当已存在申请的buffer,返回buffer序号
在初始化SurfaceTexture对象时,上面的构造函数中实例化mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
createGraphicBufferAlloc的实现在以下路径:frameworks\base\libs\gui\ISurfaceComposer.cpp
-
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc()
-
{
-
uint32_t n;
-
Parcel data, reply;
-
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-
remote()->transact(BnSurfaceComposer::CREATE_GRAPHIC_BUFFER_ALLOC, data, &reply);
-
return interface_cast<IGraphicBufferAlloc>(reply.readStrongBinder());
-
}
由上面接着他会调用IGraphicBufferAlloc::createGraphicBuffer(),路径:frameworks\base\libs\gui\IGraphicBufferAlloc.cpp
-
virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
-
PixelFormat format, uint32_t usage, status_t* error) {
-
Parcel data, reply;
-
data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor());
-
data.writeInt32(w);
-
data.writeInt32(h);
-
data.writeInt32(format);
-
data.writeInt32(usage);
-
remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply);
-
sp<GraphicBuffer> graphicBuffer;
-
status_t result = reply.readInt32();
-
if (result == NO_ERROR) {
-
graphicBuffer = new GraphicBuffer();
-
reply.read(*graphicBuffer);
-
// reply.readStrongBinder();
-
// here we don't even have to read the BufferReference from
-
// the parcel, it'll die with the parcel.
-
}
-
*error = result;
-
return graphicBuffer;
-
}
这里实例化GraphicBuffer类的对象,并且用返回的这个对象实例化graphicBuffer变量
这篇文章写得很吃力,不是理解的很透彻,其中可能很多思路根本就是错误的,待修正啊。。
待续。。。。
阅读(1608) | 评论(0) | 转发(0) |