Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Native Development

Reply
New Contributor
DamienDub
Posts: 5
Registered: ‎08-21-2013
My Device: Z10, Q10

Camera & adding preview buffers

Hi everyone,

 

I have strange behaviour regarding a custom control built for scanning QR codes.

Here is the code I have so far: 

QRCodeScannerSDK::QRCodeScannerSDK(Container *parent)
: CustomControl(parent)
, camera(new Camera(parent))
, cameraSettings(new CameraSettings(this))
, isScanningStarted(false)
, isVibrateEnabled(true)
, nbuffers(2)
{

    setRoot(camera);

    // Connect to useful signals
    int result = connect(camera, SIGNAL(cameraOpened()),
            this, SLOT(onCameraOpened()));
    Q_UNUSED(result);
    Q_ASSERT(result);

    result = connect(camera, SIGNAL(cameraClosed()),
            this, SLOT(onCameraClosed()));
    Q_ASSERT(result);

    result = connect(camera, SIGNAL(cameraResourceReleased()),
            this, SLOT(onCameraResourceReleased()));
    Q_ASSERT(result);

    result = connect(camera, SIGNAL(cameraResourceAvailable()),
            this, SLOT(onCameraResourceAvailable()));
    Q_ASSERT(result);

    result = connect(camera, SIGNAL(viewfinderStarted()),
            this, SLOT(onViewfinderStarted()));
    Q_ASSERT(result);

    result = connect(camera, SIGNAL(viewfinderStopped()),
            this, SLOT(onViewfinderStopped()));
    Q_ASSERT(result);

    // Handle error signals
    result = connect(camera, SIGNAL(cameraOpenFailed(bb::cascades::multimedia::CameraError::Type)),
            this, SLOT(onCameraFailed()));
    Q_ASSERT(result);

    result = connect(camera, SIGNAL(viewfinderStartFailed(bb::cascades::multimedia::CameraError::Type)),
            this, SLOT(onCameraFailed()));
    Q_ASSERT(result);

    // Send fail signal if we cannot access cameras
    if(!camera->allCamerasAccessible())
    {
        emit QRCodeScanningFailed(QRCodeScannerSDKException(QRCodeScannerSDKErrorCodes::PERMISSION_DENIED));
    }

    // Prepare the decoder
    qrCodeReader = Ref<MultiFormatReader>(new MultiFormatReader());
    DecodeHints *hints = new DecodeHints();
    hints->addFormat(BarcodeFormat_QR_CODE);
    qrCodeReader.object_->setHints(*hints);
}

QRCodeScannerSDK::~QRCodeScannerSDK()
{
    // Delete settings
    if (cameraSettings != NULL)
    {
        delete cameraSettings;
    }

    if(camera != NULL)
    {
        delete camera;
    }

    //    // Close the camera.
    //    camera->close();
}


void QRCodeScannerSDK::onPreviewFrameAvailable(
        SharedUCharPointer previewBuffer, quint64 size, unsigned int width,
        unsigned int height, unsigned int stride)
{
    if(isScanningStarted)
    {
        try
        {

            // Initialize QR Code result
            Ref<LuminanceSource> source(
                    new GreyscaleLuminanceSource(previewBuffer.data(), stride,
                            size / stride, 0, 0, width, height));
            Ref<Binarizer> binarizer(new HybridBinarizer(source));
            Ref<BinaryBitmap> bitmap(new BinaryBitmap(binarizer));
            Ref<Result> result;

            // Decode bitmap
            // Note that since we only target QR codes, we do not need to rotate the bitmap and decode it twice
            result = qrCodeReader->decode(bitmap);

            // Vibrate a little
            VibrationController vc(this);
            if(vc.isSupported() && isVibrateEnabled)
            {
                vc.start(100, 500);
            }

            // Send result
            isScanningStarted = false;
            emit newQRCodeDetected(QString::fromStdString(result->getText()->getText().data()));

        }
        catch (std::exception &e)
        {
            // Nothing was decoded
        }
    }

    // Add another buffer to Zxing buffer pool
    camera->addPreviewBuffer(previewBuffer, size);
}


