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

Side by Side 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 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « gpu/config/software_rendering_list_json.cc ('k') | media/base/android/media_codec_bridge.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 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.media.AudioFormat; 7 import android.media.AudioFormat;
8 import android.media.AudioManager; 8 import android.media.AudioManager;
9 import android.media.AudioTrack; 9 import android.media.AudioTrack;
10 import android.media.MediaCodec; 10 import android.media.MediaCodec;
11 import android.media.MediaCodecInfo; 11 import android.media.MediaCodecInfo;
12 import android.media.MediaCodecList; 12 import android.media.MediaCodecList;
13 import android.media.MediaCrypto; 13 import android.media.MediaCrypto;
14 import android.media.MediaFormat; 14 import android.media.MediaFormat;
15 import android.os.Build; 15 import android.os.Build;
16 import android.os.Bundle;
16 import android.util.Log; 17 import android.util.Log;
17 import android.view.Surface; 18 import android.view.Surface;
18 19
19 import java.io.IOException; 20 import java.io.IOException;
20 import java.nio.ByteBuffer; 21 import java.nio.ByteBuffer;
21 import java.util.ArrayList; 22 import java.util.ArrayList;
23 import java.util.Collection;
22 import java.util.HashMap; 24 import java.util.HashMap;
23 import java.util.Map; 25 import java.util.Map;
24 26
25 import org.chromium.base.CalledByNative; 27 import org.chromium.base.CalledByNative;
26 import org.chromium.base.JNINamespace; 28 import org.chromium.base.JNINamespace;
27 29
28 /** 30 /**
29 * A wrapper of the MediaCodec class to facilitate exception capturing and 31 * A wrapper of the MediaCodec class to facilitate exception capturing and
30 * audio rendering. 32 * audio rendering.
31 */ 33 */
32 @JNINamespace("media") 34 @JNINamespace("media")
33 class MediaCodecBridge { 35 class MediaCodecBridge {
34 private static final String TAG = "MediaCodecBridge"; 36 private static final String TAG = "MediaCodecBridge";
35 37
36 // Error code for MediaCodecBridge. Keep this value in sync with 38 // Error code for MediaCodecBridge. Keep this value in sync with
37 // MediaCodecStatus in media_codec_bridge.h. 39 // MediaCodecStatus in media_codec_bridge.h.
38 private static final int MEDIA_CODEC_OK = 0; 40 private static final int MEDIA_CODEC_OK = 0;
39 private static final int MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER = 1; 41 private static final int MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER = 1;
40 private static final int MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER = 2; 42 private static final int MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER = 2;
41 private static final int MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED = 3; 43 private static final int MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED = 3;
42 private static final int MEDIA_CODEC_OUTPUT_FORMAT_CHANGED = 4; 44 private static final int MEDIA_CODEC_OUTPUT_FORMAT_CHANGED = 4;
43 private static final int MEDIA_CODEC_INPUT_END_OF_STREAM = 5; 45 private static final int MEDIA_CODEC_INPUT_END_OF_STREAM = 5;
44 private static final int MEDIA_CODEC_OUTPUT_END_OF_STREAM = 6; 46 private static final int MEDIA_CODEC_OUTPUT_END_OF_STREAM = 6;
45 private static final int MEDIA_CODEC_NO_KEY = 7; 47 private static final int MEDIA_CODEC_NO_KEY = 7;
46 private static final int MEDIA_CODEC_STOPPED = 8; 48 private static final int MEDIA_CODEC_STOPPED = 8;
47 private static final int MEDIA_CODEC_ERROR = 9; 49 private static final int MEDIA_CODEC_ERROR = 9;
48 50
51 // Codec direction. Keep this in sync with media_codec_bridge.h.
52 private static final int MEDIA_CODEC_DECODER = 0;
53 private static final int MEDIA_CODEC_ENCODER = 1;
54
49 // After a flush(), dequeueOutputBuffer() can often produce empty presentati on timestamps 55 // After a flush(), dequeueOutputBuffer() can often produce empty presentati on timestamps
50 // for several frames. As a result, the player may find that the time does n ot increase 56 // for several frames. As a result, the player may find that the time does n ot increase
51 // after decoding a frame. To detect this, we check whether the presentation timestamp from 57 // after decoding a frame. To detect this, we check whether the presentation timestamp from
52 // dequeueOutputBuffer() is larger than input_timestamp - MAX_PRESENTATION_T IMESTAMP_SHIFT_US 58 // dequeueOutputBuffer() is larger than input_timestamp - MAX_PRESENTATION_T IMESTAMP_SHIFT_US
53 // after a flush. And we set the presentation timestamp from dequeueOutputBu ffer() to be 59 // after a flush. And we set the presentation timestamp from dequeueOutputBu ffer() to be
54 // non-decreasing for the remaining frames. 60 // non-decreasing for the remaining frames.
55 private static final long MAX_PRESENTATION_TIMESTAMP_SHIFT_US = 100000; 61 private static final long MAX_PRESENTATION_TIMESTAMP_SHIFT_US = 100000;
56 62
57 private ByteBuffer[] mInputBuffers; 63 private ByteBuffer[] mInputBuffers;
58 private ByteBuffer[] mOutputBuffers; 64 private ByteBuffer[] mOutputBuffers;
(...skipping 18 matching lines...) Expand all
77 @CalledByNative("DequeueInputResult") 83 @CalledByNative("DequeueInputResult")
78 private int index() { return mIndex; } 84 private int index() { return mIndex; }
79 } 85 }
80 86
81 /** 87 /**
82 * This class represents supported android codec information. 88 * This class represents supported android codec information.
83 */ 89 */
84 private static class CodecInfo { 90 private static class CodecInfo {
85 private final String mCodecType; // e.g. "video/x-vnd.on2.vp8". 91 private final String mCodecType; // e.g. "video/x-vnd.on2.vp8".
86 private final String mCodecName; // e.g. "OMX.google.vp8.decoder". 92 private final String mCodecName; // e.g. "OMX.google.vp8.decoder".
93 private final int mDirection;
87 94
88 private CodecInfo(String codecType, String codecName) { 95 private CodecInfo(String codecType, String codecName,
96 int direction) {
89 mCodecType = codecType; 97 mCodecType = codecType;
90 mCodecName = codecName; 98 mCodecName = codecName;
99 mDirection = direction;
91 } 100 }
92 101
93 @CalledByNative("CodecInfo") 102 @CalledByNative("CodecInfo")
94 private String codecType() { return mCodecType; } 103 private String codecType() { return mCodecType; }
95 104
96 @CalledByNative("CodecInfo") 105 @CalledByNative("CodecInfo")
97 private String codecName() { return mCodecName; } 106 private String codecName() { return mCodecName; }
107
108 @CalledByNative("CodecInfo")
109 private int direction() { return mDirection; }
98 } 110 }
99 111
100 private static class DequeueOutputResult { 112 private static class DequeueOutputResult {
101 private final int mStatus; 113 private final int mStatus;
102 private final int mIndex; 114 private final int mIndex;
103 private final int mFlags; 115 private final int mFlags;
104 private final int mOffset; 116 private final int mOffset;
105 private final long mPresentationTimeMicroseconds; 117 private final long mPresentationTimeMicroseconds;
106 private final int mNumBytes; 118 private final int mNumBytes;
107 119
(...skipping 24 matching lines...) Expand all
132 144
133 @CalledByNative("DequeueOutputResult") 145 @CalledByNative("DequeueOutputResult")
134 private int numBytes() { return mNumBytes; } 146 private int numBytes() { return mNumBytes; }
135 } 147 }
136 148
137 /** 149 /**
138 * Get a list of supported android codec mimes. 150 * Get a list of supported android codec mimes.
139 */ 151 */
140 @CalledByNative 152 @CalledByNative
141 private static CodecInfo[] getCodecsInfo() { 153 private static CodecInfo[] getCodecsInfo() {
142 Map<String, CodecInfo> CodecInfoMap = new HashMap<String, CodecInfo>(); 154 // Return the first (highest-priority) codec for each MIME type.
155 Map<String, CodecInfo> encoderInfoMap = new HashMap<String, CodecInfo>() ;
156 Map<String, CodecInfo> decoderInfoMap = new HashMap<String, CodecInfo>() ;
143 int count = MediaCodecList.getCodecCount(); 157 int count = MediaCodecList.getCodecCount();
144 for (int i = 0; i < count; ++i) { 158 for (int i = 0; i < count; ++i) {
145 MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i); 159 MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
146 if (info.isEncoder()) { 160 int direction =
147 continue; 161 info.isEncoder() ? MEDIA_CODEC_ENCODER : MEDIA_CODEC_DECODER;
148 }
149
150 String codecString = info.getName(); 162 String codecString = info.getName();
151 String[] supportedTypes = info.getSupportedTypes(); 163 String[] supportedTypes = info.getSupportedTypes();
152 for (int j = 0; j < supportedTypes.length; ++j) { 164 for (int j = 0; j < supportedTypes.length; ++j) {
153 if (!CodecInfoMap.containsKey(supportedTypes[j])) { 165 Map<String, CodecInfo> map = info.isEncoder() ? encoderInfoMap : decoderInfoMap;
154 CodecInfoMap.put(supportedTypes[j], new CodecInfo( 166 if (!map.containsKey(supportedTypes[j])) {
155 supportedTypes[j], codecString)); 167 map.put(supportedTypes[j], new CodecInfo(
168 supportedTypes[j], codecString, direction));
156 } 169 }
157 } 170 }
158 } 171 }
159 return CodecInfoMap.values().toArray( 172 ArrayList<CodecInfo> codecInfos = new ArrayList<CodecInfo>(
160 new CodecInfo[CodecInfoMap.size()]); 173 decoderInfoMap.size() + encoderInfoMap.size());
174 codecInfos.addAll(encoderInfoMap.values());
175 codecInfos.addAll(decoderInfoMap.values());
176 return codecInfos.toArray(new CodecInfo[codecInfos.size()]);
161 } 177 }
162 178
163 private static String getSecureDecoderNameForMime(String mime) { 179 private static String getSecureDecoderNameForMime(String mime) {
164 int count = MediaCodecList.getCodecCount(); 180 int count = MediaCodecList.getCodecCount();
165 for (int i = 0; i < count; ++i) { 181 for (int i = 0; i < count; ++i) {
166 MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i); 182 MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
167 if (info.isEncoder()) { 183 if (info.isEncoder()) {
168 continue; 184 continue;
169 } 185 }
170 186
171 String[] supportedTypes = info.getSupportedTypes(); 187 String[] supportedTypes = info.getSupportedTypes();
172 for (int j = 0; j < supportedTypes.length; ++j) { 188 for (int j = 0; j < supportedTypes.length; ++j) {
173 if (supportedTypes[j].equalsIgnoreCase(mime)) { 189 if (supportedTypes[j].equalsIgnoreCase(mime)) {
174 return info.getName() + ".secure"; 190 return info.getName() + ".secure";
175 } 191 }
176 } 192 }
177 } 193 }
178 194
179 return null; 195 return null;
180 } 196 }
181 197
182 private MediaCodecBridge(MediaCodec mediaCodec) { 198 private MediaCodecBridge(MediaCodec mediaCodec) {
183 assert(mediaCodec != null); 199 assert(mediaCodec != null);
184 mMediaCodec = mediaCodec; 200 mMediaCodec = mediaCodec;
185 mLastPresentationTimeUs = 0; 201 mLastPresentationTimeUs = 0;
186 mFlushed = true; 202 mFlushed = true;
187 } 203 }
188 204
189 @CalledByNative 205 @CalledByNative
190 private static MediaCodecBridge create(String mime, boolean isSecure) { 206 private static MediaCodecBridge create(String mime, boolean isSecure, int di rection) {
191 // Creation of ".secure" codecs sometimes crash instead of throwing exce ptions 207 // Creation of ".secure" codecs sometimes crash instead of throwing exce ptions
192 // on pre-JBMR2 devices. 208 // on pre-JBMR2 devices.
193 if (isSecure && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_M R2) { 209 if (isSecure && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_M R2) {
194 return null; 210 return null;
195 } 211 }
196 MediaCodec mediaCodec = null; 212 MediaCodec mediaCodec = null;
197 try { 213 try {
198 // |isSecure| only applies to video decoders. 214 // |isSecure| only applies to video decoders.
199 if (mime.startsWith("video") && isSecure) { 215 if (mime.startsWith("video") && isSecure && direction == MEDIA_CODEC _DECODER) {
200 mediaCodec = MediaCodec.createByCodecName(getSecureDecoderNameFo rMime(mime)); 216 mediaCodec = MediaCodec.createByCodecName(getSecureDecoderNameFo rMime(mime));
201 } else { 217 } else {
202 mediaCodec = MediaCodec.createDecoderByType(mime); 218 if (direction == MEDIA_CODEC_ENCODER) {
219 mediaCodec = MediaCodec.createEncoderByType(mime);
220 } else {
221 mediaCodec = MediaCodec.createDecoderByType(mime);
222 }
203 } 223 }
204 } catch (Exception e) { 224 } catch (Exception e) {
205 Log.e(TAG, "Failed to create MediaCodec: " + mime + ", isSecure: " 225 Log.e(TAG, "Failed to create MediaCodec: " + mime + ", isSecure: "
206 + isSecure + ", " + e.toString()); 226 + isSecure + ", direction: " + direction, e);
207 } 227 }
208 228
209 if (mediaCodec == null) { 229 if (mediaCodec == null) {
210 return null; 230 return null;
211 } 231 }
212 232
213 return new MediaCodecBridge(mediaCodec); 233 return new MediaCodecBridge(mediaCodec);
214 } 234 }
215 235
216 @CalledByNative 236 @CalledByNative
217 private void release() { 237 private void release() {
238 mMediaCodec.stop();
218 mMediaCodec.release(); 239 mMediaCodec.release();
240 mMediaCodec = null;
219 if (mAudioTrack != null) { 241 if (mAudioTrack != null) {
220 mAudioTrack.release(); 242 mAudioTrack.release();
221 } 243 }
222 } 244 }
223 245
224 @CalledByNative 246 @CalledByNative
225 private boolean start() { 247 private boolean start() {
226 try { 248 try {
227 mMediaCodec.start(); 249 mMediaCodec.start();
228 mInputBuffers = mMediaCodec.getInputBuffers(); 250 mInputBuffers = mMediaCodec.getInputBuffers();
229 } catch (IllegalStateException e) { 251 } catch (IllegalStateException e) {
230 Log.e(TAG, "Cannot start the media codec " + e.toString()); 252 Log.e(TAG, "Cannot start the media codec", e);
231 return false; 253 return false;
232 } 254 }
233 return true; 255 return true;
234 } 256 }
235 257
236 @CalledByNative 258 @CalledByNative
237 private DequeueInputResult dequeueInputBuffer(long timeoutUs) { 259 private DequeueInputResult dequeueInputBuffer(long timeoutUs) {
238 int status = MEDIA_CODEC_ERROR; 260 int status = MEDIA_CODEC_ERROR;
239 int index = -1; 261 int index = -1;
240 try { 262 try {
241 int index_or_status = mMediaCodec.dequeueInputBuffer(timeoutUs); 263 int index_or_status = mMediaCodec.dequeueInputBuffer(timeoutUs);
242 if (index_or_status >= 0) { // index! 264 if (index_or_status >= 0) { // index!
243 status = MEDIA_CODEC_OK; 265 status = MEDIA_CODEC_OK;
244 index = index_or_status; 266 index = index_or_status;
245 } else if (index_or_status == MediaCodec.INFO_TRY_AGAIN_LATER) { 267 } else if (index_or_status == MediaCodec.INFO_TRY_AGAIN_LATER) {
246 Log.e(TAG, "dequeueInputBuffer: MediaCodec.INFO_TRY_AGAIN_LATER" ); 268 Log.e(TAG, "dequeueInputBuffer: MediaCodec.INFO_TRY_AGAIN_LATER" );
247 status = MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER; 269 status = MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER;
248 } else { 270 } else {
271 Log.e(TAG, "Unexpected index_or_status: " + index_or_status);
249 assert(false); 272 assert(false);
250 } 273 }
251 } catch(Exception e) { 274 } catch(Exception e) {
252 Log.e(TAG, "Failed to dequeue input buffer: " + e.toString()); 275 Log.e(TAG, "Failed to dequeue input buffer", e);
253 } 276 }
254 return new DequeueInputResult(status, index); 277 return new DequeueInputResult(status, index);
255 } 278 }
256 279
257 @CalledByNative 280 @CalledByNative
258 private int flush() { 281 private int flush() {
259 try { 282 try {
260 mFlushed = true; 283 mFlushed = true;
261 if (mAudioTrack != null) { 284 if (mAudioTrack != null) {
262 mAudioTrack.flush(); 285 mAudioTrack.flush();
263 } 286 }
264 mMediaCodec.flush(); 287 mMediaCodec.flush();
265 } catch(IllegalStateException e) { 288 } catch(IllegalStateException e) {
266 Log.e(TAG, "Failed to flush MediaCodec " + e.toString()); 289 Log.e(TAG, "Failed to flush MediaCodec", e);
267 return MEDIA_CODEC_ERROR; 290 return MEDIA_CODEC_ERROR;
268 } 291 }
269 return MEDIA_CODEC_OK; 292 return MEDIA_CODEC_OK;
270 } 293 }
271 294
272 @CalledByNative 295 @CalledByNative
273 private void stop() { 296 private void stop() {
274 mMediaCodec.stop(); 297 mMediaCodec.stop();
275 if (mAudioTrack != null) { 298 if (mAudioTrack != null) {
276 mAudioTrack.pause(); 299 mAudioTrack.pause();
(...skipping 14 matching lines...) Expand all
291 private ByteBuffer getInputBuffer(int index) { 314 private ByteBuffer getInputBuffer(int index) {
292 return mInputBuffers[index]; 315 return mInputBuffers[index];
293 } 316 }
294 317
295 @CalledByNative 318 @CalledByNative
296 private ByteBuffer getOutputBuffer(int index) { 319 private ByteBuffer getOutputBuffer(int index) {
297 return mOutputBuffers[index]; 320 return mOutputBuffers[index];
298 } 321 }
299 322
300 @CalledByNative 323 @CalledByNative
324 private int getInputBuffersCount() {
325 return mInputBuffers.length;
326 }
327
328 @CalledByNative
329 private int getOutputBuffersCount() {
330 return mOutputBuffers != null ? mOutputBuffers.length : -1;
331 }
332
333 @CalledByNative
334 private int getOutputBuffersCapacity() {
335 return mOutputBuffers != null ? mOutputBuffers[0].capacity() : -1;
336 }
337
338 @CalledByNative
339 private boolean getOutputBuffers() {
340 try {
341 mOutputBuffers = mMediaCodec.getOutputBuffers();
342 } catch (IllegalStateException e) {
343 Log.e(TAG, "Cannot get output buffers", e);
344 return false;
345 }
346 return true;
347 }
348
349 @CalledByNative
301 private int queueInputBuffer( 350 private int queueInputBuffer(
302 int index, int offset, int size, long presentationTimeUs, int flags) { 351 int index, int offset, int size, long presentationTimeUs, int flags) {
303 resetLastPresentationTimeIfNeeded(presentationTimeUs); 352 resetLastPresentationTimeIfNeeded(presentationTimeUs);
304 try { 353 try {
305 mMediaCodec.queueInputBuffer(index, offset, size, presentationTimeUs , flags); 354 mMediaCodec.queueInputBuffer(index, offset, size, presentationTimeUs , flags);
306 } catch(Exception e) { 355 } catch(Exception e) {
307 Log.e(TAG, "Failed to queue input buffer: " + e.toString()); 356 Log.e(TAG, "Failed to queue input buffer", e);
308 return MEDIA_CODEC_ERROR; 357 return MEDIA_CODEC_ERROR;
309 } 358 }
310 return MEDIA_CODEC_OK; 359 return MEDIA_CODEC_OK;
311 } 360 }
312 361
313 @CalledByNative 362 @CalledByNative
363 private void setVideoBitrate(int bps) {
364 Bundle b = new Bundle();
365 b.putInt(MediaCodec.PARAMETER_KEY_VIDEO_BITRATE, bps);
366 mMediaCodec.setParameters(b);
367 }
368
369 @CalledByNative
370 private void requestKeyFrameSoon() {
371 Bundle b = new Bundle();
372 b.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
373 mMediaCodec.setParameters(b);
374 }
375
376 @CalledByNative
314 private int queueSecureInputBuffer( 377 private int queueSecureInputBuffer(
315 int index, int offset, byte[] iv, byte[] keyId, int[] numBytesOfClea rData, 378 int index, int offset, byte[] iv, byte[] keyId, int[] numBytesOfClea rData,
316 int[] numBytesOfEncryptedData, int numSubSamples, long presentationT imeUs) { 379 int[] numBytesOfEncryptedData, int numSubSamples, long presentationT imeUs) {
317 resetLastPresentationTimeIfNeeded(presentationTimeUs); 380 resetLastPresentationTimeIfNeeded(presentationTimeUs);
318 try { 381 try {
319 MediaCodec.CryptoInfo cryptoInfo = new MediaCodec.CryptoInfo(); 382 MediaCodec.CryptoInfo cryptoInfo = new MediaCodec.CryptoInfo();
320 cryptoInfo.set(numSubSamples, numBytesOfClearData, numBytesOfEncrypt edData, 383 cryptoInfo.set(numSubSamples, numBytesOfClearData, numBytesOfEncrypt edData,
321 keyId, iv, MediaCodec.CRYPTO_MODE_AES_CTR); 384 keyId, iv, MediaCodec.CRYPTO_MODE_AES_CTR);
322 mMediaCodec.queueSecureInputBuffer(index, offset, cryptoInfo, presen tationTimeUs, 0); 385 mMediaCodec.queueSecureInputBuffer(index, offset, cryptoInfo, presen tationTimeUs, 0);
323 } catch (MediaCodec.CryptoException e) { 386 } catch (MediaCodec.CryptoException e) {
324 Log.e(TAG, "Failed to queue secure input buffer: " + e.toString()); 387 Log.e(TAG, "Failed to queue secure input buffer", e);
325 if (e.getErrorCode() == MediaCodec.CryptoException.ERROR_NO_KEY) { 388 if (e.getErrorCode() == MediaCodec.CryptoException.ERROR_NO_KEY) {
326 Log.e(TAG, "MediaCodec.CryptoException.ERROR_NO_KEY"); 389 Log.e(TAG, "MediaCodec.CryptoException.ERROR_NO_KEY");
327 return MEDIA_CODEC_NO_KEY; 390 return MEDIA_CODEC_NO_KEY;
328 } 391 }
329 Log.e(TAG, "MediaCodec.CryptoException with error code " + e.getErro rCode()); 392 Log.e(TAG, "MediaCodec.CryptoException with error code " + e.getErro rCode());
330 return MEDIA_CODEC_ERROR; 393 return MEDIA_CODEC_ERROR;
331 } catch(IllegalStateException e) { 394 } catch(IllegalStateException e) {
332 Log.e(TAG, "Failed to queue secure input buffer: " + e.toString()); 395 Log.e(TAG, "Failed to queue secure input buffer", e);
333 return MEDIA_CODEC_ERROR; 396 return MEDIA_CODEC_ERROR;
334 } 397 }
335 return MEDIA_CODEC_OK; 398 return MEDIA_CODEC_OK;
336 } 399 }
337 400
338 @CalledByNative 401 @CalledByNative
339 private void releaseOutputBuffer(int index, boolean render) { 402 private void releaseOutputBuffer(int index, boolean render) {
340 mMediaCodec.releaseOutputBuffer(index, render); 403 mMediaCodec.releaseOutputBuffer(index, render);
341 } 404 }
342 405
343 @CalledByNative 406 @CalledByNative
344 private boolean getOutputBuffers() {
345 try {
346 mOutputBuffers = mMediaCodec.getOutputBuffers();
347 } catch (IllegalStateException e) {
348 Log.e(TAG, "Cannot get output buffers " + e.toString());
349 return false;
350 }
351 return true;
352 }
353
354 @CalledByNative
355 private DequeueOutputResult dequeueOutputBuffer(long timeoutUs) { 407 private DequeueOutputResult dequeueOutputBuffer(long timeoutUs) {
356 MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); 408 MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
357 int status = MEDIA_CODEC_ERROR; 409 int status = MEDIA_CODEC_ERROR;
358 int index = -1; 410 int index = -1;
359 try { 411 try {
360 int index_or_status = mMediaCodec.dequeueOutputBuffer(info, timeoutU s); 412 int index_or_status = mMediaCodec.dequeueOutputBuffer(info, timeoutU s);
361 if (info.presentationTimeUs < mLastPresentationTimeUs) { 413 if (info.presentationTimeUs < mLastPresentationTimeUs) {
362 // TODO(qinmin): return a special code through DequeueOutputResu lt 414 // TODO(qinmin): return a special code through DequeueOutputResu lt
363 // to notify the native code the the frame has a wrong presentat ion 415 // to notify the native code the the frame has a wrong presentat ion
364 // timestamp and should be skipped. 416 // timestamp and should be skipped.
365 info.presentationTimeUs = mLastPresentationTimeUs; 417 info.presentationTimeUs = mLastPresentationTimeUs;
366 } 418 }
367 mLastPresentationTimeUs = info.presentationTimeUs; 419 mLastPresentationTimeUs = info.presentationTimeUs;
368 420
369 if (index_or_status >= 0) { // index! 421 if (index_or_status >= 0) { // index!
370 status = MEDIA_CODEC_OK; 422 status = MEDIA_CODEC_OK;
371 index = index_or_status; 423 index = index_or_status;
372 } else if (index_or_status == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED ) { 424 } else if (index_or_status == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED ) {
373 status = MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED; 425 status = MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED;
374 } else if (index_or_status == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { 426 } else if (index_or_status == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
375 status = MEDIA_CODEC_OUTPUT_FORMAT_CHANGED; 427 status = MEDIA_CODEC_OUTPUT_FORMAT_CHANGED;
376 } else if (index_or_status == MediaCodec.INFO_TRY_AGAIN_LATER) { 428 } else if (index_or_status == MediaCodec.INFO_TRY_AGAIN_LATER) {
377 status = MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER; 429 status = MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER;
378 } else { 430 } else {
431 Log.e(TAG, "Unexpected index_or_status: " + index_or_status);
379 assert(false); 432 assert(false);
380 } 433 }
381 } catch (IllegalStateException e) { 434 } catch (IllegalStateException e) {
382 Log.e(TAG, "Failed to dequeue output buffer: " + e.toString()); 435 Log.e(TAG, "Failed to dequeue output buffer", e);
383 } 436 }
384 437
385 return new DequeueOutputResult( 438 return new DequeueOutputResult(
386 status, index, info.flags, info.offset, info.presentationTimeUs, info.size); 439 status, index, info.flags, info.offset, info.presentationTimeUs, info.size);
387 } 440 }
388 441
389 @CalledByNative 442 @CalledByNative
390 private boolean configureVideo(MediaFormat format, Surface surface, MediaCry pto crypto, 443 private boolean configureVideo(MediaFormat format, Surface surface, MediaCry pto crypto,
391 int flags) { 444 int flags) {
392 try { 445 try {
393 mMediaCodec.configure(format, surface, crypto, flags); 446 mMediaCodec.configure(format, surface, crypto, flags);
394 return true; 447 return true;
395 } catch (IllegalStateException e) { 448 } catch (IllegalStateException e) {
396 Log.e(TAG, "Cannot configure the video codec " + e.toString()); 449 Log.e(TAG, "Cannot configure the video codec", e);
397 } 450 }
398 return false; 451 return false;
399 } 452 }
400 453
401 @CalledByNative 454 @CalledByNative
402 private static MediaFormat createAudioFormat(String mime, int SampleRate, in t ChannelCount) { 455 private static MediaFormat createAudioFormat(String mime, int SampleRate, in t ChannelCount) {
403 return MediaFormat.createAudioFormat(mime, SampleRate, ChannelCount); 456 return MediaFormat.createAudioFormat(mime, SampleRate, ChannelCount);
404 } 457 }
405 458
406 @CalledByNative 459 @CalledByNative
407 private static MediaFormat createVideoFormat(String mime, int width, int hei ght) { 460 private static MediaFormat createVideoDecoderFormat(String mime, int width, int height) {
408 return MediaFormat.createVideoFormat(mime, width, height); 461 return MediaFormat.createVideoFormat(mime, width, height);
409 } 462 }
410 463
411 @CalledByNative 464 @CalledByNative
465 private static MediaFormat createVideoEncoderFormat(String mime, int width, int height,
466 int bitRate, int frameRate, int iFrameInterval, int colorFormat) {
467 MediaFormat format = MediaFormat.createVideoFormat(mime, width, height);
468 format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
469 format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
470 format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, iFrameInterval);
471 format.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
472 return format;
473 }
474
475 @CalledByNative
412 private static void setCodecSpecificData(MediaFormat format, int index, byte [] bytes) { 476 private static void setCodecSpecificData(MediaFormat format, int index, byte [] bytes) {
413 String name = null; 477 String name = null;
414 if (index == 0) { 478 if (index == 0) {
415 name = "csd-0"; 479 name = "csd-0";
416 } else if (index == 1) { 480 } else if (index == 1) {
417 name = "csd-1"; 481 name = "csd-1";
418 } 482 }
419 if (name != null) { 483 if (name != null) {
420 format.setByteBuffer(name, ByteBuffer.wrap(bytes)); 484 format.setByteBuffer(name, ByteBuffer.wrap(bytes));
421 } 485 }
(...skipping 16 matching lines...) Expand all
438 AudioFormat.CHANNEL_OUT_STEREO; 502 AudioFormat.CHANNEL_OUT_STEREO;
439 // Using 16bit PCM for output. Keep this value in sync with 503 // Using 16bit PCM for output. Keep this value in sync with
440 // kBytesPerAudioOutputSample in media_codec_bridge.cc. 504 // kBytesPerAudioOutputSample in media_codec_bridge.cc.
441 int minBufferSize = AudioTrack.getMinBufferSize(sampleRate, chan nelConfig, 505 int minBufferSize = AudioTrack.getMinBufferSize(sampleRate, chan nelConfig,
442 AudioFormat.ENCODING_PCM_16BIT); 506 AudioFormat.ENCODING_PCM_16BIT);
443 mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRa te, channelConfig, 507 mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRa te, channelConfig,
444 AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrac k.MODE_STREAM); 508 AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrac k.MODE_STREAM);
445 } 509 }
446 return true; 510 return true;
447 } catch (IllegalStateException e) { 511 } catch (IllegalStateException e) {
448 Log.e(TAG, "Cannot configure the audio codec " + e.toString()); 512 Log.e(TAG, "Cannot configure the audio codec", e);
449 } 513 }
450 return false; 514 return false;
451 } 515 }
452 516
453 @CalledByNative 517 @CalledByNative
454 private void playOutputBuffer(byte[] buf) { 518 private void playOutputBuffer(byte[] buf) {
455 if (mAudioTrack != null) { 519 if (mAudioTrack != null) {
456 if (AudioTrack.PLAYSTATE_PLAYING != mAudioTrack.getPlayState()) { 520 if (AudioTrack.PLAYSTATE_PLAYING != mAudioTrack.getPlayState()) {
457 mAudioTrack.play(); 521 mAudioTrack.play();
458 } 522 }
(...skipping 13 matching lines...) Expand all
472 } 536 }
473 537
474 private void resetLastPresentationTimeIfNeeded(long presentationTimeUs) { 538 private void resetLastPresentationTimeIfNeeded(long presentationTimeUs) {
475 if (mFlushed) { 539 if (mFlushed) {
476 mLastPresentationTimeUs = 540 mLastPresentationTimeUs =
477 Math.max(presentationTimeUs - MAX_PRESENTATION_TIMESTAMP_SHI FT_US, 0); 541 Math.max(presentationTimeUs - MAX_PRESENTATION_TIMESTAMP_SHI FT_US, 0);
478 mFlushed = false; 542 mFlushed = false;
479 } 543 }
480 } 544 }
481 } 545 }
OLDNEW
« no previous file with comments | « gpu/config/software_rendering_list_json.cc ('k') | media/base/android/media_codec_bridge.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698