Ejemplo n.º 1
0
static void
test_set_and_fail_to_play_buffer (const gchar * _data)
{
  gpointer data = (gpointer) _data;
  GstBuffer *buffer;
  gint num_bytes;

  num_bytes = strlen (data);
  buffer = gst_buffer_new ();
  gst_buffer_insert_memory (buffer, 0,
      gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
          data, num_bytes, 0, num_bytes, data, NULL));

  fail_unless (gst_pad_push (srcpad, buffer) == GST_FLOW_ERROR);
}
Ejemplo n.º 2
0
static GstBuffer *
create_read_only_buffer (void)
{
  GstBuffer *buf;

  buf = gst_buffer_new ();

  /* assign some read-only data to the new buffer */
  gst_buffer_insert_memory (buf, -1,
      gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
          (gpointer) ro_memory, sizeof (ro_memory),
          0, sizeof (ro_memory), NULL, NULL));

  return buf;
}
Ejemplo n.º 3
0
/*
 * couple gstreamer tightly by lock-stepping
 */
static int pipeline_push(struct videnc_state *st, const struct vidframe *frame)
{
	GstBuffer *buffer;
	uint8_t *data;
	size_t size;
	GstFlowReturn ret;
	int err = 0;

#if 1
	/* XXX: should not block the function here */

	/*
	 * Wait "start feed".
	 */
	pthread_mutex_lock(&st->streamer.wait.mutex);
	if (st->streamer.wait.flag == 1) {
		pthread_cond_wait(&st->streamer.wait.cond,
				  &st->streamer.wait.mutex);
	}
	if (st->streamer.eos.flag == -1)
		/* error */
		err = ENODEV;
	pthread_mutex_unlock(&st->streamer.wait.mutex);
	if (err)
		return err;
#endif

	/*
	 * Copy frame into buffer for gstreamer
	 */

	/* NOTE: I420 (YUV420P): hardcoded. */
	size = frame->linesize[0] * frame->size.h
		+ frame->linesize[1] * frame->size.h * 0.5
		+ frame->linesize[2] * frame->size.h * 0.5;

	/* allocate memory; memory is freed within callback of
	   gst_memory_new_wrapped of gst_video_push */
	data = g_try_malloc(size);
	if (!data)
		return ENOMEM;

	/* copy content of frame */
	size = 0;
	memcpy(&data[size], frame->data[0],
	       frame->linesize[0] * frame->size.h);
	size += frame->linesize[0] * frame->size.h;
	memcpy(&data[size], frame->data[1],
	       frame->linesize[1] * frame->size.h * 0.5);
	size += frame->linesize[1] * frame->size.h * 0.5;
	memcpy(&data[size], frame->data[2],
	       frame->linesize[2] * frame->size.h * 0.5);
	size += frame->linesize[2] * frame->size.h * 0.5;

	/* Wrap memory in a gstreamer buffer */
	buffer = gst_buffer_new();
	gst_buffer_insert_memory(buffer, -1,
				 gst_memory_new_wrapped (0, data, size, 0,
							 size, data, g_free));

	/*
	 * Push data and EOS into gstreamer.
	 */

	ret = gst_app_src_push_buffer(st->streamer.source, buffer);
	if (ret != GST_FLOW_OK) {
		warning("gst_video: pushing buffer failed\n");
		err = EPROTO;
		goto out;
	}

#if 0
	ret = gst_app_src_end_of_stream(st->streamer.source);
	if (ret != GST_FLOW_OK) {
		warning("gst_video: pushing EOS failed\n");
		err = EPROTO;
		goto out;
	}
#endif


#if 0
	/*
	 * Wait "processing done".
	 */
	pthread_mutex_lock(&st->streamer.eos.mutex);
	if (st->streamer.eos.flag == 0)
		/* will returns with EOS (1) or error (-1) */
		pthread_cond_wait(&st->streamer.wait.cond,
				  &st->streamer.wait.mutex);
	if (st->streamer.eos.flag == 1)
		/* reset eos */
		st->streamer.eos.flag = 0;
	else
		/* error */
		err = -1;
	pthread_mutex_unlock(&st->streamer.wait.mutex);
#endif


 out:
	return err;
}
Ejemplo n.º 4
0
/* Retrieve a frame and feed it into the pipeline
 */
