status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow( sp<CameraHardwareInterface> device, int32_t width, int32_t height) { status_t res; BufferQueue::createBufferQueue(&mProducer, &mConsumer); mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL, true, true); if (mSurfaceTexture == NULL) { return NO_MEMORY; } int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; res = mSurfaceTexture->setDefaultBufferSize(width, height); if (res) { return res; } res = mSurfaceTexture->setDefaultBufferFormat(format); if (res) { return res; } mSurface = new Surface(mProducer, /*useAsync*/ true); if (mSurface == NULL) { return NO_MEMORY; } res = native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_CAMERA); if (res) { ALOGE("%s: Unable to connect to native window", __FUNCTION__); return res; } return device->setPreviewWindow(mSurface); }
int PreviewRenderer::init() { int err = 0; ANativeWindow* anw = mSurface.get(); err = native_window_api_connect(anw, NATIVE_WINDOW_API_CPU); if (err) goto fail; err = native_window_set_usage( anw, GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN); if (err) goto fail; err = native_window_set_buffer_count(anw, 3); if (err) goto fail; err = native_window_set_scaling_mode( anw, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); if (err) goto fail; err = native_window_set_buffers_geometry( anw, mWidth, mHeight, HAL_PIXEL_FORMAT_YV12); if (err) goto fail; err = native_window_set_buffers_transform(anw, 0); if (err) goto fail; fail: return err; }
EGLSurface EglWindowSurfaceImpl::Create(EGLDisplay dpy, EGLConfig cfg, ANativeWindow* window, EGLint* out_error) { LOG_ALWAYS_FATAL_IF(out_error == NULL); *out_error = EGL_SUCCESS; EGLint format = 0; EGLint sfc_type = 0; EglDisplayImpl* display = EglDisplayImpl::GetDisplay(dpy); if (!display->GetConfigAttribute(cfg, EGL_NATIVE_VISUAL_ID, &format)) { ALOGE("Unable to get native visual format."); *out_error = EGL_BAD_ALLOC; return EGL_NO_SURFACE; } else if (!display->GetConfigAttribute(cfg, EGL_SURFACE_TYPE, &sfc_type)) { ALOGE("Unable to get surface type."); *out_error = EGL_BAD_ALLOC; return EGL_NO_SURFACE; } else if (!(sfc_type & EGL_WINDOW_BIT)) { ALOGE("Must support EGL_WINDOW_BIT surface types."); *out_error = EGL_BAD_ALLOC; return EGL_NO_SURFACE; } else if (!window) { ALOGE("No native window provided."); *out_error = EGL_BAD_ALLOC; return EGL_NO_SURFACE; } else if (window->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) { ALOGE("Invalid native window."); *out_error = EGL_BAD_ALLOC; return EGL_NO_SURFACE; } else if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != android::OK) { ALOGE("Could not connect to native window."); *out_error = EGL_BAD_ALLOC; return EGL_NO_SURFACE; } int width = 0; window->query(window, NATIVE_WINDOW_WIDTH, &width); int height = 0; window->query(window, NATIVE_WINDOW_HEIGHT, &height); if (format != 0) { native_window_set_buffers_format(window, format); } window->setSwapInterval(window, 1); SurfacePtr s(new EglWindowSurfaceImpl(dpy, cfg, sfc_type, width, height, window)); if (s == NULL) { native_window_set_buffers_format(window, 0); native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); *out_error = EGL_BAD_ALLOC; return EGL_NO_DISPLAY; } return display->GetSurfaces().Register(s); }
status_t CameraClient::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) { ALOGE("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); } #ifdef QCOM_HARDWARE #ifndef NO_UPDATE_PREVIEW } else { if (window != 0) { native_window_set_buffers_transform(window.get(), mOrientation); } result = mHardware->setPreviewWindow(window); #endif #endif } 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; }
int IOMXHWBuffer_Connect( void *window ) { ANativeWindow *anw = (ANativeWindow *)window; CHECK_ANW(); #if ANDROID_API >= 14 if (native_window_api_connect( anw, NATIVE_WINDOW_API_MEDIA ) != 0) { LOGE( "native_window_api_connect FAIL" ); return -EINVAL; } #endif }
void SurfaceUtils::connectAPI(int api) { native_window_api_connect(mWindow, api); }
status_t pushBlankBuffersToNativeWindow(ANativeWindow *nativeWindow /* nonnull */) { status_t err = NO_ERROR; ANativeWindowBuffer* anb = NULL; int numBufs = 0; int minUndequeuedBufs = 0; // We need to reconnect to the ANativeWindow as a CPU client to ensure that // no frames get dropped by SurfaceFlinger assuming that these are video // frames. err = native_window_api_disconnect(nativeWindow, NATIVE_WINDOW_API_MEDIA); if (err != NO_ERROR) { ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", strerror(-err), -err); return err; } err = native_window_api_connect(nativeWindow, NATIVE_WINDOW_API_CPU); if (err != NO_ERROR) { ALOGE("error pushing blank frames: api_connect failed: %s (%d)", strerror(-err), -err); (void)native_window_api_connect(nativeWindow, NATIVE_WINDOW_API_MEDIA); return err; } err = setNativeWindowSizeFormatAndUsage( nativeWindow, 1, 1, HAL_PIXEL_FORMAT_RGBX_8888, 0, GRALLOC_USAGE_SW_WRITE_OFTEN); if (err != NO_ERROR) { goto error; } static_cast<Surface*>(nativeWindow)->getIGraphicBufferProducer()->allowAllocation(true); err = nativeWindow->query(nativeWindow, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs); if (err != NO_ERROR) { ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query " "failed: %s (%d)", strerror(-err), -err); goto error; } numBufs = minUndequeuedBufs + 1; err = native_window_set_buffer_count(nativeWindow, numBufs); if (err != NO_ERROR) { ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)", strerror(-err), -err); goto error; } // We push numBufs + 1 buffers to ensure that we've drawn into the same // buffer twice. This should guarantee that the buffer has been displayed // on the screen and then been replaced, so an previous video frames are // guaranteed NOT to be currently displayed. for (int i = 0; i < numBufs + 1; i++) { err = native_window_dequeue_buffer_and_wait(nativeWindow, &anb); if (err != NO_ERROR) { ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)", strerror(-err), -err); break; } sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); // Fill the buffer with the a 1x1 checkerboard pattern ;) uint32_t *img = NULL; err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); if (err != NO_ERROR) { ALOGE("error pushing blank frames: lock failed: %s (%d)", strerror(-err), -err); break; } *img = 0; err = buf->unlock(); if (err != NO_ERROR) { ALOGE("error pushing blank frames: unlock failed: %s (%d)", strerror(-err), -err); break; } err = nativeWindow->queueBuffer(nativeWindow, buf->getNativeBuffer(), -1); if (err != NO_ERROR) { ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)", strerror(-err), -err); break; } anb = NULL; } error: if (anb != NULL) { nativeWindow->cancelBuffer(nativeWindow, anb, -1); anb = NULL; } // Clean up after success or error. status_t err2 = native_window_api_disconnect(nativeWindow, NATIVE_WINDOW_API_CPU); if (err2 != NO_ERROR) { ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", strerror(-err2), -err2); if (err == NO_ERROR) { err = err2; } } err2 = native_window_api_connect(nativeWindow, NATIVE_WINDOW_API_MEDIA); if (err2 != NO_ERROR) { ALOGE("error pushing blank frames: api_connect failed: %s (%d)", strerror(-err), -err); if (err == NO_ERROR) { err = err2; } } return err; }
// This test is intended to verify that proper synchronization is done when // rendering into an FBO. TEST_F(SurfaceTextureFBOTest, BlitFromCpuFilledBufferToFbo) { const int texWidth = 64; const int texHeight = 64; ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU)); ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(), texWidth, texHeight)); ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(), HAL_PIXEL_FORMAT_RGBA_8888)); ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); android_native_buffer_t* anb; ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); ASSERT_TRUE(anb != NULL); sp<GraphicBuffer> buf(GraphicBuffer::from(anb)); // Fill the buffer with green uint8_t* img = NULL; buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); fillRGBA8BufferSolid(img, texWidth, texHeight, buf->getStride(), 0, 255, 0, 255); buf->unlock(); ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(), -1)); ASSERT_EQ(NO_ERROR, mST->updateTexImage()); glBindFramebuffer(GL_FRAMEBUFFER, mFbo); drawTexture(); glBindFramebuffer(GL_FRAMEBUFFER, 0); for (int i = 0; i < 4; i++) { SCOPED_TRACE(String8::format("frame %d", i).string()); ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); ASSERT_TRUE(anb != NULL); buf = GraphicBuffer::from(anb); // Fill the buffer with red ASSERT_EQ(NO_ERROR, buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img))); fillRGBA8BufferSolid(img, texWidth, texHeight, buf->getStride(), 255, 0, 0, 255); ASSERT_EQ(NO_ERROR, buf->unlock()); ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(), -1)); ASSERT_EQ(NO_ERROR, mST->updateTexImage()); drawTexture(); EXPECT_TRUE(checkPixel( 24, 39, 255, 0, 0, 255)); } glBindFramebuffer(GL_FRAMEBUFFER, mFbo); EXPECT_TRUE(checkPixel( 24, 39, 0, 255, 0, 255)); }
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); 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; 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; }
void FakeSurfaceComposer::captureScreenImp(const sp<IGraphicBufferProducer>& producer, uint32_t reqWidth, uint32_t reqHeight, const sp<GraphicProducerWrapper>& wrapper) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(wrapper.get()); RefPtr<nsScreenGonk> screen = nsScreenManagerGonk::GetPrimaryScreen(); // get screen geometry nsIntRect screenBounds = screen->GetNaturalBounds().ToUnknownRect(); const uint32_t hw_w = screenBounds.width; const uint32_t hw_h = screenBounds.height; if (reqWidth > hw_w || reqHeight > hw_h) { ALOGE("size mismatch (%d, %d) > (%d, %d)", reqWidth, reqHeight, hw_w, hw_h); static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(BAD_VALUE); return; } reqWidth = (!reqWidth) ? hw_w : reqWidth; reqHeight = (!reqHeight) ? hw_h : reqHeight; nsScreenGonk* screenPtr = screen.forget().take(); nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([screenPtr, reqWidth, reqHeight, producer, wrapper]() { // create a surface (because we're a producer, and we need to // dequeue/queue a buffer) sp<Surface> sur = new Surface(producer); ANativeWindow* window = sur.get(); if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != NO_ERROR) { static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(BAD_VALUE); NS_ReleaseOnMainThread(screenPtr); return; } uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; int err = 0; err = native_window_set_buffers_dimensions(window, reqWidth, reqHeight); err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888); err |= native_window_set_usage(window, usage); status_t result = NO_ERROR; if (err == NO_ERROR) { ANativeWindowBuffer* buffer; result = native_window_dequeue_buffer_and_wait(window, &buffer); if (result == NO_ERROR) { nsresult rv = screenPtr->MakeSnapshot(buffer); if (rv != NS_OK) { result = INVALID_OPERATION; } window->queueBuffer(window, buffer, -1); } } else { result = BAD_VALUE; } native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(result); NS_ReleaseOnMainThread(screenPtr); }); mozilla::layers::CompositorParent::CompositorLoop()->PostTask( FROM_HERE, new RunnableCallTask(runnable)); }
status_t StreamAdapter::connectToDevice(camera2_device_t *d, uint32_t width, uint32_t height, int format) { if (mState != UNINITIALIZED) return INVALID_OPERATION; if (d == NULL) { ALOGE("%s: Null device passed to stream adapter", __FUNCTION__); return BAD_VALUE; } status_t res; mWidth = width; mHeight = height; mFormat = format; // Allocate device-side stream interface uint32_t id; uint32_t formatActual; // ignored uint32_t usage; uint32_t maxBuffers = 2; res = d->ops->allocate_stream(d, mWidth, mHeight, mFormat, getStreamOps(), &id, &formatActual, &usage, &maxBuffers); if (res != OK) { ALOGE("%s: Device stream allocation failed: %s (%d)", __FUNCTION__, strerror(-res), res); mState = UNINITIALIZED; return res; } mDevice = d; mId = id; mUsage = usage; mMaxProducerBuffers = maxBuffers; // Configure consumer-side ANativeWindow interface res = native_window_api_connect(mConsumerInterface.get(), NATIVE_WINDOW_API_CAMERA); if (res != OK) { ALOGE("%s: Unable to connect to native window for stream %d", __FUNCTION__, mId); mState = ALLOCATED; return res; } res = native_window_set_usage(mConsumerInterface.get(), mUsage); if (res != OK) { ALOGE("%s: Unable to configure usage %08x for stream %d", __FUNCTION__, mUsage, mId); mState = CONNECTED; return res; } res = native_window_set_buffers_geometry(mConsumerInterface.get(), mWidth, mHeight, mFormat); if (res != OK) { ALOGE("%s: Unable to configure buffer geometry" " %d x %d, format 0x%x for stream %d", __FUNCTION__, mWidth, mHeight, mFormat, mId); mState = CONNECTED; return res; } int maxConsumerBuffers; res = mConsumerInterface->query(mConsumerInterface.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers); if (res != OK) { ALOGE("%s: Unable to query consumer undequeued" " buffer count for stream %d", __FUNCTION__, mId); mState = CONNECTED; return res; } mMaxConsumerBuffers = maxConsumerBuffers; ALOGV("%s: Producer wants %d buffers, consumer wants %d", __FUNCTION__, mMaxProducerBuffers, mMaxConsumerBuffers); int totalBuffers = mMaxConsumerBuffers + mMaxProducerBuffers; res = native_window_set_buffer_count(mConsumerInterface.get(), totalBuffers); if (res != OK) { ALOGE("%s: Unable to set buffer count for stream %d", __FUNCTION__, mId); mState = CONNECTED; return res; } // Register allocated buffers with HAL device buffer_handle_t *buffers = new buffer_handle_t[totalBuffers]; ANativeWindowBuffer **anwBuffers = new ANativeWindowBuffer*[totalBuffers]; int bufferIdx = 0; for (; bufferIdx < totalBuffers; bufferIdx++) { res = native_window_dequeue_buffer_and_wait(mConsumerInterface.get(), &anwBuffers[bufferIdx]); if (res != OK) { ALOGE("%s: Unable to dequeue buffer %d for initial registration for" "stream %d", __FUNCTION__, bufferIdx, mId); mState = CONNECTED; goto cleanUpBuffers; } buffers[bufferIdx] = anwBuffers[bufferIdx]->handle; } res = mDevice->ops->register_stream_buffers(mDevice, mId, totalBuffers, buffers); if (res != OK) { ALOGE("%s: Unable to register buffers with HAL device for stream %d", __FUNCTION__, mId); mState = CONNECTED; } else { mState = ACTIVE; } cleanUpBuffers: for (int i = 0; i < bufferIdx; i++) { res = mConsumerInterface->cancelBuffer(mConsumerInterface.get(), anwBuffers[i], -1); } delete anwBuffers; delete buffers; return res; }
bool_e anativewindow_allocate(anativewindow_t *anw, uint32_t buffer_width, uint32_t buffer_height, int32_t numBuffers, int32_t format, bool flipH) { if (format != ANW_NV12_FORMAT) return false_e; if (anw) { status_t status = 0; anw->m_format = format; anw->m_usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_SW_READ_OFTEN | // Non-cached ? If you use RARELY it will complain GRALLOC_USAGE_SW_WRITE_NEVER; // can't access from UVA anw->m_numBuffers = numBuffers; anw->m_width = buffer_width; anw->m_height = buffer_height; anw->m_native_buffers = (ANativeWindowBuffer **)calloc(numBuffers, sizeof(ANativeWindowBuffer *)); DVP_PRINT(DVP_ZONE_VIDEO, "Created %u pointers in native array %p\n", numBuffers, anw->m_native_buffers); if (anw->m_native_buffers == NULL) { return false_e; } // connect to the native window API status = native_window_api_connect(anw->m_window.get(), NATIVE_WINDOW_API_CAMERA); ANW_ERROR(status,"CONNECT"); // set the scaling mode of the windows status = native_window_set_scaling_mode(anw->m_window.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); ANW_ERROR(status,"SCALING"); #if defined(BLAZE_TABLET) && defined(ICS) // set the layout of the buffer status = native_window_set_buffers_layout(anw->m_window.get(), NATIVE_WINDOW_BUFFERS_LAYOUT_PROGRESSIVE); // progressive ANW_ERROR(status,"LAYOUT"); #endif // set the format of the buffer status = native_window_set_buffers_format(anw->m_window.get(), anw->m_format); ANW_ERROR(status,"FORMAT"); // setup the dimensions status = native_window_set_buffers_dimensions(anw->m_window.get(), anw->m_width, anw->m_height); ANW_ERROR(status,"DIM"); if (flipH) { // set the horizontal flip status = native_window_set_buffers_transform(anw->m_window.get(), NATIVE_WINDOW_TRANSFORM_FLIP_H); ANW_ERROR(status,"TRANSFORM FLIP HORIZONTAL"); } // set the usage of the GRALLOC buffers status = native_window_set_usage(anw->m_window.get(), anw->m_usage); if (status < 0 ) { DVP_PRINT(DVP_ZONE_ERROR, "%s[%u] USAGE status = %d (0x%08x)\n", __FUNCTION__, __LINE__, status, anw->m_usage); } // set the number of buffers required. status = native_window_set_buffer_count(anw->m_window.get(), anw->m_numBuffers); ANW_ERROR(status,"COUNT"); // get the number of dequeueable buffers status = anw->m_window->query(anw->m_window.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, (int*)&anw->m_nonqueue); ANW_ERROR(status,"QUERY NONQUEUE"); for (uint32_t n = 0; n < anw->m_numBuffers; n++) { status = anw->m_window->dequeueBuffer(anw->m_window.get(), &anw->m_native_buffers[n]); if (status != 0) { DVP_PRINT(DVP_ZONE_ERROR, "%s[%u] %s status = %d\n", __FUNCTION__, __LINE__, "Failed window buffer dequeue!", status); \ return false_e; } if (anw->m_native_buffers[n]) { native_handle_t *hdl = (native_handle_t *)anw->m_native_buffers[n]->handle; hdl = hdl; // warnings DVP_PRINT(DVP_ZONE_VIDEO, "ANativeBuffer %p => dim %dx%d stride %d usage %d format %d handle %p numFds=%u\n", anw->m_native_buffers[n], anw->m_native_buffers[n]->width, anw->m_native_buffers[n]->height, anw->m_native_buffers[n]->stride, anw->m_native_buffers[n]->usage, anw->m_native_buffers[n]->format, anw->m_native_buffers[n]->handle, hdl->numFds); } } return true_e; } return false_e; }
status_t setNativeWindowSizeFormatAndUsage( ANativeWindow *nativeWindow /* nonnull */, int width, int height, int format, int rotation, int usage, bool reconnect) { status_t err = NO_ERROR; // In some cases we need to reconnect so that we can dequeue all buffers if (reconnect) { err = native_window_api_disconnect(nativeWindow, NATIVE_WINDOW_API_MEDIA); if (err != NO_ERROR) { ALOGE("native_window_api_disconnect failed: %s (%d)", strerror(-err), -err); return err; } err = native_window_api_connect(nativeWindow, NATIVE_WINDOW_API_MEDIA); if (err != NO_ERROR) { ALOGE("native_window_api_connect failed: %s (%d)", strerror(-err), -err); return err; } } err = native_window_set_buffers_dimensions(nativeWindow, width, height); if (err != NO_ERROR) { ALOGE("native_window_set_buffers_dimensions failed: %s (%d)", strerror(-err), -err); return err; } err = native_window_set_buffers_format(nativeWindow, format); if (err != NO_ERROR) { ALOGE("native_window_set_buffers_format failed: %s (%d)", strerror(-err), -err); return err; } int transform = 0; if ((rotation % 90) == 0) { switch ((rotation / 90) & 3) { case 1: transform = HAL_TRANSFORM_ROT_90; break; case 2: transform = HAL_TRANSFORM_ROT_180; break; case 3: transform = HAL_TRANSFORM_ROT_270; break; default: transform = 0; break; } } err = native_window_set_buffers_transform(nativeWindow, transform); if (err != NO_ERROR) { ALOGE("native_window_set_buffers_transform failed: %s (%d)", strerror(-err), -err); return err; } int consumerUsage = 0; err = nativeWindow->query(nativeWindow, NATIVE_WINDOW_CONSUMER_USAGE_BITS, &consumerUsage); if (err != NO_ERROR) { ALOGW("failed to get consumer usage bits. ignoring"); err = NO_ERROR; } // Make sure to check whether either Stagefright or the video decoder // requested protected buffers. if (usage & GRALLOC_USAGE_PROTECTED) { // Check if the ANativeWindow sends images directly to SurfaceFlinger. int queuesToNativeWindow = 0; err = nativeWindow->query( nativeWindow, NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &queuesToNativeWindow); if (err != NO_ERROR) { ALOGE("error authenticating native window: %s (%d)", strerror(-err), -err); return err; } // Check if the ANativeWindow uses hardware protected buffers. if (queuesToNativeWindow != 1 && !(consumerUsage & GRALLOC_USAGE_PROTECTED)) { ALOGE("native window could not be authenticated"); return PERMISSION_DENIED; } } int finalUsage = usage | consumerUsage; ALOGV("gralloc usage: %#x(producer) + %#x(consumer) = %#x", usage, consumerUsage, finalUsage); err = native_window_set_usage(nativeWindow, finalUsage); if (err != NO_ERROR) { ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err); return err; } err = native_window_set_scaling_mode( nativeWindow, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); if (err != NO_ERROR) { ALOGE("native_window_set_scaling_mode failed: %s (%d)", strerror(-err), -err); return err; } ALOGD("set up nativeWindow %p for %dx%d, color %#x, rotation %d, usage %#x", nativeWindow, width, height, format, rotation, finalUsage); return NO_ERROR; }