久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Android Camera HAL3中預(yù)覽preview模式下的數(shù)據(jù)流

 Elaine個人小館 2016-12-27

Android Camera HAL3中預(yù)覽preview模式下的數(shù)據(jù)流


前沿:

為了更好的梳理preview下buffer數(shù)據(jù)流的操作過程,,前一文中對surface下的buffer相關(guān)的操作架構(gòu)進行了描述,。本文主要以此為基礎(chǔ),,重點分析再Camera2Client和Camera3Device下是如何維護并讀寫這些視頻幀緩存的,。

1. Camera3Device::convertMetadataListToRequestListLocked函數(shù)

結(jié)合上一博文中關(guān)于preview的控制流,定位到數(shù)據(jù)流主要的操作主要是對preview模式下將CameraMetadata mPreviewRequest轉(zhuǎn)換為CaptureRequest的過程之中,,回顧到mPreviewRequest是主要包含了當前preview下所需要Camera3Device來操作的OutputStream的index值,。

2. Camera3Device::configureStreamsLocked函數(shù)

在configureStreamsLocked的函數(shù)中,主要關(guān)注的是Camera3Device對當前所具有的所有的mInputStreams和mOutputStreams進行Config的操作,,分別包括startConfiguration/finishConfiguration兩個狀態(tài),。

2.1 mOutputStreams.editValueAt(i)->startConfiguration()

這里的遍歷所有輸出stream即最終調(diào)用的函數(shù)入口為Camera3Stream::startConfiguration(),這里需要先看下Camera3OutputStream的整個結(jié)構(gòu),,出現(xiàn)了Camera3Stream和Camera3IOStreamBase,,兩者是Input和Output stream所共有的,,前者提供的更多的是對buffer的config、get/retrun buffer的操作,,后者以維護當前的stream所擁有的buffer數(shù)目,。另一個支路camera3_stream_t是一個和Camera HAL3底層進行stream信息交互的入口。

startConfiguration函數(shù)首先是判斷當前stream的狀態(tài),,對于已經(jīng)config的不作處理,,config的主要操作是getEndpointUsage:

status_t Camera3OutputStream::getEndpointUsage(uint32_t *usage) { status_t res; int32_t u = 0; res = mConsumer->query(mConsumer.get(), NATIVE_WINDOW_CONSUMER_USAGE_BITS, &u); *usage = u; return res;}
這里的mConsumer其實就是之前創(chuàng)建的Surface的本體,每一個Stream在建立時createStream,,都會傳入一個ANativeWIndow類似的Consumer綁定到當前的stream中去,。這里主要是完成當前window所管理的buffer的USAGE值,可參看grallo.h中的定義,,由Gralloc模塊負責指定當前buffer操作是由HW還是SW來完成以及不同的應(yīng)用場合,,在Gralloc模塊中不同模塊需求的buffer亦會有不同的分配、定義與處理方式:

/* buffer will be used as an OpenGL ES texture */ GRALLOC_USAGE_HW_TEXTURE = 0x00000100, /* buffer will be used as an OpenGL ES render target */ GRALLOC_USAGE_HW_RENDER = 0x00000200, /* buffer will be used by the 2D hardware blitter */ GRALLOC_USAGE_HW_2D = 0x00000400, /* buffer will be used by the HWComposer HAL module */ GRALLOC_USAGE_HW_COMPOSER = 0x00000800, /* buffer will be used with the framebuffer device */ GRALLOC_USAGE_HW_FB = 0x00001000, /* buffer will be used with the HW video encoder */ GRALLOC_USAGE_HW_VIDEO_ENCODER = 0x00010000, /* buffer will be written by the HW camera pipeline */ GRALLOC_USAGE_HW_CAMERA_WRITE = 0x00020000, /* buffer will be read by the HW camera pipeline */ GRALLOC_USAGE_HW_CAMERA_READ = 0x00040000, /* buffer will be used as part of zero-shutter-lag queue */ GRALLOC_USAGE_HW_CAMERA_ZSL = 0x00060000, /* mask for the camera access values */ GRALLOC_USAGE_HW_CAMERA_MASK = 0x00060000, /* mask for the software usage bit-mask */ GRALLOC_USAGE_HW_MASK = 0x00071F00,

