| 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; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 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 MediaCodec wrapper for adapting the API and catching exceptions. | 27 * A MediaCodec wrapper for adapting the API and catching exceptions. |
| 28 */ | 28 */ |
| 29 @JNINamespace("media") | 29 @JNINamespace("media") |
| 30 class MediaCodecBridge { | 30 class MediaCodecBridge { |
| 31 private static final String TAG = "cr_MediaCodecBridge"; | 31 private static final String TAG = "cr.MediaCodecBridge"; |
| 32 | |
| 33 // Status codes. Keep these in sync with MediaCodecStatus in media_codec_bri
dge.h. | |
| 34 private static final int MEDIA_CODEC_OK = 0; | |
| 35 private static final int MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER = 1; | |
| 36 private static final int MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER = 2; | |
| 37 private static final int MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED = 3; | |
| 38 private static final int MEDIA_CODEC_OUTPUT_FORMAT_CHANGED = 4; | |
| 39 private static final int MEDIA_CODEC_NO_KEY = 5; | |
| 40 private static final int MEDIA_CODEC_ERROR = 6; | |
| 41 | 32 |
| 42 // After a flush(), dequeueOutputBuffer() can often produce empty presentati
on timestamps | 33 // After a flush(), dequeueOutputBuffer() can often produce empty presentati
on timestamps |
| 43 // for several frames. As a result, the player may find that the time does n
ot increase | 34 // for several frames. As a result, the player may find that the time does n
ot increase |
| 44 // after decoding a frame. To detect this, we check whether the presentation
timestamp from | 35 // after decoding a frame. To detect this, we check whether the presentation
timestamp from |
| 45 // dequeueOutputBuffer() is larger than input_timestamp - MAX_PRESENTATION_T
IMESTAMP_SHIFT_US | 36 // dequeueOutputBuffer() is larger than input_timestamp - MAX_PRESENTATION_T
IMESTAMP_SHIFT_US |
| 46 // after a flush. And we set the presentation timestamp from dequeueOutputBu
ffer() to be | 37 // after a flush. And we set the presentation timestamp from dequeueOutputBu
ffer() to be |
| 47 // non-decreasing for the remaining frames. | 38 // non-decreasing for the remaining frames. |
| 48 private static final long MAX_PRESENTATION_TIMESTAMP_SHIFT_US = 100000; | 39 private static final long MAX_PRESENTATION_TIMESTAMP_SHIFT_US = 100000; |
| 49 | 40 |
| 50 // We use only one output audio format (PCM16) that has 2 bytes per sample | 41 // We use only one output audio format (PCM16) that has 2 bytes per sample |
| 51 private static final int PCM16_BYTES_PER_SAMPLE = 2; | 42 private static final int PCM16_BYTES_PER_SAMPLE = 2; |
| 52 | 43 |
| 53 // The following values should be kept in sync with the media::EncryptionSch
eme::CipherMode | |
| 54 // enum in media/base/encryption_scheme.h | |
| 55 private static final int MEDIA_ENCRYPTION_SCHEME_CIPHER_MODE_UNENCRYPTED = 0
; | |
| 56 private static final int MEDIA_ENCRYPTION_SCHEME_CIPHER_MODE_AES_CTR = 1; | |
| 57 private static final int MEDIA_ENCRYPTION_SCHEME_CIPHER_MODE_AES_CBC = 2; | |
| 58 | |
| 59 private static final int MEDIA_CODEC_UNKNOWN_CIPHER_MODE = -1; | 44 private static final int MEDIA_CODEC_UNKNOWN_CIPHER_MODE = -1; |
| 60 | 45 |
| 61 // TODO(qinmin): Use MediaFormat constants when part of the public API. | 46 // TODO(qinmin): Use MediaFormat constants when part of the public API. |
| 62 private static final String KEY_CROP_LEFT = "crop-left"; | 47 private static final String KEY_CROP_LEFT = "crop-left"; |
| 63 private static final String KEY_CROP_RIGHT = "crop-right"; | 48 private static final String KEY_CROP_RIGHT = "crop-right"; |
| 64 private static final String KEY_CROP_BOTTOM = "crop-bottom"; | 49 private static final String KEY_CROP_BOTTOM = "crop-bottom"; |
| 65 private static final String KEY_CROP_TOP = "crop-top"; | 50 private static final String KEY_CROP_TOP = "crop-top"; |
| 66 | 51 |
| 67 private static final int BITRATE_ADJUSTMENT_FPS = 30; | 52 private static final int BITRATE_ADJUSTMENT_FPS = 30; |
| 68 private static final int MAXIMUM_INITIAL_FPS = 30; | 53 private static final int MAXIMUM_INITIAL_FPS = 30; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 @CalledByNative("DequeueOutputResult") | 131 @CalledByNative("DequeueOutputResult") |
| 147 private int numBytes() { | 132 private int numBytes() { |
| 148 return mNumBytes; | 133 return mNumBytes; |
| 149 } | 134 } |
| 150 } | 135 } |
| 151 | 136 |
| 152 /** A wrapper around a MediaFormat. */ | 137 /** A wrapper around a MediaFormat. */ |
| 153 @MainDex | 138 @MainDex |
| 154 private static class GetOutputFormatResult { | 139 private static class GetOutputFormatResult { |
| 155 private final int mStatus; | 140 private final int mStatus; |
| 156 // May be null if mStatus is not MEDIA_CODEC_OK. | 141 // May be null if mStatus is not MediaCodecStatus.OK. |
| 157 private final MediaFormat mFormat; | 142 private final MediaFormat mFormat; |
| 158 | 143 |
| 159 private GetOutputFormatResult(int status, MediaFormat format) { | 144 private GetOutputFormatResult(int status, MediaFormat format) { |
| 160 mStatus = status; | 145 mStatus = status; |
| 161 mFormat = format; | 146 mFormat = format; |
| 162 } | 147 } |
| 163 | 148 |
| 164 private boolean formatHasCropValues() { | 149 private boolean formatHasCropValues() { |
| 165 return mFormat.containsKey(KEY_CROP_RIGHT) && mFormat.containsKey(KE
Y_CROP_LEFT) | 150 return mFormat.containsKey(KEY_CROP_RIGHT) && mFormat.containsKey(KE
Y_CROP_LEFT) |
| 166 && mFormat.containsKey(KEY_CROP_BOTTOM) && mFormat.containsK
ey(KEY_CROP_TOP); | 151 && mFormat.containsKey(KEY_CROP_BOTTOM) && mFormat.containsK
ey(KEY_CROP_TOP); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 mFlushed = true; | 190 mFlushed = true; |
| 206 mAdaptivePlaybackSupported = adaptivePlaybackSupported; | 191 mAdaptivePlaybackSupported = adaptivePlaybackSupported; |
| 207 mBitrateAdjustmentType = bitrateAdjustmentType; | 192 mBitrateAdjustmentType = bitrateAdjustmentType; |
| 208 } | 193 } |
| 209 | 194 |
| 210 @CalledByNative | 195 @CalledByNative |
| 211 private static MediaCodecBridge create( | 196 private static MediaCodecBridge create( |
| 212 String mime, boolean isSecure, int direction, boolean requireSoftwar
eCodec) { | 197 String mime, boolean isSecure, int direction, boolean requireSoftwar
eCodec) { |
| 213 MediaCodecUtil.CodecCreationInfo info = new MediaCodecUtil.CodecCreation
Info(); | 198 MediaCodecUtil.CodecCreationInfo info = new MediaCodecUtil.CodecCreation
Info(); |
| 214 try { | 199 try { |
| 215 if (direction == MediaCodecUtil.MEDIA_CODEC_ENCODER) { | 200 if (direction == MediaCodecDirection.ENCODER) { |
| 216 info = MediaCodecUtil.createEncoder(mime); | 201 info = MediaCodecUtil.createEncoder(mime); |
| 217 } else { | 202 } else { |
| 218 // |isSecure| only applies to video decoders. | 203 // |isSecure| only applies to video decoders. |
| 219 info = MediaCodecUtil.createDecoder(mime, isSecure, requireSoftw
areCodec); | 204 info = MediaCodecUtil.createDecoder(mime, isSecure, requireSoftw
areCodec); |
| 220 } | 205 } |
| 221 } catch (Exception e) { | 206 } catch (Exception e) { |
| 222 Log.e(TAG, "Failed to create MediaCodec: %s, isSecure: %s, direction
: %d", | 207 Log.e(TAG, "Failed to create MediaCodec: %s, isSecure: %s, direction
: %d", |
| 223 mime, isSecure, direction, e); | 208 mime, isSecure, direction, e); |
| 224 } | 209 } |
| 225 | 210 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 return false; | 247 return false; |
| 263 } catch (IllegalArgumentException e) { | 248 } catch (IllegalArgumentException e) { |
| 264 Log.e(TAG, "Cannot start the media codec", e); | 249 Log.e(TAG, "Cannot start the media codec", e); |
| 265 return false; | 250 return false; |
| 266 } | 251 } |
| 267 return true; | 252 return true; |
| 268 } | 253 } |
| 269 | 254 |
| 270 @CalledByNative | 255 @CalledByNative |
| 271 private DequeueInputResult dequeueInputBuffer(long timeoutUs) { | 256 private DequeueInputResult dequeueInputBuffer(long timeoutUs) { |
| 272 int status = MEDIA_CODEC_ERROR; | 257 int status = MediaCodecStatus.ERROR; |
| 273 int index = -1; | 258 int index = -1; |
| 274 try { | 259 try { |
| 275 int indexOrStatus = mMediaCodec.dequeueInputBuffer(timeoutUs); | 260 int indexOrStatus = mMediaCodec.dequeueInputBuffer(timeoutUs); |
| 276 if (indexOrStatus >= 0) { // index! | 261 if (indexOrStatus >= 0) { // index! |
| 277 status = MEDIA_CODEC_OK; | 262 status = MediaCodecStatus.OK; |
| 278 index = indexOrStatus; | 263 index = indexOrStatus; |
| 279 } else if (indexOrStatus == MediaCodec.INFO_TRY_AGAIN_LATER) { | 264 } else if (indexOrStatus == MediaCodec.INFO_TRY_AGAIN_LATER) { |
| 280 status = MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER; | 265 status = MediaCodecStatus.TRY_AGAIN_LATER; |
| 281 } else { | 266 } else { |
| 282 Log.e(TAG, "Unexpected index_or_status: " + indexOrStatus); | 267 Log.e(TAG, "Unexpected index_or_status: " + indexOrStatus); |
| 283 assert false; | 268 assert false; |
| 284 } | 269 } |
| 285 } catch (Exception e) { | 270 } catch (Exception e) { |
| 286 Log.e(TAG, "Failed to dequeue input buffer", e); | 271 Log.e(TAG, "Failed to dequeue input buffer", e); |
| 287 } | 272 } |
| 288 return new DequeueInputResult(status, index); | 273 return new DequeueInputResult(status, index); |
| 289 } | 274 } |
| 290 | 275 |
| 291 @CalledByNative | 276 @CalledByNative |
| 292 private int flush() { | 277 private int flush() { |
| 293 try { | 278 try { |
| 294 mFlushed = true; | 279 mFlushed = true; |
| 295 mMediaCodec.flush(); | 280 mMediaCodec.flush(); |
| 296 } catch (IllegalStateException e) { | 281 } catch (IllegalStateException e) { |
| 297 Log.e(TAG, "Failed to flush MediaCodec", e); | 282 Log.e(TAG, "Failed to flush MediaCodec", e); |
| 298 return MEDIA_CODEC_ERROR; | 283 return MediaCodecStatus.ERROR; |
| 299 } | 284 } |
| 300 return MEDIA_CODEC_OK; | 285 return MediaCodecStatus.OK; |
| 301 } | 286 } |
| 302 | 287 |
| 303 @CalledByNative | 288 @CalledByNative |
| 304 private void stop() { | 289 private void stop() { |
| 305 try { | 290 try { |
| 306 mMediaCodec.stop(); | 291 mMediaCodec.stop(); |
| 307 } catch (IllegalStateException e) { | 292 } catch (IllegalStateException e) { |
| 308 Log.e(TAG, "Failed to stop MediaCodec", e); | 293 Log.e(TAG, "Failed to stop MediaCodec", e); |
| 309 } | 294 } |
| 310 } | 295 } |
| 311 | 296 |
| 312 @TargetApi(Build.VERSION_CODES.KITKAT) | 297 @TargetApi(Build.VERSION_CODES.KITKAT) |
| 313 @CalledByNative | 298 @CalledByNative |
| 314 private String getName() { | 299 private String getName() { |
| 315 String codecName = "unknown"; | 300 String codecName = "unknown"; |
| 316 try { | 301 try { |
| 317 codecName = mMediaCodec.getName(); | 302 codecName = mMediaCodec.getName(); |
| 318 } catch (IllegalStateException e) { | 303 } catch (IllegalStateException e) { |
| 319 Log.e(TAG, "Cannot get codec name", e); | 304 Log.e(TAG, "Cannot get codec name", e); |
| 320 } | 305 } |
| 321 return codecName; | 306 return codecName; |
| 322 } | 307 } |
| 323 | 308 |
| 324 @CalledByNative | 309 @CalledByNative |
| 325 private GetOutputFormatResult getOutputFormat() { | 310 private GetOutputFormatResult getOutputFormat() { |
| 326 MediaFormat format = null; | 311 MediaFormat format = null; |
| 327 int status = MEDIA_CODEC_OK; | 312 int status = MediaCodecStatus.OK; |
| 328 try { | 313 try { |
| 329 format = mMediaCodec.getOutputFormat(); | 314 format = mMediaCodec.getOutputFormat(); |
| 330 } catch (IllegalStateException e) { | 315 } catch (IllegalStateException e) { |
| 331 Log.e(TAG, "Failed to get output format", e); | 316 Log.e(TAG, "Failed to get output format", e); |
| 332 status = MEDIA_CODEC_ERROR; | 317 status = MediaCodecStatus.ERROR; |
| 333 } | 318 } |
| 334 return new GetOutputFormatResult(status, format); | 319 return new GetOutputFormatResult(status, format); |
| 335 } | 320 } |
| 336 | 321 |
| 337 /** Returns null if MediaCodec throws IllegalStateException. */ | 322 /** Returns null if MediaCodec throws IllegalStateException. */ |
| 338 @CalledByNative | 323 @CalledByNative |
| 339 private ByteBuffer getInputBuffer(int index) { | 324 private ByteBuffer getInputBuffer(int index) { |
| 340 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { | 325 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { |
| 341 try { | 326 try { |
| 342 return mMediaCodec.getInputBuffer(index); | 327 return mMediaCodec.getInputBuffer(index); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 363 } | 348 } |
| 364 | 349 |
| 365 @CalledByNative | 350 @CalledByNative |
| 366 private int queueInputBuffer( | 351 private int queueInputBuffer( |
| 367 int index, int offset, int size, long presentationTimeUs, int flags)
{ | 352 int index, int offset, int size, long presentationTimeUs, int flags)
{ |
| 368 resetLastPresentationTimeIfNeeded(presentationTimeUs); | 353 resetLastPresentationTimeIfNeeded(presentationTimeUs); |
| 369 try { | 354 try { |
| 370 mMediaCodec.queueInputBuffer(index, offset, size, presentationTimeUs
, flags); | 355 mMediaCodec.queueInputBuffer(index, offset, size, presentationTimeUs
, flags); |
| 371 } catch (Exception e) { | 356 } catch (Exception e) { |
| 372 Log.e(TAG, "Failed to queue input buffer", e); | 357 Log.e(TAG, "Failed to queue input buffer", e); |
| 373 return MEDIA_CODEC_ERROR; | 358 return MediaCodecStatus.ERROR; |
| 374 } | 359 } |
| 375 return MEDIA_CODEC_OK; | 360 return MediaCodecStatus.OK; |
| 376 } | 361 } |
| 377 | 362 |
| 378 @TargetApi(Build.VERSION_CODES.KITKAT) | 363 @TargetApi(Build.VERSION_CODES.KITKAT) |
| 379 @CalledByNative | 364 @CalledByNative |
| 380 private void setVideoBitrate(int bps, int frameRate) { | 365 private void setVideoBitrate(int bps, int frameRate) { |
| 381 int targetBps = bps; | 366 int targetBps = bps; |
| 382 if (mBitrateAdjustmentType == BitrateAdjustmentTypes.FRAMERATE_ADJUSTMEN
T | 367 if (mBitrateAdjustmentType == BitrateAdjustmentTypes.FRAMERATE_ADJUSTMEN
T |
| 383 && frameRate > 0) { | 368 && frameRate > 0) { |
| 384 targetBps = BITRATE_ADJUSTMENT_FPS * bps / frameRate; | 369 targetBps = BITRATE_ADJUSTMENT_FPS * bps / frameRate; |
| 385 } | 370 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 405 } catch (IllegalStateException e) { | 390 } catch (IllegalStateException e) { |
| 406 Log.e(TAG, "Failed to set MediaCodec parameters", e); | 391 Log.e(TAG, "Failed to set MediaCodec parameters", e); |
| 407 } | 392 } |
| 408 } | 393 } |
| 409 | 394 |
| 410 // Incoming |native| values are as defined in media/base/encryption_scheme.h
. Translated values | 395 // Incoming |native| values are as defined in media/base/encryption_scheme.h
. Translated values |
| 411 // are from MediaCodec. At present, these values are in sync. Returns | 396 // are from MediaCodec. At present, these values are in sync. Returns |
| 412 // MEDIA_CODEC_UNKNOWN_CIPHER_MODE in the case of unknown incoming value. | 397 // MEDIA_CODEC_UNKNOWN_CIPHER_MODE in the case of unknown incoming value. |
| 413 private int translateCipherModeValue(int nativeValue) { | 398 private int translateCipherModeValue(int nativeValue) { |
| 414 switch (nativeValue) { | 399 switch (nativeValue) { |
| 415 case MEDIA_ENCRYPTION_SCHEME_CIPHER_MODE_UNENCRYPTED: | 400 case CipherMode.UNENCRYPTED: |
| 416 return MediaCodec.CRYPTO_MODE_UNENCRYPTED; | 401 return MediaCodec.CRYPTO_MODE_UNENCRYPTED; |
| 417 case MEDIA_ENCRYPTION_SCHEME_CIPHER_MODE_AES_CTR: | 402 case CipherMode.AES_CTR: |
| 418 return MediaCodec.CRYPTO_MODE_AES_CTR; | 403 return MediaCodec.CRYPTO_MODE_AES_CTR; |
| 419 case MEDIA_ENCRYPTION_SCHEME_CIPHER_MODE_AES_CBC: | 404 case CipherMode.AES_CBC: |
| 420 return MediaCodec.CRYPTO_MODE_AES_CBC; | 405 return MediaCodec.CRYPTO_MODE_AES_CBC; |
| 421 default: | 406 default: |
| 422 Log.e(TAG, "Unsupported cipher mode: " + nativeValue); | 407 Log.e(TAG, "Unsupported cipher mode: " + nativeValue); |
| 423 return MEDIA_CODEC_UNKNOWN_CIPHER_MODE; | 408 return MEDIA_CODEC_UNKNOWN_CIPHER_MODE; |
| 424 } | 409 } |
| 425 } | 410 } |
| 426 | 411 |
| 427 @CalledByNative | 412 @CalledByNative |
| 428 private int queueSecureInputBuffer(int index, int offset, byte[] iv, byte[]
keyId, | 413 private int queueSecureInputBuffer(int index, int offset, byte[] iv, byte[]
keyId, |
| 429 int[] numBytesOfClearData, int[] numBytesOfEncryptedData, int numSub
Samples, | 414 int[] numBytesOfClearData, int[] numBytesOfEncryptedData, int numSub
Samples, |
| 430 int cipherMode, int patternEncrypt, int patternSkip, long presentati
onTimeUs) { | 415 int cipherMode, int patternEncrypt, int patternSkip, long presentati
onTimeUs) { |
| 431 resetLastPresentationTimeIfNeeded(presentationTimeUs); | 416 resetLastPresentationTimeIfNeeded(presentationTimeUs); |
| 432 try { | 417 try { |
| 433 cipherMode = translateCipherModeValue(cipherMode); | 418 cipherMode = translateCipherModeValue(cipherMode); |
| 434 if (cipherMode == MEDIA_CODEC_UNKNOWN_CIPHER_MODE) { | 419 if (cipherMode == MEDIA_CODEC_UNKNOWN_CIPHER_MODE) { |
| 435 return MEDIA_CODEC_ERROR; | 420 return MediaCodecStatus.ERROR; |
| 436 } | 421 } |
| 437 boolean usesCbcs = cipherMode == MediaCodec.CRYPTO_MODE_AES_CBC; | 422 boolean usesCbcs = cipherMode == MediaCodec.CRYPTO_MODE_AES_CBC; |
| 438 if (usesCbcs && !MediaCodecUtil.platformSupportsCbcsEncryption()) { | 423 if (usesCbcs && !MediaCodecUtil.platformSupportsCbcsEncryption()) { |
| 439 Log.e(TAG, "Encryption scheme 'cbcs' not supported on this platf
orm."); | 424 Log.e(TAG, "Encryption scheme 'cbcs' not supported on this platf
orm."); |
| 440 return MEDIA_CODEC_ERROR; | 425 return MediaCodecStatus.ERROR; |
| 441 } | 426 } |
| 442 CryptoInfo cryptoInfo = new CryptoInfo(); | 427 CryptoInfo cryptoInfo = new CryptoInfo(); |
| 443 cryptoInfo.set(numSubSamples, numBytesOfClearData, numBytesOfEncrypt
edData, keyId, iv, | 428 cryptoInfo.set(numSubSamples, numBytesOfClearData, numBytesOfEncrypt
edData, keyId, iv, |
| 444 cipherMode); | 429 cipherMode); |
| 445 if (patternEncrypt != 0 && patternSkip != 0) { | 430 if (patternEncrypt != 0 && patternSkip != 0) { |
| 446 if (usesCbcs) { | 431 if (usesCbcs) { |
| 447 // Above platform check ensured that setting the pattern is
indeed supported. | 432 // Above platform check ensured that setting the pattern is
indeed supported. |
| 448 MediaCodecUtil.setPatternIfSupported(cryptoInfo, patternEncr
ypt, patternSkip); | 433 MediaCodecUtil.setPatternIfSupported(cryptoInfo, patternEncr
ypt, patternSkip); |
| 449 } else { | 434 } else { |
| 450 Log.e(TAG, "Pattern encryption only supported for 'cbcs' sch
eme (CBC mode)."); | 435 Log.e(TAG, "Pattern encryption only supported for 'cbcs' sch
eme (CBC mode)."); |
| 451 return MEDIA_CODEC_ERROR; | 436 return MediaCodecStatus.ERROR; |
| 452 } | 437 } |
| 453 } | 438 } |
| 454 mMediaCodec.queueSecureInputBuffer(index, offset, cryptoInfo, presen
tationTimeUs, 0); | 439 mMediaCodec.queueSecureInputBuffer(index, offset, cryptoInfo, presen
tationTimeUs, 0); |
| 455 } catch (MediaCodec.CryptoException e) { | 440 } catch (MediaCodec.CryptoException e) { |
| 456 if (e.getErrorCode() == MediaCodec.CryptoException.ERROR_NO_KEY) { | 441 if (e.getErrorCode() == MediaCodec.CryptoException.ERROR_NO_KEY) { |
| 457 Log.d(TAG, "Failed to queue secure input buffer: CryptoException
.ERROR_NO_KEY"); | 442 Log.d(TAG, "Failed to queue secure input buffer: CryptoException
.ERROR_NO_KEY"); |
| 458 return MEDIA_CODEC_NO_KEY; | 443 return MediaCodecStatus.NO_KEY; |
| 459 } | 444 } |
| 460 Log.e(TAG, "Failed to queue secure input buffer, CryptoException wit
h error code " | 445 Log.e(TAG, "Failed to queue secure input buffer, CryptoException wit
h error code " |
| 461 + e.getErrorCode()); | 446 + e.getErrorCode()); |
| 462 return MEDIA_CODEC_ERROR; | 447 return MediaCodecStatus.ERROR; |
| 463 } catch (IllegalStateException e) { | 448 } catch (IllegalStateException e) { |
| 464 Log.e(TAG, "Failed to queue secure input buffer, IllegalStateExcepti
on " + e); | 449 Log.e(TAG, "Failed to queue secure input buffer, IllegalStateExcepti
on " + e); |
| 465 return MEDIA_CODEC_ERROR; | 450 return MediaCodecStatus.ERROR; |
| 466 } | 451 } |
| 467 return MEDIA_CODEC_OK; | 452 return MediaCodecStatus.OK; |
| 468 } | 453 } |
| 469 | 454 |
| 470 @CalledByNative | 455 @CalledByNative |
| 471 private void releaseOutputBuffer(int index, boolean render) { | 456 private void releaseOutputBuffer(int index, boolean render) { |
| 472 try { | 457 try { |
| 473 mMediaCodec.releaseOutputBuffer(index, render); | 458 mMediaCodec.releaseOutputBuffer(index, render); |
| 474 } catch (IllegalStateException e) { | 459 } catch (IllegalStateException e) { |
| 475 // TODO(qinmin): May need to report the error to the caller. crbug.c
om/356498. | 460 // TODO(qinmin): May need to report the error to the caller. crbug.c
om/356498. |
| 476 Log.e(TAG, "Failed to release output buffer", e); | 461 Log.e(TAG, "Failed to release output buffer", e); |
| 477 } | 462 } |
| 478 } | 463 } |
| 479 | 464 |
| 480 @SuppressWarnings("deprecation") | 465 @SuppressWarnings("deprecation") |
| 481 @CalledByNative | 466 @CalledByNative |
| 482 private DequeueOutputResult dequeueOutputBuffer(long timeoutUs) { | 467 private DequeueOutputResult dequeueOutputBuffer(long timeoutUs) { |
| 483 MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); | 468 MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); |
| 484 int status = MEDIA_CODEC_ERROR; | 469 int status = MediaCodecStatus.ERROR; |
| 485 int index = -1; | 470 int index = -1; |
| 486 try { | 471 try { |
| 487 int indexOrStatus = mMediaCodec.dequeueOutputBuffer(info, timeoutUs)
; | 472 int indexOrStatus = mMediaCodec.dequeueOutputBuffer(info, timeoutUs)
; |
| 488 if (info.presentationTimeUs < mLastPresentationTimeUs) { | 473 if (info.presentationTimeUs < mLastPresentationTimeUs) { |
| 489 // TODO(qinmin): return a special code through DequeueOutputResu
lt | 474 // TODO(qinmin): return a special code through DequeueOutputResu
lt |
| 490 // to notify the native code the the frame has a wrong presentat
ion | 475 // to notify the native code the the frame has a wrong presentat
ion |
| 491 // timestamp and should be skipped. | 476 // timestamp and should be skipped. |
| 492 info.presentationTimeUs = mLastPresentationTimeUs; | 477 info.presentationTimeUs = mLastPresentationTimeUs; |
| 493 } | 478 } |
| 494 mLastPresentationTimeUs = info.presentationTimeUs; | 479 mLastPresentationTimeUs = info.presentationTimeUs; |
| 495 | 480 |
| 496 if (indexOrStatus >= 0) { // index! | 481 if (indexOrStatus >= 0) { // index! |
| 497 status = MEDIA_CODEC_OK; | 482 status = MediaCodecStatus.OK; |
| 498 index = indexOrStatus; | 483 index = indexOrStatus; |
| 499 } else if (indexOrStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED)
{ | 484 } else if (indexOrStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED)
{ |
| 500 mOutputBuffers = mMediaCodec.getOutputBuffers(); | 485 mOutputBuffers = mMediaCodec.getOutputBuffers(); |
| 501 status = MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED; | 486 status = MediaCodecStatus.OUTPUT_BUFFERS_CHANGED; |
| 502 } else if (indexOrStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { | 487 } else if (indexOrStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { |
| 503 status = MEDIA_CODEC_OUTPUT_FORMAT_CHANGED; | 488 status = MediaCodecStatus.OUTPUT_FORMAT_CHANGED; |
| 504 MediaFormat newFormat = mMediaCodec.getOutputFormat(); | 489 MediaFormat newFormat = mMediaCodec.getOutputFormat(); |
| 505 } else if (indexOrStatus == MediaCodec.INFO_TRY_AGAIN_LATER) { | 490 } else if (indexOrStatus == MediaCodec.INFO_TRY_AGAIN_LATER) { |
| 506 status = MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER; | 491 status = MediaCodecStatus.TRY_AGAIN_LATER; |
| 507 } else { | 492 } else { |
| 508 Log.e(TAG, "Unexpected index_or_status: " + indexOrStatus); | 493 Log.e(TAG, "Unexpected index_or_status: " + indexOrStatus); |
| 509 assert false; | 494 assert false; |
| 510 } | 495 } |
| 511 } catch (IllegalStateException e) { | 496 } catch (IllegalStateException e) { |
| 512 status = MEDIA_CODEC_ERROR; | 497 status = MediaCodecStatus.ERROR; |
| 513 Log.e(TAG, "Failed to dequeue output buffer", e); | 498 Log.e(TAG, "Failed to dequeue output buffer", e); |
| 514 } | 499 } |
| 515 | 500 |
| 516 return new DequeueOutputResult( | 501 return new DequeueOutputResult( |
| 517 status, index, info.flags, info.offset, info.presentationTimeUs,
info.size); | 502 status, index, info.flags, info.offset, info.presentationTimeUs,
info.size); |
| 518 } | 503 } |
| 519 | 504 |
| 520 @CalledByNative | 505 @CalledByNative |
| 521 private boolean configureVideo(MediaFormat format, Surface surface, MediaCry
pto crypto, | 506 private boolean configureVideo(MediaFormat format, Surface surface, MediaCry
pto crypto, |
| 522 int flags, boolean allowAdaptivePlayback) { | 507 int flags, boolean allowAdaptivePlayback) { |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 622 MediaFormat format = MediaFormat.createVideoFormat(mime, width, height); | 607 MediaFormat format = MediaFormat.createVideoFormat(mime, width, height); |
| 623 format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate); | 608 format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate); |
| 624 format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate); | 609 format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate); |
| 625 format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, iFrameInterval); | 610 format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, iFrameInterval); |
| 626 format.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat); | 611 format.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat); |
| 627 Log.d(TAG, "video encoder format: " + format); | 612 Log.d(TAG, "video encoder format: " + format); |
| 628 return format; | 613 return format; |
| 629 } | 614 } |
| 630 | 615 |
| 631 @CalledByNative | 616 @CalledByNative |
| 632 private boolean isAdaptivePlaybackSupported(int width, int height) { | 617 private boolean isAdaptivePlaybackSupported() { |
| 633 // If media codec has adaptive playback supported, then the max sizes | 618 // If media codec has adaptive playback supported, then the max sizes |
| 634 // used during creation are only hints. | 619 // used during creation are only hints. |
| 635 return mAdaptivePlaybackSupported; | 620 return mAdaptivePlaybackSupported; |
| 636 } | 621 } |
| 637 | 622 |
| 638 @CalledByNative | 623 @CalledByNative |
| 639 private static void setCodecSpecificData(MediaFormat format, int index, byte
[] bytes) { | 624 private static void setCodecSpecificData(MediaFormat format, int index, byte
[] bytes) { |
| 640 // Codec Specific Data is set in the MediaFormat as ByteBuffer entries w
ith keys csd-0, | 625 // Codec Specific Data is set in the MediaFormat as ByteBuffer entries w
ith keys csd-0, |
| 641 // csd-1, and so on. See: http://developer.android.com/reference/android
/media/MediaCodec.html | 626 // csd-1, and so on. See: http://developer.android.com/reference/android
/media/MediaCodec.html |
| 642 // for details. | 627 // for details. |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | 702 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { |
| 718 return AudioFormat.CHANNEL_OUT_7POINT1_SURROUND; | 703 return AudioFormat.CHANNEL_OUT_7POINT1_SURROUND; |
| 719 } else { | 704 } else { |
| 720 return AudioFormat.CHANNEL_OUT_7POINT1; | 705 return AudioFormat.CHANNEL_OUT_7POINT1; |
| 721 } | 706 } |
| 722 default: | 707 default: |
| 723 return AudioFormat.CHANNEL_OUT_DEFAULT; | 708 return AudioFormat.CHANNEL_OUT_DEFAULT; |
| 724 } | 709 } |
| 725 } | 710 } |
| 726 } | 711 } |
| OLD | NEW |