Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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.  
  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.  
  444.