Beispiel #1
0
static GstStateChangeReturn
gst_siren_change_state (GstElement * element, GstStateChange transition)
{
  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
  GstSirenEnc *enc = GST_SIREN_ENC (element);

  switch (transition) {
    case GST_STATE_CHANGE_READY_TO_PAUSED:
      enc->discont = FALSE;
      break;
    default:
      break;
  }

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

  switch (transition) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      gst_adapter_clear (enc->adapter);
      break;
    default:
      break;
  }

  return ret;
}
Beispiel #2
0
static gboolean
gst_siren_enc_stop (GstAudioEncoder * enc)
{
  GstSirenEnc *senc = GST_SIREN_ENC (enc);

  GST_DEBUG_OBJECT (senc, "stop");

  Siren7_CloseEncoder (senc->encoder);

  return TRUE;
}
Beispiel #3
0
static gboolean
gst_siren_enc_start (GstAudioEncoder * enc)
{
  GstSirenEnc *senc = GST_SIREN_ENC (enc);

  GST_DEBUG_OBJECT (enc, "start");

  senc->encoder = Siren7_NewEncoder (16000);

  return TRUE;
}
Beispiel #4
0
static void
gst_siren_enc_finalize (GObject * object)
{
  GstSirenEnc *enc = GST_SIREN_ENC (object);

  GST_DEBUG_OBJECT (object, "Disposing");

  Siren7_CloseEncoder (enc->encoder);
  g_object_unref (enc->adapter);

  G_OBJECT_CLASS (parent_class)->finalize (object);
}
Beispiel #5
0
static gboolean
gst_siren_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
{
  GstSirenEnc *enc;
  gboolean res;
  GstCaps *outcaps;

  enc = GST_SIREN_ENC (GST_PAD_PARENT (pad));

  outcaps = gst_static_pad_template_get_caps (&srctemplate);
  res = gst_pad_set_caps (enc->srcpad, outcaps);
  gst_caps_unref (outcaps);

  return res;
}
Beispiel #6
0
static gboolean
gst_siren_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info)
{
  GstSirenEnc *enc;
  gboolean res;
  GstCaps *outcaps;

  enc = GST_SIREN_ENC (benc);

  outcaps = gst_static_pad_template_get_caps (&srctemplate);
  res = gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc), outcaps);
  gst_caps_unref (outcaps);

  /* report needs to base class */
  gst_audio_encoder_set_frame_samples_min (benc, 320);
  gst_audio_encoder_set_frame_samples_max (benc, 320);
  /* no remainder or flushing please */
  gst_audio_encoder_set_hard_min (benc, TRUE);
  gst_audio_encoder_set_drainable (benc, FALSE);

  return res;
}
Beispiel #7
0
static gboolean
gst_siren_enc_sink_event (GstPad * pad, GstEvent * event)
{
  GstSirenEnc *enc;
  gboolean res;

  enc = GST_SIREN_ENC (GST_PAD_PARENT (pad));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_EOS:
      gst_adapter_clear (enc->adapter);
      res = gst_pad_push_event (enc->srcpad, event);
      break;
    case GST_EVENT_FLUSH_STOP:
      gst_adapter_clear (enc->adapter);
      res = gst_pad_push_event (enc->srcpad, event);
      break;
    default:
      res = gst_pad_push_event (enc->srcpad, event);
      break;
  }
  return res;
}
Beispiel #8
0
static GstFlowReturn
gst_siren_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
{
  GstSirenEnc *enc;
  GstFlowReturn ret = GST_FLOW_OK;
  GstBuffer *out_buf;
  guint8 *in_data, *out_data;
  guint i, size, num_frames;
  gint out_size, in_size;
  gint encode_ret;

  g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);

  enc = GST_SIREN_ENC (benc);

  size = GST_BUFFER_SIZE (buf);

  GST_LOG_OBJECT (enc, "Received buffer of size %d", GST_BUFFER_SIZE (buf));

  g_return_val_if_fail (size > 0, GST_FLOW_ERROR);
  g_return_val_if_fail (size % 640 == 0, GST_FLOW_ERROR);

  /* we need to process 640 input bytes to produce 40 output bytes */
  /* calculate the amount of frames we will handle */
  num_frames = size / 640;

  /* this is the input/output size */
  in_size = num_frames * 640;
  out_size = num_frames * 40;

  GST_LOG_OBJECT (enc, "we have %u frames, %u in, %u out", num_frames, in_size,
      out_size);

  /* get a buffer */
  ret = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_ENCODER_SRC_PAD (benc),
      -1, out_size, GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (benc)), &out_buf);
  if (ret != GST_FLOW_OK)
    goto alloc_failed;

  /* get the input data for all the frames */
  in_data = GST_BUFFER_DATA (buf);
  out_data = GST_BUFFER_DATA (out_buf);

  for (i = 0; i < num_frames; i++) {
    GST_LOG_OBJECT (enc, "Encoding frame %u/%u", i, num_frames);

    /* encode 640 input bytes to 40 output bytes */
    encode_ret = Siren7_EncodeFrame (enc->encoder, in_data, out_data);
    if (encode_ret != 0)
      goto encode_error;

    /* move to next frame */
    out_data += 40;
    in_data += 640;
  }

  GST_LOG_OBJECT (enc, "Finished encoding");

  /* we encode all we get, pass it along */
  ret = gst_audio_encoder_finish_frame (benc, out_buf, -1);

