         }
     }
     
-    var sizeToChange: CGSize?
-    
-    public func onChangedSize(_ size: CGSize) {
+    fileprivate func onVideoFrameSizeUpdated(_ videoFrameSize: CGSize) {
         // ここも前述のエラーと同様の理由で処理を後回しにする
         if allowsRender {
-            setRemoteVideoViewSize(size)
+            updateNativeVideoViewSize(videoFrameSize)
         } else {
-            sizeToChange = size
-        }
-    }
-    
-    func setRemoteVideoViewSize(_ size: CGSize) {
-        // 映像の解像度のアスペクト比に合わせて
-        // RTCEAGLVideoView のサイズと位置を変更する
-        let adjustSize = fitSize(from: size, to: frame.size)
-        nativeVideoView.setSize(adjustSize)
-        sizeToChange = nil
-        nativeVideoView.frame =
-            CGRect(x: (frame.size.width - adjustSize.width) / 2,
-                   y: (frame.size.height - adjustSize.height) / 2,
-                   width: adjustSize.width,
-                   height: adjustSize.height)
-        setNeedsDisplay()
-    }
-    
-    public func renderFrame(_ frame: VideoFrame?) {
+            videoFrameSizeToChange = videoFrameSize
+        }
+    }
+    
+    fileprivate func render(videoFrame: VideoFrame?) {
         guard allowsRender else { return }
-        updateSize()
-
-        if let frame = frame {
+        updateSizeIfNeeded()
+        
+        if let frame = videoFrame {
             switch frame {
             case .native(capturer: _, frame: let frame):
                 snapshotView.isHidden = true
                 nativeVideoView.isHidden = false
                 nativeVideoView.renderFrame(frame)
             case .snapshot(let snapshot):
+                // snapshot は WebRTC.framework の仕組みを使用しないで描画しており、
+                // snapshotView のレイアウトも AutoLayoutによって実施されている。
+                // ここでは描画モードの指定を忘れず行う。
                 snapshotView.isHidden = false
                 nativeVideoView.isHidden = true
+                snapshotView.contentMode = renderingContentMode
                 snapshotView.image = UIImage(cgImage: snapshot.image)
             case .other:
                 nativeVideoView.renderFrame(nil)

    // ただし、このエラーは無視しても以降の描画に問題はなく、クラッシュもしない
    // また、遅延プロパティでもキーウィンドウ外で初期化すれば
    // エラーが発生するため、根本的な解決策ではないので注意
    lazy var contentView: VideoViewContentView! = {
        guard let topLevel = Bundle(for: VideoView.self)
            .loadNibNamed("VideoView", owner: self, options: nil) else
        {
            assertionFailure("cannot load VideoView's nib file")
            return nil
        }
        
        let view: VideoViewContentView = topLevel[0] as! VideoViewContentView
        view.frame = self.bounds
        self.addSubview(view)
        if view.allowsRender {
            view.setNeedsDisplay()
        }
        return view
    }()

    override public init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    required public init?(coder: NSCoder) {
        super.init(coder: coder)
    }
    
    override public func layoutSubviews() {
        super.layoutSubviews()
        contentView.setRemoteVideoViewSize(frame.size)
    }
    
    public func onChangedSize(_ size: CGSize) {
        contentView.onChangedSize(size)
    }
    
    public func renderFrame(_ frame: VideoFrame?) {
        contentView.renderFrame(frame)
    }
    
}

class VideoViewContentView: UIView, VideoRenderer {
    
    @IBOutlet weak var nativeVideoView: RTCEAGLVideoView!
    @IBOutlet weak var snapshotView: UIImageView!
    
    var allowsRender: Bool {
        get {
            // 前述のエラーはキーウィンドウ外での描画でも発生するので、
            // ビューがキーウィンドウに表示されている場合のみ描画を許可する

import UIKit
import WebRTC

public class VideoView: UIView {
    
    // キーウィンドウ外で RTCEAGLVideoView を生成すると次のエラーが発生するため、
    // contentView を Nib ファイルでセットせずに遅延プロパティで初期化する
