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 |