SurfaceTexture的Buffer入隊流程


Figure 1queueBuffer流程

1. 在AWesomePlayer的Render中將解碼后的Buf通過ANativeWindow接口通知SurfaceTextureClient

struct AwesomeNativeWindowRenderer : public AwesomeRenderer {

virtual void render(MediaBuffer *buffer) {

int64_t timeUs;

CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));

native_window_set_buffers_timestamp(mNativeWindow.get(), timeUs * 1000);

status_t err = mNativeWindow->queueBuffer(

mNativeWindow.get(), buffer->graphicBuffer().get());

 

}

}

進入到SurfaceTextureClient的queueBuffer(),這里的工作主要有:

1) 更新timestamp,如果沒有,則用系統時間

2) 根據Buffer地址從slots中取出Buffer的序號

3) 將序號以及時間戳、以及其它信息通過Binder通信發送給SurfaceTexture。

int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {

LOGV("SurfaceTextureClient::queueBuffer");

Mutex::Autolock lock(mMutex);

int64_t timestamp;

if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {

timestamp = systemTime(SYSTEM_TIME_MONOTONIC);

LOGV("SurfaceTextureClient::queueBuffer making up timestamp: %.2f ms",

timestamp / 1000000.f);

} else {

timestamp = mTimestamp;

}

int i = getSlotFromBufferLocked(buffer);

status_t err = mSurfaceTexture->queueBuffer(i, timestamp,

&mDefaultWidth, &mDefaultHeight, &mTransformHint);

return err;

}

2. 在SurfaceFlinger進程中,本地端的SurfaceTexture接收到Binder消息,並進入queueBuffer函數。主要做以下工作:

1) 根據傳入的int buf從slots中找出相應的Buffer,並更新此buffer的相關信息。

2)發信號mDequeueCondition.signal(),用作通知等待者

3) 通知監聽者,onFrameAvailable有幀到達

status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp,

uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {

ST_LOGV("queueBuffer: slot=%d time=%lld", buf, timestamp);

 

sp<FrameAvailableListener> listener;

 

{ // scope for the lock

Mutex::Autolock lock(mMutex);

//一些參數檢查

 

if (mSynchronousMode) {

// In synchronous mode we queue all buffers in a FIFO.

mQueue.push_back(buf);

 

// Synchronous mode always signals that an additional frame should

// be consumed.

listener = mFrameAvailableListener;

} else {

// In asynchronous mode we only keep the most recent buffer.

if (mQueue.empty()) {

mQueue.push_back(buf);

 

// Asynchronous mode only signals that a frame should be

// consumed if no previous frame was pending. If a frame were

// pending then the consumer would have already been notified.

listener = mFrameAvailableListener;

} else {

Fifo::iterator front(mQueue.begin());

// buffer currently queued is freed

mSlots[*front].mBufferState = BufferSlot::FREE;

// and we record the new buffer index in the queued list

*front = buf;

}

}

 

mSlots[buf].mBufferState = BufferSlot::QUEUED;

mSlots[buf].mCrop = mNextCrop;

mSlots[buf].mTransform = mNextTransform;

mSlots[buf].mScalingMode = mNextScalingMode;

mSlots[buf].mTimestamp = timestamp;

mFrameCounter++;

mSlots[buf].mFrameNumber = mFrameCounter;

 

mDequeueCondition.signal();

 

*outWidth = mDefaultWidth;

*outHeight = mDefaultHeight;

*outTransform = 0;

} // scope for the lock

 

// call back without lock held

if (listener != 0) {

listener->onFrameAvailable();

}

return OK;

}

在Layer中,第一次引用時會創建SurfaceTexture,並實現FrameAvailableListener

void Layer::onFirstRef()

{

LayerBaseClient::onFirstRef();

 

struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener {

FrameQueuedListener(Layer* layer) : mLayer(layer) { }

private:

wp<Layer> mLayer;

virtual void onFrameAvailable() {

sp<Layer> that(mLayer.promote());

if (that != 0) {

that->onFrameQueued();

}

}

};

mSurfaceTexture = new SurfaceTextureLayer(mTextureName, this);

mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));

mSurfaceTexture->setSynchronousMode(true);

mSurfaceTexture->setBufferCountServer(2);

}

控制流進入Layer:onFrameQueued()函數,最后調用SurfaceFlinger的事件函數,通知其新事件。

void Layer::onFrameQueued() {

android_atomic_inc(&mQueuedFrames);

mFlinger->signalEvent();

}

3. 在SurfaceFlinger中獲得事件,進入主循環處理事件

bool SurfaceFlinger::threadLoop()

{

waitForEvent();

// post surfaces (if needed)

handlePageFlip();//設置剛入隊的Buffer為當前激活的Buffer

handleRepaint();//將當前激活的Buffer地址送給硬件疊加層,進行疊加

 

在lockPageFlip函數中遍歷每一層設置當前激活的Buffer

bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)

{

bool recomputeVisibleRegions = false;

size_t count = currentLayers.size();

sp<LayerBase> const* layers = currentLayers.array();

for (size_t i=0 ; i<count ; i++) {

const sp<LayerBase>& layer(layers[i]);

layer->lockPageFlip(recomputeVisibleRegions);

}

return recomputeVisibleRegions;

}

對每個Layer將當前Buffer設置為激活Buffer

void Layer::lockPageFlip(bool& recomputeVisibleRegions)

{

// update the active buffer

mActiveBuffer = mSurfaceTexture->getCurrentBuffer();

 

在handleRepaint()中調用setupHardwareComposer建立疊加層

setupHardwareComposer(mDirtyRegion);

void SurfaceFlinger::setupHardwareComposer(Region& dirtyInOut)

{

/*

* update the per-frame h/w composer data for each layer

* and build the transparent region of the FB

*/

for (size_t i=0 ; i<count ; i++) {

const sp<LayerBase>& layer(layers[i]);

layer->setPerFrameData(&cur[i]);

}

}

 

將當前激活的buffer設置到 handware composer中進行疊加

void Layer::setPerFrameData(hwc_layer_t* hwcl) {

const sp<GraphicBuffer>& buffer(mActiveBuffer);

if (buffer == NULL) {

// this can happen if the client never drew into this layer yet,

// or if we ran out of memory. In that case, don't let

// HWC handle it.

hwcl->flags |= HWC_SKIP_LAYER;

hwcl->handle = NULL;

} else {

hwcl->handle = buffer->handle;

}

}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM