Created
February 20, 2021 12:13
-
-
Save lexbailey/594e77728e55b88ff2b81cbf0cbde651 to your computer and use it in GitHub Desktop.
BROKEN CODE DO NOT USE: Trying to get an AppSrc to feed data into a GES timeline, not working yest
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| Attempted demo of AppSrc with GES timeline | |
| Does not work | |
| Creates a simple GTK Window, inits GES to preview to that window, adds a test video clip (muted) and | |
| adds the custom audio synth element, but the audio synth element sound does not play | |
| Currently reports some assertion errors. | |
| """ | |
| import sys | |
| import gi | |
| gi.require_version('Gtk', '3.0') | |
| gi.require_version('Gst', '1.0') | |
| gi.require_version('GstVideo', '1.0') | |
| gi.require_version('GES', '1.0') | |
| gi.require_version('GstApp', '1.0') | |
| from gi.repository import Gtk, GObject, Gst | |
| from gi.repository import GstVideo | |
| from gi.repository import GES, Gio | |
| from gi.repository import GstApp | |
| Gtk.init(sys.argv) | |
| Gst.init_check(sys.argv) | |
| GES.init() | |
| class AudioSynth(GstApp.AppSrc): | |
| def __init__(self, *args, **kwargs): | |
| super().__init__(*args, **kwargs) | |
| self.sample_rate = 8000 | |
| self.wave = self.sinwave_sequence(300) | |
| self.rawcaps = Gst.Caps.from_string( | |
| 'audio/x-raw,format=U8,rate={},channels=1,layout=interleaved'.format(self.sample_rate) | |
| ) | |
| def sinwave_sequence(self, freq): | |
| """ Placeholder: just an interesting and easily recognised noise, TODO replace with actual synth code """ | |
| n = 0 | |
| freqs = [freq, freq + 100, freq + 200, freq + 300] | |
| freqs += list(reversed(freqs[1:3])) | |
| f = 0 | |
| while True: | |
| n += 1 | |
| samples_per_cycle = self.sample_rate/freq | |
| yield int( | |
| 127 * (math.sin( | |
| math.pi*2*((n%samples_per_cycle)/samples_per_cycle) | |
| ) + 1.0) | |
| ) | |
| if n % int(0.15 * self.sample_rate) == 0: | |
| f += 1; f = f % len(freqs) | |
| freq = freqs[f] | |
| def do_enough_data(self): | |
| print("Got enough samples") | |
| def do_need_data(self, need): | |
| print("Pushing {} more samples".format(need)) | |
| # TODO seeking won't work with this code | |
| buf = Gst.Buffer.new_wrapped(bytes(islice(self.wave, 4096))) | |
| self.push_buffer(buf) | |
| def link_with_raw_caps(self, dest): | |
| self.link_filtered(dest, self.rawcaps) | |
| class SynthAudioSourceElement(GES.AudioSource): | |
| def __init__(self): | |
| print("Created source") | |
| super().__init__() | |
| def do_create_source(self): | |
| print("Creating audio synth element source") | |
| self.pipeline = Gst.ElementFactory.make("pipeline", None) | |
| source = AudioSynth() | |
| convert = Gst.ElementFactory.make("audioconvert") | |
| pipeline.add(source) | |
| pipeline.add(convert) | |
| source.link_with_raw_caps(convert) | |
| return self.pipeline | |
| class SynthAudioClip(GES.SourceClip): | |
| def __init__(self): | |
| super().__init__() | |
| self.set_supported_formats(GES.TrackType.AUDIO) | |
| def do_create_track_element(self, type_): | |
| print("Creating audio synth element") | |
| assert type_ == GES.TrackType.AUDIO | |
| self.element = SynthAudioSourceElement() | |
| print(self.element) | |
| return self.element | |
| class EditorWindow(Gtk.ApplicationWindow): | |
| def __init__(self): | |
| super().__init__(title='test') | |
| self.connect('destroy', self.quit) | |
| self.connect('realize', self._on_realize) | |
| self.set_default_size(1200, 800) | |
| self.project = None | |
| def _on_realize(self, widget): | |
| self.sink = Gst.ElementFactory.make("gtksink", None) | |
| if self.sink is None: | |
| print("Error, unable to create video sink", file=sys.stderr) | |
| sys.exit(1) | |
| self.add(self.sink.props.widget) | |
| self.show_all() | |
| def play(self): | |
| self.pipeline.set_state(Gst.State.PLAYING) | |
| def _asset_added(self, ges_proj, asset): | |
| dur = 10 * Gst.SECOND | |
| print("Adding asset to layer", asset) | |
| if asset.get_id() == 'GESTestClip': | |
| # If this is the test clip, mute it (just so we can hear the audio synth easier) | |
| clip = self.layer.add_asset(asset, 0, 0, dur, GES.TrackType.UNKNOWN) | |
| clip.set_mute(True) | |
| else: | |
| # Otherwise, just add asset audio track | |
| clip = self.layer2.add_asset(asset, 0, 0, dur, GES.TrackType.AUDIO) | |
| def test_clip(self): | |
| clip = GES.TestClip() | |
| self.layer.add_clip(clip) | |
| clip2 = SynthAudioClip() | |
| self.layer2.add_clip(clip2) | |
| def _error_loading_asset(self, ges_proj, error, asset_id, _type): | |
| print("Error adding asset to timeline.", error, asset_id, _type) | |
| def _bus_message(self, bus, message): | |
| if message.type == Gst.MessageType.EOS: | |
| print("end of playback") | |
| elif message.type == Gst.MessageType.ERROR: | |
| error = message.parse_error() | |
| print("error %s" % error[1]) | |
| elif message.type == Gst.MessageType.WARNING: | |
| warning = message.parse_warning() | |
| print("warning: %s" == warning[1]) | |
| elif message.type & Gst.MessageType.STATE_CHANGED: | |
| pass#print(message) | |
| else: | |
| pass#print(message.type) | |
| def init_playback(self): | |
| self.timeline = GES.Timeline.new_audio_video() | |
| self.ges_proj = self.timeline.get_asset() | |
| self.ges_proj.connect("asset-added", self._asset_added) | |
| self.ges_proj.connect("error-loading-asset", self._error_loading_asset) | |
| self.layer = self.timeline.append_layer() | |
| self.layer2 = self.timeline.append_layer() | |
| self.pipeline = GES.Pipeline() | |
| self.pipeline.set_timeline(self.timeline) | |
| self.pipeline.preview_set_video_sink(self.sink) | |
| bus = self.pipeline.get_bus() | |
| bus.add_signal_watch() | |
| bus.connect("message", self._bus_message) | |
| def quit(self, window): | |
| Gtk.main_quit() | |
| ew = EditorWindow() | |
| ew.show_all() | |
| ew.init_playback() | |
| ew.test_clip() | |
| ew.play() | |
| Gtk.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment