Beispiel #1
0
    def dar(self):
        if self.trackEntry.video:
            if (self.trackEntry.video.displayWidth
                    and self.trackEntry.video.displayHeight):
                return QQ(self.trackEntry.video.displayWidth,
                          self.trackEntry.video.displayHeight)

            return QQ(self.trackEntry.video.pixelWidth,
                      self.trackEntry.video.pixelHeight)
Beispiel #2
0
    def fgdata(self, index, obj):
        diff = self.editdata(index, obj)

        if diff is not None:
            if abs(diff) >= 2 / QQ(24000 / 1001):
                return self.white

            elif abs(diff) >= 1 / QQ(24000 / 1001):
                return self.red

            elif abs(diff) < 0.2 / QQ(24000 / 1001):
                return self.blue

            return self.fgcolor
Beispiel #3
0
    def bgdata(self, index, obj):
        diff = self.editdata(index, obj)

        if diff is not None and abs(diff) >= 2 / QQ(24000 / 1001):
            return self.red

        return self.bgcolor
Beispiel #4
0
    def __setattr__(self, attr, value):
        x265paramname = attr.rstrip("_").replace("_", "-")

        if value is None and x265paramname in x265params:
            self.x265params[x265paramname] = value

        elif ((isinstance(value, str) and x265paramname in x265strparams)
              or (isinstance(value, int) and not isinstance(value, bool)
                  and x265paramname in x265intparams) or
              (isinstance(value, float) and x265paramname in x265floatparams)
              or (isinstance(value, bool) and x265paramname in x265boolparams)
              or
              (isinstance(value, QQ) and x265paramname in x265rationalparams)):
            self.x265params[x265paramname] = value

        elif x265paramname in x265rationalparams:
            self.x265params[x265paramname] = QQ(value)

        elif x265paramname in x265floatparams:
            self.x265params[x265paramname] = float(value)

        elif x265paramname in x265intparams:
            self.x265params[x265paramname] = int(value)

        elif x265paramname in x265boolparams:
            self.x265params[x265paramname] = bool(value)

        elif x265paramname in x265strparams:
            self.x265params[x265paramname] = str(value)

        return object.__setattr__(self, attr, value)
Beispiel #5
0
    def _sendframe(self):
        if self._noMoreFrames:
            raise StopIteration

        try:
            frame = next(self._framesource)
        except StopIteration:
            self._success = True
            return self.stop()

        if isinstance(frame, av.AudioFrame):
            frame = aconvert(frame, self._encoder.format.name)
            frame.pts = None

        else:
            frame.pts = int(10**9*frame.pts*frame.time_base)

        frame.time_base = QQ(1, 10**9)

        if callable(self._notifyencode):
            self._notifyencode(frame)

        packets = self._encoder.encode(frame)
        self._packets.extend(packets)

        if frame is None:
            self.close()

        return len(packets)
Beispiel #6
0
    def __init__(self, codec, framesource, notifyencode=None,
                 logfile=None, **kwargs):
        if isinstance(codec, av.Codec):
            if not codec.is_encoder:
                raise TypeError("Codec object is not an encoder.")

            self._encoder = codec.create()

        else:
            self._encoder = av.CodecContext.create(codec, "w")

        for key, value in kwargs.items():
            if value is not None:
                setattr(self._encoder, key, value)

        if "time_base" not in kwargs:
            self._encoder.time_base = QQ(1, 10**9)

        self._framesource = framesource
        self._packets = deque()
        self._logfile = logfile
        self._notifyencode = notifyencode
        self._isopen = False
        self._packetsEncoded = 0
        self._streamSize = 0
        self._noMoreFrames = False
        self._success = False
        self._pts = 0
Beispiel #7
0
    def __init__(self,
                 src_start,
                 src_fps=QQ(24000, 1001),
                 pulldown=None,
                 pulldownoffset=0,
                 yblend=False,
                 uvblend=False,
                 prev=None,
                 next=None,
                 framecount=None,
                 parent=None):
        super().__init__(src_start=src_start,
                         prev=prev,
                         next=next,
                         parent=parent)
        self.src_fps = src_fps
        self.yblend = bool(yblend)
        self.uvblend = bool(uvblend)
        self.pulldown = str(pulldown).upper() if pulldown is not None else None

        if self.pulldown is not None:
            self.pulldownoffset = int(pulldownoffset) % self.old_blksize

        else:
            self.pulldownoffset = 0

        self._reverse_mapping = None
        self._reverse_mapping_head = None
        self._reverse_mapping_tail = None

        self._forward_matrix_blended = None
        self._reverse_matrix_blended = None
        self._reverse_matrix_blended_head = None
        self._reverse_matrix_blended_tail = None
        self._framecount = framecount
