diff --git a/sys/rpicamsrc/RaspiCapture.c b/sys/rpicamsrc/RaspiCapture.c index 797147fabb..3688ae4152 100644 --- a/sys/rpicamsrc/RaspiCapture.c +++ b/sys/rpicamsrc/RaspiCapture.c @@ -752,6 +752,21 @@ static void destroy_camera_component(RASPIVID_STATE *state) } } +gboolean raspi_capture_request_i_frame(RASPIVID_STATE *state) +{ + MMAL_PORT_T *encoder_output = NULL; + MMAL_STATUS_T status; + MMAL_PARAMETER_BOOLEAN_T param = {{ MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME, sizeof(param)}, 1}; + encoder_output = state->encoder_component->output[0]; + status = mmal_port_parameter_set(encoder_output, ¶m.hdr); + if (status != MMAL_SUCCESS) + { + vcos_log_error("Unable to request I-frame"); + return FALSE; + } + return TRUE; +} + /** * Create the encoder component, set up its ports * diff --git a/sys/rpicamsrc/RaspiCapture.h b/sys/rpicamsrc/RaspiCapture.h index 3c6dcf5b1f..37a7ba7bef 100644 --- a/sys/rpicamsrc/RaspiCapture.h +++ b/sys/rpicamsrc/RaspiCapture.h @@ -92,6 +92,7 @@ gboolean raspi_capture_start(RASPIVID_STATE *state); GstFlowReturn raspi_capture_fill_buffer(RASPIVID_STATE *state, GstBuffer **buf); void raspi_capture_stop(RASPIVID_STATE *state); void raspi_capture_free(RASPIVID_STATE *state); +gboolean raspi_capture_request_i_frame(RASPIVID_STATE *state); G_END_DECLS diff --git a/sys/rpicamsrc/gstrpicamsrc.c b/sys/rpicamsrc/gstrpicamsrc.c index 2900bb2550..5d2d0c3ea7 100644 --- a/sys/rpicamsrc/gstrpicamsrc.c +++ b/sys/rpicamsrc/gstrpicamsrc.c @@ -181,6 +181,8 @@ static GstFlowReturn gst_rpi_cam_src_create (GstPushSrc * parent, static GstCaps *gst_rpi_cam_src_get_caps (GstBaseSrc * src, GstCaps * filter); static gboolean gst_rpi_cam_src_set_caps (GstBaseSrc * src, GstCaps * caps); static GstCaps *gst_rpi_cam_src_fixate (GstBaseSrc * basesrc, GstCaps * caps); +static gboolean gst_rpi_cam_src_event (GstBaseSrc * src, GstEvent * event); +static gboolean gst_rpi_cam_src_send_event (GstElement * element, GstEvent * event); static void gst_rpi_cam_src_class_init (GstRpiCamSrcClass * klass) @@ -312,6 +314,8 @@ gst_rpi_cam_src_class_init (GstRpiCamSrcClass * klass) basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_get_caps); basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_set_caps); basesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_fixate); + basesrc_class->event = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_event); + gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_send_event); pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_create); raspicapture_init (); @@ -532,6 +536,58 @@ gst_rpi_cam_src_stop (GstBaseSrc * parent) return TRUE; } +static gboolean +gst_rpi_cam_src_send_event (GstElement * parent, GstEvent * event) +{ + GstRpiCamSrc *src = GST_RPICAMSRC (parent); + gboolean ret; + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CUSTOM_DOWNSTREAM: + case GST_EVENT_CUSTOM_UPSTREAM: + if (gst_video_event_is_force_key_unit (event)) { + if (src->started) { + ret = raspi_capture_request_i_frame (src->capture_state); + } else { + ret = FALSE; + } + gst_event_unref (event); + } else { + ret = GST_ELEMENT_CLASS (parent_class)->send_event(parent, event); + } + break; + default: + ret = GST_ELEMENT_CLASS (parent_class)->send_event(parent, event); + break; + } + return ret; +} + +static gboolean +gst_rpi_cam_src_event (GstBaseSrc * parent, GstEvent * event) +{ + GstRpiCamSrc *src = GST_RPICAMSRC (parent); + gboolean ret; + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CUSTOM_DOWNSTREAM: + case GST_EVENT_CUSTOM_UPSTREAM: + if (gst_video_event_is_force_key_unit (event)) { + if (src->started) { + ret = raspi_capture_request_i_frame (src->capture_state); + } else { + ret = FALSE; + } + gst_event_unref (event); + } else { + ret = GST_BASE_SRC_CLASS (parent_class)->event(parent, event); + } + break; + default: + ret = GST_BASE_SRC_CLASS (parent_class)->event(parent, event); + break; + } + return ret; +} + static GstCaps * gst_rpi_cam_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter) {