Op 18-12-12 13:04, Maarten Lankhorst schreef:
> Op 18-12-12 11:42, Christian König schreef:
>> On 18.12.2012 09:18, Maarten Lankhorst wrote:
>>> Writemask was XY instead of YZ (thanks to calim for spotting it).
>>>
>>> The pixel calculation resulted in the pixel always being off by one.
>>> If y was .5:
>>>
>>> y' = round(y) + 0.5 = 1.5
>>>
>>> Fixing this also means the LRP function has to swap the pixels it, since
>>> it's now the other way around for top/bottom.
>>>
>>> WIth these fixes only chroma for top and bottom pixel rows are wrongly 
>>> interpolated
>>> in my test program:
>> Sounds good, but what's the reason that first and last row is interpolated 
>> wrong? Just some issues with the border color/wrap handling?
> If I had to guess it interpolates the first and last row, rather than using 
> the exact value of that line for the top/bottom chroma samples
> there. So it's just border handling sampling from both surfaces that's wrong 
> I think.
>
> As you can see in the diff below, it repeats the cbcr[1] value for cbcr[0], 
> similar for cbcr[63] and cbcr[62]:
>>> --- nvidia
>>> +++ nouveau
>>> @@ -1,4 +1,4 @@
>>> -YCbCr[0] = 00c080
>>> +YCbCr[0] = 00b070
>>>   YCbCr[1] = 00b070
>>>   YCbCr[2] = 029050
>>>   YCbCr[3] = 207050
>>> @@ -61,4 +61,4 @@
>>>   YCbCr[60] = 0c5070
>>>   YCbCr[61] = c05090
>>>   YCbCr[62] = 0e70b0
>>> -YCbCr[63] = e080c0
>>> +YCbCr[63] = e070b0
>>>
>>> Signed-off-by: Maarten Lankhorst <[email protected]>
>> Reviewed-by: Christian König <[email protected]>
> Thanks, will commit.
>
> The program I used for testing is attached.
Now it is!
> Also I seem to be getting a lockup if I convert  that program to use YV12 
> format instead, nouveau requires the interlaced buffer handling for vdec,
> and disables support for progressive video buffers. Would probably also need 
> the separate patch, for fixing up vl_video_buffer_surfaces.
>
> ~Maarten

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <X11/Xlib.h>
#include <vdpau/vdpau.h>
#include <vdpau/vdpau_x11.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
#define ok(a) do { ret = a; if (ret != VDP_STATUS_OK) { fprintf(stderr, "%s:%u %u %s\n", __FUNCTION__, __LINE__, ret, vdp_get_error_string(ret)); exit(1); } } while (0)

