Advertisement
Guest User

pi storm

a guest
Jun 5th, 2012
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.76 KB | None | 0 0
  1. #!/usr/bin/env python
  2.  
  3. import sys
  4. import subprocess
  5. import tornado.httpserver
  6. import tornado.ioloop
  7. import tornado.web
  8. import signal
  9. import shlex
  10. import os
  11.  
  12. class Ring:
  13.     def __init__( self, packets = 100 ):
  14.         self.packets = packets
  15.         self.queue = [ ]
  16.         self.read = 0
  17.         self.write = 0
  18.         self.closed = False
  19.  
  20.     def put( self, data ):
  21.         if self.closed: return
  22.         if self.write % self.packets == len( self.queue ):
  23.             self.queue.append( data )
  24.         else:
  25.             self.queue[ self.write % self.packets ] = data
  26.         self.write += 1
  27.  
  28.     def get( self ):
  29.         if self.closed and self.read >= self.write: return ''
  30.         result = self.queue[ self.read % self.packets ]
  31.         self.queue[ self.read % self.packets ] = None
  32.         self.read += 1
  33.         return result
  34.  
  35.     def has( self ):
  36.         return self.read < self.write
  37.  
  38.     def close( self ):
  39.         self.closed = True
  40.  
  41.     def done( self ):
  42.         return self.closed
  43.  
  44. class stream_handler( tornado.web.RequestHandler ):
  45.  
  46.     @tornado.web.asynchronous
  47.     def get( self ):
  48.         url = self.get_argument( 'url', '' )
  49.         if url != "":
  50.             self.ring = Ring( packets )
  51.             self.call_subprocess( shlex.split( str( backend % url ) ) )
  52.             tornado.ioloop.IOLoop.instance( ).add_callback( self.callback )
  53.         else:
  54.             self.write( 'Content-Type: text/plain\n' )
  55.             self.write( 'Unable to handle request' )
  56.  
  57.     def callback( self ):
  58.         try:
  59.             if self.ring.has( ):
  60.                 data = self.ring.get( )
  61.                 if len( data ) == 0: return
  62.                 self.write( data )
  63.                 self.flush( )
  64.             if not self.ring.done( ) or self.ring.has( ):
  65.                 tornado.ioloop.IOLoop.instance( ).add_callback( self.callback )
  66.         except:
  67.             pass
  68.  
  69.     def call_subprocess( self, command ):
  70.         self.ioloop = tornado.ioloop.IOLoop.instance( )
  71.         self.pipe = subprocess.Popen( command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, close_fds = True )
  72.         self.ioloop.add_handler( self.pipe.stdout.fileno( ), self.async_callback( self.on_subprocess_result, None ), self.ioloop.READ )
  73.  
  74.     def on_subprocess_result(self, callback, fd, result):
  75.         try:
  76.             data = self.pipe.stdout.read( 10240 )
  77.             if len( data ) == 0:
  78.                 self.ring.close( )
  79.                 self.ioloop.remove_handler( fd )
  80.             else:
  81.                 self.ring.put( data )
  82.         except:
  83.             self.ioloop.remove_handler( fd )
  84.             self.ring.close( )
  85.  
  86.     def on_connection_close( self ):
  87.         self.ring.close( )
  88.         self.pipe.stdout.close( )
  89.         self.pipe.kill( )
  90.  
  91. port = 57740
  92. packets = 50000
  93. size = 10240
  94. backend = 'ffmpeg -i "%s" -s 640x360 -deinterlace -f mpegts -qscale 2 -vcodec mpeg4 pipe:'
  95.  
  96. if __name__ == "__main__":
  97.     signal.signal( signal.SIGCHLD, signal.SIG_IGN )
  98.     application = tornado.web.Application( [ ( r"/stream", stream_handler ), ] )
  99.     http_server = tornado.httpserver.HTTPServer( application, no_keep_alive=True )
  100.     http_server.listen( port )
  101.     tornado.ioloop.IOLoop.instance( ).start( )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement