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;
}
Exemple #5
0
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
}
Exemple #6
0
 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;
}
Exemple #12
0
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;
}