I.MX6 HDMI support in v4.2

Krzysztof Hałasa khalasa at piap.pl
Tue Sep 15 01:24:55 PDT 2015


> Testing Linux v4.2 + PLL5 DTS patch (for HDMI output with enabled LVDS).
> Using mplayer with YUV420 (DRM Xvideo would probably work with packed
> UYVY-alike formats but I need YUV420 because H.264 decoder produces it).
> The driver is git://ftp.arm.linux.org.uk/~rmk/xf86-video-armada.git,
> branch unstable-devel, and it uses
> git://ftp.arm.linux.org.uk/~rmk/libdrm-armada.git/.
>
> 	IMX DRM Xvideo output:
>
> Only unscaled video: no color (luminance is good but the color
> components are green). The driver doesn't use color information.

1024 x 768 for now. I noticed a strange thing: XvShmPutImage() usually
takes (much) less than 4 milliseconds, but every 315 frames, it takes
much longer (when started, it takes 1259 frames). The following is with
constant image, i.e., not altered between frames. Source attached (one
may need to change xv_port variable).

Now what?

XVideo: using adaptor #0, port 85
Image ID 30323449 1024x768 data_size 1179648 num_planes 3 pitches 1024 512 512 data 0x76b86000
Frame#  frame count from the last such event
  vvvv   vvvv
  1259   1259: Took 0.665640667 s, avg 0.000530765 s
  1574    315: Took 0.501529334 s, avg 0.000743380 s
  1889    315: Took 0.496656667 s, avg 0.000882432 s
  2204    315: Took 0.496726667 s, avg 0.000981782 s
  2519    315: Took 0.496672333 s, avg 0.001056277 s
  2834    315: Took 0.496910000 s, avg 0.001114301 s
  3149    315: Took 0.497260667 s, avg 0.001160832 s
  3464    315: Took 0.499651334 s, avg 0.001199600 s
  3779    315: Took 0.495202334 s, avg 0.001230718 s
  4094    315: Took 0.499449667 s, avg 0.001258081 s
  4409    315: Took 0.525910333 s, avg 0.001287535 s
  4724    315: Took 0.510400000 s, avg 0.001309786 s
  5039    315: Took 0.541753334 s, avg 0.001335467 s
  5354    315: Took 0.537526666 s, avg 0.001357350 s
  5669    315: Took 0.542006000 s, avg 0.001377594 s
  5984    315: Took 0.539530333 s, avg 0.001395288 s
  6299    315: Took 0.541836000 s, avg 0.001411578 s
  6614    315: Took 0.541556333 s, avg 0.001426275 s
  6929    315: Took 0.543209666 s, avg 0.001439874 s
  7244    315: Took 0.540764000 s, avg 0.001451956 s
  7559    315: Took 0.512616666 s, avg 0.001459303 s
  7874    315: Took 0.541380000 s, avg 0.001469720 s
  8189    315: Took 0.535251333 s, avg 0.001478584 s
  8504    315: Took 0.536773334 s, avg 0.001486975 s
  8819    315: Took 0.521379000 s, avg 0.001493018 s
  9134    315: Took 0.492112667 s, avg 0.001495438 s
  9449    315: Took 0.616766000 s, avg 0.001510886 s
  9764    315: Took 0.492945666 s, avg 0.001512657 s
 10079    315: Took 0.492615000 s, avg 0.001514286 s
 10394    315: Took 0.493068000 s, avg 0.001515858 s
 10709    315: Took 0.496838000 s, avg 0.001517693 s
 11024    315: Took 0.516352333 s, avg 0.001521193 s
 11339    315: Took 0.500899333 s, avg 0.001523138 s
 11654    315: Took 0.494034334 s, avg 0.001524386 s
 11969    315: Took 0.492401000 s, avg 0.001525430 s
 12284    315: Took 0.505440000 s, avg 0.001527485 s
 12599    315: Took 0.511242666 s, avg 0.001529898 s
 12914    315: Took 0.493489333 s, avg 0.001530816 s

With etnaviv Xvideo, the effect is similar but much worse:

> 	rmk/drm-etnaviv-devel:
>
> With unscaled video, the only visible problem is tearing in the middle
> of the screen (unability to sync with screen refresh).

XVideo: using adaptor #1, port 90
Image ID 30323449 1024x768 data_size 1179648 num_planes 3 pitches 1024 512 512 data 0x76b8d000
  1259   1259: Took 18.864969669 s, avg 0.014974047 s
  1574    315: Took 20.758470002 s, avg 0.025159601 s
  1889    315: Took 20.720458336 s, avg 0.031929827 s
  2204    315: Took 20.831572669 s, avg 0.036815999 s
  2519    315: Took 20.807073336 s, avg 0.040470906 s
  2834    315: Took 20.789431003 s, avg 0.043307485 s
  3149    315: Took 20.809190003 s, avg 0.045582932 s
  3464    315: Took 20.803870003 s, avg 0.047443189 s
  3779    315: Took 20.798422002 s, avg 0.048991905 s
  4094    315: Took 20.809182336 s, avg 0.050304985 s
  4409    315: Took 20.812659336 s, avg 0.051431326 s
  4724    315: Took 20.816828669 s, avg 0.052408363 s
  5039    315: Took 20.814890002 s, avg 0.053262894 s
  5354    315: Took 20.803809003 s, avg 0.054014822 s
  5669    315: Took 20.798233669 s, avg 0.054682176 s
  5984    315: Took 20.809503336 s, avg 0.055281168 s
  6299    315: Took 20.814339002 s, avg 0.055821065 s
  6614    315: Took 20.812699003 s, avg 0.056309294 s
  6929    315: Took 20.800363670 s, avg 0.056751361 s
  7244    315: Took 20.814518669 s, avg 0.057156941 s
  7559    315: Took 20.814902002 s, avg 0.057528773 s
  7874    315: Took 20.814914336 s, avg 0.057870859 s
  8189    315: Took 20.803919669 s, avg 0.058185288 s
  8504    315: Took 20.807010336 s, avg 0.058476760 s
  8819    315: Took 20.855880669 s, avg 0.058752983 s
  9134    315: Took 20.809301669 s, avg 0.059005029 s
  9449    315: Took 26.004653003 s, avg 0.059790071 s
  9764    315: Took 20.796989002 s, avg 0.059991163 s
 10079    315: Took 20.798379670 s, avg 0.060179803 s
 10394    315: Took 20.809240335 s, avg 0.060358055 s
 10709    315: Took 20.814655003 s, avg 0.060526351 s
 11024    315: Took 20.803836002 s, avg 0.060684046 s
-- 
Krzysztof Halasa

Industrial Research Institute for Automation and Measurements PIAP
Al. Jerozolimskie 202, 02-486 Warsaw, Poland

#include <ctype.h>
#include <signal.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/shm.h>
#include <sys/time.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xv.h>
#include <X11/extensions/Xvlib.h>
#include <X11/extensions/XShm.h>

#define IMAGE_FORMAT_NAME "planar I420"
#define IMAGE_FORMAT      0x30323449
#define PIXEL_FORMAT      AV_PIX_FMT_YUV420P

static Display *display;
static Window window;
static XShmSegmentInfo shminfo;
static XvImage *image;
static GC gc;
static unsigned w, h;
static unsigned xv_port = 90;

static void test_xv(void)
{
	fprintf(stderr, "Image ID %X %ux%u data_size %u num_planes %u pitches %u %u %u data %p\n",
			image->id, image->width, image->height, image->data_size, image->num_planes, image->pitches[0], image->pitches[1], image->pitches[2], image->data);

	struct timespec ts;
	if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
		fprintf(stderr, "clock_gettime(MONOTONIC) failed: %m\n");
		exit(1);
	}

	unsigned long long prev_t = (unsigned long long)ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
	unsigned long long start_t = prev_t;
	unsigned count = 0, prev_count = 0;

	while (1) {
		memset(image->data, count, image->data_size);
		XvShmPutImage(display, xv_port, window, gc, image, 0, 0, w, h, 0, 0, w, h, True);

		if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
			fprintf(stderr, "clock_gettime(MONOTONIC) failed: %m\n");
			exit(1);
		}
		unsigned long long t = (unsigned long long)ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
		if (t - prev_t > 4 * 1000 * 1000) {
			fprintf(stdout, "%6u %6u: Took %llu.%09llu s, avg %llu.%09llu s\n",
					count, count - prev_count,
					(t - prev_t) / (1000 * 1000 * 1000),
					(t - prev_t) % (1000 * 1000 * 1000),
					(t - start_t) / (count + 1) / (1000 * 1000 * 1000),
					(t - start_t) / (count + 1) % (1000 * 1000 * 1000));
			prev_count = count;
		}
		prev_t = t;
		count++;
	}
}

