Пример #1
0
static GstStateChangeReturn
gst_musepackdec_change_state (GstElement * element, GstStateChange transition)
{
  GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (element);
  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;

  switch (transition) {
    case GST_STATE_CHANGE_READY_TO_PAUSED:
      gst_segment_init (&musepackdec->segment, GST_FORMAT_DEFAULT);
      musepackdec->segment.position = 0;
      break;
    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_segment_init (&musepackdec->segment, GST_FORMAT_UNDEFINED);
      musepackdec->offset = 0;
      musepackdec->rate = 0;
      musepackdec->bps = 0;
      break;
    default:
      break;
  }

  return ret;

}
Пример #2
0
static void
gst_musepackdec_dispose (GObject * obj)
{
  GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (obj);

  g_free (musepackdec->r);
  musepackdec->r = NULL;

  if (musepackdec->d) {
    mpc_demux_exit (musepackdec->d);
    musepackdec->d = NULL;
  }

  G_OBJECT_CLASS (parent_class)->dispose (obj);
}
Пример #3
0
static void
gst_musepackdec_dispose (GObject * obj)
{
    GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (obj);

    g_free (musepackdec->r);
    musepackdec->r = NULL;

#ifdef MPC_IS_OLD_API
    g_free (musepackdec->d);
    musepackdec->d = NULL;
#else
    if (musepackdec->d) {
        mpc_demux_exit (musepackdec->d);
        musepackdec->d = NULL;
    }
#endif

    G_OBJECT_CLASS (parent_class)->dispose (obj);
}
Пример #4
0
static gboolean
gst_musepackdec_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
  GstMusepackDec *dec;
  gboolean res;

  dec = GST_MUSEPACK_DEC (parent);

  GST_DEBUG_OBJECT (dec, "handling %s event", GST_EVENT_TYPE_NAME (event));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_SEEK:
      res = gst_musepackdec_handle_seek_event (dec, event);
      break;
    default:
      res = gst_pad_event_default (pad, parent, event);
      break;
  }

  return res;
}
Пример #5
0
static void
gst_musepackdec_loop (GstPad * sinkpad)
{
  GstMusepackDec *musepackdec;
  GstFlowReturn flow;
  GstBuffer *out;
  GstMapInfo info;
  mpc_frame_info frame;
  mpc_status err;
  gint num_samples, samplerate, bitspersample;

  musepackdec = GST_MUSEPACK_DEC (GST_PAD_PARENT (sinkpad));

  samplerate = g_atomic_int_get (&musepackdec->rate);

  if (samplerate == 0) {
    if (!gst_musepack_stream_init (musepackdec))
      goto pause_task;

    gst_musepackdec_send_newsegment (musepackdec);
    samplerate = g_atomic_int_get (&musepackdec->rate);
  }

  bitspersample = g_atomic_int_get (&musepackdec->bps);

  out = gst_buffer_new_allocate (NULL, MPC_DECODER_BUFFER_LENGTH * 4, NULL);

  gst_buffer_map (out, &info, GST_MAP_READWRITE);
  frame.buffer = (MPC_SAMPLE_FORMAT *) info.data;
  err = mpc_demux_decode (musepackdec->d, &frame);
  gst_buffer_unmap (out, &info);

  if (err != MPC_STATUS_OK) {
    GST_ERROR_OBJECT (musepackdec, "Failed to decode sample");
    GST_ELEMENT_ERROR (musepackdec, STREAM, DECODE, (NULL), (NULL));
    goto pause_task;
  } else if (frame.bits == -1) {
    goto eos_and_pause;
  }

  num_samples = frame.samples;

  gst_buffer_set_size (out, num_samples * bitspersample);

  GST_BUFFER_OFFSET (out) = musepackdec->segment.position;
  GST_BUFFER_PTS (out) =
      gst_util_uint64_scale_int (musepackdec->segment.position,
      GST_SECOND, samplerate);
  GST_BUFFER_DURATION (out) =
      gst_util_uint64_scale_int (num_samples, GST_SECOND, samplerate);

  musepackdec->segment.position += num_samples;

  GST_LOG_OBJECT (musepackdec, "Pushing buffer, timestamp %" GST_TIME_FORMAT,
      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (out)));

  flow = gst_pad_push (musepackdec->srcpad, out);
  if (flow != GST_FLOW_OK) {
    GST_DEBUG_OBJECT (musepackdec, "Flow: %s", gst_flow_get_name (flow));
    goto pause_task;
  }

  /* check if we're at the end of a configured segment */
  if (musepackdec->segment.stop != -1 &&
      musepackdec->segment.position >= musepackdec->segment.stop) {
    gint64 stop_time;

    GST_DEBUG_OBJECT (musepackdec, "Reached end of configured segment");

    if ((musepackdec->segment.flags & GST_SEEK_FLAG_SEGMENT) == 0)
      goto eos_and_pause;

    GST_DEBUG_OBJECT (musepackdec, "Posting SEGMENT_DONE message");

    stop_time = gst_util_uint64_scale_int (musepackdec->segment.stop,
        GST_SECOND, samplerate);

    gst_element_post_message (GST_ELEMENT (musepackdec),
        gst_message_new_segment_done (GST_OBJECT (musepackdec),
            GST_FORMAT_TIME, stop_time));
    gst_pad_push_event (musepackdec->srcpad,
        gst_event_new_segment_done (GST_FORMAT_TIME, stop_time));

    goto pause_task;
  }

  return;

