GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (object);
switch (prop_id) {
- case PROP_OUTPUT_IO_MODE:
- gst_v4l2_object_set_property_helper (self->v4l2output,
- prop_id, value, pspec);
- break;
case PROP_CAPTURE_IO_MODE:
- gst_v4l2_object_set_property_helper (self->v4l2capture,
- prop_id, value, pspec);
+ if (!gst_v4l2_object_set_property_helper (self->v4l2capture,
+ prop_id, value, pspec)) {
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
break;
/* By default, only set on output */
GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (object);
switch (prop_id) {
- case PROP_OUTPUT_IO_MODE:
- gst_v4l2_object_get_property_helper (self->v4l2output,
- prop_id, value, pspec);
- break;
case PROP_CAPTURE_IO_MODE:
- gst_v4l2_object_get_property_helper (self->v4l2output,
- PROP_IO_MODE, value, pspec);
+ if (!gst_v4l2_object_get_property_helper (self->v4l2capture,
+ prop_id, value, pspec)) {
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
break;
/* By default read from output */
GstTask *task = encoder->srcpad->task;
/* Wait for the task to be drained */
+ GST_DEBUG_OBJECT (self, "Waiting for encoder stop");
GST_OBJECT_LOCK (task);
while (GST_TASK_STATE (task) == GST_TASK_STARTED)
GST_TASK_WAIT (task);
if (gst_v4l2_video_enc_finish (encoder) != GST_FLOW_OK)
return FALSE;
+ gst_v4l2_object_stop (self->v4l2output);
+ gst_v4l2_object_stop (self->v4l2capture);
+
gst_video_codec_state_unref (self->input_state);
self->input_state = NULL;
}
GST_DEBUG_OBJECT (self, "Negotiating %s profile and level.",
klass->codec_name);
+ /* Only renegotiate on upstream changes */
+ if (self->input_state)
+ return TRUE;
+
allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
if (allowed_caps) {
if (!GST_VIDEO_ENCODER_CLASS (parent_class)->negotiate (encoder))
return FALSE;
- if (!gst_buffer_pool_set_active (GST_BUFFER_POOL (self->v4l2capture->pool),
- TRUE)) {
- GST_WARNING_OBJECT (self, "Could not activate capture buffer pool.");
- return FALSE;
- }
-
return TRUE;
g_ctrl_failed:
frame = gst_v4l2_video_enc_get_oldest_frame (encoder);
if (frame) {
+ /* At this point, the delta unit buffer flag is already correctly set by
+ * gst_v4l2_buffer_pool_process. Since gst_video_encoder_finish_frame
+ * will overwrite it from GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame),
+ * set that here.
+ */
+ if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT))
+ GST_VIDEO_CODEC_FRAME_UNSET_SYNC_POINT (frame);
+ else
+ GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
frame->output_buffer = buffer;
buffer = NULL;
ret = gst_video_encoder_finish_frame (encoder, frame);
{
GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
GstFlowReturn ret = GST_FLOW_OK;
+ GstTaskState task_state;
GST_DEBUG_OBJECT (self, "Handling frame %d", frame->system_frame_number);
if (G_UNLIKELY (!g_atomic_int_get (&self->active)))
goto flushing;
- if (gst_pad_get_task_state (GST_VIDEO_DECODER_SRC_PAD (self)) ==
- GST_TASK_STOPPED) {
+ task_state = gst_pad_get_task_state (GST_VIDEO_ENCODER_SRC_PAD (self));
+ if (task_state == GST_TASK_STOPPED || task_state == GST_TASK_PAUSED) {
GstBufferPool *pool = GST_BUFFER_POOL (self->v4l2output->pool);
/* It possible that the processing thread stopped due to an error */
goto activate_failed;
}
+ if (!gst_buffer_pool_set_active
+ (GST_BUFFER_POOL (self->v4l2capture->pool), TRUE)) {
+ GST_WARNING_OBJECT (self, "Could not activate capture buffer pool.");
+ goto activate_failed;
+ }
+
GST_DEBUG_OBJECT (self, "Starting encoding thread");
/* Start the processing task, when it quits, the task will disable input
{
GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
GstVideoCodecState *state = gst_video_encoder_get_output_state (encoder);
+ GstCaps *caps;
GstV4l2Error error = GST_V4L2_ERROR_INIT;
GstClockTime latency;
gboolean ret = FALSE;
* GstVideoEncoder have set the width, height and framerate into the state
* caps. These are needed by the driver to calculate the buffer size and to
* implement bitrate adaptation. */
- if (!gst_v4l2_object_set_format (self->v4l2capture, state->caps, &error)) {
+ caps = gst_caps_copy (state->caps);
+ gst_structure_remove_field (gst_caps_get_structure (caps, 0), "colorimetry");
+ if (!gst_v4l2_object_set_format (self->v4l2capture, caps, &error)) {
gst_v4l2_error (self, &error);
+ gst_caps_unref (caps);
ret = FALSE;
goto done;
}
+ gst_caps_unref (caps);
if (gst_v4l2_object_decide_allocation (self->v4l2capture, query)) {
GstVideoEncoderClass *enc_class = GST_VIDEO_ENCODER_CLASS (parent_class);
{
GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
gboolean ret;
+ GstEventType type = GST_EVENT_TYPE (event);
- switch (GST_EVENT_TYPE (event)) {
+ switch (type) {
case GST_EVENT_FLUSH_START:
GST_DEBUG_OBJECT (self, "flush start");
gst_v4l2_object_unlock (self->v4l2output);
ret = GST_VIDEO_ENCODER_CLASS (parent_class)->sink_event (encoder, event);
- switch (GST_EVENT_TYPE (event)) {
+ switch (type) {
case GST_EVENT_FLUSH_START:
gst_pad_stop_task (encoder->srcpad);
GST_DEBUG_OBJECT (self, "flush start done");
GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (instance);
self->v4l2output = gst_v4l2_object_new (GST_ELEMENT (self),
+ GST_OBJECT (GST_VIDEO_ENCODER_SINK_PAD (self)),
V4L2_BUF_TYPE_VIDEO_OUTPUT, klass->default_device,
gst_v4l2_get_output, gst_v4l2_set_output, NULL);
self->v4l2output->no_initial_format = TRUE;
self->v4l2output->keep_aspect = FALSE;
self->v4l2capture = gst_v4l2_object_new (GST_ELEMENT (self),
+ GST_OBJECT (GST_VIDEO_ENCODER_SRC_PAD (self)),
V4L2_BUF_TYPE_VIDEO_CAPTURE, klass->default_device,
gst_v4l2_get_input, gst_v4l2_set_input, NULL);
- self->v4l2capture->no_initial_format = TRUE;
- self->v4l2output->keep_aspect = FALSE;
}
static void
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
cdata->src_caps));
+ gst_caps_unref (cdata->sink_caps);
+ gst_caps_unref (cdata->src_caps);
g_free (cdata);
}
}
if (gst_caps_is_subset (sink_caps, gst_v4l2_object_get_raw_caps ())
- && check_caps (src_caps, gst_v4l2_object_get_codec_caps ()))
+ && check_caps (src_caps, codec_caps))
ret = TRUE;
return ret;