static void
recorder_record_frame (ShellRecorder *recorder,
                       gboolean       paint)
{
  GstBuffer *buffer;
  ClutterCapture *captures;
  int n_captures;
  cairo_surface_t *image;
  guint size;
  uint8_t *data;
  GstMemory *memory;
  int i;
  GstClock *clock;
  GstClockTime now, base_time;

  g_return_if_fail (recorder->current_pipeline != NULL);

  /* If we get into the red zone, stop buffering new frames; 13/16 is
  * a bit more than the 3/4 threshold for a red indicator to keep the
  * indicator from flashing between red and yellow. */
  if (recorder->memory_used > (recorder->memory_target * 13) / 16)
    return;

  /* Drop frames to get down to something like the target frame rate; since frames
   * are generated with VBlank sync, we don't have full control anyways, so we just
   * drop frames if the interval since the last frame is less than 75% of the
   * desired inter-frame interval.
   */
  clock = gst_element_get_clock (recorder->current_pipeline->src);

  /* If we have no clock yet, the pipeline is not yet in PLAYING */
  if (!clock)
    return;

  base_time = gst_element_get_base_time (recorder->current_pipeline->src);
  now = gst_clock_get_time (clock) - base_time;
  gst_object_unref (clock);

  if (GST_CLOCK_TIME_IS_VALID (recorder->last_frame_time) &&
      now - recorder->last_frame_time < gst_util_uint64_scale_int (GST_SECOND, 3, 4 * recorder->framerate))
    return;
  recorder->last_frame_time = now;

  clutter_stage_capture (recorder->stage, paint, &recorder->area,
                         &captures, &n_captures);

  if (n_captures == 0)
    return;

  if (n_captures == 1)
    image = cairo_surface_reference (captures[0].image);
  else
    image = shell_util_composite_capture_images (captures,
                                                 n_captures,
                                                 recorder->area.x,
                                                 recorder->area.y,
                                                 recorder->area.width,
                                                 recorder->area.height);

  data = cairo_image_surface_get_data (image);
  size = (cairo_image_surface_get_height (image) *
          cairo_image_surface_get_stride (image));

  for (i = 0; i < n_captures; i++)
    cairo_surface_destroy (captures[i].image);
  g_free (captures);

  buffer = gst_buffer_new();
  memory = gst_memory_new_wrapped (0, data, size, 0, size,
                                   image,
                                   (GDestroyNotify) cairo_surface_destroy);
  gst_buffer_insert_memory (buffer, -1, memory);

  GST_BUFFER_PTS(buffer) = now;

  if (recorder->draw_cursor &&
      !g_settings_get_boolean (recorder->a11y_settings, MAGNIFIER_ACTIVE_KEY))
    recorder_draw_cursor (recorder, buffer);

  shell_recorder_src_add_buffer (SHELL_RECORDER_SRC (recorder->current_pipeline->src), buffer);
  gst_buffer_unref (buffer);

  /* Reset the timeout that we used to avoid an overlong pause in the stream */
  recorder_remove_redraw_timeout (recorder);
  recorder_add_redraw_timeout (recorder);
}
Ejemplo n.º 5
0
static void
gst_droidcamsrc_dev_frame_available (void *user)
{
  GstDroidCamSrcDev *dev = (GstDroidCamSrcDev *) user;
  GstDroidCamSrc *src = GST_DROIDCAMSRC (GST_PAD_PARENT (dev->imgsrc->pad));
  GstDroidCamSrcPad *pad = dev->vfsrc;
  DroidMediaBuffer *buffer;
  GstMemory *mem;
  DroidMediaRect rect;
  guint width, height;
  GstBuffer *buff;
  DroidMediaBufferCallbacks cb;
  GstFlowReturn flow_ret;
  DroidMediaBufferInfo info;

  GST_DEBUG_OBJECT (src, "frame available");

  if (!pad->running) {
    GST_DEBUG_OBJECT (src, "vfsrc pad task is not running");

    goto acquire_and_release;
  }

  /* We are accessing this without a lock because:
   * 1) We should not be called while preview is stopped and this is when we manipulate this flag
   * 2) We can get called when we start the preview and we will deadlock because the lock is already held
   */
  if (dev->use_raw_data) {
    goto acquire_and_release;
  }

  flow_ret = gst_buffer_pool_acquire_buffer (dev->pool, &buff, NULL);
  if (flow_ret != GST_FLOW_OK) {
    GST_WARNING_OBJECT (src, "failed to acquire buffer from pool: %s",
        gst_flow_get_name (flow_ret));

    goto acquire_and_release;
  }

  cb.ref = (DroidMediaCallback) gst_buffer_ref;
  cb.unref = (DroidMediaCallback) gst_buffer_unref;
  cb.data = buff;

  mem =
      gst_droid_media_buffer_allocator_alloc (dev->media_allocator, dev->queue,
      &cb);
  if (!mem) {
    GST_ERROR_OBJECT (src, "failed to acquire buffer from droidmedia");
    gst_buffer_unref (buff);
    return;
  }

  buffer = gst_droid_media_buffer_memory_get_buffer (mem);

  gst_buffer_insert_memory (buff, 0, mem);
  gst_droidcamsrc_timestamp (src, buff);

  rect = droid_media_buffer_get_crop_rect (buffer);
  width = droid_media_buffer_get_width (buffer);
  height = droid_media_buffer_get_height (buffer);

  gst_droidcamsrc_dev_prepare_buffer (dev, buff, rect, width, height,
      GST_VIDEO_FORMAT_YV12);

  g_mutex_lock (&pad->lock);
  g_queue_push_tail (pad->queue, buff);
  g_cond_signal (&pad->cond);
  g_mutex_unlock (&pad->lock);

  GST_OBJECT_LOCK (src);
  src->crop_rect = rect;
  GST_OBJECT_UNLOCK (src);
  return;

acquire_and_release:
  if (droid_media_buffer_queue_acquire_and_release (dev->queue, &info)) {
    GST_OBJECT_LOCK (src);
    src->crop_rect = info.crop_rect;
    GST_OBJECT_UNLOCK (src);
  }
}
Ejemplo n.º 6
0
static void
gst_droidcamsrc_dev_video_frame_callback (void *user,
    DroidMediaCameraRecordingData * video_data)
{
  GstDroidCamSrcDev *dev = (GstDroidCamSrcDev *) user;
  GstDroidCamSrc *src = GST_DROIDCAMSRC (GST_PAD_PARENT (dev->imgsrc->pad));
  void *data = droid_media_camera_recording_frame_get_data (video_data);
  GstBuffer *buffer;
  GstMemory *mem;
  GstDroidCamSrcDevVideoData *mem_data;
  gboolean drop_buffer;

  GST_DEBUG_OBJECT (src, "dev video frame callback");

  g_mutex_lock (&dev->vid->lock);

  /* TODO: not sure what to do with timestamp */

  /* unlikely but just in case */
  if (G_UNLIKELY (!data)) {
    GST_ERROR ("invalid memory from camera HAL");
    droid_media_camera_release_recording_frame (dev->cam, video_data);
    goto unlock_and_out;
  }

  /* TODO: this is bad */
  mem_data = g_slice_new0 (GstDroidCamSrcDevVideoData);
  mem_data->dev = dev;
  mem_data->data = video_data;

  buffer = gst_buffer_new ();
  mem = gst_wrapped_memory_allocator_wrap (dev->wrap_allocator,
      data, droid_media_camera_recording_frame_get_size (video_data),
      (GFunc) gst_droidcamsrc_dev_release_recording_frame, mem_data);
  gst_buffer_insert_memory (buffer, 0, mem);

  GST_BUFFER_OFFSET (buffer) = dev->vid->video_frames;
  GST_BUFFER_OFFSET_END (buffer) = ++dev->vid->video_frames;
  gst_droidcamsrc_timestamp (src, buffer);

  g_rec_mutex_lock (dev->lock);
  ++dev->vid->queued_frames;
  g_rec_mutex_unlock (dev->lock);

  drop_buffer = !dev->vid->running;

  if (drop_buffer) {
    GST_INFO_OBJECT (src,
        "dropping buffer because video recording is not running");
    gst_buffer_unref (buffer);
  } else {
    g_mutex_lock (&dev->vidsrc->lock);
    g_queue_push_tail (dev->vidsrc->queue, buffer);
    g_cond_signal (&dev->vidsrc->cond);
    g_mutex_unlock (&dev->vidsrc->lock);
  }

unlock_and_out:
  /* in case stop_video_recording() is waiting for us */
  g_cond_signal (&dev->vid->cond);
  g_mutex_unlock (&dev->vid->lock);
}