예제 #1
0
 def _on_warning(self, _bus, message):
     assert message.type == Gst.MessageType.WARNING
     if self.sink_pipeline is not None:
         Gst.debug_bin_to_dot_file_with_ts(
             self.sink_pipeline, Gst.DebugGraphDetails.ALL, "WARNING")
     err, dbg = message.parse_warning()
     warn("%s: %s\n%s\n" % (err, err.message, dbg))
예제 #2
0
 def restart_source(self, *_args):
     warn("Attempting to recover from video loss: "
          "Stopping source pipeline and waiting 5s...")
     self.source_pipeline.set_state(Gst.State.NULL)
     self.source_pipeline = None
     GObjectTimeout(5, self.start_source).start()
     return False  # stop the timeout from running again
예제 #3
0
 def restart_source(self, *_args):
     warn("Attempting to recover from video loss: "
          "Stopping source pipeline and waiting 5s...")
     self.source_pipeline.set_state(Gst.State.NULL)
     self.source_pipeline = None
     GObjectTimeout(5, self.start_source).start()
     return False  # stop the timeout from running again
예제 #4
0
 def start_source(self):
     if self.tearing_down:
         return False
     warn("Restarting source pipeline...")
     self.create_source_pipeline()
     self.set_source_pipeline_playing()
     warn("Restarted source pipeline")
     return False  # stop the timeout from running again
예제 #5
0
 def start_source(self):
     if self.tearing_down:
         return False
     warn("Restarting source pipeline...")
     self.create_source_pipeline()
     self.set_source_pipeline_playing()
     warn("Restarted source pipeline")
     if self.restart_source_enabled:
         self.underrun_timeout.start()
     return False  # stop the timeout from running again
예제 #6
0
    def _push_sample(self, sample):
        # Calculate whether we need to draw any annotations on the output video.
        now = sample.time
        annotations = []
        with self.annotations_lock:
            # Remove expired annotations
            self.text_annotations = [x for x in self.text_annotations
                                     if now < x.end_time]
            current_texts = [x for x in self.text_annotations if x.time <= now]
            for annotation in list(self.annotations):
                if annotation.time == now:
                    annotations.append(annotation)
                if now >= annotation.time:
                    self.annotations.remove(annotation)

        sample = gst_sample_make_writable(sample)
        img = array_from_sample(sample, readwrite=True)
        # Text:
        _draw_text(
            img,
            datetime.datetime.fromtimestamp(now).strftime("%H:%M:%S.%f")[:-4],
            (10, 30), (255, 255, 255))
        for i, x in enumerate(reversed(current_texts)):
            origin = (10, (i + 2) * 30)
            age = float(now - x.time) / 3
            color = (native(int(255 * max([1 - age, 0.5]))).__int__(),) * 3
            _draw_text(img, x.text, origin, color)

        # Regions:
        for annotation in annotations:
            _draw_annotation(img, annotation)

        APPSRC_LIMIT_BYTES = 100 * 1024 * 1024  # 100MB
        if self.appsrc.props.current_level_bytes > APPSRC_LIMIT_BYTES:
            # appsrc is backed-up, perhaps something's gone wrong.  We don't
            # want to use up all RAM, so let's drop the buffer on the floor.
            if not self._appsrc_was_full:
                warn("sink pipeline appsrc is full, dropping buffers from now "
                     "on")
                self._appsrc_was_full = True
            return
        elif self._appsrc_was_full:
            debug("sink pipeline appsrc no longer full, pushing buffers again")
            self._appsrc_was_full = False

        self.appsrc.props.caps = sample.get_caps()
        self.appsrc.emit("push-buffer", sample.get_buffer())
        self._sample_count += 1
예제 #7
0
    def on_new_sample(self, appsink):
        sample = appsink.emit("pull-sample")

        running_time = sample.get_segment().to_running_time(
            Gst.Format.TIME, sample.get_buffer().pts)
        sample.time = float(appsink.base_time + running_time) / 1e9

        if (sample.time > self.init_time + 31536000 or
                sample.time < self.init_time - 31536000):  # 1 year
            warn("Received frame with suspicious timestamp: %f. Check your "
                 "source-pipeline configuration." % sample.time)

        frame = array_from_sample(sample)
        frame.flags.writeable = False

        # See also: logging.draw_on
        frame._draw_sink = weakref.ref(self._sink_pipeline)  # pylint: disable=protected-access
        self.tell_user_thread(frame)
        self._sink_pipeline.on_sample(sample)
        return Gst.FlowReturn.OK
