Example: Show Viewfinder window

This example shows you how to connect to the configured camera of SENSOR_UNIT_1 to show the viewfinder window and show a video stream from a camera.

In this case, the camera can be live camera or prerecorded video.

The example is for a system that: The following sample code does the following:
  1. Create a default blue Screen window. This is a parent window for your application. As part of creating this default window, create a unique GROUP_ID. You'll use this group ID later.
  2. Connect to the camera and set the viewfinder mode.
  3. Pass the unique Group ID (from step 1) to the Camera library.
  4. Start the viewfinder.
  5. Use the Screen Event framework to retrieve a reference to the viewfinder window object. The Camera library takes care of creating this window. Because you set the group ID, it will attempt to join the group you provided. For this reason, you need to use the Screen Event framework to be notified when it occurs. The event you wait on is SCREEN_EVENT_CREATE.
  6. Use the Screen API to make the window visible. You may need to change the Z-order so that it appears on top of the parent window.
    Note: The application can only change the Z-order if your system isn't using a window manager. If your system is using a window manager context, then you might not be able to control the Z-order. For more information, see Window Management" in the Screen Developer's Guide.
  7. You don't need to repost the contents in this example. The Camera library takes care of reposting the contents of the viewfinder window. You will need to handle Screen events though. For more information about handling Screen events, see Screen Events in the Screen Developer's Guide.
  8. After you are done streaming content from the camera, you can stop the viewfinder.
  9. If you are done using the camera, you should close the camera to release resources that were allocated when you opened the camera. Any related buffers you have allocated should be deallocated at this point as well, such as any memory allocated for Screen.

Here's sample code for showing a viewfinder window using the Camera library:

#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <screen/screen.h>
#include <camera/camera_api.h>
#include <camera/camera_encoder.h>
#include <camera/camera_3a.h>


