desc:使用surfaceView渲染视频
parent
be4c2b9c4f
commit
4d78e48101
@ -0,0 +1,214 @@
|
||||
package com.yinuo.library.vlc.encoder;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.hardware.Camera;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.view.Surface;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Created by liwentian on 2017/8/29.
|
||||
*/
|
||||
|
||||
public class CameraHelper {
|
||||
|
||||
public static final int MEDIA_TYPE_IMAGE = 1;
|
||||
public static final int MEDIA_TYPE_VIDEO = 2;
|
||||
|
||||
public static int getFrontCameraId() {
|
||||
int frontIdx = 0;
|
||||
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
|
||||
for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
|
||||
Camera.getCameraInfo(i, cameraInfo);
|
||||
|
||||
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
|
||||
frontIdx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return frontIdx;
|
||||
}
|
||||
|
||||
public static int getDisplayOrientation(Activity activity, int cameraId) {
|
||||
Camera.CameraInfo info = new Camera.CameraInfo();
|
||||
Camera.getCameraInfo(cameraId, info);
|
||||
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
|
||||
|
||||
int degrees = 0;
|
||||
switch (rotation) {
|
||||
case Surface.ROTATION_0:
|
||||
degrees = 0;
|
||||
break;
|
||||
case Surface.ROTATION_90:
|
||||
degrees = 90;
|
||||
break;
|
||||
case Surface.ROTATION_180:
|
||||
degrees = 180;
|
||||
break;
|
||||
case Surface.ROTATION_270:
|
||||
degrees = 270;
|
||||
break;
|
||||
}
|
||||
int result;
|
||||
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
|
||||
result = (info.orientation + degrees) % 360;
|
||||
result = (360 - result) % 360; // compensate the mirror
|
||||
} else {
|
||||
// back-facing
|
||||
result = (info.orientation - degrees + 360) % 360;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over supported camera video sizes to see which one best fits the
|
||||
* dimensions of the given view while maintaining the aspect ratio. If none can,
|
||||
* be lenient with the aspect ratio.
|
||||
*
|
||||
* @param supportedVideoSizes Supported camera video sizes.
|
||||
* @param previewSizes Supported camera preview sizes.
|
||||
* @param w The width of the view.
|
||||
* @param h The height of the view.
|
||||
* @return Best match camera video size to fit in the view.
|
||||
*/
|
||||
public static Camera.Size getOptimalVideoSize(List<Camera.Size> supportedVideoSizes,
|
||||
List<Camera.Size> previewSizes, int w, int h) {
|
||||
// Use a very small tolerance because we want an exact match.
|
||||
final double ASPECT_TOLERANCE = 0.1;
|
||||
double targetRatio = (double) w / h;
|
||||
|
||||
// Supported video sizes list might be null, it means that we are allowed to use the preview
|
||||
// sizes
|
||||
List<Camera.Size> videoSizes;
|
||||
if (supportedVideoSizes != null) {
|
||||
videoSizes = supportedVideoSizes;
|
||||
} else {
|
||||
videoSizes = previewSizes;
|
||||
}
|
||||
Camera.Size optimalSize = null;
|
||||
|
||||
// Start with max value and refine as we iterate over available video sizes. This is the
|
||||
// minimum difference between view and camera height.
|
||||
double minDiff = Double.MAX_VALUE;
|
||||
|
||||
// Target view height
|
||||
int targetHeight = h;
|
||||
|
||||
// Try to find a video size that matches aspect ratio and the target view size.
|
||||
// Iterate over all available sizes and pick the largest size that can fit in the view and
|
||||
// still maintain the aspect ratio.
|
||||
for (Camera.Size size : videoSizes) {
|
||||
double ratio = (double) size.width / size.height;
|
||||
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
|
||||
continue;
|
||||
if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) {
|
||||
optimalSize = size;
|
||||
minDiff = Math.abs(size.height - targetHeight);
|
||||
}
|
||||
}
|
||||
|
||||
// Cannot find video size that matches the aspect ratio, ignore the requirement
|
||||
if (optimalSize == null) {
|
||||
minDiff = Double.MAX_VALUE;
|
||||
for (Camera.Size size : videoSizes) {
|
||||
if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) {
|
||||
optimalSize = size;
|
||||
minDiff = Math.abs(size.height - targetHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
return optimalSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the default camera on the device. Return null if there is no camera on the device.
|
||||
*/
|
||||
public static Camera getDefaultCameraInstance() {
|
||||
int front = getFrontCameraId();
|
||||
return Camera.open(front);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the default rear/back facing camera on the device. Returns null if camera is not
|
||||
* available.
|
||||
*/
|
||||
public static Camera getDefaultBackFacingCameraInstance() {
|
||||
return getDefaultCamera(Camera.CameraInfo.CAMERA_FACING_BACK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the default front facing camera on the device. Returns null if camera is not
|
||||
* available.
|
||||
*/
|
||||
public static Camera getDefaultFrontFacingCameraInstance() {
|
||||
return getDefaultCamera(Camera.CameraInfo.CAMERA_FACING_FRONT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param position Physical position of the camera i.e Camera.CameraInfo.CAMERA_FACING_FRONT
|
||||
* or Camera.CameraInfo.CAMERA_FACING_BACK.
|
||||
* @return the default camera on the device. Returns null if camera is not available.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
|
||||
private static Camera getDefaultCamera(int position) {
|
||||
// Find the total number of cameras available
|
||||
int mNumberOfCameras = Camera.getNumberOfCameras();
|
||||
|
||||
// Find the ID of the back-facing ("default") camera
|
||||
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
|
||||
for (int i = 0; i < mNumberOfCameras; i++) {
|
||||
Camera.getCameraInfo(i, cameraInfo);
|
||||
if (cameraInfo.facing == position) {
|
||||
return Camera.open(i);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a media file in the {@code Environment.DIRECTORY_PICTURES} directory. The directory
|
||||
* is persistent and available to other applications like gallery.
|
||||
*
|
||||
* @param type Media type. Can be video or image.
|
||||
* @return A file object pointing to the newly created file.
|
||||
*/
|
||||
public static File getOutputMediaFile(int type, String name) {
|
||||
// To be safe, you should check that the SDCard is mounted
|
||||
// using Environment.getExternalStorageState() before doing this.
|
||||
if (!Environment.getExternalStorageState().equalsIgnoreCase(Environment.MEDIA_MOUNTED)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
File mediaStorageDir = Environment.getExternalStoragePublicDirectory("video");
|
||||
if (!mediaStorageDir.exists() && !mediaStorageDir.mkdirs()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create a media file name
|
||||
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date());
|
||||
File mediaFile;
|
||||
if (type == MEDIA_TYPE_IMAGE) {
|
||||
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
|
||||
"IMG_" + timeStamp + ".jpg");
|
||||
} else if (type == MEDIA_TYPE_VIDEO) {
|
||||
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
|
||||
"VID_" + timeStamp + "_" + name + ".mp4");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return mediaFile;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue