Exemplo n.º 1
0
def makeAudioEncodeBin(config, analysis, tag, withRateControl=True, pipelineInfo=None, logger=None):
    logger = logger or log
    pipelineParts = list()
    bin = gst.Bin()

    # input queue element
    inqueue = gst.element_factory_make("queue", "audioinqueue-%s" % tag)
    # Cannot specify max_size_time property because of some buggy buffers
    # with invalid time that make the queue lock
    inqueue.props.max_size_time = 0
    inqueue.props.max_size_buffers = 200
    pipelineParts.append("queue")

    # audiorate element
    if withRateControl:
        rate = gst.element_factory_make("audiorate", "audiorate-%s" % tag)
        # Add a tolerance of 20ms to audiorate to fix cracking audio
        if gstreamer.element_has_property(rate, "tolerance"):
            rate.set_property("tolerance", DEFAULT_TOLERANCE)
        pipelineParts.append("audiorate")
    else:
        rate = None

    # audioconvert element
    convert = gst.element_factory_make("audioconvert", "audioconvert-%s" % tag)
    pipelineParts.append("audioconvert")

    # audioresample element
    # Use legacyresample if available because after 0.10.22 the old
    # audioresample element got renamed to legacyresample and replaced
    # by speexresample that cause audio/video synchronization issues.
    resamplerName = "audioresample"
    if gstreamer.element_factory_exists("legacyresample"):
        resamplerName = "legacyresample"
    if config.audioResampler:
        if gstreamer.element_factory_exists(config.audioResampler):
            resamplerName = config.audioResampler
        else:
            logger.warning("Audio resampler %s doesn't exist, defaulting to %s", config.audioResampler, resamplerName)
    resample = gst.element_factory_make(resamplerName, "%s-%s" % (resamplerName, tag))
    pipelineParts.append(resamplerName)

    # capsfilter element
    capsfilter = gst.element_factory_make("capsfilter", "audiocapsfilter-%s" % tag)
    # Because the analysis not reliably give channel
    # and rate info, do not not rely on it.
    if config.audioRate or config.audioChannels:
        capsList = []
        if config.audioRate:
            capsList.append("rate=%d" % config.audioRate)
        elif analysis.audioRate:
            capsList.append("rate=%d" % analysis.audioRate)
        if config.audioChannels:
            capsList.append("channels=%d" % config.audioChannels)
        elif analysis.audioChannels:
            capsList.append("channels=%d" % analysis.audioChannels)
        caps = ", ".join(capsList)
        if caps:
            fullcaps = "audio/x-raw-int, %s;audio/x-raw-float, %s" % (caps, caps)
            logger.debug("Audio capsfilter: '%s'", fullcaps)
            pipelineParts.append("'%s'" % fullcaps)
            capsfilter.props.caps = gst.caps_from_string(fullcaps)
        else:
            logger.debug("No audio capsfilter")

    # encoder elements
    encode = gstutils.parse_bin_from_description(config.audioEncoder, True)
    pipelineParts.extend(map(str.strip, config.audioEncoder.split("!")))

    # output queue element
    outqueue = gst.element_factory_make("queue", "audioutqueue-%s" % tag)
    outqueue.props.max_size_time = gst.SECOND * 20
    outqueue.props.max_size_buffers = 0
    pipelineParts.append("queue")

    if rate:
        bin.add(inqueue, rate, convert, resample, capsfilter, encode, outqueue)
        gst.element_link_many(inqueue, rate, convert, resample, capsfilter, encode, outqueue)
    else:
        bin.add(inqueue, convert, resample, capsfilter, encode, outqueue)
        gst.element_link_many(inqueue, convert, resample, capsfilter, encode, outqueue)

    bin.add_pad(gst.GhostPad("sink", inqueue.get_pad("sink")))
    bin.add_pad(gst.GhostPad("src", outqueue.get_pad("src")))

    pipelineDesc = " ! ".join(pipelineParts)
    logger.debug("Audio pipeline: %s", pipelineDesc)

    if pipelineInfo != None:
        pipelineInfo["audio"] = pipelineDesc

    return bin