main()
{
camera_handle_t cameraHandle;
int err;




// Must use Screen to use the Camera library
screen_context_t context;
screen_window_t window;


// Create a screen context and a window
   screen_create_context(&context, 0);

//Create the viewfinder window to put our viewfinder (image buffers) into
int screenUsage = SCREEN_USAGE_NATIVE;
// depends on your display - this requires that you know what formats are
// supported
int screenFormat = SCREEN_FORMAT_RGBA8888; 

//Create a window for filling in with color
screen_create_window(&window, context);

screen_set_window_property_iv(window, SCREEN_PROPERTY_USAGE, &screenUsage);
screen_set_window_property_iv(window, SCREEN_PROPERTY_FORMAT, &screenFormat);

// Create buffers for the window - mem associated with window
screen_create_window_buffers(window, 1);

screen_buffer_t screenBuffer;
int size[2];
int blitInfo[] = {SCREEN_BLIT_COLOR, (int) 0xff00ffff, SCREEN_BLIT_END};


// Get a  buffer
screen_get_window_property_pv(window, SCREEN_PROPERTY_RENDER_BUFFERS,
                                      (void **)&screenBuffer);
// Fill the window a nice torquiose shade
screen_fill(context, screenBuffer, blitInfo);

// Get the size of the buffer
screen_get_window_property_iv(window, SCREEN_PROPERTY_BUFFER_SIZE, size);

// Post the changes to the display to position 0, 0
// and with the screen size of 720, 1280
int rects[4] = {0,0,720,1280};
screen_post_window(window, screenBuffer, 1, rects, 0);

// Set the group ID
char groupId[64];
snprintf(groupId, sizeof(groupId), "camera_unique_group_%x_%x",
                         getpid(), cameraHandle);
screen_create_window_group(window, groupId);
screen_flush_context(context, SCREEN_WAIT_IDLE);


//Connect to the camera configured as CAMERA_UNIT_1
camera_open(CAMERA_UNIT_1, CAMERA_MODE_RW | CAMERA_MODE_ROLL,
            &cameraHandle);

// Set the viewfinder image stream mode
camera_set_vf_mode(cameraHandle, CAMERA_VFMODE_VIDEO);

// Set viewfinder window properties and pass the group ID
char windowId[64];
snprintf(windowId, sizeof(windowId), "viewfinder_window_%x", cameraHandle);
camera_set_vf_property(cameraHandle,
                       CAMERA_IMGPROP_WIN_GROUPID, groupId,
                       CAMERA_IMGPROP_WIN_ID, windowId);

// Start the viewfinder
camera_start_viewfinder(cameraHandle, NULL, NULL, NULL);

// After you start the viewfinder, a SCREEN_CREATE event is
// emitted when the viewfinder window is joined with the parent window.
// You need to catch the create event
screen_event_t screenEvent;
bool gotEvent = false;
screen_window_t viewfinder;
// This is the viewfinder (image buffer contents) window's that's passed to you.
screen_window_t *viewfinderHandle = NULL; 
screen_stream_t *streamHandle =NULL;
viewfinderHandle = &viewfinder;

if (viewfinderHandle) {
       *viewfinderHandle = NULL;
}

if (streamHandle){
       *streamHandle = NULL;
}


// Application is created to hold the event so it's local to the application
// Screen doesn't manage this for you.
if (screen_create_event(&screenEvent) == -1) {
    err = errno;
    printf("Failed to create screen event: err = %d\n", err);
    return;
}

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

    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_PROPERTY) {
        screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_OBJECT_TYPE,
                                     &objectType);
    }
    else if (eventType == SCREEN_EVENT_CREATE) {
        // Got the Create event
        screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_OBJECT_TYPE,
                                     &objectType);
        //Get a reference to the Stream object from the Camera service
        if (streamHandle && (objectType == SCREEN_OBJECT_TYPE_STREAM)) {
            screen_get_event_property_pv(screenEvent, SCREEN_PROPERTY_STREAM,
                                         (void**)streamHandle);
        }
        else if (viewfinderHandle && (objectType == SCREEN_OBJECT_TYPE_WINDOW)) {
            screen_get_event_property_pv(screenEvent, SCREEN_PROPERTY_WINDOW,
                                         (void**)viewfinderHandle);
        }
        //You now have references to the memory that Screen allocated for you.
        //You're responsible for cleaning this up!
        if ((!streamHandle || *streamHandle) && 
            (!viewfinderHandle || *viewfinderHandle)) {
        
            break;
        }
    }
    else if (eventType == SCREEN_EVENT_CLOSE) {
                // Got a close event, make sure it is for a window close
                if (screen_get_event_property_iv(screenEvent,
                                                 SCREEN_PROPERTY_OBJECT_TYPE,
                                                 &objectType) == - 1) {
                    err = errno;
                    printf("Failed to get object type of screen event: err = %d\n", err);
                    break;
                }
                if (objectType == SCREEN_OBJECT_TYPE_WINDOW) {
                    // Get child window handle
                    if (screen_get_event_property_pv(screenEvent, SCREEN_PROPERTY_WINDOW,
                                                     (void **)&viewfinderHandle) == -1) {
                        err = errno;
                        printf("Failed to get screen event window: err = %d\n", err);
                        break;
                    }
                    // Call destroy on this window handle to free a small bit
                    // of memory allocated on our behalf or you'll have a
                    // memory leak
                    if (screen_destroy_window(*viewfinderHandle) == -1) {
                        err = errno;
                        printf("Failed to destroy window remnants: err = %d\n", err);
                        break;
                    }
                }// end else if
    }//end eventType == SCREEN_EVENT_CLOSE
}


//Ensure you do cleanup so there isn't a memory leak;
screen_destroy_event(screenEvent);


// We should have a handle to the viewfinder window. Let's
// make it visible.
int vsize[2] = {1280, 720 };
int vposition[2]={0,0};
screen_set_window_property_iv(*viewfinderHandle, SCREEN_PROPERTY_SIZE, vsize);
screen_set_window_property_iv(*viewfinderHandle, SCREEN_PROPERTY_BUFFER_SIZE, vsize);
screen_set_window_property_iv(*viewfinderHandle, SCREEN_PROPERTY_SOURCE_SIZE, vsize);
screen_set_window_property_iv(*viewfinderHandle, SCREEN_PROPERTY_POSITION, vposition);

//Make the window visible by changing the focus.
int visible = 1;
screen_set_window_property_iv(*viewfinderHandle, SCREEN_PROPERTY_VISIBLE, &visible);

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

//Press x to stop streaming the video
int exitExample = 0;
static char userString[80];
while (exitExample == 0) {
     printf("\tPress x to exit:\n");
     fgets(userString, sizeof(userString), stdin);
     if ( (userString[0] == 'x') || (userString[0] == 'X') ) {
       exitExample = 1;
     }
}


//Stop streaming image buffers from the camera
camera_stop_viewfinder(cameraHandle);
//Deallocate resources and release the handle from the camera
camera_close(cameraHandle);

screen_destroy_window(viewfinder);
screen_destroy_window(window);
screen_destroy_context(context);

return 0;
}