static GstStateChangeReturn gst_rtp_mp4g_pay_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret; GstRtpMP4GPay *rtpmp4gpay; rtpmp4gpay = GST_RTP_MP4G_PAY (element); switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: gst_rtp_mp4g_pay_cleanup (rtpmp4gpay); break; default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: gst_rtp_mp4g_pay_cleanup (rtpmp4gpay); break; default: break; } return ret; }
static gboolean gst_rtp_mp4g_pay_sink_event (GstRTPBasePayload * payload, GstEvent * event) { GstRtpMP4GPay *rtpmp4gpay; rtpmp4gpay = GST_RTP_MP4G_PAY (payload); GST_DEBUG ("Got event: %s", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEGMENT: case GST_EVENT_EOS: /* This flush call makes sure that the last buffer is always pushed * to the base payloader */ gst_rtp_mp4g_pay_flush (rtpmp4gpay); break; case GST_EVENT_FLUSH_STOP: gst_rtp_mp4g_pay_reset (rtpmp4gpay); break; default: break; } /* let parent handle event too */ return GST_RTP_BASE_PAYLOAD_CLASS (parent_class)->sink_event (payload, event); }
static gboolean gst_rtp_mp4g_pay_handle_event (GstPad * pad, GstEvent * event) { GstRtpMP4GPay *rtpmp4gpay; rtpmp4gpay = GST_RTP_MP4G_PAY (gst_pad_get_parent (pad)); GST_DEBUG ("Got event: %s", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_NEWSEGMENT: case GST_EVENT_EOS: /* This flush call makes sure that the last buffer is always pushed * to the base payloader */ gst_rtp_mp4g_pay_flush (rtpmp4gpay); break; case GST_EVENT_FLUSH_STOP: gst_rtp_mp4g_pay_reset (rtpmp4gpay); break; default: break; } g_object_unref (rtpmp4gpay); /* let parent handle event too */ return FALSE; }
static void gst_rtp_mp4g_pay_finalize (GObject * object) { GstRtpMP4GPay *rtpmp4gpay; rtpmp4gpay = GST_RTP_MP4G_PAY (object); gst_rtp_mp4g_pay_cleanup (rtpmp4gpay); g_object_unref (rtpmp4gpay->adapter); rtpmp4gpay->adapter = NULL; G_OBJECT_CLASS (parent_class)->finalize (object); }
/* we expect buffers as exactly one complete AU */ static GstFlowReturn gst_rtp_mp4g_pay_handle_buffer (GstRTPBasePayload * basepayload, GstBuffer * buffer) { GstRtpMP4GPay *rtpmp4gpay; rtpmp4gpay = GST_RTP_MP4G_PAY (basepayload); rtpmp4gpay->first_timestamp = GST_BUFFER_TIMESTAMP (buffer); rtpmp4gpay->first_duration = GST_BUFFER_DURATION (buffer); /* we always encode and flush a full AU */ gst_adapter_push (rtpmp4gpay->adapter, buffer); return gst_rtp_mp4g_pay_flush (rtpmp4gpay); }
static gboolean gst_rtp_mp4g_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps) { GstRtpMP4GPay *rtpmp4gpay; GstStructure *structure; const GValue *codec_data; const gchar *media_type = NULL; gboolean res; rtpmp4gpay = GST_RTP_MP4G_PAY (payload); structure = gst_caps_get_structure (caps, 0); codec_data = gst_structure_get_value (structure, "codec_data"); if (codec_data) { GST_LOG_OBJECT (rtpmp4gpay, "got codec_data"); if (G_VALUE_TYPE (codec_data) == GST_TYPE_BUFFER) { GstBuffer *buffer; const gchar *name; buffer = gst_value_get_buffer (codec_data); GST_LOG_OBJECT (rtpmp4gpay, "configuring codec_data"); name = gst_structure_get_name (structure); /* parse buffer */ if (!strcmp (name, "audio/mpeg")) { res = gst_rtp_mp4g_pay_parse_audio_config (rtpmp4gpay, buffer); media_type = "audio"; } else if (!strcmp (name, "video/mpeg")) { res = gst_rtp_mp4g_pay_parse_video_config (rtpmp4gpay, buffer); media_type = "video"; } else { res = FALSE; } if (!res) goto config_failed; /* now we can configure the buffer */ if (rtpmp4gpay->config) gst_buffer_unref (rtpmp4gpay->config); rtpmp4gpay->config = gst_buffer_copy (buffer); } } if (media_type == NULL) goto config_failed; gst_rtp_base_payload_set_options (payload, media_type, TRUE, "MPEG4-GENERIC", rtpmp4gpay->rate); res = gst_rtp_mp4g_pay_new_caps (rtpmp4gpay); return res; /* ERRORS */ config_failed: { GST_DEBUG_OBJECT (rtpmp4gpay, "failed to parse config"); return FALSE; } }