Support Android API 19

Since "adb forward" fallback has been implemented, it is easy to support
API 19.

Replace the incompatible calls related to MediaCodec to use
minSdkVersion 19 instead of 21.
This commit is contained in:
Romain Vimont 2018-03-28 22:02:27 +02:00 committed by Eugen Pechanec
parent ed84e18b1a
commit 02b72e6653
No known key found for this signature in database
GPG key ID: 1E110C960179440E
3 changed files with 32 additions and 5 deletions

View file

@ -38,7 +38,7 @@ Its features include:
## Requirements
The Android device requires at least API 21 (Android 5.0).
The Android device requires at least API 19 (Android 4.4).
Make sure you [enable adb debugging][enable-adb] on your device(s).

View file

@ -4,7 +4,7 @@ android {
compileSdkVersion 31
defaultConfig {
applicationId "com.genymobile.scrcpy"
minSdkVersion 21
minSdkVersion 19
targetSdkVersion 31
versionCode 12400
versionName "1.24"

View file

@ -144,9 +144,11 @@ public class ScreenEncoder implements Device.RotationListener {
return 0;
}
@SuppressWarnings("deprecation") // Android API 19 requires to call deprecated methods
private boolean encode(MediaCodec codec, FileDescriptor fd) throws IOException {
boolean eof = false;
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
ByteBuffer[] cachedOutputBuffers = null;
while (!consumeRotationChange() && !eof) {
int outputBufferId = codec.dequeueOutputBuffer(bufferInfo, -1);
@ -157,7 +159,15 @@ public class ScreenEncoder implements Device.RotationListener {
break;
}
if (outputBufferId >= 0) {
ByteBuffer codecBuffer = codec.getOutputBuffer(outputBufferId);
ByteBuffer codecBuffer;
if (Build.VERSION.SDK_INT >= 21) {
codecBuffer = codec.getOutputBuffer(outputBufferId);
} else {
if (cachedOutputBuffers == null) {
cachedOutputBuffers = codec.getOutputBuffers();
}
codecBuffer = cachedOutputBuffers[outputBufferId];
}
if (sendFrameMeta) {
writeFrameMeta(fd, bufferInfo, codecBuffer.remaining());
@ -168,6 +178,8 @@ public class ScreenEncoder implements Device.RotationListener {
// If this is not a config packet, then it contains a frame
firstFrameSent = true;
}
} else if (outputBufferId == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
cachedOutputBuffers = null;
}
} finally {
if (outputBufferId >= 0) {
@ -201,10 +213,25 @@ public class ScreenEncoder implements Device.RotationListener {
IO.writeFully(fd, headerBuffer);
}
@SuppressWarnings("deprecation") // Android API 19 requires to call deprecated methods
private static MediaCodecInfo[] getCodecInfosCompat() {
if (Build.VERSION.SDK_INT >= 21) {
MediaCodecList list = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
return list.getCodecInfos();
} else {
final int size = MediaCodecList.getCodecCount();
final MediaCodecInfo[] infos = new MediaCodecInfo[size];
for (int i = 0; i < size; i++) {
infos[i] = MediaCodecList.getCodecInfoAt(i);
}
return infos;
}
}
private static MediaCodecInfo[] listEncoders() {
List<MediaCodecInfo> result = new ArrayList<>();
MediaCodecList list = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
for (MediaCodecInfo codecInfo : list.getCodecInfos()) {
MediaCodecInfo[] codecInfos = getCodecInfosCompat();
for (MediaCodecInfo codecInfo : codecInfos) {
if (codecInfo.isEncoder() && Arrays.asList(codecInfo.getSupportedTypes()).contains(MediaFormat.MIMETYPE_VIDEO_AVC)) {
result.add(codecInfo);
}