void QRCodeScannerSDK::onCameraOpened()
{
    qDebug() << "[DEBUG] CAMERA OPENED ---------------------------------";

    // Fill Zxing buffer pool with two buffers (it may be more effecient with more)
      quint64 bufferSize = camera->previewBufferSize();
      for (int i = 0; i < nbuffers; i++)
      {
          camera->addPreviewBuffer(QSharedPointer<unsigned char>(new unsigned char[bufferSize]), bufferSize);
      }

    //TODO:
    // Resolution of captured bitmaps may have a different aspect ratio than the viewfinder's layout.
    // And since the viewfinders keeps the camera's aspect ratio small black frames may appear around the viewfinder.
    // Something to consider: unlike the Z10, future BlackBerry smartphones will have either 16:9 either 1:1 aspect ratios.

    // Configure camera
    camera->getSettings(cameraSettings);
    cameraSettings->setCameraMode(CameraMode::Photo);
    cameraSettings->setFocusMode(CameraFocusMode::ContinuousMacro);
    cameraSettings->setCaptureResolution(QSize(2448, 2448));

    if (!camera->applySettings(cameraSettings))
        qWarning() << "Failed to set up Camera settings";

    QSize resolution =  cameraSettings->captureResolution();
    qDebug() << "Resolutions: " << resolution.width() << "x" << resolution.height();

    QVariantList list = camera->supportedCaptureResolutions(CameraMode::Photo);
    qDebug() << "Resolution supported: " << list;


    // Connect to receive preview frames
    int result = connect(camera, SIGNAL(previewFrameAvailable(bb::cascades::multimedia::SharedUCharPointer, quint64, unsigned int, unsigned int, unsigned int)),
            this, SLOT(onPreviewFrameAvailable(bb::cascades::multimedia::SharedUCharPointer, quint64, unsigned int, unsigned int, unsigned int)));
    Q_UNUSED(result);
    Q_ASSERT(result);

    // Start view finder
    camera->startViewfinder();
}

void QRCodeScannerSDK::onViewfinderStarted()
{
    qDebug() << "[DEBUG] VIEW FINDER STARTED ---------------------------------";
}

void QRCodeScannerSDK::onViewfinderStopped()
{
    qDebug() << "[DEBUG] VIEW FINDER STOPPED ---------------------------------";

    //    // We don't need buffer frames any more
    //    disconnect(camera, SIGNAL(previewFrameAvailable(bb::cascades::multimedia::SharedUCharPointer, quint64, unsigned int, unsigned int, unsigned int)),
    //            this, SLOT(onPreviewFrameAvailable(bb::cascades::multimedia::SharedUCharPointer, quint64, unsigned int, unsigned int, unsigned int)));

    if(!isScanningStarted)
    {
        camera->close();
    }
}

void QRCodeScannerSDK::onCameraClosed()
{
    qDebug() << "[DEBUG] CAMERA CLOSED ---------------------------------";

}

void QRCodeScannerSDK::onCameraResourceReleased()
{
    qDebug() << "[DEBUG] CAMERA RES RELEASED ---------------------------------";

}

void QRCodeScannerSDK::onCameraResourceAvailable()
{
    qDebug() << "[DEBUG] CAMERA RES AVAILABLE ---------------------------------";

    if(isScanningStarted)
    {
        camera->startViewfinder();
    }
}

void QRCodeScannerSDK::onCameraFailed()
{
    qDebug() << "[DEBUG] CAMERA FAIL ---------------------------------";

    emit QRCodeScanningFailed(QRCodeScannerSDKException(QRCodeScannerSDKErrorCodes::INTERNAL_ERROR));
}

void QRCodeScannerSDK::startScanning()
{
    qDebug() << "[DEBUG] STARTED SCANNING ---------------------------------";

    // Set flag
    isScanningStarted = true;

    // Open the camera
    camera->open(CameraUnit::Rear);
}

void QRCodeScannerSDK::stopScanning()
{
    qDebug() << "[DEBUG] STOPPED SCANNING ---------------------------------";

    // Set flag
    isScanningStarted = false;

    // Stop the viewfinder
    camera->stopViewfinder();

}

 

The first time I use the custom control, everything works fine and the preview are correctly added to the buffer pool and read. The log shows the lines below repeatedly:

- VfFrameBufferQueue::addBuffer(VfFrameBuffer) queue count(2)
- CamControllerUtility::S_CopyNV12Frame copy frame data(size=777600, width=720, height=720, stride=736, uvOffset=544768, uvStride=768)
- VfFrameBuffer VfFrameBufferQueue::getBuffer() queue count(1)
- void bb::cascades::multimedia::CameraPrivate::addPreviewBuffer(const QSharedPointer<unsigned char>&, quint64) called

 

However, if I stop the viewfinder and start it again. Something wrong happens with the buffers and I get:

bool VfFrameBufferQueue::grow() command queue overflow: buffers available(16)
bool VfFrameBufferQueue::addBuffer(VfFrameBuffer) Failed to resize queue

 And QR codes are not scanned.  Why does that happen ? 

 

Retired
PBernhardt
Posts: 749
Registered: ‎12-16-2008
My Device: BlackBerry Z30

Re: Camera & adding preview buffers

Well, the error

bool VfFrameBufferQueue::grow() command queue overflow: buffers available(16)

means that there are already 16 buffers that have been added, which is the maximum. I'm not sure what would be causing you to enter that state, however. stopViewfinder() should get rid of all the buffers in the pool. 

 

When exactly are you getting that error?

 

 

Paul Bernhardt
Application Development Consultant
BlackBerry
@PBernhardt

Did this answer your question? Please accept this post as the solution.
Found a bug? Report it to the Developer Issue Tracker