Silence-GitHub / BBMetalImage

A high performance Swift library for GPU-accelerated image/video processing based on Metal.
MIT License
985 stars 125 forks source link

video not show after remove consumer and add some new consumers #34

Closed R3l0ad3d closed 4 years ago

R3l0ad3d commented 4 years ago

when i remove all consumer and add new consumers then metal view not show video . its the main problem . any one help ? videoSource?.removeAllConsumers() videoSource?.add(consumer: box) .add(consumer: lutFilter!) .add(consumer: metalView!) videoSource?.add(consumer: videoWriter!) this is my code . even if i add new consumer after first time thats not effect on view . here i want to change "box" consumer to any other filter consumer . rest of consumer are same . how can i do that . if i remove first and add to consumer first index then view not show that effect .

Silence-GitHub commented 4 years ago

All sources should remove consumers.

videoSource?.removeAllConsumers()
box.removeAllConsumers()
lutFilter!.removeAllConsumers()

videoSource?.add(consumer: otherFilter)
    .add(consumer: lutFilter!)
    .add(consumer: metalView!)
R3l0ad3d commented 4 years ago

`var commonFilter : BBMetalBaseFilter? case .Normal: let gaussian = BBMetalGaussianBlurFilter(sigma: 10)

            videoSource?.removeAllConsumers()
            lutFilter?.removeAllConsumers()
            commonFilter?.removeAllConsumers()

            //current filter
            commonFilter = gaussian

            videoSource?.add(consumer: gaussian)
            .add(consumer: lutFilter!)
                .add(consumer: metalView!)
            //videoSource?.add(consumer: videoWriter!)

            break
        case .Box:
            let box = BBMetalBoxBlurFilter(kernelWidth: 5, kernelHeight: 5)

            videoSource?.removeAllConsumers()
            commonFilter?.removeAllConsumers()
            lutFilter?.removeAllConsumers()

            //current filter
            commonFilter = box

            videoSource?.add(consumer: box)
            .add(consumer: lutFilter!)
                .add(consumer: metalView!)
            videoSource?.add(consumer: videoWriter!)

        break`

that is my code but its still no update metal view when i change initial consumer to this consumers . please help

Silence-GitHub commented 4 years ago
  1. Could you please show more code?
  2. See the demo project. You may find what you need
R3l0ad3d commented 4 years ago