done:
  return ret;

  /* ERRORS */
alloc_failed:
  {
    GST_DEBUG_OBJECT (enc, "failed to pad_alloc buffer: %d (%s)", ret,
        gst_flow_get_name (ret));
    goto done;
  }
encode_error:
  {
    GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
        ("Error encoding frame: %d", encode_ret));
    ret = GST_FLOW_ERROR;
    gst_buffer_unref (out_buf);
    goto done;
  }
}
Beispiel #9
0
static GstFlowReturn
gst_siren_enc_chain (GstPad * pad, GstBuffer * buf)
{
  GstSirenEnc *enc;
  GstFlowReturn ret = GST_FLOW_OK;
  GstBuffer *out_buf;
  guint8 *in_data, *out_data;
  guint8 *to_free = NULL;
  guint i, size, num_frames;
  gint out_size, in_size;
  gint encode_ret;
  gboolean discont;
  GstClockTime timestamp;
  guint64 distance;
  GstCaps *outcaps;

  enc = GST_SIREN_ENC (GST_PAD_PARENT (pad));

  discont = GST_BUFFER_IS_DISCONT (buf);
  if (discont) {
    GST_DEBUG_OBJECT (enc, "received DISCONT, flush adapter");
    gst_adapter_clear (enc->adapter);
    enc->discont = TRUE;
  }

  gst_adapter_push (enc->adapter, buf);

  size = gst_adapter_available (enc->adapter);

  GST_LOG_OBJECT (enc, "Received buffer of size %d with adapter of size : %d",
      GST_BUFFER_SIZE (buf), size);

  /* we need to process 640 input bytes to produce 40 output bytes */
  /* calculate the amount of frames we will handle */
  num_frames = size / 640;

  /* no frames, wait some more */
  if (num_frames == 0)
    goto done;

  /* this is the input/output size */
  in_size = num_frames * 640;
  out_size = num_frames * 40;

  GST_LOG_OBJECT (enc, "we have %u frames, %u in, %u out", num_frames, in_size,
      out_size);

  /* set output caps when needed */
  if ((outcaps = GST_PAD_CAPS (enc->srcpad)) == NULL) {
    outcaps = gst_static_pad_template_get_caps (&srctemplate);
    gst_pad_set_caps (enc->srcpad, outcaps);
    gst_caps_unref (outcaps);
  }

  /* get a buffer */
  ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad, -1,
      out_size, outcaps, &out_buf);
  if (ret != GST_FLOW_OK)
    goto alloc_failed;

  /* get the timestamp for the output buffer */
  timestamp = gst_adapter_prev_timestamp (enc->adapter, &distance);

  /* add the amount of time taken by the distance */
  if (timestamp != -1)
    timestamp += gst_util_uint64_scale_int (distance / 2, GST_SECOND, 16000);

  GST_LOG_OBJECT (enc,
      "timestamp %" GST_TIME_FORMAT ", distance %" G_GUINT64_FORMAT,
      GST_TIME_ARGS (timestamp), distance);

  /* get the input data for all the frames */
  to_free = in_data = gst_adapter_take (enc->adapter, in_size);
  out_data = GST_BUFFER_DATA (out_buf);

  for (i = 0; i < num_frames; i++) {
    GST_LOG_OBJECT (enc, "Encoding frame %u/%u", i, num_frames);

    /* encode 640 input bytes to 40 output bytes */
    encode_ret = Siren7_EncodeFrame (enc->encoder, in_data, out_data);
    if (encode_ret != 0)
      goto encode_error;

    /* move to next frame */
    out_data += 40;
    in_data += 640;
  }

  GST_LOG_OBJECT (enc, "Finished encoding");

  /* mark discont */
  if (enc->discont) {
    GST_BUFFER_FLAG_SET (out_buf, GST_BUFFER_FLAG_DISCONT);
    enc->discont = FALSE;
  }
  GST_BUFFER_TIMESTAMP (out_buf) = timestamp;
  GST_BUFFER_DURATION (out_buf) = num_frames * FRAME_DURATION;

  ret = gst_pad_push (enc->srcpad, out_buf);

