Add support for videoBitRate and audioBitRate

pull/360/head
Mattia Iavarone 6 years ago
parent 8fbc1675ec
commit a1e7718f0e
  1. 2
      MIGRATION.md
  2. 1
      cameraview/src/main/gles/com/otaliastudios/cameraview/MediaEncoderEngine.java
  3. 4
      cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java
  4. 9
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java
  5. 24
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java
  6. 14
      cameraview/src/main/java/com/otaliastudios/cameraview/FullVideoRecorder.java
  7. 16
      cameraview/src/main/java/com/otaliastudios/cameraview/SnapshotVideoRecorder.java
  8. 20
      cameraview/src/main/java/com/otaliastudios/cameraview/VideoResult.java
  9. 3
      cameraview/src/main/res/values/attrs.xml

@ -49,3 +49,5 @@
- VideoSnapshots now respect maxDuration and maxSize limits - VideoSnapshots now respect maxDuration and maxSize limits
- TODO: cameraPreview documentation - TODO: cameraPreview documentation
- TODO: takeVideoSnapshot documentation - TODO: takeVideoSnapshot documentation
- New setVideoBitRate() and setAudioBitRate() (and XML too) options, accepting bits per second values.
TODO: document them

@ -56,6 +56,7 @@ class MediaEncoderEngine {
public void run() { public void run() {
// Trying to convert the size constraints to duration constraints, // Trying to convert the size constraints to duration constraints,
// because they are super easy to check. // because they are super easy to check.
// This is really naive & not accurate, but...
int bitRate = 0; int bitRate = 0;
for (MediaEncoder encoder : mEncoders) { for (MediaEncoder encoder : mEncoders) {
bitRate += encoder.getBitRate(); bitRate += encoder.getBitRate();

@ -631,6 +631,8 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera
videoResult.audio = mAudio; videoResult.audio = mAudio;
videoResult.maxSize = mVideoMaxSize; videoResult.maxSize = mVideoMaxSize;
videoResult.maxDuration = mVideoMaxDuration; videoResult.maxDuration = mVideoMaxDuration;
videoResult.videoBitRate = mVideoBitRate;
videoResult.audioBitRate = mAudioBitRate;
// Initialize the media recorder // Initialize the media recorder
mCamera.unlock(); mCamera.unlock();
@ -660,6 +662,8 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera
videoResult.isSnapshot = true; videoResult.isSnapshot = true;
videoResult.codec = mVideoCodec; videoResult.codec = mVideoCodec;
videoResult.location = mLocation; videoResult.location = mLocation;
videoResult.videoBitRate = mVideoBitRate;
videoResult.audioBitRate = mAudioBitRate;
// What matters as size here is the preview size, which is passed to the GlCameraPreview // What matters as size here is the preview size, which is passed to the GlCameraPreview
// surface texture, which is then passed to the encoder. The view size has no influence. // surface texture, which is then passed to the encoder. The view size has no influence.

@ -59,6 +59,8 @@ abstract class CameraController implements
protected VideoRecorder mVideoRecorder; protected VideoRecorder mVideoRecorder;
protected long mVideoMaxSize; protected long mVideoMaxSize;
protected int mVideoMaxDuration; protected int mVideoMaxDuration;
protected int mVideoBitRate;
protected int mAudioBitRate;
protected Size mCaptureSize; protected Size mCaptureSize;
protected Size mPreviewSize; protected Size mPreviewSize;
protected int mPreviewFormat; protected int mPreviewFormat;
@ -291,6 +293,13 @@ abstract class CameraController implements
mVideoCodec = codec; mVideoCodec = codec;
} }
final void setVideoBitRate(int videoBitRate) {
mVideoBitRate = videoBitRate;
}
final void setAudioBitRate(int audioBitRate) {
mAudioBitRate = audioBitRate;
}
//endregion //endregion

@ -109,6 +109,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
VideoCodec codec = VideoCodec.fromValue(a.getInteger(R.styleable.CameraView_cameraVideoCodec, VideoCodec.DEFAULT.value())); VideoCodec codec = VideoCodec.fromValue(a.getInteger(R.styleable.CameraView_cameraVideoCodec, VideoCodec.DEFAULT.value()));
long videoMaxSize = (long) a.getFloat(R.styleable.CameraView_cameraVideoMaxSize, 0); long videoMaxSize = (long) a.getFloat(R.styleable.CameraView_cameraVideoMaxSize, 0);
int videoMaxDuration = a.getInteger(R.styleable.CameraView_cameraVideoMaxDuration, 0); int videoMaxDuration = a.getInteger(R.styleable.CameraView_cameraVideoMaxDuration, 0);
int videoBitRate = a.getInteger(R.styleable.CameraView_cameraVideoBitRate, 0);
int audioBitRate = a.getInteger(R.styleable.CameraView_cameraAudioBitRate, 0);
// Picture size selector // Picture size selector
List<SizeSelector> pictureConstraints = new ArrayList<>(3); List<SizeSelector> pictureConstraints = new ArrayList<>(3);
@ -207,11 +209,13 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
setGrid(grid); setGrid(grid);
setHdr(hdr); setHdr(hdr);
setAudio(audio); setAudio(audio);
setAudioBitRate(audioBitRate);
setPictureSize(pictureSelector); setPictureSize(pictureSelector);
setVideoSize(videoSelector); setVideoSize(videoSelector);
setVideoCodec(codec); setVideoCodec(codec);
setVideoMaxSize(videoMaxSize); setVideoMaxSize(videoMaxSize);
setVideoMaxDuration(videoMaxDuration); setVideoMaxDuration(videoMaxDuration);
setVideoBitRate(videoBitRate);
// Apply gestures // Apply gestures
mapGesture(Gesture.TAP, tapGesture); mapGesture(Gesture.TAP, tapGesture);
@ -1090,6 +1094,26 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraController.setVideoSizeSelector(selector); mCameraController.setVideoSizeSelector(selector);
} }
/**
* Sets the bit rate in bits per second for video capturing.
* Will be used by both {@link #takeVideo(File)} and {@link #takeVideoSnapshot(File)}.
*
* @param bitRate desired bit rate
*/
public void setVideoBitRate(int bitRate) {
mCameraController.setVideoBitRate(bitRate);
}
/**
* Sets the bit rate in bits per second for audio capturing.
* Will be used by both {@link #takeVideo(File)} and {@link #takeVideoSnapshot(File)}.
*
* @param bitRate desired bit rate
*/
public void setAudioBitRate(int bitRate) {
mCameraController.setAudioBitRate(bitRate);
}
/** /**
* Adds a {@link CameraListener} instance to be notified of all * Adds a {@link CameraListener} instance to be notified of all

@ -45,12 +45,22 @@ class FullVideoRecorder extends VideoRecorder {
case H_264: mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); break; case H_264: mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); break;
case DEVICE_DEFAULT: mMediaRecorder.setVideoEncoder(mProfile.videoCodec); break; case DEVICE_DEFAULT: mMediaRecorder.setVideoEncoder(mProfile.videoCodec); break;
} }
mMediaRecorder.setVideoEncodingBitRate(mProfile.videoBitRate); if (mResult.videoBitRate <= 0) {
mMediaRecorder.setVideoEncodingBitRate(mProfile.videoBitRate);
mResult.videoBitRate = mProfile.videoBitRate;
} else {
mMediaRecorder.setVideoEncodingBitRate(mResult.videoBitRate);
}
if (mResult.getAudio() == Audio.ON) { if (mResult.getAudio() == Audio.ON) {
mMediaRecorder.setAudioChannels(mProfile.audioChannels); mMediaRecorder.setAudioChannels(mProfile.audioChannels);
mMediaRecorder.setAudioSamplingRate(mProfile.audioSampleRate); mMediaRecorder.setAudioSamplingRate(mProfile.audioSampleRate);
mMediaRecorder.setAudioEncoder(mProfile.audioCodec); mMediaRecorder.setAudioEncoder(mProfile.audioCodec);
mMediaRecorder.setAudioEncodingBitRate(mProfile.audioBitRate); if (mResult.audioBitRate <= 0) {
mMediaRecorder.setAudioEncodingBitRate(mProfile.audioBitRate);
mResult.audioBitRate = mProfile.audioBitRate;
} else {
mMediaRecorder.setAudioEncodingBitRate(mResult.audioBitRate);
}
} }
if (mResult.getLocation() != null) { if (mResult.getLocation() != null) {
mMediaRecorder.setLocation( mMediaRecorder.setLocation(

@ -36,16 +36,6 @@ class SnapshotVideoRecorder extends VideoRecorder implements GlCameraPreview.Ren
@Override @Override
void start() { void start() {
mDesiredState = STATE_RECORDING; mDesiredState = STATE_RECORDING;
// TODO respect maxSize by doing inspecting frameRate, bitRate and frame size?
// TODO do this at the encoder level, not here with a handler.
/* if (mResult.maxDuration > 0) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mDesiredState = STATE_NOT_RECORDING;
}
}, (long) mResult.maxDuration);
} */
} }
@Override @Override
@ -75,9 +65,11 @@ class SnapshotVideoRecorder extends VideoRecorder implements GlCameraPreview.Ren
case H_264: type = "video/avc"; break; // MediaFormat.MIMETYPE_VIDEO_AVC: case H_264: type = "video/avc"; break; // MediaFormat.MIMETYPE_VIDEO_AVC:
case DEVICE_DEFAULT: type = "video/avc"; break; case DEVICE_DEFAULT: type = "video/avc"; break;
} }
if (mResult.videoBitRate <= 0) mResult.videoBitRate = 1000000;
if (mResult.audioBitRate <= 0) mResult.audioBitRate = 64000;
TextureMediaEncoder.Config config = new TextureMediaEncoder.Config( TextureMediaEncoder.Config config = new TextureMediaEncoder.Config(
width, height, width, height,
1000000, mResult.videoBitRate,
30, 30,
mResult.getRotation(), mResult.getRotation(),
type, mTextureId, type, mTextureId,
@ -87,7 +79,7 @@ class SnapshotVideoRecorder extends VideoRecorder implements GlCameraPreview.Ren
TextureMediaEncoder videoEncoder = new TextureMediaEncoder(config); TextureMediaEncoder videoEncoder = new TextureMediaEncoder(config);
AudioMediaEncoder audioEncoder = null; AudioMediaEncoder audioEncoder = null;
if (mResult.audio == Audio.ON) { if (mResult.audio == Audio.ON) {
audioEncoder = new AudioMediaEncoder(new AudioMediaEncoder.Config(64000)); audioEncoder = new AudioMediaEncoder(new AudioMediaEncoder.Config(mResult.audioBitRate));
} }
mEncoderEngine = new MediaEncoderEngine(mResult.file, videoEncoder, audioEncoder, mEncoderEngine = new MediaEncoderEngine(mResult.file, videoEncoder, audioEncoder,
mResult.maxDuration, mResult.maxSize, SnapshotVideoRecorder.this); mResult.maxDuration, mResult.maxSize, SnapshotVideoRecorder.this);

@ -25,6 +25,8 @@ public class VideoResult {
long maxSize; long maxSize;
int maxDuration; int maxDuration;
int endReason; int endReason;
int videoBitRate;
int audioBitRate;
VideoResult() {} VideoResult() {}
@ -126,4 +128,22 @@ public class VideoResult {
public int getTerminationReason() { public int getTerminationReason() {
return endReason; return endReason;
} }
/**
* Returns the bit rate used for video encoding.
*
* @return the video bit rate
*/
public int getVideoBitRate() {
return videoBitRate;
}
/**
* Returns the bit rate used for audio encoding.
*
* @return the audio bit rate
*/
public int getAudioBitRate() {
return audioBitRate;
}
} }

@ -22,6 +22,9 @@
<attr name="cameraVideoSizeBiggest" format="boolean"/> <attr name="cameraVideoSizeBiggest" format="boolean"/>
<attr name="cameraVideoSizeAspectRatio" format="string|reference"/> <attr name="cameraVideoSizeAspectRatio" format="string|reference"/>
<attr name="cameraVideoBitRate" format="integer|reference" />
<attr name="cameraAudioBitRate" format="integer|reference" />
<attr name="cameraGestureTap" format="enum"> <attr name="cameraGestureTap" format="enum">
<enum name="none" value="0" /> <enum name="none" value="0" />
<enum name="focus" value="1" /> <enum name="focus" value="1" />

Loading…
Cancel
Save