static GstFlowReturn
gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
                          GstCaps * caps, GstBuffer ** buf)
{
    gint width, height;
    GstStructure *structure = NULL;
    GstSLVideo *slvideo;
    slvideo = GST_SLVIDEO(bsink);

    // caps == requested caps
    // we can ignore these and reverse-negotiate our preferred dimensions with
    // the peer if we like - we need to do this to obey dynamic resize requests
    // flowing in from the app.
    structure = llgst_caps_get_structure (caps, 0);
    if (!llgst_structure_get_int(structure, "width", &width) ||
            !llgst_structure_get_int(structure, "height", &height))
    {
        GST_WARNING_OBJECT (slvideo, "no width/height in caps %" GST_PTR_FORMAT, caps);
        return GST_FLOW_NOT_NEGOTIATED;
    }

    GstBuffer *newbuf = llgst_buffer_new();
    bool made_bufferdata_ptr = false;
#define MAXDEPTHHACK 4

    GST_OBJECT_LOCK(slvideo);
    if (slvideo->resize_forced_always) // app is giving us a fixed size to work with
    {
        gint slwantwidth, slwantheight;
        slwantwidth = slvideo->resize_try_width;
        slwantheight = slvideo->resize_try_height;

        if (slwantwidth != width ||
                slwantheight != height)
        {
            // don't like requested caps, we will issue our own suggestion - copy
            // the requested caps but substitute our own width and height and see
            // if our peer is happy with that.

            GstCaps *desired_caps;
            GstStructure *desired_struct;
            desired_caps = llgst_caps_copy (caps);
            desired_struct = llgst_caps_get_structure (desired_caps, 0);

            GValue value = {0};
            g_value_init(&value, G_TYPE_INT);
            g_value_set_int(&value, slwantwidth);
            llgst_structure_set_value (desired_struct, "width", &value);
            g_value_unset(&value);
            g_value_init(&value, G_TYPE_INT);
            g_value_set_int(&value, slwantheight);
            llgst_structure_set_value (desired_struct, "height", &value);

            if (llgst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (slvideo),
                                            desired_caps))
            {
                // todo: re-use buffers from a pool?
                // todo: set MALLOCDATA to null, set DATA to point straight to shm?

                // peer likes our cap suggestion
                DEBUGMSG("peer loves us :)");
                GST_BUFFER_SIZE(newbuf) = slwantwidth * slwantheight * MAXDEPTHHACK;
                GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf));
                GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf);
                llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), desired_caps);

                made_bufferdata_ptr = true;
            } else {
                // peer hates our cap suggestion
                INFOMSG("peer hates us :(");
                llgst_caps_unref(desired_caps);
            }
        }
    }

    GST_OBJECT_UNLOCK(slvideo);

    if (!made_bufferdata_ptr) // need to fallback to malloc at original size
    {
        GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK;
        GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf));
        GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf);
        llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps);
    }

    *buf = GST_BUFFER_CAST(newbuf);

    return GST_FLOW_OK;
}
예제 #2
0
static GstFlowReturn
gst_celt_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
{
  GstCeltEnc *enc;
  GstFlowReturn ret = GST_FLOW_OK;

  enc = GST_CELT_ENC (benc);

  if (!enc->header_sent) {
    /* Celt streams begin with two headers; the initial header (with
       most of the codec setup parameters) which is mandated by the Ogg
       bitstream spec.  The second header holds any comment fields.
       We merely need to make the headers, then pass them to libcelt 
       one at a time; libcelt handles the additional Ogg bitstream 
       constraints */
    GstBuffer *buf1, *buf2;
    GstCaps *caps;
    /* libcelt has a bug which underestimates header size by 4... */
    unsigned int header_size = enc->header.header_size + 4;
    unsigned char *data = g_malloc (header_size);

    /* create header buffer */
    int error = celt_header_to_packet (&enc->header, data, header_size);
    if (error < 0) {
      g_free (data);
      goto no_header;
    }
    buf1 = gst_buffer_new ();
    GST_BUFFER_DATA (buf1) = GST_BUFFER_MALLOCDATA (buf1) = data;
    GST_BUFFER_SIZE (buf1) = header_size;
    GST_BUFFER_OFFSET_END (buf1) = 0;
    GST_BUFFER_OFFSET (buf1) = 0;

    /* create comment buffer */
    buf2 = gst_celt_enc_create_metadata_buffer (enc);

    /* mark and put on caps */
    caps = gst_pad_get_caps (GST_AUDIO_ENCODER_SRC_PAD (enc));
    gst_caps_set_simple (caps,
        "rate", G_TYPE_INT, enc->rate,
        "channels", G_TYPE_INT, enc->channels,
        "frame-size", G_TYPE_INT, enc->frame_size, NULL);
    caps = _gst_caps_set_buffer_array (caps, "streamheader", buf1, buf2, NULL);

    /* negotiate with these caps */
    GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps);
    GST_LOG_OBJECT (enc, "rate=%d channels=%d frame-size=%d",
        enc->rate, enc->channels, enc->frame_size);
    gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc), caps);

    gst_buffer_set_caps (buf1, caps);
    gst_buffer_set_caps (buf2, caps);
    gst_caps_unref (caps);

    /* push out buffers */
    /* store buffers for later pre_push sending */
    g_slist_foreach (enc->headers, (GFunc) gst_buffer_unref, NULL);
    enc->headers = NULL;
    GST_DEBUG_OBJECT (enc, "storing header buffers");
    enc->headers = g_slist_prepend (enc->headers, buf2);
    enc->headers = g_slist_prepend (enc->headers, buf1);

    enc->header_sent = TRUE;
  }

  GST_DEBUG_OBJECT (enc, "received buffer %p of %u bytes", buf,
      buf ? GST_BUFFER_SIZE (buf) : 0);

  ret = gst_celt_enc_encode (enc, buf);

