|
| 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 | + */ |
| 32 | +#include <stdio.h> |
| 33 | +#include <string.h> |
| 34 | +#include <stdlib.h> |
| 35 | +#include <getopt.h> |
| 36 | +#include <unistd.h> |
| 37 | +#include <sys/types.h> |
| 38 | +#include <sys/stat.h> |
| 39 | +#include <fcntl.h> |
| 40 | +#include <assert.h> |
| 41 | +#include <va/va.h> |
| 42 | +#include <vector> |
| 43 | +#include <va/va_drm.h> |
| 44 | +#include "va_display.h" |
| 45 | +#include <time.h> |
| 46 | +#include <va/va_drmcommon.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 | + |
| 55 | +#define CLIP_WIDTH 1920 |
| 56 | +#define CLIP_HEIGHT 1920 |
| 57 | + |
| 58 | +VADisplay openDriver(char *device_paths) |
| 59 | +{ |
| 60 | + int drm_fd = open(device_paths, O_RDWR); |
| 61 | + if (drm_fd < 0) |
| 62 | + { |
| 63 | + printf("####INFO: device %s is invalid !\n", device_paths); |
| 64 | + return NULL; |
| 65 | + } |
| 66 | + |
| 67 | + VADisplay va_dpy = vaGetDisplayDRM(drm_fd); |
| 68 | + if(va_dpy) |
| 69 | + return va_dpy; |
| 70 | + |
| 71 | + close(drm_fd); |
| 72 | + drm_fd = -1; |
| 73 | + return 0; |
| 74 | +} |
| 75 | + |
| 76 | +/* Data dump of a 16x16 MPEG2 video clip,it has one I frame |
| 77 | + */ |
| 78 | +static unsigned char mpeg2_clip[] = { |
| 79 | + 0x00, 0x00, 0x01, 0xb3, 0x01, 0x00, 0x10, 0x13, 0xff, 0xff, 0xe0, 0x18, 0x00, 0x00, 0x01, 0xb5, |
| 80 | + 0x14, 0x8a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0xb8, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, |
| 81 | + 0x01, 0x00, 0x00, 0x0f, 0xff, 0xf8, 0x00, 0x00, 0x01, 0xb5, 0x8f, 0xff, 0xf3, 0x41, 0x80, 0x00, |
| 82 | + 0x00, 0x01, 0x01, 0x13, 0xe1, 0x00, 0x15, 0x81, 0x54, 0xe0, 0x2a, 0x05, 0x43, 0x00, 0x2d, 0x60, |
| 83 | + 0x18, 0x01, 0x4e, 0x82, 0xb9, 0x58, 0xb1, 0x83, 0x49, 0xa4, 0xa0, 0x2e, 0x05, 0x80, 0x4b, 0x7a, |
| 84 | + 0x00, 0x01, 0x38, 0x20, 0x80, 0xe8, 0x05, 0xff, 0x60, 0x18, 0xe0, 0x1d, 0x80, 0x98, 0x01, 0xf8, |
| 85 | + 0x06, 0x00, 0x54, 0x02, 0xc0, 0x18, 0x14, 0x03, 0xb2, 0x92, 0x80, 0xc0, 0x18, 0x94, 0x42, 0x2c, |
| 86 | + 0xb2, 0x11, 0x64, 0xa0, 0x12, 0x5e, 0x78, 0x03, 0x3c, 0x01, 0x80, 0x0e, 0x80, 0x18, 0x80, 0x6b, |
| 87 | + 0xca, 0x4e, 0x01, 0x0f, 0xe4, 0x32, 0xc9, 0xbf, 0x01, 0x42, 0x69, 0x43, 0x50, 0x4b, 0x01, 0xc9, |
| 88 | + 0x45, 0x80, 0x50, 0x01, 0x38, 0x65, 0xe8, 0x01, 0x03, 0xf3, 0xc0, 0x76, 0x00, 0xe0, 0x03, 0x20, |
| 89 | + 0x28, 0x18, 0x01, 0xa9, 0x34, 0x04, 0xc5, 0xe0, 0x0b, 0x0b, 0x04, 0x20, 0x06, 0xc0, 0x89, 0xff, |
| 90 | + 0x60, 0x12, 0x12, 0x8a, 0x2c, 0x34, 0x11, 0xff, 0xf6, 0xe2, 0x40, 0xc0, 0x30, 0x1b, 0x7a, 0x01, |
| 91 | + 0xa9, 0x0d, 0x00, 0xac, 0x64 |
| 92 | +}; |
| 93 | + |
| 94 | +/* hardcoded here without a bitstream parser helper |
| 95 | + * please see picture mpeg2-I.jpg for bitstream details |
| 96 | + */ |
| 97 | +static VAPictureParameterBufferMPEG2 pic_param = { |
| 98 | + horizontal_size: 16, |
| 99 | + vertical_size: 16, |
| 100 | + forward_reference_picture: 0xffffffff, |
| 101 | + backward_reference_picture: 0xffffffff, |
| 102 | + picture_coding_type: 1, |
| 103 | + f_code: 0xffff, |
| 104 | + { |
| 105 | + { |
| 106 | + intra_dc_precision: 0, |
| 107 | + picture_structure: 3, |
| 108 | + top_field_first: 0, |
| 109 | + frame_pred_frame_dct: 1, |
| 110 | + concealment_motion_vectors: 0, |
| 111 | + q_scale_type: 0, |
| 112 | + intra_vlc_format: 0, |
| 113 | + alternate_scan: 0, |
| 114 | + repeat_first_field: 0, |
| 115 | + progressive_frame: 1, |
| 116 | + is_first_field: 1 |
| 117 | + }, |
| 118 | + } |
| 119 | +}; |
| 120 | + |
| 121 | +/* see MPEG2 spec65 for the defines of matrix */ |
| 122 | +static VAIQMatrixBufferMPEG2 iq_matrix = { |
| 123 | + load_intra_quantiser_matrix: 1, |
| 124 | + load_non_intra_quantiser_matrix: 1, |
| 125 | + load_chroma_intra_quantiser_matrix: 0, |
| 126 | + load_chroma_non_intra_quantiser_matrix: 0, |
| 127 | +intra_quantiser_matrix: |
| 128 | + { |
| 129 | + 8, 16, 16, 19, 16, 19, 22, 22, |
| 130 | + 22, 22, 22, 22, 26, 24, 26, 27, |
| 131 | + 27, 27, 26, 26, 26, 26, 27, 27, |
| 132 | + 27, 29, 29, 29, 34, 34, 34, 29, |
| 133 | + 29, 29, 27, 27, 29, 29, 32, 32, |
| 134 | + 34, 34, 37, 38, 37, 35, 35, 34, |
| 135 | + 35, 38, 38, 40, 40, 40, 48, 48, |
| 136 | + 46, 46, 56, 56, 58, 69, 69, 83 |
| 137 | + }, |
| 138 | +non_intra_quantiser_matrix: |
| 139 | + {16}, |
| 140 | +chroma_intra_quantiser_matrix: |
| 141 | + {0}, |
| 142 | +chroma_non_intra_quantiser_matrix: |
| 143 | + {0} |
| 144 | +}; |
| 145 | + |
| 146 | +#if 1 |
| 147 | +static VASliceParameterBufferMPEG2 slice_param = { |
| 148 | + slice_data_size: 150, |
| 149 | + slice_data_offset: 0, |
| 150 | + slice_data_flag: 0, |
| 151 | + macroblock_offset: 38, /* 4byte + 6bits=38bits */ |
| 152 | + slice_horizontal_position: 0, |
| 153 | + slice_vertical_position: 0, |
| 154 | + quantiser_scale_code: 2, |
| 155 | + intra_slice_flag: 0 |
| 156 | +}; |
| 157 | +#endif |
| 158 | + |
| 159 | +#define CLIP_WIDTH 16 |
| 160 | +#define CLIP_HEIGHT 16 |
| 161 | + |
| 162 | +#define WIN_WIDTH (CLIP_WIDTH<<1) |
| 163 | +#define WIN_HEIGHT (CLIP_HEIGHT<<1) |
| 164 | + |
| 165 | +int main(int argc, char **argv) |
| 166 | +{ |
| 167 | + VAEntrypoint entrypoints[5]; |
| 168 | + int num_entrypoints, vld_entrypoint; |
| 169 | + VAConfigAttrib attrib; |
| 170 | + VAConfigID config_id; |
| 171 | + VASurfaceID surface_id_1, surface_id_2; |
| 172 | + VAContextID context_id_1; |
| 173 | + VABufferID pic_param_buf, iqmatrix_buf, slice_param_buf, slice_data_buf; |
| 174 | + int major_ver, minor_ver; |
| 175 | + VADisplay va_dpy_1, va_dpy_2; |
| 176 | + VAStatus va_status; |
| 177 | + |
| 178 | + va_init_display_args(&argc, argv); |
| 179 | + va_dpy_1 = openDriver(argv[1]); |
| 180 | + va_status = vaInitialize(va_dpy_1, &major_ver, &minor_ver); |
| 181 | + assert(va_status == VA_STATUS_SUCCESS); |
| 182 | + |
| 183 | + va_dpy_2 = openDriver(argv[1]); |
| 184 | + va_status = vaInitialize(va_dpy_2, &major_ver, &minor_ver); |
| 185 | + assert(va_status == VA_STATUS_SUCCESS); |
| 186 | + |
| 187 | +////////////////////////////create decode and export surface//////////////////////////////// |
| 188 | + va_status = vaQueryConfigEntrypoints(va_dpy_1, VAProfileMPEG2Main, entrypoints, |
| 189 | + &num_entrypoints); |
| 190 | + CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints"); |
| 191 | + |
| 192 | + for (vld_entrypoint = 0; vld_entrypoint < num_entrypoints; vld_entrypoint++) { |
| 193 | + if (entrypoints[vld_entrypoint] == VAEntrypointVLD) |
| 194 | + break; |
| 195 | + } |
| 196 | + if (vld_entrypoint == num_entrypoints) { |
| 197 | + /* not find VLD entry point */ |
| 198 | + assert(0); |
| 199 | + } |
| 200 | + |
| 201 | + /* Assuming finding VLD, find out the format for the render target */ |
| 202 | + attrib.type = VAConfigAttribRTFormat; |
| 203 | + vaGetConfigAttributes(va_dpy_1, VAProfileMPEG2Main, VAEntrypointVLD, |
| 204 | + &attrib, 1); |
| 205 | + if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) { |
| 206 | + /* not find desired YUV420 RT format */ |
| 207 | + assert(0); |
| 208 | + } |
| 209 | + |
| 210 | + va_status = vaCreateConfig(va_dpy_1, VAProfileMPEG2Main, VAEntrypointVLD, |
| 211 | + &attrib, 1, &config_id); |
| 212 | + CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints"); |
| 213 | + |
| 214 | + //create surface1 |
| 215 | + va_status = vaCreateSurfaces( |
| 216 | + va_dpy_1, |
| 217 | + VA_RT_FORMAT_YUV420, CLIP_WIDTH, CLIP_HEIGHT, |
| 218 | + &surface_id_1, 1, |
| 219 | + NULL, 0 |
| 220 | + ); |
| 221 | + CHECK_VASTATUS(va_status, "vaCreateSurfaces"); |
| 222 | + |
| 223 | + /* Create a context1 for this decode pipe */ |
| 224 | + va_status = vaCreateContext(va_dpy_1, config_id, |
| 225 | + CLIP_WIDTH, |
| 226 | + ((CLIP_HEIGHT + 15) / 16) * 16, |
| 227 | + VA_PROGRESSIVE, |
| 228 | + &surface_id_1, |
| 229 | + 1, |
| 230 | + &context_id_1); |
| 231 | + CHECK_VASTATUS(va_status, "vaCreateContext"); |
| 232 | + |
| 233 | + va_status = vaCreateBuffer(va_dpy_1, context_id_1, |
| 234 | + VAPictureParameterBufferType, |
| 235 | + sizeof(VAPictureParameterBufferMPEG2), |
| 236 | + 1, &pic_param, |
| 237 | + &pic_param_buf); |
| 238 | + CHECK_VASTATUS(va_status, "vaCreateBuffer"); |
| 239 | + |
| 240 | + va_status = vaCreateBuffer(va_dpy_1, context_id_1, |
| 241 | + VAIQMatrixBufferType, |
| 242 | + sizeof(VAIQMatrixBufferMPEG2), |
| 243 | + 1, &iq_matrix, |
| 244 | + &iqmatrix_buf); |
| 245 | + CHECK_VASTATUS(va_status, "vaCreateBuffer"); |
| 246 | + |
| 247 | + va_status = vaCreateBuffer(va_dpy_1, context_id_1, |
| 248 | + VASliceParameterBufferType, |
| 249 | + sizeof(VASliceParameterBufferMPEG2), |
| 250 | + 1, |
| 251 | + &slice_param, &slice_param_buf); |
| 252 | + CHECK_VASTATUS(va_status, "vaCreateBuffer"); |
| 253 | + |
| 254 | + va_status = vaCreateBuffer(va_dpy_1, context_id_1, |
| 255 | + VASliceDataBufferType, |
| 256 | + 0xc4 - 0x2f + 1, |
| 257 | + 1, |
| 258 | + mpeg2_clip + 0x2f, |
| 259 | + &slice_data_buf); |
| 260 | + CHECK_VASTATUS(va_status, "vaCreateBuffer"); |
| 261 | + |
| 262 | + va_status = vaBeginPicture(va_dpy_1, context_id_1, surface_id_1); |
| 263 | + CHECK_VASTATUS(va_status, "vaBeginPicture"); |
| 264 | + |
| 265 | + va_status = vaRenderPicture(va_dpy_1, context_id_1, &pic_param_buf, 1); |
| 266 | + CHECK_VASTATUS(va_status, "vaRenderPicture"); |
| 267 | + |
| 268 | + va_status = vaRenderPicture(va_dpy_1, context_id_1, &iqmatrix_buf, 1); |
| 269 | + CHECK_VASTATUS(va_status, "vaRenderPicture"); |
| 270 | + |
| 271 | + va_status = vaRenderPicture(va_dpy_1, context_id_1, &slice_param_buf, 1); |
| 272 | + CHECK_VASTATUS(va_status, "vaRenderPicture"); |
| 273 | + |
| 274 | + va_status = vaRenderPicture(va_dpy_1, context_id_1, &slice_data_buf, 1); |
| 275 | + CHECK_VASTATUS(va_status, "vaRenderPicture"); |
| 276 | + |
| 277 | + va_status = vaEndPicture(va_dpy_1, context_id_1); |
| 278 | + CHECK_VASTATUS(va_status, "vaEndPicture"); |
| 279 | + |
| 280 | + va_status = vaSyncSurface(va_dpy_1, surface_id_1); |
| 281 | + CHECK_VASTATUS(va_status, "vaSyncSurface"); |
| 282 | + |
| 283 | + //vaExportSurface to get surface prime_fd |
| 284 | + VADRMPRIMESurfaceDescriptor desc; |
| 285 | + memset(&desc, 0, sizeof(VADRMPRIMESurfaceDescriptor)); |
| 286 | + va_status = vaExportSurfaceHandle(va_dpy_1, surface_id_1, VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, 0, &desc); |
| 287 | +////////////////////////////end decoding///////////////////////////////////////////////////////////// |
| 288 | + |
| 289 | +////////////////////////////copy out surface from va_dpy_1 to another surface in va_dpy_2//////////// |
| 290 | + ////import surface from va_dpy_1 and create output surface |
| 291 | + VASurfaceAttrib surf_attrib[2]; |
| 292 | + |
| 293 | + surf_attrib[0].type = VASurfaceAttribMemoryType; |
| 294 | + surf_attrib[0].value.type = VAGenericValueTypeInteger; |
| 295 | + surf_attrib[0].flags = VA_SURFACE_ATTRIB_SETTABLE; |
| 296 | + surf_attrib[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2; |
| 297 | + |
| 298 | + surf_attrib[1].type = VASurfaceAttribExternalBufferDescriptor; |
| 299 | + surf_attrib[1].value.type = VAGenericValueTypePointer; |
| 300 | + surf_attrib[1].flags = VA_SURFACE_ATTRIB_SETTABLE; |
| 301 | + surf_attrib[1].value.value.p = &desc; |
| 302 | + va_status = vaCreateSurfaces( |
| 303 | + va_dpy_2, |
| 304 | + VA_RT_FORMAT_YUV420, CLIP_WIDTH, CLIP_HEIGHT, |
| 305 | + &surface_id_2, 1, |
| 306 | + surf_attrib, 2 |
| 307 | + ); |
| 308 | + CHECK_VASTATUS(va_status, "vaCreateSurfaces"); |
| 309 | + |
| 310 | + VASurfaceID surface_id_3; |
| 311 | + va_status = vaCreateSurfaces( |
| 312 | + va_dpy_2, |
| 313 | + VA_RT_FORMAT_YUV420, CLIP_WIDTH, CLIP_HEIGHT, |
| 314 | + &surface_id_3, 1, |
| 315 | + NULL, 0 |
| 316 | + ); |
| 317 | + CHECK_VASTATUS(va_status, "vaCreateSurfaces"); |
| 318 | + |
| 319 | + //vaCopy |
| 320 | + VACopyObject dst; |
| 321 | + dst.obj_type = VACopyObjectSurface; |
| 322 | + dst.object.surface_id = surface_id_3; |
| 323 | + VACopyObject src; |
| 324 | + src.obj_type = VACopyObjectSurface; |
| 325 | + src.object.surface_id = surface_id_2; |
| 326 | + VACopyOption option; |
| 327 | + option.bits.va_copy_sync = VA_EXEC_SYNC; |
| 328 | + option.bits.va_copy_mode = VA_EXEC_MODE_DEFAULT; |
| 329 | + va_status = vaCopy(va_dpy_2, &dst, &src, option); |
| 330 | + CHECK_VASTATUS(va_status, "vaCopy"); |
| 331 | + |
| 332 | + va_status = vaSyncSurface(va_dpy_2, surface_id_2); |
| 333 | + va_status = vaSyncSurface(va_dpy_2, surface_id_3); |
| 334 | + CHECK_VASTATUS(va_status, "vaSyncSurface"); |
| 335 | +////////////////////////////end copy////////////////////////////////////////////////////////////////// |
| 336 | + |
| 337 | + vaDestroySurfaces(va_dpy_1, &surface_id_1, 1); |
| 338 | + vaDestroySurfaces(va_dpy_2, &surface_id_2, 1); |
| 339 | + vaDestroySurfaces(va_dpy_2, &surface_id_3, 1); |
| 340 | + vaDestroyConfig(va_dpy_1, config_id); |
| 341 | + vaDestroyContext(va_dpy_1, context_id_1); |
| 342 | + |
| 343 | + vaTerminate(va_dpy_1); |
| 344 | + vaTerminate(va_dpy_2); |
| 345 | + va_close_display(va_dpy_1); |
| 346 | + va_close_display(va_dpy_2); |
| 347 | + return 0; |
| 348 | +} |
0 commit comments