2.2 mHal3Device->ops->configure_streams(mHal3Device, &config);

config是一個camera3_stream_configuration數(shù)據(jù)結(jié)構(gòu),,他記錄了一次和HAL3交互的stream的數(shù)量,,已經(jīng)當前每一個stream的屬性配置相關(guān)的信息camer3_stream_t,包括stream中每一個buffer的屬性值,,stream的類型值等等,,提交這些信息供hal3去分析處理。在高通平臺中你可以看到,,對于每一個stream在HAL3平臺下均以一個Channel的形式存在,。

typedef struct camera3_stream_configuration { uint32_t num_streams; camera3_stream_t **streams;} camera3_stream_configuration_t;

stream_type包括:CAMERA3_STREAM_OUTPUT、CAMERA3_STREAM_INPUT,、CAMERA3_STREAM_BIDIRECTIONAL,。

format主要是指當前buffer支持的像素點存儲格式,以HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED居多,,表明數(shù)據(jù)格式是由Gralloc模塊來決定的,。

對于HAL3中對configureStreams接口的實現(xiàn)會放在后續(xù)介紹高通平臺的實現(xiàn)機制時再做分析。

2.3 Camera3Stream::finishConfiguration

該函數(shù)主要執(zhí)行configureQueueLocked和registerBuffersLocked兩個函數(shù)

