g3dvl: Update XvMC unit tests.
This commit is contained in:
parent
3122f2bebe
commit
6fca18696d
|
@ -15,11 +15,11 @@ static Status Validate
|
|||
unsigned int width,
|
||||
unsigned int height,
|
||||
int flags,
|
||||
int *found_port,
|
||||
int *chroma_format,
|
||||
int *mc_type
|
||||
)
|
||||
{
|
||||
unsigned int found_port = 0;
|
||||
unsigned int found_surface = 0;
|
||||
XvAdaptorInfo *adaptor_info;
|
||||
unsigned int num_adaptors;
|
||||
|
@ -30,22 +30,24 @@ static Status Validate
|
|||
|
||||
assert(display && chroma_format);
|
||||
|
||||
*found_port = 0;
|
||||
|
||||
ret = XvQueryAdaptors(display, XDefaultRootWindow(display), &num_adaptors, &adaptor_info);
|
||||
if (ret != Success)
|
||||
return ret;
|
||||
|
||||
/* Scan through all adaptors looking for this port and surface */
|
||||
for (i = 0; i < num_adaptors && !found_port; ++i)
|
||||
for (i = 0; i < num_adaptors && !*found_port; ++i)
|
||||
{
|
||||
/* Scan through all ports of this adaptor looking for our port */
|
||||
for (j = 0; j < adaptor_info[i].num_ports && !found_port; ++j)
|
||||
for (j = 0; j < adaptor_info[i].num_ports && !*found_port; ++j)
|
||||
{
|
||||
/* If this is our port, scan through all its surfaces looking for our surface */
|
||||
if (adaptor_info[i].base_id + j == port)
|
||||
{
|
||||
XvMCSurfaceInfo *surface_info;
|
||||
|
||||
found_port = 1;
|
||||
*found_port = 1;
|
||||
surface_info = XvMCListSurfaceTypes(display, adaptor_info[i].base_id, &num_types);
|
||||
|
||||
if (surface_info)
|
||||
|
@ -75,7 +77,7 @@ static Status Validate
|
|||
|
||||
XvFreeAdaptorInfo(adaptor_info);
|
||||
|
||||
if (!found_port)
|
||||
if (!*found_port)
|
||||
return XvBadPort;
|
||||
if (!found_surface)
|
||||
return BadMatch;
|
||||
|
@ -127,6 +129,7 @@ static enum vlFormat FormatToVL(int xvmc_format)
|
|||
|
||||
Status XvMCCreateContext(Display *display, XvPortID port, int surface_type_id, int width, int height, int flags, XvMCContext *context)
|
||||
{
|
||||
int found_port;
|
||||
int chroma_format;
|
||||
int mc_type;
|
||||
Status ret;
|
||||
|
@ -140,8 +143,10 @@ Status XvMCCreateContext(Display *display, XvPortID port, int surface_type_id, i
|
|||
if (!context)
|
||||
return XvMCBadContext;
|
||||
|
||||
ret = Validate(display, port, surface_type_id, width, height, flags, &chroma_format, &mc_type);
|
||||
if (ret != Success)
|
||||
ret = Validate(display, port, surface_type_id, width, height, flags, &found_port, &chroma_format, &mc_type);
|
||||
|
||||
/* XXX: Success and XvBadPort have the same value */
|
||||
if (ret != Success || !found_port)
|
||||
return ret;
|
||||
|
||||
/* XXX: Assumes default screen, should check which screen port is on */
|
||||
|
|
|
@ -2,4 +2,4 @@ test_context
|
|||
test_surface
|
||||
test_blocks
|
||||
test_rendering
|
||||
|
||||
xvmc_bench
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
CFLAGS += -g -Wall -Werror
|
||||
CFLAGS += -g -Wall
|
||||
LDFLAGS +=
|
||||
LIBS += -lXvMCW -lXvMC -lXv
|
||||
|
||||
|
@ -6,7 +6,7 @@ LIBS += -lXvMCW -lXvMC -lXv
|
|||
|
||||
.PHONY = all clean
|
||||
|
||||
all: test_context test_surface test_blocks test_rendering
|
||||
all: test_context test_surface test_blocks test_rendering xvmc_bench
|
||||
|
||||
test_context: test_context.o testlib.o
|
||||
$(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
|
||||
|
@ -20,6 +20,8 @@ test_blocks: test_blocks.o testlib.o
|
|||
test_rendering: test_rendering.o testlib.o
|
||||
$(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
|
||||
|
||||
clean:
|
||||
rm -rf *.o test_context test_surface test_blocks test_rendering
|
||||
xvmc_bench: xvmc_bench.o testlib.o
|
||||
$(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
|
||||
|
||||
clean:
|
||||
rm -rf *.o test_context test_surface test_blocks test_rendering xvmc_bench
|
||||
|
|
|
@ -51,11 +51,6 @@ int main(int argc, char **argv)
|
|||
assert(XvMCCreateBlocks(display, NULL, 1, &blocks) == XvMCBadContext);
|
||||
/* Test 0 blocks */
|
||||
assert(XvMCCreateBlocks(display, &context, 0, &blocks) == BadValue);
|
||||
/* Test too many blocks */
|
||||
/*assert(XvMCCreateBlocks(display, &context, 16384, &blocks) == BadAlloc);*/
|
||||
|
||||
/* Note: No XvMCBadBlock(s) error in spec */
|
||||
|
||||
/* Test valid params */
|
||||
assert(XvMCCreateBlocks(display, &context, min_required_blocks, &blocks) == Success);
|
||||
/* Test context id assigned and correct */
|
||||
|
@ -68,11 +63,6 @@ int main(int argc, char **argv)
|
|||
assert(XvMCCreateMacroBlocks(display, NULL, 1, ¯oblocks) == XvMCBadContext);
|
||||
/* Test 0 macroblocks */
|
||||
assert(XvMCCreateMacroBlocks(display, &context, 0, ¯oblocks) == BadValue);
|
||||
/* Test too many macroblocks */
|
||||
/*assert(XvMCCreateMacroBlocks(display, &context, 16384, ¯oblocks) == BadAlloc);*/
|
||||
|
||||
/* Note: No XvMCBadMacroBlock(s) error in spec */
|
||||
|
||||
/* Test valid params */
|
||||
assert(XvMCCreateMacroBlocks(display, &context, min_required_macroblocks, ¯oblocks) == Success);
|
||||
/* Test context id assigned and correct */
|
||||
|
@ -92,4 +82,3 @@ int main(int argc, char **argv)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,15 +40,14 @@ int main(int argc, char **argv)
|
|||
XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
|
||||
}
|
||||
|
||||
/* Note: XvMCBadContext not a valid return for XvMCCreateContext in the XvMC API, but openChrome driver returns it */
|
||||
/* Note: Nvidia binary driver segfaults on NULL context, halts with debug output on bad port */
|
||||
|
||||
/* Test NULL context */
|
||||
/* XXX: XvMCBadContext not a valid return for XvMCCreateContext in the XvMC API, but openChrome driver returns it */
|
||||
assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, NULL) == XvMCBadContext);
|
||||
/* Test invalid port */
|
||||
assert(XvMCCreateContext(display, port_num + 1, surface_type_id, width, height, XVMC_DIRECT, &context) == XvBadPort);
|
||||
/* XXX: Success and XvBadPort have the same value, if this call actually gets passed the validation step as of now we'll crash later */
|
||||
assert(XvMCCreateContext(display, -1, surface_type_id, width, height, XVMC_DIRECT, &context) == XvBadPort);
|
||||
/* Test invalid surface */
|
||||
assert(XvMCCreateContext(display, port_num, surface_type_id + 1, width, height, XVMC_DIRECT, &context) == BadMatch);
|
||||
assert(XvMCCreateContext(display, port_num, -1, width, height, XVMC_DIRECT, &context) == BadMatch);
|
||||
/* Test invalid flags */
|
||||
assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, -1, &context) == BadValue);
|
||||
/* Test huge width */
|
||||
|
@ -91,4 +90,3 @@ int main(int argc, char **argv)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,38 +1,126 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <error.h>
|
||||
#include "testlib.h"
|
||||
|
||||
#define BLOCK_WIDTH 8
|
||||
#define BLOCK_HEIGHT 8
|
||||
#define BLOCK_SIZE (BLOCK_WIDTH * BLOCK_HEIGHT)
|
||||
#define MACROBLOCK_WIDTH 16
|
||||
#define MACROBLOCK_HEIGHT 16
|
||||
#define MACROBLOCK_WIDTH_IN_BLOCKS (MACROBLOCK_WIDTH / BLOCK_WIDTH)
|
||||
#define MACROBLOCK_HEIGHT_IN_BLOCKS (MACROBLOCK_HEIGHT / BLOCK_HEIGHT)
|
||||
#define BLOCKS_PER_MACROBLOCK 6
|
||||
|
||||
#define INPUT_WIDTH 16
|
||||
#define INPUT_HEIGHT 16
|
||||
#define INPUT_WIDTH_IN_MACROBLOCKS (INPUT_WIDTH / MACROBLOCK_WIDTH)
|
||||
#define INPUT_HEIGHT_IN_MACROBLOCKS (INPUT_HEIGHT / MACROBLOCK_HEIGHT)
|
||||
#define NUM_MACROBLOCKS (INPUT_WIDTH_IN_MACROBLOCKS * INPUT_HEIGHT_IN_MACROBLOCKS)
|
||||
|
||||
#define DEFAULT_OUTPUT_WIDTH INPUT_WIDTH
|
||||
#define DEFAULT_OUTPUT_HEIGHT INPUT_HEIGHT
|
||||
#define DEFAULT_ACCEPTABLE_ERR 0.01
|
||||
|
||||
void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt)
|
||||
{
|
||||
int fail = 0;
|
||||
int i;
|
||||
|
||||
*output_width = DEFAULT_OUTPUT_WIDTH;
|
||||
*output_height = DEFAULT_OUTPUT_WIDTH;
|
||||
*acceptable_error = DEFAULT_ACCEPTABLE_ERR;
|
||||
*prompt = 1;
|
||||
|
||||
for (i = 1; i < argc && !fail; ++i)
|
||||
{
|
||||
if (!strcmp(argv[i], "-w"))
|
||||
{
|
||||
if (sscanf(argv[++i], "%u", output_width) != 1)
|
||||
fail = 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-h"))
|
||||
{
|
||||
if (sscanf(argv[++i], "%u", output_height) != 1)
|
||||
fail = 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-e"))
|
||||
{
|
||||
if (sscanf(argv[++i], "%lf", acceptable_error) != 1)
|
||||
fail = 1;
|
||||
}
|
||||
else if (strcmp(argv[i], "-n"))
|
||||
*prompt = 0;
|
||||
else
|
||||
fail = 1;
|
||||
}
|
||||
|
||||
if (fail)
|
||||
error
|
||||
(
|
||||
1, 0,
|
||||
"Bad argument.\n"
|
||||
"\n"
|
||||
"Usage: %s [options]\n"
|
||||
"\t-w <width>\tOutput width\n"
|
||||
"\t-h <height>\tOutput height\n"
|
||||
"\t-e <error>\tAcceptable margin of error per pixel, from 0 to 1\n"
|
||||
"\t-n\tDon't prompt for quit\n",
|
||||
argv[0]
|
||||
);
|
||||
}
|
||||
|
||||
void Gradient(short *block, unsigned int start, unsigned int stop, int horizontal)
|
||||
{
|
||||
unsigned int x, y;
|
||||
unsigned int range = stop - start;
|
||||
|
||||
if (horizontal)
|
||||
{
|
||||
for (y = 0; y < BLOCK_HEIGHT; ++y)
|
||||
for (x = 0; x < BLOCK_WIDTH; ++x)
|
||||
block[y * BLOCK_WIDTH + x] = (short)(start + range * (x / (float)(BLOCK_WIDTH - 1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y = 0; y < BLOCK_HEIGHT; ++y)
|
||||
for (x = 0; x < BLOCK_WIDTH; ++x)
|
||||
block[y * BLOCK_WIDTH + x] = (short)(start + range * (y / (float)(BLOCK_HEIGHT - 1)));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const unsigned int width = 32, height = 32;
|
||||
const unsigned int mwidth = width / 16, mheight = height / 16;
|
||||
const unsigned int num_macroblocks = mwidth * mheight;
|
||||
const unsigned int num_blocks = num_macroblocks * 6;
|
||||
const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
|
||||
|
||||
int quit = 0;
|
||||
unsigned int output_width;
|
||||
unsigned int output_height;
|
||||
double acceptable_error;
|
||||
int prompt;
|
||||
Display *display;
|
||||
Window root, window;
|
||||
Pixmap framebuffer;
|
||||
XEvent event;
|
||||
const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
|
||||
XvPortID port_num;
|
||||
int surface_type_id;
|
||||
unsigned int is_overlay, intra_unsigned;
|
||||
int colorkey;
|
||||
XvMCContext context;
|
||||
XvMCSurface surface;
|
||||
XvMCBlockArray blocks;
|
||||
XvMCMacroBlockArray macroblocks;
|
||||
unsigned int b, x, y;
|
||||
XvMCBlockArray block_array;
|
||||
XvMCMacroBlockArray mb_array;
|
||||
int mbx, mby, bx, by;
|
||||
XvMCMacroBlock *mb;
|
||||
short *blocks;
|
||||
int quit = 0;
|
||||
|
||||
ParseArgs(argc, argv, &output_width, &output_height, &acceptable_error, &prompt);
|
||||
|
||||
display = XOpenDisplay(NULL);
|
||||
|
||||
if (!GetPort
|
||||
(
|
||||
display,
|
||||
width,
|
||||
height,
|
||||
INPUT_WIDTH,
|
||||
INPUT_HEIGHT,
|
||||
XVMC_CHROMA_FORMAT_420,
|
||||
mc_types,
|
||||
2,
|
||||
|
@ -53,80 +141,126 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
root = XDefaultRootWindow(display);
|
||||
window = XCreateSimpleWindow(display, root, 0, 0, width, height, 0, 0, colorkey);
|
||||
framebuffer = XCreatePixmap(display, root, width, height, 24);
|
||||
window = XCreateSimpleWindow(display, root, 0, 0, output_width, output_height, 0, 0, colorkey);
|
||||
|
||||
assert(XvMCCreateContext(display, port_num, surface_type_id, INPUT_WIDTH, INPUT_HEIGHT, XVMC_DIRECT, &context) == Success);
|
||||
assert(XvMCCreateSurface(display, &context, &surface) == Success);
|
||||
assert(XvMCCreateBlocks(display, &context, NUM_MACROBLOCKS * BLOCKS_PER_MACROBLOCK, &block_array) == Success);
|
||||
assert(XvMCCreateMacroBlocks(display, &context, NUM_MACROBLOCKS, &mb_array) == Success);
|
||||
|
||||
mb = mb_array.macro_blocks;
|
||||
blocks = block_array.blocks;
|
||||
|
||||
for (mby = 0; mby < INPUT_HEIGHT_IN_MACROBLOCKS; ++mby)
|
||||
for (mbx = 0; mbx < INPUT_WIDTH_IN_MACROBLOCKS; ++mbx)
|
||||
{
|
||||
mb->x = mbx;
|
||||
mb->y = mby;
|
||||
mb->macroblock_type = XVMC_MB_TYPE_INTRA;
|
||||
/*mb->motion_type = ;*/
|
||||
/*mb->motion_vertical_field_select = ;*/
|
||||
mb->dct_type = XVMC_DCT_TYPE_FRAME;
|
||||
/*mb->PMV[0][0][0] = ;
|
||||
mb->PMV[0][0][1] = ;
|
||||
mb->PMV[0][1][0] = ;
|
||||
mb->PMV[0][1][1] = ;
|
||||
mb->PMV[1][0][0] = ;
|
||||
mb->PMV[1][0][1] = ;
|
||||
mb->PMV[1][1][0] = ;
|
||||
mb->PMV[1][1][1] = ;*/
|
||||
mb->index = (mby * INPUT_WIDTH_IN_MACROBLOCKS + mbx) * BLOCKS_PER_MACROBLOCK;
|
||||
mb->coded_block_pattern = 0x3F;
|
||||
|
||||
mb++;
|
||||
|
||||
for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS; ++by)
|
||||
for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS; ++bx)
|
||||
{
|
||||
const int start = 16, stop = 235, range = stop - start;
|
||||
|
||||
Gradient
|
||||
(
|
||||
blocks,
|
||||
(short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
|
||||
(short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
|
||||
1
|
||||
);
|
||||
|
||||
blocks += BLOCK_SIZE;
|
||||
}
|
||||
|
||||
for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS / 2; ++by)
|
||||
for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS / 2; ++bx)
|
||||
{
|
||||
const int start = 16, stop = 240, range = stop - start;
|
||||
|
||||
Gradient
|
||||
(
|
||||
blocks,
|
||||
(short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
|
||||
(short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
|
||||
1
|
||||
);
|
||||
|
||||
blocks += BLOCK_SIZE;
|
||||
|
||||
Gradient
|
||||
(
|
||||
blocks,
|
||||
(short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
|
||||
(short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
|
||||
1
|
||||
);
|
||||
|
||||
blocks += BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
XSelectInput(display, window, ExposureMask | KeyPressMask);
|
||||
XMapWindow(display, window);
|
||||
XSync(display, 0);
|
||||
|
||||
assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
|
||||
assert(XvMCCreateSurface(display, &context, &surface) == Success);
|
||||
assert(XvMCCreateBlocks(display, &context, num_blocks, &blocks) == Success);
|
||||
assert(XvMCCreateMacroBlocks(display, &context, num_macroblocks, ¯oblocks) == Success);
|
||||
|
||||
for (b = 0; b < 6; ++b)
|
||||
{
|
||||
for (y = 0; y < 8; ++y)
|
||||
{
|
||||
for (x = 0; x < 8; ++x)
|
||||
{
|
||||
blocks.blocks[b * 64 + y * 8 + x] = 0xFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (y = 0; y < mheight; ++y)
|
||||
{
|
||||
for (x = 0; x < mwidth; ++x)
|
||||
{
|
||||
macroblocks.macro_blocks[y * mwidth + x].x = x;
|
||||
macroblocks.macro_blocks[y * mwidth + x].y = y;
|
||||
macroblocks.macro_blocks[y * mwidth + x].index = (y * mwidth + x) * 6;
|
||||
macroblocks.macro_blocks[y * mwidth + x].macroblock_type = XVMC_MB_TYPE_INTRA;
|
||||
macroblocks.macro_blocks[y * mwidth + x].coded_block_pattern = 0x3F;
|
||||
macroblocks.macro_blocks[y * mwidth + x].dct_type = XVMC_DCT_TYPE_FRAME;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test NULL context */
|
||||
assert(XvMCRenderSurface(display, NULL, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, 1, 0, ¯oblocks, &blocks) == XvMCBadContext);
|
||||
assert(XvMCRenderSurface(display, NULL, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadContext);
|
||||
/* Test NULL surface */
|
||||
assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, NULL, NULL, NULL, 0, 1, 0, ¯oblocks, &blocks) == XvMCBadSurface);
|
||||
assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, NULL, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadSurface);
|
||||
/* Test bad picture structure */
|
||||
assert(XvMCRenderSurface(display, &context, 0, &surface, NULL, NULL, 0, 1, 0, ¯oblocks, &blocks) == BadValue);
|
||||
assert(XvMCRenderSurface(display, &context, 0, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == BadValue);
|
||||
/* Test valid params */
|
||||
assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, num_macroblocks, 0, ¯oblocks, &blocks) == Success);
|
||||
assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == Success);
|
||||
|
||||
/* Test NULL surface */
|
||||
assert(XvMCPutSurface(display, NULL, window, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == XvMCBadSurface);
|
||||
assert(XvMCPutSurface(display, NULL, window, 0, 0, INPUT_WIDTH, INPUT_HEIGHT, 0, 0, output_width, output_height, XVMC_FRAME_PICTURE) == XvMCBadSurface);
|
||||
/* Test bad window */
|
||||
/* X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */
|
||||
/* XXX: X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */
|
||||
/*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/
|
||||
/* Test valid params */
|
||||
assert(XvMCPutSurface(display, &surface, framebuffer, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == Success);
|
||||
|
||||
puts("Press any key to continue...");
|
||||
if (prompt)
|
||||
{
|
||||
puts("Press any button to quit...");
|
||||
|
||||
while (!quit)
|
||||
{
|
||||
if (XPending(display) > 0)
|
||||
{
|
||||
XEvent event;
|
||||
|
||||
XNextEvent(display, &event);
|
||||
|
||||
switch (event.type)
|
||||
{
|
||||
case Expose:
|
||||
{
|
||||
XCopyArea
|
||||
/* Test valid params */
|
||||
assert
|
||||
(
|
||||
display,
|
||||
framebuffer,
|
||||
window,
|
||||
XDefaultGC(display, XDefaultScreen(display)),
|
||||
0,
|
||||
0,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
0
|
||||
XvMCPutSurface
|
||||
(
|
||||
display, &surface, window,
|
||||
0, 0, INPUT_WIDTH, INPUT_HEIGHT,
|
||||
0, 0, output_width, output_height,
|
||||
XVMC_FRAME_PICTURE
|
||||
) == Success
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
@ -137,17 +271,17 @@ int main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(XvMCDestroyBlocks(display, &blocks) == Success);
|
||||
assert(XvMCDestroyMacroBlocks(display, ¯oblocks) == Success);
|
||||
assert(XvMCDestroyBlocks(display, &block_array) == Success);
|
||||
assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success);
|
||||
assert(XvMCDestroySurface(display, &surface) == Success);
|
||||
assert(XvMCDestroyContext(display, &context) == Success);
|
||||
|
||||
XFreePixmap(display, framebuffer);
|
||||
XvUngrabPort(display, port_num, CurrentTime);
|
||||
XDestroyWindow(display, window);
|
||||
XCloseDisplay(display);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -85,3 +85,35 @@ int GetPort
|
|||
return found_port;
|
||||
}
|
||||
|
||||
unsigned int align(unsigned int value, unsigned int alignment)
|
||||
{
|
||||
return (value + alignment - 1) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
/* From the glibc manual */
|
||||
int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y)
|
||||
{
|
||||
/* Perform the carry for the later subtraction by updating y. */
|
||||
if (x->tv_usec < y->tv_usec)
|
||||
{
|
||||
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
|
||||
y->tv_usec -= 1000000 * nsec;
|
||||
y->tv_sec += nsec;
|
||||
}
|
||||
if (x->tv_usec - y->tv_usec > 1000000)
|
||||
{
|
||||
int nsec = (x->tv_usec - y->tv_usec) / 1000000;
|
||||
y->tv_usec += 1000000 * nsec;
|
||||
y->tv_sec -= nsec;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the time remaining to wait.
|
||||
* tv_usec is certainly positive.
|
||||
*/
|
||||
result->tv_sec = x->tv_sec - y->tv_sec;
|
||||
result->tv_usec = x->tv_usec - y->tv_usec;
|
||||
|
||||
/* Return 1 if result is negative. */
|
||||
return x->tv_sec < y->tv_sec;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line);
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/XvMClib.h>
|
||||
|
||||
|
@ -34,5 +35,8 @@ int GetPort
|
|||
unsigned int *intra_unsigned
|
||||
);
|
||||
|
||||
#endif
|
||||
unsigned int align(unsigned int value, unsigned int alignment);
|
||||
|
||||
int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,271 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <error.h>
|
||||
#include <sys/time.h>
|
||||
#include "testlib.h"
|
||||
|
||||
#define MACROBLOCK_WIDTH 16
|
||||
#define MACROBLOCK_HEIGHT 16
|
||||
#define BLOCKS_PER_MACROBLOCK 6
|
||||
|
||||
#define DEFAULT_INPUT_WIDTH 720
|
||||
#define DEFAULT_INPUT_HEIGHT 480
|
||||
#define DEFAULT_REPS 100
|
||||
|
||||
#define PIPELINE_STEP_MC 1
|
||||
#define PIPELINE_STEP_CSC 2
|
||||
#define PIPELINE_STEP_SWAP 4
|
||||
|
||||
#define MB_TYPE_I 1
|
||||
#define MB_TYPE_P 2
|
||||
#define MB_TYPE_B 4
|
||||
|
||||
struct Config
|
||||
{
|
||||
unsigned int input_width;
|
||||
unsigned int input_height;
|
||||
unsigned int output_width;
|
||||
unsigned int output_height;
|
||||
unsigned int pipeline;
|
||||
unsigned int mb_types;
|
||||
unsigned int reps;
|
||||
};
|
||||
|
||||
void ParseArgs(int argc, char **argv, struct Config *config)
|
||||
{
|
||||
int fail = 0;
|
||||
int i;
|
||||
|
||||
config->input_width = DEFAULT_INPUT_WIDTH;
|
||||
config->input_height = DEFAULT_INPUT_HEIGHT;
|
||||
config->output_width = 0;
|
||||
config->output_height = 0;
|
||||
config->pipeline = 0;
|
||||
config->mb_types = 0;
|
||||
config->reps = DEFAULT_REPS;
|
||||
|
||||
for (i = 1; i < argc && !fail; ++i)
|
||||
{
|
||||
if (!strcmp(argv[i], "-iw"))
|
||||
{
|
||||
if (sscanf(argv[++i], "%u", &config->input_width) != 1)
|
||||
fail = 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-ih"))
|
||||
{
|
||||
if (sscanf(argv[++i], "%u", &config->input_height) != 1)
|
||||
fail = 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-ow"))
|
||||
{
|
||||
if (sscanf(argv[++i], "%u", &config->output_width) != 1)
|
||||
fail = 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-oh"))
|
||||
{
|
||||
if (sscanf(argv[++i], "%u", &config->output_height) != 1)
|
||||
fail = 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-p"))
|
||||
{
|
||||
char *token = strtok(argv[++i], ",");
|
||||
|
||||
while (token && !fail)
|
||||
{
|
||||
if (!strcmp(token, "mc"))
|
||||
config->pipeline |= PIPELINE_STEP_MC;
|
||||
else if (!strcmp(token, "csc"))
|
||||
config->pipeline |= PIPELINE_STEP_CSC;
|
||||
else if (!strcmp(token, "swp"))
|
||||
config->pipeline |= PIPELINE_STEP_SWAP;
|
||||
else
|
||||
fail = 1;
|
||||
|
||||
if (!fail)
|
||||
token = strtok(NULL, ",");
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[i], "-mb"))
|
||||
{
|
||||
char *token = strtok(argv[++i], ",");
|
||||
|
||||
while (token && !fail)
|
||||
{
|
||||
if (strcmp(token, "i"))
|
||||
config->mb_types |= MB_TYPE_I;
|
||||
else if (strcmp(token, "p"))
|
||||
config->mb_types |= MB_TYPE_P;
|
||||
else if (strcmp(token, "b"))
|
||||
config->mb_types |= MB_TYPE_B;
|
||||
else
|
||||
fail = 1;
|
||||
|
||||
if (!fail)
|
||||
token = strtok(NULL, ",");
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[i], "-r"))
|
||||
{
|
||||
if (sscanf(argv[++i], "%u", &config->reps) != 1)
|
||||
fail = 1;
|
||||
}
|
||||
else
|
||||
fail = 1;
|
||||
}
|
||||
|
||||
if (fail)
|
||||
error
|
||||
(
|
||||
1, 0,
|
||||
"Bad argument.\n"
|
||||
"\n"
|
||||
"Usage: %s [options]\n"
|
||||
"\t-iw <width>\tInput width\n"
|
||||
"\t-ih <height>\tInput height\n"
|
||||
"\t-ow <width>\tOutput width\n"
|
||||
"\t-oh <height>\tOutput height\n"
|
||||
"\t-p <pipeline>\tPipeline to test\n"
|
||||
"\t-mb <mb type>\tMacroBlock types to use\n"
|
||||
"\t-r <reps>\tRepetitions\n\n"
|
||||
"\tPipeline steps: mc,csc,swap\n"
|
||||
"\tMB types: i,p,b\n",
|
||||
argv[0]
|
||||
);
|
||||
|
||||
if (config->output_width == 0)
|
||||
config->output_width = config->input_width;
|
||||
if (config->output_height == 0)
|
||||
config->output_height = config->input_height;
|
||||
if (!config->pipeline)
|
||||
config->pipeline = PIPELINE_STEP_MC | PIPELINE_STEP_CSC | PIPELINE_STEP_SWAP;
|
||||
if (!config->mb_types)
|
||||
config->mb_types = MB_TYPE_I | MB_TYPE_P | MB_TYPE_B;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct Config config;
|
||||
Display *display;
|
||||
Window root, window;
|
||||
const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
|
||||
XvPortID port_num;
|
||||
int surface_type_id;
|
||||
unsigned int is_overlay, intra_unsigned;
|
||||
int colorkey;
|
||||
XvMCContext context;
|
||||
XvMCSurface surface;
|
||||
XvMCBlockArray block_array;
|
||||
XvMCMacroBlockArray mb_array;
|
||||
unsigned int mbw, mbh;
|
||||
unsigned int mbx, mby;
|
||||
unsigned int reps;
|
||||
struct timeval start, stop, diff;
|
||||
double diff_secs;
|
||||
|
||||
ParseArgs(argc, argv, &config);
|
||||
|
||||
mbw = align(config.input_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH;
|
||||
mbh = align(config.input_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT;
|
||||
|
||||
display = XOpenDisplay(NULL);
|
||||
|
||||
if (!GetPort
|
||||
(
|
||||
display,
|
||||
config.input_width,
|
||||
config.input_height,
|
||||
XVMC_CHROMA_FORMAT_420,
|
||||
mc_types,
|
||||
2,
|
||||
&port_num,
|
||||
&surface_type_id,
|
||||
&is_overlay,
|
||||
&intra_unsigned
|
||||
))
|
||||
{
|
||||
XCloseDisplay(display);
|
||||
error(1, 0, "Error, unable to find a good port.\n");
|
||||
}
|
||||
|
||||
if (is_overlay)
|
||||
{
|
||||
Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
|
||||
XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
|
||||
}
|
||||
|
||||
root = XDefaultRootWindow(display);
|
||||
window = XCreateSimpleWindow(display, root, 0, 0, config.output_width, config.output_height, 0, 0, colorkey);
|
||||
|
||||
assert(XvMCCreateContext(display, port_num, surface_type_id, config.input_width, config.input_width, XVMC_DIRECT, &context) == Success);
|
||||
assert(XvMCCreateSurface(display, &context, &surface) == Success);
|
||||
assert(XvMCCreateBlocks(display, &context, mbw * mbh * BLOCKS_PER_MACROBLOCK, &block_array) == Success);
|
||||
assert(XvMCCreateMacroBlocks(display, &context, mbw * mbh, &mb_array) == Success);
|
||||
|
||||
for (mby = 0; mby < mbh; ++mby)
|
||||
for (mbx = 0; mbx < mbw; ++mbx)
|
||||
{
|
||||
mb_array.macro_blocks[mby * mbw + mbx].x = mbx;
|
||||
mb_array.macro_blocks[mby * mbw + mbx].y = mby;
|
||||
mb_array.macro_blocks[mby * mbw + mbx].macroblock_type = XVMC_MB_TYPE_INTRA;
|
||||
/*mb->motion_type = ;*/
|
||||
/*mb->motion_vertical_field_select = ;*/
|
||||
mb_array.macro_blocks[mby * mbw + mbx].dct_type = XVMC_DCT_TYPE_FRAME;
|
||||
/*mb->PMV[0][0][0] = ;
|
||||
mb->PMV[0][0][1] = ;
|
||||
mb->PMV[0][1][0] = ;
|
||||
mb->PMV[0][1][1] = ;
|
||||
mb->PMV[1][0][0] = ;
|
||||
mb->PMV[1][0][1] = ;
|
||||
mb->PMV[1][1][0] = ;
|
||||
mb->PMV[1][1][1] = ;*/
|
||||
mb_array.macro_blocks[mby * mbw + mbx].index = (mby * mbw + mbx) * BLOCKS_PER_MACROBLOCK;
|
||||
mb_array.macro_blocks[mby * mbw + mbx].coded_block_pattern = 0x3F;
|
||||
}
|
||||
|
||||
XSelectInput(display, window, ExposureMask | KeyPressMask);
|
||||
XMapWindow(display, window);
|
||||
XSync(display, 0);
|
||||
|
||||
gettimeofday(&start, NULL);
|
||||
|
||||
for (reps = 0; reps < config.reps; ++reps)
|
||||
{
|
||||
if (config.pipeline & PIPELINE_STEP_MC)
|
||||
{
|
||||
assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, mbw * mbh, 0, &mb_array, &block_array) == Success);
|
||||
assert(XvMCFlushSurface(display, &surface) == Success);
|
||||
}
|
||||
if (config.pipeline & PIPELINE_STEP_CSC)
|
||||
assert(XvMCPutSurface(display, &surface, window, 0, 0, config.input_width, config.input_height, 0, 0, config.output_width, config.output_height, XVMC_FRAME_PICTURE) == Success);
|
||||
}
|
||||
|
||||
gettimeofday(&stop, NULL);
|
||||
|
||||
timeval_subtract(&diff, &stop, &start);
|
||||
diff_secs = (double)diff.tv_sec + (double)diff.tv_usec / 1000000.0;
|
||||
|
||||
printf("XvMC Benchmark\n");
|
||||
printf("Input: %u,%u\nOutput: %u,%u\n", config.input_width, config.input_height, config.output_width, config.output_height);
|
||||
printf("Pipeline: ");
|
||||
if (config.pipeline & PIPELINE_STEP_MC)
|
||||
printf("|mc|");
|
||||
if (config.pipeline & PIPELINE_STEP_CSC)
|
||||
printf("|csc|");
|
||||
if (config.pipeline & PIPELINE_STEP_SWAP)
|
||||
printf("|swap|");
|
||||
printf("\n");
|
||||
printf("Reps: %u\n", config.reps);
|
||||
printf("Total time: %.2lf (%.2lf reps / sec)\n", diff_secs, config.reps / diff_secs);
|
||||
|
||||
assert(XvMCDestroyBlocks(display, &block_array) == Success);
|
||||
assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success);
|
||||
assert(XvMCDestroySurface(display, &surface) == Success);
|
||||
assert(XvMCDestroyContext(display, &context) == Success);
|
||||
|
||||
XvUngrabPort(display, port_num, CurrentTime);
|
||||
XDestroyWindow(display, window);
|
||||
XCloseDisplay(display);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue