Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(685)

Unified Diff: media/base/android/java/src/org/chromium/media/MediaCodecBridge.java

Issue 74563002: AndroidVideoEncodeAccelerator is born! (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
diff --git a/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java b/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
index d8e576fb34f2bc50e918462cc980c6a35b6f0cc5..d762408d9ba64d9afc58b82f2ba1c35572fdd6e3 100644
--- a/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
+++ b/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
@@ -13,12 +13,14 @@ import android.media.MediaCodecList;
import android.media.MediaCrypto;
import android.media.MediaFormat;
import android.os.Build;
+import android.os.Bundle;
import android.util.Log;
import android.view.Surface;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@@ -84,10 +86,13 @@ class MediaCodecBridge {
private static class CodecInfo {
private final String mCodecType; // e.g. "video/x-vnd.on2.vp8".
private final String mCodecName; // e.g. "OMX.google.vp8.decoder".
+ private final boolean mIsEncoder;
- private CodecInfo(String codecType, String codecName) {
+ private CodecInfo(String codecType, String codecName,
+ boolean isEncoder) {
mCodecType = codecType;
mCodecName = codecName;
+ mIsEncoder = isEncoder;
}
@CalledByNative("CodecInfo")
@@ -95,6 +100,9 @@ class MediaCodecBridge {
@CalledByNative("CodecInfo")
private String codecName() { return mCodecName; }
+
+ @CalledByNative("CodecInfo")
+ private boolean isEncoder() { return mIsEncoder; }
}
private static class DequeueOutputResult {
@@ -139,25 +147,27 @@ class MediaCodecBridge {
*/
@CalledByNative
private static CodecInfo[] getCodecsInfo() {
- Map<String, CodecInfo> CodecInfoMap = new HashMap<String, CodecInfo>();
+ Map<String, CodecInfo> encoderInfoMap = new HashMap<String, CodecInfo>();
+ Map<String, CodecInfo> decoderInfoMap = new HashMap<String, CodecInfo>();
xhwang 2013/11/19 00:11:25 It's a bit odd to have two maps here then merge th
Ami GONE FROM CHROMIUM 2013/11/21 22:59:07 Agreed.
int count = MediaCodecList.getCodecCount();
for (int i = 0; i < count; ++i) {
MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
- if (info.isEncoder()) {
- continue;
- }
-
+ boolean isEncoder = info.isEncoder();
String codecString = info.getName();
String[] supportedTypes = info.getSupportedTypes();
for (int j = 0; j < supportedTypes.length; ++j) {
- if (!CodecInfoMap.containsKey(supportedTypes[j])) {
- CodecInfoMap.put(supportedTypes[j], new CodecInfo(
- supportedTypes[j], codecString));
+ Map<String, CodecInfo> map = isEncoder ? encoderInfoMap : decoderInfoMap;
+ if (!map.containsKey(supportedTypes[j])) {
+ map.put(supportedTypes[j], new CodecInfo(
+ supportedTypes[j], codecString, isEncoder));
}
}
}
- return CodecInfoMap.values().toArray(
- new CodecInfo[CodecInfoMap.size()]);
+ ArrayList<CodecInfo> codecInfos = new ArrayList<CodecInfo>(
+ decoderInfoMap.size() + encoderInfoMap.size());
+ codecInfos.addAll(encoderInfoMap.values());
+ codecInfos.addAll(decoderInfoMap.values());
+ return codecInfos.toArray(new CodecInfo[codecInfos.size()]);
}
private static String getSecureDecoderNameForMime(String mime) {
@@ -187,7 +197,7 @@ class MediaCodecBridge {
}
@CalledByNative
- private static MediaCodecBridge create(String mime, boolean isSecure) {
+ private static MediaCodecBridge create(String mime, boolean isSecure, boolean isEncoder) {
// Creation of ".secure" codecs sometimes crash instead of throwing exceptions
// on pre-JBMR2 devices.
if (isSecure && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
@@ -196,14 +206,18 @@ class MediaCodecBridge {
MediaCodec mediaCodec = null;
try {
// |isSecure| only applies to video decoders.
- if (mime.startsWith("video") && isSecure) {
+ if (mime.startsWith("video") && isSecure && !isEncoder) {
mediaCodec = MediaCodec.createByCodecName(getSecureDecoderNameForMime(mime));
} else {
- mediaCodec = MediaCodec.createDecoderByType(mime);
+ if (isEncoder) {
+ mediaCodec = MediaCodec.createEncoderByType(mime);
+ } else {
+ mediaCodec = MediaCodec.createDecoderByType(mime);
+ }
}
} catch (Exception e) {
Log.e(TAG, "Failed to create MediaCodec: " + mime + ", isSecure: "
- + isSecure + ", " + e.toString());
+ + isSecure + ", isEncoder: " + isEncoder, e);
}
if (mediaCodec == null) {
@@ -215,7 +229,10 @@ class MediaCodecBridge {
@CalledByNative
private void release() {
+ String name = mMediaCodec.getName();
+ mMediaCodec.stop();
mMediaCodec.release();
+ mMediaCodec = null;
if (mAudioTrack != null) {
mAudioTrack.release();
}
@@ -227,7 +244,7 @@ class MediaCodecBridge {
mMediaCodec.start();
mInputBuffers = mMediaCodec.getInputBuffers();
} catch (IllegalStateException e) {
- Log.e(TAG, "Cannot start the media codec " + e.toString());
+ Log.e(TAG, "Cannot start the media codec", e);
return false;
}
return true;
@@ -246,10 +263,11 @@ class MediaCodecBridge {
Log.e(TAG, "dequeueInputBuffer: MediaCodec.INFO_TRY_AGAIN_LATER");
status = MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER;
} else {
+ Log.e(TAG, "Unexpected index_or_status: " + index_or_status);
assert(false);
}
} catch(Exception e) {
- Log.e(TAG, "Failed to dequeue input buffer: " + e.toString());
+ Log.e(TAG, "Failed to dequeue input buffer", e);
}
return new DequeueInputResult(status, index);
}
@@ -263,7 +281,7 @@ class MediaCodecBridge {
}
mMediaCodec.flush();
} catch(IllegalStateException e) {
- Log.e(TAG, "Failed to flush MediaCodec " + e.toString());
+ Log.e(TAG, "Failed to flush MediaCodec", e);
return MEDIA_CODEC_ERROR;
}
return MEDIA_CODEC_OK;
@@ -304,13 +322,27 @@ class MediaCodecBridge {
try {
mMediaCodec.queueInputBuffer(index, offset, size, presentationTimeUs, flags);
} catch(Exception e) {
- Log.e(TAG, "Failed to queue input buffer: " + e.toString());
+ Log.e(TAG, "Failed to queue input buffer", e);
return MEDIA_CODEC_ERROR;
}
return MEDIA_CODEC_OK;
}
@CalledByNative
+ private void setVideoBitrate(int bps) {
+ Bundle b = new Bundle();
+ b.putInt(MediaCodec.PARAMETER_KEY_VIDEO_BITRATE, bps);
+ mMediaCodec.setParameters(b);
+ }
+
+ @CalledByNative
+ private void requestKeyFrameSoon() {
+ Bundle b = new Bundle();
+ b.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
+ mMediaCodec.setParameters(b);
+ }
+
+ @CalledByNative
private int queueSecureInputBuffer(
int index, int offset, byte[] iv, byte[] keyId, int[] numBytesOfClearData,
int[] numBytesOfEncryptedData, int numSubSamples, long presentationTimeUs) {
@@ -321,7 +353,7 @@ class MediaCodecBridge {
keyId, iv, MediaCodec.CRYPTO_MODE_AES_CTR);
mMediaCodec.queueSecureInputBuffer(index, offset, cryptoInfo, presentationTimeUs, 0);
} catch (MediaCodec.CryptoException e) {
- Log.e(TAG, "Failed to queue secure input buffer: " + e.toString());
+ Log.e(TAG, "Failed to queue secure input buffer", e);
// TODO(xhwang): Replace hard coded value with constant/enum.
if (e.getErrorCode() == 1) {
Log.e(TAG, "No key available.");
@@ -329,7 +361,7 @@ class MediaCodecBridge {
}
return MEDIA_CODEC_ERROR;
} catch(IllegalStateException e) {
- Log.e(TAG, "Failed to queue secure input buffer: " + e.toString());
+ Log.e(TAG, "Failed to queue secure input buffer", e);
return MEDIA_CODEC_ERROR;
}
return MEDIA_CODEC_OK;
@@ -341,11 +373,26 @@ class MediaCodecBridge {
}
@CalledByNative
+ private int getInputBuffersCount() {
+ return mInputBuffers.length;
+ }
+
+ @CalledByNative
+ private int getOutputBuffersCount() {
+ return mOutputBuffers != null ? mOutputBuffers.length : -1;
+ }
+
+ @CalledByNative
+ private int getOutputBuffersCapacity() {
+ return mOutputBuffers != null ? mOutputBuffers[0].capacity() : -1;
+ }
+
+ @CalledByNative
private boolean getOutputBuffers() {
try {
mOutputBuffers = mMediaCodec.getOutputBuffers();
} catch (IllegalStateException e) {
- Log.e(TAG, "Cannot get output buffers " + e.toString());
+ Log.e(TAG, "Cannot get output buffers", e);
return false;
}
return true;
@@ -376,10 +423,11 @@ class MediaCodecBridge {
} else if (index_or_status == MediaCodec.INFO_TRY_AGAIN_LATER) {
status = MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER;
} else {
+ Log.e(TAG, "Unexpected index_or_status: " + index_or_status);
assert(false);
}
} catch (IllegalStateException e) {
- Log.e(TAG, "Failed to dequeue output buffer: " + e.toString());
+ Log.e(TAG, "Failed to dequeue output buffer", e);
}
return new DequeueOutputResult(
@@ -393,7 +441,7 @@ class MediaCodecBridge {
mMediaCodec.configure(format, surface, crypto, flags);
return true;
} catch (IllegalStateException e) {
- Log.e(TAG, "Cannot configure the video codec " + e.toString());
+ Log.e(TAG, "Cannot configure the video codec", e);
}
return false;
}
@@ -404,11 +452,22 @@ class MediaCodecBridge {
}
@CalledByNative
- private static MediaFormat createVideoFormat(String mime, int width, int height) {
+ private static MediaFormat createVideoDecoderFormat(String mime, int width, int height) {
return MediaFormat.createVideoFormat(mime, width, height);
}
@CalledByNative
+ private static MediaFormat createVideoEncoderFormat(String mime, int width, int height,
+ int bitRate, int frameRate, int iFrameInterval, int colorFormat) {
+ MediaFormat format = MediaFormat.createVideoFormat(mime, width, height);
+ format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
+ format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
+ format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, iFrameInterval);
+ format.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
+ return format;
+ }
+
+ @CalledByNative
private static void setCodecSpecificData(MediaFormat format, int index, byte[] bytes) {
String name = null;
if (index == 0) {
@@ -445,7 +504,7 @@ class MediaCodecBridge {
}
return true;
} catch (IllegalStateException e) {
- Log.e(TAG, "Cannot configure the audio codec " + e.toString());
+ Log.e(TAG, "Cannot configure the audio codec", e);
}
return false;
}

Powered by Google App Engine
This is Rietveld 408576698