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 42f1241380c04c4635acb4886f5e60c9ad3ba85d..7025a1de6f19aa14461866e6d101bcf69827908f 100644 |
--- a/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java |
+++ b/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java |
@@ -27,12 +27,20 @@ import org.chromium.base.JNINamespace; |
*/ |
@JNINamespace("media") |
class MediaCodecBridge { |
- |
private static final String TAG = "MediaCodecBridge"; |
// Error code for MediaCodecBridge. Keep this value in sync with |
- // INFO_MEDIA_CODEC_ERROR in media_codec_bridge.h. |
- private static final int MEDIA_CODEC_ERROR = -1000; |
+ // MediaCodecStatus in media_codec_bridge.h. |
+ private static final int MEDIA_CODEC_OK = 0; |
+ private static final int MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER = 1; |
+ private static final int MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER = 2; |
+ private static final int MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED = 3; |
+ private static final int MEDIA_CODEC_OUTPUT_FORMAT_CHANGED = 4; |
+ private static final int MEDIA_CODEC_INPUT_END_OF_STREAM = 5; |
+ private static final int MEDIA_CODEC_OUTPUT_END_OF_STREAM = 6; |
+ private static final int MEDIA_CODEC_NO_KEY = 7; |
+ private static final int MEDIA_CODEC_STOPPED = 8; |
+ private static final int MEDIA_CODEC_ERROR = 9; |
// After a flush(), dequeueOutputBuffer() can often produce empty presentation timestamps |
// for several frames. As a result, the player may find that the time does not increase |
@@ -50,15 +58,33 @@ class MediaCodecBridge { |
private boolean mFlushed; |
private long mLastPresentationTimeUs; |
+ private static class DequeueInputResult { |
+ private final int mStatus; |
+ private final int mIndex; |
+ |
+ private DequeueInputResult(int status, int index) { |
+ mStatus = status; |
+ mIndex = index; |
+ } |
+ |
+ @CalledByNative("DequeueInputResult") |
+ private int status() { return mStatus; } |
+ |
+ @CalledByNative("DequeueInputResult") |
+ private int index() { return mIndex; } |
+ } |
+ |
private static class DequeueOutputResult { |
+ private final int mStatus; |
private final int mIndex; |
private final int mFlags; |
private final int mOffset; |
private final long mPresentationTimeMicroseconds; |
private final int mNumBytes; |
- private DequeueOutputResult(int index, int flags, int offset, |
+ private DequeueOutputResult(int status, int index, int flags, int offset, |
long presentationTimeMicroseconds, int numBytes) { |
+ mStatus = status; |
mIndex = index; |
mFlags = flags; |
mOffset = offset; |
@@ -67,6 +93,9 @@ class MediaCodecBridge { |
} |
@CalledByNative("DequeueOutputResult") |
+ private int status() { return mStatus; } |
+ |
+ @CalledByNative("DequeueOutputResult") |
private int index() { return mIndex; } |
@CalledByNative("DequeueOutputResult") |
@@ -143,13 +172,24 @@ class MediaCodecBridge { |
} |
@CalledByNative |
- private int dequeueInputBuffer(long timeoutUs) { |
+ private DequeueInputResult dequeueInputBuffer(long timeoutUs) { |
+ int status = MEDIA_CODEC_ERROR; |
+ int index = -1; |
try { |
- return mMediaCodec.dequeueInputBuffer(timeoutUs); |
+ int index_or_status = mMediaCodec.dequeueInputBuffer(timeoutUs); |
+ if (index_or_status >= 0) { // index! |
+ status = MEDIA_CODEC_OK; |
+ index = index_or_status; |
+ } else if (index_or_status == MediaCodec.INFO_TRY_AGAIN_LATER) { |
+ Log.e(TAG, "dequeueInputBuffer: MediaCodec.INFO_TRY_AGAIN_LATER"); |
+ status = MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER; |
+ } else { |
+ assert(false); |
+ } |
} catch(Exception e) { |
- Log.e(TAG, "Cannot dequeue Input buffer " + e.toString()); |
+ Log.e(TAG, "Failed to dequeue input buffer: " + e.toString()); |
} |
- return MEDIA_CODEC_ERROR; |
+ return new DequeueInputResult(status, index); |
} |
@CalledByNative |
@@ -190,18 +230,20 @@ class MediaCodecBridge { |
} |
@CalledByNative |
- private void queueInputBuffer( |
+ private int queueInputBuffer( |
int index, int offset, int size, long presentationTimeUs, int flags) { |
resetLastPresentationTimeIfNeeded(presentationTimeUs); |
try { |
mMediaCodec.queueInputBuffer(index, offset, size, presentationTimeUs, flags); |
- } catch(IllegalStateException e) { |
- Log.e(TAG, "Failed to queue input buffer " + e.toString()); |
+ } catch(Exception e) { |
+ Log.e(TAG, "Failed to queue input buffer: " + e.toString()); |
+ return MEDIA_CODEC_ERROR; |
} |
+ return MEDIA_CODEC_OK; |
} |
@CalledByNative |
- private void queueSecureInputBuffer( |
+ private int queueSecureInputBuffer( |
int index, int offset, byte[] iv, byte[] keyId, int[] numBytesOfClearData, |
int[] numBytesOfEncryptedData, int numSubSamples, long presentationTimeUs) { |
resetLastPresentationTimeIfNeeded(presentationTimeUs); |
@@ -210,9 +252,19 @@ class MediaCodecBridge { |
cryptoInfo.set(numSubSamples, numBytesOfClearData, numBytesOfEncryptedData, |
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()); |
+ // TODO(xhwang): Replace hard coded value with constant/enum. |
+ if (e.getErrorCode() == 1) { |
+ Log.e(TAG, "No key available."); |
+ return MEDIA_CODEC_NO_KEY; |
+ } |
+ 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.toString()); |
+ return MEDIA_CODEC_ERROR; |
} |
+ return MEDIA_CODEC_OK; |
} |
@CalledByNative |
@@ -228,9 +280,10 @@ class MediaCodecBridge { |
@CalledByNative |
private DequeueOutputResult dequeueOutputBuffer(long timeoutUs) { |
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); |
- int index = MEDIA_CODEC_ERROR; |
+ int status = MEDIA_CODEC_ERROR; |
+ int index = -1; |
try { |
- index = mMediaCodec.dequeueOutputBuffer(info, timeoutUs); |
+ int index_or_status = mMediaCodec.dequeueOutputBuffer(info, timeoutUs); |
if (info.presentationTimeUs < mLastPresentationTimeUs) { |
// TODO(qinmin): return a special code through DequeueOutputResult |
// to notify the native code the the frame has a wrong presentation |
@@ -238,11 +291,25 @@ class MediaCodecBridge { |
info.presentationTimeUs = mLastPresentationTimeUs; |
} |
mLastPresentationTimeUs = info.presentationTimeUs; |
+ |
+ if (index_or_status >= 0) { // index! |
+ status = MEDIA_CODEC_OK; |
+ index = index_or_status; |
+ } else if (index_or_status == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) { |
+ status = MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED; |
+ } else if (index_or_status == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { |
+ status = MEDIA_CODEC_OUTPUT_FORMAT_CHANGED; |
+ } else if (index_or_status == MediaCodec.INFO_TRY_AGAIN_LATER) { |
+ status = MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER; |
+ } else { |
+ assert(false); |
+ } |
} catch (IllegalStateException e) { |
- Log.e(TAG, "Cannot dequeue output buffer " + e.toString()); |
+ Log.e(TAG, "Failed to dequeue output buffer: " + e.toString()); |
} |
+ |
return new DequeueOutputResult( |
- index, info.flags, info.offset, info.presentationTimeUs, info.size); |
+ status, index, info.flags, info.offset, info.presentationTimeUs, info.size); |
} |
@CalledByNative |