Skip to content

Commit c5ad29d

Browse files
committed
[Decode] Test shared surface copy between two media instances
Signed-off-by: Xu, Zhengguo <[email protected]>
1 parent 29c0a92 commit c5ad29d

File tree

3 files changed

+356
-1
lines changed

3 files changed

+356
-1
lines changed

decode/Makefile.am

+5-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2121
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2222

23-
bin_PROGRAMS = mpeg2vldemo loadjpeg
23+
bin_PROGRAMS = mpeg2vldemo loadjpeg mpeg2sharedsurfacecopy
2424

2525
AM_CPPFLAGS = \
2626
-Wall \
@@ -40,6 +40,10 @@ TEST_LIBS = \
4040
mpeg2vldemo_LDADD = $(TEST_LIBS)
4141
mpeg2vldemo_SOURCES = mpeg2vldemo.cpp
4242

43+
mpeg2sharedsurfacecopy_LDADD = $(TEST_LIBS)
44+
mpeg2sharedsurfacecopy_SOURCES = mpeg2sharedsurfacecopy.cpp
45+
46+
4347
loadjpeg_LDADD = $(TEST_LIBS)
4448
loadjpeg_SOURCES = loadjpeg.c tinyjpeg.c
4549

decode/meson.build

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
executable('mpeg2vldemo', [ 'mpeg2vldemo.cpp' ],
22
dependencies: libva_display_dep,
33
install: true)
4+
executable('mpeg2sharedsurfacecopy', [ 'mpeg2sharedsurfacecopy.cpp' ],
5+
dependencies: libva_display_dep,
6+
install: true)
47
executable('loadjpeg', [ 'loadjpeg.c', 'tinyjpeg.c' ],
58
dependencies: libva_display_dep,
69
install: true)

decode/mpeg2sharedsurfacecopy.cpp

+348
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,348 @@
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

Comments
 (0)