int main(void)
{
	display = XOpenDisplay(NULL);
	if (!display) {
		fprintf(stderr, "Unable to open X11 display\n");
		exit(1);
	}

	unsigned int screen = DefaultScreen(display);
	Window rdw;
	unsigned rb, rd;
	int x, y;
	if (!XGetGeometry(display, XRootWindow(display, screen), &rdw, &x, &y, &w, &h, &rb, &rd)) {
		fprintf(stderr, "Unable to get root window geometry\n");
		exit(1);
	}

	fprintf(stderr, "Creating %ux%u window at %ux%u\n", w, h, x, y);
	window = XCreateSimpleWindow(display, XRootWindow(display, screen), x, y, w, h, 0, 0, 0);

	static XClassHint class_hints = {.res_name = "Xvideo test", .res_class = "XVideo test"};
	XSetClassHint(display, window, &class_hints);

	XMapWindow(display, window);
	XStoreName(display, window, "Xvideo test");
	XSetIconName(display, window, "Xvideo test");
	XFlush(display);

	// Search for Xvideo ports
	XvAdaptorInfo *info;
	unsigned adaptors;
	if (XvQueryAdaptors(display, window, &adaptors, &info) != Success) {
		fprintf(stderr, "No XVideo adaptors found\n");
		exit(1);
	}

	unsigned cnt, found = 0;
	for (cnt = 0; cnt < adaptors; cnt++) {
		XvAdaptorInfo *adaptor = &info[cnt];
#if 0
		fprintf(stderr, "Xv adaptor: %s, port base %lu, count %lu, type 0x%X, %lu format(s)\n",
				adaptor->name, adaptor->base_id, adaptor->num_ports, adaptor->type, adaptor->num_formats);
		for (unsigned cnt1 = 0; cnt1 < adaptor->num_formats; cnt1++) {
			XvFormat *format = &adaptor->formats[cnt1];
			fprintf(stderr, "   depth %u, visual ID 0x%lX\n", format->depth, format->visual_id);
		}
#endif

		for (unsigned cnt1 = 0; cnt1 < adaptor->num_ports; cnt1++) {
			int num_formats;
			XvImageFormatValues *image_formats = XvListImageFormats(display, adaptor->base_id + cnt1, &num_formats);
			for (int cnt2 = 0; cnt2 < num_formats; cnt2++) {
				XvImageFormatValues *image_format = &image_formats[cnt2];

#if 0
				fprintf(stderr, "   Port %lu: type %i ID 0x%X (%c%c%c%c) byte order %i\n",
						adaptor->base_id + cnt1, image_format->type, image_format->id,
						isprint( image_format->id        & 0xFF) ?  image_format->id        & 0xFF : '?',
						isprint((image_format->id >>  8) & 0xFF) ? (image_format->id >>  8) & 0xFF : '?',
						isprint((image_format->id >> 16) & 0xFF) ? (image_format->id >> 16) & 0xFF : '?',
						isprint((image_format->id >> 24) & 0xFF) ? (image_format->id >> 24) & 0xFF : '?',
						image_format->byte_order);
#endif

				if (!found) {
					if (xv_port) {
						if (xv_port >= adaptor->base_id && xv_port < adaptor->base_id + adaptor->num_ports) {
							if (!(adaptor->type & XvImageMask))
								fprintf(stderr, "XVideo port %u doesn't have XvImageMask capability\n", xv_port);
							else if (image_format->id == IMAGE_FORMAT)
								found = 1;
							else if (xv_port == adaptor->base_id + adaptor->num_ports - 1)
								fprintf(stderr, "XVideo port %u doesn't support " IMAGE_FORMAT_NAME "image format\n", xv_port);
						}
					} else {
						if (adaptor->type & XvImageMask && adaptor->num_ports && image_format->id == IMAGE_FORMAT) {
							xv_port = adaptor->base_id;
							found = 1;
						}
					}
					if (found)
						fprintf(stderr, "XVideo: using adaptor #%u, port %u\n", cnt, xv_port);
				}
			}

			XFree(image_formats);
		}
	}
	XvFreeAdaptorInfo(info);

	if (!found) {
		fprintf(stderr, "No valid XVideo adaptor found\n");
		exit(1);
	}

	image = XvShmCreateImage(display, xv_port, IMAGE_FORMAT, NULL, w, h, &shminfo);
	shminfo.shmid = shmget(IPC_PRIVATE, image->data_size, IPC_CREAT | 0777);
	if (shminfo.shmid < 0)
		exit(1);

	shminfo.shmaddr = image->data = shmat(shminfo.shmid, 0, 0);
	if (shminfo.shmaddr == (void*) -1)
		exit(1);

	shminfo.readOnly = False;

	if (!XShmAttach(display, &shminfo))
		exit(1);

	gc = XCreateGC(display, window, 0, 0);
	test_xv();
	exit(0);
}



More information about the linux-arm-kernel mailing list