|
|
Line 46: |
Line 46: |
| * Jump to a specific time | | * Jump to a specific time |
| * The console show the errors, warnings and logs of gstd | | * The console show the errors, warnings and logs of gstd |
− |
| |
− | ==Code Analysis==
| |
− |
| |
− | This example application can be divided into 3 sections:
| |
− | # Init Sequence & Command Parser
| |
− | # GstcPlayer Class
| |
− | ## Error Handler
| |
− |
| |
− | ===Init Sequence & Command Parser===
| |
− | This section is pretty straightforward. You just need to pas the video file path as the only argument.
| |
− |
| |
− | <syntaxhighlight lang=python>
| |
− | if __name__ == "__main__":
| |
− | print("Sample PyGstC Video Player")
| |
− | '''
| |
− | .
| |
− | .
| |
− | . '''
| |
− | </syntaxhighlight>
| |
− |
| |
− | Once the application is started. Automatically, it will open and reproduce the video. On the command prompt, you can specify any of the supported commands.
| |
− |
| |
− | ===GstcPlayer Class===
| |
− | This class contains all the necessary calls to communicate with the GStreamer Daemon, through the Python GstdClient.
| |
− |
| |
− | Firs of all the Python GstdClient needs to be imported with:
| |
− | <syntaxhighlight lang=python>
| |
− | from pygstc.gstc import GstcError, GstdError, GstdClient
| |
− | from pygstc.logger import CustomLogger
| |
− | </syntaxhighlight>
| |
− |
| |
− | There are two main objects to manipulate the GstdClient over Python. First the Logger class (''CustomLogger'') and the GstdClient itself. The logger can have different information levels, for example you can pass an 'ERROR' level.
| |
− | <syntaxhighlight lang=python>
| |
− | class GstcPlayer:
| |
− |
| |
− | def __init__(self, videoPath):
| |
− | self.gstd_logger = CustomLogger('simple_playback', loglevel='WARNING')
| |
− | self.gstc = GstdClient(logger=self.gstd_logger)
| |
− | </syntaxhighlight>
| |
− |
| |
− | Once those objects are created. The [[https://developer.ridgerun.com/wiki/index.php?title=GStreamer_Daemon_-_Python_API|Python API]] offers a set of calls to communicate with the GStreamer Daemon. For example, when the ''play'' command is executed, the following actions are executed:
| |
− | <syntaxhighlight lang=python>
| |
− | def playVideo(self):
| |
− | self.gstc.pipeline_create(self.pipeName, self.pipeline)
| |
− | self.gstc.pipeline_play(self.pipeName)
| |
− | </syntaxhighlight>
| |
− |
| |
− | Let's say you just want to pause the video and continue from that point. Then you can modify the playing function similar to:
| |
− | <syntaxhighlight lang=python>
| |
− | def playVideo(self):
| |
− | if (not self.pipe_exists(self.pipeName)):
| |
− | self.gstc.pipeline_create(self.pipeName, self.pipeline)
| |
− | self.gstc.pipeline_play(self.pipeName)
| |
− |
| |
− | def pipe_exists(self, pipe_name):
| |
− | #Check if pipe is already created
| |
− | existing_pipes = self.gstc.list_pipelines()
| |
− | if (existing_pipes == []):
| |
− | ret = False
| |
− | elif( existing_pipes[0]['name'] == pipe_name):
| |
− | ret = True
| |
− | else:
| |
− | ret = False
| |
− | return ret
| |
− | </syntaxhighlight>
| |
− |
| |
− | Then a ''pause'' call can be created with:
| |
− | <syntaxhighlight lang=python>
| |
− | def pauseVideo(self):
| |
− | self.gstc.pipeline_pause(self.pipeName)
| |
− | </syntaxhighlight>
| |
− |
| |
− | And to use the same ''play'' command:
| |
− |
| |
− | Similar, when the command stop is executed there are some instructions to achieve this:
| |
− | <syntaxhighlight lang=python>
| |
− | def stopVideo(self)
| |
− | self.gstc.pipeline_stop(self.pipeName)
| |
− | self.gstc.pipeline_delete(self.pipeName)
| |
− | </syntaxhighlight>
| |
− |
| |
− | The same process was used to implement changes in playback speed, by using:
| |
− | <syntaxhighlight lang=python>
| |
− | self.gstc.event_seek(self.pipeName, rate=self.playingSpeed, format=3, flags=1, start_type=1, start=0, end_type=1, end=-1)
| |
− | </syntaxhighlight>
| |
− | You can use the same ''event_seek'' call to select a time to jump on the video.
| |
− |
| |
− | ====Error Handler====
| |
− | The Python API offers calls to read messages from the GStreamer Daemon Bus. The very basic command to read from the bus is:
| |
− | <syntaxhighlight lang=python>
| |
− | resp = self.gstc.bus_read(self.pipeName)
| |
− | </syntaxhighlight>
| |
− |
| |
− | This call does '''not''' need any use thread to be executed. It can be called at any moment by the user application.
| |
− |
| |
− | For the Video Player, this function is contained within a separate thread just to avoid manually reading from the bus with a command. By doing so we achieved a more complete application, and also for the demonstration purposes. This thread function configures the reading from the bus with a timeout, so we can gracefully exit the thread whenever the user demands so. Also, it is possible to filter the messages by specific types, such as errors or warnings.
| |
− |
| |
− | <syntaxhighlight lang=python>
| |
− | def errPlayerHandler(self):
| |
− | self.gstc.bus_timeout(self.pipeName, 1000)
| |
− | self.gstc.bus_filter(self.pipeName, "error+eos+warning")
| |
− |
| |
− | if(self.pipe_exists(self.pipeName)):
| |
− | resp = self.gstc.bus_read(self.pipeName)
| |
− | if (resp != None and resp["type"] == "error"):
| |
− | print("Info: Video stopped")
| |
− | self.gstc.pipeline_pause(self.pipeName)
| |
− | self.gstc.pipeline_stop(self.pipeName)
| |
− | elif (resp != None and resp["type"] == "eos"):
| |
− | print("Info: Video stream ended")
| |
− | self.gstc.pipeline_pause(self.pipeName)
| |
− | </syntaxhighlight>
| |
− |
| |
− | With the implemented filters two main actions are detected:
| |
− | # When the Video finalize reproducing, and then the pipeline is paused.
| |
− | # If an error occurred the pipeline is stopped.
| |
− |
| |
− | If you inspect the code, you will find that this function has locking objects to avoid race conditions. But for basic understanding, we presented the essentials instructions from the application.
| |
− |
| |
− |
| |
− |
| |
− | {{GStreamer Daemon/Foot | previous=API Examples | next=Troubleshooting}}
| |