android+preview固定,Android Camera Preview ANativeWindow的处理

从JNI的调用看,Java通过surfacetexture来显示preview。CameraService通过surfacetexture获取ANativeWindow,向OpenGL传递数据。

ANativeWindow的函数实现是在CameraHardwareInterface.h中,

structcamera_preview_window {structpreview_stream_ops nw;void *user;

};struct camera_preview_window mHalPreviewWindow;

preview_stream_ops 的定义在hardware/libhardware/include/hardware/camera.h中

69c5a8ac3fa60e0848d784a6dd461da6.png

typedef structpreview_stream_ops {int (*dequeue_buffer)(struct preview_stream_ops*w,

buffer_handle_t** buffer, int *stride);int (*enqueue_buffer)(struct preview_stream_ops*w,

buffer_handle_t*buffer);int (*cancel_buffer)(struct preview_stream_ops*w,

buffer_handle_t*buffer);int (*set_buffer_count)(struct preview_stream_ops* w, intcount);int (*set_buffers_geometry)(struct preview_stream_ops*pw,int w, int h, intformat);int (*set_crop)(struct preview_stream_ops *w,int left, int top, int right, intbottom);int (*set_usage)(struct preview_stream_ops* w, intusage);int (*set_swap_interval)(struct preview_stream_ops *w, intinterval);int (*get_min_undequeued_buffer_count)(const struct preview_stream_ops *w,int *count);int (*lock_buffer)(struct preview_stream_ops*w,

buffer_handle_t*buffer);//Timestamps are measured in nanoseconds, and must be comparable//and monotonically increasing between two frames in the same//preview stream. They do not need to be comparable between//consecutive or parallel preview streams, cameras, or app runs. int (*set_timestamp)(struct preview_stream_ops *w, int64_t timestamp);

} preview_stream_ops_t;

69c5a8ac3fa60e0848d784a6dd461da6.png

在CameraHardwareInterface.h中的初始化函数中,调用initHalPreviewWindow()

69c5a8ac3fa60e0848d784a6dd461da6.png

status_t initialize(hw_module_t *module)

{

ALOGI("Opening camera %s", mName.string());int rc = module->methods->open(module, mName.string(),

(hw_device_t**)&mDevice);if (rc !=OK) {

ALOGE("Could not open camera %s: %d", mName.string(), rc);returnrc;

}

initHalPreviewWindow();returnrc;

}

69c5a8ac3fa60e0848d784a6dd461da6.png

69c5a8ac3fa60e0848d784a6dd461da6.png

voidinitHalPreviewWindow()

{

mHalPreviewWindow.nw.cancel_buffer=__cancel_buffer;

mHalPreviewWindow.nw.lock_buffer=__lock_buffer;

mHalPreviewWindow.nw.dequeue_buffer=__dequeue_buffer;

mHalPreviewWindow.nw.enqueue_buffer=__enqueue_buffer;

mHalPreviewWindow.nw.set_buffer_count=__set_buffer_count;

mHalPreviewWindow.nw.set_buffers_geometry=__set_buffers_geometry;

mHalPreviewWindow.nw.set_crop=__set_crop;

mHalPreviewWindow.nw.set_timestamp=__set_timestamp;

mHalPreviewWindow.nw.set_usage=__set_usage;

mHalPreviewWindow.nw.set_swap_interval=__set_swap_interval;

mHalPreviewWindow.nw.get_min_undequeued_buffer_count=__get_min_undequeued_buffer_count;

}

69c5a8ac3fa60e0848d784a6dd461da6.png

OK,将__xxxx函数赋值给mHalPreviewWindow.nw中的函数指针。

在Preview之前需要将ANativeWindow传递到HAL,

69c5a8ac3fa60e0848d784a6dd461da6.png

/** Set the ANativeWindow to which preview frames are sent*/status_t setPreviewWindow(const sp&buf)

{

ALOGV("%s(%s) buf %p", __FUNCTION__, mName.string(), buf.get());if (mDevice->ops->set_preview_window) { mPreviewWindow=buf; mHalPreviewWindow.user= this;

ALOGV("%s &mHalPreviewWindow %p mHalPreviewWindow.user %p", __FUNCTION__,&mHalPreviewWindow, mHalPreviewWindow.user);return mDevice->ops->set_preview_window(mDevice,

buf.get() ? &mHalPreviewWindow.nw : 0);

}returnINVALID_OPERATION;

}