Beispiel #8
0
 def __init__(self,
              rate=QQ(24000, 1001),
              prev=None,
              next=None,
              parent=None):
     super().__init__(prev=prev, next=next, parent=parent)
     self.rate = rate
Beispiel #9
0
    def seteditdata(self, index, obj, value):
        K, zone = self.filter.zoneAt(obj)

        if value is None:
            zone.src_fps = QQ(24000, 1001)

        else:
            zone.src_fps = value
Beispiel #10
0
    def setcheckstate(self, index, obj, data):
        if obj == 0:
            return

        if self.checkstate(index, obj):
            self.filter.removeZoneAt(obj)

        else:
            self.filter.insertZoneAt(obj, src_fps=QQ(24000, 1001))
Beispiel #11
0
    def defaultDuration(self):
        if isinstance(self.trackEntry.defaultDuration, int):
            q, r = divmod(self.trackEntry.defaultDuration, 1000)

            if r % 111 in (0, 1):
                """Possible repeating digit. Will assume as such."""
                return 1000 * q + r + QQ(r // 111, 9)

            return self.trackEntry.defaultDuration
Beispiel #12
0
    def autoFrameRate(self, table):
        isdefault = (len(self.filter) == 1
                     and self.filter.start.src_fps == QQ(24000, 1001)
                     and self.filter.start.pulldown is None)

        if isdefault or QMessageBox.question(
                table, "Auto Frame Rate",
                "Current zone settings will be lost! Do you wish to proceed?",
                QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes:
            self.filter.autoframerate()
            table.contentsModified.emit()
Beispiel #13
0
    def setModelData(self, editor, model, index):
        value = editor.text()

        if regex.match(r"^\d+/\d+$", value):
            value = QQ(value)

        elif regex.match(r"^\d+$", value):
            value = int(value)

        else:
            value = float(value)

        model.setData(index, value, Qt.EditRole)
Beispiel #14
0
    def defaultDuration(self):
        if self.encoder:
            if self.type == "audio":
                if self.codec in ("aac", "libfdk_aac"):
                    return QQ(1024, self.rate)/self.time_base

                elif self.codec == "ac3":
                    return QQ(1536, self.rate)/self.time_base

                elif self.codec == "dca":
                    return QQ(512, self.rate)/self.time_base

                elif self.codec == "truehd":
                    return QQ(40, self.rate)/self.time_base

            elif self.filters and self.filters.defaultDuration is not None:
                return (self.filters.defaultDuration
                        * self.filters.time_base/self.time_base)

        source = self.source

        if source is not None and source.defaultDuration is not None:
            return source.defaultDuration*source.time_base/self.time_base
Beispiel #15
0
    def handleRateChanged(self, value):
        if not regex.match(r"^(\d+(?:\.\d+)?|\.\d+|\d+/\d+)$", value):
            return

        if regex.match(r"^\d+/\d+$", value):
            value = QQ(value)

        elif regex.match(r"^\d+$", value):
            value = int(value)

        else:
            value = float(value)

        self.filtercopy.rate = value
        self.isModified()
Beispiel #16
0
    def setSar(self, sar):
        if not regex.match(r"^(\d+(?:\.\d+)?|\.\d+|\d+/\d+)$", sar):
            return

        if regex.match(r"^\d+/\d+$", sar):
            sar = QQ(sar)

        elif regex.match(r"^\d+$", sar):
            sar = int(sar)

        else:
            sar = float(sar)

        self.filtercopy.sar = sar
        self.isModified()
    def updateChildGeometry(self, size):
        if (self.inputPreviewWindow.framesource is not None
                and self.outputPreviewWindow.framesource is not None):
            inputDar = self.inputPreviewWindow.dar
            outputDar = self.outputPreviewWindow.dar

            if (isinstance(inputDar, (QQ, int))
                    and isinstance(outputDar, (QQ, int))):
                ratio = QQ(inputDar, outputDar)
                self.layout().setColumnStretch(0, ratio.numerator)
                self.layout().setColumnStretch(1, ratio.denominator)

            else:
                ratio = inputDar / outputDar
                self.layout().setColumnStretch(0, int(1000 * ratio))
                self.layout().setColumnStretch(1, 1000)
Beispiel #18
0
 def __init__(self,
              zones=[],
              time_base=QQ(1, 10**9),
              start_pts_time=0,
              prev=None,
              next=None,
              notify_input=None,
              notify_output=None):
     super().__init__(zones=zones,
                      prev=prev,
                      next=next,
                      notify_input=notify_input,
                      notify_output=notify_output)
     self.time_base = time_base
     self._start_pts_time = start_pts_time
     self._columns = None
Beispiel #19
0
    def autoframerate(self):
        while len(self) > 1:
            self.removeZoneAt(self[1].src_start)

        dt = numpy.diff(self.prev.pts)
        n = 0
        fr = None

        while n < len(dt) - 1:
            if abs(dt[n:n + 2] - numpy.array([50, 33])).max() <= 1:
                if fr != QQ(24000, 1001):
                    fr = QQ(24000, 1001)
                    if n == 0:
                        self.start.src_fps = fr
                        self.start.pulldown = None

                    else:
                        self.insertZoneAt(n, src_fps=fr)

                n += 2

                while (n < len(dt) - 1 and
                       abs(dt[n:n + 2] - numpy.array([50, 33])).max() <= 1):
                    n += 2

            elif abs(dt[n] - 33) <= 1:
                if fr != QQ(30000, 1001):
                    fr = QQ(30000, 1001)

                    if n == 0:
                        self.start.src_fps = fr
                        self.start.pulldown = None

                    else:
                        self.insertZoneAt(n, src_fps=fr)

                n += 1

                while n < len(dt) - 1 and abs(dt[n] - 33).max() <= 1:
                    n += 1

            elif fr != QQ(24000, 1001):
                fr = QQ(24000, 1001)

                if n == 0:
                    self.start.src_fps = fr
                    self.start.pulldown = None

                else:
                    self.insertZoneAt(n, src_fps=fr)

                n += 1

            else:
                n += 1
Beispiel #20
0
    def __init__(self,
                 duration,
                 title="Untitled",
                 framecount=None,
                 time_base=QQ(1 / 1000),
                 keep=7200,
                 font=QFont("DejaVu Serif", 8),
                 parent=None):
        super(TrackStats, self).__init__(parent)
        self.setHidden(True)
        self.framecount = framecount
        self.duration = duration
        self.timestamps = []
        self.sizes = []
        self.byteswritten = 0
        self.packetsreceived = 0
        self.lastpts = 0
        self.keep = keep
        self.time_base = time_base
        self.font = font

        self.titleLabel = QLabel(title, self)
        self.titleLabel.setFont(self.font)

        self.frameCountLabel = QLabel(self)
        self.sizeLabel = QLabel(self)
        self.bitrateLabel = QLabel(self)
        self.timestampLabel = QLabel(self)
        self.etaLabel = QLabel(self)
        self.etaLabel.setHidden(True)

        self.frameCountLabel.setFont(self.font)
        self.sizeLabel.setFont(self.font)
        self.bitrateLabel.setFont(self.font)
        self.timestampLabel.setFont(self.font)
        self.etaLabel.setFont(self.font)
        self.reset()
Beispiel #21
0
def _convert_dict(d, stripnones=True):
    for oldkey in list(d.keys()):
        newkey = oldkey.rstrip("_").replace("_", "-")

        if newkey not in x265params:
            raise ValueError(f"Not a valid x265 parameter: {newkey}")

        value = d.pop(oldkey)

        if value is None:
            if not stripnones:
                d[newkey] = None

            continue

        if ((isinstance(value, str) and newkey in x265strparams)
                or (isinstance(value, int) and not isinstance(value, bool)
                    and newkey in x265intparams)
                or (isinstance(value, float) and newkey in x265floatparams)
                or (isinstance(value, bool) and newkey in x265boolparams)
                or (isinstance(value, QQ) and newkey in x265rationalparams)):
            d[newkey] = value

        elif newkey in x265rationalparams:
            d[newkey] = QQ(value)

        elif newkey in x265floatparams:
            d[newkey] = float(value)

        elif newkey in x265intparams:
            d[newkey] = int(value)

        elif newkey in x265boolparams:
            d[newkey] = bool(value)

        elif newkey in x265strparams:
            d[newkey] = str(value)
Beispiel #22
0
 def _fromBytes(cls, data, parent=None):
     numdata, dendata = parseVints(data)
     return cls(QQ(
         fromVint(numdata) - 2**(7 * len(numdata) - 1), fromVint(dendata)),
                parent=parent)
Beispiel #23
0
 def __setstate__(self, state):
     self.rate = state.get("rate", QQ(24000, 1001))
     super().__setstate__(state)
Beispiel #24
0
 def sar(self):
     if self.trackEntry.video:
         return self.dar / QQ(self.trackEntry.video.pixelWidth,
                              self.trackEntry.video.pixelHeight)
Beispiel #25
0
 def __setstate__(self, state):
     self.time_base = state.get("time_base", QQ(1, 10**9))
     super().__setstate__(state)
Beispiel #26
0
 def __init__(self, segments=[], time_base=QQ(1, 10**9), **kwargs):
     self.segments = list(map(tryweakref, segments))
     self.time_base = time_base
     super().__init__(**kwargs)
Beispiel #27
0
 def time_base(self):
     return QQ(1, 10**9)
Beispiel #28
0
 def setZoneValues(table, zone, src_fps=QQ(24000, 1001),
                   pulldown=None, pulldownoffset=0):
     zone.src_fps = src_fps
     zone.pulldown = pulldown
     zone.pulldownoffset = pulldownoffset
     table.contentsModified.emit()
Beispiel #29
0
    def __init__(
            self,
            framesource,
            # Pyav encoder context options
            width,
            height,
            sample_aspect_ratio=1,
            rate=QQ(24000, 1001),
            pix_fmt="yuv420p",
            time_base=None,
            preset=None,
            tune=None,
            forced_idr=None,

            # Quality, rate control and rate distortion options
            bitrate=None,
            qp=None,
            crf=None,
            lossless=None,

            # python-transcode
            notifyencode=None,
            logfile=None,
            **x265params):

        self._rate = rate
        _convert_dict(x265params)

        kwargs = dict(width=width,
                      height=height,
                      sample_aspect_ratio=sample_aspect_ratio,
                      rate=rate,
                      pix_fmt=pix_fmt,
                      time_base=time_base)

        options = {}

        if crf:
            options["crf"] = f"{crf:.2f}"
            print(f"        crf={crf:.2f}", file=logfile)

        elif bitrate:
            kwargs["bit_rate"] = int(1000 * bitrate)
            print(f"        bitrate={bitrate:,.2f}kbps", file=logfile)

        elif qp:
            x265params["qp"] = qp
            print(f"        qp={qp}", file=logfile)

        elif lossless:
            x265params["lossless"] = True
            print("        lossless", file=logfile)

        if preset:
            options["preset"] = preset
            print(f"        preset={preset}", file=logfile)

        if tune:
            options["tune"] = tune
            print(f"        tune={tune}", file=logfile)

        self._rfd, self._wfd = os.pipe()
        self._rf = os.fdopen(self._rfd, "r")
        self._wf = os.fdopen(self._wfd, "w")
        flag = fcntl.fcntl(self._rfd, fcntl.F_GETFL)
        fcntl.fcntl(self._rfd, fcntl.F_SETFL, flag | os.O_NONBLOCK)

        if rate:
            x265params["fps"] = rate

        x265params = OrderedDict([("preset", None), ("tune", None),
                                  ("pass", None), ("stats", None)],
                                 **x265params)

        x265params["csv"] = f"/dev/fd/{self._wfd}"
        x265params["csv-log-level"] = 1

        L = []

        for key, value in x265params.items():
            if value is True:
                L.append(f"{key}=1")
                print(f"        {key}", file=logfile)

            elif value is False:
                L.append(f"{key}=0")
                print(f"        no-{key}", file=logfile)

            elif isinstance(value, str):
                L.append(f"{key}={quote(value)}")

                if key != "csv":
                    print(f"        {key}={value}", file=logfile)

            elif isinstance(value, QQ):
                if key in x265colonrationalparams:
                    L.append(f"{key}={value.numerator}\\:{value.denominator}")

                if key in x265slashrationalparams:
                    L.append(f"{key}={value.numerator}/{value.denominator}")

                print(f"        {key}={value.numerator}/{value.denominator}",
                      file=logfile)

            elif value is not None:
                L.append(f"{key}={value}")

                if key != "csv-log-level":
                    print(f"        {key}={value}", file=logfile)

        if L:
            options["x265-params"] = ":".join(L)

        if options:
            kwargs["options"] = options

        self._statspattern = (r"(?P<encodeorder>\d+),"
                              r"\s+(?P<pict_type>[IBP])-SLICE,"
                              r"\s*(?P<displayorder>\d+),"
                              r"\s*(?P<qp>\d+(?:\.\d+)?),"
                              r"\s*(?P<bits>\d+),"
                              r"\s*(?P<scenecut>[01]),")

        self._statsbuffer = ""
        self._pktCount = {s: 0 for s in "IBP"}
        self._pktSizeSums = {s: 0 for s in "IBP"}
        self._pktQPSums = {s: 0 for s in "IBP"}
        self._pts = {}
        self._pass = x265params.get("pass")
        self._stats = x265params.get("stats")

        super().__init__("libx265",
                         framesource,
                         notifyencode=notifyencode,
                         logfile=logfile,
                         **kwargs)
Beispiel #30
0
    def createContextMenu(self, table, index, obj):
        menu = ZoneCol.createContextMenu(self, table, index, obj)
        menu.addSeparator()
        J, zone = self.filter.zoneAt(obj)

        menu.addAction(QAction(
            "&AA (24000/1001)", table,
            triggered=partial(self.setZoneValues, table=table, zone=zone)))

        menu.addAction(QAction(
            "AA (&30000/1001)", table,
            triggered=partial(
                self.setZoneValues, table=table, zone=zone,
                src_fps=QQ(30000, 1001))))

        menu.addAction(QAction(
            "A&B (24000/1001)", table,
            triggered=partial(
                self.setZoneValues, table=table, zone=zone, pulldown="AB")))

        menu.addSeparator()

        menu.addAction(QAction(
            "AAABBCCCDD(&0) (30000/1001)", table,
            triggered=partial(
                self.setZoneValues, table=table, zone=zone,
                src_fps=QQ(30000, 1001), pulldown="AAABBCCCDD",
                pulldownoffset=(zone.src_start - obj) % 5)))

        menu.addAction(QAction(
            "AAABBCCCDD(&1) (30000/1001)", table,
            triggered=partial(
                self.setZoneValues, table=table, zone=zone,
                src_fps=QQ(30000, 1001), pulldown="AAABBCCCDD",
                pulldownoffset=(1 + zone.src_start - obj) % 5)))

        menu.addAction(QAction(
            "AAABBCCCDD(&2) (30000/1001)", table,
            triggered=partial(
                self.setZoneValues, table=table, zone=zone,
                src_fps=QQ(30000, 1001), pulldown="AAABBCCCDD",
                pulldownoffset=(2 + zone.src_start - obj) % 5)))

        menu.addAction(QAction(
            "AAABBCCCDD(&3) (30000/1001)", table,
            triggered=partial(
                self.setZoneValues, table=table, zone=zone,
                src_fps=QQ(30000, 1001), pulldown="AAABBCCCDD",
                pulldownoffset=(3 + zone.src_start - obj) % 5)))

        menu.addAction(QAction(
            "AAABBCCCDD(&4) (30000/1001)", table,
            triggered=partial(
                self.setZoneValues, table=table, zone=zone,
                src_fps=QQ(30000, 1001), pulldown="AAABBCCCDD",
                pulldownoffset=(4 + zone.src_start - obj) % 5)))

        menu.addSeparator()

        menu.addAction(QAction(
            "AAABBCC&DDD (30000/1001)", table,
            triggered=partial(
                self.setZoneValues, table=table, zone=zone,
                src_fps=QQ(30000, 1001), pulldown="AAABBCCDDD",
                pulldownoffset=0)))

        menu.addAction(QAction(
            "AAABBCCDD&E (30000/1001)", table,
            triggered=partial(
                self.setZoneValues, table=table, zone=zone,
                src_fps=QQ(30000, 1001), pulldown="AAABBCCDDE",
                pulldownoffset=0)))

        menu.addSeparator()

        menu.addAction(QAction(
            "Auto Frame Rate", table,
            triggered=partial(self.autoFrameRate, table=table)))
        return menu