Rev 6117 | Rev 6121 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 6117 | Rev 6118 | ||
---|---|---|---|
1 | #include |
1 | #include |
2 | #include |
2 | #include |
3 | #include |
3 | #include |
4 | #include |
4 | #include |
5 | #include |
5 | #include |
6 | #include |
6 | #include |
7 | #include |
7 | #include |
8 | #include |
8 | #include |
9 | #include |
9 | #include |
10 | #include |
10 | #include |
11 | #include |
11 | #include |
12 | #include |
12 | #include |
13 | #include "winlib/winlib.h" |
13 | #include "winlib/winlib.h" |
14 | #include "fplay.h" |
14 | #include "fplay.h" |
15 | - | ||
16 | extern int dfx; |
- | |
17 | 15 | ||
18 | struct hw_profile |
16 | struct hw_profile |
19 | { |
17 | { |
20 | enum AVCodecID av_codec; |
18 | enum AVCodecID av_codec; |
21 | int ff_profile; |
19 | int ff_profile; |
22 | uint64_t va_profile; |
20 | uint64_t va_profile; |
23 | }; |
21 | }; |
24 | 22 | ||
25 | 23 | ||
26 | #define ENTER() printf("enter %s\n",__FUNCTION__) |
24 | #define ENTER() printf("enter %s\n",__FUNCTION__) |
27 | #define LEAVE() printf("leave %s\n",__FUNCTION__) |
25 | #define LEAVE() printf("leave %s\n",__FUNCTION__) |
28 | #define FAIL() printf("fail %s\n",__FUNCTION__) |
26 | #define FAIL() printf("fail %s\n",__FUNCTION__) |
29 | 27 | ||
30 | 28 | ||
31 | #if DEBUG |
29 | #if DEBUG |
32 | # define D(x) x |
30 | # define D(x) x |
33 | # define bug printf |
31 | # define bug printf |
34 | #else |
32 | #else |
35 | # define D(x) |
33 | # define D(x) |
36 | #endif |
34 | #endif |
37 | 35 | ||
38 | #undef ARRAY_ELEMS |
36 | #undef ARRAY_ELEMS |
39 | #define ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) |
37 | #define ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) |
40 | 38 | ||
41 | static int drm_fd = 0; |
39 | static int drm_fd = 0; |
42 | static struct vaapi_context *v_context; |
40 | static struct vaapi_context *v_context; |
43 | 41 | ||
44 | static VASurfaceID v_surface_id[4]; |
42 | static VASurfaceID v_surface_id[4]; |
45 | 43 | ||
46 | #define HAS_HEVC VA_CHECK_VERSION(0, 38, 0) |
44 | #define HAS_HEVC VA_CHECK_VERSION(0, 38, 0) |
47 | #define HAS_VP9 (VA_CHECK_VERSION(0, 38, 1) && defined(FF_PROFILE_VP9_0)) |
45 | #define HAS_VP9 (VA_CHECK_VERSION(0, 38, 1) && defined(FF_PROFILE_VP9_0)) |
48 | 46 | ||
49 | #define PE(av_codec_id, ff_profile, vdp_profile) \ |
47 | #define PE(av_codec_id, ff_profile, vdp_profile) \ |
50 | {AV_CODEC_ID_ ## av_codec_id, FF_PROFILE_ ## ff_profile, \ |
48 | {AV_CODEC_ID_ ## av_codec_id, FF_PROFILE_ ## ff_profile, \ |
51 | VAProfile ## vdp_profile} |
49 | VAProfile ## vdp_profile} |
52 | 50 | ||
53 | static const struct hw_profile profiles[] = { |
51 | static const struct hw_profile profiles[] = { |
54 | PE(MPEG2VIDEO, MPEG2_MAIN, MPEG2Main), |
52 | PE(MPEG2VIDEO, MPEG2_MAIN, MPEG2Main), |
55 | PE(MPEG2VIDEO, MPEG2_SIMPLE, MPEG2Simple), |
53 | PE(MPEG2VIDEO, MPEG2_SIMPLE, MPEG2Simple), |
56 | PE(MPEG4, MPEG4_ADVANCED_SIMPLE, MPEG4AdvancedSimple), |
54 | PE(MPEG4, MPEG4_ADVANCED_SIMPLE, MPEG4AdvancedSimple), |
57 | PE(MPEG4, MPEG4_MAIN, MPEG4Main), |
55 | PE(MPEG4, MPEG4_MAIN, MPEG4Main), |
58 | PE(MPEG4, MPEG4_SIMPLE, MPEG4Simple), |
56 | PE(MPEG4, MPEG4_SIMPLE, MPEG4Simple), |
59 | PE(H264, H264_HIGH, H264High), |
57 | PE(H264, H264_HIGH, H264High), |
60 | PE(H264, H264_MAIN, H264Main), |
58 | PE(H264, H264_MAIN, H264Main), |
61 | PE(H264, H264_BASELINE, H264Baseline), |
59 | PE(H264, H264_BASELINE, H264Baseline), |
62 | PE(VC1, VC1_ADVANCED, VC1Advanced), |
60 | PE(VC1, VC1_ADVANCED, VC1Advanced), |
63 | PE(VC1, VC1_MAIN, VC1Main), |
61 | PE(VC1, VC1_MAIN, VC1Main), |
64 | PE(VC1, VC1_SIMPLE, VC1Simple), |
62 | PE(VC1, VC1_SIMPLE, VC1Simple), |
65 | PE(WMV3, VC1_ADVANCED, VC1Advanced), |
63 | PE(WMV3, VC1_ADVANCED, VC1Advanced), |
66 | PE(WMV3, VC1_MAIN, VC1Main), |
64 | PE(WMV3, VC1_MAIN, VC1Main), |
67 | PE(WMV3, VC1_SIMPLE, VC1Simple), |
65 | PE(WMV3, VC1_SIMPLE, VC1Simple), |
68 | #if HAS_HEVC |
66 | #if HAS_HEVC |
69 | PE(HEVC, HEVC_MAIN, HEVCMain), |
67 | PE(HEVC, HEVC_MAIN, HEVCMain), |
70 | PE(HEVC, HEVC_MAIN_10, HEVCMain10), |
68 | PE(HEVC, HEVC_MAIN_10, HEVCMain10), |
71 | #endif |
69 | #endif |
72 | #if HAS_VP9 |
70 | #if HAS_VP9 |
73 | PE(VP9, VP9_0, VP9Profile0), |
71 | PE(VP9, VP9_0, VP9Profile0), |
74 | #endif |
72 | #endif |
75 | {0} |
73 | {0} |
76 | }; |
74 | }; |
77 | 75 | ||
78 | int va_check_codec_support(enum AVCodecID id) |
76 | int va_check_codec_support(enum AVCodecID id) |
79 | { |
77 | { |
80 | for (int n = 0; profiles[n].av_codec; n++) { |
78 | for (int n = 0; profiles[n].av_codec; n++) { |
81 | if (profiles[n].av_codec == id) |
79 | if (profiles[n].av_codec == id) |
82 | return 1; |
80 | return 1; |
83 | } |
81 | } |
84 | return 0; |
82 | return 0; |
85 | } |
83 | } |
86 | 84 | ||
87 | static int vaapi_check_status(VAStatus status, const char *msg) |
85 | static int vaapi_check_status(VAStatus status, const char *msg) |
88 | { |
86 | { |
89 | if (status != VA_STATUS_SUCCESS) { |
87 | if (status != VA_STATUS_SUCCESS) { |
90 | fprintf(stderr, "[%s] %s: %s\n", PACKAGE_NAME, msg, vaErrorStr(status)); |
88 | fprintf(stderr, "[%s] %s: %s\n", PACKAGE_NAME, msg, vaErrorStr(status)); |
91 | return 0; |
89 | return 0; |
92 | } |
90 | } |
93 | return 1; |
91 | return 1; |
94 | }; |
92 | }; |
95 | 93 | ||
96 | static const char *string_of_VADisplayAttribType(VADisplayAttribType type) |
94 | static const char *string_of_VADisplayAttribType(VADisplayAttribType type) |
97 | { |
95 | { |
98 | switch (type) { |
96 | switch (type) { |
99 | #define TYPE(type) \ |
97 | #define TYPE(type) \ |
100 | case VADisplayAttrib##type: return "VADisplayAttrib" #type |
98 | case VADisplayAttrib##type: return "VADisplayAttrib" #type |
101 | TYPE(Brightness); |
99 | TYPE(Brightness); |
102 | TYPE(Contrast); |
100 | TYPE(Contrast); |
103 | TYPE(Hue); |
101 | TYPE(Hue); |
104 | TYPE(Saturation); |
102 | TYPE(Saturation); |
105 | TYPE(BackgroundColor); |
103 | TYPE(BackgroundColor); |
106 | #if !VA_CHECK_VERSION(0,34,0) |
104 | #if !VA_CHECK_VERSION(0,34,0) |
107 | TYPE(DirectSurface); |
105 | TYPE(DirectSurface); |
108 | #endif |
106 | #endif |
109 | #if VA_CHECK_VERSION(0,32,0) |
107 | #if VA_CHECK_VERSION(0,32,0) |
110 | TYPE(Rotation); |
108 | TYPE(Rotation); |
111 | #endif |
109 | #endif |
112 | #undef TYPE |
110 | #undef TYPE |
113 | default: break; |
111 | default: break; |
114 | } |
112 | } |
115 | return " |
113 | return " |
116 | } |
114 | } |
117 | 115 | ||
118 | static const char *string_of_VAProfile(VAProfile profile) |
116 | static const char *string_of_VAProfile(VAProfile profile) |
119 | { |
117 | { |
120 | switch (profile) { |
118 | switch (profile) { |
121 | #define PROFILE(profile) \ |
119 | #define PROFILE(profile) \ |
122 | case VAProfile##profile: return "VAProfile" #profile |
120 | case VAProfile##profile: return "VAProfile" #profile |
123 | PROFILE(MPEG2Simple); |
121 | PROFILE(MPEG2Simple); |
124 | PROFILE(MPEG2Main); |
122 | PROFILE(MPEG2Main); |
125 | PROFILE(MPEG4Simple); |
123 | PROFILE(MPEG4Simple); |
126 | PROFILE(MPEG4AdvancedSimple); |
124 | PROFILE(MPEG4AdvancedSimple); |
127 | PROFILE(MPEG4Main); |
125 | PROFILE(MPEG4Main); |
128 | #if VA_CHECK_VERSION(0,32,0) |
126 | #if VA_CHECK_VERSION(0,32,0) |
129 | PROFILE(JPEGBaseline); |
127 | PROFILE(JPEGBaseline); |
130 | PROFILE(H263Baseline); |
128 | PROFILE(H263Baseline); |
131 | PROFILE(H264ConstrainedBaseline); |
129 | PROFILE(H264ConstrainedBaseline); |
132 | #endif |
130 | #endif |
133 | PROFILE(H264Baseline); |
131 | PROFILE(H264Baseline); |
134 | PROFILE(H264Main); |
132 | PROFILE(H264Main); |
135 | PROFILE(H264High); |
133 | PROFILE(H264High); |
136 | PROFILE(VC1Simple); |
134 | PROFILE(VC1Simple); |
137 | PROFILE(VC1Main); |
135 | PROFILE(VC1Main); |
138 | PROFILE(VC1Advanced); |
136 | PROFILE(VC1Advanced); |
139 | #undef PROFILE |
137 | #undef PROFILE |
140 | default: break; |
138 | default: break; |
141 | } |
139 | } |
142 | return " |
140 | return " |
143 | } |
141 | } |
144 | 142 | ||
145 | static const char *string_of_VAEntrypoint(VAEntrypoint entrypoint) |
143 | static const char *string_of_VAEntrypoint(VAEntrypoint entrypoint) |
146 | { |
144 | { |
147 | switch (entrypoint) { |
145 | switch (entrypoint) { |
148 | #define ENTRYPOINT(entrypoint) \ |
146 | #define ENTRYPOINT(entrypoint) \ |
149 | case VAEntrypoint##entrypoint: return "VAEntrypoint" #entrypoint |
147 | case VAEntrypoint##entrypoint: return "VAEntrypoint" #entrypoint |
150 | ENTRYPOINT(VLD); |
148 | ENTRYPOINT(VLD); |
151 | ENTRYPOINT(IZZ); |
149 | ENTRYPOINT(IZZ); |
152 | ENTRYPOINT(IDCT); |
150 | ENTRYPOINT(IDCT); |
153 | ENTRYPOINT(MoComp); |
151 | ENTRYPOINT(MoComp); |
154 | ENTRYPOINT(Deblocking); |
152 | ENTRYPOINT(Deblocking); |
155 | #if VA_CHECK_VERSION(0,32,0) |
153 | #if VA_CHECK_VERSION(0,32,0) |
156 | ENTRYPOINT(EncSlice); |
154 | ENTRYPOINT(EncSlice); |
157 | ENTRYPOINT(EncPicture); |
155 | ENTRYPOINT(EncPicture); |
158 | #endif |
156 | #endif |
159 | #undef ENTRYPOINT |
157 | #undef ENTRYPOINT |
160 | default: break; |
158 | default: break; |
161 | } |
159 | } |
162 | return " |
160 | return " |
163 | } |
161 | } |
164 | 162 | ||
165 | VADisplay va_open_display(void) |
163 | VADisplay va_open_display(void) |
166 | { |
164 | { |
167 | VADisplay va_dpy; |
165 | VADisplay va_dpy; |
168 | 166 | ||
169 | drm_fd = get_service("DISPLAY"); |
167 | drm_fd = get_service("DISPLAY"); |
170 | if (drm_fd == 0) |
168 | if (drm_fd == 0) |
171 | return NULL; |
169 | return NULL; |
172 | 170 | ||
173 | va_dpy = vaGetDisplayDRM(drm_fd); |
171 | va_dpy = vaGetDisplayDRM(drm_fd); |
174 | if (va_dpy) |
172 | if (va_dpy) |
175 | return va_dpy; |
173 | return va_dpy; |
176 | 174 | ||
177 | drm_fd = 0; |
175 | drm_fd = 0; |
178 | return NULL; |
176 | return NULL; |
179 | }; |
177 | }; |
180 | 178 | ||
181 | int vaapi_init(VADisplay display) |
179 | int vaapi_init(VADisplay display) |
182 | { |
180 | { |
183 | struct vaapi_context *vaapi; |
181 | struct vaapi_context *vaapi; |
184 | int major_version, minor_version; |
182 | int major_version, minor_version; |
185 | int i, num_display_attrs, max_display_attrs; |
183 | int i, num_display_attrs, max_display_attrs; |
186 | VADisplayAttribute *display_attrs = NULL; |
184 | VADisplayAttribute *display_attrs = NULL; |
187 | VAStatus status; |
185 | VAStatus status; |
188 | 186 | ||
189 | if (v_context) |
187 | if (v_context) |
190 | return 0; |
188 | return 0; |
191 | 189 | ||
192 | if (!display) |
190 | if (!display) |
193 | goto error; |
191 | goto error; |
194 | D(bug("VA display %p\n", display)); |
192 | D(bug("VA display %p\n", display)); |
195 | 193 | ||
196 | status = vaInitialize(display, &major_version, &minor_version); |
194 | status = vaInitialize(display, &major_version, &minor_version); |
197 | if (!vaapi_check_status(status, "vaInitialize()")) |
195 | if (!vaapi_check_status(status, "vaInitialize()")) |
198 | goto error; |
196 | goto error; |
199 | D(bug("VA API version %d.%d\n", major_version, minor_version)); |
197 | D(bug("VA API version %d.%d\n", major_version, minor_version)); |
200 | 198 | ||
201 | max_display_attrs = vaMaxNumDisplayAttributes(display); |
199 | max_display_attrs = vaMaxNumDisplayAttributes(display); |
202 | display_attrs = malloc(max_display_attrs * sizeof(display_attrs[0])); |
200 | display_attrs = malloc(max_display_attrs * sizeof(display_attrs[0])); |
203 | if (!display_attrs) |
201 | if (!display_attrs) |
204 | goto error; |
202 | goto error; |
205 | 203 | ||
206 | num_display_attrs = 0; /* XXX: workaround old GMA500 bug */ |
204 | num_display_attrs = 0; /* XXX: workaround old GMA500 bug */ |
207 | status = vaQueryDisplayAttributes(display, display_attrs, &num_display_attrs); |
205 | status = vaQueryDisplayAttributes(display, display_attrs, &num_display_attrs); |
208 | if (!vaapi_check_status(status, "vaQueryDisplayAttributes()")) |
206 | if (!vaapi_check_status(status, "vaQueryDisplayAttributes()")) |
209 | goto error; |
207 | goto error; |
210 | D(bug("%d display attributes available\n", num_display_attrs)); |
208 | D(bug("%d display attributes available\n", num_display_attrs)); |
211 | for (i = 0; i < num_display_attrs; i++) { |
209 | for (i = 0; i < num_display_attrs; i++) { |
212 | VADisplayAttribute * const display_attr = &display_attrs[i]; |
210 | VADisplayAttribute * const display_attr = &display_attrs[i]; |
213 | D(bug(" %-32s (%s/%s) min %d max %d value 0x%x\n", |
211 | D(bug(" %-32s (%s/%s) min %d max %d value 0x%x\n", |
214 | string_of_VADisplayAttribType(display_attr->type), |
212 | string_of_VADisplayAttribType(display_attr->type), |
215 | (display_attr->flags & VA_DISPLAY_ATTRIB_GETTABLE) ? "get" : "---", |
213 | (display_attr->flags & VA_DISPLAY_ATTRIB_GETTABLE) ? "get" : "---", |
216 | (display_attr->flags & VA_DISPLAY_ATTRIB_SETTABLE) ? "set" : "---", |
214 | (display_attr->flags & VA_DISPLAY_ATTRIB_SETTABLE) ? "set" : "---", |
217 | display_attr->min_value, |
215 | display_attr->min_value, |
218 | display_attr->max_value, |
216 | display_attr->max_value, |
219 | display_attr->value)); |
217 | display_attr->value)); |
220 | } |
218 | } |
221 | 219 | ||
222 | if ((vaapi = calloc(1, sizeof(*vaapi))) == NULL) |
220 | if ((vaapi = calloc(1, sizeof(*vaapi))) == NULL) |
223 | goto error; |
221 | goto error; |
224 | vaapi->display = display; |
222 | vaapi->display = display; |
225 | vaapi->config_id = VA_INVALID_ID; |
223 | vaapi->config_id = VA_INVALID_ID; |
226 | vaapi->context_id = VA_INVALID_ID; |
224 | vaapi->context_id = VA_INVALID_ID; |
227 | // vaapi->pic_param_buf_id = VA_INVALID_ID; |
- | |
228 | // vaapi->iq_matrix_buf_id = VA_INVALID_ID; |
- | |
229 | // vaapi->bitplane_buf_id = VA_INVALID_ID; |
- | |
230 | 225 | ||
231 | v_context = vaapi; |
226 | v_context = vaapi; |
232 | 227 | ||
233 | return 0; |
228 | return 0; |
234 | 229 | ||
235 | error: |
230 | error: |
236 | free(display_attrs); |
231 | free(display_attrs); |
237 | return -1; |
232 | return -1; |
238 | } |
233 | } |
239 | 234 | ||
240 | 235 | ||
241 | static int has_profile(struct vaapi_context *vaapi, VAProfile profile) |
236 | static int has_profile(struct vaapi_context *vaapi, VAProfile profile) |
242 | { |
237 | { |
243 | VAProfile *profiles; |
238 | VAProfile *profiles; |
244 | int n_profiles; |
239 | int n_profiles; |
245 | VAStatus status; |
240 | VAStatus status; |
246 | int i; |
241 | int i; |
247 | 242 | ||
248 | profiles = calloc(vaMaxNumProfiles(vaapi->display), sizeof(profiles[0])); |
243 | profiles = calloc(vaMaxNumProfiles(vaapi->display), sizeof(profiles[0])); |
249 | 244 | ||
250 | status = vaQueryConfigProfiles(vaapi->display,profiles,&n_profiles); |
245 | status = vaQueryConfigProfiles(vaapi->display,profiles,&n_profiles); |
251 | 246 | ||
252 | if (!vaapi_check_status(status, "vaQueryConfigProfiles()")) |
247 | if (!vaapi_check_status(status, "vaQueryConfigProfiles()")) |
253 | return 0; |
248 | return 0; |
254 | 249 | ||
255 | D(bug("%d profiles available\n", n_profiles)); |
250 | D(bug("%d profiles available\n", n_profiles)); |
256 | 251 | ||
257 | for (i = 0; i < n_profiles; i++) |
252 | for (i = 0; i < n_profiles; i++) |
258 | { |
253 | { |
259 | if (profiles[i] == profile) |
254 | if (profiles[i] == profile) |
260 | return 1; |
255 | return 1; |
261 | } |
256 | } |
262 | return 0; |
257 | return 0; |
263 | } |
258 | } |
264 | 259 | ||
265 | static int has_entrypoint(struct vaapi_context *vaapi, VAProfile profile, VAEntrypoint entrypoint) |
260 | static int has_entrypoint(struct vaapi_context *vaapi, VAProfile profile, VAEntrypoint entrypoint) |
266 | { |
261 | { |
267 | VAEntrypoint *entrypoints; |
262 | VAEntrypoint *entrypoints; |
268 | int n_entrypoints; |
263 | int n_entrypoints; |
269 | VAStatus status; |
264 | VAStatus status; |
270 | int i; |
265 | int i; |
271 | 266 | ||
272 | entrypoints = calloc(vaMaxNumEntrypoints(vaapi->display), sizeof(entrypoints[0])); |
267 | entrypoints = calloc(vaMaxNumEntrypoints(vaapi->display), sizeof(entrypoints[0])); |
273 | 268 | ||
274 | status = vaQueryConfigEntrypoints(vaapi->display, profile, |
269 | status = vaQueryConfigEntrypoints(vaapi->display, profile, |
275 | entrypoints, &n_entrypoints); |
270 | entrypoints, &n_entrypoints); |
276 | if (!vaapi_check_status(status, "vaQueryConfigEntrypoints()")) |
271 | if (!vaapi_check_status(status, "vaQueryConfigEntrypoints()")) |
277 | return 0; |
272 | return 0; |
278 | 273 | ||
279 | D(bug("%d entrypoints available for %s\n", n_entrypoints, |
274 | D(bug("%d entrypoints available for %s\n", n_entrypoints, |
280 | string_of_VAProfile(profile))); |
275 | string_of_VAProfile(profile))); |
281 | 276 | ||
282 | for (i = 0; i < n_entrypoints; i++) |
277 | for (i = 0; i < n_entrypoints; i++) |
283 | { |
278 | { |
284 | if (entrypoints[i] == entrypoint) |
279 | if (entrypoints[i] == entrypoint) |
285 | return 1; |
280 | return 1; |
286 | } |
281 | } |
287 | return 0; |
282 | return 0; |
288 | } |
283 | } |
289 | 284 | ||
290 | static int vaapi_init_decoder(VAProfile profile, |
285 | static int vaapi_init_decoder(VAProfile profile, |
291 | VAEntrypoint entrypoint, |
286 | VAEntrypoint entrypoint, |
292 | unsigned int picture_width, |
287 | unsigned int picture_width, |
293 | unsigned int picture_height) |
288 | unsigned int picture_height) |
294 | { |
289 | { |
295 | struct vaapi_context* const vaapi = v_context; |
290 | struct vaapi_context* const vaapi = v_context; |
296 | VAConfigAttrib attrib; |
291 | VAConfigAttrib attrib; |
297 | VAConfigID config_id = VA_INVALID_ID; |
292 | VAConfigID config_id = VA_INVALID_ID; |
298 | VAContextID context_id = VA_INVALID_ID; |
293 | VAContextID context_id = VA_INVALID_ID; |
299 | VAStatus status; |
294 | VAStatus status; |
300 | 295 | ||
301 | ENTER(); |
296 | ENTER(); |
302 | if (!vaapi) |
297 | if (!vaapi) |
303 | { |
298 | { |
304 | FAIL(); |
299 | FAIL(); |
305 | return -1; |
300 | return -1; |
306 | }; |
301 | }; |
307 | 302 | ||
308 | if (!has_profile(vaapi, profile)) |
303 | if (!has_profile(vaapi, profile)) |
309 | { |
304 | { |
310 | FAIL(); |
305 | FAIL(); |
311 | return -1; |
306 | return -1; |
312 | }; |
307 | }; |
313 | 308 | ||
314 | if (!has_entrypoint(vaapi, profile, entrypoint)) |
309 | if (!has_entrypoint(vaapi, profile, entrypoint)) |
315 | { |
310 | { |
316 | FAIL(); |
311 | FAIL(); |
317 | return -1; |
312 | return -1; |
318 | }; |
313 | }; |
319 | 314 | ||
320 | if (vaapi->config_id != VA_INVALID_ID) |
315 | if (vaapi->config_id != VA_INVALID_ID) |
321 | vaDestroyConfig(vaapi->display, vaapi->config_id); |
316 | vaDestroyConfig(vaapi->display, vaapi->config_id); |
322 | 317 | ||
323 | attrib.type = VAConfigAttribRTFormat; |
318 | attrib.type = VAConfigAttribRTFormat; |
324 | 319 | ||
325 | printf("vaGetConfigAttributes\n"); |
320 | printf("vaGetConfigAttributes\n"); |
326 | status = vaGetConfigAttributes(vaapi->display, profile, entrypoint, |
321 | status = vaGetConfigAttributes(vaapi->display, profile, entrypoint, |
327 | &attrib, 1); |
322 | &attrib, 1); |
328 | if (!vaapi_check_status(status, "vaGetConfigAttributes()")) |
323 | if (!vaapi_check_status(status, "vaGetConfigAttributes()")) |
329 | { |
324 | { |
330 | FAIL(); |
325 | FAIL(); |
331 | return -1; |
326 | return -1; |
332 | } |
327 | } |
333 | 328 | ||
334 | if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) |
329 | if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) |
335 | { |
330 | { |
336 | printf("Chroma format not supported.\n"); |
331 | printf("Chroma format not supported.\n"); |
337 | FAIL(); |
332 | FAIL(); |
338 | return -1; |
333 | return -1; |
339 | }; |
334 | }; |
340 | 335 | ||
341 | printf("vaCreateConfig\n"); |
336 | printf("vaCreateConfig\n"); |
342 | status = vaCreateConfig(vaapi->display, profile, entrypoint, |
337 | status = vaCreateConfig(vaapi->display, profile, entrypoint, |
343 | &attrib, 1, &config_id); |
338 | &attrib, 1, &config_id); |
344 | if (!vaapi_check_status(status, "vaCreateConfig()")) |
339 | if (!vaapi_check_status(status, "vaCreateConfig()")) |
345 | { |
340 | { |
346 | FAIL(); |
341 | FAIL(); |
347 | return -1; |
342 | return -1; |
348 | } |
343 | } |
349 | 344 | ||
350 | printf("vaCreateSurfaces %dx%d\n",picture_width,picture_height); |
345 | printf("vaCreateSurfaces %dx%d\n",picture_width,picture_height); |
351 | status = vaCreateSurfaces(vaapi->display, VA_RT_FORMAT_YUV420, picture_width, picture_height, |
346 | status = vaCreateSurfaces(vaapi->display, VA_RT_FORMAT_YUV420, picture_width, picture_height, |
352 | v_surface_id,4,NULL,0); |
347 | v_surface_id,4,NULL,0); |
353 | printf("v_surface_id_3 %x\n", v_surface_id[3]); |
348 | printf("v_surface_id_3 %x\n", v_surface_id[3]); |
354 | if (!vaapi_check_status(status, "vaCreateSurfaces()")) |
349 | if (!vaapi_check_status(status, "vaCreateSurfaces()")) |
355 | { |
350 | { |
356 | FAIL(); |
351 | FAIL(); |
357 | return -1; |
352 | return -1; |
358 | }; |
353 | }; |
359 | { |
354 | { |
360 | VAImage vaimage; |
355 | VAImage vaimage; |
361 | VABufferInfo info = {0}; |
356 | VABufferInfo info = {0}; |
362 | 357 | ||
363 | vaDeriveImage(vaapi->display,v_surface_id[0],&vaimage); |
358 | vaDeriveImage(vaapi->display,v_surface_id[0],&vaimage); |
364 | printf("vaDeriveImage: %x fourcc: %x\n" |
359 | printf("vaDeriveImage: %x fourcc: %x\n" |
365 | "offset0: %d pitch0: %d\n" |
360 | "offset0: %d pitch0: %d\n" |
366 | "offset1: %d pitch1: %d\n" |
361 | "offset1: %d pitch1: %d\n" |
367 | "offset2: %d pitch2: %d\n", |
362 | "offset2: %d pitch2: %d\n", |
368 | vaimage.buf, vaimage.format.fourcc, |
363 | vaimage.buf, vaimage.format.fourcc, |
369 | vaimage.offsets[0],vaimage.pitches[0], |
364 | vaimage.offsets[0],vaimage.pitches[0], |
370 | vaimage.offsets[1],vaimage.pitches[1], |
365 | vaimage.offsets[1],vaimage.pitches[1], |
371 | vaimage.offsets[2],vaimage.pitches[2]); |
366 | vaimage.offsets[2],vaimage.pitches[2]); |
372 | 367 | ||
373 | info.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM; |
368 | info.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM; |
374 | vaAcquireBufferHandle(vaapi->display, vaimage.buf, &info); |
369 | vaAcquireBufferHandle(vaapi->display, vaimage.buf, &info); |
375 | printf("vaAcquireBufferHandle: %x type: %x\n" |
370 | printf("vaAcquireBufferHandle: %x type: %x\n" |
376 | "mem type: %x mem size: %x\n", |
371 | "mem type: %x mem size: %x\n", |
377 | info.handle, info.type, info.mem_type, info.mem_size); |
372 | info.handle, info.type, info.mem_type, info.mem_size); |
378 | 373 | ||
379 | vaReleaseBufferHandle(vaapi->display, vaimage.buf); |
374 | vaReleaseBufferHandle(vaapi->display, vaimage.buf); |
380 | 375 | ||
381 | vaDestroyImage(vaapi->display,vaimage.image_id); |
376 | vaDestroyImage(vaapi->display,vaimage.image_id); |
382 | }; |
377 | }; |
383 | 378 | ||
384 | printf("vaCreateContext %dx%d\n",picture_width,picture_height); |
379 | printf("vaCreateContext %dx%d\n",picture_width,picture_height); |
385 | status = vaCreateContext(vaapi->display, config_id, |
380 | status = vaCreateContext(vaapi->display, config_id, |
386 | picture_width, picture_height, |
381 | picture_width, picture_height, |
387 | VA_PROGRESSIVE, |
382 | VA_PROGRESSIVE, |
388 | v_surface_id, 4, |
383 | v_surface_id, 4, |
389 | &context_id); |
384 | &context_id); |
390 | if (!vaapi_check_status(status, "vaCreateContext()")) |
385 | if (!vaapi_check_status(status, "vaCreateContext()")) |
391 | { |
386 | { |
392 | FAIL(); |
387 | FAIL(); |
393 | return -1; |
388 | return -1; |
394 | }; |
389 | }; |
395 | 390 | ||
396 | vaapi->config_id = config_id; |
391 | vaapi->config_id = config_id; |
397 | vaapi->context_id = context_id; |
392 | vaapi->context_id = context_id; |
398 | LEAVE(); |
393 | LEAVE(); |
399 | return 0; |
394 | return 0; |
400 | } |
395 | } |
401 | 396 | ||
402 | 397 | ||
403 | static enum PixelFormat get_format(struct AVCodecContext *avctx, |
398 | static enum PixelFormat get_format(struct AVCodecContext *avctx, |
404 | const enum AVPixelFormat *fmt) |
399 | const enum AVPixelFormat *fmt) |
405 | { |
400 | { |
406 | int i, profile; |
401 | int i, profile; |
407 | 402 | ||
408 | ENTER(); |
403 | ENTER(); |
409 | 404 | ||
410 | // for (int i = 0; fmt[i] != AV_PIX_FMT_NONE; i++) |
405 | // for (int i = 0; fmt[i] != AV_PIX_FMT_NONE; i++) |
411 | // printf(" %s", av_get_pix_fmt_name(fmt[i])); |
406 | // printf(" %s", av_get_pix_fmt_name(fmt[i])); |
412 | 407 | ||
413 | for (i = 0; fmt[i] != PIX_FMT_NONE; i++) { |
408 | for (i = 0; fmt[i] != PIX_FMT_NONE; i++) { |
414 | printf("pixformat %x\n", fmt[i]); |
409 | printf("pixformat %x\n", fmt[i]); |
415 | if (fmt[i] != AV_PIX_FMT_VAAPI_VLD) |
410 | if (fmt[i] != AV_PIX_FMT_VAAPI_VLD) |
416 | continue; |
411 | continue; |
417 | 412 | ||
418 | switch (avctx->codec_id) |
413 | switch (avctx->codec_id) |
419 | { |
414 | { |
420 | case CODEC_ID_MPEG2VIDEO: |
415 | case CODEC_ID_MPEG2VIDEO: |
421 | profile = VAProfileMPEG2Main; |
416 | profile = VAProfileMPEG2Main; |
422 | break; |
417 | break; |
423 | case CODEC_ID_MPEG4: |
418 | case CODEC_ID_MPEG4: |
424 | case CODEC_ID_H263: |
419 | case CODEC_ID_H263: |
425 | profile = VAProfileMPEG4AdvancedSimple; |
420 | profile = VAProfileMPEG4AdvancedSimple; |
426 | break; |
421 | break; |
427 | case CODEC_ID_H264: |
422 | case CODEC_ID_H264: |
428 | profile = VAProfileH264High; |
423 | profile = VAProfileH264High; |
429 | break; |
424 | break; |
430 | case CODEC_ID_WMV3: |
425 | case CODEC_ID_WMV3: |
431 | profile = VAProfileVC1Main; |
426 | profile = VAProfileVC1Main; |
432 | break; |
427 | break; |
433 | case CODEC_ID_VC1: |
428 | case CODEC_ID_VC1: |
434 | profile = VAProfileVC1Advanced; |
429 | profile = VAProfileVC1Advanced; |
435 | break; |
430 | break; |
436 | default: |
431 | default: |
437 | profile = -1; |
432 | profile = -1; |
438 | break; |
433 | break; |
439 | } |
434 | } |
440 | if (profile >= 0) { |
435 | if (profile >= 0) { |
441 | if (vaapi_init_decoder(profile, VAEntrypointVLD, avctx->width, avctx->height) == 0) |
436 | if (vaapi_init_decoder(profile, VAEntrypointVLD, avctx->width, avctx->height) == 0) |
442 | { |
437 | { |
443 | avctx->hwaccel_context = v_context; |
438 | avctx->hwaccel_context = v_context; |
444 | LEAVE(); |
439 | LEAVE(); |
445 | return fmt[i]; ; |
440 | return fmt[i]; ; |
446 | } |
441 | } |
447 | } |
442 | } |
448 | } |
443 | } |
449 | FAIL(); |
444 | FAIL(); |
450 | return PIX_FMT_NONE; |
445 | return PIX_FMT_NONE; |
451 | } |
446 | } |
452 | 447 | ||
453 | struct av_surface |
448 | struct av_surface |
454 | { |
449 | { |
455 | int w; |
450 | int w; |
456 | int h; |
451 | int h; |
457 | VASurfaceID id; |
452 | VASurfaceID id; |
458 | }; |
453 | }; |
459 | 454 | ||
460 | static void av_release_buffer(void *opaque, uint8_t *data) |
455 | static void av_release_buffer(void *opaque, uint8_t *data) |
461 | { |
456 | { |
462 | struct av_surface surface = *(struct av_surface*)data; |
457 | struct av_surface surface = *(struct av_surface*)data; |
463 | // VDPAUContext *ctx = opaque; |
458 | // VDPAUContext *ctx = opaque; |
464 | 459 | ||
465 | // ctx->video_surface_destroy(surface); |
460 | // ctx->video_surface_destroy(surface); |
466 | av_freep(&data); |
461 | av_freep(&data); |
467 | } |
462 | } |
468 | - | ||
469 | 463 | ||
470 | static int get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flags) |
464 | static int get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flags) |
- | 465 | { |
|
471 | { |
466 | vst_t *vst = (vst_t*)avctx->opaque; |
472 | void *surface = (void *)(uintptr_t)v_surface_id[dfx]; |
- | |
473 | - | ||
474 | // printf("%s surface %x\n", __FUNCTION__, surface); |
- | |
475 | 467 | void *surface = (void *)(uintptr_t)v_surface_id[vst->dfx]; |
|
476 | // pic->type= FF_BUFFER_TYPE_USER; |
468 | |
477 | pic->data[3] = surface; |
469 | pic->data[3] = surface; |
478 | 470 | ||
479 | struct av_surface *avsurface; |
471 | struct av_surface *avsurface; |
480 | surface = av_malloc(sizeof(*avsurface)); |
472 | surface = av_malloc(sizeof(*avsurface)); |
481 | if (!surface) |
473 | if (!surface) |
482 | return AVERROR(ENOMEM); |
474 | return AVERROR(ENOMEM); |
483 | 475 | ||
484 | pic->buf[0] = av_buffer_create((uint8_t*)avsurface, sizeof(*avsurface), |
476 | pic->buf[0] = av_buffer_create((uint8_t*)avsurface, sizeof(*avsurface), |
485 | av_release_buffer, avctx, |
477 | av_release_buffer, avctx, |
486 | AV_BUFFER_FLAG_READONLY); |
478 | AV_BUFFER_FLAG_READONLY); |
487 | return 0; |
479 | return 0; |
488 | } |
480 | } |
489 | 481 | ||
490 | struct vaapi_context va_context_storage; |
482 | struct vaapi_context va_context_storage; |
491 | 483 | ||
492 | int fplay_init_context(AVCodecContext *avctx) |
484 | int fplay_init_context(vst_t *vst) |
493 | { |
485 | { |
- | 486 | AVCodecContext *vCtx = vst->vCtx; |
|
494 | ENTER(); |
487 | |
495 | 488 | vCtx->opaque = vst; |
|
496 | avctx->thread_count = 1; |
489 | vCtx->thread_count = 1; |
497 | avctx->get_format = get_format; |
- | |
498 | avctx->get_buffer2 = get_buffer2; |
490 | vCtx->get_format = get_format; |
499 | 491 | vCtx->get_buffer2 = get_buffer2; |
|
500 | LEAVE(); |
492 | |
501 | return 0; |
493 | return 0; |
502 | } |
494 | } |
503 | 495 | ||
504 | int fplay_vaapi_init(void) |
496 | int fplay_vaapi_init(void) |
505 | { |
497 | { |
506 | VADisplay dpy; |
498 | VADisplay dpy; |
507 | 499 | ||
508 | dpy = va_open_display(); |
500 | dpy = va_open_display(); |
509 | 501 | ||
510 | if (vaapi_init(dpy) < 0) |
502 | if (vaapi_init(dpy) < 0) |
511 | return -1; |
503 | return -1; |
512 | 504 | ||
513 | return 0; |
505 | return 0; |
514 | } |
506 | } |
515 | 507 | ||
516 | struct SwsContext *vacvt_ctx; |
508 | struct SwsContext *vacvt_ctx; |
517 | - | ||
518 | - | ||
519 | void va_sync() |
- | |
520 | { |
- | |
521 | struct vaapi_context* const vaapi = v_context; |
- | |
522 | - | ||
523 | vaSyncSurface(vaapi->display,v_surface_id[dfx]); |
- | |
524 | }; |
- | |
525 | - | ||
526 | 509 | ||
527 | void va_convert_picture(int width, int height, AVPicture *pic) |
510 | void va_convert_picture(vst_t *vst, int width, int height, AVPicture *pic) |
528 | { |
511 | { |
529 | uint8_t *src_data[4]; |
512 | uint8_t *src_data[4]; |
530 | int src_linesize[4]; |
513 | int src_linesize[4]; |
531 | VAImage vaimage; |
514 | VAImage vaimage; |
532 | VAStatus status; |
515 | VAStatus status; |
533 | uint8_t *vdata; |
516 | uint8_t *vdata; |
534 | struct vaapi_context* const vaapi = v_context; |
517 | struct vaapi_context* const vaapi = v_context; |
- | 518 | ||
535 | - | ||
536 | - | ||
537 | va_sync(); |
519 | vaSyncSurface(vaapi->display,v_surface_id[vst->dfx]); |
538 | 520 | ||
539 | status = vaDeriveImage(vaapi->display,v_surface_id[dfx],&vaimage); |
521 | status = vaDeriveImage(vaapi->display,v_surface_id[vst->dfx],&vaimage); |
540 | if (!vaapi_check_status(status, "vaDeriveImage()")) |
522 | if (!vaapi_check_status(status, "vaDeriveImage()")) |
541 | { |
523 | { |
542 | FAIL(); |
524 | FAIL(); |
543 | return; |
525 | return; |
544 | }; |
526 | }; |
545 | 527 | ||
546 | static int once = 2; |
528 | static int once = 2; |
547 | 529 | ||
548 | if(once && dfx == 0) |
530 | if(once && vst->dfx == 0) |
549 | { |
531 | { |
550 | VABufferInfo info = {0}; |
532 | VABufferInfo info = {0}; |
551 | 533 | ||
552 | printf("vaDeriveImage: %x fourcc: %x\n" |
534 | printf("vaDeriveImage: %x fourcc: %x\n" |
553 | "offset0: %d pitch0: %d\n" |
535 | "offset0: %d pitch0: %d\n" |
554 | "offset1: %d pitch1: %d\n" |
536 | "offset1: %d pitch1: %d\n" |
555 | "offset2: %d pitch2: %d\n", |
537 | "offset2: %d pitch2: %d\n", |
556 | vaimage.buf, vaimage.format.fourcc, |
538 | vaimage.buf, vaimage.format.fourcc, |
557 | vaimage.offsets[0],vaimage.pitches[0], |
539 | vaimage.offsets[0],vaimage.pitches[0], |
558 | vaimage.offsets[1],vaimage.pitches[1], |
540 | vaimage.offsets[1],vaimage.pitches[1], |
559 | vaimage.offsets[2],vaimage.pitches[2]); |
541 | vaimage.offsets[2],vaimage.pitches[2]); |
560 | 542 | ||
561 | info.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM; |
543 | info.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM; |
562 | status = vaAcquireBufferHandle(vaapi->display, vaimage.buf, &info); |
544 | status = vaAcquireBufferHandle(vaapi->display, vaimage.buf, &info); |
563 | if (vaapi_check_status(status, "vaAcquireBufferHandle()")) |
545 | if (vaapi_check_status(status, "vaAcquireBufferHandle()")) |
564 | { |
546 | { |
565 | printf("vaAcquireBufferHandle: %x type: %x\n" |
547 | printf("vaAcquireBufferHandle: %x type: %x\n" |
566 | "mem type: %x mem size: %d\n", |
548 | "mem type: %x mem size: %d\n", |
567 | info.handle, info.type, info.mem_type, info.mem_size); |
549 | info.handle, info.type, info.mem_type, info.mem_size); |
568 | 550 | ||
569 | vaReleaseBufferHandle(vaapi->display, vaimage.buf); |
551 | vaReleaseBufferHandle(vaapi->display, vaimage.buf); |
570 | } |
552 | } |
571 | once--; |
553 | once--; |
572 | }; |
554 | }; |
573 | 555 | ||
574 | src_linesize[0] = vaimage.pitches[0]; |
556 | src_linesize[0] = vaimage.pitches[0]; |
575 | src_linesize[1] = vaimage.pitches[1]; |
557 | src_linesize[1] = vaimage.pitches[1]; |
576 | src_linesize[2] = vaimage.pitches[2]; |
558 | src_linesize[2] = vaimage.pitches[2]; |
577 | src_linesize[3] = 0; |
559 | src_linesize[3] = 0; |
578 | 560 | ||
579 | status = vaMapBuffer(vaapi->display,vaimage.buf,(void **)&vdata); |
561 | status = vaMapBuffer(vaapi->display,vaimage.buf,(void **)&vdata); |
580 | if (!vaapi_check_status(status, "vaMapBuffer()")) |
562 | if (!vaapi_check_status(status, "vaMapBuffer()")) |
581 | { |
563 | { |
582 | FAIL(); |
564 | FAIL(); |
583 | return; |
565 | return; |
584 | }; |
566 | }; |
585 | 567 | ||
586 | // printf("vdata: %x offset0: %d offset1: %d offset2: %d\n", vdata, |
568 | // printf("vdata: %x offset0: %d offset1: %d offset2: %d\n", vdata, |
587 | // vaimage.offsets[0], |
569 | // vaimage.offsets[0], |
588 | // vaimage.offsets[1], |
570 | // vaimage.offsets[1], |
589 | // vaimage.offsets[2]); |
571 | // vaimage.offsets[2]); |
590 | 572 | ||
591 | src_data[0] = vdata + vaimage.offsets[0]; |
573 | src_data[0] = vdata + vaimage.offsets[0]; |
592 | src_data[1] = vdata + vaimage.offsets[1]; |
574 | src_data[1] = vdata + vaimage.offsets[1]; |
593 | src_data[2] = vdata + vaimage.offsets[2]; |
575 | src_data[2] = vdata + vaimage.offsets[2]; |
594 | src_data[3] = 0; |
576 | src_data[3] = 0; |
595 | 577 | ||
596 | vacvt_ctx = sws_getCachedContext(vacvt_ctx, width, height, AV_PIX_FMT_NV12, |
578 | vacvt_ctx = sws_getCachedContext(vacvt_ctx, width, height, AV_PIX_FMT_NV12, |
597 | width, height, AV_PIX_FMT_BGRA, |
579 | width, height, AV_PIX_FMT_BGRA, |
598 | SWS_FAST_BILINEAR, NULL, NULL, NULL); |
580 | SWS_FAST_BILINEAR, NULL, NULL, NULL); |
599 | if(vacvt_ctx == NULL) |
581 | if(vacvt_ctx == NULL) |
600 | { |
582 | { |
601 | printf("Cannot initialize the conversion context!\n"); |
583 | printf("Cannot initialize the conversion context!\n"); |
602 | return ; |
584 | return ; |
603 | }; |
585 | }; |
604 | 586 | ||
605 | 587 | ||
606 | // __asm__ volatile ("int3"); |
588 | // __asm__ volatile ("int3"); |
607 | 589 | ||
608 | sws_scale(vacvt_ctx, (const uint8_t* const *)src_data, src_linesize, 0, height, pic->data, pic->linesize); |
590 | sws_scale(vacvt_ctx, (const uint8_t* const *)src_data, src_linesize, 0, height, pic->data, pic->linesize); |
609 | 591 | ||
610 | vaUnmapBuffer (vaapi->display, vaimage.buf); |
592 | vaUnmapBuffer (vaapi->display, vaimage.buf); |
611 | vaDestroyImage(vaapi->display, vaimage.image_id); |
593 | vaDestroyImage(vaapi->display, vaimage.image_id); |
612 | }>>>> |
594 | }>>>> |