UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Adventurer
Adventurer
686 Views
Registered: ‎09-05-2018

VCU Framework - resolution change event

Jump to solution

Hello all

Is it possible to an application running the VCU TRD 2018.3 framework to get event/interrupt when the HDMI In is disconnected or when the resolution is changed ( 1080p to 4k60) or p30 to 60 etc.

 

Thanks

 

0 Kudos
1 Solution

Accepted Solutions
Highlighted
Xilinx Employee
Xilinx Employee
665 Views
Registered: ‎08-01-2007

Re: VCU Framework - resolution change event

Jump to solution

This is not really a VCU question, but more of an HDMI question.

HDMI Rx uses the V4L2 framework as documented on the HDMI RX Wiki Page.

HDMI Rx will issue an interrupt when the resolution changes or the HDMI input unplugged.

Chris
Video Design Hub | Embedded SW Support

---------------------------------------------------------------------------
Don’t forget to Reply, Kudo, and Accept as Solution.
---------------------------------------------------------------------------
3 Replies
Highlighted
Xilinx Employee
Xilinx Employee
666 Views
Registered: ‎08-01-2007

Re: VCU Framework - resolution change event

Jump to solution

This is not really a VCU question, but more of an HDMI question.

HDMI Rx uses the V4L2 framework as documented on the HDMI RX Wiki Page.

HDMI Rx will issue an interrupt when the resolution changes or the HDMI input unplugged.

Chris
Video Design Hub | Embedded SW Support

---------------------------------------------------------------------------
Don’t forget to Reply, Kudo, and Accept as Solution.
---------------------------------------------------------------------------
Adventurer
Adventurer
634 Views
Registered: ‎09-05-2018

Re: VCU Framework - resolution change event

Jump to solution
Thanks for your input
0 Kudos
Adventurer
Adventurer
337 Views
Registered: ‎09-05-2018

Re: VCU Framework - resolution change event

Jump to solution

Sample of code for the  community

compile:

aarch64-linux-gnu-gcc -O2 -W -Wall -std=gnu99 -Wno-unused-variable -Wno-unused-function -Wno-unused-parameter -g -c -o m2m.o m2m.c
aarch64-linux-gnu-gcc -o m2m m2m.o -lrt

/*
 *  V4L2 probe video
 *
 *  This program can be used and distributed without restrictions.
 *
 * This program is based on the examples provided with the V4L2 API
 * see https://linuxtv.org/docs.php for more information
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include <getopt.h>             /* getopt_long() */

#include <fcntl.h>              /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

#include <linux/videodev2.h>

#define CLEAR(x) memset(&(x), 0, sizeof(x))

enum io_method {
        IO_METHOD_READ,
        IO_METHOD_MMAP,
        IO_METHOD_USERPTR,
};

struct buffer {
        void   *start;
        size_t  length;
};

static char            *dev_name;
static char            *sub_dev_name;
static enum io_method   io = IO_METHOD_MMAP;
static int              fd = -1;
static int              sub_fd = -1;
struct buffer          *buffers;
struct buffer          *buffers_out;
static unsigned int     n_buffers;
static unsigned int     n_buffers_out;
static int              m2m_enabled;
static char            *out_filename;
static FILE            *out_fp;
static int              force_format;
static int              frame_count = 70;
static char            *in_filename;
static FILE            *in_fp;

static void errno_exit(const char *s)
{
        fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));
        exit(EXIT_FAILURE);
}

static int xioctl(int fh, int request, void *arg)
{
        int r;

        do {
                r = ioctl(fh, request, arg);
        } while (-1 == r && EINTR == errno);

        return r;
}



static void uninit_device(void)
{
}


static void init_device_inp(void)
{

        struct v4l2_event_subscription sub;

        memset(&sub, 0, sizeof(sub));

        sub.type = V4L2_EVENT_SOURCE_CHANGE;
        ioctl(sub_fd, VIDIOC_SUBSCRIBE_EVENT, &sub);

}

