0

Question: How do I write video stream from Raspberry Pi camera to HDMI connected display?

Answer: see below

Mich
  • 3,188
  • 4
  • 37
  • 85

1 Answers1

1

My system: Raspberry Pi3, Raspbian Jessie distribution VisualGDB and VisualStudio 2015

Spending a few hours putting together various test code from different posts, I'm posting this compiled test code for the community to use. It works ~ 15fps with 1200x720p color video output.

Sources: https://raspberrypi.stackexchange.com/questions/7092/display-a-test-pattern-by-writing-the-frame-buffer-and-then-clear-it

https://visualgdb.com/tutorials/raspberry/camera/

NOTES: VisualGDB has some issues with Sysroot syncing, when I ran the built-in operation from Visual Studio, it copied a bunch of headers with size 0. Instead, I manually copied the /opt/vc folder to C:\SysGCC\raspberry\arm-linux-gnueabihf\sysroot directly

I also had to copy libbcm_host.so (along with libraspicam.so.0.1 as in the linked tutorial) from /opt/vc/lib to local build/Debug/src folder,

And add =/opt/vc/include to includes (= indicates local sysroom directory) And bcm_host to library names.

NOTE2: Either Raspbian distro or the compiler do not like while(1) loops, so if you replace the for(...) loop for drawing frames with a while(1) without any exit conditions, you will get a black screen for output. Probable cause is the optimizer, good practice is to just avoid having infinite loops without an exit condition altogether.

NOTE3: If using HDMI output to monitor with less than 1280x720 resolution (less than camera video stream), some issues may occur, looking for someone to edit the code for smaller screens. Older versions of RPi with Composite video output are also not tested.

Thanks,

#include <stdio.h>
#include <syslog.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include "interface\vmcs_host\vc_dispmanx_types.h"
#include <bcm_host.h>
#include "raspicam.h"
#include <iostream>


typedef struct
{
    DISPMANX_DISPLAY_HANDLE_T   display;
    DISPMANX_MODEINFO_T         info;
    void                        *image;
    DISPMANX_UPDATE_HANDLE_T    update;
    DISPMANX_RESOURCE_HANDLE_T  resource;
    DISPMANX_ELEMENT_HANDLE_T   element;
    uint32_t                    vc_image_ptr;

} RECT_VARS_T;

int main(int argc, char **argv) 
{
    RECT_VARS_T vars;
    VC_RECT_T src_rect;
    VC_RECT_T dst_rect;
    VC_DISPMANX_ALPHA_T alpha = { 
        static_cast<DISPMANX_FLAGS_ALPHA_T>(DISPMANX_FLAGS_ALPHA_FROM_SOURCE | DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS),
        255, /*alpha 0->255*/
        0
    };

    bcm_host_init();

    vars.display = vc_dispmanx_display_open(0);
    vc_dispmanx_display_get_info(vars.display, &vars.info);

    //Grab Camera feed
    raspicam::RaspiCam v_camera; //camera object
    //Open camera 
    std::cout << "Opening Camera..." << std::endl;
    if (!v_camera.open()) 
    {
        std::cerr << "Error opening camera" << std::endl; 
        return -1;
    }
    //may need to wait a while until camera stabilizes

    int cam_width = v_camera.getWidth();
    int cam_height = v_camera.getHeight();

    vars.image = calloc(1, cam_width * cam_height * 3);
    vars.resource = vc_dispmanx_resource_create( VC_IMAGE_RGB888,
        cam_width,
        cam_height,
        &vars.vc_image_ptr);

    vc_dispmanx_rect_set(&dst_rect, 0, 0, cam_width, cam_height);
    vars.update = vc_dispmanx_update_start(10);
    vars.element = vc_dispmanx_element_add( vars.update,
        vars.display,
        2000, // layer
        &dst_rect,
        vars.resource,
        &src_rect, //may not need this
        DISPMANX_PROTECTION_NONE,
        &alpha,
        NULL, // clamp
        static_cast<DISPMANX_TRANSFORM_T>(0));

    //Draw 50 frames to screen
    for (int i = 0; i < 50; i++)
    {    
        vc_dispmanx_resource_write_data( vars.resource,
            VC_IMAGE_RGB888,
            cam_width * 3,
            vars.image,
            &dst_rect);

        unsigned char* fbp = static_cast<unsigned char*>(vars.image);   
        v_camera.grab();
        v_camera.retrieve(fbp, raspicam::RASPICAM_FORMAT_RGB);//get camera image
        vc_dispmanx_update_submit_sync(vars.update); 
    }

    int ret = vc_dispmanx_resource_delete(vars.resource);
    vc_dispmanx_display_close(vars.display);

    return true;
}

If you want to perform any image processing, just write directly using fbp pointer inside the loop, for example (not the most efficient method)

int location_cam = 0;
for (int x = 200; x < 300; x++)
{       
    for (int y = 200; y < 300; y++)
    {
        location_cam = (x) * (3) + (y) * cam_width * 3;
        *(fbp + location_cam) = 255;        //red
        *(fbp + location_cam + 1) = 0;     //green
        *(fbp + location_cam + 2) = 0;    //blue
    }
}
Community
  • 1
  • 1
Mich
  • 3,188
  • 4
  • 37
  • 85
  • Please post to the answer in the answer section so that the question can remain. As it stands now somebody visiting this page won't know what problem you were solving. – takendarkk Mar 31 '17 at 21:21