eos_and_pause:
  {
    GST_DEBUG_OBJECT (musepackdec, "sending EOS event");
    gst_pad_push_event (musepackdec->srcpad, gst_event_new_eos ());
    /* fall through to pause */
  }

pause_task:
  {
    GST_DEBUG_OBJECT (musepackdec, "Pausing task");
    gst_pad_pause_task (sinkpad);
    return;
  }
}
Пример #6
0
static gboolean
gst_musepackdec_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
{
  GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (parent);
  GstFormat format;
  gboolean res = FALSE;
  gint samplerate;

  samplerate = g_atomic_int_get (&musepackdec->rate);

  if (samplerate == 0)
    goto done;

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

      gst_query_parse_position (query, &format, NULL);

      GST_OBJECT_LOCK (musepackdec);
      cur_off = musepackdec->segment.position;
      GST_OBJECT_UNLOCK (musepackdec);

      if (format == GST_FORMAT_TIME) {
        cur = gst_util_uint64_scale_int (cur_off, GST_SECOND, samplerate);
        gst_query_set_position (query, GST_FORMAT_TIME, cur);
        res = TRUE;
      } else if (format == GST_FORMAT_DEFAULT) {
        gst_query_set_position (query, GST_FORMAT_DEFAULT, cur_off);
        res = TRUE;
      }
      break;
    }
    case GST_QUERY_DURATION:{
      gint64 len, len_off;

      gst_query_parse_duration (query, &format, NULL);

      GST_OBJECT_LOCK (musepackdec);
      len_off = musepackdec->segment.duration;
      GST_OBJECT_UNLOCK (musepackdec);

      if (format == GST_FORMAT_TIME) {
        len = gst_util_uint64_scale_int (len_off, GST_SECOND, samplerate);
        gst_query_set_duration (query, GST_FORMAT_TIME, len);
        res = TRUE;
      } else if (format == GST_FORMAT_DEFAULT) {
        gst_query_set_duration (query, GST_FORMAT_DEFAULT, len_off);
        res = TRUE;
      }
      break;
    }
    case GST_QUERY_SEEKING:{
      GstFormat fmt;
      gint64 len, len_off;

      res = TRUE;
      gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);

      GST_OBJECT_LOCK (musepackdec);
      len_off = musepackdec->segment.duration;
      GST_OBJECT_UNLOCK (musepackdec);

      if (fmt == GST_FORMAT_TIME) {
        len = gst_util_uint64_scale_int (len_off, GST_SECOND, samplerate);
        gst_query_set_seeking (query, fmt, TRUE, 0, len);
      } else if (fmt == GST_FORMAT_DEFAULT) {
        gst_query_set_seeking (query, fmt, TRUE, 0, len_off);
      } else {
        gst_query_set_seeking (query, fmt, FALSE, -1, -1);
      }
      break;
    }
    default:
      res = gst_pad_query_default (pad, parent, query);
      break;
  }