done:
  return ret;

  /* ERRORS */
no_header:
  {
    GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
        ("Failed to encode header"));
    ret = GST_FLOW_ERROR;
    goto done;
  }
}
예제 #3
0
void test_buffer_clipping_samples()
{
  GstSegment s;
  GstBuffer *buf;
  GstBuffer *ret;
  guint8 *data;
  
        	xmlfile = "test_buffer_clipping_samples";
  std_log(LOG_FILENAME_LINE, "Test Started test_buffer_clipping_samples");

  /* Clip start and end */
  buf = gst_buffer_new ();
  data = (guint8 *) g_malloc (1000);
  GST_BUFFER_SIZE (buf) = 1000;
  GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data;

  gst_segment_init (&s, GST_FORMAT_DEFAULT);
  gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 400,
      800, 400);

  GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND;
  GST_BUFFER_DURATION (buf) = 10 * GST_SECOND;
  GST_BUFFER_OFFSET (buf) = 200;
  GST_BUFFER_OFFSET_END (buf) = 1200;

  ret = gst_audio_buffer_clip (buf, &s, 100, 1);
  fail_unless (ret != NULL);

  fail_unless (GST_BUFFER_TIMESTAMP (ret) == 4 * GST_SECOND);
  fail_unless (GST_BUFFER_DURATION (ret) == 4 * GST_SECOND);
  fail_unless (GST_BUFFER_OFFSET (ret) == 400);
  fail_unless (GST_BUFFER_OFFSET_END (ret) == 800);
  fail_unless (GST_BUFFER_DATA (ret) == data + 200);
  fail_unless (GST_BUFFER_SIZE (ret) == 400);

  gst_buffer_unref (ret);

  /* Clip only start */
  buf = gst_buffer_new ();
  data = (guint8 *) g_malloc (1000);
  GST_BUFFER_SIZE (buf) = 1000;
  GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data;

  gst_segment_init (&s, GST_FORMAT_DEFAULT);
  gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 400,
      1200, 400);

  GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND;
  GST_BUFFER_DURATION (buf) = 10 * GST_SECOND;
  GST_BUFFER_OFFSET (buf) = 200;
  GST_BUFFER_OFFSET_END (buf) = 1200;

  ret = gst_audio_buffer_clip (buf, &s, 100, 1);
  fail_unless (ret != NULL);

  fail_unless (GST_BUFFER_TIMESTAMP (ret) == 4 * GST_SECOND);
  fail_unless (GST_BUFFER_DURATION (ret) == 8 * GST_SECOND);
  fail_unless (GST_BUFFER_OFFSET (ret) == 400);
  fail_unless (GST_BUFFER_OFFSET_END (ret) == 1200);
  fail_unless (GST_BUFFER_DATA (ret) == data + 200);
  fail_unless (GST_BUFFER_SIZE (ret) == 800);

  gst_buffer_unref (ret);

  /* Clip only stop */
  buf = gst_buffer_new ();
  data = (guint8 *) g_malloc (1000);
  GST_BUFFER_SIZE (buf) = 1000;
  GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data;

  gst_segment_init (&s, GST_FORMAT_DEFAULT);
  gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 200,
      1000, 200);

  GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND;
  GST_BUFFER_DURATION (buf) = 10 * GST_SECOND;
  GST_BUFFER_OFFSET (buf) = 200;
  GST_BUFFER_OFFSET_END (buf) = 1200;

  ret = gst_audio_buffer_clip (buf, &s, 100, 1);
  fail_unless (ret != NULL);

  fail_unless (GST_BUFFER_TIMESTAMP (ret) == 2 * GST_SECOND);
  fail_unless (GST_BUFFER_DURATION (ret) == 8 * GST_SECOND);
  fail_unless (GST_BUFFER_OFFSET (ret) == 200);
  fail_unless (GST_BUFFER_OFFSET_END (ret) == 1000);
  fail_unless (GST_BUFFER_DATA (ret) == data);
  fail_unless (GST_BUFFER_SIZE (ret) == 800);

  gst_buffer_unref (ret);

  /* Buffer outside segment */
  buf = gst_buffer_new ();
  data = (guint8 *) g_malloc (1000);
  GST_BUFFER_SIZE (buf) = 1000;
  GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data;

  gst_segment_init (&s, GST_FORMAT_DEFAULT);
  gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 1200,
      2000, 1200);

  GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND;
  GST_BUFFER_DURATION (buf) = 10 * GST_SECOND;
  GST_BUFFER_OFFSET (buf) = 200;
  GST_BUFFER_OFFSET_END (buf) = 1200;

  ret = gst_audio_buffer_clip (buf, &s, 100, 1);
  fail_unless (ret == NULL);

  /* Clip start and end but don't touch duration and offset_end */
  buf = gst_buffer_new ();
  data = (guint8 *) g_malloc (1000);
  GST_BUFFER_SIZE (buf) = 1000;
  GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data;

  gst_segment_init (&s, GST_FORMAT_DEFAULT);
  gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 400,
      800, 400);

  GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND;
  GST_BUFFER_DURATION (buf) = GST_CLOCK_TIME_NONE;
  GST_BUFFER_OFFSET (buf) = 200;
  GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE;

  ret = gst_audio_buffer_clip (buf, &s, 100, 1);
  fail_unless (ret != NULL);

  fail_unless (GST_BUFFER_TIMESTAMP (ret) == 4 * GST_SECOND);
  fail_unless (GST_BUFFER_DURATION (ret) == GST_CLOCK_TIME_NONE);
  fail_unless (GST_BUFFER_OFFSET (ret) == 400);
  fail_unless (GST_BUFFER_OFFSET_END (ret) == GST_BUFFER_OFFSET_NONE);
  fail_unless (GST_BUFFER_DATA (ret) == data + 200);
  fail_unless (GST_BUFFER_SIZE (ret) == 400);

  gst_buffer_unref (ret);

  /* If the buffer has no offset it should assert()
   * FIXME: check if return value is the same as the input buffer.
   *        probably can't be done because the assert() does a SIGABRT.
   */
  buf = gst_buffer_new ();
  data = (guint8 *) g_malloc (1000);
  GST_BUFFER_SIZE (buf) = 1000;
  GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data;

  gst_segment_init (&s, GST_FORMAT_DEFAULT);
  gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 0, 10, 0);

  GST_BUFFER_TIMESTAMP (buf) = 0 * GST_SECOND;
  GST_BUFFER_DURATION (buf) = GST_CLOCK_TIME_NONE;
  GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE;
  GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE;

  ASSERT_CRITICAL (ret = gst_audio_buffer_clip (buf, &s, 100, 1));

  gst_buffer_unref (buf);
  
      std_log(LOG_FILENAME_LINE, "Test Successful");
  create_xml(0);
}
예제 #4
0
static GstFlowReturn
gst_shm_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
{
  GstShmSrc *self = GST_SHM_SRC (psrc);
  gchar *buf = NULL;
  int rv = 0;
  struct GstShmBuffer *gsb;

  do {
    if (gst_poll_wait (self->poll, GST_CLOCK_TIME_NONE) < 0) {
      if (errno == EBUSY)
        return GST_FLOW_WRONG_STATE;
      GST_ELEMENT_ERROR (self, RESOURCE, READ, ("Failed to read from shmsrc"),
          ("Poll failed on fd: %s", strerror (errno)));
      return GST_FLOW_ERROR;
    }

    if (self->unlocked)
      return GST_FLOW_WRONG_STATE;

    if (gst_poll_fd_has_closed (self->poll, &self->pollfd)) {
      GST_ELEMENT_ERROR (self, RESOURCE, READ, ("Failed to read from shmsrc"),
          ("Control socket has closed"));
      return GST_FLOW_ERROR;
    }

    if (gst_poll_fd_has_error (self->poll, &self->pollfd)) {
      GST_ELEMENT_ERROR (self, RESOURCE, READ, ("Failed to read from shmsrc"),
          ("Control socket has error"));
      return GST_FLOW_ERROR;
    }

    if (gst_poll_fd_can_read (self->poll, &self->pollfd)) {
      buf = NULL;
      GST_LOG_OBJECT (self, "Reading from pipe");
      GST_OBJECT_LOCK (self);
      rv = sp_client_recv (self->pipe->pipe, &buf);
      GST_OBJECT_UNLOCK (self);
      if (rv < 0) {
        GST_ELEMENT_ERROR (self, RESOURCE, READ, ("Failed to read from shmsrc"),
            ("Error reading control data: %d", rv));
        return GST_FLOW_ERROR;
      }
    }
  } while (buf == NULL);

  GST_LOG_OBJECT (self, "Got buffer %p of size %d", buf, rv);

  gsb = g_slice_new0 (struct GstShmBuffer);
  gsb->buf = buf;
  gsb->pipe = self->pipe;
  gst_shm_pipe_inc (self->pipe);

  *outbuf = gst_buffer_new ();
  GST_BUFFER_FLAG_SET (*outbuf, GST_BUFFER_FLAG_READONLY);
  GST_BUFFER_DATA (*outbuf) = (guint8 *) buf;
  GST_BUFFER_SIZE (*outbuf) = rv;
  GST_BUFFER_MALLOCDATA (*outbuf) = (guint8 *) gsb;
  GST_BUFFER_FREE_FUNC (*outbuf) = free_buffer;

  return GST_FLOW_OK;
}
예제 #5
0
static void
gst_decklink_src_task (void *priv)
{
  GstDecklinkSrc *decklinksrc = GST_DECKLINK_SRC (priv);
  GstBuffer *buffer;
  GstBuffer *audio_buffer;
  IDeckLinkVideoInputFrame *video_frame;
  IDeckLinkAudioInputPacket *audio_frame;
  void *data;
  int n_samples;
  GstFlowReturn ret;
  const GstDecklinkMode *mode;

  GST_DEBUG_OBJECT (decklinksrc, "task");

  g_mutex_lock (decklinksrc->mutex);
  while (decklinksrc->video_frame == NULL && !decklinksrc->stop) {
    g_cond_wait (decklinksrc->cond, decklinksrc->mutex);
  }
  video_frame = decklinksrc->video_frame;
  audio_frame = decklinksrc->audio_frame;
  decklinksrc->video_frame = NULL;
  decklinksrc->audio_frame = NULL;
  g_mutex_unlock (decklinksrc->mutex);

  if (decklinksrc->stop) {
    if (video_frame)
      video_frame->Release ();
    if (audio_frame)
      audio_frame->Release ();
    GST_DEBUG ("stopping task");
    return;
  }

  /* warning on dropped frames */
  if (decklinksrc->dropped_frames - decklinksrc->dropped_frames_old > 0) {
    GST_ELEMENT_WARNING (decklinksrc, RESOURCE, READ,
        ("Dropped %d frame(s), for a total of %d frame(s)",
            decklinksrc->dropped_frames - decklinksrc->dropped_frames_old,
            decklinksrc->dropped_frames), (NULL));
    decklinksrc->dropped_frames_old = decklinksrc->dropped_frames;
  }

  if (!decklinksrc->video_new_segment) {
    GstEvent *event;
    gboolean ret;

    event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
        0, GST_CLOCK_TIME_NONE, 0);

    ret = gst_pad_push_event (decklinksrc->videosrcpad, event);
    if (!ret) {
      GST_WARNING ("new segment event not handled");
    }

    decklinksrc->video_new_segment = TRUE;
  }

  mode = gst_decklink_get_mode (decklinksrc->mode);

  video_frame->GetBytes (&data);
  if (decklinksrc->copy_data) {
    buffer = gst_buffer_new_and_alloc (mode->width * mode->height * 2);

    memcpy (GST_BUFFER_DATA (buffer), data, mode->width * mode->height * 2);

    video_frame->Release ();
  } else {
    VideoFrame *vf;

    vf = (VideoFrame *) g_malloc0 (sizeof (VideoFrame));
    buffer = gst_buffer_new ();
    GST_BUFFER_SIZE (buffer) = mode->width * mode->height * 2;

    GST_BUFFER_DATA (buffer) = (guint8 *) data;

    GST_BUFFER_FREE_FUNC (buffer) = video_frame_free;
    GST_BUFFER_MALLOCDATA (buffer) = (guint8 *) vf;
    vf->frame = video_frame;
    vf->input = decklinksrc->input;
    vf->input->AddRef ();
  }

  GST_BUFFER_TIMESTAMP (buffer) =
      gst_util_uint64_scale_int (decklinksrc->frame_num * GST_SECOND,
      mode->fps_d, mode->fps_n);
  GST_BUFFER_DURATION (buffer) =
      gst_util_uint64_scale_int ((decklinksrc->frame_num + 1) * GST_SECOND,
      mode->fps_d, mode->fps_n) - GST_BUFFER_TIMESTAMP (buffer);
  GST_BUFFER_OFFSET (buffer) = decklinksrc->frame_num;
  GST_BUFFER_OFFSET_END (buffer) = decklinksrc->frame_num;
  if (decklinksrc->frame_num == 0) {
    GstEvent *event;
    gboolean ret;

    GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);

    event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0,
        GST_CLOCK_TIME_NONE, 0);

    if (gst_pad_is_linked (decklinksrc->videosrcpad)) {
      gst_event_ref (event);
      ret = gst_pad_push_event (decklinksrc->videosrcpad, event);
      if (!ret) {
        GST_ERROR_OBJECT (decklinksrc, "new segment event ret=%d", ret);
        gst_event_unref (event);
        return;
      }
    } else {
      gst_event_unref (event);
    }

    if (gst_pad_is_linked (decklinksrc->audiosrcpad)) {
      ret = gst_pad_push_event (decklinksrc->audiosrcpad, event);
      if (!ret) {
        GST_ERROR_OBJECT (decklinksrc, "new segment event ret=%d", ret);
        gst_event_unref (event);
      }
    } else {
      gst_event_unref (event);
    }

  }

  if (decklinksrc->video_caps == NULL) {
    decklinksrc->video_caps = gst_decklink_mode_get_caps (decklinksrc->mode);
  }
  gst_buffer_set_caps (buffer, decklinksrc->video_caps);

  ret = gst_pad_push (decklinksrc->videosrcpad, buffer);
  if (!(ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED ||
          ret == GST_FLOW_WRONG_STATE)) {
    GST_ELEMENT_ERROR (decklinksrc, STREAM, FAILED,
        ("Internal data stream error."),
        ("stream stopped, reason %s", gst_flow_get_name (ret)));
  }

  if (gst_pad_is_linked (decklinksrc->audiosrcpad)) {
    if (!decklinksrc->audio_new_segment) {
      GstEvent *event;
      gboolean ret;

      event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
          0, GST_CLOCK_TIME_NONE, 0);

      ret = gst_pad_push_event (decklinksrc->audiosrcpad, event);
      if (!ret) {
        GST_WARNING ("new segment event not handled");
      }

      decklinksrc->audio_new_segment = TRUE;
    }

    n_samples = audio_frame->GetSampleFrameCount ();
    audio_frame->GetBytes (&data);
    audio_buffer = gst_buffer_new_and_alloc (n_samples * 2 * 2);
    memcpy (GST_BUFFER_DATA (audio_buffer), data, n_samples * 2 * 2);

    GST_BUFFER_TIMESTAMP (audio_buffer) =
        gst_util_uint64_scale_int (decklinksrc->num_audio_samples * GST_SECOND,
        1, 48000);
    GST_BUFFER_DURATION (audio_buffer) =
        gst_util_uint64_scale_int (n_samples * GST_SECOND, 1, 48000);
    decklinksrc->num_audio_samples += n_samples;

    if (decklinksrc->audio_caps == NULL) {
      decklinksrc->audio_caps = gst_caps_new_simple ("audio/x-raw-int",
          "endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
          "signed", G_TYPE_BOOLEAN, TRUE,
          "depth", G_TYPE_INT, 16,
          "width", G_TYPE_INT, 16,
          "channels", G_TYPE_INT, 2, "rate", G_TYPE_INT, 48000, NULL);
    }
    gst_buffer_set_caps (audio_buffer, decklinksrc->audio_caps);

    ret = gst_pad_push (decklinksrc->audiosrcpad, audio_buffer);
    if (!(ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED ||
            ret == GST_FLOW_WRONG_STATE)) {
      GST_ELEMENT_ERROR (decklinksrc, STREAM, FAILED,
          ("Internal data stream error."),
          ("stream stopped, reason %s", gst_flow_get_name (ret)));
    }
  }
  if (audio_frame)
    audio_frame->Release ();
}
예제 #6
0
static GstFlowReturn gst_nrzikiss_chain(GstPad *pad, GstBuffer *buf)
{
	Gst_nrzikiss *nrzikiss;
	GstCaps *caps;
	gfloat *demod;
	int i;
	int pushed = 0;

	nrzikiss = GST_NRZIKISS(gst_pad_get_parent(pad));

	demod = (gfloat *)GST_BUFFER_DATA(buf);
	for (i = 0; i < GST_BUFFER_SIZE(buf)/sizeof(gfloat); i ++) {
		int bit;
		if (demod[i] > 0.0) {
			bit = nrzikiss->lastbit;
			nrzikiss->lastbit = 1;
		} else {
			bit = !nrzikiss->lastbit;
			nrzikiss->lastbit = 0;
		}
		if (bit) {
			nrzikiss->ones++;
		} else {
			if (nrzikiss->ones == 5) {
				nrzikiss->ones = 0;
				nrzikiss->stuffed = 3;
				/* Stuffed bit, drop it and go to next */
				continue;
			}
			nrzikiss->ones = 0;
			if (nrzikiss->stuffed >= 0)
				nrzikiss->stuffed--;
		}
		nrzikiss->byte >>= 1;
		nrzikiss->byte |= bit * 128;
		if (nrzikiss->byte == 0x7e && nrzikiss->stuffed < 0) {
			nrzikiss->bytelen = 0;
			if (nrzikiss->buf) {
				if ((nrzikiss->crc & 0xffff) != 0xf0b8 ||
				    GST_BUFFER_SIZE(nrzikiss->buf) < 5) {
					nrzikiss->crc = 0xffff;
					GST_BUFFER_SIZE(nrzikiss->buf) = 2;
					continue;
				}
				GST_BUFFER_SIZE(nrzikiss->buf)-=2;
				GST_BUFFER_DATA(nrzikiss->buf)
				    [GST_BUFFER_SIZE(nrzikiss->buf)++] = 0xc0;
				GST_BUFFER_TIMESTAMP(nrzikiss->buf) =
				    GST_BUFFER_TIMESTAMP(buf);
				GST_BUFFER_OFFSET(nrzikiss->buf) =
				    nrzikiss->offset;
				nrzikiss->offset += 
				    GST_BUFFER_SIZE(nrzikiss->buf);
				caps = gst_pad_get_caps(nrzikiss->srcpad);
				gst_buffer_set_caps(nrzikiss->buf, caps);
				gst_caps_unref(caps);
				gst_pad_push(nrzikiss->srcpad, nrzikiss->buf);
				pushed = 1;
			}
			nrzikiss->buf = gst_buffer_new();
			GST_BUFFER_SIZE(nrzikiss->buf) = 2;
			GST_BUFFER_DATA(nrzikiss->buf) = (guchar *)g_malloc(1024);
			GST_BUFFER_MALLOCDATA(nrzikiss->buf) =
			    GST_BUFFER_DATA(nrzikiss->buf);
			GST_BUFFER_DATA(nrzikiss->buf)[0] = 0xc0;
			GST_BUFFER_DATA(nrzikiss->buf)[1] = 0x0;
			nrzikiss->crc = 0xffff;
		}
		if (++nrzikiss->bytelen == 8) {
			guchar *buffer;

			nrzikiss->bytelen = 0;
			if (!nrzikiss->buf)
				continue;
			if (GST_BUFFER_SIZE(nrzikiss->buf) >= 32768)
				continue;
			if (GST_BUFFER_SIZE(nrzikiss->buf) % 1024 >= 1022) {
				guchar *newbuf;
				newbuf = (guchar *) g_realloc(
				    GST_BUFFER_DATA(nrzikiss->buf),
				    GST_BUFFER_SIZE(nrzikiss->buf) + 1026);
				GST_BUFFER_MALLOCDATA(nrzikiss->buf) =
				    GST_BUFFER_DATA(nrzikiss->buf);
				if (!newbuf) {
					/* Low mem, we drop whatever we had
					   and hope frames are smaller than
					   this (or more mem will come back)
					 */
					nrzikiss->crc = 0xffff;
					GST_BUFFER_SIZE(nrzikiss->buf) = 2;
					continue;
				}
				GST_BUFFER_DATA(nrzikiss->buf) = newbuf;
			}
			buffer = GST_BUFFER_DATA(nrzikiss->buf);
			nrzikiss->crc = (nrzikiss->crc >> 8) ^
			    crc_ccitt_table[(nrzikiss->crc ^ nrzikiss->byte) & 0xff];
			if (nrzikiss->byte == 0xc0) {
				buffer[GST_BUFFER_SIZE(nrzikiss->buf)] = 0xdb;
				buffer[GST_BUFFER_SIZE(nrzikiss->buf)+1] = 0xdc;
				GST_BUFFER_SIZE(nrzikiss->buf)+= 2;
			} else if (nrzikiss->byte == 0xdb) {
				buffer[GST_BUFFER_SIZE(nrzikiss->buf)] = 0xdb;
				buffer[GST_BUFFER_SIZE(nrzikiss->buf)+1] = 0xdd;
				GST_BUFFER_SIZE(nrzikiss->buf)+= 2;
			} else {
				buffer[GST_BUFFER_SIZE(nrzikiss->buf)] =
				    nrzikiss->byte;
				GST_BUFFER_SIZE(nrzikiss->buf)++;
			}
		}
	}
예제 #7
0
파일: gstaravis.c 프로젝트: Will-W/aravis
static GstFlowReturn
gst_aravis_create (GstPushSrc * push_src, GstBuffer ** buffer)
{
	GstAravis *gst_aravis;
	ArvBuffer *arv_buffer;
	int arv_row_stride;

	gst_aravis = GST_ARAVIS (push_src);

	do {
		arv_buffer = arv_stream_timeout_pop_buffer (gst_aravis->stream, gst_aravis->buffer_timeout_us);
		if (arv_buffer != NULL && arv_buffer->status != ARV_BUFFER_STATUS_SUCCESS)
			arv_stream_push_buffer (gst_aravis->stream, arv_buffer);
	} while (arv_buffer != NULL && arv_buffer->status != ARV_BUFFER_STATUS_SUCCESS);

	if (arv_buffer == NULL)
		return GST_FLOW_ERROR;

	*buffer = gst_buffer_new ();

	arv_row_stride = arv_buffer->width * ARV_PIXEL_FORMAT_BIT_PER_PIXEL (arv_buffer->pixel_format) / 8;

	/* Gstreamer requires row stride to be a multiple of 4 */
	if ((arv_row_stride & 0x3) != 0) {
		int gst_row_stride;
		size_t size;
		void *data;
		int i;

		gst_row_stride = (arv_row_stride & ~(0x3)) + 4;

		size = arv_buffer->height * gst_row_stride;
		data = g_malloc (size);

		for (i = 0; i < arv_buffer->height; i++)
			memcpy (((char *) data) + i * gst_row_stride, ((char *) arv_buffer->data) + i * arv_row_stride, arv_row_stride);

		GST_BUFFER_DATA (buffer) = data;
		GST_BUFFER_MALLOCDATA (buffer) = data;
		GST_BUFFER_SIZE (buffer) = size;
	} else {
		GST_BUFFER_DATA (*buffer) = arv_buffer->data;
		GST_BUFFER_MALLOCDATA (*buffer) = NULL;
		GST_BUFFER_SIZE (*buffer) = arv_buffer->size;
	}

	if (!gst_base_src_get_do_timestamp(GST_BASE_SRC(push_src))) {
		if (gst_aravis->timestamp_offset == 0) {
			gst_aravis->timestamp_offset = arv_buffer->timestamp_ns;
			gst_aravis->last_timestamp = arv_buffer->timestamp_ns;
		}

		GST_BUFFER_TIMESTAMP (*buffer) = arv_buffer->timestamp_ns - gst_aravis->timestamp_offset;
		GST_BUFFER_DURATION (*buffer) = arv_buffer->timestamp_ns - gst_aravis->last_timestamp;

		gst_aravis->last_timestamp = arv_buffer->timestamp_ns;
	}

	arv_stream_push_buffer (gst_aravis->stream, arv_buffer);

	gst_buffer_set_caps (*buffer, gst_aravis->fixed_caps);

	return GST_FLOW_OK;
}
static GstFlowReturn
gst_multi_file_src_create (GstPushSrc * src, GstBuffer ** buffer)
{
  GstMultiFileSrc *multifilesrc;
  gsize size;
  gchar *data;
  gchar *filename;
  GstBuffer *buf;
  gboolean ret;
  GError *error = NULL;

  multifilesrc = GST_MULTI_FILE_SRC (src);

  if (multifilesrc->index < multifilesrc->start_index) {
    multifilesrc->index = multifilesrc->start_index;
  }
  filename = gst_multi_file_src_get_filename (multifilesrc);

  GST_DEBUG_OBJECT (multifilesrc, "reading from file \"%s\".", filename);

  ret = g_file_get_contents (filename, &data, &size, &error);
  if (!ret) {
    if (multifilesrc->successful_read) {
      /* If we've read at least one buffer successfully, not finding the
       * next file is EOS. */
      g_free (filename);
      if (error != NULL)
        g_error_free (error);

      if (multifilesrc->loop) {
        error = NULL;
        multifilesrc->index = multifilesrc->start_index;

        filename = gst_multi_file_src_get_filename (multifilesrc);
        ret = g_file_get_contents (filename, &data, &size, &error);
        if (!ret) {
          g_free (filename);
          if (error != NULL)
            g_error_free (error);

          return GST_FLOW_UNEXPECTED;
        }
      } else {
        return GST_FLOW_UNEXPECTED;
      }
    } else {
      goto handle_error;
    }
  }

  multifilesrc->successful_read = TRUE;
  multifilesrc->index++;
  if (multifilesrc->stop_index != -1 &&
      multifilesrc->index >= multifilesrc->stop_index) {
    multifilesrc->index = multifilesrc->start_index;
  }

  buf = gst_buffer_new ();
  GST_BUFFER_DATA (buf) = (unsigned char *) data;
  GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
  GST_BUFFER_SIZE (buf) = size;
  GST_BUFFER_OFFSET (buf) = multifilesrc->offset;
  GST_BUFFER_OFFSET_END (buf) = multifilesrc->offset + size;
  multifilesrc->offset += size;
  gst_buffer_set_caps (buf, multifilesrc->caps);

  GST_DEBUG_OBJECT (multifilesrc, "read file \"%s\".", filename);

  g_free (filename);
  *buffer = buf;
  return GST_FLOW_OK;

handle_error:
  {
    if (error != NULL) {
      GST_ELEMENT_ERROR (multifilesrc, RESOURCE, READ,
          ("Error while reading from file \"%s\".", filename),
          ("%s", error->message));
      g_error_free (error);
    } else {
      GST_ELEMENT_ERROR (multifilesrc, RESOURCE, READ,
          ("Error while reading from file \"%s\".", filename),
          ("%s", g_strerror (errno)));
    }
    g_free (filename);
    return GST_FLOW_ERROR;
  }
}
예제 #9
0
static GstFlowReturn
gst_speex_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
{
  GstSpeexEnc *enc;
  GstFlowReturn ret = GST_FLOW_OK;

  enc = GST_SPEEX_ENC (benc);

  if (!enc->header_sent) {
    /* Speex streams begin with two headers; the initial header (with
       most of the codec setup parameters) which is mandated by the Ogg
       bitstream spec.  The second header holds any comment fields.
       We merely need to make the headers, then pass them to libspeex 
       one at a time; libspeex handles the additional Ogg bitstream 
       constraints */
    GstBuffer *buf1, *buf2;
    GstCaps *caps;
    guchar *data;
    gint data_len;

    /* create header buffer */
    data = (guint8 *) speex_header_to_packet (&enc->header, &data_len);
    buf1 = gst_buffer_new ();
    GST_BUFFER_DATA (buf1) = GST_BUFFER_MALLOCDATA (buf1) = data;
    GST_BUFFER_SIZE (buf1) = data_len;
    GST_BUFFER_OFFSET_END (buf1) = 0;
    GST_BUFFER_OFFSET (buf1) = 0;

    /* create comment buffer */
    buf2 = gst_speex_enc_create_metadata_buffer (enc);

    /* mark and put on caps */
    caps = gst_caps_new_simple ("audio/x-speex", "rate", G_TYPE_INT, enc->rate,
        "channels", G_TYPE_INT, enc->channels, NULL);
    caps = _gst_caps_set_buffer_array (caps, "streamheader", buf1, buf2, NULL);

    /* negotiate with these caps */
    GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps);

    gst_buffer_set_caps (buf1, caps);
    gst_buffer_set_caps (buf2, caps);
    gst_caps_unref (caps);

    /* push out buffers */
    ret = gst_speex_enc_push_buffer (enc, buf1);

    if (ret != GST_FLOW_OK) {
      gst_buffer_unref (buf2);
      goto done;
    }

    ret = gst_speex_enc_push_buffer (enc, buf2);

    if (ret != GST_FLOW_OK)
      goto done;

    enc->header_sent = TRUE;
  }

  GST_DEBUG_OBJECT (enc, "received buffer %p of %u bytes", buf,
      buf ? GST_BUFFER_SIZE (buf) : 0);

  ret = gst_speex_enc_encode (enc, buf);

done:
  return ret;
}
예제 #10
0
static GstFlowReturn
gst_flxdec_chain (GstPad * pad, GstBuffer * buf)
{
    GstCaps *caps;
    guint avail;
    GstFlowReturn res = GST_FLOW_OK;

    GstFlxDec *flxdec;
    FlxHeader *flxh;

    g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
    flxdec = (GstFlxDec *) gst_pad_get_parent (pad);
    g_return_val_if_fail (flxdec != NULL, GST_FLOW_ERROR);

    gst_adapter_push (flxdec->adapter, buf);
    avail = gst_adapter_available (flxdec->adapter);

    if (flxdec->state == GST_FLXDEC_READ_HEADER) {
        if (avail >= FlxHeaderSize) {
            const guint8 *data = gst_adapter_peek (flxdec->adapter, FlxHeaderSize);

            memcpy ((gchar *) & flxdec->hdr, data, FlxHeaderSize);
            FLX_HDR_FIX_ENDIANNESS (&(flxdec->hdr));
            gst_adapter_flush (flxdec->adapter, FlxHeaderSize);

            flxh = &flxdec->hdr;

            /* check header */
            if (flxh->type != FLX_MAGICHDR_FLI &&
                    flxh->type != FLX_MAGICHDR_FLC && flxh->type != FLX_MAGICHDR_FLX)
                goto wrong_type;

            GST_LOG ("size      :  %d", flxh->size);
            GST_LOG ("frames    :  %d", flxh->frames);
            GST_LOG ("width     :  %d", flxh->width);
            GST_LOG ("height    :  %d", flxh->height);
            GST_LOG ("depth     :  %d", flxh->depth);
            GST_LOG ("speed     :  %d", flxh->speed);

            flxdec->next_time = 0;

            if (flxh->type == FLX_MAGICHDR_FLI) {
                flxdec->frame_time = JIFFIE * flxh->speed;
            } else if (flxh->speed == 0) {
                flxdec->frame_time = GST_SECOND / 70;
            } else {
                flxdec->frame_time = flxh->speed * GST_MSECOND;
            }

            flxdec->duration = flxh->frames * flxdec->frame_time;
            GST_LOG ("duration   :  %" GST_TIME_FORMAT,
                     GST_TIME_ARGS (flxdec->duration));

            caps = gst_caps_from_string (GST_VIDEO_CAPS_xRGB_HOST_ENDIAN);
            gst_caps_set_simple (caps,
                                 "width", G_TYPE_INT, flxh->width,
                                 "height", G_TYPE_INT, flxh->height,
                                 "framerate", GST_TYPE_FRACTION, (gint) GST_MSECOND,
                                 (gint) flxdec->frame_time / 1000, NULL);

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

            if (flxh->depth <= 8)
                flxdec->converter =
                    flx_colorspace_converter_new (flxh->width, flxh->height);

            if (flxh->type == FLX_MAGICHDR_FLC || flxh->type == FLX_MAGICHDR_FLX) {
                GST_LOG ("(FLC) aspect_dx :  %d", flxh->aspect_dx);
                GST_LOG ("(FLC) aspect_dy :  %d", flxh->aspect_dy);
                GST_LOG ("(FLC) oframe1   :  0x%08x", flxh->oframe1);
                GST_LOG ("(FLC) oframe2   :  0x%08x", flxh->oframe2);
            }

            flxdec->size = (flxh->width * flxh->height);

            /* create delta and output frame */
            flxdec->frame = gst_buffer_new ();
            flxdec->delta = gst_buffer_new ();
            GST_BUFFER_DATA (flxdec->frame) = g_malloc (flxdec->size);
            GST_BUFFER_MALLOCDATA (flxdec->frame) = GST_BUFFER_DATA (flxdec->frame);
            GST_BUFFER_SIZE (flxdec->frame) = flxdec->size;
            GST_BUFFER_DATA (flxdec->delta) = g_malloc (flxdec->size);
            GST_BUFFER_MALLOCDATA (flxdec->delta) = GST_BUFFER_DATA (flxdec->delta);
            GST_BUFFER_SIZE (flxdec->delta) = flxdec->size;

            flxdec->state = GST_FLXDEC_PLAYING;
        }
    } else if (flxdec->state == GST_FLXDEC_PLAYING) {
        GstBuffer *out;

        /* while we have enough data in the adapter */
        while (avail >= FlxFrameChunkSize) {
            FlxFrameChunk flxfh;
            guchar *chunk;
            const guint8 *data;

            chunk = NULL;
            data = gst_adapter_peek (flxdec->adapter, FlxFrameChunkSize);
            memcpy (&flxfh, data, FlxFrameChunkSize);
            FLX_FRAME_CHUNK_FIX_ENDIANNESS (&flxfh);

            switch (flxfh.id) {
            case FLX_FRAME_TYPE:
                /* check if we have the complete frame */
                if (avail < flxfh.size)
                    goto need_more_data;

                /* flush header */
                gst_adapter_flush (flxdec->adapter, FlxFrameChunkSize);

                chunk = gst_adapter_take (flxdec->adapter,
                                          flxfh.size - FlxFrameChunkSize);
                FLX_FRAME_TYPE_FIX_ENDIANNESS ((FlxFrameType *) chunk);
                if (((FlxFrameType *) chunk)->chunks == 0)
                    break;

                /* create 32 bits output frame */
                res = gst_pad_alloc_buffer_and_set_caps (flxdec->srcpad,
                        GST_BUFFER_OFFSET_NONE,
                        flxdec->size * 4, GST_PAD_CAPS (flxdec->srcpad), &out);
                if (res != GST_FLOW_OK)
                    break;

                /* decode chunks */
                flx_decode_chunks (flxdec,
                                   ((FlxFrameType *) chunk)->chunks,
                                   chunk + FlxFrameTypeSize, GST_BUFFER_DATA (flxdec->frame));

                /* save copy of the current frame for possible delta. */
                memcpy (GST_BUFFER_DATA (flxdec->delta),
                        GST_BUFFER_DATA (flxdec->frame), GST_BUFFER_SIZE (flxdec->delta));

                /* convert current frame. */
                flx_colorspace_convert (flxdec->converter,
                                        GST_BUFFER_DATA (flxdec->frame), GST_BUFFER_DATA (out));

                GST_BUFFER_TIMESTAMP (out) = flxdec->next_time;
                flxdec->next_time += flxdec->frame_time;

                gst_pad_push (flxdec->srcpad, out);
                break;
            }

            if (chunk)
                g_free (chunk);

            avail = gst_adapter_available (flxdec->adapter);
        }
    }
need_more_data:
    gst_object_unref (flxdec);
    return res;

    /* ERRORS */
wrong_type:
    {
        GST_ELEMENT_ERROR (flxdec, STREAM, WRONG_TYPE, (NULL),
                           ("not a flx file (type %x)", flxh->type));
        gst_object_unref (flxdec);
        return GST_FLOW_ERROR;
    }
}