VdpGetProcAddress * vdp_get_proc_address;
VdpGetErrorString * vdp_get_error_string;
VdpGetApiVersion * vdp_get_api_version;
VdpGetInformationString * vdp_get_information_string;
VdpDeviceDestroy * vdp_device_destroy;
VdpGenerateCSCMatrix * vdp_generate_csc_matrix;
VdpVideoSurfaceQueryCapabilities * vdp_video_surface_query_capabilities;
VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities * vdp_video_surface_query_get_put_bits_y_cb_cr_capabilities;
VdpVideoSurfaceCreate * vdp_video_surface_create;
VdpVideoSurfaceDestroy * vdp_video_surface_destroy;
VdpVideoSurfaceGetParameters * vdp_video_surface_get_parameters;
VdpVideoSurfaceGetBitsYCbCr * vdp_video_surface_get_bits_y_cb_cr;
VdpVideoSurfacePutBitsYCbCr * vdp_video_surface_put_bits_y_cb_cr;
VdpOutputSurfaceQueryCapabilities * vdp_output_surface_query_capabilities;
VdpOutputSurfaceQueryGetPutBitsNativeCapabilities * vdp_output_surface_query_get_put_bits_native_capabilities;
VdpOutputSurfaceQueryPutBitsIndexedCapabilities * vdp_output_surface_query_put_bits_indexed_capabilities;
VdpOutputSurfaceQueryPutBitsYCbCrCapabilities * vdp_output_surface_query_put_bits_y_cb_cr_capabilities;
VdpOutputSurfaceCreate * vdp_output_surface_create;
VdpOutputSurfaceDestroy * vdp_output_surface_destroy;
VdpOutputSurfaceGetParameters * vdp_output_surface_get_parameters;
VdpOutputSurfaceGetBitsNative * vdp_output_surface_get_bits_native;
VdpOutputSurfacePutBitsNative * vdp_output_surface_put_bits_native;
VdpOutputSurfacePutBitsIndexed * vdp_output_surface_put_bits_indexed;
VdpOutputSurfacePutBitsYCbCr * vdp_output_surface_put_bits_y_cb_cr;
VdpBitmapSurfaceQueryCapabilities * vdp_bitmap_surface_query_capabilities;
VdpBitmapSurfaceCreate * vdp_bitmap_surface_create;
VdpBitmapSurfaceDestroy * vdp_bitmap_surface_destroy;
VdpBitmapSurfaceGetParameters * vdp_bitmap_surface_get_parameters;
VdpBitmapSurfacePutBitsNative * vdp_bitmap_surface_put_bits_native;
VdpOutputSurfaceRenderOutputSurface * vdp_output_surface_render_output_surface;
VdpOutputSurfaceRenderBitmapSurface * vdp_output_surface_render_bitmap_surface;
VdpDecoderQueryCapabilities * vdp_decoder_query_capabilities;
VdpDecoderCreate * vdp_decoder_create;
VdpDecoderDestroy * vdp_decoder_destroy;
VdpDecoderGetParameters * vdp_decoder_get_parameters;
VdpDecoderRender * vdp_decoder_render;
VdpVideoMixerQueryFeatureSupport * vdp_video_mixer_query_feature_support;
VdpVideoMixerQueryParameterSupport * vdp_video_mixer_query_parameter_support;
VdpVideoMixerQueryAttributeSupport * vdp_video_mixer_query_attribute_support;
VdpVideoMixerQueryParameterValueRange * vdp_video_mixer_query_parameter_value_range;
VdpVideoMixerQueryAttributeValueRange * vdp_video_mixer_query_attribute_value_range;
VdpVideoMixerCreate * vdp_video_mixer_create;
VdpVideoMixerSetFeatureEnables * vdp_video_mixer_set_feature_enables;
VdpVideoMixerSetAttributeValues * vdp_video_mixer_set_attribute_values;
VdpVideoMixerGetFeatureSupport * vdp_video_mixer_get_feature_support;
VdpVideoMixerGetFeatureEnables * vdp_video_mixer_get_feature_enables;
VdpVideoMixerGetParameterValues * vdp_video_mixer_get_parameter_values;
VdpVideoMixerGetAttributeValues * vdp_video_mixer_get_attribute_values;
VdpVideoMixerDestroy * vdp_video_mixer_destroy;
VdpVideoMixerRender * vdp_video_mixer_render;
VdpPresentationQueueTargetDestroy * vdp_presentation_queue_target_destroy;
VdpPresentationQueueCreate * vdp_presentation_queue_create;
VdpPresentationQueueDestroy * vdp_presentation_queue_destroy;
VdpPresentationQueueSetBackgroundColor * vdp_presentation_queue_set_background_color;
VdpPresentationQueueGetBackgroundColor * vdp_presentation_queue_get_background_color;
VdpPresentationQueueGetTime * vdp_presentation_queue_get_time;
VdpPresentationQueueDisplay * vdp_presentation_queue_display;
VdpPresentationQueueBlockUntilSurfaceIdle * vdp_presentation_queue_block_until_surface_idle;
VdpPresentationQueueQuerySurfaceStatus * vdp_presentation_queue_query_surface_status;
VdpPreemptionCallbackRegister * vdp_preemption_callback_register;
VdpPresentationQueueTargetCreateX11 * vdp_presentation_queue_target_create_x11;

