Example #1
0
 def setup_pipeline(self, scores, width, height, src_format):
     """
         Given a list of pipeline options ordered by their score
         and an input format (width, height and source pixel format),
         we try to create a working pipeline, trying each option
         until one succeeds.
     """
     start = time.time()
     debug("setup_pipeline%s", (scores, width, height, src_format))
     for option in scores:
         try:
             _, csc_spec, enc_in_format, encoder_spec = option
             debug("setup_pipeline: trying %s", option)
             speed = self.get_current_speed()
             quality = self.get_current_quality()
             if csc_spec:
                 #TODO: no need to OR encoder mask if we are scaling...
                 self.width_mask = csc_spec.width_mask & encoder_spec.width_mask
                 self.height_mask = csc_spec.height_mask & encoder_spec.height_mask
                 csc_width = width & self.width_mask
                 csc_height = height & self.height_mask
                 enc_width, enc_height = self.get_encoder_dimensions(
                     csc_spec, encoder_spec, csc_width, csc_height)
                 #csc speed is not very important compared to encoding speed,
                 #so make sure it never degrades quality
                 csc_speed = min(speed, 100 - quality / 2.0)
                 csc_start = time.time()
                 self._csc_encoder = csc_spec.codec_class()
                 self._csc_encoder.init_context(csc_width, csc_height,
                                                src_format, enc_width,
                                                enc_height, enc_in_format,
                                                csc_speed)
                 csc_end = time.time()
                 debug("setup_pipeline: csc=%s, info=%s, setup took %.2fms",
                       self._csc_encoder, self._csc_encoder.get_info(),
                       (csc_end - csc_start) * 1000.0)
             else:
                 #use the encoder's mask directly since that's all we have to worry about!
                 self.width_mask = encoder_spec.width_mask
                 self.height_mask = encoder_spec.height_mask
                 enc_width = width & self.width_mask
                 enc_height = height & self.height_mask
             enc_start = time.time()
             self._video_encoder = encoder_spec.codec_class()
             self._video_encoder.init_context(enc_width, enc_height,
                                              enc_in_format, quality, speed,
                                              self.encoding_options)
             enc_end = time.time()
             debug(
                 "setup_pipeline: video encoder=%s, info: %s, setup took %.2fms",
                 self._video_encoder, self._video_encoder.get_info(),
                 (enc_end - enc_start) * 1000.0)
             return True
         except:
             log.warn("setup_pipeline failed for %s", option, exc_info=True)
     end = time.time()
     debug("setup_pipeline(..) failed! took %.2fms", (end - start) * 1000.0)
     return False
Example #2
0
    def do_check_pipeline(self, encoding, width, height, src_format):
        """
            Checks that the current pipeline is still valid
            for the given input. If not, close it and make a new one.
        """
        #must be called with video lock held!
        if self._video_encoder is None:
            return False

        if self._csc_encoder:
            csc_width = width & self.width_mask
            csc_height = height & self.height_mask
            if self._csc_encoder.get_src_format()!=src_format:
                debug("check_pipeline csc: switching source format from %s to %s",
                                            self._csc_encoder.get_src_format(), src_format)
                return False
            elif self._csc_encoder.get_src_width()!=csc_width or self._csc_encoder.get_src_height()!=csc_height:
                debug("check_pipeline csc: window dimensions have changed from %sx%s to %sx%s, csc info=%s",
                                            self._csc_encoder.get_src_width(), self._csc_encoder.get_src_height(), csc_width, csc_height, self._csc_encoder.get_info())
                return False
            elif self._csc_encoder.get_dst_format()!=self._video_encoder.get_src_format():
                log.warn("check_pipeline csc: intermediate format mismatch: %s vs %s, csc info=%s",
                                            self._csc_encoder.get_dst_format(), self._video_encoder.get_src_format(), self._csc_encoder.get_info())
                return False

            #encoder will take its input from csc:
            encoder_src_width = self._csc_encoder.get_dst_width()
            encoder_src_height = self._csc_encoder.get_dst_height()
        else:
            #direct to video encoder without csc:
            encoder_src_width = width & self.width_mask
            encoder_src_height = height & self.height_mask

            if self._video_encoder.get_src_format()!=src_format:
                debug("check_pipeline video: invalid source format %s, expected %s",
                                                self._video_encoder.get_src_format(), src_format)
                return False

        if self._video_encoder.get_encoding()!=encoding:
            debug("check_pipeline video: invalid encoding %s, expected %s",
                                            self._video_encoder.get_encoding(), encoding)
            return False
        elif self._video_encoder.get_width()!=encoder_src_width or self._video_encoder.get_height()!=encoder_src_height:
            debug("check_pipeline video: window dimensions have changed from %sx%s to %sx%s",
                                            self._video_encoder.get_width(), self._video_encoder.get_height(), encoder_src_width, encoder_src_height)
            return False
        return True
Example #3
0
 def setup_pipeline(self, scores, width, height, src_format):
     """
         Given a list of pipeline options ordered by their score
         and an input format (width, height and source pixel format),
         we try to create a working pipeline, trying each option
         until one succeeds.
     """
     assert width>0 and height>0, "invalid dimensions: %sx%s" % (width, height)
     start = time.time()
     debug("setup_pipeline%s", (scores, width, height, src_format))
     for option in scores:
         try:
             _, csc_spec, enc_in_format, encoder_spec = option
             debug("setup_pipeline: trying %s", option)
             scaling = self.calculate_scaling(width, height, encoder_spec.max_w, encoder_spec.max_h)
             encoder_scaling = scaling
             speed = self.get_current_speed()
             quality = self.get_current_quality()
             min_w = 1
             min_h = 1
             max_w = 16384
             max_h = 16384
             if csc_spec:
                 #TODO: no need to OR encoder mask if we are scaling...
                 self.width_mask = csc_spec.width_mask & encoder_spec.width_mask
                 self.height_mask = csc_spec.height_mask & encoder_spec.height_mask
                 min_w = max(min_w, csc_spec.min_w)
                 min_h = max(min_h, csc_spec.min_h)
                 max_w = min(max_w, csc_spec.max_w)
                 max_h = min(max_h, csc_spec.max_h)
                 csc_width = width & self.width_mask
                 csc_height = height & self.height_mask
                 enc_width, enc_height = self.get_encoder_dimensions(csc_spec, encoder_spec, csc_width, csc_height, scaling)
                 encoder_scaling = (1, 1)
                 #csc speed is not very important compared to encoding speed,
                 #so make sure it never degrades quality
                 csc_speed = min(speed, 100-quality/2.0)
                 csc_start = time.time()
                 self._csc_encoder = csc_spec.codec_class()
                 self._csc_encoder.init_context(csc_width, csc_height, src_format,
                                                       enc_width, enc_height, enc_in_format, csc_speed)
                 csc_end = time.time()
                 debug("setup_pipeline: csc=%s, info=%s, setup took %.2fms",
                       self._csc_encoder, self._csc_encoder.get_info(), (csc_end-csc_start)*1000.0)
             else:
                 #use the encoder's mask directly since that's all we have to worry about!
                 self.width_mask = encoder_spec.width_mask
                 self.height_mask = encoder_spec.height_mask
                 #restrict limits:
                 min_w = max(min_w, encoder_spec.min_w)
                 min_h = max(min_h, encoder_spec.min_h)
                 max_w = min(max_w, encoder_spec.max_w)
                 max_h = min(max_h, encoder_spec.max_h)
                 enc_width = width & self.width_mask
                 enc_height = height & self.height_mask
                 if encoder_scaling!=(1,1) and not encoder_spec.can_scale:
                     debug("scaling is now enabled, so skipping %s", encoder_spec)
                     continue
             if width<=0 or height<=0:
                 #log.warn("skipping invalid dimensions..")
                 continue
             enc_start = time.time()
             self._video_encoder = encoder_spec.codec_class()
             self._video_encoder.init_context(enc_width, enc_height, enc_in_format, encoder_spec.encoding, quality, speed, encoder_scaling, self.encoding_options)
             #record new actual limits:
             self.actual_scaling = scaling
             self.min_w = min_w
             self.min_h = min_h
             self.max_w = max_w
             self.max_h = max_h
             enc_end = time.time()
             debug("setup_pipeline: video encoder=%s, info: %s, setup took %.2fms",
                     self._video_encoder, self._video_encoder.get_info(), (enc_end-enc_start)*1000.0)
             return  True
         except TransientCodecException, e:
             log.warn("setup_pipeline failed for %s: %s", option, e)
             self.cleanup_codecs()
         except:
Example #4
0
                self._video_encoder.init_context(enc_width, enc_height, enc_in_format, encoder_spec.encoding, quality, speed, encoder_scaling, self.encoding_options)
                #record new actual limits:
                self.actual_scaling = scaling
                self.min_w = min_w
                self.min_h = min_h
                self.max_w = max_w
                self.max_h = max_h
                enc_end = time.time()
                debug("setup_pipeline: video encoder=%s, info: %s, setup took %.2fms",
                        self._video_encoder, self._video_encoder.get_info(), (enc_end-enc_start)*1000.0)
                return  True
            except TransientCodecException, e:
                log.warn("setup_pipeline failed for %s: %s", option, e)
                self.cleanup_codecs()
            except:
                log.warn("setup_pipeline failed for %s", option, exc_info=True)
                self.cleanup_codecs()
        end = time.time()
        debug("setup_pipeline(..) failed! took %.2fms", (end-start)*1000.0)
        return False


    def video_encode(self, encoding, image, options):
        """
            This method is used by make_data_packet to encode frames using video encoders.
            Video encoders only deal with fixed dimensions,
            so we must clean and reinitialize the encoder if the window dimensions
            has changed.
            Since this runs in the non-UI thread 'data_to_packet', we must
            use the '_lock' to prevent races.
        """
Example #5
0
 def setup_pipeline(self, scores, width, height, src_format):
     """
         Given a list of pipeline options ordered by their score
         and an input format (width, height and source pixel format),
         we try to create a working pipeline, trying each option
         until one succeeds.
     """
     assert width > 0 and height > 0, "invalid dimensions: %sx%s" % (width,
                                                                     height)
     start = time.time()
     debug("setup_pipeline%s", (scores, width, height, src_format))
     for option in scores:
         try:
             _, csc_spec, enc_in_format, encoder_spec = option
             debug("setup_pipeline: trying %s", option)
             scaling = self.calculate_scaling(width, height,
                                              encoder_spec.max_w,
                                              encoder_spec.max_h)
             encoder_scaling = scaling
             speed = self.get_current_speed()
             quality = self.get_current_quality()
             min_w = 1
             min_h = 1
             max_w = 16384
             max_h = 16384
             if csc_spec:
                 #TODO: no need to OR encoder mask if we are scaling...
                 self.width_mask = csc_spec.width_mask & encoder_spec.width_mask
                 self.height_mask = csc_spec.height_mask & encoder_spec.height_mask
                 min_w = max(min_w, csc_spec.min_w)
                 min_h = max(min_h, csc_spec.min_h)
                 max_w = min(max_w, csc_spec.max_w)
                 max_h = min(max_h, csc_spec.max_h)
                 csc_width = width & self.width_mask
                 csc_height = height & self.height_mask
                 enc_width, enc_height = self.get_encoder_dimensions(
                     csc_spec, encoder_spec, csc_width, csc_height, scaling)
                 encoder_scaling = (1, 1)
                 #csc speed is not very important compared to encoding speed,
                 #so make sure it never degrades quality
                 csc_speed = min(speed, 100 - quality / 2.0)
                 csc_start = time.time()
                 self._csc_encoder = csc_spec.codec_class()
                 self._csc_encoder.init_context(csc_width, csc_height,
                                                src_format, enc_width,
                                                enc_height, enc_in_format,
                                                csc_speed)
                 csc_end = time.time()
                 debug("setup_pipeline: csc=%s, info=%s, setup took %.2fms",
                       self._csc_encoder, self._csc_encoder.get_info(),
                       (csc_end - csc_start) * 1000.0)
             else:
                 #use the encoder's mask directly since that's all we have to worry about!
                 self.width_mask = encoder_spec.width_mask
                 self.height_mask = encoder_spec.height_mask
                 #restrict limits:
                 min_w = max(min_w, encoder_spec.min_w)
                 min_h = max(min_h, encoder_spec.min_h)
                 max_w = min(max_w, encoder_spec.max_w)
                 max_h = min(max_h, encoder_spec.max_h)
                 enc_width = width & self.width_mask
                 enc_height = height & self.height_mask
                 if encoder_scaling != (1,
                                        1) and not encoder_spec.can_scale:
                     debug("scaling is now enabled, so skipping %s",
                           encoder_spec)
                     continue
             if width <= 0 or height <= 0:
                 #log.warn("skipping invalid dimensions..")
                 continue
             enc_start = time.time()
             self._video_encoder = encoder_spec.codec_class()
             self._video_encoder.init_context(enc_width, enc_height,
                                              enc_in_format,
                                              encoder_spec.encoding,
                                              quality, speed,
                                              encoder_scaling,
                                              self.encoding_options)
             #record new actual limits:
             self.actual_scaling = scaling
             self.min_w = min_w
             self.min_h = min_h
             self.max_w = max_w
             self.max_h = max_h
             enc_end = time.time()
             debug(
                 "setup_pipeline: video encoder=%s, info: %s, setup took %.2fms",
                 self._video_encoder, self._video_encoder.get_info(),
                 (enc_end - enc_start) * 1000.0)
             return True
         except TransientCodecException, e:
             log.warn("setup_pipeline failed for %s: %s", option, e)
             self.cleanup_codecs()
         except:
