forked from KolibriOS/kolibrios
283 lines
9.9 KiB
C++
283 lines
9.9 KiB
C++
|
/*
|
||
|
* 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;
|
||
|
}
|