static void load_vdpau(VdpDevice dev);

static const int input_width = 1440;
static const int input_height = 64;
static const int output_width = 1440;
static const int output_height = 64;

VdpDevice dev;

static inline uint64_t gettime(void)
{
	struct timespec ts;
	clock_gettime(CLOCK_REALTIME, &ts);
	return ts.tv_sec * 1000 + ts.tv_nsec / 1000000ULL;
}

static void test(VdpVideoMixer mixer, VdpVideoSurface surf, VdpOutputSurface osurf)
{
	char *cbcr;
	uint32_t *out;
	int i, j;
	void *data[3];
	uint32_t len[3] = { input_width, input_width, 0 };
	VdpStatus ret;
	VdpVideoMixerAttribute attr = VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX;
	float csc[3][4] = {
	{ 1.f, 0.f, 0.f, 0.f },
	{ 0.f, 1.f, 0.f, 0.f },
	{ 0.f, 0.f, 1.f, 0.f },
	};
	void *pcsc = &csc;

	vdp_video_mixer_set_attribute_values(mixer, 1, &attr, &pcsc);

	data[0] = malloc(len[0] * input_height);
	for (i = 0; i < input_height; i += 2) {
		int val = i & 0xe;

		memset(data[0] + i * len[0], val << 0, len[0]);
		memset(data[0] + (i+1) * len[0], val << 4, len[0]);
	}

	data[1] = cbcr = malloc(len[1] * input_height/2);
	data[2] = NULL;

#if 1
	for (i = 0; i < input_height / 2; ++i) {
		for (j = 0; j < input_width / 2; ++j, cbcr += 2) {
			cbcr[0] = (i & 1) ? 0x80 : (i & 2) ? 0x40 : 0xc0;
			cbcr[1] = !(i & 1) ? 0x80 : (i & 2) ? 0xc0 : 0x40;
		}
	}
#else
	memset(data[1], 0x80, len[1] * input_height / 2);
#endif

	ok(vdp_video_surface_put_bits_y_cb_cr(surf, VDP_YCBCR_FORMAT_NV12, data, len));
	free(data[1]);
	free(data[0]);

	ok(vdp_video_mixer_render(mixer, VDP_INVALID_HANDLE, NULL,
			       VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME,
			       0, NULL, surf, 0, NULL,
			       NULL, osurf, NULL, NULL, 0, NULL));

	len[0] = output_width * 4;
	data[0] = out = malloc(len[0] * output_height);

	ok(vdp_output_surface_get_bits_native(osurf, NULL, data, len));

	for (i = 0; i < output_height; ++i) {
		uint32_t val = *out++;

		for (j = 1; j < output_width; ++j) {
			uint32_t oval = *out++;
			assert(oval == val);
		}
	}
	out = data[0];

	for (i = 0; i < output_height; ++i, out += output_width) {
		fprintf(stderr, "YCbCr[%i] = %06x\n", i, *out & 0xffffff);
	}
}

