Commit d76376f1 authored by Austin Yuan's avatar Austin Yuan

refine test program: putsurface/h264encode

Signed-off-by: default avatarAustin Yuan <shengquan.yuan@intel.com>
parent 867fcd64
......@@ -26,7 +26,7 @@
* it is a real program to show how VAAPI encoding work,
* It does H264 element stream level encoding on auto-generated YUV data
*
* gcc -o h264encode h264encode -lva -lva-x11 -I /usr/include/va
* gcc -o h264encode h264encode -lva -lva-x11 -I/usr/include/va
* ./h264encode -w <width> -h <height> -n <frame_num>
*
*/
......@@ -54,6 +54,8 @@ if (va_status != VA_STATUS_SUCCESS) { \
exit(1); \
}
#include "loadsurface.h"
#define SURFACE_NUM 18 /* 16 surfaces for src, 2 surface for reconstructed/reference */
static Display *x11_display;
......@@ -67,11 +69,15 @@ static int win_height;
static int coded_fd;
static char coded_file[256];
#define CODEDBUF_NUM 5
static VABufferID coded_buf[CODEDBUF_NUM];
static int frame_display = 0; /* display the frame during encoding */
static int frame_width=352, frame_height=288;
static int frame_rate = 30;
static int frame_count = 1000;
static int frame_count = 400;
static int intra_count = 30;
static int frame_bitrate = 64000;
static int frame_bitrate = 8000000; /* 8M */
static int initial_qp = 15;
static int minimal_qp = 0;
......@@ -85,11 +91,13 @@ static int upload_source_YUV_once_for_all()
int i;
for (i=0; i<SURFACE_NUM-2; i++) {
upload_surafce(va_dpy, surface_id[i], box_width, row_shift, 0);
printf("\rLoading data into surface %d.....", i);
upload_surface(va_dpy, surface_id[i], box_width, row_shift, 0);
row_shift++;
if (row_shift==(2*box_width)) row_shift= 0;
}
printf("\n", i);
return 0;
}
......@@ -102,13 +110,19 @@ static int save_coded_buf(VABufferID coded_buf, int current_frame, int frame_ski
VAStatus va_status;
va_status = vaMapBuffer(va_dpy,coded_buf,&coded_p);
CHECK_VASTATUS(va_status,"vaMapBuffer");
coded_size = *((unsigned long *) coded_p); /* first DWord is the coded video size */
coded_offset = *((unsigned long *) (coded_p + 4)); /* second DWord is byte offset */
wrt_size = write(coded_fd,coded_p+coded_offset,coded_size);
assert(wrt_size==coded_size);
if (wrt_size != coded_size) {
fprintf(stderr, "Trying to write %d bytes, but actual %d bytes\n",
coded_size, wrt_size);
exit(1);
}
vaUnmapBuffer(va_dpy,coded_buf);
printf("\r "); /* return back to startpoint */
switch (current_frame % 4) {
case 0:
......@@ -133,23 +147,22 @@ static int save_coded_buf(VABufferID coded_buf, int current_frame, int frame_ski
printf("(%06d bytes coded)",coded_size);
if (frame_skipped)
printf("(SKipped)");
printf(" ");
return;
}
static int display_surface(int current_frame, int *exit_encode)
static int display_surface(int frame_id, int *exit_encode)
{
Window win = display_win;
XEvent event;
VAStatus va_status;
if (current_frame == 0) {
if (win == 0) { /* display reconstructed surface */
win_width = frame_width;
win_height = frame_height;
}
if (win == 0) { /* display reconstructed surface */
win = XCreateSimpleWindow(x11_display, RootWindow(x11_display, 0), 0, 0,
frame_width, frame_height, 0, 0, WhitePixel(x11_display, 0));
XMapWindow(x11_display, win);
......@@ -158,6 +171,11 @@ static int display_surface(int current_frame, int *exit_encode)
display_win = win;
}
va_status = vaPutSurface(va_dpy, surface_id[frame_id], win,
0,0, frame_width, frame_height,
0,0, win_width, win_height,
NULL,0,0);
*exit_encode = 0;
while(XPending(x11_display)) {
XNextEvent(x11_display, &event);
......@@ -174,11 +192,7 @@ static int display_surface(int current_frame, int *exit_encode)
win_height = event.xconfigure.height;
}
}
va_status = vaPutSurface(va_dpy, surface_id[current_frame], win,
0,0, frame_width, frame_height,
0,0, win_width, win_height,
NULL,0,0);
return;
}
......@@ -195,7 +209,6 @@ enum {
static int do_h264_encoding(void)
{
VAEncSequenceParameterBufferH264 seq_h264;
VAEncPictureParameterBufferH264 pic_h264;
VAEncSliceParameterBuffer slice_h264;
VAStatus va_status;
......@@ -203,14 +216,20 @@ static int do_h264_encoding(void)
int codedbuf_size;
VASurfaceStatus surface_status;
int src_surface, dst_surface, ref_surface;
int putsurface=0, frame_skipped = 0;
int exit_encode = 0;
int frame_skipped = 0;
int i;
va_status = vaCreateSurfaces(va_dpy,frame_width, frame_height,
VA_RT_FORMAT_YUV420, SURFACE_NUM, &surface_id[0]);
CHECK_VASTATUS(va_status, "vaCreateSurfaces");
/* upload RAW YUV data into all surfaces */
upload_source_YUV_once_for_all();
codedbuf_size = (frame_width * frame_height * 400) / (16*16);
src_surface = 0;
/* the last two frames are reference/reconstructed frame */
dst_surface = SURFACE_NUM - 1;
ref_surface = SURFACE_NUM - 2;
......@@ -220,9 +239,12 @@ static int do_h264_encoding(void)
CHECK_VASTATUS(va_status,"vaBeginPicture");
if (i == 0) {
VAEncSequenceParameterBufferH264 seq_h264 = {0};
VABufferID seq_param_buf;
seq_h264.level_idc = SH_LEVEL_3;
seq_h264.picture_width_in_mbs = frame_width;
seq_h264.picture_height_in_mbs = frame_height;
seq_h264.picture_width_in_mbs = frame_width / 16;
seq_h264.picture_height_in_mbs = frame_height / 16;
seq_h264.bits_per_second = frame_bitrate;
seq_h264.frame_rate = frame_rate;
seq_h264.initial_qp = initial_qp;
......@@ -242,14 +264,6 @@ static int do_h264_encoding(void)
va_status = vaCreateBuffer(va_dpy,context_id,VAEncCodedBufferType,
codedbuf_size, 1, NULL, &coded_buf);
/* if a frame is skipped, current frame still use last reference frame */
if (frame_skipped == 0) {
/* swap ref/dst */
int tmp = dst_surface;
dst_surface = ref_surface;
ref_surface = tmp;
}
pic_h264.reference_picture = surface_id[ref_surface];
pic_h264.reconstructed_picture= surface_id[dst_surface];
pic_h264.coded_buf = coded_buf;
......@@ -261,41 +275,54 @@ static int do_h264_encoding(void)
sizeof(pic_h264),1,&pic_h264,&pic_param_buf);
CHECK_VASTATUS(va_status,"vaCreateBuffer");;
va_status = vaRenderPicture(va_dpy,context_id, &pic_param_buf, 1);
CHECK_VASTATUS(va_status,"vaRenderPicture");
/* one frame, one slice */
slice_h264.start_row_number = 0;
slice_h264.slice_height = frame_height/16; /* Measured by MB */
slice_h264.slice_flags.bits.is_intra = i % intra_count;
slice_h264.slice_flags.bits.is_intra = ((i % intra_count) == 0);
slice_h264.slice_flags.bits.disable_deblocking_filter_idc = 0;
va_status = vaCreateBuffer(va_dpy,context_id,VAEncSliceParameterBufferType,
sizeof(slice_h264),1,&slice_h264,&slice_param_buf);
CHECK_VASTATUS(va_status,"vaCreateBuffer");;
va_status = vaRenderPicture(va_dpy,context_id, &pic_param_buf, 1);
CHECK_VASTATUS(va_status,"vaRenderPicture");;
va_status = vaRenderPicture(va_dpy,context_id, &slice_param_buf, 1);
CHECK_VASTATUS(va_status,"vaRenderPicture");;
CHECK_VASTATUS(va_status,"vaRenderPicture");
va_status = vaEndPicture(va_dpy,context_id);
CHECK_VASTATUS(va_status,"vaEndPicture");;
va_status = vaSyncSurface(va_dpy, surface_id[0]);
CHECK_VASTATUS(va_status,"vaSyncSurface");;
va_status = vaSyncSurface(va_dpy, surface_id[src_surface]);
CHECK_VASTATUS(va_status,"vaSyncSurface");
surface_status = 0;
va_status = vaQuerySurfaceStatus(va_dpy, surface_id[src_surface],&surface_status);
frame_skipped = (surface_status & VASurfaceSkipped);
save_coded_buf(coded_buf, i, frame_skipped);
/* should display reconstructed frame, but just diplay source frame */
display_surface(src_surface, &exit_encode);
if (exit_encode)
frame_count = i;
if (frame_display) {
int exit_encode = 0;
display_surface(src_surface, &exit_encode);
if (exit_encode)
frame_count = i;
}
/* use next surface */
src_surface++;
if (src_surface == (SURFACE_NUM - 2))
src_surface = 0;
/* if a frame is skipped, current frame still use last reference frame */
if (frame_skipped == 0) {
/* swap ref/dst */
int tmp = dst_surface;
dst_surface = ref_surface;
ref_surface = tmp;
}
}
return 0;
......@@ -312,7 +339,7 @@ int main(int argc,char **argv)
char c;
strcpy(coded_file, "/tmp/demo.264");
while ((c =getopt(argc,argv,"w:h:n:p:f:r:q:s:o:?") ) != EOF) {
while ((c =getopt(argc,argv,"w:h:n:p:f:r:q:s:o:d?") ) != EOF) {
switch (c) {
case 'w':
frame_width = atoi(optarg);
......@@ -338,6 +365,9 @@ int main(int argc,char **argv)
case 's':
minimal_qp = atoi(optarg);
break;
case 'd':
frame_display = 1;
break;
case 'o':
strcpy(coded_file, optarg);
break;
......@@ -351,7 +381,7 @@ int main(int argc,char **argv)
printf(" -r bit rate\n");
printf(" -q initial QP\n");
printf(" -s maximum QP\n");
printf(" -s coded file\n");
printf(" -o coded file\n");
exit(0);
}
}
......@@ -415,8 +445,10 @@ int main(int argc,char **argv)
printf("Coded %d frames, %dx%d, save the coded file into %s\n",
frame_count, frame_width, frame_height, coded_file);
do_h264_encoding();
printf("\n\n");
vaDestroySurfaces(va_dpy,&surface_id[0],3);
vaDestroySurfaces(va_dpy,&surface_id[0],SURFACE_NUM);
vaDestroyConfig(va_dpy,config_id);
vaDestroyContext(va_dpy,context_id);
......
../putsurface/loadsurface.h
\ No newline at end of file
......@@ -23,6 +23,8 @@
*/
/* gcc -o putsurface putsurface.c -lva -lva-x11 -I/usr/include/va */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
......@@ -37,8 +39,8 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <va/va.h>
#include <va/va_x11.h>
#include "va.h"
#include "va_x11.h"
#include <assert.h>
......@@ -75,7 +77,7 @@ static Display *x11_display;
static VADisplay *va_dpy;
static int multi_thread=0;
static int put_pixmap = 0;
static int test_clip = 1;
static int test_clip = 0;
static int display_field = VA_FRAME_PICTURE;
static int check_event = 1;
static int verbose=0;
......@@ -185,6 +187,17 @@ static VASurfaceID get_next_free_surface(int *index)
return surface_id[i];
}
/*
* Helper function for profiling purposes
*/
static unsigned long get_tick_count(void)
{
struct timeval tv;
if (gettimeofday(&tv, NULL))
return 0;
return tv.tv_usec/1000+tv.tv_sec*1000;
}
static int putsurface_thread(void *data)
{
int width=win_width, height=win_height;
......@@ -198,7 +211,9 @@ static int putsurface_thread(void *data)
int index = 0;
Bool is_event;
XEvent event;
unsigned int frame_num=0, start_time, putsurface_time;
VARectangle cliprects[2]; /* client supplied clip list */
if (win == win_thread0) {
printf("Enter into thread0\n\n");
pixmap = pixmap_thread0;
......@@ -218,7 +233,8 @@ static int putsurface_thread(void *data)
printf("vaPutSurface into a Window directly\n\n");
draw = win;
}
putsurface_time = 0;
while (!quit) {
VASurfaceID surface_id = VA_INVALID_SURFACE;
......@@ -228,13 +244,39 @@ static int putsurface_thread(void *data)
if (verbose) printf("Thread %x Display surface 0x%p,\n", (unsigned int)win, (void *)surface_id);
upload_surface(va_dpy, surface_id, box_width, row_shift, display_field);
start_time = get_tick_count();
vaStatus = vaPutSurface(va_dpy, surface_id, draw,
0,0,surface_width,surface_height,
0,0,width,height,
NULL,0,display_field);
(test_clip==0)?NULL:&cliprects[0],
(test_clip==0)?0:2,
display_field);
CHECK_VASTATUS(vaStatus,"vaPutSurface");
putsurface_time += (get_tick_count() - start_time);
if ((frame_num % 0xff) == 0) {
fprintf(stderr, "%.2f FPS \r", 256000.0 / (float)putsurface_time);
putsurface_time = 0;
if (test_clip) {
srand((unsigned)time(NULL));
cliprects[0].x = (rand() % width);
cliprects[0].y = (rand() % height);
cliprects[0].width = (rand() % (width - cliprects[0].x));
cliprects[0].height = (rand() % (height - cliprects[0].y));
cliprects[1].x = (rand() % width);
cliprects[1].y = (rand() % height);
cliprects[1].width = (rand() % (width - cliprects[1].x));
cliprects[1].height = (rand() % (height - cliprects[1].y));
printf("\nTest clip (%d,%d, %d x %d) and (%d,%d, %d x %d) \n",
cliprects[0].x, cliprects[0].y, cliprects[0].width, cliprects[0].height,
cliprects[1].x, cliprects[1].y, cliprects[1].width, cliprects[1].height);
}
}
if (put_pixmap)
XCopyArea(x11_display, pixmap, win, context, 0, 0, width, height, 0, 0);
......@@ -242,7 +284,7 @@ static int putsurface_thread(void *data)
if (check_event) {
pthread_mutex_lock(&gmutex);
is_event =XCheckWindowEvent(x11_display, win, StructureNotifyMask|KeyPressMask,&event);
is_event = XCheckWindowEvent(x11_display, win, StructureNotifyMask|KeyPressMask,&event);
pthread_mutex_unlock(&gmutex);
if (is_event) {
/* bail on any focused key press */
......@@ -262,6 +304,8 @@ static int putsurface_thread(void *data)
row_shift++;
if (row_shift==(2*box_width)) row_shift= 0;
frame_num++;
}
pthread_exit(NULL);
......@@ -277,7 +321,7 @@ int main(int argc,char **argv)
char c;
int i;
while ((c =getopt(argc,argv,"w:h:d:f:tep?nv") ) != EOF) {
while ((c =getopt(argc,argv,"w:h:d:f:tcep?nv") ) != EOF) {
switch (c) {
case '?':
printf("putsurface <options>\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment