예제 #1
0
static void
gst_wavpack_parse_finalize (GObject * object)
{
  gst_wavpack_parse_reset (GST_WAVPACK_PARSE (object));

  G_OBJECT_CLASS (parent_class)->finalize (object);
}
예제 #2
0
static GstStateChangeReturn
gst_wavpack_parse_change_state (GstElement * element, GstStateChange transition)
{
  GstWavpackParse *wvparse = GST_WAVPACK_PARSE (element);

  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;

  switch (transition) {
    case GST_STATE_CHANGE_READY_TO_PAUSED:
      gst_segment_init (&wvparse->segment, GST_FORMAT_DEFAULT);
      wvparse->segment.last_stop = 0;
    default:
      break;
  }

  if (GST_ELEMENT_CLASS (parent_class)->change_state)
    ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);

  switch (transition) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      gst_wavpack_parse_reset (wvparse);
      break;
    default:
      break;
  }

  return ret;
}
예제 #3
0
static GstFlowReturn
gst_wavpack_parse_chain (GstPad * pad, GstBuffer * buf)
{
  GstWavpackParse *wvparse = GST_WAVPACK_PARSE (GST_PAD_PARENT (pad));
  GstFlowReturn ret = GST_FLOW_OK;
  WavpackHeader wph;
  const guint8 *tmp_buf;

  if (!wvparse->adapter) {
    wvparse->adapter = gst_adapter_new ();
  }

  if (GST_BUFFER_IS_DISCONT (buf)) {
    gst_adapter_clear (wvparse->adapter);
    wvparse->discont = TRUE;
  }

  gst_adapter_push (wvparse->adapter, buf);

  if (gst_adapter_available (wvparse->adapter) < sizeof (WavpackHeader))
    return ret;

  if (!gst_wavpack_parse_resync_adapter (wvparse->adapter))
    return ret;

  tmp_buf = gst_adapter_peek (wvparse->adapter, sizeof (WavpackHeader));
  gst_wavpack_read_header (&wph, (guint8 *) tmp_buf);

  while (gst_adapter_available (wvparse->adapter) >= wph.ckSize + 4 * 1 + 4) {
    GstBuffer *outbuf =
        gst_adapter_take_buffer (wvparse->adapter, wph.ckSize + 4 * 1 + 4);

    if (!outbuf)
      return GST_FLOW_ERROR;

    if (wvparse->srcpad == NULL) {
      if (!gst_wavpack_parse_create_src_pad (wvparse, outbuf, &wph)) {
        GST_ERROR_OBJECT (wvparse, "Failed to create src pad");
        ret = GST_FLOW_ERROR;
        break;
      }
    }

    ret = gst_wavpack_parse_push_buffer (wvparse, outbuf, &wph);

    if (ret != GST_FLOW_OK)
      break;

    if (gst_adapter_available (wvparse->adapter) >= sizeof (WavpackHeader)) {
      tmp_buf = gst_adapter_peek (wvparse->adapter, sizeof (WavpackHeader));

      if (!gst_wavpack_parse_resync_adapter (wvparse->adapter))
        break;

      gst_wavpack_read_header (&wph, (guint8 *) tmp_buf);
    }
  }

  return ret;
}
예제 #4
0
static gboolean
gst_wavpack_parse_sink_event (GstPad * pad, GstEvent * event)
{
  GstWavpackParse *parse;

  gboolean ret = TRUE;

  parse = GST_WAVPACK_PARSE (gst_pad_get_parent (pad));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_FLUSH_STOP:{
      if (parse->adapter) {
        gst_adapter_clear (parse->adapter);
      }
      if (parse->pending_buffer) {
        gst_buffer_unref (parse->pending_buffer);
        parse->pending_buffer = NULL;
        parse->pending_offset = 0;
      }
      ret = gst_pad_push_event (parse->srcpad, event);
      break;
    }
    case GST_EVENT_NEWSEGMENT:{
      parse->need_newsegment = TRUE;
      gst_event_unref (event);
      ret = TRUE;
      break;
    }
    case GST_EVENT_EOS:{
      if (parse->adapter) {
        /* remove all bytes that are left in the adapter after EOS. They can't
         * be a complete Wavpack block and we can't do anything with them */
        gst_adapter_clear (parse->adapter);
      }
      if (parse->pending_buffer) {
        gst_buffer_unref (parse->pending_buffer);
        parse->pending_buffer = NULL;
        parse->pending_offset = 0;
      }
      ret = gst_pad_push_event (parse->srcpad, event);
      break;
    }
    default:{
      /* stream lock is recursive, should be fine for all events */
      GST_PAD_STREAM_LOCK (pad);
      if (parse->srcpad == NULL) {
        parse->queued_events = g_list_append (parse->queued_events, event);
      } else {
        ret = gst_pad_push_event (parse->srcpad, event);
      }
      GST_PAD_STREAM_UNLOCK (pad);
    }
  }


  gst_object_unref (parse);
  return ret;
}
예제 #5
0
static gboolean
gst_wavpack_parse_src_event (GstPad * pad, GstEvent * event)
{
  GstWavpackParse *parse;
  gboolean ret;

  parse = GST_WAVPACK_PARSE (gst_pad_get_parent (pad));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_SEEK:
      ret = gst_wavpack_parse_handle_seek_event (parse, event);
      break;
    default:
      ret = gst_pad_event_default (pad, event);
      break;
  }

  gst_object_unref (parse);
  return ret;
}
예제 #6
0
static gboolean
gst_wavpack_parse_src_query (GstPad * pad, GstQuery * query)
{
  GstWavpackParse *parse = GST_WAVPACK_PARSE (gst_pad_get_parent (pad));

  GstFormat format;

  gboolean ret = FALSE;

  switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_POSITION:{
      gint64 cur;

      guint rate;

      GST_OBJECT_LOCK (parse);
      cur = parse->segment.last_stop;
      rate = parse->samplerate;
      GST_OBJECT_UNLOCK (parse);

      if (rate == 0) {
        GST_DEBUG_OBJECT (parse, "haven't read header yet");
        break;
      }

      gst_query_parse_position (query, &format, NULL);

      switch (format) {
        case GST_FORMAT_TIME:
          cur = gst_util_uint64_scale_int (cur, GST_SECOND, rate);
          gst_query_set_position (query, GST_FORMAT_TIME, cur);
          ret = TRUE;
          break;
        case GST_FORMAT_DEFAULT:
          gst_query_set_position (query, GST_FORMAT_DEFAULT, cur);
          ret = TRUE;
          break;
        default:
          GST_DEBUG_OBJECT (parse, "cannot handle position query in "
              "%s format. Forwarding upstream.", gst_format_get_name (format));
          ret = gst_pad_query_default (pad, query);
          break;
      }
      break;
    }
    case GST_QUERY_DURATION:{
      gint64 len;

      guint rate;

      GST_OBJECT_LOCK (parse);
      rate = parse->samplerate;
      len = parse->total_samples;
      GST_OBJECT_UNLOCK (parse);

      if (rate == 0) {
        GST_DEBUG_OBJECT (parse, "haven't read header yet");
        break;
      }

      gst_query_parse_duration (query, &format, NULL);

      switch (format) {
        case GST_FORMAT_TIME:
          if (len != G_GINT64_CONSTANT (-1))
            len = gst_util_uint64_scale_int (len, GST_SECOND, rate);
          gst_query_set_duration (query, GST_FORMAT_TIME, len);
          ret = TRUE;
          break;
        case GST_FORMAT_DEFAULT:
          gst_query_set_duration (query, GST_FORMAT_DEFAULT, len);
          ret = TRUE;
          break;
        default:
          GST_DEBUG_OBJECT (parse, "cannot handle duration query in "
              "%s format. Forwarding upstream.", gst_format_get_name (format));
          ret = gst_pad_query_default (pad, query);
          break;
      }
      break;
    }
    case GST_QUERY_SEEKING:{
      gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
      if (format == GST_FORMAT_TIME || format == GST_FORMAT_DEFAULT) {
        gboolean seekable;

        gint64 duration = -1;

        /* only fails if we didn't read the headers yet and can't say
         * anything about our seeking capabilities */
        if (!gst_pad_query_duration (pad, &format, &duration))
          break;

        /* can't seek in streaming mode yet */
        GST_OBJECT_LOCK (parse);
        seekable = (parse->adapter == NULL);
        GST_OBJECT_UNLOCK (parse);

        gst_query_set_seeking (query, format, seekable, 0, duration);
        ret = TRUE;
      }
      break;
    }
    default:{
      ret = gst_pad_query_default (pad, query);
      break;
    }
  }

  gst_object_unref (parse);
  return ret;

}
예제 #7
0
static void
gst_wavpack_parse_loop (GstElement * element)
{
  GstWavpackParse *parse = GST_WAVPACK_PARSE (element);

  GstFlowReturn flow_ret;
  WavpackHeader header = { {0,}, 0, };
  GstBuffer *buf = NULL;

  flow_ret = gst_wavpack_parse_resync_loop (parse, &header);

  if (flow_ret != GST_FLOW_OK)
    goto pause;

  GST_LOG_OBJECT (parse, "Read header at offset %" G_GINT64_FORMAT
      ": chunk size = %u+8", parse->current_offset, header.ckSize);

  buf = gst_wavpack_parse_pull_buffer (parse, parse->current_offset,
      header.ckSize + 8, &flow_ret);

  if (flow_ret != GST_FLOW_OK)
    goto pause;

  if (parse->srcpad == NULL) {
    if (!gst_wavpack_parse_create_src_pad (parse, buf, &header)) {
      GST_ERROR_OBJECT (parse, "Failed to create src pad");
      flow_ret = GST_FLOW_ERROR;
      goto pause;
    }
  }
  if (header.flags & INITIAL_BLOCK)
    gst_wavpack_parse_index_append_entry (parse, parse->current_offset,
        header.block_index, header.block_samples);

  flow_ret = gst_wavpack_parse_push_buffer (parse, buf, &header);
  if (flow_ret != GST_FLOW_OK)
    goto pause;

  return;

pause:
  {
    const gchar *reason = gst_flow_get_name (flow_ret);

    GST_LOG_OBJECT (parse, "pausing task, reason %s", reason);
    gst_pad_pause_task (parse->sinkpad);

    if (GST_FLOW_IS_FATAL (flow_ret) || flow_ret == GST_FLOW_NOT_LINKED) {
      if (flow_ret == GST_FLOW_UNEXPECTED && parse->srcpad) {
        if (parse->segment.flags & GST_SEEK_FLAG_SEGMENT) {
          GstClockTime stop;

          GST_LOG_OBJECT (parse, "Sending segment done");

          if ((stop = parse->segment.stop) == -1)
            stop = parse->segment.duration;

          gst_element_post_message (GST_ELEMENT_CAST (parse),
              gst_message_new_segment_done (GST_OBJECT_CAST (parse),
                  parse->segment.format, stop));
        } else {
          GST_LOG_OBJECT (parse, "Sending EOS, at end of stream");
          gst_pad_push_event (parse->srcpad, gst_event_new_eos ());
        }
      } else {
        GST_ELEMENT_ERROR (parse, STREAM, FAILED,
            (_("Internal data stream error.")),
            ("stream stopped, reason %s", reason));
        if (parse->srcpad)
          gst_pad_push_event (parse->srcpad, gst_event_new_eos ());
      }
    }
    return;
  }
}