예제 #8
0
    def on_new_sample(self, appsink):
        sample = appsink.emit("pull-sample")

        running_time = sample.get_segment().to_running_time(
            Gst.Format.TIME, sample.get_buffer().pts)
        sample.time = (
            float(appsink.base_time + running_time) / 1e9)

        if (sample.time > self.init_time + 31536000 or
                sample.time < self.init_time - 31536000):  # 1 year
            warn("Received frame with suspicious timestamp: %f. Check your "
                 "source-pipeline configuration." % sample.time)

        frame = array_from_sample(sample)
        frame.flags.writeable = False

        # See also: logging.draw_on
        frame._draw_sink = weakref.ref(self._sink_pipeline)  # pylint: disable=protected-access
        self.tell_user_thread(frame)
        self._sink_pipeline.on_sample(sample)
        return Gst.FlowReturn.OK
예제 #9
0
 def on_warning(self, _bus, message):
     assert message.type == Gst.MessageType.WARNING
     Gst.debug_bin_to_dot_file_with_ts(
         self.source_pipeline, Gst.DebugGraphDetails.ALL, "WARNING")
     err, dbg = message.parse_warning()
     warn("%s: %s\n%s\n" % (err, err.message, dbg))
예제 #10
0
 def on_eos_from_source_pipeline(self, _bus, _message):
     if not self.tearing_down:
         warn("Got EOS from source pipeline")
         self.restart_source()
예제 #11
0
 def on_eos_from_source_pipeline(self, _bus, _message):
     if not self.tearing_down:
         warn("Got EOS from source pipeline")
         self.restart_source()
예제 #12
0
def new_device_under_test_from_config(parsed_args=None,
                                      transformation_pipeline=None):
    """
    `parsed_args` if present should come from calling argparser().parse_args().
    """
    from _stbt.control import uri_to_control

    if parsed_args is None:
        args = argparser().parse_args([])
    else:
        args = parsed_args

    if args.source_pipeline is None:
        args.source_pipeline = get_config('global', 'source_pipeline')
    if args.sink_pipeline is None:
        args.sink_pipeline = get_config('global', 'sink_pipeline')
    if args.control is None:
        args.control = get_config('global', 'control')
    if args.save_video is None:
        args.save_video = False
    if args.restart_source is None:
        args.restart_source = get_config('global',
                                         'restart_source',
                                         type_=bool)
    if transformation_pipeline is None:
        transformation_pipeline = get_config('global',
                                             'transformation_pipeline')
    source_teardown_eos = get_config('global',
                                     'source_teardown_eos',
                                     type_=bool)
    use_old_threading_behaviour = get_config('global',
                                             'use_old_threading_behaviour',
                                             type_=bool)
    if use_old_threading_behaviour:
        warn(
            dedent("""\
            global.use_old_threading_behaviour is enabled.  This is intended as
            a stop-gap measure to allow upgrading to stb-tester v28. We
            recommend porting functions that depend on stbt.get_frame()
            returning consecutive frames on each call to use stbt.frames()
            instead.  This should make your functions usable from multiple
            threads.

            If porting to stbt.frames is not suitable please let us know on
            https://github.com/stb-tester/stb-tester/pull/449 otherwise this
            configuration option will be removed in a future release of
            stb-tester.
            """))

    display = [None]

    def raise_in_user_thread(exception):
        display[0].tell_user_thread(exception)

    mainloop = _mainloop()

    if not args.sink_pipeline and not args.save_video:
        sink_pipeline = NoSinkPipeline()
    else:
        sink_pipeline = SinkPipeline(  # pylint: disable=redefined-variable-type
            args.sink_pipeline, raise_in_user_thread, args.save_video)

    display[0] = Display(args.source_pipeline, sink_pipeline,
                         args.restart_source, transformation_pipeline,
                         source_teardown_eos)
    return DeviceUnderTest(
        display=display[0],
        control=uri_to_control(args.control, display[0]),
        sink_pipeline=sink_pipeline,
        mainloop=mainloop,
        use_old_threading_behaviour=use_old_threading_behaviour)