Here is the example of SlowMo video capture using Camera2 API and CamEX2 class. This is the code for recording slow-motion video which you can find at the bottom of CamEX2 Class of attached example,
Usage:
Note: This is not a complete camera example but just a tutorial of the above functions. So the preview panel may look stretched but the recorded video file will not.
B4X:
#Region HighSpeed/SlowMo
Public Sub getHighSpeedVideoSizesAndFPS As List
Dim scMap As JavaObject = GetFromCameraCharacteristic("SCALER_STREAM_CONFIGURATION_MAP")
Dim sizelist() As Object = scMap.RunMethod("getHighSpeedVideoSizes",Null)
Dim FPSRanges() As Object
Dim vList As List
vList.Initialize
For Each size As JavaObject In sizelist
FPSRanges = scMap.RunMethodJO("getHighSpeedVideoFpsRangesFor",Array(size))
Dim fpsVal As Int
Dim fpsR As Object
For Each fps As JavaObject In FPSRanges
fpsVal = fps.RunMethod("getUpper",Null)
fpsR = fps
Next
vList.Add(CreateMap("sizeObject":size, "FPSRange":fpsR, "FPS":fpsVal, "quality":size.RunMethod("getHeight",Null)&"p"))
Next
Return vList
End Sub
'Prepares the surface for high speed video capture.
'Need to add this line to the manifest editor:
'AddPermission(android.permission.RECORD_AUDIO)
Public Sub PrepareSurfaceForHighSpeedVideo (MyTaskIndex As Int, Dir As String, FileName As String, FPS As Int, Size As Object) As ResumableSub
If getHighSpeedVideoSizesAndFPS.Size > 0 Then
HighSpeedVideo = False
If MyTaskIndex <> TaskIndex Then Return False
CloseSession
Wait For (CreateSurface) Complete (Result As Boolean)
If MyTaskIndex <> TaskIndex Then Return False
File.Delete(Dir, FileName)
MediaRecorder = Camera.CreateMediaRecorder(PreviewSize, Dir, FileName)
MediaRecorder.RunMethod("setOrientationHint", Array(GetHintOrientation))
MediaRecorder.RunMethod("setVideoFrameRate", Array(30))
Dim dFps As Double = FPS
MediaRecorder.RunMethod("setCaptureRate", Array(dFps))
Dim ii As Int = (FPS/30)*1000000
MediaRecorder.RunMethod("setVideoEncodingBitRate", Array(ii))
Dim jo As JavaObject = Me
jo.RunMethod("StartHighSpeedSession",Array(Camera,tv, Size))
Wait For Camera_SessionConfigured (Success As Boolean)
If MyTaskIndex <> TaskIndex Then Return False
HighSpeedVideo = True
Return Success
Else
Return False
End If
End Sub
#End Region
#if Java
import android.view.TextureView;
import android.view.Surface;
import android.util.Size;
import android.util.Log;
import android.util.Range;
import java.util.ArrayList;
import java.util.List;
import java.io.IOException;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession;
import android.media.MediaCodec;
import android.os.Handler;
public void StartHighSpeedSession(final anywheresoftware.b4a.objects.Camera2 _cam,final TextureView Surface, final Size PreviewSize) throws CameraAccessException, IllegalStateException, IOException {
final ArrayList<Surface> targets = new ArrayList<Surface>();
if (Surface != null) {
_cam.previewSurface = new Surface(Surface.getSurfaceTexture());
Surface.getSurfaceTexture().setDefaultBufferSize(PreviewSize.getWidth(), PreviewSize.getHeight());
targets.add(_cam.previewSurface);
}
_cam.persistentSurface = MediaCodec.createPersistentInputSurface();
_cam.mediaRecorder.setInputSurface(_cam.persistentSurface);
_cam.mediaRecorder.prepare();
targets.add(_cam.persistentSurface);
_cam.cameraDevice.createConstrainedHighSpeedCaptureSession((java.util.List)targets, (CameraCaptureSession.StateCallback)new CameraCaptureSession.StateCallback() {
public void onConfigureFailed(final CameraCaptureSession session) {
ba.raiseEventFromUI(null, "camera_sessionconfigured", new Object[] { false });
}
public void onConfigured(final CameraCaptureSession session) {
_cam.captureSession = session;
ba.raiseEventFromUI(null, "camera_sessionconfigured", new Object[] { true });
}
public void onClosed(final CameraCaptureSession session) {
if (_cam.captureSession != null && _cam.captureSession.equals(session)) {
_cam.captureSession = null;
}
}
}, (Handler)null);
}
public Object SetRepeatingBurst(final anywheresoftware.b4a.objects.Camera2 _cam,final Object Builder, final Range<Integer> fpsRange) throws CameraAccessException {
final CaptureRequest.Builder builder = ((CaptureRequest.Builder)Builder);
final CaptureRequest req = builder.build();
CameraConstrainedHighSpeedCaptureSession mPreviewSessionHighSpeed = (CameraConstrainedHighSpeedCaptureSession) _cam.captureSession;
List<CaptureRequest> mPreviewBuilderBurst = mPreviewSessionHighSpeed.createHighSpeedRequestList(req);
mPreviewSessionHighSpeed.setRepeatingBurst(mPreviewBuilderBurst, null, (Handler)null);
return req;
}
#End If
Usage:
- Check if the device supports High FPS video recording using getHighSpeedVideoSizesAndFPS.
- This will return a list of High FPS profile.
- Each Profile will contain a capture size, fps range, max fps of that profile and a quality string (eg. 720p) for information
- If the list size is ZERO then the device does not support High FPS recording
- Initialize Camera Preview (check example attached line 84, 85)
- At last call, PrepareSurfaceForHighSpeedVideo to prepare the hardware to High FPS mode. (check example attached line 87)
- Now you can call StartVideoRecording and StopVideoRecording to record a slow-motion video.
Note: This is not a complete camera example but just a tutorial of the above functions. So the preview panel may look stretched but the recorded video file will not.
Attachments
Last edited: