Exemple #1
0
static gboolean
gst_ivf_parse_stop (GstBaseParse * parse)
{
  GstIvfParse *const ivf = GST_IVF_PARSE (parse);

  gst_ivf_parse_reset (ivf);

  return TRUE;
}
Exemple #2
0
static void
gst_ivf_parse_finalize (GObject * object)
{
  GstIvfParse *const ivf = GST_IVF_PARSE (object);

  GST_DEBUG_OBJECT (ivf, "finalizing");
  gst_ivf_parse_reset (ivf);

  G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gst_ivf_parse_dispose (GObject * object)
{
  GstIvfParse *ivf = GST_IVF_PARSE (object);

  GST_DEBUG_OBJECT (ivf, "disposing");
  gst_ivf_parse_reset (ivf);

  G_OBJECT_CLASS (parent_class)->dispose (object);
}
Exemple #4
0
static gboolean
gst_ivf_parse_start (GstBaseParse * parse)
{
  GstIvfParse *const ivf = GST_IVF_PARSE (parse);

  gst_ivf_parse_reset (ivf);

  /* Minimal file header size needed at start */
  gst_base_parse_set_min_frame_size (parse, IVF_FILE_HEADER_SIZE);

  /* No sync code to detect frame boundaries */
  gst_base_parse_set_syncable (parse, FALSE);

  return TRUE;
}
Exemple #5
0
static GstFlowReturn
gst_ivf_parse_handle_frame (GstBaseParse * parse,
    GstBaseParseFrame * frame, gint * skipsize)
{
  GstIvfParse *const ivf = GST_IVF_PARSE (parse);

  switch (ivf->state) {
    case GST_IVF_PARSE_START:
      return gst_ivf_parse_handle_frame_start (ivf, frame, skipsize);
    case GST_IVF_PARSE_DATA:
      return gst_ivf_parse_handle_frame_data (ivf, frame, skipsize);
    default:
      break;
  }

  g_assert_not_reached ();
  return GST_FLOW_ERROR;
}
/* chain function
 * this function does the actual processing
 */
static GstFlowReturn
gst_ivf_parse_chain (GstPad * pad, GstBuffer * buf)
{
  GstIvfParse *ivf = GST_IVF_PARSE (GST_OBJECT_PARENT (pad));
  gboolean res;

  /* lazy creation of the adapter */
  if (G_UNLIKELY (ivf->adapter == NULL)) {
    ivf->adapter = gst_adapter_new ();
  }

  GST_LOG_OBJECT (ivf, "Pushing buffer of size %u to adapter",
      GST_BUFFER_SIZE (buf));

  gst_adapter_push (ivf->adapter, buf); /* adapter takes ownership of buf */

  res = GST_FLOW_OK;

  switch (ivf->state) {
    case GST_IVF_PARSE_START:
      if (gst_adapter_available (ivf->adapter) >= 32) {
        GstCaps *caps;

        const guint8 *data = gst_adapter_peek (ivf->adapter, 32);
        guint32 magic = GST_READ_UINT32_LE (data);
        guint16 version = GST_READ_UINT16_LE (data + 4);
        guint16 header_size = GST_READ_UINT16_LE (data + 6);
        guint32 fourcc = GST_READ_UINT32_LE (data + 8);
        guint16 width = GST_READ_UINT16_LE (data + 12);
        guint16 height = GST_READ_UINT16_LE (data + 14);
        guint32 rate_num = GST_READ_UINT32_LE (data + 16);
        guint32 rate_den = GST_READ_UINT32_LE (data + 20);
#ifndef GST_DISABLE_GST_DEBUG
        guint32 num_frames = GST_READ_UINT32_LE (data + 24);
#endif

        /* last 4 bytes unused */
        gst_adapter_flush (ivf->adapter, 32);

        if (magic != GST_MAKE_FOURCC ('D', 'K', 'I', 'F') ||
            version != 0 || header_size != 32 ||
            fourcc != GST_MAKE_FOURCC ('V', 'P', '8', '0')) {
          GST_ELEMENT_ERROR (ivf, STREAM, WRONG_TYPE, (NULL), (NULL));
          return GST_FLOW_ERROR;
        }

        /* create src pad caps */
        caps = gst_caps_new_simple ("video/x-vp8",
            "width", G_TYPE_INT, width, "height", G_TYPE_INT, height,
            "framerate", GST_TYPE_FRACTION, rate_num, rate_den, NULL);

        GST_INFO_OBJECT (ivf, "Found stream: %" GST_PTR_FORMAT, caps);

        GST_LOG_OBJECT (ivf, "Stream has %d frames", num_frames);

        gst_pad_set_caps (ivf->srcpad, caps);
        gst_caps_unref (caps);

        /* keep framerate in instance for convenience */
        ivf->rate_num = rate_num;
        ivf->rate_den = rate_den;

        gst_pad_push_event (ivf->srcpad, gst_event_new_new_segment (FALSE, 1.0,
                GST_FORMAT_TIME, 0, -1, 0));

        /* move along */
        ivf->state = GST_IVF_PARSE_DATA;
      } else {
        GST_LOG_OBJECT (ivf, "Header data not yet available.");
        break;
      }

      /* fall through */

    case GST_IVF_PARSE_DATA:
      while (gst_adapter_available (ivf->adapter) > 12) {
        const guint8 *data = gst_adapter_peek (ivf->adapter, 12);
        guint32 frame_size = GST_READ_UINT32_LE (data);
        guint64 frame_pts = GST_READ_UINT64_LE (data + 4);

        GST_LOG_OBJECT (ivf,
            "Read frame header: size %u, pts %" G_GUINT64_FORMAT, frame_size,
            frame_pts);

        if (gst_adapter_available (ivf->adapter) >= 12 + frame_size) {
          GstBuffer *frame;

          gst_adapter_flush (ivf->adapter, 12);

          frame = gst_adapter_take_buffer (ivf->adapter, frame_size);
          gst_buffer_set_caps (frame, GST_PAD_CAPS (ivf->srcpad));
          GST_BUFFER_TIMESTAMP (frame) =
              gst_util_uint64_scale_int (GST_SECOND * frame_pts, ivf->rate_den,
              ivf->rate_num);
          GST_BUFFER_DURATION (frame) =
              gst_util_uint64_scale_int (GST_SECOND, ivf->rate_den,
              ivf->rate_num);

          GST_DEBUG_OBJECT (ivf, "Pushing frame of size %u, ts %"
              GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", off %"
              G_GUINT64_FORMAT ", off_end %" G_GUINT64_FORMAT,
              GST_BUFFER_SIZE (frame),
              GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (frame)),
              GST_TIME_ARGS (GST_BUFFER_DURATION (frame)),
              GST_BUFFER_OFFSET (frame), GST_BUFFER_OFFSET_END (frame));

          res = gst_pad_push (ivf->srcpad, frame);
          if (res != GST_FLOW_OK)
            break;
        } else {
          GST_LOG_OBJECT (ivf, "Frame data not yet available.");
          break;
        }
      }
      break;

    default:
      g_return_val_if_reached (GST_FLOW_ERROR);
  }

  return res;
}