Skip to content

Commit

Permalink
video capture completed
Browse files Browse the repository at this point in the history
  • Loading branch information
HelloHuDi committed May 22, 2018
1 parent 6fb64eb commit c0e9810
Show file tree
Hide file tree
Showing 9 changed files with 528 additions and 60 deletions.
117 changes: 100 additions & 17 deletions app/src/main/java/com/hd/screen/capture/MainActivity.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.hd.screen.capture;

import android.annotation.SuppressLint;
import android.media.MediaCodecInfo;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.text.format.DateUtils;
import android.util.Log;
import android.util.Range;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
Expand All @@ -15,7 +17,13 @@
import com.hd.screencapture.config.AudioConfig;
import com.hd.screencapture.config.ScreenCaptureConfig;
import com.hd.screencapture.config.VideoConfig;
import com.hd.screencapture.help.ExecutorUtil;
import com.hd.screencapture.help.ScreenCaptureState;
import com.hd.screencapture.help.Utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


/**
Expand All @@ -27,27 +35,31 @@ public class MainActivity extends AppCompatActivity implements ScreenCaptureStre

private boolean isRunning;

private TextView tvTime,tvVideoHeaderData,tvVideoData,tvAudioData;
private TextView tvTime, tvVideoHeaderData, tvVideoData, tvAudioData;

private ExecutorUtil executorUtil;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvTime=findViewById(R.id.tvTime);
tvVideoHeaderData=findViewById(R.id.tvVideoHeaderData);
tvVideoData=findViewById(R.id.tvVideoData);
tvAudioData=findViewById(R.id.tvAudioData);
tvTime = findViewById(R.id.tvTime);
tvVideoHeaderData = findViewById(R.id.tvVideoHeaderData);
tvVideoData = findViewById(R.id.tvVideoData);
tvAudioData = findViewById(R.id.tvAudioData);
log();
init();
}

private void init() {
executorUtil = new ExecutorUtil();
ScreenCaptureConfig captureConfig = new ScreenCaptureConfig.Builder()//
.setAllowLog(BuildConfig.DEBUG)
.setVideoConfig(VideoConfig.initDefaultConfig(this))//
.setAudioConfig(AudioConfig.initDefaultConfig())//
.setCaptureCallback(this)//
.setAutoMoveTaskToBack(true)//
.create();//
.setAllowLog(false/*BuildConfig.DEBUG*/)//
.setVideoConfig(VideoConfig.initDefaultConfig(this))//
.setAudioConfig(AudioConfig.initDefaultConfig())//
.setCaptureCallback(this)//
.setAutoMoveTaskToBack(true)//
.create();//
screenCapture = ScreenCapture.with(this).setConfig(captureConfig);
}

Expand All @@ -71,31 +83,102 @@ public void stopCapture(View view) {
public void captureState(ScreenCaptureState state) {
isRunning = !(ScreenCaptureState.FAILED == state || ScreenCaptureState.COMPLETED == state);
Log.d("tag", "capture state ==>" + state + "==" + isRunning);
runOnUiThread(() -> Toast.makeText(MainActivity.this, "capture state ==>" + state, Toast.LENGTH_SHORT).show());
executorUtil.mainThread().execute(() -> Toast.makeText(MainActivity.this, "capture state ==>" + state, Toast.LENGTH_SHORT).show());
}

@SuppressLint("SetTextI18n")
@Override
public void captureTime(long time) {
runOnUiThread(() -> tvTime.setText("capture time ==>"+ DateUtils.formatElapsedTime(time)));
executorUtil.mainThread().execute(() -> tvTime.setText("capture time ==>" + DateUtils.formatElapsedTime(time)));
}

@SuppressLint("SetTextI18n")
@Override
public void videoHeaderByte(@NonNull byte[] sps, @NonNull byte[] pps) {
runOnUiThread(() -> tvVideoHeaderData.setText("video header byte length ==> sps len: " + sps.length +", pps len : "+ pps.length));
executorUtil.mainThread().execute(() -> tvVideoHeaderData.setText("video header byte length ==> sps len: " + sps.length + ", pps len : " + pps.length));
//executorUtil.networkIO().execute();
}

@SuppressLint("SetTextI18n")
@Override
public void videoContentByte(@NonNull byte[] content) {
runOnUiThread(() -> tvVideoData.setText("video content byte len ==> " + content.length));

executorUtil.mainThread().execute(() -> tvVideoData.setText("video content byte len ==> " + content.length));
//executorUtil.networkIO().execute();
}

@SuppressLint("SetTextI18n")
@Override
public void audioContentByte(@NonNull byte[] content) {
runOnUiThread(() -> tvAudioData.setText("audio content byte len ==> " + content.length));
executorUtil.mainThread().execute(() -> tvAudioData.setText("audio content byte len ==> " + content.length));
//executorUtil.networkIO().execute();
}

private void log() {
MediaCodecInfo[] videoInfos = Utils.findAllVideoEncoder();
MediaCodecInfo[] audioInfos = Utils.findAllAudioEncoder();
String[] videoCodecName = Utils.findAllVideoCodecName();
String[] audioCodecName = Utils.findAllAudioCodecName();
Log.d("tag", "\nall ========" + Arrays.toString(videoInfos)//
+ "\n========" + Arrays.toString(audioInfos)//
+ "\n========" + Arrays.toString(videoCodecName)//
+ "\n========" + Arrays.toString(audioCodecName)//
+ "\n========" + Arrays.toString(Utils.aacProfiles()));
for (String codecName : videoCodecName) {
MediaCodecInfo.CodecProfileLevel[] levels = Utils.findVideoProfileLevel(codecName);
MediaCodecInfo.CodecCapabilities capabilities = Utils.findVideoCodecCapabilities(codecName);
for (MediaCodecInfo.CodecProfileLevel level : levels) {
Log.d("tag", "\nvideoCodecName : " + codecName + " ,level========" + level.level //
+ "\n========" + level.profile //
+ "\n========" + Utils.avcProfileLevelToString(level)//
+ "\n========" + Utils.toProfileLevel(Utils.avcProfileLevelToString(level)));
}
Range<Integer> videoBitrateRange = capabilities.getVideoCapabilities().getBitrateRange();
Range<Integer> videoFrameRatesRange = capabilities.getVideoCapabilities().getSupportedFrameRates();

Log.d("tag", "\nvideoCodecName : " + codecName + "=======" + videoBitrateRange//
+ "\n========" + videoFrameRatesRange);

int[] videoColorFormats = capabilities.colorFormats;
Log.d("tag", "\nvideoCodecName : " + codecName + "==videoColorFormats:" + Arrays.toString(videoColorFormats));
for (int colorFormat : videoColorFormats) {
Log.d("tag", "\nvideoCodecName : " + codecName //
+ "\n=======colorFormat :" + Utils.toHumanReadable(colorFormat)//
+ "\n=======" + Utils.toColorFormat(Utils.toHumanReadable(colorFormat)));
}
}
for (String codecName : audioCodecName) {
MediaCodecInfo.CodecProfileLevel[] levels = Utils.findAudioProfileLevel(codecName);
MediaCodecInfo.CodecCapabilities capabilities = Utils.findAudioCodecCapabilities(codecName);
for (MediaCodecInfo.CodecProfileLevel level : levels) {
Log.d("tag", "\naudioCodecName : " + codecName + " ,level========" + level.level //
+ "\n========" + level.profile);
}
Range<Integer> audioBitrateRange = capabilities.getAudioCapabilities().getBitrateRange();
Range<Integer>[] audioSampleRateRanges = capabilities.getAudioCapabilities().getSupportedSampleRateRanges();
int[] audioSampleRates = capabilities.getAudioCapabilities().getSupportedSampleRates();

//
int lower = Math.max(audioBitrateRange.getLower() / 1000, 80);
int upper = audioBitrateRange.getUpper() / 1000;
List<Integer> rates = new ArrayList<>();
for (int rate = lower; rate < upper; rate += lower) {
rates.add(rate);
}
rates.add(upper);

Log.d("tag", "\naudioCodecName : " + codecName + "=======" + audioBitrateRange //
+ "\n========" + rates//
+ "\n========" + Arrays.toString(audioSampleRateRanges) //
+ "\n========" + Arrays.toString(audioSampleRates));


int[] audioColorFormats = capabilities.colorFormats;
Log.d("tag", "\naudioCodecName : " + codecName + "==audioColorFormats:" + Arrays.toString(audioColorFormats));
for (int colorFormat : audioColorFormats) {
Log.d("tag", "\naudioCodecName : " + codecName//
+ "\n=======colorFormat :" + Utils.toHumanReadable(colorFormat)//
+ "\n=======" + Utils.toColorFormat(Utils.toHumanReadable(colorFormat)));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,17 @@ public static ScreenCapture with(@NonNull AppCompatActivity activity) {
if (!Utils.isExternalStorageReady()) {
Log.e(TAG, "current no storage space");
}
if(!Utils.isPermissionGranted(activity,false)){
Log.e(TAG, "no permission !!!");
}
return new ScreenCapture(activity);
}

private ScreenCaptureFragment screenCaptureFragment;

private CaptureObserver observer;

protected AtomicBoolean capture = new AtomicBoolean(false);
private AtomicBoolean capture = new AtomicBoolean(false);

private ScreenCapture(@NonNull AppCompatActivity activity) {
//add lifecycle observer
Expand Down Expand Up @@ -108,6 +111,7 @@ public void run() {

public void stopCapture() {
if (isRunning()) {
capture.set(false);
screenCaptureFragment.stopCapture();
} else {
Log.e(TAG, "stop capture always");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import android.media.MediaFormat;
import android.os.Build;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;
import android.view.Surface;

Expand All @@ -17,14 +18,14 @@
import java.nio.ByteBuffer;
import java.util.Objects;

import static android.content.ContentValues.TAG;

/**
* Created by hd on 2018/5/20 .
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class VideoRecorder extends Recorder {

private final String TAG = "VideoRecorder";

private Surface surface;

private MediaCodec mEncoder;
Expand Down Expand Up @@ -81,20 +82,29 @@ private MediaFormat createMediaFormat() {
format.setInteger(MediaFormat.KEY_BIT_RATE, config.getVideoConfig().getBitrate());
format.setInteger(MediaFormat.KEY_FRAME_RATE, config.getVideoConfig().getFrameRate());
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, config.getVideoConfig().getIFrameInterval());
if(config.allowLog())
Log.d(TAG, "created video format: " + format);
MediaCodecInfo.CodecProfileLevel codecProfileLevel=config.getVideoConfig().getLevel();
if (codecProfileLevel != null && codecProfileLevel.profile != 0 && codecProfileLevel.level != 0) {
format.setInteger(MediaFormat.KEY_PROFILE, codecProfileLevel.profile);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
format.setInteger(MediaFormat.KEY_LEVEL, codecProfileLevel.level);
}else{
format.setInteger("level", codecProfileLevel.level);
}
}
if (config.allowLog())
Log.d(TAG, "created video format: " + format);
return format;
}

private MediaCodec createEncoder(String mimeType) throws IOException {
// try {
// // use codec name first
// if (this.mCodecName != null) {
// return MediaCodec.createByCodecName(mCodecName);
// }
// } catch (IOException e) {
// Log.w("@@", "Create MediaCodec by name '" + mCodecName + "' failure!", e);
// }
String mCodecName = config.getVideoConfig().getCodecName();
try {
if (!TextUtils.isEmpty(mCodecName)) {
return MediaCodec.createByCodecName(mCodecName);
}
} catch (IOException e) {
Log.w(TAG, "Create MediaCodec by name '" + mCodecName + "' failure!", e);
}
return MediaCodec.createEncoderByType(mimeType);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package com.hd.screencapture.config;

import android.media.AudioFormat;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;

import com.hd.screencapture.help.Utils;

/**
* Created by hd on 2018/5/18 .
Expand All @@ -13,6 +18,18 @@ public class AudioConfig extends CaptureConfig{

private int bitrate = AudioFormat.ENCODING_PCM_16BIT;

/**
* {@link Utils#findAllAudioCodecName()}
* {@link MediaCodec#createByCodecName(String)}
*/
private String codecName;

/**
* {@link Utils#findAudioProfileLevel(String)}
* {@link MediaFormat#KEY_AAC_PROFILE}
*/
private MediaCodecInfo.CodecProfileLevel level;

public static AudioConfig initDefaultConfig() {
return new AudioConfig();
}
Expand Down Expand Up @@ -40,4 +57,20 @@ public int getBitrate() {
public void setBitrate(int bitrate) {
this.bitrate = bitrate;
}

public String getCodecName() {
return codecName;
}

public void setCodecName(String codecName) {
this.codecName = codecName;
}

public MediaCodecInfo.CodecProfileLevel getLevel() {
return level;
}

public void setLevel(MediaCodecInfo.CodecProfileLevel level) {
this.level = level;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
import com.hd.screencapture.callback.ScreenCaptureCallback;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
* Created by hd on 2018/5/14 .
Expand Down Expand Up @@ -42,8 +45,8 @@ public class ScreenCaptureConfig extends CaptureConfig {
* screen capture file
*/
private File file = new File(
Environment.getExternalStorageDirectory(), //
"screen_capture_" + System.currentTimeMillis() + ".mp4");
Environment.getExternalStorageDirectory(), "screen_capture_" //
+ new SimpleDateFormat("yyyyMMdd-HH-mm-ss", Locale.US).format(new Date()) + ".mp4");

/**
* not provided voice recording by default
Expand Down
Loading

0 comments on commit c0e9810

Please sign in to comment.