Exemplo n.º 2
0
    def generate(self):
        if self._deferred:
            return self._deferred
        self._deferred = defer.Deferred()
        self._deferred.addBoth(self.__bbShutdownPipeline)
        try:
            if not self.path:
                handle, self.path =  tempfile.mkstemp()
                os.close(handle)
                self._deferred.addErrback(self.__ebRemoveTempFile)

            if self.videoCodec:
                if isinstance(self.videoRate, (int, long)):
                    videoRate = (self.videoRate, 1)
                    vRate = float(self.videoRate)
                elif isinstance(self.videoRate, (list, tuple)):
                    videoRate = self.videoRate
                    vRate = float(videoRate[0]) / float(videoRate[1])
                aBlockSize = int(round(self.audioRate / vRate))
                buffCount = int(round(vRate * self.duration)) + 1
            else:
                aBlockSize = int(round(self.audioRate / 10))
                buffCount = int(round(10 * self.duration)) + 1
            self._pipeline = gst.Pipeline("GenMediaFile")

            filesink = gst.element_factory_make("filesink")
            filesink.props.location = self.path
            self._pipeline.add(filesink)
            if self.muxer:
                muxer = gst.parse_launch(self.muxer)
                self._pipeline.add(muxer)
                muxer.link(filesink)
            else:
                muxer = filesink

            if self.videoCodec:
                vCaps = ("width=(int)%d, height=(int)%d, framerate=(fraction)%d/%d, "
                         "pixel-aspect-ratio=(fraction)%d/%d"
                         % (self.videoWidth, self.videoHeight, videoRate[0],
                            videoRate[1], self.videoPAR[0], self.videoPAR[1]))
                vCaps = "video/x-raw-rgb, %s;video/x-raw-yuv, %s" % (vCaps, vCaps)
                videotestsrc = gst.element_factory_make("videotestsrc")
                videotestsrc.props.num_buffers = buffCount
                videocaps = gst.element_factory_make("capsfilter")
                videocaps.props.caps = gst.caps_from_string(vCaps)
                videoencoder = gstutils.parse_bin_from_description(self.videoCodec, True)
                videoqueue = gst.element_factory_make("queue")
                self._pipeline.add(videotestsrc, videocaps, videoencoder, videoqueue)
                gst.element_link_many(videotestsrc, videocaps, videoencoder,
                                      videoqueue, muxer)

            if self.audioCodec:
                aCaps = ("rate=(int)%d, channels=(int)%d"
                         % (self.audioRate, self.audioChannels))
                aCaps = "audio/x-raw-int, %s;audio/x-raw-float, %s" % (aCaps, aCaps)
                audiotestsrc = gst.element_factory_make("audiotestsrc")
                audiotestsrc.props.num_buffers = buffCount
                audiotestsrc.props.samplesperbuffer = aBlockSize
                audioconvert = gst.element_factory_make("audioconvert")
                audiocaps = gst.element_factory_make("capsfilter")
                audiocaps.props.caps = gst.caps_from_string(aCaps)
                audioencoder = gstutils.parse_bin_from_description(self.audioCodec, True)
                audioqueue = gst.element_factory_make("queue")
                self._pipeline.add(audiotestsrc, audioconvert, audiocaps,
                                   audioencoder, audioqueue)
                gst.element_link_many(audiotestsrc, audioconvert, audiocaps,
                                      audioencoder, audioqueue, muxer)

            d = defer.Deferred()
            self._bus = self._pipeline.get_bus()
            self._bus.add_signal_watch()
            self._bus.connect("message", self._bus_message_callback)
            ret = self._pipeline.set_state(gst.STATE_PLAYING)
            if ret == gst.STATE_CHANGE_FAILURE:
                raise Exception("Fail to change pipeline state to PLAYING")
            return self._deferred
        except:
            self._deferred.errback(Failure())
            return self._deferred
