Android(安卓)Camera数据流分析全程记录(overlay方式)
16lz
2021-01-26
Android Camera数据流分析全程记录(overlay方式)
这篇文章接着上一篇文章继续: http://blog.chinaunix.net/uid-26765074-id-3568436.html
上一篇文章overlay这个过程已经走了一遍,但是根本是这个流程还没有走完,由上一篇文章知道,最后调用了postFrame方法, postFrame这个方法都实现了什么样的功能呢???他是怎样是的从driver获得的数据最终显示成图像的呢??
这个问题我一直在寻求答案,不过很悲催啊??这个postFrame方法我始终没有理解清楚,这里有多少说多少自己的看法,希望有大神能指点指点
这里就从postFrame入手了:
首先要找的mANativewindow这个变量类型的定义,找了好久才找到的,悲催:system\core\include\system\Window.h
我们首先看看 mANativewindow到底前身是什么,我们调用的这个方法到底是在哪里实现的,首先我们看一下他是从哪里引入进来的??
这里通过anm这个方法转换而来的ANativeWindow类型的变量a其实就是我们在上面initialize方式中初始化的 mPreviewWindow
而这个 mPreviewWindow就是上层传下来的的surface
这里是camera service层,个人认为是在这里对window这个参数进行了配置,连接api...还有其他的操作
这里先说说现在的想法,自己的理解, maybe wrong
这里跳度很大,看看下面的方法,来源:frameworks\base\libs\gui\SurfaceTextureClient.cpp
说的是 SurfaceTextureClient类的构造方法
我们以dequeueBuffer为例进行讲解,那就先看看 hook_dequeueBuffer的实现
private SurfaceTexture mSurfaceTexture;
接下来看看他是在哪里实例化的
这里调用了类 SurfaceTexture的方法 dequeueBuffer
很纠结啊,看的
当已存在申请的buffer,返回buffer序号
在初始化SurfaceTexture对象时,上面的构造函数中实例化 mGraphicBufferAlloc = composer - > createGraphicBufferAlloc ( ) ;
createGraphicBufferAlloc的实现在以下路径:frameworks\base\libs\gui\ISurfaceComposer.cpp
这篇文章写得很吃力,不是理解的很透彻,其中可能很多思路根本就是错误的,待修正啊。。
待续。。。。
这篇文章接着上一篇文章继续: 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();
- inti;
- ///@todoDocropping basedonthe stabilized frame coordinates
- ///@todo Insert logictodrop frames here basedonrefresh rate of
- ///displayorrendering rate whicheverislower
- ///Queue the buffertooverlay
- 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);
- //Setcrop onlyifcurrent xandy offsetsdonotmatch 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 basedonthe pixel format
- if(strcmp(mPixelFormat,(constchar*)CameraParameters::PIXEL_FORMAT_YUV422I)==0)
- {
- bytesPerPixel=2;
- }
- elseif(strcmp(mPixelFormat,(constchar*)CameraParameters::PIXEL_FORMAT_RGB565)==0)
- {
- bytesPerPixel=2;
- }
- elseif(strcmp(mPixelFormat,(constchar*)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,ifthe surfaceis
- //already invalid,we'll know soon enough.
- mANativeWindow->set_crop(mANativeWindow,xOff/bytesPerPixel,yOff,
- (xOff/bytesPerPixel)+mPreviewWidth,yOff+mPreviewHeight);
- ///Update the current xandy offsets
- mXOff=xOff;
- mYOff=yOff;
- }
- //这里说说自己对以上代码的理解,上面通过传入的displayFrame类型变量check,传入的配置是否与系统此时实际显示属性一致,不一致,则从新进行裁剪,配置显示大小,位置等
- {
- buffer_handle_t*handle=(buffer_handle_t*)mBuffers[i].opaque;
- //unlock buffer before sendingtodisplay
- 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 hasnotminimum buffer requirement.We should be abletodequeue
- //the buffer immediately
- TIUTILS::Message msg;
- mDisplayQ.put(&msg);
- #ifPPM_INSTRUMENTATION||PPM_INSTRUMENTATION_ABS
- if(mMeasureStandby)
- {
- CameraHal::PPM("Standby to first shot: Sensor Change completed - ",&mStandbyToShot);
- mMeasureStandby=false;
- }
- elseif(CameraFrame::CameraFrame::SNAPSHOT_FRAME==dispFrame.mType)
- {
- CameraHal::PPM("Shot to snapshot: ",&mStartCapture);
- mShotToShot=true;
- }
- elseif(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 bufferanddequeue 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这个变量类型的定义,找了好久才找到的,悲催: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 usedtoautomatically refcount ANativeWindow's.*/
- void incStrong(constvoid*id)const{
- common.incRef(const_cast<android_native_base_t*>(&common));
- }
- void decStrong(constvoid*id)const{
- common.decRef(const_cast<android_native_base_t*>(&common));
- }
- #endif
- struct android_native_base_t common;
- /*flags describing some attributes of this surfaceorits updater*/
- constuint32_t flags;
- /*min swap interval supported by this updated*/
- constintminSwapInterval;
- /*max swap interval supported by this updated*/
- constintmaxSwapInterval;
- /*horizontalandvertical resolutioninDPI*/
- constfloat xdpi;
- constfloat ydpi;
- /*Some storage reservedforthe OEM's driver.*/
- intptr_t oem[4];
- /*
- *Setthe swap intervalforthis surface.
- *
- *Returns 0onsuccessor-errnoonerror.
- */
- int(*setSwapInterval)(struct ANativeWindow*window,intinterval);
- /*
- *hook called by EGLtoacquire a buffer.After thiscall,the buffer
- *isnotlocked,so its content cannot be modified.
- *thiscallmay blockifno buffers are available.
- *
- *Returns 0onsuccessor-errnoonerror.
- */
- int(*dequeueBuffer)(struct ANativeWindow*window,struct ANativeWindowBuffer**buffer);
- /*
- *hook called by EGLtolock a buffer.This MUST be called before modifying
- *the content of a buffer.The buffer must have been acquired with
- *dequeueBuffer first.
- *
- *Returns 0onsuccessor-errnoonerror.
- */
- int(*lockBuffer)(struct ANativeWindow*window,struct ANativeWindowBuffer*buffer);
- /*
- *hook called by EGL when modificationstothe render buffer are done.
- *This unlocksandpost the buffer.
- *
- *Buffers MUST be queuedinthe same order than they were dequeued.
- *
- *Returns 0onsuccessor-errnoonerror.
- */
- int(*queueBuffer)(struct ANativeWindow*window,struct ANativeWindowBuffer*buffer);
- /*
- *hook usedtoretrieve information about the nativewindow.
- *
- *Returns 0onsuccessor-errnoonerror.
- */
- int(*query)(conststruct ANativeWindow*window,intwhat,int*value);
- /*
- *hook usedtoperform various operationsonthe surface.
- *(*perform)()isa generic mechanismtoadd functionalityto
- *ANativeWindowwhilekeeping backward binary compatibility.
- *
- *DONOTCALLTHIS HOOK DIRECTLY.Instead,use the helper functions
- *defined below.
- *
- *(*perform)()returns-ENOENTifthe'what'parameterisnotsupported
- *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,intoperation,...);
- /*
- *hook usedtocancel a buffer that has been dequeued.
- *No synchronizationisperformed between dequeue()andcancel(),so
- *either external synchronizationisneeded,orthese functions must be
- *called from the same thread.
- */
- int(*cancelBuffer)(struct ANativeWindow*window,struct ANativeWindowBuffer*buffer);
- void*reserved_proc[2];
- };
我们首先看看 mANativewindow到底前身是什么,我们调用的这个方法到底是在哪里实现的,首先我们看一下他是从哪里引入进来的??
- intANativeWindowDisplayAdapter::setPreviewWindow(preview_stream_ops_t*window)
- {
- LOG_FUNCTION_NAME;
- ///Note that Display Adapter cannot work without a validwindowobject
- 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 existingwindowobject,ifit exists
- destroy();
- ///Movetonewwindowobj
- mANativeWindow=window;
- LOG_FUNCTION_NAME_EXIT;
- return NO_ERROR;
- }
- /**Setthe ANativeWindowtowhich preview frames are sent*/
- status_t setPreviewWindow(constsp<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;
- }
- status_t initialize(hw_module_t*module)
- {
- LOGI("Opening camera %s",mName.string());
- intrc=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;
- }
- 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;
- }
- staticint__cancel_buffer(struct preview_stream_ops*w,
- buffer_handle_t*buffer)
- {
- ANativeWindow*a=anw(w);
- returna->cancelBuffer(a,container_of(buffer,ANativeWindowBuffer,handle));
- }
这里通过anm这个方法转换而来的ANativeWindow类型的变量a其实就是我们在上面initialize方式中初始化的 mPreviewWindow
而这个 mPreviewWindow就是上层传下来的的surface
这里是camera service层,个人认为是在这里对window这个参数进行了配置,连接api...还有其他的操作
- status_t CameraService::Client::setPreviewWindow(constsp<IBinder>&binder,
- constsp<ANativeWindow>&window){
- Mutex::Autolock lock(mLock);
- status_t result=checkPidAndHardware();
- if(result!=NO_ERROR)return result;
- //returnifno changeinsurface.
- 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;
- }
- }
- //Ifpreview has been already started,register preview buffersnow.
- 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 oldwindowandremember the
- //newwindow.
- disconnectWindow(mPreviewWindow);
- mSurface=binder;
- mPreviewWindow=window;
- }else{
- //Something went wrong after we connectedtothe newwindow,so
- //disconnect here.
- disconnectWindow(window);
- }
- return result;
- }
这里先说说现在的想法,自己的理解, maybe wrong
这里跳度很大,看看下面的方法,来源:frameworks\base\libs\gui\SurfaceTextureClient.cpp
说的是 SurfaceTextureClient类的构造方法
- SurfaceTextureClient::SurfaceTextureClient(
- constsp<ISurfaceTexture>&surfaceTexture)
- {
- SurfaceTextureClient::init();
- SurfaceTextureClient::setISurfaceTexture(surfaceTexture);
- }
- void SurfaceTextureClient::init(){
- //Initialize the ANativeWindowfunctionpointers.
- 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;
- }
我们以dequeueBuffer为例进行讲解,那就先看看 hook_dequeueBuffer的实现
- intSurfaceTextureClient::hook_dequeueBuffer(ANativeWindow*window,
- ANativeWindowBuffer**buffer){
- SurfaceTextureClient*c=getSelf(window);
- return c->dequeueBuffer(buffer);
- }
- intSurfaceTextureClient::dequeueBuffer(android_native_buffer_t**buffer){
- LOGV("SurfaceTextureClient::dequeueBuffer");
- Mutex::Autolock lock(mMutex);
- intbuf=-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;
- }
private SurfaceTexture mSurfaceTexture;
接下来看看他是在哪里实例化的
- @Override
- publicvoid open(FilterContext context){
- if(mLogVerbose)Log.v(TAG,"Opening");
- //Open camera
- mCamera=Camera.open(mCameraId);
- //Setparameters
- getCameraParameters();
- mCamera.setParameters(mCameraParameters);
- //Create frame formats
- createFormats();
- //Bind ittoour 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 SurfaceTexturetocallback
- mSurfaceTexture.setOnFrameAvailableListener(onCameraFrameAvailableListener);
- //Start the preview
- mNewFrameAvailable=false;
- mCamera.startPreview();
- }
- 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 PIDanda 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));
- }
这里调用了类 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);
- intfound,foundSync;
- intdequeuedCount=0;
- bool tryAgain=true;
- while(tryAgain){
- if(mAbandoned){
- ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- //We needtowaitforthe FIFOtodrainifthe number of buffer
- //needstochange.
- //
- //The condition"number of buffers needs to change"istrueif
- //-the client doesn't care about how many buffers there are
- //-ANDthe actual number of bufferisdifferent from what was
- //setinthe last setBufferCountServer()
- //-OR-
- //setBufferCountServer()wassettoa value incompatible with
- //the synchronization mode(forinstance because the sync mode
- //changed since)
- //
- //As long as this conditionistrueANDthe FIFOisnotempty,we
- //waitonmDequeueCondition.
- constintminBufferCountNeeded=mSynchronousMode?
- MIN_SYNC_BUFFER_SLOTS:MIN_ASYNC_BUFFER_SLOTS;
- constbool numberOfBuffersNeedsToChange=!mClientBufferCount&&
- ((mServerBufferCount!=mBufferCount)||
- (mServerBufferCount<minBufferCountNeeded));
- if(!mQueue.isEmpty()&&numberOfBuffersNeedsToChange){
- //waitforthe FIFOtodrain
- mDequeueCondition.wait(mMutex);
- //NOTE:we continue here because we needtoreevaluate our
- //whole state(eg:we could be abandonedordisconnected)
- continue;
- }
- if(numberOfBuffersNeedsToChange){
- //here we're guaranteed that mQueueisempty
- freeAllBuffersLocked();
- mBufferCount=mServerBufferCount;
- if(mBufferCount<minBufferCountNeeded)
- mBufferCount=minBufferCountNeeded;
- mCurrentTexture=INVALID_BUFFER_SLOT;
- returnFlags|=ISurfaceTexture::RELEASE_ALL_BUFFERS;
- }
- //lookfora free buffertogivetothe client
- found=INVALID_BUFFER_SLOT;
- foundSync=INVALID_BUFFER_SLOT;
- dequeuedCount=0;
- for(inti=0;i<mBufferCount;i++){
- constintstate=mSlots[i].mBufferState;
- if(state==BufferSlot::DEQUEUED){
- dequeuedCount++;
- }
- //ifbufferisFREE 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 arenotallowedtodequeue more than one buffer
- //ifthey didn'tseta buffer count.
- if(!mClientBufferCount&&dequeuedCount){
- return-EINVAL;
- }
- //See whether a buffer has been queued since the last setBufferCount so
- //we know whethertoperform the MIN_UNDEQUEUED_BUFFERS check below.
- bool bufferHasBeenQueued=mCurrentTexture!=INVALID_BUFFER_SLOT;
- if(bufferHasBeenQueued){
- //make sure the clientisnottryingtodequeue more buffers
- //than allowed.
- constintavail=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'reinsynchronous modeanddidn't find a buffer,we needtowait
- //forsome bufferstobe consumed
- tryAgain=mSynchronousMode&&(foundSync==INVALID_BUFFER_SLOT);
- if(tryAgain){
- mDequeueCondition.wait(mMutex);
- }
- }
- if(mSynchronousMode&&found==INVALID_BUFFER_SLOT){
- //foundSync guaranteedtobe!=INVALID_BUFFER_SLOT
- found=foundSync;
- }
- if(found==INVALID_BUFFER_SLOT){
- return-EBUSY;
- }
- constintbuf=found;
- *outBuf=found;
- constbool useDefaultSize=!w&&!h;
- if(useDefaultSize){
- //use the default size
- w=mDefaultWidth;
- h=mDefaultHeight;
- }
- constbool updateFormat=(format!=0);
- if(!updateFormat){
- //keep the current(ordefault)format
- format=mPixelFormat;
- }
- //bufferisnowinDEQUEUED(but can also be current at the sametime,
- //ifwe'reinsynchronous mode)
- mSlots[buf].mBufferState=BufferSlot::DEQUEUED;
- constsp<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_terror;
- sp<GraphicBuffer>graphicBuffer(
- mGraphicBufferAlloc->createGraphicBuffer(
- w,h,format,usage,&error));
- if(graphicBuffer==0){
- ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
- "failed");
- returnerror;
- }
- 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;
- }
很纠结啊,看的
当已存在申请的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());
- }
- 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 havetoread the BufferReference from
- //the parcel,it'll die with the parcel.
- }
- *error=result;
- return graphicBuffer;
- }
这篇文章写得很吃力,不是理解的很透彻,其中可能很多思路根本就是错误的,待修正啊。。
待续。。。。
更多相关文章
- SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
- android jni方法模拟高频按键点击
- Android调用webservice接口
- Android电池驱动
- Android开发中的单元测试-初级教程(01)
- Android(安卓)Camera从App层到framework层到HAL层的初始化过程
- Android(安卓)SurfaceFlinger 学习之路(五)----VSync 工作原理
- EP28-DownloadManager分析(1)
- Android视图加载流程(3)之ViewRootImpl的UI刷新机制