Example #6
0
    def do_check_pipeline(self, encoding, width, height, src_format):
        """
            Checks that the current pipeline is still valid
            for the given input. If not, close it and make a new one.
        """
        #must be called with video lock held!
        if self._video_encoder is None:
            return False

        if self._csc_encoder:
            csc_width = width & self.width_mask
            csc_height = height & self.height_mask
            if self._csc_encoder.get_src_format() != src_format:
                debug(
                    "check_pipeline csc: switching source format from %s to %s",
                    self._csc_encoder.get_src_format(), src_format)
                return False
            elif self._csc_encoder.get_src_width(
            ) != csc_width or self._csc_encoder.get_src_height() != csc_height:
                debug(
                    "check_pipeline csc: window dimensions have changed from %sx%s to %sx%s, csc info=%s",
                    self._csc_encoder.get_src_width(),
                    self._csc_encoder.get_src_height(), csc_width, csc_height,
                    self._csc_encoder.get_info())
                return False
            elif self._csc_encoder.get_dst_format(
            ) != self._video_encoder.get_src_format():
                log.warn(
                    "check_pipeline csc: intermediate format mismatch: %s vs %s, csc info=%s",
                    self._csc_encoder.get_dst_format(),
                    self._video_encoder.get_src_format(),
                    self._csc_encoder.get_info())
                return False

            #encoder will take its input from csc:
            encoder_src_width = self._csc_encoder.get_dst_width()
            encoder_src_height = self._csc_encoder.get_dst_height()
        else:
            #direct to video encoder without csc:
            encoder_src_width = width & self.width_mask
            encoder_src_height = height & self.height_mask

            if self._video_encoder.get_src_format() != src_format:
                debug(
                    "check_pipeline video: invalid source format %s, expected %s",
                    self._video_encoder.get_src_format(), src_format)
                return False

        if self._video_encoder.get_encoding() != encoding:
            debug("check_pipeline video: invalid encoding %s, expected %s",
                  self._video_encoder.get_encoding(), encoding)
            return False
        elif self._video_encoder.get_width(
        ) != encoder_src_width or self._video_encoder.get_height(
        ) != encoder_src_height:
            debug(
                "check_pipeline video: window dimensions have changed from %sx%s to %sx%s",
                self._video_encoder.get_width(),
                self._video_encoder.get_height(), encoder_src_width,
                encoder_src_height)
            return False
        return True
