예제 #1
0
static GstAmcFormat *
create_amc_format (GstAmcVideoEnc * encoder, GstVideoCodecState * input_state,
    GstCaps * src_caps)
{
  GstAmcVideoEncClass *klass;
  GstStructure *s;
  const gchar *name;
  const gchar *mime = NULL;
  const gchar *profile_string = NULL;
  const gchar *level_string = NULL;
  struct
  {
    const gchar *key;
    gint id;
  } amc_profile = {
  NULL, -1};
  struct
  {
    const gchar *key;
    gint id;
  } amc_level = {
  NULL, -1};
  gint color_format;
  gint stride, slice_height;
  GstAmcFormat *format = NULL;
  GstVideoInfo *info = &input_state->info;
  GError *err = NULL;

  klass = GST_AMC_VIDEO_ENC_GET_CLASS (encoder);
  s = gst_caps_get_structure (src_caps, 0);
  if (!s)
    return NULL;

  name = gst_structure_get_name (s);
  profile_string = gst_structure_get_string (s, "profile");
  level_string = gst_structure_get_string (s, "level");

  if (strcmp (name, "video/mpeg") == 0) {
    gint mpegversion;

    if (!gst_structure_get_int (s, "mpegversion", &mpegversion))
      return NULL;

    if (mpegversion == 4) {
      mime = "video/mp4v-es";

      if (profile_string) {
        amc_profile.key = "profile";    /* named profile ? */
        amc_profile.id = gst_amc_mpeg4_profile_from_string (profile_string);
      }

      if (level_string) {
        amc_level.key = "level";        /* named level ? */
        amc_level.id = gst_amc_mpeg4_level_from_string (level_string);
      }
    } else if ( /* mpegversion == 1 || */ mpegversion == 2)
      mime = "video/mpeg2";
  } else if (strcmp (name, "video/x-h263") == 0) {
    mime = "video/3gpp";
  } else if (strcmp (name, "video/x-h264") == 0) {
    mime = "video/avc";

    if (profile_string) {
      amc_profile.key = "profile";      /* named profile ? */
      amc_profile.id = gst_amc_avc_profile_from_string (profile_string);
    }

    if (level_string) {
      amc_level.key = "level";  /* named level ? */
      amc_level.id = gst_amc_avc_level_from_string (level_string);
    }
  } else if (strcmp (name, "video/x-vp8") == 0) {
    mime = "video/x-vnd.on2.vp8";
  } else {
    GST_ERROR_OBJECT (encoder, "Failed to convert caps(%s/...) to any mime",
        name);
    return NULL;
  }

  format = gst_amc_format_new_video (mime, info->width, info->height, &err);
  if (!format) {
    GST_ERROR_OBJECT (encoder, "Failed to create a \"%s,%dx%d\" MediaFormat",
        mime, info->width, info->height);
    GST_ELEMENT_ERROR_FROM_ERROR (encoder, err);
    return NULL;
  }

  color_format =
      gst_amc_video_format_to_color_format (klass->codec_info,
      mime, info->finfo->format);
  if (color_format == -1)
    goto video_format_failed_to_convert;

  gst_amc_format_set_int (format, "bitrate", encoder->bitrate, &err);
  if (err)
    GST_ELEMENT_WARNING_FROM_ERROR (encoder, err);
  gst_amc_format_set_int (format, "color-format", color_format, &err);
  if (err)
    GST_ELEMENT_WARNING_FROM_ERROR (encoder, err);
  stride = GST_ROUND_UP_4 (info->width);        /* safe (?) */
  gst_amc_format_set_int (format, "stride", stride, &err);
  if (err)
    GST_ELEMENT_WARNING_FROM_ERROR (encoder, err);
  slice_height = info->height;
  gst_amc_format_set_int (format, "slice-height", slice_height, &err);
  if (err)
    GST_ELEMENT_WARNING_FROM_ERROR (encoder, err);

  if (profile_string) {
    if (amc_profile.id == -1)
      goto unsupported_profile;

    /* FIXME: Set to any value in AVCProfile* leads to
     * codec configuration fail */
    /* gst_amc_format_set_int (format, amc_profile.key, 0x40); */
  }

  if (level_string) {
    if (amc_level.id == -1)
      goto unsupported_level;

    /* gst_amc_format_set_int (format, amc_level.key, amc_level.id); */
  }

  gst_amc_format_set_int (format, "i-frame-interval", encoder->i_frame_int,
      &err);
  if (err)
    GST_ELEMENT_WARNING_FROM_ERROR (encoder, err);

  if (info->fps_d)
    gst_amc_format_set_float (format, "frame-rate",
        ((gfloat) info->fps_n) / info->fps_d, &err);
  if (err)
    GST_ELEMENT_WARNING_FROM_ERROR (encoder, err);

  encoder->format = info->finfo->format;
  if (!gst_amc_color_format_info_set (&encoder->color_format_info,
          klass->codec_info, mime, color_format, info->width, info->height,
          stride, slice_height, 0, 0, 0, 0))
    goto color_format_info_failed_to_set;

  GST_DEBUG_OBJECT (encoder,
      "Color format info: {color_format=%d, width=%d, height=%d, "
      "stride=%d, slice-height=%d, crop-left=%d, crop-top=%d, "
      "crop-right=%d, crop-bottom=%d, frame-size=%d}",
      encoder->color_format_info.color_format, encoder->color_format_info.width,
      encoder->color_format_info.height, encoder->color_format_info.stride,
      encoder->color_format_info.slice_height,
      encoder->color_format_info.crop_left, encoder->color_format_info.crop_top,
      encoder->color_format_info.crop_right,
      encoder->color_format_info.crop_bottom,
      encoder->color_format_info.frame_size);

  return format;

video_format_failed_to_convert:
  GST_ERROR_OBJECT (encoder, "Failed to convert video format");
  gst_amc_format_free (format);
  return NULL;

color_format_info_failed_to_set:
  GST_ERROR_OBJECT (encoder, "Failed to set up GstAmcColorFormatInfo");
  gst_amc_format_free (format);
  return NULL;

unsupported_profile:
  GST_ERROR_OBJECT (encoder, "Unsupport profile '%s'", profile_string);
  gst_amc_format_free (format);
  return NULL;

unsupported_level:
  GST_ERROR_OBJECT (encoder, "Unsupport level '%s'", level_string);
  gst_amc_format_free (format);
  return NULL;
}
예제 #2
0
static gboolean
gst_amc_video_dec_set_src_caps (GstAmcVideoDec * self, GstAmcFormat * format)
{
  GstVideoCodecState *output_state;
  const gchar *mime;
  gint color_format, width, height;
  gint stride, slice_height;
  gint crop_left, crop_right;
  gint crop_top, crop_bottom;
  GstVideoFormat gst_format;
  GstAmcVideoDecClass *klass = GST_AMC_VIDEO_DEC_GET_CLASS (self);
  GError *err = NULL;
  gboolean ret;

  if (!gst_amc_format_get_int (format, "color-format", &color_format, &err) ||
      !gst_amc_format_get_int (format, "width", &width, &err) ||
      !gst_amc_format_get_int (format, "height", &height, &err)) {
    GST_ERROR_OBJECT (self, "Failed to get output format metadata: %s",
        err->message);
    g_clear_error (&err);
    return FALSE;
  }

  if (!gst_amc_format_get_int (format, "stride", &stride, &err) ||
      !gst_amc_format_get_int (format, "slice-height", &slice_height, &err)) {
    GST_ERROR_OBJECT (self, "Failed to get stride and slice-height: %s",
        err->message);
    g_clear_error (&err);
    return FALSE;
  }

  if (!gst_amc_format_get_int (format, "crop-left", &crop_left, &err) ||
      !gst_amc_format_get_int (format, "crop-right", &crop_right, &err) ||
      !gst_amc_format_get_int (format, "crop-top", &crop_top, &err) ||
      !gst_amc_format_get_int (format, "crop-bottom", &crop_bottom, &err)) {
    GST_ERROR_OBJECT (self, "Failed to get crop rectangle: %s", err->message);
    g_clear_error (&err);
    return FALSE;
  }

  if (width == 0 || height == 0) {
    GST_ERROR_OBJECT (self, "Height or width not set");
    return FALSE;
  }

  if (crop_bottom)
    height = height - (height - crop_bottom - 1);
  if (crop_top)
    height = height - crop_top;

  if (crop_right)
    width = width - (width - crop_right - 1);
  if (crop_left)
    width = width - crop_left;

  mime = caps_to_mime (self->input_state->caps);
  if (!mime) {
    GST_ERROR_OBJECT (self, "Failed to convert caps to mime");
    return FALSE;
  }

  gst_format =
      gst_amc_color_format_to_video_format (klass->codec_info, mime,
      color_format);

  if (gst_format == GST_VIDEO_FORMAT_UNKNOWN) {
    GST_ERROR_OBJECT (self, "Unknown color format 0x%08x", color_format);
    return FALSE;
  }

  output_state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
      gst_format, width, height, self->input_state);

  /* FIXME: Special handling for multiview, untested */
  if (color_format == COLOR_QCOM_FormatYVU420SemiPlanar32mMultiView) {
    gst_video_multiview_video_info_change_mode (&output_state->info,
        GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM, GST_VIDEO_MULTIVIEW_FLAGS_NONE);
  }

  self->format = gst_format;
  if (!gst_amc_color_format_info_set (&self->color_format_info,
          klass->codec_info, mime, color_format, width, height, stride,
          slice_height, crop_left, crop_right, crop_top, crop_bottom)) {
    GST_ERROR_OBJECT (self, "Failed to set up GstAmcColorFormatInfo");
    return FALSE;
  }

  GST_DEBUG_OBJECT (self,
      "Color format info: {color_format=%d, width=%d, height=%d, "
      "stride=%d, slice-height=%d, crop-left=%d, crop-top=%d, "
      "crop-right=%d, crop-bottom=%d, frame-size=%d}",
      self->color_format_info.color_format, self->color_format_info.width,
      self->color_format_info.height, self->color_format_info.stride,
      self->color_format_info.slice_height, self->color_format_info.crop_left,
      self->color_format_info.crop_top, self->color_format_info.crop_right,
      self->color_format_info.crop_bottom, self->color_format_info.frame_size);

  ret = gst_video_decoder_negotiate (GST_VIDEO_DECODER (self));
  gst_video_codec_state_unref (output_state);
  self->input_state_changed = FALSE;

  return ret;
}