159 gobject_class->get_property = gst_basertppayload_get_property; |
161 gobject_class->get_property = gst_basertppayload_get_property; |
160 |
162 |
161 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU, |
163 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU, |
162 g_param_spec_uint ("mtu", "MTU", |
164 g_param_spec_uint ("mtu", "MTU", |
163 "Maximum size of one packet", |
165 "Maximum size of one packet", |
164 28, G_MAXUINT, DEFAULT_MTU, |
166 28, G_MAXUINT, DEFAULT_MTU, G_PARAM_READWRITE)); |
165 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
166 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PT, |
167 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PT, |
167 g_param_spec_uint ("pt", "payload type", |
168 g_param_spec_uint ("pt", "payload type", |
168 "The payload type of the packets", 0, 0x80, DEFAULT_PT, |
169 "The payload type of the packets", |
169 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
170 0, 0x80, DEFAULT_PT, G_PARAM_READWRITE)); |
170 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SSRC, |
171 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SSRC, |
171 g_param_spec_uint ("ssrc", "SSRC", |
172 g_param_spec_uint ("ssrc", "SSRC", |
172 "The SSRC of the packets (default == random)", 0, G_MAXUINT32, |
173 "The SSRC of the packets (default == random)", |
173 DEFAULT_SSRC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
174 0, G_MAXUINT32, DEFAULT_SSRC, G_PARAM_READWRITE)); |
174 g_object_class_install_property (G_OBJECT_CLASS (klass), |
175 g_object_class_install_property (G_OBJECT_CLASS (klass), |
175 PROP_TIMESTAMP_OFFSET, g_param_spec_uint ("timestamp-offset", |
176 PROP_TIMESTAMP_OFFSET, g_param_spec_uint ("timestamp-offset", |
176 "Timestamp Offset", |
177 "Timestamp Offset", |
177 "Offset to add to all outgoing timestamps (default = random)", 0, |
178 "Offset to add to all outgoing timestamps (default = random)", 0, |
178 G_MAXUINT32, DEFAULT_TIMESTAMP_OFFSET, |
179 G_MAXUINT32, DEFAULT_TIMESTAMP_OFFSET, G_PARAM_READWRITE)); |
179 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
180 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM_OFFSET, |
180 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM_OFFSET, |
181 g_param_spec_int ("seqnum-offset", "Sequence number Offset", |
181 g_param_spec_int ("seqnum-offset", "Sequence number Offset", |
182 "Offset to add to all outgoing seqnum (-1 = random)", -1, G_MAXUINT16, |
182 "Offset to add to all outgoing seqnum (-1 = random)", -1, G_MAXUINT16, |
183 DEFAULT_SEQNUM_OFFSET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
183 DEFAULT_SEQNUM_OFFSET, G_PARAM_READWRITE)); |
184 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MAX_PTIME, |
184 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MAX_PTIME, |
185 g_param_spec_int64 ("max-ptime", "Max packet time", |
185 g_param_spec_int64 ("max-ptime", "Max packet time", |
186 "Maximum duration of the packet data in ns (-1 = unlimited up to MTU)", |
186 "Maximum duration of the packet data in ns (-1 = unlimited up to MTU)", |
187 -1, G_MAXINT64, DEFAULT_MAX_PTIME, |
187 -1, G_MAXINT64, DEFAULT_MAX_PTIME, G_PARAM_READWRITE)); |
188 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
189 /** |
188 /** |
190 * GstBaseRTPAudioPayload:min-ptime: |
189 * GstBaseRTPAudioPayload:min-ptime: |
191 * |
190 * |
192 * Minimum duration of the packet data in ns (can't go above MTU) |
191 * Minimum duration of the packet data in ns (can't go above MTU) |
193 * |
192 * |
194 * Since: 0.10.13 |
193 * Since: 0.10.13 |
195 **/ |
194 **/ |
196 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MIN_PTIME, |
195 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MIN_PTIME, |
197 g_param_spec_int64 ("min-ptime", "Min packet time", |
196 g_param_spec_int64 ("min-ptime", "Min packet time", |
198 "Minimum duration of the packet data in ns (can't go above MTU)", |
197 "Minimum duration of the packet data in ns (can't go above MTU)", |
199 0, G_MAXINT64, DEFAULT_MIN_PTIME, |
198 0, G_MAXINT64, DEFAULT_MIN_PTIME, G_PARAM_READWRITE)); |
200 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
201 |
199 |
202 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMESTAMP, |
200 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMESTAMP, |
203 g_param_spec_uint ("timestamp", "Timestamp", |
201 g_param_spec_uint ("timestamp", "Timestamp", |
204 "The RTP timestamp of the last processed packet", |
202 "The RTP timestamp of the last processed packet", |
205 0, G_MAXUINT32, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); |
203 0, G_MAXUINT32, 0, G_PARAM_READABLE)); |
206 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM, |
204 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM, |
207 g_param_spec_uint ("seqnum", "Sequence number", |
205 g_param_spec_uint ("seqnum", "Sequence number", |
208 "The RTP sequence number of the last processed packet", |
206 "The RTP sequence number of the last processed packet", |
209 0, G_MAXUINT16, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); |
207 0, G_MAXUINT16, 0, G_PARAM_READABLE)); |
210 |
208 |
211 gstelement_class->change_state = gst_basertppayload_change_state; |
209 gstelement_class->change_state = gst_basertppayload_change_state; |
212 |
210 |
213 GST_DEBUG_CATEGORY_INIT (basertppayload_debug, "basertppayload", 0, |
211 GST_DEBUG_CATEGORY_INIT (basertppayload_debug, "basertppayload", 0, |
214 "Base class for RTP Payloaders"); |
212 "Base class for RTP Payloaders"); |
627 return TRUE; |
624 return TRUE; |
628 |
625 |
629 return FALSE; |
626 return FALSE; |
630 } |
627 } |
631 |
628 |
632 typedef struct |
629 /** |
633 { |
630 * gst_basertppayload_push: |
634 GstBaseRTPPayload *payload; |
631 * @payload: a #GstBaseRTPPayload |
635 guint32 ssrc; |
632 * @buffer: a #GstBuffer |
636 guint16 seqnum; |
633 * |
637 guint8 pt; |
634 * Push @buffer to the peer element of the payloader. The SSRC, payload type, |
638 GstCaps *caps; |
635 * seqnum and timestamp of the RTP buffer will be updated first. |
|
636 * |
|
637 * This function takes ownership of @buffer. |
|
638 * |
|
639 * Returns: a #GstFlowReturn. |
|
640 */ |
|
641 #ifdef __SYMBIAN32__ |
|
642 EXPORT_C |
|
643 #endif |
|
644 |
|
645 GstFlowReturn |
|
646 gst_basertppayload_push (GstBaseRTPPayload * payload, GstBuffer * buffer) |
|
647 { |
|
648 GstFlowReturn res; |
639 GstClockTime timestamp; |
649 GstClockTime timestamp; |
640 guint32 rtptime; |
650 guint32 rtptime; |
641 } HeaderData; |
|
642 |
|
643 static GstBufferListItem |
|
644 find_timestamp (GstBuffer ** buffer, guint group, guint idx, HeaderData * data) |
|
645 { |
|
646 data->timestamp = GST_BUFFER_TIMESTAMP (*buffer); |
|
647 |
|
648 /* stop when we find a timestamp */ |
|
649 if (data->timestamp != -1) |
|
650 return GST_BUFFER_LIST_END; |
|
651 else |
|
652 return GST_BUFFER_LIST_CONTINUE; |
|
653 } |
|
654 |
|
655 static GstBufferListItem |
|
656 set_headers (GstBuffer ** buffer, guint group, guint idx, HeaderData * data) |
|
657 { |
|
658 gst_rtp_buffer_set_ssrc (*buffer, data->ssrc); |
|
659 gst_rtp_buffer_set_payload_type (*buffer, data->pt); |
|
660 gst_rtp_buffer_set_seq (*buffer, data->seqnum); |
|
661 gst_rtp_buffer_set_timestamp (*buffer, data->rtptime); |
|
662 gst_buffer_set_caps (*buffer, data->caps); |
|
663 data->seqnum++; |
|
664 |
|
665 return GST_BUFFER_LIST_SKIP_GROUP; |
|
666 } |
|
667 |
|
668 /* Updates the SSRC, payload type, seqnum and timestamp of the RTP buffer |
|
669 * before the buffer is pushed. */ |
|
670 static GstFlowReturn |
|
671 gst_basertppayload_prepare_push (GstBaseRTPPayload * payload, |
|
672 gpointer obj, gboolean is_list) |
|
673 { |
|
674 GstBaseRTPPayloadPrivate *priv; |
651 GstBaseRTPPayloadPrivate *priv; |
675 HeaderData data; |
|
676 |
652 |
677 if (payload->clock_rate == 0) |
653 if (payload->clock_rate == 0) |
678 goto no_rate; |
654 goto no_rate; |
679 |
655 |
680 priv = payload->priv; |
656 priv = payload->priv; |
|
657 |
|
658 gst_rtp_buffer_set_ssrc (buffer, payload->current_ssrc); |
|
659 |
|
660 gst_rtp_buffer_set_payload_type (buffer, payload->pt); |
681 |
661 |
682 /* update first, so that the property is set to the last |
662 /* update first, so that the property is set to the last |
683 * seqnum pushed */ |
663 * seqnum pushed */ |
684 payload->seqnum = priv->next_seqnum; |
664 payload->seqnum = priv->next_seqnum; |
685 |
665 gst_rtp_buffer_set_seq (buffer, payload->seqnum); |
686 /* fill in the fields we want to set on all headers */ |
666 |
687 data.payload = payload; |
667 /* can wrap around, which is perfectly fine */ |
688 data.seqnum = payload->seqnum; |
668 priv->next_seqnum++; |
689 data.ssrc = payload->current_ssrc; |
669 |
690 data.pt = payload->pt; |
670 /* add our random offset to the timestamp */ |
691 data.caps = GST_PAD_CAPS (payload->srcpad); |
671 rtptime = payload->ts_base; |
692 data.timestamp = -1; |
672 |
693 |
673 timestamp = GST_BUFFER_TIMESTAMP (buffer); |
694 /* find the first buffer with a timestamp */ |
674 if (GST_CLOCK_TIME_IS_VALID (timestamp)) { |
695 if (is_list) { |
|
696 gst_buffer_list_foreach (GST_BUFFER_LIST_CAST (obj), |
|
697 (GstBufferListFunc) find_timestamp, &data); |
|
698 } else { |
|
699 data.timestamp = GST_BUFFER_TIMESTAMP (GST_BUFFER_CAST (obj)); |
|
700 } |
|
701 |
|
702 /* convert to RTP time */ |
|
703 if (GST_CLOCK_TIME_IS_VALID (data.timestamp)) { |
|
704 gint64 rtime; |
675 gint64 rtime; |
705 |
676 |
706 rtime = gst_segment_to_running_time (&payload->segment, GST_FORMAT_TIME, |
677 rtime = gst_segment_to_running_time (&payload->segment, GST_FORMAT_TIME, |
707 data.timestamp); |
678 timestamp); |
|
679 |
|
680 /* take first timestamp as base, we want to calculate the RTP timestamp |
|
681 * starting from the ts_base */ |
|
682 if (priv->rt_base == -1) { |
|
683 priv->rt_base = rtime; |
|
684 GST_LOG_OBJECT (payload, "first timestamp %" GST_TIME_FORMAT, |
|
685 GST_TIME_ARGS (rtime)); |
|
686 } |
|
687 rtime -= priv->rt_base; |
708 |
688 |
709 rtime = gst_util_uint64_scale_int (rtime, payload->clock_rate, GST_SECOND); |
689 rtime = gst_util_uint64_scale_int (rtime, payload->clock_rate, GST_SECOND); |
710 |
690 |
711 /* add running_time in clock-rate units to the base timestamp */ |
691 /* add running_time in clock-rate units to the base timestamp */ |
712 data.rtptime = payload->ts_base + rtime; |
692 rtptime += rtime; |
713 } else { |
693 } else { |
714 /* no timestamp to convert, take previous timestamp */ |
694 /* no timestamp to convert, take previous timestamp */ |
715 data.rtptime = payload->timestamp; |
695 rtptime = payload->timestamp; |
716 } |
696 } |
717 |
697 gst_rtp_buffer_set_timestamp (buffer, rtptime); |
718 /* set ssrc, payload type, seq number, caps and rtptime */ |
698 |
719 if (is_list) { |
699 payload->timestamp = rtptime; |
720 gst_buffer_list_foreach (GST_BUFFER_LIST_CAST (obj), |
700 |
721 (GstBufferListFunc) set_headers, &data); |
701 /* set caps */ |
722 } else { |
702 gst_buffer_set_caps (buffer, GST_PAD_CAPS (payload->srcpad)); |
723 GstBuffer *buf = GST_BUFFER_CAST (obj); |
|
724 set_headers (&buf, 0, 0, &data); |
|
725 } |
|
726 |
|
727 priv->next_seqnum = data.seqnum; |
|
728 payload->timestamp = data.rtptime; |
|
729 |
703 |
730 GST_LOG_OBJECT (payload, |
704 GST_LOG_OBJECT (payload, |
731 "Preparing to push packet with size %d, seq=%d, rtptime=%u, timestamp %" |
705 "Pushing packet size %d, seq=%d, rtptime=%u, timestamp %" GST_TIME_FORMAT, |
732 GST_TIME_FORMAT, (is_list) ? -1 : |
706 GST_BUFFER_SIZE (buffer), payload->seqnum, rtptime, |
733 GST_BUFFER_SIZE (GST_BUFFER (obj)), payload->seqnum, data.rtptime, |
707 GST_TIME_ARGS (timestamp)); |
734 GST_TIME_ARGS (data.timestamp)); |
708 |
735 |
709 res = gst_pad_push (payload->srcpad, buffer); |
736 return GST_FLOW_OK; |
710 |
|
711 return res; |
737 |
712 |
738 /* ERRORS */ |
713 /* ERRORS */ |
739 no_rate: |
714 no_rate: |
740 { |
715 { |
741 GST_ELEMENT_ERROR (payload, STREAM, NOT_IMPLEMENTED, (NULL), |
716 GST_ELEMENT_ERROR (payload, STREAM, NOT_IMPLEMENTED, (NULL), |
742 ("subclass did not specify clock-rate")); |
717 ("subclass did not specify clock-rate")); |
|
718 gst_buffer_unref (buffer); |
743 return GST_FLOW_ERROR; |
719 return GST_FLOW_ERROR; |
744 } |
720 } |
745 } |
|
746 |
|
747 /** |
|
748 * gst_basertppayload_push_list: |
|
749 * @payload: a #GstBaseRTPPayload |
|
750 * @list: a #GstBufferList |
|
751 * |
|
752 * Push @list to the peer element of the payloader. The SSRC, payload type, |
|
753 * seqnum and timestamp of the RTP buffer will be updated first. |
|
754 * |
|
755 * This function takes ownership of @list. |
|
756 * |
|
757 * Returns: a #GstFlowReturn. |
|
758 * |
|
759 * Since: 0.10.24 |
|
760 */ |
|
761 |
|
762 #ifdef __SYMBIAN32__ |
|
763 EXPORT_C |
|
764 #endif |
|
765 |
|
766 GstFlowReturn |
|
767 gst_basertppayload_push_list (GstBaseRTPPayload * payload, GstBufferList * list) |
|
768 { |
|
769 GstFlowReturn res; |
|
770 |
|
771 res = gst_basertppayload_prepare_push (payload, list, TRUE); |
|
772 |
|
773 if (G_LIKELY (res == GST_FLOW_OK)) |
|
774 res = gst_pad_push_list (payload->srcpad, list); |
|
775 else |
|
776 gst_buffer_list_unref (list); |
|
777 |
|
778 return res; |
|
779 } |
|
780 |
|
781 /** |
|
782 * gst_basertppayload_push: |
|
783 * @payload: a #GstBaseRTPPayload |
|
784 * @buffer: a #GstBuffer |
|
785 * |
|
786 * Push @buffer to the peer element of the payloader. The SSRC, payload type, |
|
787 * seqnum and timestamp of the RTP buffer will be updated first. |
|
788 * |
|
789 * This function takes ownership of @buffer. |
|
790 * |
|
791 * Returns: a #GstFlowReturn. |
|
792 */ |
|
793 #ifdef __SYMBIAN32__ |
|
794 EXPORT_C |
|
795 #endif |
|
796 |
|
797 GstFlowReturn |
|
798 gst_basertppayload_push (GstBaseRTPPayload * payload, GstBuffer * buffer) |
|
799 { |
|
800 GstFlowReturn res; |
|
801 |
|
802 res = gst_basertppayload_prepare_push (payload, buffer, FALSE); |
|
803 |
|
804 if (G_LIKELY (res == GST_FLOW_OK)) |
|
805 res = gst_pad_push (payload->srcpad, buffer); |
|
806 else |
|
807 gst_buffer_unref (buffer); |
|
808 |
|
809 return res; |
|
810 } |
721 } |
811 |
722 |
812 static void |
723 static void |
813 gst_basertppayload_set_property (GObject * object, guint prop_id, |
724 gst_basertppayload_set_property (GObject * object, guint prop_id, |
814 const GValue * value, GParamSpec * pspec) |
725 const GValue * value, GParamSpec * pspec) |