blob: 25fe97254f1e58fe35bb34a1d30512f67f79879e [file] [log] [blame] [edit]
/*
* Copyright (c) 2007-2008 Intel Corporation. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* it is a real program to show how VAAPI decode work,
* It does VLD decode for a simple MPEG2 clip "mpeg2-I.m2v"
* "mpeg2-I.m2v" and VA parameters are hardcoded into mpeg2vldemo.c,
* See mpeg2-I.jif to know how those VA parameters come from
*
* gcc -o mpeg2vldemo mpeg2vldemo.c -lva -lva-x11 -I/usr/include/va
* ./mpeg2vldemo : only do decode
* ./mpeg2vldemo <any parameter >: decode+display
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <va/va.h>
#include "va_display.h"
#define CHECK_VASTATUS(va_status,func) \
if (va_status != VA_STATUS_SUCCESS) { \
fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
exit(1); \
}
/* Data dump of a 16x16 MPEG2 video clip,it has one I frame
*/
static unsigned char mpeg2_clip[] = {
0x00, 0x00, 0x01, 0xb3, 0x01, 0x00, 0x10, 0x13, 0xff, 0xff, 0xe0, 0x18, 0x00, 0x00, 0x01, 0xb5,
0x14, 0x8a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0xb8, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x0f, 0xff, 0xf8, 0x00, 0x00, 0x01, 0xb5, 0x8f, 0xff, 0xf3, 0x41, 0x80, 0x00,
0x00, 0x01, 0x01, 0x13, 0xe1, 0x00, 0x15, 0x81, 0x54, 0xe0, 0x2a, 0x05, 0x43, 0x00, 0x2d, 0x60,
0x18, 0x01, 0x4e, 0x82, 0xb9, 0x58, 0xb1, 0x83, 0x49, 0xa4, 0xa0, 0x2e, 0x05, 0x80, 0x4b, 0x7a,
0x00, 0x01, 0x38, 0x20, 0x80, 0xe8, 0x05, 0xff, 0x60, 0x18, 0xe0, 0x1d, 0x80, 0x98, 0x01, 0xf8,
0x06, 0x00, 0x54, 0x02, 0xc0, 0x18, 0x14, 0x03, 0xb2, 0x92, 0x80, 0xc0, 0x18, 0x94, 0x42, 0x2c,
0xb2, 0x11, 0x64, 0xa0, 0x12, 0x5e, 0x78, 0x03, 0x3c, 0x01, 0x80, 0x0e, 0x80, 0x18, 0x80, 0x6b,
0xca, 0x4e, 0x01, 0x0f, 0xe4, 0x32, 0xc9, 0xbf, 0x01, 0x42, 0x69, 0x43, 0x50, 0x4b, 0x01, 0xc9,
0x45, 0x80, 0x50, 0x01, 0x38, 0x65, 0xe8, 0x01, 0x03, 0xf3, 0xc0, 0x76, 0x00, 0xe0, 0x03, 0x20,
0x28, 0x18, 0x01, 0xa9, 0x34, 0x04, 0xc5, 0xe0, 0x0b, 0x0b, 0x04, 0x20, 0x06, 0xc0, 0x89, 0xff,
0x60, 0x12, 0x12, 0x8a, 0x2c, 0x34, 0x11, 0xff, 0xf6, 0xe2, 0x40, 0xc0, 0x30, 0x1b, 0x7a, 0x01,
0xa9, 0x0d, 0x00, 0xac, 0x64
};
/* hardcoded here without a bitstream parser helper
* please see picture mpeg2-I.jpg for bitstream details
*/
static VAPictureParameterBufferMPEG2 pic_param = {
horizontal_size: 16,
vertical_size: 16,
forward_reference_picture: 0xffffffff,
backward_reference_picture: 0xffffffff,
picture_coding_type: 1,
f_code: 0xffff,
{
{
intra_dc_precision: 0,
picture_structure: 3,
top_field_first: 0,
frame_pred_frame_dct: 1,
concealment_motion_vectors: 0,
q_scale_type: 0,
intra_vlc_format: 0,
alternate_scan: 0,
repeat_first_field: 0,
progressive_frame: 1,
is_first_field: 1
},
}
};
/* see MPEG2 spec65 for the defines of matrix */
static VAIQMatrixBufferMPEG2 iq_matrix = {
load_intra_quantiser_matrix: 1,
load_non_intra_quantiser_matrix: 1,
load_chroma_intra_quantiser_matrix: 0,
load_chroma_non_intra_quantiser_matrix: 0,
intra_quantiser_matrix:
{
8, 16, 16, 19, 16, 19, 22, 22,
22, 22, 22, 22, 26, 24, 26, 27,
27, 27, 26, 26, 26, 26, 27, 27,
27, 29, 29, 29, 34, 34, 34, 29,
29, 29, 27, 27, 29, 29, 32, 32,
34, 34, 37, 38, 37, 35, 35, 34,
35, 38, 38, 40, 40, 40, 48, 48,
46, 46, 56, 56, 58, 69, 69, 83
},
non_intra_quantiser_matrix:
{16},
chroma_intra_quantiser_matrix:
{0},
chroma_non_intra_quantiser_matrix:
{0}
};
#if 1
static VASliceParameterBufferMPEG2 slice_param = {
slice_data_size: 150,
slice_data_offset: 0,
slice_data_flag: 0,
macroblock_offset: 38, /* 4byte + 6bits=38bits */
slice_horizontal_position: 0,
slice_vertical_position: 0,
quantiser_scale_code: 2,
intra_slice_flag: 0
};
#endif
#define CLIP_WIDTH 16
#define CLIP_HEIGHT 16
#define WIN_WIDTH (CLIP_WIDTH<<1)
#define WIN_HEIGHT (CLIP_HEIGHT<<1)
int main(int argc, char **argv)
{
VAEntrypoint entrypoints[5];
int num_entrypoints, vld_entrypoint;
VAConfigAttrib attrib;
VAConfigID config_id;
VASurfaceID surface_id;
VAContextID context_id;
VABufferID pic_param_buf, iqmatrix_buf, slice_param_buf, slice_data_buf;
int major_ver, minor_ver;
VADisplay va_dpy;
VAStatus va_status;
int putsurface = 0;
va_init_display_args(&argc, argv);
if (argc > 1)
putsurface = 1;
va_dpy = va_open_display();
va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
assert(va_status == VA_STATUS_SUCCESS);
va_status = vaQueryConfigEntrypoints(va_dpy, VAProfileMPEG2Main, entrypoints,
&num_entrypoints);
CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints");
for (vld_entrypoint = 0; vld_entrypoint < num_entrypoints; vld_entrypoint++) {
if (entrypoints[vld_entrypoint] == VAEntrypointVLD)
break;
}
if (vld_entrypoint == num_entrypoints) {
/* not find VLD entry point */
assert(0);
}
/* Assuming finding VLD, find out the format for the render target */
attrib.type = VAConfigAttribRTFormat;
vaGetConfigAttributes(va_dpy, VAProfileMPEG2Main, VAEntrypointVLD,
&attrib, 1);
if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) {
/* not find desired YUV420 RT format */
assert(0);
}
va_status = vaCreateConfig(va_dpy, VAProfileMPEG2Main, VAEntrypointVLD,
&attrib, 1, &config_id);
CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints");
va_status = vaCreateSurfaces(
va_dpy,
VA_RT_FORMAT_YUV420, CLIP_WIDTH, CLIP_HEIGHT,
&surface_id, 1,
NULL, 0
);
CHECK_VASTATUS(va_status, "vaCreateSurfaces");
/* Create a context for this decode pipe */
va_status = vaCreateContext(va_dpy, config_id,
CLIP_WIDTH,
((CLIP_HEIGHT + 15) / 16) * 16,
VA_PROGRESSIVE,
&surface_id,
1,
&context_id);
CHECK_VASTATUS(va_status, "vaCreateContext");
va_status = vaCreateBuffer(va_dpy, context_id,
VAPictureParameterBufferType,
sizeof(VAPictureParameterBufferMPEG2),
1, &pic_param,
&pic_param_buf);
CHECK_VASTATUS(va_status, "vaCreateBuffer");
va_status = vaCreateBuffer(va_dpy, context_id,
VAIQMatrixBufferType,
sizeof(VAIQMatrixBufferMPEG2),
1, &iq_matrix,
&iqmatrix_buf);
CHECK_VASTATUS(va_status, "vaCreateBuffer");
va_status = vaCreateBuffer(va_dpy, context_id,
VASliceParameterBufferType,
sizeof(VASliceParameterBufferMPEG2),
1,
&slice_param, &slice_param_buf);
CHECK_VASTATUS(va_status, "vaCreateBuffer");
va_status = vaCreateBuffer(va_dpy, context_id,
VASliceDataBufferType,
0xc4 - 0x2f + 1,
1,
mpeg2_clip + 0x2f,
&slice_data_buf);
CHECK_VASTATUS(va_status, "vaCreateBuffer");
va_status = vaBeginPicture(va_dpy, context_id, surface_id);
CHECK_VASTATUS(va_status, "vaBeginPicture");
va_status = vaRenderPicture(va_dpy, context_id, &pic_param_buf, 1);
CHECK_VASTATUS(va_status, "vaRenderPicture");
va_status = vaRenderPicture(va_dpy, context_id, &iqmatrix_buf, 1);
CHECK_VASTATUS(va_status, "vaRenderPicture");
va_status = vaRenderPicture(va_dpy, context_id, &slice_param_buf, 1);
CHECK_VASTATUS(va_status, "vaRenderPicture");
va_status = vaRenderPicture(va_dpy, context_id, &slice_data_buf, 1);
CHECK_VASTATUS(va_status, "vaRenderPicture");
va_status = vaEndPicture(va_dpy, context_id);
CHECK_VASTATUS(va_status, "vaEndPicture");
va_status = vaSyncSurface(va_dpy, surface_id);
CHECK_VASTATUS(va_status, "vaSyncSurface");
if (putsurface) {
VARectangle src_rect, dst_rect;
src_rect.x = 0;
src_rect.y = 0;
src_rect.width = CLIP_WIDTH;
src_rect.height = CLIP_HEIGHT;
dst_rect.x = 0;
dst_rect.y = 0;
dst_rect.width = WIN_WIDTH;
dst_rect.height = WIN_HEIGHT;
va_status = va_put_surface(va_dpy, surface_id, &src_rect, &dst_rect);
CHECK_VASTATUS(va_status, "vaPutSurface");
}
printf("press any key to exit\n");
getchar();
vaDestroySurfaces(va_dpy, &surface_id, 1);
vaDestroyConfig(va_dpy, config_id);
vaDestroyContext(va_dpy, context_id);
vaTerminate(va_dpy);
va_close_display(va_dpy);
return 0;
}