OSDN Git Service

3c5af18b0e197919c494188cc98d795836ab57e7
[android-x86/hardware-intel-intel-driver.git] / src / i965_encoder.c
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 <chang.zhou@intel.com>
26  *
27  */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <assert.h>
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 #include "gen9_mfc.h"
43
44 extern Bool gen6_mfc_context_init(VADriverContextP ctx, struct intel_encoder_context *encoder_context);
45 extern Bool gen6_vme_context_init(VADriverContextP ctx, struct intel_encoder_context *encoder_context);
46 extern Bool gen7_mfc_context_init(VADriverContextP ctx, struct intel_encoder_context *encoder_context);
47 extern Bool gen9_hcpe_context_init(VADriverContextP ctx, struct intel_encoder_context *encoder_context);
48
49 static VAStatus
50 intel_encoder_check_yuv_surface(VADriverContextP ctx,
51                                 VAProfile profile,
52                                 struct encode_state *encode_state,
53                                 struct intel_encoder_context *encoder_context)
54 {
55     struct i965_driver_data *i965 = i965_driver_data(ctx);
56     struct i965_surface src_surface, dst_surface;
57     struct object_surface *obj_surface;
58     VAStatus status;
59     VARectangle rect;
60
61     /* releae the temporary surface */
62     if (encoder_context->is_tmp_id) {
63         i965_DestroySurfaces(ctx, &encoder_context->input_yuv_surface, 1);
64         encode_state->input_yuv_object = NULL;
65     }
66
67     encoder_context->is_tmp_id = 0;
68     obj_surface = SURFACE(encode_state->current_render_target);
69     assert(obj_surface && obj_surface->bo);
70
71     if (!obj_surface || !obj_surface->bo)
72         return VA_STATUS_ERROR_INVALID_PARAMETER;
73
74     if (obj_surface->fourcc == VA_FOURCC_NV12) {
75         unsigned int tiling = 0, swizzle = 0;
76
77         dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
78
79         if (tiling == I915_TILING_Y) {
80             encoder_context->input_yuv_surface = encode_state->current_render_target;
81             encode_state->input_yuv_object = obj_surface;
82             return VA_STATUS_SUCCESS;
83         }
84     }
85
86     rect.x = 0;
87     rect.y = 0;
88     rect.width = obj_surface->orig_width;
89     rect.height = obj_surface->orig_height;
90     
91     src_surface.base = (struct object_base *)obj_surface;
92     src_surface.type = I965_SURFACE_TYPE_SURFACE;
93     src_surface.flags = I965_SURFACE_FLAG_FRAME;
94     
95     status = i965_CreateSurfaces(ctx,
96                                  obj_surface->orig_width,
97                                  obj_surface->orig_height,
98                                  VA_RT_FORMAT_YUV420,
99                                  1,
100                                  &encoder_context->input_yuv_surface);
101     assert(status == VA_STATUS_SUCCESS);
102
103     if (status != VA_STATUS_SUCCESS)
104         return status;
105
106     obj_surface = SURFACE(encoder_context->input_yuv_surface);
107     encode_state->input_yuv_object = obj_surface;
108     assert(obj_surface);
109     i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
110     
111     dst_surface.base = (struct object_base *)obj_surface;
112     dst_surface.type = I965_SURFACE_TYPE_SURFACE;
113     dst_surface.flags = I965_SURFACE_FLAG_FRAME;
114
115     status = i965_image_processing(ctx,
116                                    &src_surface,
117                                    &rect,
118                                    &dst_surface,
119                                    &rect);
120     assert(status == VA_STATUS_SUCCESS);
121
122     encoder_context->is_tmp_id = 1;
123
124     return VA_STATUS_SUCCESS;
125 }
126
127
128 static VAStatus
129 intel_encoder_check_jpeg_yuv_surface(VADriverContextP ctx,
130                                 VAProfile profile,
131                                 struct encode_state *encode_state,
132                                 struct intel_encoder_context *encoder_context)
133 {
134     struct i965_driver_data *i965 = i965_driver_data(ctx);
135     struct i965_surface src_surface, dst_surface;
136     struct object_surface *obj_surface;
137     VAStatus status;
138     VARectangle rect;
139     int format=0, fourcc=0, subsample=0;
140
141     /* releae the temporary surface */
142     if (encoder_context->is_tmp_id) {
143         i965_DestroySurfaces(ctx, &encoder_context->input_yuv_surface, 1);
144         encode_state->input_yuv_object = NULL;
145     }
146
147     encoder_context->is_tmp_id = 0;
148     obj_surface = SURFACE(encode_state->current_render_target);
149     assert(obj_surface && obj_surface->bo);
150
151     if (!obj_surface || !obj_surface->bo)
152         return VA_STATUS_ERROR_INVALID_PARAMETER;
153
154     unsigned int tiling = 0, swizzle = 0;
155
156     dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
157
158     if (tiling == I915_TILING_Y) {
159         if( (obj_surface->fourcc==VA_FOURCC_NV12)  || (obj_surface->fourcc==VA_FOURCC_UYVY) ||
160             (obj_surface->fourcc==VA_FOURCC_YUY2)  || (obj_surface->fourcc==VA_FOURCC_Y800) ||
161             (obj_surface->fourcc==VA_FOURCC_RGBA)  || (obj_surface->fourcc==VA_FOURCC_444P) ) {
162             encoder_context->input_yuv_surface = encode_state->current_render_target;
163             encode_state->input_yuv_object = obj_surface;
164             return VA_STATUS_SUCCESS;
165         }
166     }
167
168     rect.x = 0;
169     rect.y = 0;
170     rect.width = obj_surface->orig_width;
171     rect.height = obj_surface->orig_height;
172
173     src_surface.base = (struct object_base *)obj_surface;
174     src_surface.type = I965_SURFACE_TYPE_SURFACE;
175     src_surface.flags = I965_SURFACE_FLAG_FRAME;
176
177     switch( obj_surface->fourcc) {
178
179         case VA_FOURCC_YUY2:
180             fourcc = VA_FOURCC_YUY2;
181             format = VA_RT_FORMAT_YUV422;
182             subsample = SUBSAMPLE_YUV422H;
183             break;
184
185         case VA_FOURCC_UYVY:
186             fourcc = VA_FOURCC_UYVY;
187             format = VA_RT_FORMAT_YUV422;
188             subsample = SUBSAMPLE_YUV422H;
189             break;
190
191         case VA_FOURCC_Y800:
192             fourcc = VA_FOURCC_Y800;
193             format = VA_RT_FORMAT_YUV400;
194             subsample = SUBSAMPLE_YUV400;
195             break;
196
197         case VA_FOURCC_444P:
198             fourcc = VA_FOURCC_444P;
199             format = VA_RT_FORMAT_YUV444;
200             subsample = SUBSAMPLE_YUV444;
201             break;
202
203         case VA_FOURCC_RGBA:
204             fourcc = VA_FOURCC_RGBA;
205             format = VA_RT_FORMAT_RGB32;
206             subsample = SUBSAMPLE_RGBX;
207             break;
208
209         default: //All other scenarios will have NV12 format
210             fourcc = VA_FOURCC_NV12;
211             format = VA_RT_FORMAT_YUV420;
212             subsample = SUBSAMPLE_YUV420;
213             break;
214     }
215
216     status = i965_CreateSurfaces(ctx,
217                                  obj_surface->orig_width,
218                                  obj_surface->orig_height,
219                                  format,
220                                  1,
221                                  &encoder_context->input_yuv_surface);
222     assert(status == VA_STATUS_SUCCESS);
223
224     if (status != VA_STATUS_SUCCESS)
225         return status;
226
227     obj_surface = SURFACE(encoder_context->input_yuv_surface);
228     encode_state->input_yuv_object = obj_surface;
229     assert(obj_surface);
230     i965_check_alloc_surface_bo(ctx, obj_surface, 1, fourcc, subsample);
231
232     dst_surface.base = (struct object_base *)obj_surface;
233     dst_surface.type = I965_SURFACE_TYPE_SURFACE;
234     dst_surface.flags = I965_SURFACE_FLAG_FRAME;
235
236     //The Y800 format is expected to be tiled.
237     //Linear Y800 is a corner case and needs code in the i965_image_processing.
238     if(obj_surface->fourcc != VA_FOURCC_Y800){
239         status = i965_image_processing(ctx,
240                                    &src_surface,
241                                    &rect,
242                                    &dst_surface,
243                                    &rect);
244         assert(status == VA_STATUS_SUCCESS);
245     }
246
247     encoder_context->is_tmp_id = 1;
248
249     return VA_STATUS_SUCCESS;
250 }
251
252 static VAStatus
253 intel_encoder_check_misc_parameter(VADriverContextP ctx,
254                                   struct encode_state *encode_state,
255                                   struct intel_encoder_context *encoder_context)
256 {
257
258     if (encode_state->misc_param[VAEncMiscParameterTypeQualityLevel] &&
259         encode_state->misc_param[VAEncMiscParameterTypeQualityLevel]->buffer) {
260         VAEncMiscParameterBuffer* pMiscParam = (VAEncMiscParameterBuffer*)encode_state->misc_param[VAEncMiscParameterTypeQualityLevel]->buffer;
261         VAEncMiscParameterBufferQualityLevel* param_quality_level = (VAEncMiscParameterBufferQualityLevel*)pMiscParam->data;
262         encoder_context->quality_level = param_quality_level->quality_level;
263
264         if (encoder_context->quality_level == 0)
265             encoder_context->quality_level = ENCODER_DEFAULT_QUALITY;
266         else if (encoder_context->quality_level > encoder_context->quality_range)
267             goto error;
268    }
269
270     return VA_STATUS_SUCCESS;
271
272 error:
273     return VA_STATUS_ERROR_INVALID_PARAMETER;
274 }
275
276 static VAStatus
277 intel_encoder_check_avc_parameter(VADriverContextP ctx,
278                                   struct encode_state *encode_state,
279                                   struct intel_encoder_context *encoder_context)
280 {
281     struct i965_driver_data *i965 = i965_driver_data(ctx);
282     struct object_surface *obj_surface; 
283     struct object_buffer *obj_buffer;
284     VAEncPictureParameterBufferH264 *pic_param = (VAEncPictureParameterBufferH264 *)encode_state->pic_param_ext->buffer;
285     int i;
286
287     assert(!(pic_param->CurrPic.flags & VA_PICTURE_H264_INVALID));
288
289     if (pic_param->CurrPic.flags & VA_PICTURE_H264_INVALID)
290         goto error;
291
292     obj_surface = SURFACE(pic_param->CurrPic.picture_id);
293     assert(obj_surface); /* It is possible the store buffer isn't allocated yet */
294     
295     if (!obj_surface)
296         goto error;
297
298     encode_state->reconstructed_object = obj_surface;
299     obj_buffer = BUFFER(pic_param->coded_buf);
300     assert(obj_buffer && obj_buffer->buffer_store && obj_buffer->buffer_store->bo);
301
302     if (!obj_buffer || !obj_buffer->buffer_store || !obj_buffer->buffer_store->bo)
303         goto error;
304
305     encode_state->coded_buf_object = obj_buffer;
306
307     for (i = 0; i < 16; i++) {
308         if (pic_param->ReferenceFrames[i].flags & VA_PICTURE_H264_INVALID ||
309             pic_param->ReferenceFrames[i].picture_id == VA_INVALID_SURFACE)
310             break;
311         else {
312             obj_surface = SURFACE(pic_param->ReferenceFrames[i].picture_id);
313             assert(obj_surface);
314
315             if (!obj_surface)
316                 goto error;
317
318             if (obj_surface->bo)
319                 encode_state->reference_objects[i] = obj_surface;
320             else
321                 encode_state->reference_objects[i] = NULL; /* FIXME: Warning or Error ??? */
322         }
323     }
324
325     for ( ; i < 16; i++)
326         encode_state->reference_objects[i] = NULL;
327     
328     return VA_STATUS_SUCCESS;
329
330 error:
331     return VA_STATUS_ERROR_INVALID_PARAMETER;
332 }
333
334 static VAStatus
335 intel_encoder_check_mpeg2_parameter(VADriverContextP ctx,
336                                     struct encode_state *encode_state,
337                                     struct intel_encoder_context *encoder_context)
338 {
339     struct i965_driver_data *i965 = i965_driver_data(ctx);
340     VAEncPictureParameterBufferMPEG2 *pic_param = (VAEncPictureParameterBufferMPEG2 *)encode_state->pic_param_ext->buffer;
341     struct object_surface *obj_surface; 
342     struct object_buffer *obj_buffer;
343     int i = 0;
344     
345     obj_surface = SURFACE(pic_param->reconstructed_picture);
346     assert(obj_surface); /* It is possible the store buffer isn't allocated yet */
347     
348     if (!obj_surface)
349         goto error;
350     
351     encode_state->reconstructed_object = obj_surface;    
352     obj_buffer = BUFFER(pic_param->coded_buf);
353     assert(obj_buffer && obj_buffer->buffer_store && obj_buffer->buffer_store->bo);
354
355     if (!obj_buffer || !obj_buffer->buffer_store || !obj_buffer->buffer_store->bo)
356         goto error;
357
358     encode_state->coded_buf_object = obj_buffer;
359
360     if (pic_param->picture_type == VAEncPictureTypeIntra) {
361     } else if (pic_param->picture_type == VAEncPictureTypePredictive) {
362         assert(pic_param->forward_reference_picture != VA_INVALID_SURFACE);
363         obj_surface = SURFACE(pic_param->forward_reference_picture);
364         assert(obj_surface && obj_surface->bo);
365
366         if (!obj_surface || !obj_surface->bo)
367             goto error;
368
369         encode_state->reference_objects[i++] = obj_surface;
370     } else if (pic_param->picture_type == VAEncPictureTypeBidirectional) {
371         assert(pic_param->forward_reference_picture != VA_INVALID_SURFACE);
372         obj_surface = SURFACE(pic_param->forward_reference_picture);
373         assert(obj_surface && obj_surface->bo);
374
375         if (!obj_surface || !obj_surface->bo)
376             goto error;
377
378         encode_state->reference_objects[i++] = obj_surface;
379
380         assert(pic_param->backward_reference_picture != VA_INVALID_SURFACE);
381         obj_surface = SURFACE(pic_param->backward_reference_picture);
382         assert(obj_surface && obj_surface->bo);
383
384         if (!obj_surface || !obj_surface->bo)
385             goto error;
386
387         encode_state->reference_objects[i++] = obj_surface;
388     } else 
389         goto error;
390
391     for ( ; i < 16; i++)
392         encode_state->reference_objects[i] = NULL;
393
394     return VA_STATUS_SUCCESS;
395
396 error:
397     return VA_STATUS_ERROR_INVALID_PARAMETER;
398 }
399
400 static VAStatus
401 intel_encoder_check_jpeg_parameter(VADriverContextP ctx,
402                                   struct encode_state *encode_state,
403                                   struct intel_encoder_context *encoder_context)
404 {
405     struct i965_driver_data *i965 = i965_driver_data(ctx);
406     struct object_buffer *obj_buffer;
407     VAEncPictureParameterBufferJPEG *pic_param = (VAEncPictureParameterBufferJPEG *)encode_state->pic_param_ext->buffer;
408
409
410     assert(!(pic_param->pic_flags.bits.profile)); //Baseline profile is 0.
411
412     obj_buffer = BUFFER(pic_param->coded_buf);
413     assert(obj_buffer && obj_buffer->buffer_store && obj_buffer->buffer_store->bo);
414
415     if (!obj_buffer || !obj_buffer->buffer_store || !obj_buffer->buffer_store->bo)
416         goto error;
417
418     encode_state->coded_buf_object = obj_buffer;
419
420     return VA_STATUS_SUCCESS;
421
422 error:
423     return VA_STATUS_ERROR_INVALID_PARAMETER;
424 }
425
426 static VAStatus
427 intel_encoder_check_vp8_parameter(VADriverContextP ctx,
428                                     struct encode_state *encode_state,
429                                     struct intel_encoder_context *encoder_context)
430 {
431     struct i965_driver_data *i965 = i965_driver_data(ctx);
432     VAEncPictureParameterBufferVP8 *pic_param = (VAEncPictureParameterBufferVP8 *)encode_state->pic_param_ext->buffer;
433     struct object_surface *obj_surface;
434     struct object_buffer *obj_buffer;
435     int i = 0;
436     int is_key_frame = !pic_param->pic_flags.bits.frame_type;
437  
438     obj_surface = SURFACE(pic_param->reconstructed_frame);
439     assert(obj_surface); /* It is possible the store buffer isn't allocated yet */
440     
441     if (!obj_surface)
442         goto error;
443     
444     encode_state->reconstructed_object = obj_surface;    
445     obj_buffer = BUFFER(pic_param->coded_buf);
446     assert(obj_buffer && obj_buffer->buffer_store && obj_buffer->buffer_store->bo);
447
448     if (!obj_buffer || !obj_buffer->buffer_store || !obj_buffer->buffer_store->bo)
449         goto error;
450
451     encode_state->coded_buf_object = obj_buffer;
452
453     if (!is_key_frame) {
454         assert(pic_param->ref_last_frame != VA_INVALID_SURFACE);
455         obj_surface = SURFACE(pic_param->ref_last_frame);
456         assert(obj_surface && obj_surface->bo);
457
458         if (!obj_surface || !obj_surface->bo)
459             goto error;
460
461         encode_state->reference_objects[i++] = obj_surface;
462
463         assert(pic_param->ref_gf_frame != VA_INVALID_SURFACE);
464         obj_surface = SURFACE(pic_param->ref_gf_frame);
465         assert(obj_surface && obj_surface->bo);
466
467         if (!obj_surface || !obj_surface->bo)
468             goto error;
469
470         encode_state->reference_objects[i++] = obj_surface;
471
472         assert(pic_param->ref_arf_frame != VA_INVALID_SURFACE);
473         obj_surface = SURFACE(pic_param->ref_arf_frame);
474         assert(obj_surface && obj_surface->bo);
475
476         if (!obj_surface || !obj_surface->bo)
477             goto error;
478
479         encode_state->reference_objects[i++] = obj_surface;
480     }
481
482     for ( ; i < 16; i++)
483         encode_state->reference_objects[i] = NULL;
484
485     return VA_STATUS_SUCCESS;
486
487 error:
488     return VA_STATUS_ERROR_INVALID_PARAMETER;
489 }
490
491 static VAStatus
492 intel_encoder_check_hevc_parameter(VADriverContextP ctx,
493                                   struct encode_state *encode_state,
494                                   struct intel_encoder_context *encoder_context)
495 {
496     struct i965_driver_data *i965 = i965_driver_data(ctx);
497     struct object_surface *obj_surface; 
498     struct object_buffer *obj_buffer;
499     VAEncPictureParameterBufferHEVC *pic_param = (VAEncPictureParameterBufferHEVC *)encode_state->pic_param_ext->buffer;
500     VAEncSliceParameterBufferHEVC *slice_param;
501     int i;
502
503     assert(!(pic_param->decoded_curr_pic.flags & VA_PICTURE_HEVC_INVALID));
504
505     if (pic_param->decoded_curr_pic.flags & VA_PICTURE_HEVC_INVALID)
506         goto error;
507
508     obj_surface = SURFACE(pic_param->decoded_curr_pic.picture_id);
509     assert(obj_surface); /* It is possible the store buffer isn't allocated yet */
510     
511     if (!obj_surface)
512         goto error;
513
514     encode_state->reconstructed_object = obj_surface;
515     obj_buffer = BUFFER(pic_param->coded_buf);
516     assert(obj_buffer && obj_buffer->buffer_store && obj_buffer->buffer_store->bo);
517
518     if (!obj_buffer || !obj_buffer->buffer_store || !obj_buffer->buffer_store->bo)
519         goto error;
520
521     encode_state->coded_buf_object = obj_buffer;
522
523     for (i = 0; i < 15; i++) {
524         if (pic_param->reference_frames[i].flags & VA_PICTURE_HEVC_INVALID ||
525             pic_param->reference_frames[i].picture_id == VA_INVALID_SURFACE)
526             break;
527         else {
528             obj_surface = SURFACE(pic_param->reference_frames[i].picture_id);
529             assert(obj_surface);
530
531             if (!obj_surface)
532                 goto error;
533
534             if (obj_surface->bo)
535                 encode_state->reference_objects[i] = obj_surface;
536             else
537                 encode_state->reference_objects[i] = NULL; /* FIXME: Warning or Error ??? */
538         }
539     }
540
541     for ( ; i < 15; i++)
542         encode_state->reference_objects[i] = NULL;
543
544     for (i = 0; i < encode_state->num_slice_params_ext; i++) {
545         slice_param = (VAEncSliceParameterBufferHEVC *)encode_state->slice_params_ext[i]->buffer;
546
547         if (slice_param->slice_type != HEVC_SLICE_I &&
548             slice_param->slice_type != HEVC_SLICE_P &&
549             slice_param->slice_type != HEVC_SLICE_B)
550             goto error;
551
552         /* TODO: add more check here */
553     }
554
555     return VA_STATUS_SUCCESS;
556
557 error:
558     return VA_STATUS_ERROR_INVALID_PARAMETER;
559 }
560 static VAStatus
561 intel_encoder_sanity_check_input(VADriverContextP ctx,
562                                  VAProfile profile,
563                                  struct encode_state *encode_state,
564                                  struct intel_encoder_context *encoder_context)
565 {
566     VAStatus vaStatus;
567
568     switch (profile) {
569     case VAProfileH264ConstrainedBaseline:
570     case VAProfileH264Main:
571     case VAProfileH264High:
572     case VAProfileH264MultiviewHigh:
573     case VAProfileH264StereoHigh: {
574         vaStatus = intel_encoder_check_avc_parameter(ctx, encode_state, encoder_context);
575         if (vaStatus != VA_STATUS_SUCCESS)
576             goto out;
577         vaStatus = intel_encoder_check_yuv_surface(ctx, profile, encode_state, encoder_context);
578         break;
579     }
580
581     case VAProfileMPEG2Simple:
582     case VAProfileMPEG2Main: {
583         vaStatus = intel_encoder_check_mpeg2_parameter(ctx, encode_state, encoder_context);
584         if (vaStatus != VA_STATUS_SUCCESS)
585             goto out;
586         vaStatus = intel_encoder_check_yuv_surface(ctx, profile, encode_state, encoder_context);
587         break;
588     }
589
590     case VAProfileJPEGBaseline:  {
591         vaStatus = intel_encoder_check_jpeg_parameter(ctx, encode_state, encoder_context);
592         if (vaStatus != VA_STATUS_SUCCESS)
593             goto out;
594         vaStatus = intel_encoder_check_jpeg_yuv_surface(ctx, profile, encode_state, encoder_context);
595         break;
596     }
597  
598     case VAProfileVP8Version0_3: {
599         vaStatus = intel_encoder_check_vp8_parameter(ctx, encode_state, encoder_context);
600          if (vaStatus != VA_STATUS_SUCCESS)
601             goto out;
602         vaStatus = intel_encoder_check_yuv_surface(ctx, profile, encode_state, encoder_context);
603         break;
604     }
605
606     case VAProfileHEVCMain:  {
607         vaStatus = intel_encoder_check_hevc_parameter(ctx, encode_state, encoder_context);
608         if (vaStatus != VA_STATUS_SUCCESS)
609             goto out;
610         vaStatus = intel_encoder_check_yuv_surface(ctx, profile, encode_state, encoder_context);
611         break;
612     }
613     default:
614         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
615         break;
616     }
617
618     if (vaStatus == VA_STATUS_SUCCESS)
619         vaStatus = intel_encoder_check_misc_parameter(ctx, encode_state, encoder_context);
620
621 out:    
622     return vaStatus;
623 }
624  
625 static VAStatus
626 intel_encoder_end_picture(VADriverContextP ctx, 
627                           VAProfile profile, 
628                           union codec_state *codec_state,
629                           struct hw_context *hw_context)
630 {
631     struct intel_encoder_context *encoder_context = (struct intel_encoder_context *)hw_context;
632     struct encode_state *encode_state = &codec_state->encode;
633     VAStatus vaStatus;
634
635     vaStatus = intel_encoder_sanity_check_input(ctx, profile, encode_state, encoder_context);
636
637     if (vaStatus != VA_STATUS_SUCCESS)
638         return vaStatus;
639
640     encoder_context->mfc_brc_prepare(encode_state, encoder_context);
641
642     if((encoder_context->vme_context && encoder_context->vme_pipeline)) {
643         vaStatus = encoder_context->vme_pipeline(ctx, profile, encode_state, encoder_context);
644     }
645
646     if (vaStatus == VA_STATUS_SUCCESS)
647         encoder_context->mfc_pipeline(ctx, profile, encode_state, encoder_context);
648     return VA_STATUS_SUCCESS;
649 }
650
651 static void
652 intel_encoder_context_destroy(void *hw_context)
653 {
654     struct intel_encoder_context *encoder_context = (struct intel_encoder_context *)hw_context;
655
656     encoder_context->mfc_context_destroy(encoder_context->mfc_context);
657
658     if (encoder_context->vme_context_destroy && encoder_context->vme_context)
659        encoder_context->vme_context_destroy(encoder_context->vme_context);
660
661     intel_batchbuffer_free(encoder_context->base.batch);
662     free(encoder_context);
663 }
664
665
666 static VAStatus
667 intel_encoder_get_status(VADriverContextP ctx, struct hw_context *hw_context, void *buffer)
668 {
669     struct intel_encoder_context *encoder_context = (struct intel_encoder_context *)hw_context;
670     struct i965_coded_buffer_segment *coded_buffer_segment = (struct i965_coded_buffer_segment *)buffer;
671
672     if (encoder_context->get_status)
673         return encoder_context->get_status(ctx, encoder_context, coded_buffer_segment);
674
675     return VA_STATUS_ERROR_UNIMPLEMENTED;
676 }
677
678 typedef Bool (* hw_init_func)(VADriverContextP, struct intel_encoder_context *);
679
680 static struct hw_context *
681 intel_enc_hw_context_init(VADriverContextP ctx,
682                           struct object_config *obj_config,
683                           hw_init_func vme_context_init,
684                           hw_init_func mfc_context_init)
685 {
686     struct intel_driver_data *intel = intel_driver_data(ctx);
687     struct intel_encoder_context *encoder_context = calloc(1, sizeof(struct intel_encoder_context));
688     int i;
689
690     assert(encoder_context);
691     encoder_context->base.destroy = intel_encoder_context_destroy;
692     encoder_context->base.run = intel_encoder_end_picture;
693     encoder_context->base.get_status = intel_encoder_get_status;
694     encoder_context->base.batch = intel_batchbuffer_new(intel, I915_EXEC_RENDER, 0);
695     encoder_context->input_yuv_surface = VA_INVALID_SURFACE;
696     encoder_context->is_tmp_id = 0;
697     encoder_context->rate_control_mode = VA_RC_NONE;
698     encoder_context->quality_level = ENCODER_DEFAULT_QUALITY;
699     encoder_context->quality_range = 1;
700
701     switch (obj_config->profile) {
702     case VAProfileMPEG2Simple:
703     case VAProfileMPEG2Main:
704         encoder_context->codec = CODEC_MPEG2;
705         break;
706         
707     case VAProfileH264ConstrainedBaseline:
708     case VAProfileH264Main:
709     case VAProfileH264High:
710         encoder_context->codec = CODEC_H264;
711         encoder_context->quality_range = ENCODER_QUALITY_RANGE;
712         break;
713
714     case VAProfileH264StereoHigh:
715     case VAProfileH264MultiviewHigh:
716         encoder_context->codec = CODEC_H264_MVC;
717         break;
718         
719     case VAProfileJPEGBaseline:
720         encoder_context->codec = CODEC_JPEG;
721         break;
722
723     case VAProfileVP8Version0_3:
724         encoder_context->codec = CODEC_VP8;
725         break;
726
727     case VAProfileHEVCMain:
728         encoder_context->codec = CODEC_HEVC;
729         break;
730
731     default:
732         /* Never get here */
733         assert(0);
734         break;
735     }
736
737     for (i = 0; i < obj_config->num_attribs; i++) {
738         if (obj_config->attrib_list[i].type == VAConfigAttribRateControl) {
739             encoder_context->rate_control_mode = obj_config->attrib_list[i].value;
740
741             if (encoder_context->codec == CODEC_MPEG2 &&
742                 encoder_context->rate_control_mode & VA_RC_CBR) {
743                 WARN_ONCE("Don't support CBR for MPEG-2 encoding\n");
744                 encoder_context->rate_control_mode &= ~VA_RC_CBR;
745             }
746
747             break;
748         }
749     }
750
751     vme_context_init(ctx, encoder_context);
752     if(obj_config->profile != VAProfileJPEGBaseline) {
753         assert(encoder_context->vme_context);
754         assert(encoder_context->vme_context_destroy);
755         assert(encoder_context->vme_pipeline);
756     }
757
758     mfc_context_init(ctx, encoder_context);
759     assert(encoder_context->mfc_context);
760     assert(encoder_context->mfc_context_destroy);
761     assert(encoder_context->mfc_pipeline);
762
763     return (struct hw_context *)encoder_context;
764 }
765
766 struct hw_context *
767 gen6_enc_hw_context_init(VADriverContextP ctx, struct object_config *obj_config)
768 {
769     return intel_enc_hw_context_init(ctx, obj_config, gen6_vme_context_init, gen6_mfc_context_init);
770 }
771
772 struct hw_context *
773 gen7_enc_hw_context_init(VADriverContextP ctx, struct object_config *obj_config)
774 {
775
776     return intel_enc_hw_context_init(ctx, obj_config, gen7_vme_context_init, gen7_mfc_context_init);
777 }
778
779 struct hw_context *
780 gen75_enc_hw_context_init(VADriverContextP ctx, struct object_config *obj_config)
781 {
782     return intel_enc_hw_context_init(ctx, obj_config, gen75_vme_context_init, gen75_mfc_context_init);
783 }
784
785 struct hw_context *
786 gen8_enc_hw_context_init(VADriverContextP ctx, struct object_config *obj_config)
787 {
788     return intel_enc_hw_context_init(ctx, obj_config, gen8_vme_context_init, gen8_mfc_context_init);
789 }
790
791 struct hw_context *
792 gen9_enc_hw_context_init(VADriverContextP ctx, struct object_config *obj_config)
793 {
794     if (obj_config->profile == VAProfileHEVCMain) {
795         return intel_enc_hw_context_init(ctx, obj_config, gen9_vme_context_init, gen9_hcpe_context_init);
796     } else if (obj_config->profile == VAProfileJPEGBaseline)
797         return intel_enc_hw_context_init(ctx, obj_config, gen8_vme_context_init, gen8_mfc_context_init);
798     else
799         return intel_enc_hw_context_init(ctx, obj_config, gen9_vme_context_init, gen9_mfc_context_init);
800 }