Как получить конкретную область видео в Swift AVPlayer?

Я работаю над базовым Mac OS-X. Пользователь выберет видеофайл, а контроллер NSView будет воспроизводить видео с помощью AVPlayerView. Пользователь может нарисовать прямоугольник над AVPlayerView, и я достиг этой функции. Как показать выбранное видео области в прямоугольнике на камеру Предварительный просмотр Слой внизу справа?

Вот результат: Output Pic

Вот код:

var videoURL = NSURL() // The video file URL by the file chooser
var videoSize = NSSize() // Here the video resolution size will be kept i.e. 720*480
var player:AVPlayerView! // The AVPlayerView to play video

var cameraPreviewLayer:AVPlayerLayer! //The right bottom camera Preview Layer
var rectangleLayer:AVPlayerLayer! // The rectangle that will draw over AVPlayer while mouse dragging

var isClicked = false
var startPoint = NSPoint() // holds the starting point location of mouse pointer while draging

var rect:NSRect!

override func viewDidLoad() {
    super.viewDidLoad()

    self.player = AVPlayerView()

    self.player.frame.origin = CGPoint(x: 0, y: 0)
    self.player.setFrameSize(self.videoSize)

    self.player.player = AVPlayer.playerWithURL(videoURL) as! AVPlayer
    self.view.addSubview(self.player)

    setupRectangle()
    setupCameraPreviewLayer()
}

// intially setup white color rectangle that will draged over AVPlayer
func setupRectangle() {
    self.rectangleLayer = AVPlayerLayer()
    self.rectangleLayer.backgroundColor = NSColor.clearColor().CGColor
    self.rectangleLayer.borderColor = NSColor.whiteColor().CGColor
    self.rectangleLayer.borderWidth = 1.5
    self.rectangleLayer.frame = self.player.bounds
}
// intially setup CameraPreview Layer that will show at right bottom of AVPlayer
func setupCameraPreviewLayer(){
    cameraPreviewLayer = AVPlayerLayer(player: self.player.player)

    //place the cameraPreview layer at right bottom
    cameraPreviewLayer.frame.origin.x = self.player.framesize.width-100
    cameraPreviewLayer.frame.origin.y = self.player.frame.origin.y-100
    cameraPreviewLayer.frame.size.width = 100
    cameraPreviewLayer.frame.size.height = 100
}

override func  mouseDown(theEvent: NSEvent) {
    startPoint = theEvent.locationInWindow
    isClicked = true
    removeCameraPreviewLayer()
}

override func mouseDragged(theEvent: NSEvent) {
    var endPoint = theEvent.locationInWindow

    if( isClicked ){
        rect = NSRect(x: startPoint.x, y: startPoint.y, width: -(startPoint.x-endPoint.x), height: -(startPoint.y-endPoint.y))
        drawCustomRect(rect)
    }
}

override func  mouseUp(theEvent: NSEvent) {
    var endPoint = theEvent.locationInWindow

    if( isClicked ){

// I think we have to do some magic code here
        addCameraPreviewLayer()
    }
    isClicked = false;
}

// redraw the white color rectange over avplayer
func drawCustomRect(rect: NSRect) {
    self.rectangleLayer.frame = rect
    self.player.layer?.addSublayer(self.rectangleLayer)
}

// add Camera PreviewLayer from AVPlayer
func addCameraPreviewLayer() {
    self.player.layer?.addSublayer(self.layer)
}

// remove Camera PreviewLayer from AVPlayer
func removeCameraPreviewLayer() {
    self.cameraPreviewLayer.removeFromSuperlayer()
}

Вот изображение желания, которое я хочу. desired output

Предположим, что видео имеет размер 720 * 480, пользователь нарисовал прямоугольник, а его точки (x1, y1) (x2, y1) (x3, y3) (x4, y4). Как я мог обрезать видео в слое предварительного просмотра камеры (в правом нижнем углу), который показывает видеоизображение той же области, что и прямоугольник, выбранный пользователем?

Кто-нибудь помогает в достижении этой функциональности? Я провел много дней на этом и исчерпал.

Примечание. Я могу сделать это в open-CV при обработке видео с помощью ROI, но это необходимо сделать на родном языке SWIFT.

Ответ 1

Что бы я сделал, это создать контейнерный слой в качестве слоя предварительного просмотра и создать слой предварительного просмотра видео в качестве его подслоя. Затем вы можете в основном всегда настраивать размер и положение слоя предварительного просмотра видео, чтобы он соответствовал соотношению прямоугольник/большой игрок.

Для этого вы можете попытаться настроить слой камеры как таковой:

func setupCameraPreviewLayer(){
    // Create a camera preview layer container which will be used to mask the preview layer
    let cameraContainerLayer = AVLayer()
    cameraContainerLayer.maskToBounds = true

    //place the cameraContainerLayer at right bottom
    cameraContainerLayer.frame.size.width = 100 // Change this to whatever size you'd like your preview to be. The preview layer will have the same width/height ratio as the player layer
    cameraContainerLayer.frame.size.height = cameraContainerLayer.frame.size.width * self.player.framesize.height / self.player.framesize.width
    cameraContainerLayer.frame.origin.x = self.player.frame.size.width - cameraContainerLayer.frame.size.width
    cameraContainerLayer.frame.origin.y = self.player.frame.size.height - cameraContainerLayer.frame.size.height

    // Create the camera preview layer
    cameraPreviewLayer = AVPlayerLayer(player: self.player.player)

    //place the cameraPreview layer so that the container layer has the same size ratio as does the selected rectangle to the big preview layer
    let widthRatio = self.rectangleLayer.bounds.size.width / rect.size.width // rect is the CGRect of the rectangle that the user draw
    let heightRatio = self.rectangleLayer.bounds.size.height / rect.size.height // rect is the CGRect of the rectangle that the user draw

    cameraPreviewLayer.frame.size.width = cameraContainerLayer.bounds.size.width * widthRatio
    cameraPreviewLayer.frame.size.height = cameraContainerLayer.bounds.size.height * heightRatio
    cameraPreviewLayer.frame.origin.x = //calculate the right X in here based on the widthRatio
    cameraPreviewLayer.frame.origin.y = //calculate the right X in here based on the widthRatio 

    cameraContainerLayer.addSublayer(cameraPreviewLayer)
}

Что-то вроде этого должно сделать трюк

P.S: Код выше не проверен и/или завершен. Это просто то, что должно было начаться на правильном пути