From f1ac47fff77647b33d0250c4330a33bc1d6d0a5b Mon Sep 17 00:00:00 2001 From: Mike Chong Date: Wed, 31 Oct 2012 12:31:30 -0400 Subject: [PATCH] GH-206 Implemented RTMP streaming NOT YET TESTED. (this line will be removed from commit message when testing is complete) Implemented get_output_bin function in RTMP Streaming plugin. Returns a bin with video and audio sink pads, as necessary. Uses flvmux to mux the audio/video streams, and add metadata tags. Uses x264enc to encode the video to x-h264 for flv. Streams flv content to rtmp server at url provided by user. Testing notes: TODO Notes for review: - I add the metadata tags to the flv stream using the flvmux element. Currently, I'm not sure if that's the right way how to do it, and need to look into how to verify it. - I set the bitrate for the h264 encoder based on the value found in the ogg-output plugin. --- .../output/rtmp-streaming/rtmp-streaming.py | 71 ++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/src/freeseer/plugins/output/rtmp-streaming/rtmp-streaming.py b/src/freeseer/plugins/output/rtmp-streaming/rtmp-streaming.py index 90464943..a8df104d 100644 --- a/src/freeseer/plugins/output/rtmp-streaming/rtmp-streaming.py +++ b/src/freeseer/plugins/output/rtmp-streaming/rtmp-streaming.py @@ -41,14 +41,83 @@ class RTMPOutput(IOutput): # RTMP Streaming variables url = "" + video_bitrate = 2400 + #@brief - RTMP Streaming plugin. + # Structure for function was based primarily off the ogg function + # Creates a bin to stream flv content to [self.url] + # Bin has audio and video ghost sink pads + # Converts audio and video to flv with [flvmux] element + # Streams flv content to [self.url] + # TODO - Error handling - verify pad setup def get_output_bin(self, audio=True, video=True, metadata=None): bin = gst.Bin(self.name) if metadata is not None: self.set_metadata(metadata) - # TODO!! + # Muxer + muxer = gst.element_factory_make("flvmux", "muxer") + + # Setup metadata + # set tag merge mode to GST_TAG_MERGE_REPLACE + merge_mode = gst.TagMergeMode.__enum_values__[2] + + muxer.merge_tags(self.tags, merge_mode) + muxer.set_tag_merge_mode(merge_mode) + + bin.add(muxer) + + # RTMP sink + #TODO - rtmpsink factory? + rtmpsink = gst.element_factory_make('rtmpsink', 'rtmpsink') + rtmpsink.set_property('location', self.url) + bin.add(rtmpsink) + + # + # Setup Audio Pipeline if Audio Recording is Enabled + # + if audio: + audioqueue = gst.element_factory_make("queue", "audioqueue") + bin.add(audioqueue) + + audioconvert = gst.element_factory_make("audioconvert", "audioconvert") + bin.add(audioconvert) + + audiolevel = gst.element_factory_make('level', 'audiolevel') + audiolevel.set_property('interval', 20000000) + bin.add(audiolevel) + + # Setup ghost pads + audiopad = audioqueue.get_pad("sink") + audio_ghostpad = gst.GhostPad("audiosink", audiopad) + bin.add_pad(audio_ghostpad) + + gst.element_link_many(audioqueue, audioconvert, audiolevel, muxer) + + + # + # Setup Video Pipeline + # + if video: + videoqueue = gst.element_factory_make("queue", "videoqueue") + bin.add(videoqueue) + + videocodec = gst.element_factory_make("x264enc", "videocodec") + videocodec.set_property("bitrate", int(self.video_bitrate)) + bin.add(videocodec) + + # Setup ghost pads + videopad = videoqueue.get_pad("sink") + video_ghostpad = gst.GhostPad("videosink", videopad) + bin.add_pad(video_ghostpad) + + gst.element_link_many(videoqueue, videocodec, muxer) + + # + # Link muxer to rtmpsink + # + gst.element_link_many(muxer, rtmpsink) return bin