예제 #1
0
static GstStateChangeReturn
gst_y4m_encode_change_state (GstElement * element, GstStateChange transition)
{
  GstY4mEncode *filter = GST_Y4M_ENCODE (element);
  GstStateChangeReturn ret;

  switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
    case GST_STATE_CHANGE_READY_TO_PAUSED:
      break;
    default:
      break;
  }

  ret = GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, change_state,
      (element, transition), GST_STATE_CHANGE_SUCCESS);
  if (ret != GST_STATE_CHANGE_SUCCESS)
    return ret;

  switch (transition) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      gst_y4m_encode_reset (filter);
      break;
    default:
      break;
  }

  return GST_STATE_CHANGE_SUCCESS;
}
예제 #2
0
static void
gst_y4m_encode_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstY4mEncode G_GNUC_UNUSED *filter;

  g_return_if_fail (GST_IS_Y4M_ENCODE (object));
  filter = GST_Y4M_ENCODE (object);

  switch (prop_id) {
    default:
      break;
  }
}
예제 #3
0
static void
gst_y4m_encode_get_property (GObject * object, guint prop_id, GValue * value,
    GParamSpec * pspec)
{
  GstY4mEncode G_GNUC_UNUSED *filter;

  g_return_if_fail (GST_IS_Y4M_ENCODE (object));
  filter = GST_Y4M_ENCODE (object);

  switch (prop_id) {
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
예제 #4
0
static GstFlowReturn
gst_y4m_encode_handle_frame (GstVideoEncoder * encoder,
    GstVideoCodecFrame * frame)
{
  GstY4mEncode *filter = GST_Y4M_ENCODE (encoder);
  GstClockTime timestamp;

  /* check we got some decent info from caps */
  if (GST_VIDEO_INFO_FORMAT (&filter->info) == GST_VIDEO_FORMAT_UNKNOWN)
    goto not_negotiated;

  timestamp = GST_BUFFER_TIMESTAMP (frame->input_buffer);

  if (G_UNLIKELY (!filter->header)) {
    gboolean tff = FALSE;

    if (GST_VIDEO_INFO_IS_INTERLACED (&filter->info)) {
      tff =
          GST_BUFFER_FLAG_IS_SET (frame->input_buffer,
          GST_VIDEO_BUFFER_FLAG_TFF);
    }
    frame->output_buffer = gst_y4m_encode_get_stream_header (filter, tff);
    filter->header = TRUE;
    frame->output_buffer =
        gst_buffer_append (frame->output_buffer,
        gst_y4m_encode_get_frame_header (filter));
  } else {
    frame->output_buffer = gst_y4m_encode_get_frame_header (filter);
  }

  frame->output_buffer =
      gst_buffer_append (frame->output_buffer,
      gst_buffer_copy (frame->input_buffer));

  /* decorate */
  frame->output_buffer = gst_buffer_make_writable (frame->output_buffer);
  GST_BUFFER_TIMESTAMP (frame->output_buffer) = timestamp;

  return gst_video_encoder_finish_frame (encoder, frame);

not_negotiated:
  {
    GST_ELEMENT_ERROR (filter, CORE, NEGOTIATION, (NULL),
        ("format wasn't negotiated"));

    return GST_FLOW_NOT_NEGOTIATED;
  }
}
예제 #5
0
static gboolean
gst_y4m_encode_setcaps (GstPad * pad, GstCaps * vscaps)
{
  gboolean ret;
  GstY4mEncode *filter;
  GstVideoInfo info;

  filter = GST_Y4M_ENCODE (GST_PAD_PARENT (pad));

  if (!gst_video_info_from_caps (&info, vscaps))
    goto invalid_format;

  switch (GST_VIDEO_INFO_FORMAT (&info)) {
    case GST_VIDEO_FORMAT_I420:
      filter->colorspace = "420";
      break;
    case GST_VIDEO_FORMAT_Y42B:
      filter->colorspace = "422";
      break;
    case GST_VIDEO_FORMAT_Y41B:
      filter->colorspace = "411";
      break;
    case GST_VIDEO_FORMAT_Y444:
      filter->colorspace = "444";
      break;
    default:
      goto invalid_format;
  }

  filter->info = info;

  /* the template caps will do for the src pad, should always accept */
  ret = gst_pad_set_caps (filter->srcpad,
      gst_static_pad_template_get_caps (&y4mencode_src_factory));

  filter->negotiated = ret;

  return ret;

  /* ERRORS */
invalid_format:
  {
    GST_ERROR_OBJECT (filter, "got invalid caps");
    return FALSE;
  }
}
예제 #6
0
static GstFlowReturn
gst_y4m_encode_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
  GstY4mEncode *filter = GST_Y4M_ENCODE (parent);
  GstBuffer *outbuf;
  GstClockTime timestamp;

  /* check we got some decent info from caps */
  if (GST_VIDEO_INFO_FORMAT (&filter->info) == GST_VIDEO_FORMAT_UNKNOWN)
    goto not_negotiated;

  timestamp = GST_BUFFER_TIMESTAMP (buf);

  if (G_UNLIKELY (!filter->header)) {
    gboolean tff;

    if (GST_VIDEO_INFO_IS_INTERLACED (&filter->info)) {
      tff = GST_BUFFER_FLAG_IS_SET (buf, GST_VIDEO_BUFFER_FLAG_TFF);
    }
    outbuf = gst_y4m_encode_get_stream_header (filter, tff);
    filter->header = TRUE;
    outbuf =
        gst_buffer_append (outbuf, gst_y4m_encode_get_frame_header (filter));
  } else {
    outbuf = gst_y4m_encode_get_frame_header (filter);
  }
  /* join with data, FIXME, strides are all wrong etc */
  outbuf = gst_buffer_append (outbuf, buf);
  /* decorate */
  outbuf = gst_buffer_make_writable (outbuf);

  GST_BUFFER_TIMESTAMP (outbuf) = timestamp;

  return gst_pad_push (filter->srcpad, outbuf);

  /* ERRORS */
not_negotiated:
  {
    GST_ELEMENT_ERROR (filter, CORE, NEGOTIATION, (NULL),
        ("format wasn't negotiated before chain function"));
    gst_buffer_unref (buf);
    return GST_FLOW_NOT_NEGOTIATED;
  }
}
예제 #7
0
static gboolean
gst_y4m_encode_set_format (GstVideoEncoder * encoder,
    GstVideoCodecState * state)
{
  GstY4mEncode *y4menc;
  GstVideoInfo *info;
  GstVideoCodecState *output_state;

  y4menc = GST_Y4M_ENCODE (encoder);
  info = &state->info;

  switch (GST_VIDEO_INFO_FORMAT (info)) {
    case GST_VIDEO_FORMAT_I420:
      y4menc->colorspace = "420";
      break;
    case GST_VIDEO_FORMAT_Y42B:
      y4menc->colorspace = "422";
      break;
    case GST_VIDEO_FORMAT_Y41B:
      y4menc->colorspace = "411";
      break;
    case GST_VIDEO_FORMAT_Y444:
      y4menc->colorspace = "444";
      break;
    default:
      goto invalid_format;
  }

  y4menc->info = *info;

  output_state =
      gst_video_encoder_set_output_state (encoder,
      gst_static_pad_template_get_caps (&y4mencode_src_factory), state);
  gst_video_codec_state_unref (output_state);

  return TRUE;

invalid_format:
  {
    GST_ERROR_OBJECT (y4menc, "Invalid format");
    return FALSE;
  }

}
예제 #8
0
static GstFlowReturn
gst_y4m_encode_chain (GstPad * pad, GstBuffer * buf)
{
  GstY4mEncode *filter = GST_Y4M_ENCODE (GST_PAD_PARENT (pad));
  GstBuffer *outbuf;
  GstClockTime timestamp;

  /* check we got some decent info from caps */
  if (filter->width < 0) {
    GST_ELEMENT_ERROR ("filter", CORE, NEGOTIATION, (NULL),
        ("format wasn't negotiated before chain function"));
    gst_buffer_unref (buf);
    return GST_FLOW_NOT_NEGOTIATED;
  }

  timestamp = GST_BUFFER_TIMESTAMP (buf);

  if (G_UNLIKELY (!filter->header)) {
    if (filter->interlaced == TRUE) {
      if (GST_BUFFER_FLAG_IS_SET (buf, GST_VIDEO_BUFFER_TFF)) {
        filter->top_field_first = TRUE;
      } else {
        filter->top_field_first = FALSE;
      }
    }
    outbuf = gst_y4m_encode_get_stream_header (filter);
    filter->header = TRUE;
    outbuf = gst_buffer_join (outbuf, gst_y4m_encode_get_frame_header (filter));
  } else {
    outbuf = gst_y4m_encode_get_frame_header (filter);
  }
  /* join with data */
  outbuf = gst_buffer_join (outbuf, buf);
  /* decorate */
  gst_buffer_make_metadata_writable (outbuf);
  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (filter->srcpad));

  GST_BUFFER_TIMESTAMP (outbuf) = timestamp;

  return gst_pad_push (filter->srcpad, outbuf);
}
예제 #9
0
static gboolean
gst_y4m_encode_setcaps (GstPad * pad, GstCaps * vscaps)
{
  GstY4mEncode *filter;
  GstStructure *structure;
  gboolean res;
  gint w, h;
  guint32 fourcc;
  const GValue *fps, *par, *interlaced;

  filter = GST_Y4M_ENCODE (GST_PAD_PARENT (pad));

  structure = gst_caps_get_structure (vscaps, 0);

  res = gst_structure_get_int (structure, "width", &w);
  res &= gst_structure_get_int (structure, "height", &h);
  res &= ((fps = gst_structure_get_value (structure, "framerate")) != NULL);
  res &= gst_structure_get_fourcc (structure, "format", &fourcc);

  switch (fourcc) {             /* Translate fourcc to Y4M colorspace code */
    case GST_MAKE_FOURCC ('I', '4', '2', '0'):
    case GST_MAKE_FOURCC ('I', 'Y', 'U', 'V'):
      filter->colorspace = "420";
      break;
    case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
      filter->colorspace = "422";
      break;
    case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
      filter->colorspace = "411";
      break;
    case GST_MAKE_FOURCC ('Y', '4', '4', '4'):
      filter->colorspace = "444";
      break;
    default:
      res = FALSE;
      break;
  }

  if (!res || w <= 0 || h <= 0 || !GST_VALUE_HOLDS_FRACTION (fps))
    return FALSE;

  /* optional interlaced info */
  interlaced = gst_structure_get_value (structure, "interlaced");

  /* optional par info */
  par = gst_structure_get_value (structure, "pixel-aspect-ratio");

  filter->width = w;
  filter->height = h;
  filter->fps_num = gst_value_get_fraction_numerator (fps);
  filter->fps_den = gst_value_get_fraction_denominator (fps);
  if ((par != NULL) && GST_VALUE_HOLDS_FRACTION (par)) {
    filter->par_num = gst_value_get_fraction_numerator (par);
    filter->par_den = gst_value_get_fraction_denominator (par);
  } else {                      /* indicates unknown */
    filter->par_num = 0;
    filter->par_den = 0;
  }
  if ((interlaced != NULL) && G_VALUE_HOLDS (interlaced, G_TYPE_BOOLEAN)) {
    filter->interlaced = g_value_get_boolean (interlaced);
  } else {
    /* assume progressive if no interlaced property in caps */
    filter->interlaced = FALSE;
  }
  /* the template caps will do for the src pad, should always accept */
  return gst_pad_set_caps (filter->srcpad,
      gst_static_pad_template_get_caps (&y4mencode_src_factory));
}