69c5a8ac3fa60e0848d784a6dd461da6.png

在HAL中就可以使用这些函数对ANativeWindow进行操作,例如其中的一个函数实现__dequeue_buffer

此函数是从ANativeWindow队列中获取一个闲置buffer,

@CameraHardwareInterface.h

69c5a8ac3fa60e0848d784a6dd461da6.png

#define anw(n) __to_anw(((struct camera_preview_window *)n)->user) static int __dequeue_buffer(struct preview_stream_ops*w,

buffer_handle_t** buffer, int *stride)

{intrc;

ANativeWindow*a =anw(w);

ANativeWindowBuffer*anb;

rc= a->dequeueBuffer(a, &anb);if (!rc) {*buffer = &anb->handle;*stride = anb->stride;

}returnrc;

}

69c5a8ac3fa60e0848d784a6dd461da6.png

在HAL中,我们可以看到对display部分的初始化,初始视频格式设置为HAL_PIXEL_FORMAT_YCrCb_420_SP

69c5a8ac3fa60e0848d784a6dd461da6.png

ANativeWindowDisplayAdapter::ANativeWindowDisplayAdapter():mDisplayThread(NULL),

mDisplayState(ANativeWindowDisplayAdapter::DISPLAY_INIT),

mDisplayEnabled(false),

mBufferCount(0)

{

LOG_FUNCTION_NAME;

...

mPixelFormat=NULL; mNativeWindowPixelFormat=HAL_PIXEL_FORMAT_YCrCb_420_SP; }

69c5a8ac3fa60e0848d784a6dd461da6.png

以及改变pixelFormat的函数:

err = mANativeWindow->set_buffers_geometry(

mANativeWindow,

width,

height,

mNativeWindowPixelFormat);//NV21

此函数直接会直接回调到CameraHardwareInterface.h中的ANativeWindow的函数实现:

69c5a8ac3fa60e0848d784a6dd461da6.png

static int __set_buffers_geometry(struct preview_stream_ops*w,int width, int height, intformat)

{

ANativeWindow*a =anw(w);returnnative_window_set_buffers_geometry(a,

width, height, format);

}

69c5a8ac3fa60e0848d784a6dd461da6.png

而native_window_set_buffers_geometry()是跨进程的函数调用,定义在system/core/include/system/window.h

69c5a8ac3fa60e0848d784a6dd461da6.png

/** native_window_set_buffers_geometry(..., int w, int h, int format)

* All buffers dequeued after this call will have the dimensions and format

* specified. A successful call to this function has the same effect as calling

* native_window_set_buffers_size and native_window_set_buffers_format.

*

* XXX: This function is deprecated. The native_window_set_buffers_dimensions

* and native_window_set_buffers_format functions should be used instead.*/ static inline intnative_window_set_buffers_geometry(struct ANativeWindow*window,int w, int h, intformat)

{return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,

w, h, format);

}

69c5a8ac3fa60e0848d784a6dd461da6.png

Struct ANativeWindow也定义在此文件中,ANativeWindow是OpenGL画图的一个接口,Surface

类继承了ANativeWindow类。ANativeWindow类是连接OpenGL和Android窗口系统的桥梁,即OpenGL需要通过

ANativeWindow类来间接地操作Android窗口系统。这种桥梁关系是通过EGL库来建立的,所有以egl为前缀的函数名均为EGL库提供的

接口,暂时知道这么多。上面的函数是通过window->preform(,,,)实现的

69c5a8ac3fa60e0848d784a6dd461da6.png

/** 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 (private)

* 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 (private)

* NATIVE_WINDOW_LOCK (private)

* NATIVE_WINDOW_UNLOCK_AND_POST (private)

* NATIVE_WINDOW_API_CONNECT (private)

* NATIVE_WINDOW_API_DISCONNECT (private)

* NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS (private)

* NATIVE_WINDOW_SET_POST_TRANSFORM_CROP (private)

**/ int (*perform)(struct ANativeWindow*window,int operation, ... );

69c5a8ac3fa60e0848d784a6dd461da6.png

定义了一个函数指针int (*perform)(struct ANativeWindow* window, int operation, ... );

@./frameworks/native/libs/gui/SurfaceTextureClient.cpp

69c5a8ac3fa60e0848d784a6dd461da6.png

