Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add VideoCodec option #174

Merged
merged 2 commits into from
Mar 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ Most camera parameters can be controlled through XML attributes or linked method
app:cameraCropOutput="false"
app:cameraJpegQuality="100"
app:cameraVideoQuality="480p"
app:cameraVideoCodec="deviceDefault"
app:cameraWhiteBalance="auto"
app:cameraHdr="off"
app:cameraAudio="on"
Expand All @@ -416,6 +417,7 @@ Most camera parameters can be controlled through XML attributes or linked method
|[`cameraCropOutput`](#cameracropoutput)|`setCropOutput()`|`true` `false`|`false`|
|[`cameraJpegQuality`](#camerajpegquality)|`setJpegQuality()`|`0 < n <= 100`|`100`|
|[`cameraVideoQuality`](#cameravideoquality)|`setVideoQuality()`|`lowest` `highest` `maxQvga` `max480p` `max720p` `max1080p` `max2160p`|`max480p`|
|[`cameraVideoCodec`](#cameravideocodec)|`setVideoCodec()`|`deviceDefault` `h263` `h264`|`deviceDefault`|
|[`cameraWhiteBalance`](#camerawhitebalance)|`setWhiteBalance()`|`auto` `incandescent` `fluorescent` `daylight` `cloudy`|`auto`|
|[`cameraHdr`](#camerahdr)|`setHdr()`|`off` `on`|`off`|
|[`cameraAudio`](#cameraaudio)|`setAudio()`|`off` `on`|`on`|
Expand Down Expand Up @@ -504,6 +506,16 @@ cameraView.setVideoQuality(VideoQuality.MAX_1080P);
cameraView.setVideoQuality(VideoQuality.MAX_2160P);
```

#### cameraVideoCodec

Sets the encoder for video recordings.

```java
cameraView.setVideoCodec(VideoCodec.DEVICE_DEFAULT);
cameraView.setVideoCodec(VideoCodec.H_263);
cameraView.setVideoCodec(VideoCodec.H_264);
```

#### cameraWhiteBalance

Sets the desired white balance for the current session.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ public void testDefaults() {
assertEquals(cameraView.getHdr(), Hdr.DEFAULT);
assertEquals(cameraView.getAudio(), Audio.DEFAULT);
assertEquals(cameraView.getVideoQuality(), VideoQuality.DEFAULT);
assertEquals(cameraView.getVideoCodec(), VideoCodec.DEFAULT);
assertEquals(cameraView.getLocation(), null);
assertEquals(cameraView.getExposureCorrection(), 0f, 0f);
assertEquals(cameraView.getZoom(), 0f, 0f);
Expand Down Expand Up @@ -560,6 +561,14 @@ public void testVideoQuality() {
assertEquals(cameraView.getVideoQuality(), VideoQuality.LOWEST);
}

@Test
public void testVideoCodec() {
cameraView.set(VideoCodec.H_263);
assertEquals(cameraView.getVideoCodec(), VideoCodec.H_263);
cameraView.set(VideoCodec.H_264);
assertEquals(cameraView.getVideoCodec(), VideoCodec.H_264);
}

@Test
public void testPictureSizeSelector() {
SizeSelector source = SizeSelectors.minHeight(50);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.otaliastudios.cameraview;


import android.hardware.Camera;
import android.media.MediaRecorder;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.assertEquals;


@RunWith(AndroidJUnit4.class)
@SmallTest
public class MapperTest extends BaseTest {

private Mapper mapper = new Mapper() {
<T> T map(Flash flash) { return null; }
<T> T map(Facing facing) { return null; }
<T> T map(WhiteBalance whiteBalance) { return null; }
<T> T map(Hdr hdr) { return null; }
<T> Flash unmapFlash(T cameraConstant) { return null; }
<T> Facing unmapFacing(T cameraConstant) { return null; }
<T> WhiteBalance unmapWhiteBalance(T cameraConstant) { return null; }
<T> Hdr unmapHdr(T cameraConstant) { return null; }
};

@Test
public void testMap() {
assertEquals(mapper.map(VideoCodec.DEVICE_DEFAULT), MediaRecorder.VideoEncoder.DEFAULT);
assertEquals(mapper.map(VideoCodec.H_263), MediaRecorder.VideoEncoder.H263);
assertEquals(mapper.map(VideoCodec.H_264), MediaRecorder.VideoEncoder.H264);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ private void initMediaRecorder() {
mMediaRecorder.setOutputFormat(profile.fileFormat);
mMediaRecorder.setVideoFrameRate(profile.videoFrameRate);
mMediaRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
mMediaRecorder.setVideoEncoder(profile.videoCodec);
mMediaRecorder.setVideoEncoder(mMapper.map(mVideoCodec));
mMediaRecorder.setVideoEncodingBitRate(profile.videoBitRate);
if (mAudio == Audio.ON) {
mMediaRecorder.setAudioChannels(profile.audioChannels);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ abstract class CameraController implements
protected Flash mFlash;
protected WhiteBalance mWhiteBalance;
protected VideoQuality mVideoQuality;
protected VideoCodec mVideoCodec;
protected SessionType mSessionType;
protected Hdr mHdr;
protected Location mLocation;
Expand Down Expand Up @@ -285,6 +286,10 @@ final void setVideoMaxDuration(int videoMaxDurationMillis) {
mVideoMaxDuration = videoMaxDurationMillis;
}

final void setVideoCodec(VideoCodec codec) {
mVideoCodec = codec;
}


//endregion

Expand Down Expand Up @@ -362,6 +367,10 @@ final VideoQuality getVideoQuality() {
return mVideoQuality;
}

final VideoCodec getVideoCodec() {
return mVideoCodec;
}

final long getVideoMaxSize() {
return mVideoMaxSize;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ private void init(@NonNull Context context, @Nullable AttributeSet attrs) {
SessionType sessionType = SessionType.fromValue(a.getInteger(R.styleable.CameraView_cameraSessionType, SessionType.DEFAULT.value()));
Hdr hdr = Hdr.fromValue(a.getInteger(R.styleable.CameraView_cameraHdr, Hdr.DEFAULT.value()));
Audio audio = Audio.fromValue(a.getInteger(R.styleable.CameraView_cameraAudio, Audio.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);
int videoMaxDuration = a.getInteger(R.styleable.CameraView_cameraVideoMaxDuration, 0);

Expand Down Expand Up @@ -181,6 +182,7 @@ private void init(@NonNull Context context, @Nullable AttributeSet attrs) {
setHdr(hdr);
setAudio(audio);
setPictureSize(selector);
setVideoCodec(codec);
setVideoMaxSize(videoMaxSize);
setVideoMaxDuration(videoMaxDuration);

Expand Down Expand Up @@ -652,6 +654,8 @@ public void set(Control control) {
setVideoQuality((VideoQuality) control);
} else if (control instanceof WhiteBalance) {
setWhiteBalance((WhiteBalance) control);
} else if (control instanceof VideoCodec) {
setVideoCodec((VideoCodec) control);
}
}

Expand Down Expand Up @@ -1375,6 +1379,30 @@ public boolean getPlaySounds() {
}


/**
* Sets the encoder for video recordings.
* Defaults to {@link VideoCodec#DEVICE_DEFAULT}.
*
* @see VideoCodec#DEVICE_DEFAULT
* @see VideoCodec#H_263
* @see VideoCodec#H_264
*
* @param codec requested video codec
*/
public void setVideoCodec(VideoCodec codec) {
mCameraController.setVideoCodec(codec);
}


/**
* Gets the current encoder for video recordings.
* @return the current video codec
*/
public VideoCodec getVideoCodec() {
return mCameraController.getVideoCodec();
}


/**
* Sets the maximum size in bytes for recorded video files.
* Once this size is reached, the recording will automatically stop.
Expand Down
11 changes: 11 additions & 0 deletions cameraview/src/main/java/com/otaliastudios/cameraview/Mapper.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.otaliastudios.cameraview;

import android.hardware.Camera;
import android.media.MediaRecorder;
import android.os.Build;

import java.util.HashMap;
Expand All @@ -16,6 +17,16 @@ abstract class Mapper {
abstract <T> WhiteBalance unmapWhiteBalance(T cameraConstant);
abstract <T> Hdr unmapHdr(T cameraConstant);

int map(VideoCodec codec) {
switch (codec) {
case DEVICE_DEFAULT: return MediaRecorder.VideoEncoder.DEFAULT;
case H_263: return MediaRecorder.VideoEncoder.H263;
case H_264: return MediaRecorder.VideoEncoder.H264;
default: return MediaRecorder.VideoEncoder.DEFAULT;
}
}


static class Mapper1 extends Mapper {

private static final HashMap<Flash, String> FLASH = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.otaliastudios.cameraview;


/**
* Constants for selecting the encoder of video recordings.
* https://developer.android.com/guide/topics/media/media-formats.html#video-formats
*
* @see CameraView#setVideoCodec(VideoCodec)
*/
public enum VideoCodec implements Control {


/**
* Let the device choose its codec.
*/
DEVICE_DEFAULT(0),

/**
* The H.263 codec.
*/
H_263(1),

/**
* The H.264 codec.
*/
H_264(2);

static final VideoCodec DEFAULT = DEVICE_DEFAULT;

private int value;

VideoCodec(int value) {
this.value = value;
}

int value() {
return value;
}

static VideoCodec fromValue(int value) {
VideoCodec[] list = VideoCodec.values();
for (VideoCodec action : list) {
if (action.value() == value) {
return action;
}
}
return null;
}
}
6 changes: 6 additions & 0 deletions cameraview/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@

<attr name="cameraVideoMaxDuration" format="integer" />

<attr name="cameraVideoCodec" format="enum">
<enum name="deviceDefault" value="0" />
<enum name="h263" value="1" />
<enum name="h264" value="2" />
</attr>

<!-- deprecated attr name="cameraZoomMode" format="enum">
<enum name="off" value="0" />
<enum name="pinch" value="1" />
Expand Down