status_t Camera3OutputStream::configureQueueLocked() { status_t res; mTraceFirstBuffer = true; if ((res = Camera3IOStreamBase::configureQueueLocked()) != OK) { return res; } ALOG_ASSERT(mConsumer != 0, mConsumer should never be NULL); // Configure consumer-side ANativeWindow interface res = native_window_api_connect(mConsumer.get(), NATIVE_WINDOW_API_CAMERA); if (res != OK) { ALOGE(%s: Unable to connect to native window for stream %d, __FUNCTION__, mId); return res; } res = native_window_set_usage(mConsumer.get(), camera3_stream::usage); if (res != OK) { ALOGE(%s: Unable to configure usage %08x for stream %d, __FUNCTION__, camera3_stream::usage, mId); return res; } res = native_window_set_scaling_mode(mConsumer.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); if (res != OK) { ALOGE(%s: Unable to configure stream scaling: %s (%d), __FUNCTION__, strerror(-res), res); return res; } if (mMaxSize == 0) { // For buffers of known size res = native_window_set_buffers_dimensions(mConsumer.get(), camera3_stream::width, camera3_stream::height); } else { // For buffers with bounded size res = native_window_set_buffers_dimensions(mConsumer.get(), mMaxSize, 1); } if (res != OK) { ALOGE(%s: Unable to configure stream buffer dimensions %d x %d (maxSize %zu) for stream %d, __FUNCTION__, camera3_stream::width, camera3_stream::height, mMaxSize, mId); return res; } res = native_window_set_buffers_format(mConsumer.get(), camera3_stream::format); if (res != OK) { ALOGE(%s: Unable to configure stream buffer format %#x for stream %d, __FUNCTION__, camera3_stream::format, mId); return res; } int maxConsumerBuffers; res = mConsumer->query(mConsumer.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);//支持的最大buffer數(shù)量 if (res != OK) { ALOGE(%s: Unable to query consumer undequeued buffer count for stream %d, __FUNCTION__, mId); return res; } ALOGV(%s: Consumer wants %d buffers, HAL wants %d, __FUNCTION__, maxConsumerBuffers, camera3_stream::max_buffers); if (camera3_stream::max_buffers == 0) { ALOGE(%s: Camera HAL requested max_buffer count: %d, requires at least 1, __FUNCTION__, camera3_stream::max_buffers); return INVALID_OPERATION; } mTotalBufferCount = maxConsumerBuffers + camera3_stream::max_buffers;//至少2個buffer mHandoutTotalBufferCount = 0; mFrameCount = 0; mLastTimestamp = 0; res = native_window_set_buffer_count(mConsumer.get(), mTotalBufferCount); if (res != OK) { ALOGE(%s: Unable to set buffer count for stream %d, __FUNCTION__, mId); return res; } res = native_window_set_buffers_transform(mConsumer.get(), mTransform); if (res != OK) { ALOGE(%s: Unable to configure stream transform to %x: %s (%d), __FUNCTION__, mTransform, strerror(-res), res); } return OK;}
如果你對SurfaceFlinger的架構(gòu)熟悉的話,,該代碼會相對比較好理解,。本質(zhì)是根據(jù)當前stream設(shè)置的buffer屬性,將這些屬性值通過ANativeWindow這個接口傳遞給Consumer側(cè)去維護:

這里重點關(guān)注以下幾個buffer的相關(guān)屬性信息:

比如native_window_set_buffer_count是設(shè)置當前Window所需要的buffer數(shù)目:

總的當前stream下的buffer個數(shù)總數(shù)為mTotalBufferCount = maxConsumerBuffers + camera3_stream::max_buffers,。其中camera3_stream::max_buffer需要的buffer總數(shù)由configureStreams時HAL3底層的Device來決定的,,高通平臺下定義的camera3_stream::max_buffer數(shù)為7個,而maxConsumerBuffers指的是在所有buffer被dequeue時還應(yīng)該保留的處于queue操作的buffer個數(shù),,即全dequeue時至少有maxConsumerBuffers個buffer是處于queue狀態(tài)在被Consumer使用的,。通過query NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS來完成,一般默認是1個,,即每個stream可以認為需要由8個buffer緩存塊組成,,實際可dequeue的為8個,。

比如native_window_set_buffers_transform一般是指定buffer的Consumer,即當前buffer顯示的90/180/270°角度,。

該過程本質(zhì)是結(jié)合HAL3的底層buffer配置需求,,反過來請求Buffer的Consumer端BufferQueueConsumer來設(shè)置相關(guān)的buffer屬性。

registerBuffersLocked是一個比較重要的處理過程:

status_t Camera3Stream::registerBuffersLocked(camera3_device *hal3Device) { ATRACE_CALL(); /** * >= CAMERA_DEVICE_API_VERSION_3_2: * * camera3_device_t->ops->register_stream_buffers() is not called and must * be NULL. */ if (hal3Device->common.version >= CAMERA_DEVICE_API_VERSION_3_2) { ALOGV(%s: register_stream_buffers unused as of HAL3.2, __FUNCTION__); if (hal3Device->ops->register_stream_buffers != NULL) { ALOGE(%s: register_stream_buffers is deprecated in HAL3.2; must be set to NULL in camera3_device::ops, __FUNCTION__); return INVALID_OPERATION; } else { ALOGD(%s: Skipping NULL check for deprecated register_stream_buffers, __FUNCTION__); } return OK; } else { ALOGV(%s: register_stream_buffers using deprecated code path, __FUNCTION__); } status_t res; size_t bufferCount = getBufferCountLocked();//獲取buffer的數(shù)量,mTotalBufferCount,,最少2個buffer Vector buffers; buffers.insertAt(/*prototype_item*/NULL, /*index*/0, bufferCount); camera3_stream_buffer_set bufferSet = camera3_stream_buffer_set(); bufferSet.stream = this;//新的bufferset指向camera3_stream_t bufferSet.num_buffers = bufferCount;//當前stream下的buffer數(shù) bufferSet.buffers = buffers.editArray(); Vector streamBuffers; streamBuffers.insertAt(camera3_stream_buffer_t(), /*index*/0, bufferCount); // Register all buffers with the HAL. This means getting all the buffers // from the stream, providing them to the HAL with the // register_stream_buffers() method, and then returning them back to the // stream in the error state, since they won't have valid data. // // Only registered buffers can be sent to the HAL. uint32_t bufferIdx = 0; for (; bufferIdx < buffercount;="" bufferidx++)="" {="" res="getBufferLocked(" &streambuffers.edititemat(bufferidx)="" );//返回dequeue="" buffer出來的所有buffer="" if="" (res="" !="OK)" {="" aloge(%s:="" unable="" to="" get="" buffer="" %d="" for="" registration="" with="" hal,="" __function__,="" bufferidx);="" skip="" registering,="" go="" straight="" to="" cleanup="" break;="" }="" sp="" fence="new" fence(streambuffers[bufferidx].acquire_fence);="" fence-="">waitForever(Camera3Stream::registerBuffers);//等待可寫 buffers.editItemAt(bufferIdx) = streamBuffers[bufferIdx].buffer;//dequeue buffer出來的buffer handle } if (bufferIdx == bufferCount) { // Got all buffers, register with HAL ALOGV(%s: Registering %zu buffers with camera HAL, __FUNCTION__, bufferCount); ATRACE_BEGIN(camera3->register_stream_buffers); res = hal3Device->ops->register_stream_buffers(hal3Device, &bufferSet);//buffer綁定并register到hal層 ATRACE_END(); } // Return all valid buffers to stream, in ERROR state to indicate // they weren't filled. for (size_t i = 0; i < bufferidx;="" i++)="" {="" streambuffers.edititemat(i).release_fence="-1;" streambuffers.edititemat(i).status="CAMERA3_BUFFER_STATUS_ERROR;" returnbufferlocked(streambuffers[i],="" 0);//register后進行queue="" buffer="" }="" return="">

a 可以明確看到CAMERA_DEVICE_API_VERSION_3_2的版本才支持這個Device ops接口

b getBufferCountLocked

獲取當前stream下的允許的buffer總數(shù)

c camera3_stream_buffer_t、camera3_stream_buffer_set和buffer_handle_t

首先需要關(guān)注的結(jié)構(gòu)是camera3_stream_buffer_t,,用于描述每一個stream下的buffer自身的特性值,,其中關(guān)鍵結(jié)構(gòu)是buffer_handle_t值是每一個buffer在不同進程間共享的handle,此外acquire_fence和release_fence用來不同硬件模塊對buffer讀寫時的同步,。

camera3_stream_buffer_set是封裝了當前stream下所有的buffer的信息:

typedef struct camera3_stream_buffer_set { /** * The stream handle for the stream these buffers belong to */ camera3_stream_t *stream; /** * The number of buffers in this stream. It is guaranteed to be at least * stream->max_buffers. */ uint32_t num_buffers; /** * The array of gralloc buffer handles for this stream. If the stream format * is set to HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, the camera HAL device * should inspect the passed-in buffers to determine any platform-private * pixel format information. */ buffer_handle_t **buffers;} camera3_stream_buffer_set_t;
三個變量分別保存stream的buffer個數(shù),,當前這個set集合所屬的stream,以及他所包含的所有buffer的handle信息列表,。

d getBufferLocked獲取當前buffer

status_t Camera3OutputStream::getBufferLocked(camera3_stream_buffer *buffer) { ATRACE_CALL(); status_t res; if ((res = getBufferPreconditionCheckLocked()) != OK) { return res; } ANativeWindowBuffer* anb; int fenceFd; /** * Release the lock briefly to avoid deadlock for below scenario: * Thread 1: StreamingProcessor::startStream -> Camera3Stream::isConfiguring(). * This thread acquired StreamingProcessor lock and try to lock Camera3Stream lock. * Thread 2: Camera3Stream::returnBuffer->StreamingProcessor::onFrameAvailable(). * This thread acquired Camera3Stream lock and bufferQueue lock, and try to lock * StreamingProcessor lock. * Thread 3: Camera3Stream::getBuffer(). This thread acquired Camera3Stream lock * and try to lock bufferQueue lock. * Then there is circular locking dependency. */ sp currentConsumer = mConsumer; mLock.unlock(); res = currentConsumer->dequeueBuffer(currentConsumer.get(), &anb, &fenceFd); mLock.lock(); if (res != OK) { ALOGE(%s: Stream %d: Can't dequeue next output buffer: %s (%d), __FUNCTION__, mId, strerror(-res), res); return res; } /** * FenceFD now owned by HAL except in case of error, * in which case we reassign it to acquire_fence */ handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd, /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/true); return OK;}
該函數(shù)主要是從由ANativeWindow從Consumer端dequeue獲取一個buffer,,本質(zhì)上這個過程中首次執(zhí)行是會有Consumer端去分配一個由實際物理空間的給當前的一個buffer的。

接著執(zhí)行handoutBufferLocked,,填充camera3_stream_buffer這個結(jié)構(gòu)體,,其中設(shè)置的acquireFence為-1值表明hal3的這個buffer可被Framewrok直接使用,而acquireFence表示HAL3如何想使用這個buffer時需要等待其變?yōu)?,,因為buffer分配和handler返回不一定是一致同步的,。還會切換當前buffer的狀態(tài)CAMERA3_BUFFER_STATUS_OK。

void Camera3IOStreamBase::handoutBufferLocked(camera3_stream_buffer &buffer, buffer_handle_t *handle, int acquireFence, int releaseFence, camera3_buffer_status_t status, bool output) { /** * Note that all fences are now owned by HAL. */ // Handing out a raw pointer to this object. Increment internal refcount. incStrong(this); buffer.stream = this; buffer.buffer = handle; buffer.acquire_fence = acquireFence; buffer.release_fence = releaseFence; buffer.status = status; // Inform tracker about becoming busy if (mHandoutTotalBufferCount == 0 && mState != STATE_IN_CONFIG && mState != STATE_IN_RECONFIG) { /** * Avoid a spurious IDLE->ACTIVE->IDLE transition when using buffers * before/after register_stream_buffers during initial configuration * or re-configuration. * * TODO: IN_CONFIG and IN_RECONFIG checks only make sense for statusTracker = mStatusTracker.promote(); if (statusTracker != 0) { statusTracker->markComponentActive(mStatusId); } } mHandoutTotalBufferCount++;//統(tǒng)計dequeuebuffer的數(shù)量 if (output) { mHandoutOutputBufferCount++; }}

e hal3Device->ops->register_stream_buffers(hal3Device,&bufferSet);//buffer綁定并register到hal層

將所屬的stream下的所有buffer有關(guān)的信息,,主要是每個buffer的buffer_handle_t值,,交給HAL3層去實現(xiàn)。比如高通HAL3平臺每一個Channel對應(yīng)于Camera3Device端的stream,,而每一個stream的buffer在不同的Channel下面卻是一個個的stream,,這是高通的實現(xiàn)方式。

f 在完成register所有buffer后,,設(shè)置每一個buffer狀態(tài)為從CAMERA3_BUFFER_STATUS_OK切換到CAMERA3_BUFFER_STATUS_ERROR表明這個buffer都是可用的,,目的在于執(zhí)行returnBufferLocked是為了將這些因為register而出列的所有buffer再次cancelbuffer操作。

Camera3OutputStream::returnBufferLocked->Camera3IOStreamBase::returnAnyBufferLocked->Camera3OutputStream::returnBufferCheckedLocked

status_t Camera3OutputStream::returnBufferCheckedLocked(//result返回時調(diào)用 const camera3_stream_buffer &buffer, nsecs_t timestamp, bool output, /*out*/ sp *releaseFenceOut) { (void)output; ALOG_ASSERT(output, Expected output to be true); status_t res; sp releaseFence; /** * Fence management - calculate Release Fence */ if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) { if (buffer.release_fence != -1) { ALOGE(%s: Stream %d: HAL should not set release_fence(%d) when there is an error, __FUNCTION__, mId, buffer.release_fence); close(buffer.release_fence); } /** * Reassign release fence as the acquire fence in case of error */ releaseFence = new Fence(buffer.acquire_fence); } else { res = native_window_set_buffers_timestamp(mConsumer.get(), timestamp); if (res != OK) { ALOGE(%s: Stream %d: Error setting timestamp: %s (%d), __FUNCTION__, mId, strerror(-res), res); return res; } releaseFence = new Fence(buffer.release_fence); } int anwReleaseFence = releaseFence->dup(); /** * Release the lock briefly to avoid deadlock with * StreamingProcessor::startStream -> Camera3Stream::isConfiguring (this * thread will go into StreamingProcessor::onFrameAvailable) during * queueBuffer */ sp currentConsumer = mConsumer; mLock.unlock(); /** * Return buffer back to ANativeWindow */ if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) { // Cancel buffer res = currentConsumer->cancelBuffer(currentConsumer.get(), container_of(buffer.buffer, ANativeWindowBuffer, handle), anwReleaseFence);//Register buffer locked所在的事情,,cancelbuffer dequeue的buffer if (res != OK) { ALOGE(%s: Stream %d: Error cancelling buffer to native window: %s (%d), __FUNCTION__, mId, strerror(-res), res); } } else { if (mTraceFirstBuffer && (stream_type == CAMERA3_STREAM_OUTPUT)) { { char traceLog[48]; snprintf(traceLog, sizeof(traceLog), Stream %d: first full buffer, mId); ATRACE_NAME(traceLog); } mTraceFirstBuffer = false; } res = currentConsumer->queueBuffer(currentConsumer.get(), container_of(buffer.buffer, ANativeWindowBuffer, handle), anwReleaseFence);//queuebuffer,,送顯ANativeWindowBuffer if (res != OK) { ALOGE(%s: Stream %d: Error queueing buffer to native window: %s (%d), __FUNCTION__, mId, strerror(-res), res); } } mLock.lock(); if (res != OK) { close(anwReleaseFence); } *releaseFenceOut = releaseFence; return res;}

該函數(shù)對于首次register的處理來說,他處理的buffer均是CAMERA3_BUFFER_STATUS_ERROR,,調(diào)用了cancelBuffer將所有buffer的狀態(tài)都還原為free的狀態(tài),,依次說明目前的buffer均是可用的,之前均不涉及到對buffer的數(shù)據(jù)流的操作,。

3 buffer數(shù)據(jù)流的dequeue操作

上述步驟2主要是將每一個Stream下全部的buffer信息全部register到下層的HAL3中,,為后續(xù)對buffer的數(shù)據(jù)流讀寫操作奠定基礎(chǔ),。

那么preview模式下我們又是如何去獲得一幀完成的視頻流的呢?

觸發(fā)點就是preview模式下的Request,,前面提到過一個mPreviewRequest至少包含一個StreamProcessor和一個CallbackProcessor的兩路stream,,每路stream擁有不同的buffer數(shù)量。比如要從HAL3獲取一幀圖像數(shù)據(jù),,最簡單的思路就是從StreamProcessor下的Outputstream流中下發(fā)一個可用的buffer地址,,然后HAL3填充下數(shù)據(jù),F(xiàn)ramework就可以擁有一幀數(shù)據(jù)了,。

根據(jù)這個思路,,回顧到前一博文中每次會不斷的下發(fā)一個Request命令包到HAL3中,在這里我們就可以看到這個buffer地址身影,。

Camera3Device::RequestThread::threadLoop() 下的部分代碼:

outputBuffers.insertAt(camera3_stream_buffer_t(), 0, nextRequest->mOutputStreams.size());//Streamprocess,Callbackprocessor request.output_buffers = outputBuffers.array();//camera3_stream_buffer_t for (size_t i = 0; i < nextrequest-="">mOutputStreams.size(); i++) { res = nextRequest->mOutputStreams.editItemAt(i)-> getBuffer(&outputBuffers.editItemAt(i));//等待獲取buffer,內(nèi)部是dequeue一根buffer填充到camera3_stream_buffer_t if (res != OK) { // Can't get output buffer from gralloc queue - this could be due to // abandoned queue or other consumer misbehavior, so not a fatal // error ALOGE(RequestThread: Can't get output buffer, skipping request: %s (%d), strerror(-res), res); Mutex::Autolock l(mRequestLock); if (mListener != NULL) { mListener->notifyError( ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST, nextRequest->mResultExtras); } cleanUpFailedRequest(request, nextRequest, outputBuffers); return true; } request.num_output_buffers++;//一般一根OutStream對應(yīng)一個buffer,故總的out_buffer數(shù)目 }
在這個下發(fā)到HAL3的camera3_capture_request中,,可以看到 const camera3_stream_buffer_t *output_buffers,下面的代碼可以說明這一次的Request的output_buffers是打包了當前Camera3Device所擁有的mOutputStreams,。

outputBuffers.insertAt(camera3_stream_buffer_t(), 0, nextRequest->mOutputStreams.size());//Streamprocess,Callbackprocessor
對于每一個OutputStream他會給她分配一個buffer handle,。關(guān)注下面的處理代碼:

nextRequest->mOutputStreams.editItemAt(i)-> getBuffer(&outputBuffers.editItemAt(i))
nextRequest->mOutputStreams.editItemAt(i)是獲取一個Camera3OutputStream對象,然后對getBuffer而言傳入的是這個Camera3OutputStream所對應(yīng)的這次buffer的輸入位置,,這個camera3_stream_buffer是需要從Camera3OutputStream對象中去獲取的,。

status_t Camera3Stream::getBuffer(camera3_stream_buffer *buffer) { ATRACE_CALL(); Mutex::Autolock l(mLock); status_t res = OK; // This function should be only called when the stream is configured already. if (mState != STATE_CONFIGURED) { ALOGE(%s: Stream %d: Can't get buffers if stream is not in CONFIGURED state %d, __FUNCTION__, mId, mState); return INVALID_OPERATION; } // Wait for new buffer returned back if we are running into the limit. if (getHandoutOutputBufferCountLocked() == camera3_stream::max_buffers) {//dequeue過多時等待queue的釋放 ALOGV(%s: Already dequeued max output buffers (%d), wait for next returned one., __FUNCTION__, camera3_stream::max_buffers); res = mOutputBufferReturnedSignal.waitRelative(mLock, kWaitForBufferDuration); if (res != OK) { if (res == TIMED_OUT) { ALOGE(%s: wait for output buffer return timed out after %lldms, __FUNCTION__, kWaitForBufferDuration / 1000000LL); } return res; } } res = getBufferLocked(buffer); if (res == OK) { fireBufferListenersLocked(*buffer, /*acquired*/true, /*output*/true); } return res;}
上述的代碼先是檢查dequeue了的buffer是否已經(jīng)達到本stream申請的buffer數(shù)目的最大值,如果已經(jīng)全部dequeue的話就得wait到當前已經(jīng)有buffer return并且queue操作后,,在處理完成后才允許將從buffer隊列中再次執(zhí)行dequeue操作,。

隨后調(diào)用getBufferLocked通過2.2(d)小節(jié)可以知道是從buffer隊列中獲取一個可用的buffer,并填充這個camera3_stream_buffer值,。

這樣處理完的結(jié)果是,,下發(fā)的Request包含所有模塊下的outputstream,同時每個stream都配備了一個camera3_stream_buffer供底層HAL3.0去處理,,而這個buffer在Camera3Device模式下,,可以是交互的是幀圖像數(shù)據(jù),可以是參數(shù)控制命令,,也可以是其他的3A信息,,這些不同的信息一般歸不同的模塊管理,也就是不同的stream來處理,。

4 buffer數(shù)據(jù)流的queue操作

dequeue出來的buffer信息已經(jīng)隨著Request下發(fā)到了HAL3層,,在Camera3Device架構(gòu)下,可以使用一個Callback接口將數(shù)據(jù)從HAL3回傳到Camera所在的Framework層,。Camera3Device私有繼承了一個Callback接口camera3_callback_ops數(shù)據(jù)結(jié)構(gòu),,分別預(yù)留了notify和process_capture_result。前者是用于回調(diào)一些shutter已經(jīng)error等信息,后者以Callback數(shù)據(jù)流為主,,這個回調(diào)接口通過device->initialize(camera3_device, this)來完成注冊,。

void Camera3Device::sProcessCaptureResult(const camera3_callback_ops *cb, const camera3_capture_result *result) { Camera3Device *d = const_cast(static_cast(cb)); d->processCaptureResult(result);}
返回的buffer所有信息均包含在camera3_capture_result中,該函數(shù)的處理過程相對比較復(fù)雜,,如果只定位queue buffer的入口可直接到returnOutputBuffers中去:

void Camera3Device::returnOutputBuffers( const camera3_stream_buffer_t *outputBuffers, size_t numBuffers, nsecs_t timestamp) { for (size_t i = 0; i < numbuffers;="" i++)//對每一個buffer所屬的stream進行分析="" {="" camera3stream="" *stream="Camera3Stream::cast(outputBuffers[i].stream);//該buffer對應(yīng)的camera3_stream" status_t="" res="stream-">returnBuffer(outputBuffers[i], timestamp);//Camera3OutPutStream,,每一各stream對應(yīng)的return // Note: stream may be deallocated at this point, if this buffer was // the last reference to it. if (res != OK) { ALOGE(Can't return buffer to its stream: %s (%d), strerror(-res), res); } }}
因為在下發(fā)Request時,每一個buffer均包含所述的stream信息,,當buffer數(shù)據(jù)返回到Framework層時,,我們又可以轉(zhuǎn)到Camera3OutPutStream來處理這個return的buffer。

status_t Camera3Stream::returnBuffer(const camera3_stream_buffer &buffer, nsecs_t timestamp) { ATRACE_CALL(); Mutex::Autolock l(mLock); /** * TODO: Check that the state is valid first. * * = HAL3.2 CONFIGURED only * * Do this for getBuffer as well. */ status_t res = returnBufferLocked(buffer, timestamp);//以queue buffer為主 if (res == OK) { fireBufferListenersLocked(buffer, /*acquired*/false, /*output*/true); mOutputBufferReturnedSignal.signal(); } return res;}
在這里看看registerBuffersLocked,,參考前面對這個函數(shù)他是register完所有的buffer時被調(diào)用,,在這里其本質(zhì)處理的buffer狀態(tài)不在是CAMERA3_BUFFER_STATUS_ERROR,而是CAMERA3_BUFFER_STATUS_OK故執(zhí)行的是將會queuebuffer的操作,。

5 buffer數(shù)據(jù)真正的被Consumer處理

在queuebuffer的操作時,,參考前一博文Android5.1中surface和CpuConsumer下生產(chǎn)者和消費者間的處理框架簡述很容易知道真正的Consumer需要開始工作了,,對于preview模式下的當然是由SurfaceFlinger的那套機制去處理,。而在Camera2Client和Camera3Device下你還可以看到CPUConsumer的存在,比如:

void CallbackProcessor::onFrameAvailable(const BufferItem& /*item*/) { Mutex::Autolock l(mInputMutex); if (!mCallbackAvailable) { mCallbackAvailable = true; mCallbackAvailableSignal.signal();//數(shù)據(jù)callback線程處理 }}
在這里,,你就可以去處理那些處于queue狀態(tài)的buffer數(shù)據(jù),,比如這里的Callback將這幀數(shù)據(jù)上傳會APP。

bool CallbackProcessor::threadLoop() { status_t res; { Mutex::Autolock l(mInputMutex); while (!mCallbackAvailable) { res = mCallbackAvailableSignal.waitRelative(mInputMutex, kWaitDuration); if (res == TIMED_OUT) return true; } mCallbackAvailable = false; } do { sp client = mClient.promote(); if (client == 0) { res = discardNewCallback(); } else { res = processNewCallback(client);//callback 處理新的一幀 } } while (res == OK); return true;}
l.mRemoteCallback->dataCallback(CAMERA_MSG_PREVIEW_FRAME, callbackHeap->mBuffers[heapIdx], NULL);//處理成API的需求后,,回調(diào)Preview frame

6 總結(jié)

到這里,,整個preview預(yù)覽的視頻流基本介紹完畢了,主要框架雖然負責,,但仔細看看也就是buffer的queue與dequeue操作,,真正的HAL3的實現(xiàn)才是最為復(fù)雜的。后續(xù)還會簡單介紹下整個take picture的過程,,數(shù)據(jù)的回調(diào)處理在后續(xù)中還會繼續(xù)分析,。

下面貼一圖是整個Camera3架構(gòu)下基于Request和result的處理流序圖:



原文地址:http://www./cjjc/1060618.html

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多