int SurfaceTextureClient::perform(intoperation, va_list args)

{int res =NO_ERROR;switch(operation) {caseNATIVE_WINDOW_CONNECT://deprecated. must return NO_ERROR. break;caseNATIVE_WINDOW_DISCONNECT://deprecated. must return NO_ERROR. break;caseNATIVE_WINDOW_SET_USAGE:

res=dispatchSetUsage(args);break;caseNATIVE_WINDOW_SET_CROP:

res=dispatchSetCrop(args);break;caseNATIVE_WINDOW_SET_BUFFER_COUNT:

res=dispatchSetBufferCount(args);break;caseNATIVE_WINDOW_SET_BUFFERS_GEOMETRY:

res=dispatchSetBuffersGeometry(args);break;caseNATIVE_WINDOW_SET_BUFFERS_TRANSFORM:

res=dispatchSetBuffersTransform(args);break;caseNATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:

res=dispatchSetBuffersTimestamp(args);break;caseNATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:

res=dispatchSetBuffersDimensions(args);break;caseNATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS:

res=dispatchSetBuffersUserDimensions(args);break;caseNATIVE_WINDOW_SET_BUFFERS_FORMAT:

res=dispatchSetBuffersFormat(args);break;caseNATIVE_WINDOW_LOCK:

res=dispatchLock(args);break;caseNATIVE_WINDOW_UNLOCK_AND_POST:

res=dispatchUnlockAndPost(args);break;caseNATIVE_WINDOW_SET_SCALING_MODE:

res=dispatchSetScalingMode(args);break;caseNATIVE_WINDOW_API_CONNECT:

res=dispatchConnect(args);break;caseNATIVE_WINDOW_API_DISCONNECT:

res=dispatchDisconnect(args);break;default:

res=NAME_NOT_FOUND;break;

}returnres;

}

69c5a8ac3fa60e0848d784a6dd461da6.png

69c5a8ac3fa60e0848d784a6dd461da6.png

intSurfaceTextureClient::dispatchSetBuffersGeometry(va_list args) {int w = va_arg(args, int);int h = va_arg(args, int);int f = va_arg(args, int);int err =setBuffersDimensions(w, h);if (err != 0) {returnerr;

}returnsetBuffersFormat(f);

}

69c5a8ac3fa60e0848d784a6dd461da6.png

69c5a8ac3fa60e0848d784a6dd461da6.png

int SurfaceTextureClient::setBuffersFormat(intformat)

{

ALOGV("SurfaceTextureClient::setBuffersFormat");if (format<0)returnBAD_VALUE;

Mutex::Autolocklock(mMutex);

mReqFormat=format;returnNO_ERROR;

}

69c5a8ac3fa60e0848d784a6dd461da6.png

看不出来什么。mReqFormat也没有什么条件进行判断。再看另外一个函数

69c5a8ac3fa60e0848d784a6dd461da6.png

int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t**buffer) {

ATRACE_CALL();

ALOGV("SurfaceTextureClient::dequeueBuffer");

Mutex::Autolocklock(mMutex);int buf = -1;int reqW = mReqWidth ?mReqWidth : mUserWidth;int reqH = mReqHeight ?mReqHeight : mUserHeight;

status_t result= mSurfaceTexture->dequeueBuffer(&buf, reqW, reqH,

mReqFormat, mReqUsage);

69c5a8ac3fa60e0848d784a6dd461da6.png

mSurfaceTexture是I

mSurfaceTexture是ISurfaceTexture类型,是SurfaceTexture服务client service结构中的client。

SurfaceTexture.cpp中

69c5a8ac3fa60e0848d784a6dd461da6.png

class BpSurfaceTexture : public BpInterface{public:virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,

uint32_t format, uint32_t usage) {

Parcel data, reply;

data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());

data.writeInt32(w);

data.writeInt32(h);

data.writeInt32(format);

data.writeInt32(usage);

status_t result= remote()->transact(DEQUEUE_BUFFER, data, &reply);if (result !=NO_ERROR) {returnresult;

}*buf =reply.readInt32();

result=reply.readInt32();returnresult;

}

}

69c5a8ac3fa60e0848d784a6dd461da6.png

再看BnSurfaceTexture是如何实现DEQUEUE_BUFFER的

69c5a8ac3fa60e0848d784a6dd461da6.png

