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
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
|
|
}
|
|
}
|
|
|