Soruce Description

  1. Main
  2. Media
    1. Common
    2. Stream
    3. Broadcast
  3. Admin
  4. Cocoapod Library
  5. Etc

Main

Media

  • 방송 송출(Stream), 방송 수신(Broadcast) 메뉴
  • 공통 기능(Common) 메뉴

Common

Model

  • StoreProductType.swift

View

  • MediaMenuView.swift

ViewModel

  • BroadcastViewModel.swift
  • ChatRoomViewModel.swift

ViewController

  • MediaMenuViewController.swift
  • MediaMenuViewController+TableView.swift

Stream

Model

  • StreamMenuSegues.swift
  • VisualEffect.swift

View

DrawSqaure.swift

1) Menu

  • StreamViewController.swift

방송 송출 연결 해제 및 소켓 통신 이벤트

  • StreamViewController+OnboardingView.swift

방송송출 튜토리얼 메뉴

  • StreamViewController+InputBarAccessoryView.swift

방송송출 채팅 메뉴

  • StreamSettingViewController.swift

방송송출 설정 메뉴

2) Onboarding

조도 센서

줌 컨트롤

뷰티 필터

카메라 반전 필터

방송 송출 라이브러리

Broadcast

  • BroadcastViewController.swift

방송 수신 라이브러리

Admin

Cocoapod Library

CocoadPod 라이브러리 중 SwinjectStoryboard, PictureInPicture, HaishinKit 라이브러리 파일에는 자체 작업 소스가 추가된 상태다. 그렇기 때문에, 라이브러리 수정시 기존에 수정한 소스를 다시 머지하여 기존 기능을 유지해야 한다.

작업 내용

SwinjectStoryboard, PictureInPicture, HaishinKit라이브러리에 기존 작업 소스 추가

SwinjectStoryboard

라이브러리 포팅시 Hash 프로토콜 오류가 발생하기 때문에, Hash 프로토콜 오류를 수정해서 사용해야 한다.

  • SwinjectStoryboardOption.swift
internal var hashValue: Int {
         return controllerType.hashValue
 }

func hash(into: inout Hasher) {
      into.combine(self.controllerType)
 }

PictureInPicture

라이브러리 포팅시 Hash 프로토콜 오류가 발생하기 때문에, Hash 프로토콜 오류를 수정해서 사용해야 한다.

  • PictureInPicture.swift
//기존 소스
static var defaultCorner: Corner {
      return Corner(.bottom, defaultEdge)
}

//수정 소스
static var defaultCorner: Corner {
	      return Corner(.top, defaultEdge)
}
  • PictureInPictureWindow.swift
init(disposeHandler: @escaping (() -> Void)) {
//추가 소스
....
    let marginSize = CGSize(width: 20, height: 20)
    let pipCloseButton = UIButton(frame: CGRect(x: UIScreen.main.bounds.width - (100 + marginSize.width), y: marginSize.height, width: 100, height: 100))
    pipCloseButton.setBackgroundImage(UIImage(named: "iconPipClose"), for: .normal)
    pipCloseButton.addTarget(self, action:#selector(tapCloseButton), for: .touchUpInside)
    userInterfaceShutoutView.addSubview(pipCloseButton)
....
}

//추가 소스
@objc private func tapCloseButton() {
      self.dismiss(animation: false)
 }

HaishinKit

RTMP 라이브러리 기능에 줌 기능과 영상 필터 기능을 적용하기 위해 소스를 추가한다.

  • VideoIOComponent+Extension.swift
extension VideoIOComponent {
...................................
// 핀치 줌 기능 추가
@available(iOS 11.0, *)
    func setPinchZoomFactor(_ state: UIGestureRecognizer.State, scale: CGFloat) -> CGFloat {
        guard let device: AVCaptureDevice = (input as? AVCaptureDeviceInput)?.device,
            1 <= zoomFactor && zoomFactor < device.activeFormat.videoMaxZoomFactor
            else { return 0  }
          
        var currentZoomFactor: CGFloat = 0
        
        switch state {
        case .began:
            self.initialZoomScale = device.videoZoomFactor
            currentZoomFactor = initialZoomScale
            
        case .changed:
            var factor = self.initialZoomScale * scale
            factor = max(1, min(factor, 10))
            print("factor",factor)
            
            currentZoomFactor = factor
            do {
                try device.lockForConfiguration()
                device.ramp(toVideoZoomFactor: factor, withRate: 3.0)
                device.unlockForConfiguration()
            } catch let error as NSError {
                logger.error("while locking device for clamp: \(error)")
            }
        default:
            return 0
        }
        
        return currentZoomFactor
    }
    
//카메라 노출 변경 기능
    var camExposureRange: [Float]? {
        get{
            guard let device: AVCaptureDevice = (input as? AVCaptureDeviceInput)?.device else {
                return nil
                }
        
            return [Float(device.minExposureTargetBias), Float(device.maxExposureTargetBias)]
        }
    }
...................................
}
  • NetStream.swift
open class NetStream: NSObject {
...................................
//추가 소스
	open func camExposureRange() ->[Float]? {
	        return  mixer.videoIO.camExposureRange
	    }
	    
	    open func changeExposureValue(bias: Float) {
	        mixer.videoIO.exposureBias = bias
	    }
	    
	    @available(iOS 11.0, *)
	    open func setPinchZoomFactor(_ state: UIGestureRecognizer.State, scale: CGFloat) -> CGFloat {
	        return  mixer.videoIO.setPinchZoomFactor(state, scale: scale)
	    }
...................................
}
  • VideoIOComponent.swift
final class VideoIOComponent: IOComponent {

		var position: AVCaptureDevice.Position = .back
...................................
//추가 소스
		var initialZoomScale: CGFloat = 1
    var zoomScaleRange: ClosedRange<CGFloat> = 1...10
...................................
//추가 소스
var exposureBias: Float = 0 {
          didSet {
              let exposureMode: AVCaptureDevice.ExposureMode = continuousExposure ? .continuousAutoExposure : .autoExpose
              guard let device: AVCaptureDevice = (input as? AVCaptureDeviceInput)?.device,
                  device.isExposureModeSupported(exposureMode) else {
                      logger.warn("exposureMode(\(exposureMode.rawValue)) is not supported")
                      return
              }
              do {
                  try device.lockForConfiguration()
                  device.exposureMode = .autoExpose
                  device.setExposureTargetBias(exposureBias, completionHandler: nil)
                  device.unlockForConfiguration()
              } catch let error as NSError {
                  logger.error("while locking device for autoexpose: \(error)")
              }
          }
      }
...................................
}

extension VideoIOComponent {
    func encodeSampleBuffer(_ sampleBuffer: CMSampleBuffer) {
	func encodeSampleBuffer(_ sampleBuffer: CMSampleBuffer) {
		// 추가 소스
		autoreleasepool {
...................................
		}
	}
}

Etc