Here's a patch I use for profiling video decoding and rendering speed.
It adds a pyglet option "profile_media" which makes sure that
- the video file's frame rate is ignored
- exactly one frame is decoded and rendered in every call to
media_player.py's on_draw()
- the process is terminated after 500 frames of decoded video
- the decoding is done by the main thread
- on_draw() is called as often as possible

The goal is to saturate a single CPU core with the task of video
decoding and color space conversion and to be able to time how long it
takes to render 500 frames.

After having applied this patch, you can run a benchmark like this:

export PYGLET_PROFILE_MEDIA=TRUE
export PYGLET_VSYNC=FALSE
time python examples/media_player.py <video file with at least 500
frames>

(Yes, probably it would have been a good idea to write a separate tool
rather than to modify media_player.py)

Some results will be in the next post.
Jan

Index: pyglet/media/__init__.py
===================================================================
--- pyglet/media/__init__.py    (Revision 2539)
+++ pyglet/media/__init__.py    (Arbeitskopie)
@@ -83,6 +83,7 @@
 import pyglet

 _debug = pyglet.options['debug_media']
+_profile = pyglet.options['profile_media']

 class MediaException(Exception):
     pass
@@ -992,7 +993,10 @@
                     period = 1. / self.source.video_format.frame_rate
                 else:
                     period = 1. / 30.
-                pyglet.clock.schedule_interval(self.update_texture,
period)
+                if _profile:
+                    pyglet.clock.schedule(lambda dt: None)
+                else:
+                    pyglet.clock.schedule_interval
(self.update_texture, period)
         else:
             if self._audio_player:
                 self._audio_player.stop()
@@ -1117,23 +1121,26 @@
         self.seek(time)

     def update_texture(self, dt=None, time=None):
-        if time is None:
-            time = self._audio_player.get_time()
-        if time is None:
-            return
+        if _profile:
+            ts = 0
+        else:
+            if time is None:
+                time = self._audio_player.get_time()
+            if time is None:
+                return

-        if (self._last_video_timestamp is not None and
-            time <= self._last_video_timestamp):
-            return
+            if (self._last_video_timestamp is not None and
+                time <= self._last_video_timestamp):
+                return

-        ts = self._groups[0].get_next_video_timestamp()
-        while ts is not None and ts < time:
-            self._groups[0].get_next_video_frame() # Discard frame
             ts = self._groups[0].get_next_video_timestamp()
+            while ts is not None and ts < time:
+                self._groups[0].get_next_video_frame() # Discard
frame
+                ts = self._groups[0].get_next_video_timestamp()

-        if ts is None:
-            self._last_video_timestamp = None
-            return
+            if ts is None:
+                self._last_video_timestamp = None
+                return

         image = self._groups[0].get_next_video_frame()
         if image is not None:
Index: pyglet/media/avbin.py
===================================================================
--- pyglet/media/avbin.py       (Revision 2539)
+++ pyglet/media/avbin.py       (Arbeitskopie)
@@ -41,6 +41,7 @@
 import ctypes
 import threading
 import time
+import os

 import pyglet
 from pyglet import gl
@@ -381,8 +382,10 @@
             self._video_timestamp = max(self._video_timestamp,
                                         video_packet.timestamp)
             self._video_packets.append(video_packet)
-            self._decode_thread.put_job(
-                lambda: self._decode_video_packet(video_packet))
+
+            if not _profile:
+                self._decode_thread.put_job(
+                    lambda: self._decode_video_packet(video_packet))

             return 'video', video_packet

@@ -487,6 +490,11 @@
     def _decode_video_packet(self, packet):
         width = self.video_format.width
         height = self.video_format.height
+
+        if _profile and packet.id == 500:
+            print "%dx%d" % (width, height)
+            os.kill(os.getpid(),9)
+
         pitch = width * 3
         buffer = (ctypes.c_uint8 * (pitch * height))()
         result = av.avbin_decode_video(self._video_stream,
@@ -499,10 +507,11 @@

         packet.image = image_data

-        # Notify get_next_video_frame() that another one is ready.
-        self._condition.acquire()
-        self._condition.notify()
-        self._condition.release()
+        if not _profile:
+            # Notify get_next_video_frame() that another one is
ready.
+            self._condition.acquire()
+            self._condition.notify()
+            self._condition.release()

     def _ensure_video_packets(self):
         '''Process packets until a video packet has been queued (and
begun
@@ -539,15 +548,22 @@

         if self._ensure_video_packets():
             packet = self._video_packets.pop(0)
-            if _debug:
-                print 'Waiting for', packet
+
+            if not _profile:
+                if _debug:
+                    print 'Waiting for', packet

-            # Block until decoding is complete
-            self._condition.acquire()
-            while packet.image == 0:
-                self._condition.wait()
-            self._condition.release()
+                # Block until decoding is complete
+                self._condition.acquire()
+                while packet.image == 0:
+                    self._condition.wait()
+                self._condition.release()

+            else:
+                # when we are profiling, the main thread
+                # does all the work
+                self._decode_video_packet(packet)
+
             if _debug:
                 print 'Returning', packet
             return packet.image
@@ -560,4 +576,5 @@
     _debug = False
     av.avbin_set_log_level(AVBIN_LOG_QUIET)

+_profile = pyglet.options['profile_media']
 _have_frame_rate = av.avbin_have_feature('frame_rate')
Index: pyglet/__init__.py
===================================================================
--- pyglet/__init__.py  (Revision 2539)
+++ pyglet/__init__.py  (Arbeitskopie)
@@ -139,6 +139,7 @@
     'debug_graphics_batch': False,
     'debug_lib': False,
     'debug_media': False,
+    'profile_media': False,
     'debug_texture': False,
     'debug_trace': False,
     'debug_trace_args': False,
@@ -163,6 +164,7 @@
     'debug_graphics_batch': bool,
     'debug_lib': bool,
     'debug_media': bool,
+    'profile_media': bool,
     'debug_texture': bool,
     'debug_trace': bool,
     'debug_trace_args': bool,
Index: examples/media_player.py
===================================================================
--- examples/media_player.py    (Revision 2539)
+++ examples/media_player.py    (Arbeitskopie)
@@ -298,6 +298,7 @@

         # Video
         if self.player.source and self.player.source.video_format:
+            if _profile: self.player.update_texture()
             self.player.get_texture().blit(self.video_x,
                                            self.video_y,
                                            width=self.video_width,
@@ -308,6 +309,8 @@
         for control in self.controls:
             control.draw()

+_profile = pyglet.options['profile_media']
+
 if __name__ == '__main__':
     if len(sys.argv) < 2:
         print 'Usage: media_player.py <filename> [<filename> ...]'

--

You received this message because you are subscribed to the Google Groups 
"pyglet-users" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/pyglet-users?hl=en.


Reply via email to