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); }
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; }
/* * 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; }
/* 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); }
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); } }
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); }