static void init_device(void)
{
        struct v4l2_capability cap;
        struct v4l2_cropcap cropcap;
        struct v4l2_crop crop;
        struct v4l2_format fmt;
        unsigned int min;

        if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &cap)) {
                if (EINVAL == errno) {
                        fprintf(stderr, "%s is no V4L2 device\n",
                                 dev_name);
                        exit(EXIT_FAILURE);
                } else {
                        errno_exit("VIDIOC_QUERYCAP");
                }
        }
/*
 * capability:
 *  V4L2_CAP_VIDEO_CAPTURE_MPLANE|
 *  V4L2_CAP_STREAMING|
 *  V4L2_CAP_DEVICE_CAPS|
 *  V4L2_CAP_EXT_PIX_FORMAT
 * device_caps
 *  V4L2_CAP_VIDEO_CAPTURE_MPLANE|
 *  V4L2_CAP_STREAMING|
 *  V4L2_CAP_EXT_PIX_FORMAT
 *
*/
        fprintf(stderr, "caps returned %04x\n", cap.capabilities);
        if (!(cap.capabilities & (V4L2_CAP_VIDEO_CAPTURE))
        		&&
			!(cap.capabilities & (V4L2_CAP_VIDEO_CAPTURE_MPLANE))
        	)
        {
                fprintf(stderr, "%s is no video capture device\n",
                         dev_name);
                exit(EXIT_FAILURE);
        }

        init_device_inp();

}

static void close_device(void)
{
        if (-1 == close(fd))
                errno_exit("close");

        fd = -1;
}

static void open_device(void)
{
        struct stat st;

        if (-1 == stat(dev_name, &st)) {
                fprintf(stderr, "Cannot identify '%s': %d, %s\n",
                         dev_name, errno, strerror(errno));
                exit(EXIT_FAILURE);
        }

        if (!S_ISCHR(st.st_mode)) {
                fprintf(stderr, "%s is not a device", dev_name);
                exit(EXIT_FAILURE);
        }

        fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);

        if (-1 == fd) {
                fprintf(stderr, "Cannot open '%s': %d, %s\n",
                         dev_name, errno, strerror(errno));
                exit(EXIT_FAILURE);
        }
}

static void open_sub_device(void)
{
        struct stat st;

        if (-1 == stat(sub_dev_name, &st)) {
                fprintf(stderr, "Cannot identify '%s': %d, %s\n",
                         dev_name, errno, strerror(errno));
                exit(EXIT_FAILURE);
        }

        if (!S_ISCHR(st.st_mode)) {
                fprintf(stderr, "%s is not a device", dev_name);
                exit(EXIT_FAILURE);
        }

        sub_fd = open(sub_dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);

        if (-1 == sub_fd) {
                fprintf(stderr, "Cannot open '%s': %d, %s\n",
                         dev_name, errno, strerror(errno));
                exit(EXIT_FAILURE);
        }
}

static void handle_sub_event(void)
{
        struct v4l2_event ev;

        while (!ioctl(sub_fd, VIDIOC_DQEVENT, &ev)) {
            switch (ev.type) {
            case V4L2_EVENT_SOURCE_CHANGE:
                fprintf(stderr, "Source changed\n");

                //stop_capture(V4L2_BUF_TYPE_VIDEO_CAPTURE);
                //unmap_buffers(buffers, n_buffers);

                //fprintf(stderr, "Unmapped all buffers\n");
                //free_buffers_mmap(V4L2_BUF_TYPE_VIDEO_CAPTURE);

                //init_mmap(V4L2_BUF_TYPE_VIDEO_CAPTURE, &buffers, &n_buffers);

                //start_capturing_mmap(V4L2_BUF_TYPE_VIDEO_CAPTURE, buffers, n_buffers);
                break;
            case V4L2_EVENT_EOS:
                fprintf(stderr, "EOS\n");
                break;
            }
        }

}

