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变量
这篇文章写得很吃力,不是理解的很透彻,其中可能很多思路根本就是错误的,待修正啊。。
待续。。。。