You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

218 lines
6.1 KiB

using UnityEngine;
namespace FFmpegOut
{
[RequireComponent(typeof(Camera))]
[AddComponentMenu("FFmpegOut/Camera Capture")]
public class CameraCapture : MonoBehaviour
{
#region Editable properties
[SerializeField] bool _setResolution = true;
[SerializeField] int _width = 1280;
[SerializeField] int _height = 720;
[SerializeField] int _frameRate = 30;
[SerializeField] bool _allowSlowDown = true;
[SerializeField] public FFmpegPipe.Codec _codec;
#endregion
public void SetResolution(int w,int h)
{
_width = w;
_height = h;
}
#region Private members
[SerializeField, HideInInspector] Shader _shader;
Material _material;
FFmpegPipe _pipe;
float _elapsed;
RenderTexture _tempTarget;
GameObject _tempBlitter;
static int _activePipeCount;
#endregion
#region MonoBehavior functions
public float recordTime;
private float updateIntervalTime;
private long CurrentFrameCount;
//private Camera RenderCamera;
void OnValidate()
{
}
void OnEnable()
{
if (!FFmpegConfig.CheckAvailable)
{
Debug.LogError(
"ffmpeg.exe is missing. " +
"Please refer to the installation instruction. " +
"https://github.com/keijiro/FFmpegOut"
);
enabled = false;
}
updateIntervalTime = 1 / (float)_frameRate;
//Application.targetFrameRate = _frameRate;
//RenderCamera = GetComponent<Camera>();
SetResolution(Screen.width,Screen.height);
}
void OnDisable()
{
if (_pipe != null) ClosePipe();
}
void OnDestroy()
{
if (_pipe != null) ClosePipe();
}
void Start()
{
_material = new Material(_shader);
//_frameRate = Application.targetFrameRate;
}
public void StartCapture(string filename)
{
if (_pipe == null) OpenPipe(filename);
}
public void StopCapture()
{
if (_pipe != null) ClosePipe();
}
void OnRenderImage(RenderTexture source, RenderTexture destination)
{
if (_pipe != null)
{
if ((Time.time - recordTime) / updateIntervalTime >= CurrentFrameCount)
{
var tempRT = RenderTexture.GetTemporary(source.width, source.height);
Graphics.Blit(source, tempRT, _material, 0);
var tempTex = new Texture2D(source.width, source.height, TextureFormat.RGB24, false);
tempTex.ReadPixels(new Rect(0, 0, source.width, source.height), 0, 0, false);
tempTex.Apply();
byte[] writeByte = tempTex.GetRawTextureData();
_pipe.Write(writeByte);
Destroy(tempTex);
RenderTexture.ReleaseTemporary(tempRT);
CurrentFrameCount++;
}
}
Graphics.Blit(source, destination);
}
#endregion
#region Private methods
void OpenPipe(string filename)
{
if (_pipe != null) return;
var camera = GetComponent<Camera>();
var width = _width;
var height = _height;
// Apply the screen resolution settings.
if (_setResolution)
{
_tempTarget = RenderTexture.GetTemporary(width, height);
camera.targetTexture = _tempTarget;
_tempBlitter = Blitter.CreateGameObject(camera);
}
else
{
width = camera.pixelWidth;
height = camera.pixelHeight;
}
// Open an output stream.
_pipe = new FFmpegPipe(filename, width, height, _frameRate, _codec);
_activePipeCount++;
// Change the application frame rate on the first pipe.
if (_activePipeCount == 1)
{
if (_allowSlowDown)
Time.captureFramerate = _frameRate;
//else
//Application.targetFrameRate = _frameRate;
}
recordTime = Time.time;
Debug.Log("Capture started (" + _pipe.Filename + ")");
}
void ClosePipe()
{
var camera = GetComponent<Camera>();
// Destroy the blitter object.
if (_tempBlitter != null)
{
Destroy(_tempBlitter);
_tempBlitter = null;
}
// Release the temporary render target.
if (_tempTarget != null && _tempTarget == camera.targetTexture)
{
camera.targetTexture = null;
RenderTexture.ReleaseTemporary(_tempTarget);
_tempTarget = null;
}
// Close the output stream.
if (_pipe != null)
{
CurrentFrameCount = 0;
Debug.Log("Capture ended (" + _pipe.Filename + ")");
StartCoroutine(_pipe.Close());
_activePipeCount--;
if (!string.IsNullOrEmpty(_pipe.Error))
{
Debug.LogWarning(
"ffmpeg returned with a warning or an error message. " +
"See the following lines for details:\n" + _pipe.Error
);
}
_pipe = null;
// Reset the application frame rate on the last pipe.
if (_activePipeCount == 0)
{
if (_allowSlowDown)
Time.captureFramerate = 0;
//else
//Application.targetFrameRate = -1;
//Application.targetFrameRate = _frameRate;
}
}
}
#endregion
}
}