def unittest():
    import sys, time
    logging.basicConfig(
        stream=sys.stdout,
        level=logging.DEBUG,
        format="%(asctime)s %(message)s"
    )

    sid="test"
    ig = ImageGenerator(sid)
    si_topic = config.StreamInputTopic(sid)
    img_topic = config.ImageTopic(sid)
    def image_ready(filename=""):
        logging.info("++++++++++++ image ready ++++++++++++")   
 
    signals.subscribe(img_topic,image_ready)
    stop_topic = config.StreamStopTopic(sid)        
    ig.start()
    f = open(os.environ['HOME']+"/oceans.mp4")
    while True:
        time.sleep(0.25)
        chunk = f.read(32767) 
        if not chunk or len(chunk) == 0:
            break
         
        #ig.feed(chunk) 
        signals.publish(si_topic,chunk)
    signals.publish(stop_topic)
    def run(self):
        # run worker thread that oversees the ffmpeg process, prmorning the
        # task of restarting the stream if need and be and routing video
        # traffic.
        try:
            self._run()
        except BaseException:
            logging.error(traceback.format_exc())
            signals.publish(self.sf_topic, {
                'error': 'SystemError',
                'desc': 'Exception thrown check error log'
            })

        if self.proc and not self.proc.poll():
            self.proc.kill()
            self.proc.communicate(b'')
 def _inactivity_fault(self):
     """ Test to see if traffic was received from the output pipe conf.maxInActvity
         seconds ago.
     """
     if time.time() > (self.last_output_time + self.conf['maxInActvity']):
         self.state = config.STREAM_STATE_FAULT
         signals.publish(
             self.sf_topic, {
                 'error':
                 'BadInput',
                 'desc':
                 'No input received after %d seconds' %
                 self.conf['maxInActvity']
             })
         return True
     return False
    def feed(self, data):
        """
        Feed data to ffmpeg, allow it to generate an image, send
        the filename of the image if it is a new image and at
        the minimum interval.
        """
        logging.debug("writing chunk to pipe") 
        retval = self.proc.poll()
        if retval:
            logging.error("imageGenerate: ffmpeg crash")
            return 
 
        os.write(self.vin_w,data)
        if os.access(self.imgfile,os.F_OK):
            mtime = os.stat(self.imgfile) 
            logging.info("mtime = %s" % str(mtime))
            if not self.last_mtime or mtime != self.last_mtime:
                signals.publish(self.img_topic, self.imgfile)
                self.last_mtime = mtime
    def _line_proc(self, line):
        logging.debug("line = %s" % line)
        # process stats
        # We're looking for this:
        #  'frame=  138 fps= 11 q=31.0 PSNR=Y:30.88 U:36.31 V:37.12 *:32.10 size=     882kB'
        t = line.split()
        if len(t) > 0 and t[0] == 'frame=':

            def translate(text):
                text = text.replace('kB', ' * 1000')
                text = text.replace('kbits/s', ' * 1000')
                text = text.replace('M', ' * 1000000')
                return eval(text)

            def psnr(t):
                for tt in t:
                    if tt.startswith('*:'):
                        return float(tt[2:])
                return 0

            def bitrate(line):
                pos = line.find('bitrate=')
                if pos > -1:
                    pos += len('bitrate=')
                    return line[pos:].split()[0]

                pos = line.find('size=')
                if pos > -1:
                    return line[pos:].split()[1]

                return "0"

            logging.debug(psnr)
            input_stats = {
                'fps': t[3],
                # signal to noise ratio, in example: *:(32.10)
                'psnr': psnr(t),
                'bitrate': translate(bitrate(line))
            }
            logging.debug("received stats: %s" % str(input_stats))
            # route stats to whoever is listening
            signals.publish(self.ss_topic, input_stats)
    def _while_ffmpeg_running(self):
        """
        launch ffmpeg
             route output traffic to stream input topic
             parse
        """
        if self.conf['url'] == 'testsrc':
            cmdargs = (config.FFMPEG, self.vout_w)
            cmd = _isfmt_testsrc % cmdargs
        elif self.conf['url'].startswith('http:'):
            cmdargs = (config.FFMPEG, self.conf['url'], self.vout_w)
            cmd = _isfmt_http % cmdargs
        else:
            cmdargs = (config.FFMPEG, self.conf['url'], self.vout_w)
            cmd = _isfmt % cmdargs
        logging.debug(cmd)
        self.proc = subprocess.Popen(shlex.split(cmd),
                                     shell=False,
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE)

        plist = select.poll()
        plist.register(self.cmd_r, select.POLLIN)
        plist.register(self.vout_r, select.POLLIN)
        plist.register(self.proc.stdout.fileno(), select.POLLIN)
        plist.register(self.proc.stderr.fileno(), select.POLLIN)

        # initialize reference time to now
        self.last_output_time = time.time()

        self.state = config.STREAM_STATE_STARTING
        nb_stdout = nonblockingReadline(self.proc.stdout)
        nb_stderr = nonblockingReadline(self.proc.stderr)

        # while ffmpeg is running, theer has been output activity within a configurable
        # amount of time and stream state is not fault.
        while not self.proc.poll() and not self._inactivity_fault(
        ) and self.state in (config.STREAM_STATE_STARTING,
                             config.STREAM_STATE_PLAYING):

            logging.debug("get next io activity")
            line, video_chunk = None, None
            for (fd, evt) in plist.poll(2000):  # select on 3 sources
                if not (evt & select.POLLIN):
                    self.state = config.STREAM_STATE_FAULT
                    signals.publish(self.sf_topic, {
                        'error': 'SystemError',
                        'desc': 'Pipe I/O error'
                    })
                    break

                if fd == self.cmd_r:
                    self.state = config.STREAM_STATE_STOPPED
                    break

                elif fd == self.proc.stdout.fileno():
                    logging.debug("stdout line")
                    line = nb_stdout.readline()
                elif fd == self.proc.stderr.fileno():
                    logging.debug("stdout error")
                    line = nb_stderr.readline()
                else:
                    video_chunk = os.read(self.vout_r, 0xFFFF)

                if line:
                    self._line_proc(line)
                if video_chunk:
                    self._route_video(video_chunk)

        # shutdown ffmpeg and what for process to die so we
        # don't leave defunct process.
        logging.warning("existing ffmpeg loop state=%" % self.state)
        self.proc.kill()
        self.proc.communicate(b'')
        self.proc = None
 def _route_video(self, video_chunk):
     logging.debug("_route_video: %d bytes of video received" %
                   len(video_chunk))
     signals.publish(self.si_topic, video_chunk)
     self.state = config.STREAM_STATE_PLAYING
     self.last_output_time = time.time()
 def setup(self):
     signals.publish(config.STREAM_CREATE_TOPIC, self)