status_t BnSurfaceTexture::onTransact(

uint32_t code,const Parcel& data, Parcel*reply, uint32_t flags)

{switch(code) {caseDEQUEUE_BUFFER: {

CHECK_INTERFACE(ISurfaceTexture, data, reply);

uint32_t w=data.readInt32();

uint32_t h=data.readInt32();

uint32_t format=data.readInt32();

uint32_t usage=data.readInt32();intbuf;int result = dequeueBuffer(&buf, w, h, format, usage);

reply->writeInt32(buf);

reply->writeInt32(result);returnNO_ERROR;

}break;

}

69c5a8ac3fa60e0848d784a6dd461da6.png

69c5a8ac3fa60e0848d784a6dd461da6.png

class BufferQueue : publicBnSurfaceTexture {public://dequeueBuffer gets the next buffer slot index for the client to use. If a//buffer slot is available then that slot index is written to the location//pointed to by the buf argument and a status of OK is returned. If no//slot is available then a status of -EBUSY is returned and buf is//unmodified.//The width and height parameters must be no greater than the minimum of//GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).//An error due to invalid dimensions might not be reported until//updateTexImage() is called. virtual status_t dequeueBuffer(int *buf, uint32_t width, uint32_t height,

uint32_t format, uint32_t usage);

}

69c5a8ac3fa60e0848d784a6dd461da6.png

具体实现是在BufferQueue.cpp

cdec0645add3fc3c328197dda5c76203.png BufferQueue::dequeueBuffer

上面的函数太长,如果当前的format跟参数中的format不一致,则需要重新申请,

spgraphicBuffer(

mGraphicBufferAlloc->createGraphicBuffer(

w, h, format, usage,&error));

//mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to//allocate new GraphicBuffer objects. spmGraphicBufferAlloc;

69c5a8ac3fa60e0848d784a6dd461da6.png

spGraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h,

PixelFormat format, uint32_t usage, status_t*error) {

spgraphicBuffer(newGraphicBuffer(w, h, format, usage));

status_t err= graphicBuffer->initCheck();*error =err;if (err != 0 || graphicBuffer->handle == 0) {if (err ==NO_MEMORY) {

GraphicBuffer::dumpAllocationsToSystemLog();

}

ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d)" "failed (%s), handle=%p",

w, h, strerror(-err), graphicBuffer->handle);return 0;

}returngraphicBuffer;

}

69c5a8ac3fa60e0848d784a6dd461da6.png

GraphicBuffer定义在native/include/ui/GraphicBuffer.h

构造函数中指定format的类型为PixelFormat

69c5a8ac3fa60e0848d784a6dd461da6.png

namespaceandroid {enum{// //these constants need to match those//in graphics/PixelFormat.java & pixelflinger/format.h// PIXEL_FORMAT_UNKNOWN = 0,

PIXEL_FORMAT_NONE= 0,//logical pixel formats used by the SurfaceFlinger ----------------------- PIXEL_FORMAT_CUSTOM = -4,//Custom pixel-format described by a PixelFormatInfo structure PIXEL_FORMAT_TRANSLUCENT= -3,//System chooses a format that supports translucency (many alpha bits) PIXEL_FORMAT_TRANSPARENT= -2,//System chooses a format that supports transparency//(at least 1 alpha bit) PIXEL_FORMAT_OPAQUE= -1,//System chooses an opaque format (no alpha bits required)//real pixel formats supported for rendering ----------------------------- PIXEL_FORMAT_RGBA_8888= HAL_PIXEL_FORMAT_RGBA_8888, //4x8-bit RGBA PIXEL_FORMAT_RGBX_8888 = HAL_PIXEL_FORMAT_RGBX_8888, //4x8-bit RGB0 PIXEL_FORMAT_RGB_888 = HAL_PIXEL_FORMAT_RGB_888, //3x8-bit RGB PIXEL_FORMAT_RGB_565 = HAL_PIXEL_FORMAT_RGB_565, //16-bit RGB PIXEL_FORMAT_BGRA_8888 = HAL_PIXEL_FORMAT_BGRA_8888, //4x8-bit BGRA PIXEL_FORMAT_RGBA_5551 = HAL_PIXEL_FORMAT_RGBA_5551, //16-bit ARGB PIXEL_FORMAT_RGBA_4444 = HAL_PIXEL_FORMAT_RGBA_4444, //16-bit ARGB PIXEL_FORMAT_A_8 = 8, //8-bit A }; typedef int32_t PixelFormat;structPixelFormatInfo {enum{

INDEX_ALPHA= 0,

INDEX_RED= 1,

INDEX_GREEN= 2,

INDEX_BLUE= 3};enum { //components ALPHA = 1,

RGB= 2,

RGBA= 3,

L= 4,

LA= 5,

OTHER= 0xFF};structszinfo {

uint8_t h;

uint8_t l;

};

inline PixelFormatInfo() : version(sizeof(PixelFormatInfo)) { }

size_t getScanlineSize(unsignedint width) const;

size_t getSize(size_t ci)const{return (ci <= 3) ? (cinfo[ci].h - cinfo[ci].l) : 0;

}

size_t version;

PixelFormat format;

size_t bytesPerPixel;

size_t bitsPerPixel;

union {

szinfo cinfo[4];struct{

uint8_t h_alpha;

uint8_t l_alpha;

uint8_t h_red;

uint8_t l_red;

uint8_t h_green;

uint8_t l_green;

uint8_t h_blue;

uint8_t l_blue;

};

};

uint8_t components;

uint8_t reserved0[3];

uint32_t reserved1;

};