int main(int argc, char *argv[])
{
	Display *display;
	Window root, window;
	VdpStatus ret;
	VdpPresentationQueueTarget target;
	VdpVideoSurface surf[8];
	VdpOutputSurface osurf[8];
	VdpVideoMixer mixer;
	VdpProcamp camp = { VDP_PROCAMP_VERSION, 0., 1., 1., 0. };
	VdpCSCMatrix mat;
	int i;

	VdpVideoMixerFeature mixer_features[] = {
	};
	VdpVideoMixerParameter mixer_parameters[] = {
		VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH,
		VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT
	};
	const void *mixer_values[ARRAY_SIZE(mixer_parameters)] = {
		&input_width,
		&input_height
	};

	/* This requires libvdpau_trace, which is available in libvdpau.git */
	//setenv("VDPAU_TRACE", "1", 0);

	display = XOpenDisplay(NULL);
	root = XDefaultRootWindow(display);
	window = XCreateSimpleWindow(display, root, 0, 0, output_width, output_height, 0, 0, 0);
	XSelectInput(display, window, ExposureMask | KeyPressMask);
	XMapWindow(display, window);
	XSync(display, 0);

	ret = vdp_device_create_x11(display, 0, &dev, &vdp_get_proc_address);
	assert(ret == VDP_STATUS_OK);

	load_vdpau(dev);
	vdp_generate_csc_matrix(&camp, VDP_COLOR_STANDARD_SMPTE_240M, &mat);

	ok(vdp_presentation_queue_target_create_x11(dev, window, &target));
	for (i = 0; i < ARRAY_SIZE(surf); ++i) {
		ok(vdp_video_surface_create(dev, VDP_CHROMA_TYPE_420, input_width, input_height, &surf[i]));
		ok(vdp_output_surface_create(dev, VDP_COLOR_TABLE_FORMAT_B8G8R8X8, output_width, output_height, &osurf[i]));
	}
	ok(vdp_video_mixer_create(dev, ARRAY_SIZE(mixer_features), mixer_features,
				  ARRAY_SIZE(mixer_parameters), mixer_parameters, mixer_values, &mixer));

	test(mixer, surf[0], osurf[0]);

	vdp_video_mixer_destroy(mixer);
	for (i = ARRAY_SIZE(surf); i > 0; i--) {
		vdp_output_surface_destroy(osurf[i - 1]);
		vdp_video_surface_destroy(surf[i - 1]);
	}
	vdp_presentation_queue_target_destroy(target);
	vdp_device_destroy(dev);
	XDestroyWindow(display, window);
	XCloseDisplay(display);
	return 0;
}