ok i gave you my class . i think you can understand . i have a collection view which hold the blur option . if i click Gaussian blur view effect change to Gaussian , if i click box blur video effect change to box blur . and i have more filter like blur . video play background but metal view stack after change filter . `class BBMetalBackgroundVideoView: UIView {

var backgroundImageView : UIImageView?
var metalView : BBMetalView?
var videoSource : BBMetalVideoSource?
var videoWriter : BBMetalVideoWriter?

var sourceUrl : URL?
var outputUrl : URL?

var lutFilter : BBMetalLookupFilter?
var commonFilter : BBMetalBaseFilter?

/*
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
    // Drawing code
}
*/

override func awakeFromNib() {
    super.awakeFromNib()
    commonInit()
}
override init(frame: CGRect) {
    super.init(frame: frame)
    commonInit()
}
required init?(coder: NSCoder) {
    super.init(coder: coder)
}

private func commonInit()  {
    metalView = BBMetalView(frame: self.bounds)
    metalView?.backgroundColor = .yellow
    metalView?.translatesAutoresizingMaskIntoConstraints = false
   self.addSubview(metalView!)
   metalView?.snp.makeConstraints({ (make) in
       make.top.equalToSuperview()
       make.bottom.equalToSuperview()
       make.left.equalToSuperview()
       make.right.equalToSuperview()
   })
    metalView?.bb_textureContentMode = .aspectRatioFill
    metalView?.enableSetNeedsDisplay = true
    backgroundImageView = UIImageView()
    backgroundImageView?.contentMode = .scaleAspectFill
    backgroundImageView?.translatesAutoresizingMaskIntoConstraints = false
    self.addSubview(backgroundImageView!)
    backgroundImageView?.snp.makeConstraints({ (make) in
        make.top.equalToSuperview()
        make.bottom.equalToSuperview()
        make.left.equalToSuperview()
        make.right.equalToSuperview()
    })
    backgroundImageView?.isHidden = true

    layoutIfNeeded()
}

func initialPlaySetup(url : URL, isPotrait : Bool)  {
    //update all flag

    self.isPotrait = isPotrait

    self.sourceUrl = url

    if outputUrl != nil{
        do{
            try FileManager.default.removeItem(at: outputUrl!)
        }catch{
            print(error)
        }
    }
    let milliseconds : Int = Int(NSDate.init().timeIntervalSince1970 * 1000)
    outputUrl = FileManager.default.temporaryDirectory
    outputUrl?.appendPathComponent("\(milliseconds)")
    outputUrl?.appendPathExtension(sourceUrl!.pathExtension)

    do{
        try FileManager.default.removeItem(at: outputUrl!)
    }catch{
        print(error)
    }

    let asset = AVAsset(url: url)
    firstFrameImage = asset.getFirstFrameImage()
    let outputSize = asset.getActualViewSize()

    backgroundImageView?.isHidden = false
    let bImg = firstFrameImage!.gaussianBlurBB(blurRadius: 10)

    if !isPotrait{
        backgroundImageView?.image = bImg.rotate(radians: .pi/2)
    }

    self.videoSource = BBMetalVideoSource(url: url)

    self.videoWriter = BBMetalVideoWriter(url: outputUrl!, frameSize: BBMetalIntSize(width: Int(outputSize.width), height: Int(outputSize.height)))

    self.videoSource!.playWithVideoRate = true

    commonFilter = BBMetalGaussianBlurFilter(sigma: 10)

    let lut = UIImage(named: "lookup.png")
    self.lutImage = lut
    lutFilter = BBMetalLookupFilter(lookupTable: (lut?.bb_metalTexture)!)

    self.videoSource?
        .add(consumer: commonFilter!)
        .add(consumer: lutFilter!)
        .add(consumer: metalView!)

    self.videoSource?.add(consumer: videoWriter!)
    lutFilter?.add(consumer: videoWriter!)

    self.videoSource?.start()

// self.videoSource?.start(progress: { time in // // }, completion: { (isComplete) in // // }) }

func setBlur(blurClass : BlurClass,intensity : Float) {
    blurOnVideo(blurClass: blurClass, intensity: intensity)

}

private func blurOnVideo(blurClass : BlurClass,intensity : Float){

    if blurClass.isBlur{

        let blur = blurClass.blurName
        videoSource?.cancel()
        switch blur {
        case .NoBlur:

            videoSource?.removeAllConsumers()
            commonFilter?.removeAllConsumers()
            lutFilter?.removeAllConsumers()

            videoSource?
                .add(consumer: lutFilter!)
                .add(consumer: metalView!)
            videoSource?.add(consumer: videoWriter!)
            lutFilter?.add(consumer: videoWriter!)
            self.videoSource?.start()
            break
        case .Normal:

            videoSource?.removeAllConsumers()
            commonFilter?.removeAllConsumers()
            lutFilter?.removeAllConsumers()

            commonFilter = BBMetalGaussianBlurFilter(sigma: 10)

            videoSource?.add(consumer: commonFilter!)
                        .add(consumer: lutFilter!)
                        .add(consumer: metalView!)
            videoSource?.add(consumer: videoWriter!)
            lutFilter?.add(consumer: videoWriter!)
            self.videoSource?.start()
            break
        case .Box:
            videoSource?.removeAllConsumers()
            commonFilter?.removeAllConsumers()
            lutFilter?.removeAllConsumers()

            commonFilter = BBMetalBoxBlurFilter(kernelWidth: 5, kernelHeight: 5)

            videoSource?.add(consumer: commonFilter!)
                        .add(consumer: lutFilter!)
                        .add(consumer: metalView!)
            videoSource?.add(consumer: videoWriter!)
            lutFilter?.add(consumer: videoWriter!)
            self.videoSource?.start()
        break
        case .Bilateral:
            videoSource?.removeAllConsumers()
            commonFilter?.removeAllConsumers()
            lutFilter?.removeAllConsumers()

            commonFilter = BBMetalBilateralBlurFilter()

            videoSource?.add(consumer: commonFilter!)
                        .add(consumer: lutFilter!)
                        .add(consumer: metalView!)
            videoSource?.add(consumer: videoWriter!)
            lutFilter?.add(consumer: videoWriter!)
            self.videoSource?.start()
            break
        case .Motion:

            videoSource?.removeAllConsumers()
            commonFilter?.removeAllConsumers()
            lutFilter?.removeAllConsumers()

            commonFilter = BBMetalBilateralBlurFilter(distanceNormalizationFactor: 10, stepOffset: 24)

            videoSource?.add(consumer: commonFilter!)
                        .add(consumer: lutFilter!)
                        .add(consumer: metalView!)
            videoSource?.add(consumer: videoWriter!)
            lutFilter?.add(consumer: videoWriter!)
            self.videoSource?.start()
            break
        case .Zoom:
            videoSource?.removeAllConsumers()
            commonFilter?.removeAllConsumers()
            lutFilter?.removeAllConsumers()
            commonFilter = BBMetalZoomBlurFilter(blurSize: 10, blurCenter: .center)

            videoSource?.add(consumer: commonFilter!)
                        .add(consumer: lutFilter!)
                        .add(consumer: metalView!)
            videoSource?.add(consumer: videoWriter!)
            lutFilter?.add(consumer: videoWriter!)
            self.videoSource?.start()
            break
        case .Pixellet:

            videoSource?.removeAllConsumers()
            commonFilter?.removeAllConsumers()
            lutFilter?.removeAllConsumers()

            commonFilter = BBMetalPixellateFilter()

            videoSource?.add(consumer: commonFilter!)
                        .add(consumer: lutFilter!)
                        .add(consumer: metalView!)
            videoSource?.add(consumer: videoWriter!)
            lutFilter?.add(consumer: videoWriter!)
            self.videoSource?.start()

            break
        case .PPixellet:
            videoSource?.removeAllConsumers()
            commonFilter?.removeAllConsumers()
            lutFilter?.removeAllConsumers()

            commonFilter = BBMetalPolarPixellateFilter()

            videoSource?.add(consumer: commonFilter!)
                        .add(consumer: lutFilter!)
                        .add(consumer: metalView!)
            videoSource?.add(consumer: videoWriter!)
            lutFilter?.add(consumer: videoWriter!)
            self.videoSource?.start()
            break
        case .Dot:
            videoSource?.removeAllConsumers()
            commonFilter?.removeAllConsumers()
            lutFilter?.removeAllConsumers()

            commonFilter = BBMetalPolkaDotFilter()

            videoSource?.add(consumer: commonFilter!)
                        .add(consumer: lutFilter!)
                        .add(consumer: metalView!)
            videoSource?.add(consumer: videoWriter!)
            lutFilter?.add(consumer: videoWriter!)
            self.videoSource?.start()
        break

        default:
            videoSource!.add(consumer: lutFilter!)
                        .add(consumer: metalView!)
            videoSource?.add(consumer: videoWriter!)
        }
    }else {
        //blend code
    }
}

}

`

