| /* | |
| * 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; | |
| } |