static void load_vdpau(VdpDevice dev) {
	VdpStatus ret;
#define GET_POINTER(fid, fn) ret = vdp_get_proc_address(dev, fid, (void**)&fn); assert(ret == VDP_STATUS_OK);
	GET_POINTER(VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER,                          vdp_preemption_callback_register);
	GET_POINTER(VDP_FUNC_ID_GET_ERROR_STRING,                                      vdp_get_error_string);
	GET_POINTER(VDP_FUNC_ID_GET_API_VERSION,                                       vdp_get_api_version);
	GET_POINTER(VDP_FUNC_ID_GET_INFORMATION_STRING,                                vdp_get_information_string);
	GET_POINTER(VDP_FUNC_ID_DEVICE_DESTROY,                                        vdp_device_destroy);
	GET_POINTER(VDP_FUNC_ID_GENERATE_CSC_MATRIX,                                   vdp_generate_csc_matrix);
	GET_POINTER(VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES,                      vdp_video_surface_query_capabilities);
	GET_POINTER(VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES, vdp_video_surface_query_get_put_bits_y_cb_cr_capabilities);
	GET_POINTER(VDP_FUNC_ID_VIDEO_SURFACE_CREATE,                                  vdp_video_surface_create);
	GET_POINTER(VDP_FUNC_ID_VIDEO_SURFACE_DESTROY,                                 vdp_video_surface_destroy);
	GET_POINTER(VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS,                          vdp_video_surface_get_parameters);
	GET_POINTER(VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR,                        vdp_video_surface_get_bits_y_cb_cr);
	GET_POINTER(VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR,                        vdp_video_surface_put_bits_y_cb_cr);
	GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_CAPABILITIES,                     vdp_output_surface_query_capabilities);
	GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_GET_PUT_BITS_NATIVE_CAPABILITIES, vdp_output_surface_query_get_put_bits_native_capabilities);
	GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_INDEXED_CAPABILITIES,    vdp_output_surface_query_put_bits_indexed_capabilities);
	GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_Y_CB_CR_CAPABILITIES,    vdp_output_surface_query_put_bits_y_cb_cr_capabilities);
	GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_CREATE,                                 vdp_output_surface_create);
	GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY,                                vdp_output_surface_destroy);
	GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_GET_PARAMETERS,                         vdp_output_surface_get_parameters);
	GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE,                        vdp_output_surface_get_bits_native);
	GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE,                        vdp_output_surface_put_bits_native);
	GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_INDEXED,                       vdp_output_surface_put_bits_indexed);
	GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_Y_CB_CR,                       vdp_output_surface_put_bits_y_cb_cr);
	GET_POINTER(VDP_FUNC_ID_BITMAP_SURFACE_QUERY_CAPABILITIES,                     vdp_bitmap_surface_query_capabilities);
	GET_POINTER(VDP_FUNC_ID_BITMAP_SURFACE_CREATE,                                 vdp_bitmap_surface_create);
	GET_POINTER(VDP_FUNC_ID_BITMAP_SURFACE_DESTROY,                                vdp_bitmap_surface_destroy);
	GET_POINTER(VDP_FUNC_ID_BITMAP_SURFACE_GET_PARAMETERS,                         vdp_bitmap_surface_get_parameters);
	GET_POINTER(VDP_FUNC_ID_BITMAP_SURFACE_PUT_BITS_NATIVE,                        vdp_bitmap_surface_put_bits_native);
	GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE,                  vdp_output_surface_render_output_surface);
	GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE,                  vdp_output_surface_render_bitmap_surface);
	GET_POINTER(VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES,                            vdp_decoder_query_capabilities);
	GET_POINTER(VDP_FUNC_ID_DECODER_CREATE,                                        vdp_decoder_create);
	GET_POINTER(VDP_FUNC_ID_DECODER_DESTROY,                                       vdp_decoder_destroy);
	GET_POINTER(VDP_FUNC_ID_DECODER_GET_PARAMETERS,                                vdp_decoder_get_parameters);
	GET_POINTER(VDP_FUNC_ID_DECODER_RENDER,                                        vdp_decoder_render);
	GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_QUERY_FEATURE_SUPPORT,                     vdp_video_mixer_query_feature_support);
	GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_SUPPORT,                   vdp_video_mixer_query_parameter_support);
	GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_SUPPORT,                   vdp_video_mixer_query_attribute_support);
	GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_VALUE_RANGE,               vdp_video_mixer_query_parameter_value_range);
	GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_VALUE_RANGE,               vdp_video_mixer_query_attribute_value_range);
	GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_CREATE,                                    vdp_video_mixer_create);
	GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES,                       vdp_video_mixer_set_feature_enables);
	GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES,                      vdp_video_mixer_set_attribute_values);
	GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_SUPPORT,                       vdp_video_mixer_get_feature_support);
	GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_ENABLES,                       vdp_video_mixer_get_feature_enables);
	GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_GET_PARAMETER_VALUES,                      vdp_video_mixer_get_parameter_values);
	GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_GET_ATTRIBUTE_VALUES,                      vdp_video_mixer_get_attribute_values);
	GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_DESTROY,                                   vdp_video_mixer_destroy);
	GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_RENDER,                                    vdp_video_mixer_render);
	GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY,                     vdp_presentation_queue_target_destroy);
	GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE,                             vdp_presentation_queue_create);
	GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY,                            vdp_presentation_queue_destroy);
	GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR,               vdp_presentation_queue_set_background_color);
	GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_GET_BACKGROUND_COLOR,               vdp_presentation_queue_get_background_color);
	GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME,                           vdp_presentation_queue_get_time);
	GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY,                            vdp_presentation_queue_display);
	GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE,           vdp_presentation_queue_block_until_surface_idle);
	GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS,               vdp_presentation_queue_query_surface_status);
	GET_POINTER(VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER,                          vdp_preemption_callback_register);
	GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11,                  vdp_presentation_queue_target_create_x11);
}
_______________________________________________
mesa-dev mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to