69c5a8ac3fa60e0848d784a6dd461da6.png

感觉有点问题,这里的PixelFormat跟下面的定义不一致,好像是对PixelFormat的扩展。

格式HAL_PIXEL_FORMAT_YCrCb_420_SP的定义在./system/core/include/system/graphics.h

69c5a8ac3fa60e0848d784a6dd461da6.png

enum{

HAL_PIXEL_FORMAT_RGBA_8888= 1,

HAL_PIXEL_FORMAT_RGBX_8888= 2,

HAL_PIXEL_FORMAT_RGB_888= 3,

HAL_PIXEL_FORMAT_RGB_565= 4,

HAL_PIXEL_FORMAT_BGRA_8888= 5,

HAL_PIXEL_FORMAT_RGBA_5551= 6,

HAL_PIXEL_FORMAT_RGBA_4444= 7,/*0x8 - 0xFF range unavailable*/ /** 0x100 - 0x1FF

*

* This range is reserved for pixel formats that are specific to the HAL

* implementation. Implementations can use any value in this range to

* communicate video pixel formats between their HAL modules. These formats

* must not have an alpha channel. Additionally, an EGLimage created from a

* gralloc buffer of one of these formats must be supported for use with the

* GL_OES_EGL_image_external OpenGL ES extension.*/ /** Android YUV format:

*

* This format is exposed outside of the HAL to software decoders and

* applications. EGLImageKHR must support it in conjunction with the

* OES_EGL_image_external extension.

*

* YV12 is a 4:2:0 YCrCb planar format comprised of a WxH Y plane followed

* by (W/2) x (H/2) Cr and Cb planes.

*

* This format assumes

* - an even width

* - an even height

* - a horizontal stride multiple of 16 pixels

* - a vertical stride equal to the height

*

* y_size = stride * height

* c_stride = ALIGN(stride/2, 16)

* c_size = c_stride * height/2

* size = y_size + c_size * 2

* cr_offset = y_size

* cb_offset = y_size + c_size

**/HAL_PIXEL_FORMAT_YV12= 0x32315659, //YCrCb 4:2:0 Planar /** Android RAW sensor format:

*

* This format is exposed outside of the HAL to applications.

*

* RAW_SENSOR is a single-channel 16-bit format, typically representing raw

* Bayer-pattern images from an image sensor, with minimal processing.

*

* The exact pixel layout of the data in the buffer is sensor-dependent, and

* needs to be queried from the camera device.

*

* Generally, not all 16 bits are used; more common values are 10 or 12

* bits. All parameters to interpret the raw data (black and white points,

* color space, etc) must be queried from the camera device.

*

* This format assumes

* - an even width

* - an even height

* - a horizontal stride multiple of 16 pixels (32 bytes).*/HAL_PIXEL_FORMAT_RAW_SENSOR= 0x20,/*Legacy formats (deprecated), used by ImageFormat.java*/HAL_PIXEL_FORMAT_YCbCr_422_SP= 0x10, //NV16 HAL_PIXEL_FORMAT_YCrCb_420_SP = 0x11, //NV21 HAL_PIXEL_FORMAT_YCbCr_422_I = 0x14, //YUY2 };

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值