Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5361 | serge | 1 | /* |
2 | * Copyright © 2010 Intel Corporation |
||
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 | * Authors: |
||
25 | * Zhou Chang |
||
26 | * |
||
27 | */ |
||
28 | |||
29 | #include |
||
30 | #include |
||
31 | #include |
||
32 | #include |
||
33 | |||
34 | #include "intel_batchbuffer.h" |
||
35 | #include "intel_driver.h" |
||
36 | |||
37 | #include "i965_defines.h" |
||
38 | #include "i965_drv_video.h" |
||
39 | #include "i965_encoder.h" |
||
40 | #include "gen6_vme.h" |
||
41 | #include "gen6_mfc.h" |
||
42 | |||
43 | extern Bool gen6_mfc_context_init(VADriverContextP ctx, struct intel_encoder_context *encoder_context); |
||
44 | extern Bool gen6_vme_context_init(VADriverContextP ctx, struct intel_encoder_context *encoder_context); |
||
45 | extern Bool gen7_mfc_context_init(VADriverContextP ctx, struct intel_encoder_context *encoder_context); |
||
46 | |||
47 | static VAStatus |
||
48 | intel_encoder_check_yuv_surface(VADriverContextP ctx, |
||
49 | VAProfile profile, |
||
50 | struct encode_state *encode_state, |
||
51 | struct intel_encoder_context *encoder_context) |
||
52 | { |
||
53 | struct i965_driver_data *i965 = i965_driver_data(ctx); |
||
54 | struct i965_surface src_surface, dst_surface; |
||
55 | struct object_surface *obj_surface; |
||
56 | VAStatus status; |
||
57 | VARectangle rect; |
||
58 | |||
59 | /* releae the temporary surface */ |
||
60 | if (encoder_context->is_tmp_id) { |
||
61 | i965_DestroySurfaces(ctx, &encoder_context->input_yuv_surface, 1); |
||
62 | encode_state->input_yuv_object = NULL; |
||
63 | } |
||
64 | |||
65 | encoder_context->is_tmp_id = 0; |
||
66 | obj_surface = SURFACE(encode_state->current_render_target); |
||
67 | assert(obj_surface && obj_surface->bo); |
||
68 | |||
69 | if (!obj_surface || !obj_surface->bo) |
||
70 | return VA_STATUS_ERROR_INVALID_PARAMETER; |
||
71 | |||
72 | if (obj_surface->fourcc == VA_FOURCC_NV12) { |
||
73 | unsigned int tiling = 0, swizzle = 0; |
||
74 | |||
75 | dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle); |
||
76 | |||
77 | if (tiling == I915_TILING_Y) { |
||
78 | encoder_context->input_yuv_surface = encode_state->current_render_target; |
||
79 | encode_state->input_yuv_object = obj_surface; |
||
80 | return VA_STATUS_SUCCESS; |
||
81 | } |
||
82 | } |
||
83 | |||
84 | rect.x = 0; |
||
85 | rect.y = 0; |
||
86 | rect.width = obj_surface->orig_width; |
||
87 | rect.height = obj_surface->orig_height; |
||
88 | |||
89 | src_surface.base = (struct object_base *)obj_surface; |
||
90 | src_surface.type = I965_SURFACE_TYPE_SURFACE; |
||
91 | src_surface.flags = I965_SURFACE_FLAG_FRAME; |
||
92 | |||
93 | status = i965_CreateSurfaces(ctx, |
||
94 | obj_surface->orig_width, |
||
95 | obj_surface->orig_height, |
||
96 | VA_RT_FORMAT_YUV420, |
||
97 | 1, |
||
98 | &encoder_context->input_yuv_surface); |
||
99 | assert(status == VA_STATUS_SUCCESS); |
||
100 | |||
101 | if (status != VA_STATUS_SUCCESS) |
||
102 | return status; |
||
103 | |||
104 | obj_surface = SURFACE(encoder_context->input_yuv_surface); |
||
105 | encode_state->input_yuv_object = obj_surface; |
||
106 | assert(obj_surface); |
||
107 | i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420); |
||
108 | |||
109 | dst_surface.base = (struct object_base *)obj_surface; |
||
110 | dst_surface.type = I965_SURFACE_TYPE_SURFACE; |
||
111 | dst_surface.flags = I965_SURFACE_FLAG_FRAME; |
||
112 | |||
113 | status = i965_image_processing(ctx, |
||
114 | &src_surface, |
||
115 | &rect, |
||
116 | &dst_surface, |
||
117 | &rect); |
||
118 | assert(status == VA_STATUS_SUCCESS); |
||
119 | |||
120 | encoder_context->is_tmp_id = 1; |
||
121 | |||
122 | return VA_STATUS_SUCCESS; |
||
123 | } |
||
124 | |||
125 | static VAStatus |
||
126 | intel_encoder_check_misc_parameter(VADriverContextP ctx, |
||
127 | struct encode_state *encode_state, |
||
128 | struct intel_encoder_context *encoder_context) |
||
129 | { |
||
130 | |||
131 | if (encode_state->misc_param[VAEncMiscParameterTypeQualityLevel] && |
||
132 | encode_state->misc_param[VAEncMiscParameterTypeQualityLevel]->buffer) { |
||
133 | VAEncMiscParameterBuffer* pMiscParam = (VAEncMiscParameterBuffer*)encode_state->misc_param[VAEncMiscParameterTypeQualityLevel]->buffer; |
||
134 | VAEncMiscParameterBufferQualityLevel* param_quality_level = (VAEncMiscParameterBufferQualityLevel*)pMiscParam->data; |
||
135 | encoder_context->quality_level = param_quality_level->quality_level; |
||
136 | |||
137 | if (encoder_context->quality_level == 0) |
||
138 | encoder_context->quality_level = ENCODER_DEFAULT_QUALITY; |
||
139 | else if (encoder_context->quality_level > encoder_context->quality_range) |
||
140 | goto error; |
||
141 | } |
||
142 | |||
143 | return VA_STATUS_SUCCESS; |
||
144 | |||
145 | error: |
||
146 | return VA_STATUS_ERROR_INVALID_PARAMETER; |
||
147 | } |
||
148 | |||
149 | static VAStatus |
||
150 | intel_encoder_check_avc_parameter(VADriverContextP ctx, |
||
151 | struct encode_state *encode_state, |
||
152 | struct intel_encoder_context *encoder_context) |
||
153 | { |
||
154 | struct i965_driver_data *i965 = i965_driver_data(ctx); |
||
155 | struct object_surface *obj_surface; |
||
156 | struct object_buffer *obj_buffer; |
||
157 | VAEncPictureParameterBufferH264 *pic_param = (VAEncPictureParameterBufferH264 *)encode_state->pic_param_ext->buffer; |
||
158 | int i; |
||
159 | |||
160 | assert(!(pic_param->CurrPic.flags & VA_PICTURE_H264_INVALID)); |
||
161 | |||
162 | if (pic_param->CurrPic.flags & VA_PICTURE_H264_INVALID) |
||
163 | goto error; |
||
164 | |||
165 | obj_surface = SURFACE(pic_param->CurrPic.picture_id); |
||
166 | assert(obj_surface); /* It is possible the store buffer isn't allocated yet */ |
||
167 | |||
168 | if (!obj_surface) |
||
169 | goto error; |
||
170 | |||
171 | encode_state->reconstructed_object = obj_surface; |
||
172 | obj_buffer = BUFFER(pic_param->coded_buf); |
||
173 | assert(obj_buffer && obj_buffer->buffer_store && obj_buffer->buffer_store->bo); |
||
174 | |||
175 | if (!obj_buffer || !obj_buffer->buffer_store || !obj_buffer->buffer_store->bo) |
||
176 | goto error; |
||
177 | |||
178 | encode_state->coded_buf_object = obj_buffer; |
||
179 | |||
180 | for (i = 0; i < 16; i++) { |
||
181 | if (pic_param->ReferenceFrames[i].flags & VA_PICTURE_H264_INVALID || |
||
182 | pic_param->ReferenceFrames[i].picture_id == VA_INVALID_SURFACE) |
||
183 | break; |
||
184 | else { |
||
185 | obj_surface = SURFACE(pic_param->ReferenceFrames[i].picture_id); |
||
186 | assert(obj_surface); |
||
187 | |||
188 | if (!obj_surface) |
||
189 | goto error; |
||
190 | |||
191 | if (obj_surface->bo) |
||
192 | encode_state->reference_objects[i] = obj_surface; |
||
193 | else |
||
194 | encode_state->reference_objects[i] = NULL; /* FIXME: Warning or Error ??? */ |
||
195 | } |
||
196 | } |
||
197 | |||
198 | for ( ; i < 16; i++) |
||
199 | encode_state->reference_objects[i] = NULL; |
||
200 | |||
201 | return VA_STATUS_SUCCESS; |
||
202 | |||
203 | error: |
||
204 | return VA_STATUS_ERROR_INVALID_PARAMETER; |
||
205 | } |
||
206 | |||
207 | static VAStatus |
||
208 | intel_encoder_check_mpeg2_parameter(VADriverContextP ctx, |
||
209 | struct encode_state *encode_state, |
||
210 | struct intel_encoder_context *encoder_context) |
||
211 | { |
||
212 | struct i965_driver_data *i965 = i965_driver_data(ctx); |
||
213 | VAEncPictureParameterBufferMPEG2 *pic_param = (VAEncPictureParameterBufferMPEG2 *)encode_state->pic_param_ext->buffer; |
||
214 | struct object_surface *obj_surface; |
||
215 | struct object_buffer *obj_buffer; |
||
216 | int i = 0; |
||
217 | |||
218 | obj_surface = SURFACE(pic_param->reconstructed_picture); |
||
219 | assert(obj_surface); /* It is possible the store buffer isn't allocated yet */ |
||
220 | |||
221 | if (!obj_surface) |
||
222 | goto error; |
||
223 | |||
224 | encode_state->reconstructed_object = obj_surface; |
||
225 | obj_buffer = BUFFER(pic_param->coded_buf); |
||
226 | assert(obj_buffer && obj_buffer->buffer_store && obj_buffer->buffer_store->bo); |
||
227 | |||
228 | if (!obj_buffer || !obj_buffer->buffer_store || !obj_buffer->buffer_store->bo) |
||
229 | goto error; |
||
230 | |||
231 | encode_state->coded_buf_object = obj_buffer; |
||
232 | |||
233 | if (pic_param->picture_type == VAEncPictureTypeIntra) { |
||
234 | } else if (pic_param->picture_type == VAEncPictureTypePredictive) { |
||
235 | assert(pic_param->forward_reference_picture != VA_INVALID_SURFACE); |
||
236 | obj_surface = SURFACE(pic_param->forward_reference_picture); |
||
237 | assert(obj_surface && obj_surface->bo); |
||
238 | |||
239 | if (!obj_surface || !obj_surface->bo) |
||
240 | goto error; |
||
241 | |||
242 | encode_state->reference_objects[i++] = obj_surface; |
||
243 | } else if (pic_param->picture_type == VAEncPictureTypeBidirectional) { |
||
244 | assert(pic_param->forward_reference_picture != VA_INVALID_SURFACE); |
||
245 | obj_surface = SURFACE(pic_param->forward_reference_picture); |
||
246 | assert(obj_surface && obj_surface->bo); |
||
247 | |||
248 | if (!obj_surface || !obj_surface->bo) |
||
249 | goto error; |
||
250 | |||
251 | encode_state->reference_objects[i++] = obj_surface; |
||
252 | |||
253 | assert(pic_param->backward_reference_picture != VA_INVALID_SURFACE); |
||
254 | obj_surface = SURFACE(pic_param->backward_reference_picture); |
||
255 | assert(obj_surface && obj_surface->bo); |
||
256 | |||
257 | if (!obj_surface || !obj_surface->bo) |
||
258 | goto error; |
||
259 | |||
260 | encode_state->reference_objects[i++] = obj_surface; |
||
261 | } else |
||
262 | goto error; |
||
263 | |||
264 | for ( ; i < 16; i++) |
||
265 | encode_state->reference_objects[i] = NULL; |
||
266 | |||
267 | return VA_STATUS_SUCCESS; |
||
268 | |||
269 | error: |
||
270 | return VA_STATUS_ERROR_INVALID_PARAMETER; |
||
271 | } |
||
272 | |||
273 | static VAStatus |
||
274 | intel_encoder_sanity_check_input(VADriverContextP ctx, |
||
275 | VAProfile profile, |
||
276 | struct encode_state *encode_state, |
||
277 | struct intel_encoder_context *encoder_context) |
||
278 | { |
||
279 | VAStatus vaStatus; |
||
280 | |||
281 | switch (profile) { |
||
282 | case VAProfileH264ConstrainedBaseline: |
||
283 | case VAProfileH264Main: |
||
284 | case VAProfileH264High: |
||
285 | case VAProfileH264MultiviewHigh: |
||
286 | case VAProfileH264StereoHigh: |
||
287 | vaStatus = intel_encoder_check_avc_parameter(ctx, encode_state, encoder_context); |
||
288 | break; |
||
289 | |||
290 | case VAProfileMPEG2Simple: |
||
291 | case VAProfileMPEG2Main: |
||
292 | vaStatus = intel_encoder_check_mpeg2_parameter(ctx, encode_state, encoder_context); |
||
293 | break; |
||
294 | |||
295 | default: |
||
296 | vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE; |
||
297 | break; |
||
298 | } |
||
299 | |||
300 | if (vaStatus != VA_STATUS_SUCCESS) |
||
301 | goto out; |
||
302 | |||
303 | vaStatus = intel_encoder_check_yuv_surface(ctx, profile, encode_state, encoder_context); |
||
304 | |||
305 | if (vaStatus == VA_STATUS_SUCCESS) |
||
306 | vaStatus = intel_encoder_check_misc_parameter(ctx, encode_state, encoder_context); |
||
307 | |||
308 | out: |
||
309 | return vaStatus; |
||
310 | } |
||
311 | |||
312 | static VAStatus |
||
313 | intel_encoder_end_picture(VADriverContextP ctx, |
||
314 | VAProfile profile, |
||
315 | union codec_state *codec_state, |
||
316 | struct hw_context *hw_context) |
||
317 | { |
||
318 | struct intel_encoder_context *encoder_context = (struct intel_encoder_context *)hw_context; |
||
319 | struct encode_state *encode_state = &codec_state->encode; |
||
320 | VAStatus vaStatus; |
||
321 | |||
322 | vaStatus = intel_encoder_sanity_check_input(ctx, profile, encode_state, encoder_context); |
||
323 | |||
324 | if (vaStatus != VA_STATUS_SUCCESS) |
||
325 | return vaStatus; |
||
326 | |||
327 | encoder_context->mfc_brc_prepare(encode_state, encoder_context); |
||
328 | |||
329 | vaStatus = encoder_context->vme_pipeline(ctx, profile, encode_state, encoder_context); |
||
330 | |||
331 | if (vaStatus == VA_STATUS_SUCCESS) |
||
332 | encoder_context->mfc_pipeline(ctx, profile, encode_state, encoder_context); |
||
333 | return VA_STATUS_SUCCESS; |
||
334 | } |
||
335 | |||
336 | static void |
||
337 | intel_encoder_context_destroy(void *hw_context) |
||
338 | { |
||
339 | struct intel_encoder_context *encoder_context = (struct intel_encoder_context *)hw_context; |
||
340 | |||
341 | encoder_context->mfc_context_destroy(encoder_context->mfc_context); |
||
342 | encoder_context->vme_context_destroy(encoder_context->vme_context); |
||
343 | intel_batchbuffer_free(encoder_context->base.batch); |
||
344 | free(encoder_context); |
||
345 | } |
||
346 | |||
347 | typedef Bool (* hw_init_func)(VADriverContextP, struct intel_encoder_context *); |
||
348 | |||
349 | static struct hw_context * |
||
350 | intel_enc_hw_context_init(VADriverContextP ctx, |
||
351 | struct object_config *obj_config, |
||
352 | hw_init_func vme_context_init, |
||
353 | hw_init_func mfc_context_init) |
||
354 | { |
||
355 | struct intel_driver_data *intel = intel_driver_data(ctx); |
||
356 | struct intel_encoder_context *encoder_context = calloc(1, sizeof(struct intel_encoder_context)); |
||
357 | int i; |
||
358 | |||
359 | encoder_context->base.destroy = intel_encoder_context_destroy; |
||
360 | encoder_context->base.run = intel_encoder_end_picture; |
||
361 | encoder_context->base.batch = intel_batchbuffer_new(intel, I915_EXEC_RENDER, 0); |
||
362 | encoder_context->input_yuv_surface = VA_INVALID_SURFACE; |
||
363 | encoder_context->is_tmp_id = 0; |
||
364 | encoder_context->rate_control_mode = VA_RC_NONE; |
||
365 | encoder_context->quality_level = ENCODER_DEFAULT_QUALITY; |
||
366 | encoder_context->quality_range = 1; |
||
367 | |||
368 | switch (obj_config->profile) { |
||
369 | case VAProfileMPEG2Simple: |
||
370 | case VAProfileMPEG2Main: |
||
371 | encoder_context->codec = CODEC_MPEG2; |
||
372 | break; |
||
373 | |||
374 | case VAProfileH264ConstrainedBaseline: |
||
375 | case VAProfileH264Main: |
||
376 | case VAProfileH264High: |
||
377 | encoder_context->codec = CODEC_H264; |
||
378 | encoder_context->quality_range = ENCODER_QUALITY_RANGE; |
||
379 | break; |
||
380 | |||
381 | case VAProfileH264StereoHigh: |
||
382 | case VAProfileH264MultiviewHigh: |
||
383 | encoder_context->codec = CODEC_H264_MVC; |
||
384 | break; |
||
385 | |||
386 | default: |
||
387 | /* Never get here */ |
||
388 | assert(0); |
||
389 | break; |
||
390 | } |
||
391 | |||
392 | for (i = 0; i < obj_config->num_attribs; i++) { |
||
393 | if (obj_config->attrib_list[i].type == VAConfigAttribRateControl) { |
||
394 | encoder_context->rate_control_mode = obj_config->attrib_list[i].value; |
||
395 | |||
396 | if (encoder_context->codec == CODEC_MPEG2 && |
||
397 | encoder_context->rate_control_mode & VA_RC_CBR) { |
||
398 | WARN_ONCE("Don't support CBR for MPEG-2 encoding\n"); |
||
399 | encoder_context->rate_control_mode &= ~VA_RC_CBR; |
||
400 | } |
||
401 | |||
402 | break; |
||
403 | } |
||
404 | } |
||
405 | |||
406 | vme_context_init(ctx, encoder_context); |
||
407 | assert(encoder_context->vme_context); |
||
408 | assert(encoder_context->vme_context_destroy); |
||
409 | assert(encoder_context->vme_pipeline); |
||
410 | |||
411 | mfc_context_init(ctx, encoder_context); |
||
412 | assert(encoder_context->mfc_context); |
||
413 | assert(encoder_context->mfc_context_destroy); |
||
414 | assert(encoder_context->mfc_pipeline); |
||
415 | |||
416 | return (struct hw_context *)encoder_context; |
||
417 | } |
||
418 | |||
419 | struct hw_context * |
||
420 | gen6_enc_hw_context_init(VADriverContextP ctx, struct object_config *obj_config) |
||
421 | { |
||
422 | return intel_enc_hw_context_init(ctx, obj_config, gen6_vme_context_init, gen6_mfc_context_init); |
||
423 | } |
||
424 | |||
425 | struct hw_context * |
||
426 | gen7_enc_hw_context_init(VADriverContextP ctx, struct object_config *obj_config) |
||
427 | { |
||
428 | |||
429 | return intel_enc_hw_context_init(ctx, obj_config, gen7_vme_context_init, gen7_mfc_context_init); |
||
430 | } |
||
431 | |||
432 | struct hw_context * |
||
433 | gen75_enc_hw_context_init(VADriverContextP ctx, struct object_config *obj_config) |
||
434 | { |
||
435 | return intel_enc_hw_context_init(ctx, obj_config, gen75_vme_context_init, gen75_mfc_context_init); |
||
436 | } |
||
437 | |||
438 | struct hw_context * |
||
439 | gen8_enc_hw_context_init(VADriverContextP ctx, struct object_config *obj_config) |
||
440 | { |
||
441 | return intel_enc_hw_context_init(ctx, obj_config, gen8_vme_context_init, gen8_mfc_context_init); |
||
442 | }>>>> |
||
443 |