done:
  return res;
}
Пример #7
0
static void
gst_musepackdec_loop (GstPad * sinkpad)
{
    GstMusepackDec *musepackdec;
    GstFlowReturn flow;
    GstBuffer *out;

#ifdef MPC_IS_OLD_API
    guint32 update_acc, update_bits;
#else
    mpc_frame_info frame;
    mpc_status err;
#endif
    gint num_samples, samplerate, bitspersample;

    musepackdec = GST_MUSEPACK_DEC (GST_PAD_PARENT (sinkpad));

    samplerate = g_atomic_int_get (&musepackdec->rate);

    if (samplerate == 0) {
        if (!gst_musepack_stream_init (musepackdec))
            goto pause_task;

        gst_musepackdec_send_newsegment (musepackdec);
        samplerate = g_atomic_int_get (&musepackdec->rate);
    }

    bitspersample = g_atomic_int_get (&musepackdec->bps);

    flow = gst_pad_alloc_buffer_and_set_caps (musepackdec->srcpad, -1,
            MPC_DECODER_BUFFER_LENGTH * 4, GST_PAD_CAPS (musepackdec->srcpad), &out);

    if (flow != GST_FLOW_OK) {
        GST_DEBUG_OBJECT (musepackdec, "Flow: %s", gst_flow_get_name (flow));
        goto pause_task;
    }
#ifdef MPC_IS_OLD_API
    num_samples = mpc_decoder_decode (musepackdec->d,
                                      (MPC_SAMPLE_FORMAT *) GST_BUFFER_DATA (out), &update_acc, &update_bits);

    if (num_samples < 0) {
        GST_ERROR_OBJECT (musepackdec, "Failed to decode sample");
        GST_ELEMENT_ERROR (musepackdec, STREAM, DECODE, (NULL), (NULL));
        goto pause_task;
    } else if (num_samples == 0) {
        goto eos_and_pause;
    }
#else
    frame.buffer = (MPC_SAMPLE_FORMAT *) GST_BUFFER_DATA (out);
    err = mpc_demux_decode (musepackdec->d, &frame);

    if (err != MPC_STATUS_OK) {
        GST_ERROR_OBJECT (musepackdec, "Failed to decode sample");
        GST_ELEMENT_ERROR (musepackdec, STREAM, DECODE, (NULL), (NULL));
        goto pause_task;
    } else if (frame.bits == -1) {
        goto eos_and_pause;
    }

    num_samples = frame.samples;
#endif

    GST_BUFFER_SIZE (out) = num_samples * bitspersample;

    GST_BUFFER_OFFSET (out) = musepackdec->segment.last_stop;
    GST_BUFFER_TIMESTAMP (out) =
        gst_util_uint64_scale_int (musepackdec->segment.last_stop,
                                   GST_SECOND, samplerate);
    GST_BUFFER_DURATION (out) =
        gst_util_uint64_scale_int (num_samples, GST_SECOND, samplerate);

    musepackdec->segment.last_stop += num_samples;

    GST_LOG_OBJECT (musepackdec, "Pushing buffer, timestamp %" GST_TIME_FORMAT,
                    GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (out)));

    flow = gst_pad_push (musepackdec->srcpad, out);
    if (flow != GST_FLOW_OK) {
        GST_DEBUG_OBJECT (musepackdec, "Flow: %s", gst_flow_get_name (flow));
        goto pause_task;
    }

    /* check if we're at the end of a configured segment */
    if (musepackdec->segment.stop != -1 &&
            musepackdec->segment.last_stop >= musepackdec->segment.stop) {
        gint64 stop_time;

        GST_DEBUG_OBJECT (musepackdec, "Reached end of configured segment");

        if ((musepackdec->segment.flags & GST_SEEK_FLAG_SEGMENT) == 0)
            goto eos_and_pause;

        GST_DEBUG_OBJECT (musepackdec, "Posting SEGMENT_DONE message");

        stop_time = gst_util_uint64_scale_int (musepackdec->segment.stop,
                                               GST_SECOND, samplerate);

        gst_element_post_message (GST_ELEMENT (musepackdec),
                                  gst_message_new_segment_done (GST_OBJECT (musepackdec),
                                          GST_FORMAT_TIME, stop_time));

        goto pause_task;
    }

    return;

eos_and_pause:
    {
        GST_DEBUG_OBJECT (musepackdec, "sending EOS event");
        gst_pad_push_event (musepackdec->srcpad, gst_event_new_eos ());
        /* fall through to pause */
    }

pause_task:
    {
        GST_DEBUG_OBJECT (musepackdec, "Pausing task");
        gst_pad_pause_task (sinkpad);
        return;
    }
}