Silence-GitHub commented 4 years ago

There are some problems.

  1. We should not enable set needs display for metal view. Remove this

    metalView?.enableSetNeedsDisplay = true
  2. Video writer should not be consumer for two sources. Remove one of lines

    videoSource?.add(consumer: videoWriter!)
    lutFilter?.add(consumer: videoWriter!)
  3. Some filters use insensitive parameters so the effects are hard to recognize. For example

    BBMetalBoxBlurFilter(kernelWidth: 5, kernelHeight: 5) // hard to see blur effect
    BBMetalBoxBlurFilter(kernelWidth: 25, kernelHeight: 65) // easier to see blur effect

By the way, I have a question: how to see metal view since backgroundImageView covers metal view?

R3l0ad3d commented 4 years ago

metalView?.enableSetNeedsDisplay = true i add that when my code is not working . and BoxBlur effect more or less that not fact in this time . metal view not show any thing when i change effects , but video play. main problem is metal view not show video after change effect . another thing you want to know about backgroundImageView that i use for instant effect show to the user , i hide it when video is playing . here i gave you a portion of my code for easily understand . this code not working on my view . but this code work , i check it to create another project and paste this view . but i cant think so why its not working . thanks for your help .

R3l0ad3d commented 4 years ago

i face another problem will you help me again ? Please help me . when i change metal view frame then video ratio change also . i want to fill video with aspect ratio of metal view frame . i use metalView?.bb_textureContentMode = .aspectRatioFill

But its work first time when i change frame then video ratio not change to .aspectRatioFill . how can i solve this problem ?

Silence-GitHub commented 4 years ago

Sorry, I can not reproduce the problem. Could you please show the code and screenshots (before and after changing fame) ?

R3l0ad3d commented 4 years ago

This is main frame that i want to resize https://ibb.co/mSgDb94 after change frame https://ibb.co/s3mVCFS https://ibb.co/QDxffmd i just change the frame . and call layoutIfNeeded() . and backgroundView code i post here . i just want to change the ratio of this frame .

Silence-GitHub commented 4 years ago

Do you use Auto Layout? When Auto Layout updates metal view frame, the internal texture frame dose not change. So the ratio is wrong. For now, update the metal view frame again even using Auto Layout

// After updating layout constrains
metalView.frame = newFrame