Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145269

Flickering in cam video display, why?

I get flickering in my cam video display, even though I (think I) turned off background erasure. Why?

enter image description here

Even the text display above the video presentation flickers.

Full code at Bitbucket.

Perhaps most relevant code, the gizmo that display the video:

class ImageDisplay:
    public gizmo::SubGizmo
{
typedef gizmo::SubGizmo Base;
private:
    winapi::graphics::ColorDib      dib_;

protected:
    void onPaint( raw::DcHandle const dc ) CPP_IS_OVERRIDE
    {
        dib_.renderOn( dc );
    }

    bool onWmEraseBkgnd( raw::DcHandle const dc )
    {
        CPP_DECLARE_UNUSED( dc );
        return true;        // Just say it's done, so it won't be done again.
    }

    void onWmPaint() CPP_IS_OVERRIDE
    {
        callOnPaint();
    }

    virtual raw::LResult dispatchWm(
        raw::UInt const     messageId,
        raw::WParam const   wParam,
        raw::LParam const   lParam
        )
    {
        CPP_DUMMY_USE_OF( wParam );  CPP_DUMMY_USE_OF( lParam );

        typedef ImageDisplay W;
        switch( messageId )
        {
        case WM_ERASEBKGND:
            return FORWARD_WM_TO( this, W::onWmEraseBkgnd, WM_ERASEBKGND, wParam, lParam );
        }

        return Base::dispatchWm( messageId, wParam, lParam );
    }

public:
    void setImage( cvapi::ImageRef const newImage )
    {
        dib_ = win_cv::dibFrom( newImage );
        setExtent( newImage.extent() );
    }

    ImageDisplay(
        Gizmo&                  parent,
        int const               x,
        int const               y,
        cvapi::ImageRef const&  pic
        )
        : Base( parent, x, y, pic.width(), pic.height() )
        , dib_( win_cv::dibFrom( pic ) )
    {}
};

The main code from the video producer thread:

void imageProducer( 
    wstring const&              namePattern,
    PutFunction const           putResult,
    Thread::Control const&      threadControl
    )
{
    assert( !!putResult );

    cv::VideoCapture cap( 0 );  // Open the default camera.
    hopefully( cap.isOpened() )
        || throwX( "cam::imageProducer: VideoCapture::<init> failed" );

    for(;;)
    {
        cv::Mat frame;

        if( threadControl.exitIsRequested() ) { return; }
        cap >> frame;           // Get a new frame from camera.

        if( threadControl.exitIsRequested() ) { return; }
        putResult( frame );
    }
}

The putResult function just calls Windows’s SendMessage, which synchronizes with the display thread.

I can't see how the flicker manages to sneak in?


EDIT: I found a fix, namely adding WS_CLIPCHILDREN to the main window, and using RedrawWindow to force immediate redrawing of the control (child window). Big mystery why it works. Bigger mystery: without RedrawWindow applied, WS_CLIPCHILDREN causes extreme slowness, like 1 frame every 20 secs?

EDIT 2: it didn't last. :-(

EDIT 3: * S O L V E D *. And mea culpa. All that flicker was caused by an inappropriate call to InvalidateRect, in the main window code. I had probably put it there just to test things, and forgotten to remove it. Argh!

Upvotes: 1

Views: 1397

Answers (1)

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145269

Mea culpa. All that flicker was caused by an inappropriate call to Windows’ InvalidateRect, in the main window code. I had probably put that call there just to test things, and forgotten to remove it. Argh!

Learning point:

Do not blame the “system” (here the Windows API, but also compiler etc.) before you have checked absolutely everything in your own code. It is like dirty fingerprints on your glasses. You never put your fingers on your glasses, and yet these fingerprints appear; same with mysterious undesirable statements in the code.

Upvotes: 2

Related Questions