Exemplo n.º 3
0
def makeVideoEncodeBin(config, analysis, tag, withRateControl=True, pipelineInfo=None, logger=None):
    logger = logger or log
    pipelineParts = list()
    bin = gst.Bin()

    # input queue element
    inqueue = gst.element_factory_make("queue", "videoinqueue-%s" % tag)
    # Cannot specify max_size_time property because of some buggy buffers
    # with invalid time that make the queue lock
    inqueue.props.max_size_time = 0
    inqueue.props.max_size_buffers = 200
    pipelineParts.append("queue")

    # ffmpegcolorspace element
    cspace = gst.element_factory_make("ffmpegcolorspace", "cspace-%s" % tag)
    pipelineParts.append("ffmpegcolorspace")

    # videorate element
    if withRateControl:
        rate = gst.element_factory_make("videorate", "videorate-%s" % tag)
        pipelineParts.append("videorate")
    else:
        rate = None

    # videoscale element
    scale = gst.element_factory_make("videoscale", "videoscale-%s" % tag)
    # use bilinear scaling for better image quality
    scale.props.method = 1
    pipelineParts.append("videoscale method=1")

    # capsfilter element
    capsfilter = gst.element_factory_make("capsfilter", "videocapsfilter-%s" % tag)
    inputSize = _getInputVideoSize(config, analysis)
    logger.debug(
        "makeVideoEncodeBin - Input Video Size: %dx%d %d/%d"
        % (inputSize[0], inputSize[1], inputSize[2].num, inputSize[2].denom)
    )
    _logPreferredSize(logger.debug, config, "makeVideoEncodeBin - Preferred Video Size:")
    outputSize = _getOutputVideoSize(config, analysis, inputSize)
    logger.debug(
        "makeVideoEncodeBin - Output Video Size: %dx%d %d/%d"
        % (outputSize[0], outputSize[1], outputSize[2].num, outputSize[2].denom)
    )
    caps = _getOutputVideoCaps(config, analysis, outputSize)
    if caps:
        logger.debug("Video capsfilter: '%s'", caps)
        capsfilter.props.caps = gst.caps_from_string(caps)
        pipelineParts.append("'%s'" % caps)
    else:
        logger.debug("No video capsfilter")

    # videobox and videocrop elements
    box = _getOutputVideoBox(config, analysis, outputSize)
    videocrop = None
    videobox = None
    if box != (0, 0, 0, 0):
        # FIXME: Crop is a temporary hack to fix wrong behaviors
        #       of the platform version of videobox with odd parameteres.
        #       gstreamer-0.10.12, gstreamer-plugins-good-0.10.5
        crop = tuple([v % 2 for v in box])
        box = tuple([v - (v % 2) for v in box])
        logger.debug("makeVideoEncodeBin - Output Video Boxing: %r" % (box,))
        videobox = gst.element_factory_make("videobox", "videobox-%s" % tag)
        videobox.props.left = box[0]
        videobox.props.top = box[1]
        videobox.props.right = box[2]
        videobox.props.bottom = box[3]
        pipelineParts.append("videobox left=%d top=%d " "right=%d bottom=%d" % box[:4])
        if crop != (0, 0, 0, 0):
            logger.debug("makeVideoEncodeBin - Output Video Cropping: %r" % (crop,))
            videocrop = gst.element_factory_make("videocrop", "videocrop-%s" % tag)
            videocrop.props.left = crop[0]
            videocrop.props.top = crop[1]
            videocrop.props.right = crop[2]
            videocrop.props.bottom = crop[3]
            pipelineParts.append("videocrop left=%d top=%d " "right=%d bottom=%d" % crop[:4])

    # encoder elements
    encode = gstutils.parse_bin_from_description(config.videoEncoder, True)
    pipelineParts.extend(map(str.strip, config.videoEncoder.split("!")))

    # output queue element
    outqueue = gst.element_factory_make("queue", "videooutqueue-%s" % tag)
    outqueue.props.max_size_time = gst.SECOND * 20
    outqueue.props.max_size_buffers = 0
    pipelineParts.append("queue")

    # Add to pipeline and link all the elements
    bin.add(inqueue, cspace, scale, capsfilter, encode, outqueue)
    if rate:
        bin.add(rate)
        gst.element_link_many(inqueue, cspace, scale, rate, capsfilter)
    else:
        gst.element_link_many(inqueue, cspace, scale, capsfilter)
    if videobox:
        bin.add(videobox)
        if videocrop:
            bin.add(videocrop)
            gst.element_link_many(capsfilter, videobox, videocrop, encode)
        else:
            gst.element_link_many(capsfilter, videobox, encode)
    else:
        gst.element_link_many(capsfilter, encode)
    gst.element_link_many(encode, outqueue)

    bin.add_pad(gst.GhostPad("sink", inqueue.get_pad("sink")))
    bin.add_pad(gst.GhostPad("src", outqueue.get_pad("src")))

    pipelineDesc = " ! ".join(pipelineParts)
    logger.debug("Video pipeline: %s", pipelineDesc)

    if pipelineInfo != None:
        pipelineInfo["video"] = pipelineDesc

    return bin