This file is indexed.

/usr/share/pyshared/pymt/modules/mjpegserver.py is in python-pymt 0.5.1-0ubuntu3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
'''
Stream the PyMT video inside MJPEG HTTP server

:Configuration:
    `ip` : str, default to ''
        By default, server will listen on all ips availables
    `port` : int, default to 8000
        TCP Port to listen
    `fps` : int, default to 20
        Fix a FPS to try to have the same FPS on the whole video
    `size` : str, default to ''
        If the image must be resized, set size to "320x240" for example

'''
#
# Developper note
#
# Double lock is needed if we don't want the sensation about laggy video
# The deal is, if we don't lock the screen, you got more FPS on OpenGL than
# streaming (and that would be good.) Except that since it's not synced,
# video look laggy.
# Double-lock was just the faster solution to do right now :)
#

import os
import pymt
import threading
import time
import StringIO
import random
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from OpenGL.GL import glReadBuffer, glReadPixels, GL_RGB, GL_UNSIGNED_BYTE, GL_FRONT
from pymt.utils import curry

if 'PYMT_DOC' not in os.environ:
	from PIL import Image

lock_current    = threading.Lock()
sem_current     = threading.Semaphore(0)
sem_next        = threading.Semaphore(1)
img_current     = None
connected       = False

def keep_running():
    return True

class MjpegHttpRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        global connected, sem_next
        try:
            connected = True
            self._stream_video()
        finally:
            connected = False
            # to prevent that app hang
            sem_next.release()
            pymt.pymt_logger.info(
                'MjpegServer: Client %s:%d disconnect' % self.client_address)

    def _stream_video(self):
        global img_current

        lfps        = []
        dt          = 0
        frames      = 0
        fps_wanted  = self.server.config.get('fps')
        if fps_wanted == '':
            fps_wanted = 0
        fps_wanted = float(fps_wanted)
        if fps_wanted <= 1:
            fps_wanted = 0
        else:
            fps_wanted = 1 / fps_wanted
        size        = self.server.config.get('size')
        if size == '':
            size = None
        else:
            size = map(int, size.split('x'))

        pymt.pymt_logger.info(
            'MjpegServer: Client %s:%d connected' % self.client_address)

        self.send_response(200, 'OK')
        self.boundary = 'pymt-mjpegserver-boundary-%d' % (random.randint(1, 9999999))
        self.send_header('Server', 'PyMT MjpegServer')
        self.send_header('Content-type', 'multipart/x-mixed-replace; boundary=%s' % self.boundary)
        self.end_headers()

        # don't accept connection until the window is created
        # XXX really needed ?
        while not pymt.getWindow():
            time.sleep(0.1)
        win = pymt.getWindow()

        dt = dt_current = dt_old = time.time()
        while keep_running():

            # SYNC START
            sem_current.acquire()

            with lock_current:
                im = Image.fromstring('RGB', win.size, img_current)
                img_current = None

            sem_next.release()
            # SYNC END

            buf = StringIO.StringIO()
            if size:
                im = im.resize(size)
            im = im.transpose(Image.FLIP_TOP_BOTTOM)
            im.save(buf, format='JPEG')
            jpeg = buf.getvalue()

            self.wfile.write('--%s\r\n' % self.boundary)
            self.wfile.write('Content-Type: image/jpeg\r\n')
            self.wfile.write('Content-Length: %d\r\n\r\n' % len(jpeg))
            self.wfile.write(jpeg)

            dt_old = dt_current
            dt_current = time.time()

            d = dt_current - dt_old
            if d < fps_wanted:
                time.sleep(d)

            frames += 1
            if dt_current - dt > 2.:
                fps = frames / (dt_current - dt)
                lfps.append(fps)
                x = sum(lfps) / len(lfps)
                pymt.pymt_logger.debug('MjpegServer: current FPS is %.1f, average is %.1f' % (fps, x))
                dt = dt_current
                frames = 0

class MjpegServerThread(threading.Thread):
    def __init__(self, config):
        super(MjpegServerThread, self).__init__()
        self.config = config

    def run(self):
        server_address = (self.config.get('ip'), int(self.config.get('port')))
        httpd = HTTPServer(server_address, MjpegHttpRequestHandler)
        httpd.config = self.config
        pymt.pymt_logger.info('MjpegServer: Listen to %s:%d' % server_address)
        while keep_running():
            httpd.handle_request()

def window_flip_and_save():
    global img_current
    win = pymt.getWindow()

    with lock_current:
        if not connected:
            return

    sem_next.acquire()

    with lock_current:
        glReadBuffer(GL_FRONT)
        data = glReadPixels(0, 0, win.width, win.height, GL_RGB, GL_UNSIGNED_BYTE)
        img_current = str(buffer(data))

    sem_current.release()

def start(win, ctx):
    win.push_handlers(on_flip=window_flip_and_save)

    ctx.config.setdefault('ip', '')
    ctx.config.setdefault('port', '8000')
    ctx.config.setdefault('fps', '')
    ctx.config.setdefault('size', '')

    ctx.server = MjpegServerThread(ctx.config)
    ctx.server.daemon = True
    ctx.server.start()

def stop(win, ctx):
    win.remove_handlers(on_flip=window_flip_and_save)