1 /*
2  * Copyright (c) 2007-2008 Intel Corporation. All Rights Reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sub license, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 /*
26  * it is a real program to show how VAAPI decode work,
27  * It does VLD decode for a simple MPEG2 clip "mpeg2-I.m2v"
28  * "mpeg2-I.m2v" and VA parameters are hardcoded into mpeg2vldemo.c,
29  * See mpeg2-I.jif to know how those VA parameters come from
30  *
31  * gcc -o  mpeg2vldemo  mpeg2vldemo.c -lva -lva-x11 -I/usr/include/va
32  * ./mpeg2vldemo  : only do decode
33  * ./mpeg2vldemo <any parameter >: decode+display
34  *
35  */
36 #include <stdio.h>
37 #include <string.h>
38 #include <stdlib.h>
39 #include <getopt.h>
40 #include <unistd.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <fcntl.h>
44 #include <assert.h>
45 #include <va/va.h>
46 #include "va_display.h"
47 
48 #define CHECK_VASTATUS(va_status,func)                                  \
49 if (va_status != VA_STATUS_SUCCESS) {                                   \
50     fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
51     exit(1);                                                            \
52 }
53 
54 /* Data dump of a 16x16 MPEG2 video clip,it has one I frame
55  */
56 static unsigned char mpeg2_clip[]={
57     0x00,0x00,0x01,0xb3,0x01,0x00,0x10,0x13,0xff,0xff,0xe0,0x18,0x00,0x00,0x01,0xb5,
58     0x14,0x8a,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0xb8,0x00,0x08,0x00,0x00,0x00,0x00,
59     0x01,0x00,0x00,0x0f,0xff,0xf8,0x00,0x00,0x01,0xb5,0x8f,0xff,0xf3,0x41,0x80,0x00,
60     0x00,0x01,0x01,0x13,0xe1,0x00,0x15,0x81,0x54,0xe0,0x2a,0x05,0x43,0x00,0x2d,0x60,
61     0x18,0x01,0x4e,0x82,0xb9,0x58,0xb1,0x83,0x49,0xa4,0xa0,0x2e,0x05,0x80,0x4b,0x7a,
62     0x00,0x01,0x38,0x20,0x80,0xe8,0x05,0xff,0x60,0x18,0xe0,0x1d,0x80,0x98,0x01,0xf8,
63     0x06,0x00,0x54,0x02,0xc0,0x18,0x14,0x03,0xb2,0x92,0x80,0xc0,0x18,0x94,0x42,0x2c,
64     0xb2,0x11,0x64,0xa0,0x12,0x5e,0x78,0x03,0x3c,0x01,0x80,0x0e,0x80,0x18,0x80,0x6b,
65     0xca,0x4e,0x01,0x0f,0xe4,0x32,0xc9,0xbf,0x01,0x42,0x69,0x43,0x50,0x4b,0x01,0xc9,
66     0x45,0x80,0x50,0x01,0x38,0x65,0xe8,0x01,0x03,0xf3,0xc0,0x76,0x00,0xe0,0x03,0x20,
67     0x28,0x18,0x01,0xa9,0x34,0x04,0xc5,0xe0,0x0b,0x0b,0x04,0x20,0x06,0xc0,0x89,0xff,
68     0x60,0x12,0x12,0x8a,0x2c,0x34,0x11,0xff,0xf6,0xe2,0x40,0xc0,0x30,0x1b,0x7a,0x01,
69     0xa9,0x0d,0x00,0xac,0x64
70 };
71 
72 /* hardcoded here without a bitstream parser helper
73  * please see picture mpeg2-I.jpg for bitstream details
74  */
75 static VAPictureParameterBufferMPEG2 pic_param={
76   horizontal_size:16,
77   vertical_size:16,
78   forward_reference_picture:0xffffffff,
79   backward_reference_picture:0xffffffff,
80   picture_coding_type:1,
81   f_code:0xffff,
82   {
83       {
84         intra_dc_precision:0,
85         picture_structure:3,
86         top_field_first:0,
87         frame_pred_frame_dct:1,
88         concealment_motion_vectors:0,
89         q_scale_type:0,
90         intra_vlc_format:0,
91         alternate_scan:0,
92         repeat_first_field:0,
93         progressive_frame:1 ,
94         is_first_field:1
95       },
96   }
97 };
98 
99 /* see MPEG2 spec65 for the defines of matrix */
100 static VAIQMatrixBufferMPEG2 iq_matrix = {
101   load_intra_quantiser_matrix:1,
102   load_non_intra_quantiser_matrix:1,
103   load_chroma_intra_quantiser_matrix:0,
104   load_chroma_non_intra_quantiser_matrix:0,
105   intra_quantiser_matrix:{
106          8, 16, 16, 19, 16, 19, 22, 22,
107         22, 22, 22, 22, 26, 24, 26, 27,
108         27, 27, 26, 26, 26, 26, 27, 27,
109         27, 29, 29, 29, 34, 34, 34, 29,
110         29, 29, 27, 27, 29, 29, 32, 32,
111         34, 34, 37, 38, 37, 35, 35, 34,
112         35, 38, 38, 40, 40, 40, 48, 48,
113         46, 46, 56, 56, 58, 69, 69, 83
114     },
115   non_intra_quantiser_matrix:{16},
116   chroma_intra_quantiser_matrix:{0},
117   chroma_non_intra_quantiser_matrix:{0}
118 };
119 
120 #if 1
121 static VASliceParameterBufferMPEG2 slice_param={
122   slice_data_size:150,
123   slice_data_offset:0,
124   slice_data_flag:0,
125   macroblock_offset:38, /* 4byte + 6bits=38bits */
126   slice_horizontal_position:0,
127   slice_vertical_position:0,
128   quantiser_scale_code:2,
129   intra_slice_flag:0
130 };
131 #endif
132 
133 #define CLIP_WIDTH  16
134 #define CLIP_HEIGHT 16
135 
136 #define WIN_WIDTH  (CLIP_WIDTH<<1)
137 #define WIN_HEIGHT (CLIP_HEIGHT<<1)
138 
main(int argc,char ** argv)139 int main(int argc,char **argv)
140 {
141     VAEntrypoint entrypoints[5];
142     int num_entrypoints,vld_entrypoint;
143     VAConfigAttrib attrib;
144     VAConfigID config_id;
145     VASurfaceID surface_id;
146     VAContextID context_id;
147     VABufferID pic_param_buf,iqmatrix_buf,slice_param_buf,slice_data_buf;
148     int major_ver, minor_ver;
149     VADisplay	va_dpy;
150     VAStatus va_status;
151     int putsurface=0;
152 
153     va_init_display_args(&argc, argv);
154 
155     if (argc > 1)
156         putsurface=1;
157 
158     va_dpy = va_open_display();
159     va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
160     assert(va_status == VA_STATUS_SUCCESS);
161 
162     va_status = vaQueryConfigEntrypoints(va_dpy, VAProfileMPEG2Main, entrypoints,
163                              &num_entrypoints);
164     CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints");
165 
166     for	(vld_entrypoint = 0; vld_entrypoint < num_entrypoints; vld_entrypoint++) {
167         if (entrypoints[vld_entrypoint] == VAEntrypointVLD)
168             break;
169     }
170     if (vld_entrypoint == num_entrypoints) {
171         /* not find VLD entry point */
172         assert(0);
173     }
174 
175     /* Assuming finding VLD, find out the format for the render target */
176     attrib.type = VAConfigAttribRTFormat;
177     vaGetConfigAttributes(va_dpy, VAProfileMPEG2Main, VAEntrypointVLD,
178                           &attrib, 1);
179     if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) {
180         /* not find desired YUV420 RT format */
181         assert(0);
182     }
183 
184     va_status = vaCreateConfig(va_dpy, VAProfileMPEG2Main, VAEntrypointVLD,
185                               &attrib, 1,&config_id);
186     CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints");
187 
188     va_status = vaCreateSurfaces(
189         va_dpy,
190         VA_RT_FORMAT_YUV420, CLIP_WIDTH, CLIP_HEIGHT,
191         &surface_id, 1,
192         NULL, 0
193     );
194     CHECK_VASTATUS(va_status, "vaCreateSurfaces");
195 
196     /* Create a context for this decode pipe */
197     va_status = vaCreateContext(va_dpy, config_id,
198                                CLIP_WIDTH,
199                                ((CLIP_HEIGHT+15)/16)*16,
200                                VA_PROGRESSIVE,
201                                &surface_id,
202                                1,
203                                &context_id);
204     CHECK_VASTATUS(va_status, "vaCreateContext");
205 
206     va_status = vaCreateBuffer(va_dpy, context_id,
207                               VAPictureParameterBufferType,
208                               sizeof(VAPictureParameterBufferMPEG2),
209                               1, &pic_param,
210                               &pic_param_buf);
211     CHECK_VASTATUS(va_status, "vaCreateBuffer");
212 
213     va_status = vaCreateBuffer(va_dpy, context_id,
214                               VAIQMatrixBufferType,
215                               sizeof(VAIQMatrixBufferMPEG2),
216                               1, &iq_matrix,
217                               &iqmatrix_buf );
218     CHECK_VASTATUS(va_status, "vaCreateBuffer");
219 
220     va_status = vaCreateBuffer(va_dpy, context_id,
221                               VASliceParameterBufferType,
222                               sizeof(VASliceParameterBufferMPEG2),
223                               1,
224                               &slice_param, &slice_param_buf);
225     CHECK_VASTATUS(va_status, "vaCreateBuffer");
226 
227     va_status = vaCreateBuffer(va_dpy, context_id,
228                               VASliceDataBufferType,
229                               0xc4-0x2f+1,
230                               1,
231                               mpeg2_clip+0x2f,
232                               &slice_data_buf);
233     CHECK_VASTATUS(va_status, "vaCreateBuffer");
234 
235     va_status = vaBeginPicture(va_dpy, context_id, surface_id);
236     CHECK_VASTATUS(va_status, "vaBeginPicture");
237 
238     va_status = vaRenderPicture(va_dpy,context_id, &pic_param_buf, 1);
239     CHECK_VASTATUS(va_status, "vaRenderPicture");
240 
241     va_status = vaRenderPicture(va_dpy,context_id, &iqmatrix_buf, 1);
242     CHECK_VASTATUS(va_status, "vaRenderPicture");
243 
244     va_status = vaRenderPicture(va_dpy,context_id, &slice_param_buf, 1);
245     CHECK_VASTATUS(va_status, "vaRenderPicture");
246 
247     va_status = vaRenderPicture(va_dpy,context_id, &slice_data_buf, 1);
248     CHECK_VASTATUS(va_status, "vaRenderPicture");
249 
250     va_status = vaEndPicture(va_dpy,context_id);
251     CHECK_VASTATUS(va_status, "vaEndPicture");
252 
253     va_status = vaSyncSurface(va_dpy, surface_id);
254     CHECK_VASTATUS(va_status, "vaSyncSurface");
255 
256     if (putsurface) {
257         VARectangle src_rect, dst_rect;
258 
259         src_rect.x      = 0;
260         src_rect.y      = 0;
261         src_rect.width  = CLIP_WIDTH;
262         src_rect.height = CLIP_HEIGHT;
263 
264         dst_rect.x      = 0;
265         dst_rect.y      = 0;
266         dst_rect.width  = WIN_WIDTH;
267         dst_rect.height = WIN_HEIGHT;
268 
269         va_status = va_put_surface(va_dpy, surface_id, &src_rect, &dst_rect);
270         CHECK_VASTATUS(va_status, "vaPutSurface");
271     }
272     printf("press any key to exit\n");
273     getchar();
274 
275     vaDestroySurfaces(va_dpy,&surface_id,1);
276     vaDestroyConfig(va_dpy,config_id);
277     vaDestroyContext(va_dpy,context_id);
278 
279     vaTerminate(va_dpy);
280     va_close_display(va_dpy);
281     return 0;
282 }
283