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)                                  \
49if (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 */
56static 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 */
75static 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 */
100static 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
121static 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
139int 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