Skip to content

Commit

Permalink
the 1.0 version completed
Browse files Browse the repository at this point in the history
  • Loading branch information
HelloHuDi committed May 23, 2018
1 parent c0e9810 commit c3e0423
Show file tree
Hide file tree
Showing 21 changed files with 424 additions and 181 deletions.
Binary file modified .idea/caches/build_file_checksums.ser
Binary file not shown.
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,29 @@
<img width="72" height="72" src="art/ic_launcher-web.png"/>
</p>
<h3 align="center">ScreenCapture</h3>
<p align="center">
<a href="" target="_blank"><img src="https://img.shields.io/badge/release-v1.0-blue.svg"></img></a>
</p>

## create mp4 with MediaProjection,there is no voice for the time being

## according to ScreenRecorder[1] adaptation,thanks [Yrom Wang](https://github.com/yrom)

## usage:

### dependencies :

```
dependencies {
//...
implementation 'com.hd:screencapture:1.0'
}
```

### code

```
ScreenCapture.with(activity).startCapture();
```

## create mp4 with MediaProjection
[1]: https://github.com/yrom/ScreenRecorder
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ dependencies {
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation project(':screencapture')
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.4'
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
}
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

<application
android:allowBackup="true"
android:name=".CaptureApp"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
Expand Down
23 changes: 23 additions & 0 deletions app/src/main/java/com/hd/screen/capture/CaptureApp.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.hd.screen.capture;

import android.app.Application;

import com.squareup.leakcanary.LeakCanary;


/**
* Created by hd on 2018/5/23 .
*/
public class CaptureApp extends Application {
@Override
public void onCreate() {
super.onCreate();
if (LeakCanary.isInAnalyzerProcess(this)) {
// This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process.
return;
}
LeakCanary.install(this);
// Normal app init code...
}
}
92 changes: 92 additions & 0 deletions app/src/main/java/com/hd/screen/capture/LogConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package com.hd.screen.capture;

import android.media.MediaCodecInfo;
import android.util.Log;
import android.util.Range;

import com.hd.screencapture.config.AudioConfig;
import com.hd.screencapture.config.VideoConfig;
import com.hd.screencapture.help.Utils;

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

/**
* Created by hd on 2018/5/23 .
*/
public final class LogConfig {

/**
* when you don't understand how to use config{@link VideoConfig}{@link AudioConfig},
* maybe these parameters can help you.
*/
public static 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)));
}
}
}
}
128 changes: 17 additions & 111 deletions app/src/main/java/com/hd/screen/capture/MainActivity.java
Original file line number Diff line number Diff line change
@@ -1,89 +1,63 @@
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;

import com.hd.screencapture.ScreenCapture;
import com.hd.screencapture.callback.ScreenCaptureStreamCallback;
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;


/**
* Created by hd on 2018/5/14 .
*/
public class MainActivity extends AppCompatActivity implements ScreenCaptureStreamCallback {

private ScreenCapture screenCapture;

private boolean isRunning;

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

private ExecutorUtil executorUtil;

private ScreenCapturePresenter screenCapturePresenter;

@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);
log();
//LogConfig.log();
init();
}

private void init() {
tvState = findViewById(R.id.tvState);
tvTime = findViewById(R.id.tvTime);
tvVideoHeaderData = findViewById(R.id.tvVideoHeaderData);
tvVideoData = findViewById(R.id.tvVideoData);
tvAudioData = findViewById(R.id.tvAudioData);
executorUtil = new ExecutorUtil();
ScreenCaptureConfig captureConfig = new ScreenCaptureConfig.Builder()//
.setAllowLog(false/*BuildConfig.DEBUG*/)//
.setVideoConfig(VideoConfig.initDefaultConfig(this))//
.setAudioConfig(AudioConfig.initDefaultConfig())//
.setCaptureCallback(this)//
.setAutoMoveTaskToBack(true)//
.create();//
screenCapture = ScreenCapture.with(this).setConfig(captureConfig);
screenCapturePresenter=new ScreenCapturePresenter(this);
}

public void startCapture(View view) {
if (!isRunning) {
screenCapture.startCapture();
} else {
Toast.makeText(MainActivity.this, "current is capturing state", Toast.LENGTH_SHORT).show();
}
screenCapturePresenter.startCapture();
}

public void stopCapture(View view) {
if (isRunning) {
screenCapture.stopCapture();
} else {
Toast.makeText(MainActivity.this, "current is stopped state", Toast.LENGTH_SHORT).show();
}
screenCapturePresenter.stopCapture();
}

@SuppressLint("SetTextI18n")
@Override
public void captureState(ScreenCaptureState state) {
isRunning = !(ScreenCaptureState.FAILED == state || ScreenCaptureState.COMPLETED == state);
Log.d("tag", "capture state ==>" + state + "==" + isRunning);
executorUtil.mainThread().execute(() -> Toast.makeText(MainActivity.this, "capture state ==>" + state, Toast.LENGTH_SHORT).show());
executorUtil.mainThread().execute(() ->{
tvState.setText("capture state ==>" + state);
Toast.makeText(MainActivity.this, "capture state ==>" + state, Toast.LENGTH_SHORT).show();
});
}

@SuppressLint("SetTextI18n")
Expand Down Expand Up @@ -113,72 +87,4 @@ public void audioContentByte(@NonNull byte[] content) {
//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
@@ -0,0 +1,55 @@
package com.hd.screen.capture;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;

import com.hd.screencapture.ScreenCapture;
import com.hd.screencapture.callback.ScreenCaptureStreamCallback;
import com.hd.screencapture.config.ScreenCaptureConfig;
import com.hd.screencapture.config.VideoConfig;

/**
* Created by hd on 2018/5/23 .
*/
public class ScreenCapturePresenter {

private ScreenCapture screenCapture;

private Context context;

ScreenCapturePresenter(@NonNull AppCompatActivity activity) {
this.context=activity.getApplicationContext();
initCapture(activity);
}

private void initCapture(AppCompatActivity activity) {
ScreenCaptureConfig captureConfig = new ScreenCaptureConfig.Builder()//
.setAllowLog(BuildConfig.DEBUG)//
.setVideoConfig(VideoConfig.initDefaultConfig(activity))//
//not completed
//.setAudioConfig(AudioConfig.initDefaultConfig())//
.setCaptureCallback((ScreenCaptureStreamCallback) activity)//
.setAutoMoveTaskToBack(true)//
.create();//
screenCapture = ScreenCapture.with(activity).setConfig(captureConfig);
}

public void startCapture() {
if (!screenCapture.isRunning()) {
screenCapture.startCapture();
} else {
Toast.makeText(context, "current is capturing state", Toast.LENGTH_SHORT).show();
}
}

public void stopCapture() {
if (screenCapture.isRunning()) {
screenCapture.stopCapture();
} else {
Toast.makeText(context, "current is stopped state", Toast.LENGTH_SHORT).show();
}
}

}
Loading

0 comments on commit c3e0423

Please sign in to comment.