static void mainloop(void)
{
        unsigned int count;

        count = frame_count;

        //while (count-- > 0) {
        while (count > 0)
        {
                for (;;) {
                        fd_set fds[3];
                        fd_set *rd_fds = &fds[0]; /* for capture */
                        fd_set *ex_fds = &fds[1]; /* for event */
                        fd_set *wr_fds = &fds[2]; /* for output */
                        struct timeval tv;
                        int r;
/*
                        if (rd_fds) {
                            FD_ZERO(rd_fds);
                            FD_SET(fd, rd_fds);
                            FD_SET(sub_fd, rd_fds);
                        }
*/
                        if (ex_fds) {
                            FD_ZERO(ex_fds);
                            //FD_SET(fd, ex_fds);
                            FD_SET(sub_fd, ex_fds);
                        }

/*                        if (wr_fds) {
                            FD_ZERO(wr_fds);
                            FD_SET(fd, wr_fds);
                            FD_SET(sub_fd, wr_fds);
                        }
*/
                        /* Timeout. */
                        tv.tv_sec = 10;
                        tv.tv_usec = 0;

                        //r = select(sub_fd + 1, rd_fds, wr_fds, ex_fds, &tv);
                        r = select(sub_fd + 1, NULL, NULL, ex_fds, &tv);

                        if (-1 == r) {
                                if (EINTR == errno)
                                        continue;
                                errno_exit("select");
                        }

                        if (0 == r) {
                                fprintf(stderr, "select timeout\n");
                                //exit(EXIT_FAILURE);
                        }

#if 0
                        if (rd_fds && FD_ISSET(fd, rd_fds)) {
                            fprintf(stderr, "Reading\n");
                            if (read_frame(V4L2_BUF_TYPE_VIDEO_CAPTURE, buffers, n_buffers))
                                break;
                        }
                        if (wr_fds && FD_ISSET(fd, wr_fds)) {
                            fprintf(stderr, "Writing\n");
                            if (read_frame(V4L2_BUF_TYPE_VIDEO_OUTPUT, buffers_out, n_buffers_out))
                                break;
                        }
#endif
                        if  (r>0)
                        {
                        	fprintf(stderr, "Something happens on socket\n");
                        	if (ex_fds && FD_ISSET(sub_fd, ex_fds))
                        	{
                            fprintf(stderr, "Exception\n");
                            handle_sub_event();
                        	}
                        }
                        /* EAGAIN - continue select loop. */
                }
        }
}

static void usage(FILE *fp, int argc, char **argv)
{
        fprintf(fp,
                 "Usage: %s [options]\n\n"
                 "Version 1.3\n"
                 "Options:\n"
                 "-d | --device name   Video device name [%s]\n"
                 "-s | --subdevice name   Video sub device name [%s] \n"
                 "-h | --help          Print this message\n"
                 "",
                 argv[0], dev_name, dev_name);
}

static const char short_options[] = "d:s:";

static const struct option
long_options[] = {
        { "device", required_argument, NULL, 'd' },
        { "subdevice", required_argument, NULL, 's' },
        { "help",   no_argument,       NULL, 'h' },
        { 0, 0, 0, 0 }
};

int main(int argc, char **argv)
{
        dev_name = "/dev/video0";
        sub_dev_name = "/dev/v4l-subdev1";

        for (;;) {
                int idx;
                int c;

                c = getopt_long(argc, argv,
                                short_options, long_options, &idx);

                if (-1 == c)
                        break;

                switch (c) {
                case 0: /* getopt_long() flag */
                        break;

                case 'd':
                        dev_name = optarg;
                        break;

                case 's':
                        sub_dev_name = optarg;
                        break;

                case 'h':
                        usage(stdout, argc, argv);
                        exit(EXIT_SUCCESS);


                default:
                        usage(stderr, argc, argv);
                        exit(EXIT_FAILURE);
                }
        }

        open_device();
        open_sub_device();
        init_device();
        mainloop();
        uninit_device();
        close_device();
        fprintf(stderr, "\n");
        return 0;
}