Use Screen to show the viewfinder window

Updated: April 19, 2023

The Sensor service takes care of creating a Screen window for you and posting the image buffers to that window, which is called a viewfinder window. Using the Screen API, you can get a reference to the viewfinder window and make it visible.

Note: When you stream compressed video and hence, you set the CAMERA_IMGPROP_FORMAT property to CAMERA_FRAMETYPE_COMPRESSEDVIDEO, you can't display this video format in a window, so you need to also set CAMERA_IMGPROP_CREATEWINDOW to 0.

When you set up Screen earlier (in Connect Screen with the Camera API), you created a Screen window group and window, and passed in the Group ID and Window ID into the Camera API using the camera_set_vf_property() function. This gives you access to the viewfinder window, because the Camera library uses the Group ID and joins the viewfinder window as a child to the parent window that your application created in that earlier step. For more information about parent windows and window groups, see Window Management and Window Groups in the Screen Developer's Guide.

After you start the viewfinder (or imaging datapath), you must use the Screen Events Framework to get a reference to the viewfinder window, and then use the Screen API to make this window visible. For full details about using Screen events, see the Event Handling chapter in the Screen Developer's Guide. A Screen Create event is emitted when you start the viewfinder (with camera_start_viewfinder()). After you handle this event, you must perform cleanup and show the image buffers on the display.

The code snippet below shows how to perform these activities. For brevity, we've omitted error checking and handling for some of the Screen calls, but in your production application code, be sure to perform the appropriate error handling.
...
...
screen_context_t screenContext;
int err;
// Start the viewfinder
err = camera_start_viewfinder(cameraHandle, NULL, NULL, NULL);
if (err != CAMERA_EOK) {
    printf("Failed to start viewfinder: err = %d\n", err);
    camera_close(cameraHandle);
    return err;
}

// We need to catch the Create event. Catching it gives us a handle to the viewfinder window.
screen_event_t screenEvent;
bool gotCreateEvent = false;

// This is the viewfinder (image buffer contents) window that's passed to you
screen_window_t* viewfinder = NULL;

// Create an event object to hold the Create event
if (screen_create_event(&screenEvent) == -1) {
    err = errno;
    printf("Failed to create screen event: err = %d\n", err);
    return err;
}

// Handle Screen events
while (screen_get_event(screenContext, screenEvent, -1) == 0) {
    int eventType;
    int objectType;

    // Get the event type
    if (screen_get_event_property_iv(screenEvent, 
                                     SCREEN_PROPERTY_TYPE,
                                     &eventType) == -1) {
        printf("Failed to get type of screen event: err = %d\n", err);
        screen_destroy_event(screenEvent);
        break;
    }

    if (eventType == SCREEN_EVENT_CREATE) {
        // Got the SCREEN_EVENT_CREATE event, which means that the viewfinder window has joined
        // the main application window 
        screen_get_event_property_iv(screenEvent, 
                                     SCREEN_PROPERTY_OBJECT_TYPE,
                                     &objectType);
        if (objectType == SCREEN_OBJECT_TYPE_WINDOW) {
            screen_get_event_property_pv(screenEvent, 
                                         SCREEN_PROPERTY_WINDOW,
                                         (void**)&viewfinder);
        }
        // You now have references to the memory that Screen allocated for you.
        // You're responsible for cleaning this up!
        if (viewfinder) {
            gotCreateEvent = true;
            break; 
        }
    }
    ...
    ...
} // end while

// Clean up memory allocated for the event object
screen_destroy_event(screenEvent);

if (gotCreateEvent == false) {
    err = errno;
    printf("Didn't get a Screen Create event... something didn't go as expected");
    return err;
}

// You now have a handle to the viewfinder window. You must make it visible.
int vsize[2] = {1280, 720};
int vposition[2]={0,0};
screen_set_window_property_iv(*viewfinder, SCREEN_PROPERTY_SIZE, vsize);
screen_set_window_property_iv(*viewfinder, SCREEN_PROPERTY_BUFFER_SIZE, vsize);
screen_set_window_property_iv(*viewfinder, SCREEN_PROPERTY_SOURCE_SIZE, vsize);
screen_set_window_property_iv(*viewfinder, SCREEN_PROPERTY_POSITION, vposition);

// Make the window visible. The Camera library takes care of reposting the content.
int visible = 1;
screen_set_window_property_iv(*viewfinder, SCREEN_PROPERTY_VISIBLE, &visible);

// Flush the changes to make them take effect.
// This is when you should see the viewfinder window on the display.
screen_flush_context(screenContext, SCREEN_WAIT_IDLE);

// At this point, your application should allow the user to do something. In the meantime, 
// your image buffers (video stream) from the camera are automatically reposted on the display.
...
...