done:
  if (to_free)
    g_free (to_free);

  return ret;

  /* ERRORS */
alloc_failed:
  {
    GST_DEBUG_OBJECT (enc, "failed to pad_alloc buffer: %d (%s)", ret,
        gst_flow_get_name (ret));
    goto done;
  }
encode_error:
  {
    GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
        ("Error encoding frame: %d", encode_ret));
    ret = GST_FLOW_ERROR;
    gst_buffer_unref (out_buf);
    goto done;
  }
}
static GstFlowReturn
gst_siren_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
{
  GstSirenEnc *enc;
  GstFlowReturn ret = GST_FLOW_OK;
  GstBuffer *out_buf;
  guint8 *in_data, *out_data;
  guint i, size, num_frames;
  gint out_size;
#ifndef GST_DISABLE_GST_DEBUG
  gint in_size;
#endif
  gint encode_ret;
  GstMapInfo inmap, outmap;

  g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);

  enc = GST_SIREN_ENC (benc);

  size = gst_buffer_get_size (buf);

  GST_LOG_OBJECT (enc, "Received buffer of size %d", size);

  g_return_val_if_fail (size > 0, GST_FLOW_ERROR);
  g_return_val_if_fail (size % 640 == 0, GST_FLOW_ERROR);

  /* we need to process 640 input bytes to produce 40 output bytes */
  /* calculate the amount of frames we will handle */
  num_frames = size / 640;

  /* this is the input/output size */
#ifndef GST_DISABLE_GST_DEBUG
  in_size = num_frames * 640;
#endif
  out_size = num_frames * 40;

  GST_LOG_OBJECT (enc, "we have %u frames, %u in, %u out", num_frames, in_size,
      out_size);

  /* get a buffer */
  out_buf = gst_audio_encoder_allocate_output_buffer (benc, out_size);
  if (out_buf == NULL)
    goto alloc_failed;

  /* get the input data for all the frames */
  gst_buffer_map (buf, &inmap, GST_MAP_READ);
  gst_buffer_map (out_buf, &outmap, GST_MAP_READ);
  in_data = inmap.data;
  out_data = outmap.data;

  for (i = 0; i < num_frames; i++) {
    GST_LOG_OBJECT (enc, "Encoding frame %u/%u", i, num_frames);

    /* encode 640 input bytes to 40 output bytes */
    encode_ret = Siren7_EncodeFrame (enc->encoder, in_data, out_data);
    if (encode_ret != 0)
      goto encode_error;

    /* move to next frame */
    out_data += 40;
    in_data += 640;
  }

  gst_buffer_unmap (buf, &inmap);
  gst_buffer_unmap (out_buf, &outmap);

  GST_LOG_OBJECT (enc, "Finished encoding");

  /* we encode all we get, pass it along */
  ret = gst_audio_encoder_finish_frame (benc, out_buf, -1);

done:
  return ret;

  /* ERRORS */
alloc_failed:
  {
    GST_DEBUG_OBJECT (enc, "failed to pad_alloc buffer: %d (%s)", ret,
        gst_flow_get_name (ret));
    goto done;
  }
encode_error:
  {
    GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
        ("Error encoding frame: %d", encode_ret));
    ret = GST_FLOW_ERROR;
    gst_buffer_unref (out_buf);
    goto done;
  }
}