| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.media; | 5 package org.chromium.media; |
| 6 | 6 |
| 7 import android.annotation.TargetApi; | 7 import android.annotation.TargetApi; |
| 8 import android.media.AudioFormat; | 8 import android.media.AudioFormat; |
| 9 import android.media.MediaCodec; | 9 import android.media.MediaCodec; |
| 10 import android.media.MediaCodec.CryptoInfo; | 10 import android.media.MediaCodec.CryptoInfo; |
| 11 import android.media.MediaCrypto; | 11 import android.media.MediaCrypto; |
| 12 import android.media.MediaFormat; | 12 import android.media.MediaFormat; |
| 13 import android.os.Build; | 13 import android.os.Build; |
| 14 import android.os.Bundle; | 14 import android.os.Bundle; |
| 15 import android.view.Surface; | 15 import android.view.Surface; |
| 16 | 16 |
| 17 import org.chromium.base.Log; | 17 import org.chromium.base.Log; |
| 18 import org.chromium.base.annotations.CalledByNative; | 18 import org.chromium.base.annotations.CalledByNative; |
| 19 import org.chromium.base.annotations.JNINamespace; | 19 import org.chromium.base.annotations.JNINamespace; |
| 20 import org.chromium.base.annotations.MainDex; | 20 import org.chromium.base.annotations.MainDex; |
| 21 import org.chromium.media.MediaCodecUtil.BitrateAdjustmentTypes; | 21 import org.chromium.media.MediaCodecUtil.BitrateAdjustmentTypes; |
| 22 import org.chromium.media.MediaCodecUtil.MimeTypes; | 22 import org.chromium.media.MediaCodecUtil.MimeTypes; |
| 23 | 23 |
| 24 import java.nio.ByteBuffer; | 24 import java.nio.ByteBuffer; |
| 25 | 25 |
| 26 /** | 26 /** |
| 27 * A wrapper of the MediaCodec class to facilitate exception capturing and | 27 * A MediaCodec wrapper for adapting the API and catching exceptions. |
| 28 * audio rendering. | |
| 29 */ | 28 */ |
| 30 @JNINamespace("media") | 29 @JNINamespace("media") |
| 31 class MediaCodecBridge { | 30 class MediaCodecBridge { |
| 32 private static final String TAG = "cr_MediaCodecBridge"; | 31 private static final String TAG = "cr_MediaCodecBridge"; |
| 33 | 32 |
| 34 // Error code for MediaCodecBridge. Keep this value in sync with | 33 // Status codes. Keep these in sync with MediaCodecStatus in media_codec_bri
dge.h. |
| 35 // MediaCodecStatus in media_codec_bridge.h. | |
| 36 private static final int MEDIA_CODEC_OK = 0; | 34 private static final int MEDIA_CODEC_OK = 0; |
| 37 private static final int MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER = 1; | 35 private static final int MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER = 1; |
| 38 private static final int MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER = 2; | 36 private static final int MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER = 2; |
| 39 private static final int MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED = 3; | 37 private static final int MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED = 3; |
| 40 private static final int MEDIA_CODEC_OUTPUT_FORMAT_CHANGED = 4; | 38 private static final int MEDIA_CODEC_OUTPUT_FORMAT_CHANGED = 4; |
| 41 private static final int MEDIA_CODEC_INPUT_END_OF_STREAM = 5; | 39 private static final int MEDIA_CODEC_NO_KEY = 5; |
| 42 private static final int MEDIA_CODEC_OUTPUT_END_OF_STREAM = 6; | 40 private static final int MEDIA_CODEC_ERROR = 6; |
| 43 private static final int MEDIA_CODEC_NO_KEY = 7; | |
| 44 private static final int MEDIA_CODEC_ABORT = 8; | |
| 45 private static final int MEDIA_CODEC_ERROR = 9; | |
| 46 | 41 |
| 47 // After a flush(), dequeueOutputBuffer() can often produce empty presentati
on timestamps | 42 // After a flush(), dequeueOutputBuffer() can often produce empty presentati
on timestamps |
| 48 // for several frames. As a result, the player may find that the time does n
ot increase | 43 // for several frames. As a result, the player may find that the time does n
ot increase |
| 49 // after decoding a frame. To detect this, we check whether the presentation
timestamp from | 44 // after decoding a frame. To detect this, we check whether the presentation
timestamp from |
| 50 // dequeueOutputBuffer() is larger than input_timestamp - MAX_PRESENTATION_T
IMESTAMP_SHIFT_US | 45 // dequeueOutputBuffer() is larger than input_timestamp - MAX_PRESENTATION_T
IMESTAMP_SHIFT_US |
| 51 // after a flush. And we set the presentation timestamp from dequeueOutputBu
ffer() to be | 46 // after a flush. And we set the presentation timestamp from dequeueOutputBu
ffer() to be |
| 52 // non-decreasing for the remaining frames. | 47 // non-decreasing for the remaining frames. |
| 53 private static final long MAX_PRESENTATION_TIMESTAMP_SHIFT_US = 100000; | 48 private static final long MAX_PRESENTATION_TIMESTAMP_SHIFT_US = 100000; |
| 54 | 49 |
| 55 // We use only one output audio format (PCM16) that has 2 bytes per sample | 50 // We use only one output audio format (PCM16) that has 2 bytes per sample |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 info.mediaCodec, mime, info.supportsAdaptivePlayback, info.bitra
teAdjustmentType); | 229 info.mediaCodec, mime, info.supportsAdaptivePlayback, info.bitra
teAdjustmentType); |
| 235 } | 230 } |
| 236 | 231 |
| 237 @CalledByNative | 232 @CalledByNative |
| 238 private void release() { | 233 private void release() { |
| 239 try { | 234 try { |
| 240 String codecName = "unknown"; | 235 String codecName = "unknown"; |
| 241 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { | 236 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { |
| 242 codecName = mMediaCodec.getName(); | 237 codecName = mMediaCodec.getName(); |
| 243 } | 238 } |
| 244 Log.w(TAG, "calling MediaCodec.release() on " + codecName); | 239 // This logging is to help us identify hung MediaCodecs in crash rep
orts. |
| 240 Log.w(TAG, "Releasing: " + codecName); |
| 245 mMediaCodec.release(); | 241 mMediaCodec.release(); |
| 242 Log.w(TAG, "Codec released"); |
| 246 } catch (IllegalStateException e) { | 243 } catch (IllegalStateException e) { |
| 247 // The MediaCodec is stuck in a wrong state, possibly due to losing | 244 // The MediaCodec is stuck in a bad state, possibly due to losing |
| 248 // the surface. | 245 // the surface. |
| 249 Log.e(TAG, "Cannot release media codec", e); | 246 Log.e(TAG, "Cannot release media codec", e); |
| 250 } | 247 } |
| 251 mMediaCodec = null; | 248 mMediaCodec = null; |
| 252 } | 249 } |
| 253 | 250 |
| 254 @SuppressWarnings("deprecation") | 251 @SuppressWarnings("deprecation") |
| 255 @CalledByNative | 252 @CalledByNative |
| 256 private boolean start() { | 253 private boolean start() { |
| 257 try { | 254 try { |
| (...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 720 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | 717 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { |
| 721 return AudioFormat.CHANNEL_OUT_7POINT1_SURROUND; | 718 return AudioFormat.CHANNEL_OUT_7POINT1_SURROUND; |
| 722 } else { | 719 } else { |
| 723 return AudioFormat.CHANNEL_OUT_7POINT1; | 720 return AudioFormat.CHANNEL_OUT_7POINT1; |
| 724 } | 721 } |
| 725 default: | 722 default: |
| 726 return AudioFormat.CHANNEL_OUT_DEFAULT; | 723 return AudioFormat.CHANNEL_OUT_DEFAULT; |
| 727 } | 724 } |
| 728 } | 725 } |
| 729 } | 726 } |
| OLD | NEW |