Example #7
0
                self.actual_scaling = scaling
                self.min_w = min_w
                self.min_h = min_h
                self.max_w = max_w
                self.max_h = max_h
                enc_end = time.time()
                debug(
                    "setup_pipeline: video encoder=%s, info: %s, setup took %.2fms",
                    self._video_encoder, self._video_encoder.get_info(),
                    (enc_end - enc_start) * 1000.0)
                return True
            except TransientCodecException, e:
                log.warn("setup_pipeline failed for %s: %s", option, e)
                self.cleanup_codecs()
            except:
                log.warn("setup_pipeline failed for %s", option, exc_info=True)
                self.cleanup_codecs()
        end = time.time()
        debug("setup_pipeline(..) failed! took %.2fms", (end - start) * 1000.0)
        return False

    def video_encode(self, encoding, image, options):
        """
            This method is used by make_data_packet to encode frames using video encoders.
            Video encoders only deal with fixed dimensions,
            so we must clean and reinitialize the encoder if the window dimensions
            has changed.
            Since this runs in the non-UI thread 'data_to_packet', we must
            use the '_lock' to prevent races.
        """
        debug("video_encode%s", (encoding, image, options))
Example #8
0
 def setup_pipeline(self, scores, width, height, src_format):
     """
         Given a list of pipeline options ordered by their score
         and an input format (width, height and source pixel format),
         we try to create a working pipeline, trying each option
         until one succeeds.
     """
     start = time.time()
     debug("setup_pipeline%s", (scores, width, height, src_format))
     for option in scores:
         try:
             _, csc_spec, enc_in_format, encoder_spec = option
             debug("setup_pipeline: trying %s", option)
             speed = self.get_current_speed()
             quality = self.get_current_quality()
             if csc_spec:
                 # TODO: no need to OR encoder mask if we are scaling...
                 self.width_mask = csc_spec.width_mask & encoder_spec.width_mask
                 self.height_mask = csc_spec.height_mask & encoder_spec.height_mask
                 csc_width = width & self.width_mask
                 csc_height = height & self.height_mask
                 enc_width, enc_height = self.get_encoder_dimensions(csc_spec, encoder_spec, csc_width, csc_height)
                 # csc speed is not very important compared to encoding speed,
                 # so make sure it never degrades quality
                 csc_speed = min(speed, 100 - quality / 2.0)
                 csc_start = time.time()
                 self._csc_encoder = csc_spec.codec_class()
                 self._csc_encoder.init_context(
                     csc_width, csc_height, src_format, enc_width, enc_height, enc_in_format, csc_speed
                 )
                 csc_end = time.time()
                 debug(
                     "setup_pipeline: csc=%s, info=%s, setup took %.2fms",
                     self._csc_encoder,
                     self._csc_encoder.get_info(),
                     (csc_end - csc_start) * 1000.0,
                 )
             else:
                 # use the encoder's mask directly since that's all we have to worry about!
                 self.width_mask = encoder_spec.width_mask
                 self.height_mask = encoder_spec.height_mask
                 enc_width = width & self.width_mask
                 enc_height = height & self.height_mask
             enc_start = time.time()
             self._video_encoder = encoder_spec.codec_class()
             self._video_encoder.init_context(
                 enc_width, enc_height, enc_in_format, quality, speed, self.encoding_options
             )
             enc_end = time.time()
             debug(
                 "setup_pipeline: video encoder=%s, info: %s, setup took %.2fms",
                 self._video_encoder,
                 self._video_encoder.get_info(),
                 (enc_end - enc_start) * 1000.0,
             )
             return True
         except:
             log.warn("setup_pipeline failed for %s", option, exc_info=True)
     end = time.time()
     debug("setup_pipeline(..) failed! took %.2fms", (end - start) * 1000.0)
     return False