Add 15 fps support for Android devices with missing 15 fps
camera mode. Some latest Android devices support only 30 fps for front camera, but HW VP8 encoder performance is not enough for 720p 30 fps encoding. Add 15 fps support for these devices by allowing frame drop in Android camera wrapper. BUG= R=tkchin@webrtc.org Review URL: https://webrtc-codereview.appspot.com/24149004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7571 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
8aa4d2d2cd
commit
d0cf68ee37
@ -11,11 +11,13 @@
|
||||
package org.webrtc.videoengine;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Exchanger;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.ImageFormat;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.hardware.Camera.Parameters;
|
||||
import android.hardware.Camera.PreviewCallback;
|
||||
import android.hardware.Camera;
|
||||
import android.opengl.GLES11Ext;
|
||||
@ -58,6 +60,7 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback {
|
||||
private double averageDurationMs;
|
||||
private long lastCaptureTimeMs;
|
||||
private int frameCount;
|
||||
private int frameDropRatio;
|
||||
|
||||
// Requests future capturers to send their frames to |localPreview| directly.
|
||||
public static void setLocalPreview(SurfaceHolder localPreview) {
|
||||
@ -170,7 +173,38 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback {
|
||||
parameters.setVideoStabilization(true);
|
||||
}
|
||||
parameters.setPreviewSize(width, height);
|
||||
|
||||
// Check if requested fps range is supported by camera,
|
||||
// otherwise calculate frame drop ratio.
|
||||
List<int[]> supportedFpsRanges = parameters.getSupportedPreviewFpsRange();
|
||||
frameDropRatio = Integer.MAX_VALUE;
|
||||
for (int i = 0; i < supportedFpsRanges.size(); i++) {
|
||||
int[] range = supportedFpsRanges.get(i);
|
||||
if (range[Parameters.PREVIEW_FPS_MIN_INDEX] == min_mfps &&
|
||||
range[Parameters.PREVIEW_FPS_MAX_INDEX] == max_mfps) {
|
||||
frameDropRatio = 1;
|
||||
break;
|
||||
}
|
||||
if (range[Parameters.PREVIEW_FPS_MIN_INDEX] % min_mfps == 0 &&
|
||||
range[Parameters.PREVIEW_FPS_MAX_INDEX] % max_mfps == 0) {
|
||||
int dropRatio = range[Parameters.PREVIEW_FPS_MAX_INDEX] / max_mfps;
|
||||
frameDropRatio = Math.min(dropRatio, frameDropRatio);
|
||||
}
|
||||
}
|
||||
if (frameDropRatio == Integer.MAX_VALUE) {
|
||||
Log.e(TAG, "Can not find camera fps range");
|
||||
error = new RuntimeException("Can not find camera fps range");
|
||||
exchange(result, false);
|
||||
return;
|
||||
}
|
||||
if (frameDropRatio > 1) {
|
||||
Log.d(TAG, "Frame dropper is enabled. Ratio: " + frameDropRatio);
|
||||
}
|
||||
min_mfps *= frameDropRatio;
|
||||
max_mfps *= frameDropRatio;
|
||||
Log.d(TAG, "Camera preview mfps range: " + min_mfps + " - " + max_mfps);
|
||||
parameters.setPreviewFpsRange(min_mfps, max_mfps);
|
||||
|
||||
int format = ImageFormat.NV21;
|
||||
parameters.setPreviewFormat(format);
|
||||
camera.setParameters(parameters);
|
||||
@ -180,7 +214,7 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback {
|
||||
}
|
||||
camera.setPreviewCallbackWithBuffer(this);
|
||||
frameCount = 0;
|
||||
averageDurationMs = 1000 / max_mfps;
|
||||
averageDurationMs = 1000000.0f / (max_mfps / frameDropRatio);
|
||||
camera.startPreview();
|
||||
exchange(result, true);
|
||||
return;
|
||||
@ -296,8 +330,13 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback {
|
||||
throw new RuntimeException("Unexpected camera in callback!");
|
||||
}
|
||||
frameCount++;
|
||||
// Check if frame needs to be dropped.
|
||||
if ((frameDropRatio > 1) && (frameCount % frameDropRatio) > 0) {
|
||||
camera.addCallbackBuffer(data);
|
||||
return;
|
||||
}
|
||||
long captureTimeMs = SystemClock.elapsedRealtime();
|
||||
if (frameCount > 1) {
|
||||
if (frameCount > frameDropRatio) {
|
||||
double durationMs = captureTimeMs - lastCaptureTimeMs;
|
||||
averageDurationMs = 0.9 * averageDurationMs + 0.1 * durationMs;
|
||||
if ((frameCount % 30) == 0) {
|
||||
|
@ -75,6 +75,36 @@ public class VideoCaptureDeviceInfoAndroid {
|
||||
sizes.put(size);
|
||||
}
|
||||
|
||||
boolean is30fpsRange = false;
|
||||
boolean is15fpsRange = false;
|
||||
// If there is constant 30 fps mode, but no 15 fps - add 15 fps
|
||||
// mode to the list of supported ranges. Frame drop will be done
|
||||
// in software.
|
||||
for (int[] range : supportedFpsRanges) {
|
||||
if (range[Parameters.PREVIEW_FPS_MIN_INDEX] == 30000 &&
|
||||
range[Parameters.PREVIEW_FPS_MAX_INDEX] == 30000) {
|
||||
is30fpsRange = true;
|
||||
}
|
||||
if (range[Parameters.PREVIEW_FPS_MIN_INDEX] == 15000 &&
|
||||
range[Parameters.PREVIEW_FPS_MAX_INDEX] == 15000) {
|
||||
is15fpsRange = true;
|
||||
}
|
||||
}
|
||||
if (is30fpsRange && !is15fpsRange) {
|
||||
Log.d(TAG, "Adding 15 fps support");
|
||||
int[] newRange = new int [Parameters.PREVIEW_FPS_MAX_INDEX + 1];
|
||||
newRange[Parameters.PREVIEW_FPS_MIN_INDEX] = 15000;
|
||||
newRange[Parameters.PREVIEW_FPS_MAX_INDEX] = 15000;
|
||||
for (int j = 0; j < supportedFpsRanges.size(); j++ ) {
|
||||
int[] range = supportedFpsRanges.get(j);
|
||||
if (range[Parameters.PREVIEW_FPS_MAX_INDEX] >
|
||||
newRange[Parameters.PREVIEW_FPS_MAX_INDEX]) {
|
||||
supportedFpsRanges.add(j, newRange);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JSONArray mfpsRanges = new JSONArray();
|
||||
for (int[] range : supportedFpsRanges) {
|
||||
JSONObject mfpsRange = new JSONObject();
|
||||
|
Loading…
x
Reference in New Issue
Block a user