diff options
-rw-r--r-- | test/encode/h264encode.c | 118 | ||||
l--------- | test/encode/loadsurface.h | 1 | ||||
-rw-r--r-- | test/putsurface/putsurface.c | 64 |
3 files changed, 130 insertions, 53 deletions
diff --git a/test/encode/h264encode.c b/test/encode/h264encode.c index 4a4d914..46f1ff6 100644 --- a/test/encode/h264encode.c +++ b/test/encode/h264encode.c @@ -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); diff --git a/test/encode/loadsurface.h b/test/encode/loadsurface.h new file mode 120000 index 0000000..fb38e2f --- /dev/null +++ b/test/encode/loadsurface.h @@ -0,0 +1 @@ +../putsurface/loadsurface.h
\ No newline at end of file diff --git a/test/putsurface/putsurface.c b/test/putsurface/putsurface.c index 46ca227..335368a 100644 --- a/test/putsurface/putsurface.c +++ b/test/putsurface/putsurface.c @@ -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"); |