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

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, 1 month 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
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 */
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 @CalledByNative("DequeueInputResult") 79 @CalledByNative("DequeueInputResult")
78 private int index() { return mIndex; } 80 private int index() { return mIndex; }
79 } 81 }
80 82
81 /** 83 /**
82 * This class represents supported android codec information. 84 * This class represents supported android codec information.
83 */ 85 */
84 private static class CodecInfo { 86 private static class CodecInfo {
85 private final String mCodecType; // e.g. "video/x-vnd.on2.vp8". 87 private final String mCodecType; // e.g. "video/x-vnd.on2.vp8".
86 private final String mCodecName; // e.g. "OMX.google.vp8.decoder". 88 private final String mCodecName; // e.g. "OMX.google.vp8.decoder".
89 private final boolean mIsEncoder;
87 90
88 private CodecInfo(String codecType, String codecName) { 91 private CodecInfo(String codecType, String codecName,
92 boolean isEncoder) {
89 mCodecType = codecType; 93 mCodecType = codecType;
90 mCodecName = codecName; 94 mCodecName = codecName;
95 mIsEncoder = isEncoder;
91 } 96 }
92 97
93 @CalledByNative("CodecInfo") 98 @CalledByNative("CodecInfo")
94 private String codecType() { return mCodecType; } 99 private String codecType() { return mCodecType; }
95 100
96 @CalledByNative("CodecInfo") 101 @CalledByNative("CodecInfo")
97 private String codecName() { return mCodecName; } 102 private String codecName() { return mCodecName; }
103
104 @CalledByNative("CodecInfo")
105 private boolean isEncoder() { return mIsEncoder; }
98 } 106 }
99 107
100 private static class DequeueOutputResult { 108 private static class DequeueOutputResult {
101 private final int mStatus; 109 private final int mStatus;
102 private final int mIndex; 110 private final int mIndex;
103 private final int mFlags; 111 private final int mFlags;
104 private final int mOffset; 112 private final int mOffset;
105 private final long mPresentationTimeMicroseconds; 113 private final long mPresentationTimeMicroseconds;
106 private final int mNumBytes; 114 private final int mNumBytes;
107 115
(...skipping 24 matching lines...) Expand all
132 140
133 @CalledByNative("DequeueOutputResult") 141 @CalledByNative("DequeueOutputResult")
134 private int numBytes() { return mNumBytes; } 142 private int numBytes() { return mNumBytes; }
135 } 143 }
136 144
137 /** 145 /**
138 * Get a list of supported android codec mimes. 146 * Get a list of supported android codec mimes.
139 */ 147 */
140 @CalledByNative 148 @CalledByNative
141 private static CodecInfo[] getCodecsInfo() { 149 private static CodecInfo[] getCodecsInfo() {
142 Map<String, CodecInfo> CodecInfoMap = new HashMap<String, CodecInfo>(); 150 Map<String, CodecInfo> encoderInfoMap = new HashMap<String, CodecInfo>() ;
151 Map<String, CodecInfo> decoderInfoMap = new HashMap<String, CodecInfo>() ;
xhwang 2013/11/19 00:11:25 It's a bit odd to have two maps here then merge th
Ami GONE FROM CHROMIUM 2013/11/21 22:59:07 Agreed.
143 int count = MediaCodecList.getCodecCount(); 152 int count = MediaCodecList.getCodecCount();
144 for (int i = 0; i < count; ++i) { 153 for (int i = 0; i < count; ++i) {
145 MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i); 154 MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
146 if (info.isEncoder()) { 155 boolean isEncoder = info.isEncoder();
147 continue;
148 }
149
150 String codecString = info.getName(); 156 String codecString = info.getName();
151 String[] supportedTypes = info.getSupportedTypes(); 157 String[] supportedTypes = info.getSupportedTypes();
152 for (int j = 0; j < supportedTypes.length; ++j) { 158 for (int j = 0; j < supportedTypes.length; ++j) {
153 if (!CodecInfoMap.containsKey(supportedTypes[j])) { 159 Map<String, CodecInfo> map = isEncoder ? encoderInfoMap : decode rInfoMap;
154 CodecInfoMap.put(supportedTypes[j], new CodecInfo( 160 if (!map.containsKey(supportedTypes[j])) {
155 supportedTypes[j], codecString)); 161 map.put(supportedTypes[j], new CodecInfo(
162 supportedTypes[j], codecString, isEncoder));
156 } 163 }
157 } 164 }
158 } 165 }
159 return CodecInfoMap.values().toArray( 166 ArrayList<CodecInfo> codecInfos = new ArrayList<CodecInfo>(
160 new CodecInfo[CodecInfoMap.size()]); 167 decoderInfoMap.size() + encoderInfoMap.size());
168 codecInfos.addAll(encoderInfoMap.values());
169 codecInfos.addAll(decoderInfoMap.values());
170 return codecInfos.toArray(new CodecInfo[codecInfos.size()]);
161 } 171 }
162 172
163 private static String getSecureDecoderNameForMime(String mime) { 173 private static String getSecureDecoderNameForMime(String mime) {
164 int count = MediaCodecList.getCodecCount(); 174 int count = MediaCodecList.getCodecCount();
165 for (int i = 0; i < count; ++i) { 175 for (int i = 0; i < count; ++i) {
166 MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i); 176 MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
167 if (info.isEncoder()) { 177 if (info.isEncoder()) {
168 continue; 178 continue;
169 } 179 }
170 180
171 String[] supportedTypes = info.getSupportedTypes(); 181 String[] supportedTypes = info.getSupportedTypes();
172 for (int j = 0; j < supportedTypes.length; ++j) { 182 for (int j = 0; j < supportedTypes.length; ++j) {
173 if (supportedTypes[j].equalsIgnoreCase(mime)) { 183 if (supportedTypes[j].equalsIgnoreCase(mime)) {
174 return info.getName() + ".secure"; 184 return info.getName() + ".secure";
175 } 185 }
176 } 186 }
177 } 187 }
178 188
179 return null; 189 return null;
180 } 190 }
181 191
182 private MediaCodecBridge(MediaCodec mediaCodec) { 192 private MediaCodecBridge(MediaCodec mediaCodec) {
183 assert(mediaCodec != null); 193 assert(mediaCodec != null);
184 mMediaCodec = mediaCodec; 194 mMediaCodec = mediaCodec;
185 mLastPresentationTimeUs = 0; 195 mLastPresentationTimeUs = 0;
186 mFlushed = true; 196 mFlushed = true;
187 } 197 }
188 198
189 @CalledByNative 199 @CalledByNative
190 private static MediaCodecBridge create(String mime, boolean isSecure) { 200 private static MediaCodecBridge create(String mime, boolean isSecure, boolea n isEncoder) {
191 // Creation of ".secure" codecs sometimes crash instead of throwing exce ptions 201 // Creation of ".secure" codecs sometimes crash instead of throwing exce ptions
192 // on pre-JBMR2 devices. 202 // on pre-JBMR2 devices.
193 if (isSecure && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_M R2) { 203 if (isSecure && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_M R2) {
194 return null; 204 return null;
195 } 205 }
196 MediaCodec mediaCodec = null; 206 MediaCodec mediaCodec = null;
197 try { 207 try {
198 // |isSecure| only applies to video decoders. 208 // |isSecure| only applies to video decoders.
199 if (mime.startsWith("video") && isSecure) { 209 if (mime.startsWith("video") && isSecure && !isEncoder) {
200 mediaCodec = MediaCodec.createByCodecName(getSecureDecoderNameFo rMime(mime)); 210 mediaCodec = MediaCodec.createByCodecName(getSecureDecoderNameFo rMime(mime));
201 } else { 211 } else {
202 mediaCodec = MediaCodec.createDecoderByType(mime); 212 if (isEncoder) {
213 mediaCodec = MediaCodec.createEncoderByType(mime);
214 } else {
215 mediaCodec = MediaCodec.createDecoderByType(mime);
216 }
203 } 217 }
204 } catch (Exception e) { 218 } catch (Exception e) {
205 Log.e(TAG, "Failed to create MediaCodec: " + mime + ", isSecure: " 219 Log.e(TAG, "Failed to create MediaCodec: " + mime + ", isSecure: "
206 + isSecure + ", " + e.toString()); 220 + isSecure + ", isEncoder: " + isEncoder, e);
207 } 221 }
208 222
209 if (mediaCodec == null) { 223 if (mediaCodec == null) {
210 return null; 224 return null;
211 } 225 }
212 226
213 return new MediaCodecBridge(mediaCodec); 227 return new MediaCodecBridge(mediaCodec);
214 } 228 }
215 229
216 @CalledByNative 230 @CalledByNative
217 private void release() { 231 private void release() {
232 String name = mMediaCodec.getName();
233 mMediaCodec.stop();
218 mMediaCodec.release(); 234 mMediaCodec.release();
235 mMediaCodec = null;
219 if (mAudioTrack != null) { 236 if (mAudioTrack != null) {
220 mAudioTrack.release(); 237 mAudioTrack.release();
221 } 238 }
222 } 239 }
223 240
224 @CalledByNative 241 @CalledByNative
225 private boolean start() { 242 private boolean start() {
226 try { 243 try {
227 mMediaCodec.start(); 244 mMediaCodec.start();
228 mInputBuffers = mMediaCodec.getInputBuffers(); 245 mInputBuffers = mMediaCodec.getInputBuffers();
229 } catch (IllegalStateException e) { 246 } catch (IllegalStateException e) {
230 Log.e(TAG, "Cannot start the media codec " + e.toString()); 247 Log.e(TAG, "Cannot start the media codec", e);
231 return false; 248 return false;
232 } 249 }
233 return true; 250 return true;
234 } 251 }
235 252
236 @CalledByNative 253 @CalledByNative
237 private DequeueInputResult dequeueInputBuffer(long timeoutUs) { 254 private DequeueInputResult dequeueInputBuffer(long timeoutUs) {
238 int status = MEDIA_CODEC_ERROR; 255 int status = MEDIA_CODEC_ERROR;
239 int index = -1; 256 int index = -1;
240 try { 257 try {
241 int index_or_status = mMediaCodec.dequeueInputBuffer(timeoutUs); 258 int index_or_status = mMediaCodec.dequeueInputBuffer(timeoutUs);
242 if (index_or_status >= 0) { // index! 259 if (index_or_status >= 0) { // index!
243 status = MEDIA_CODEC_OK; 260 status = MEDIA_CODEC_OK;
244 index = index_or_status; 261 index = index_or_status;
245 } else if (index_or_status == MediaCodec.INFO_TRY_AGAIN_LATER) { 262 } else if (index_or_status == MediaCodec.INFO_TRY_AGAIN_LATER) {
246 Log.e(TAG, "dequeueInputBuffer: MediaCodec.INFO_TRY_AGAIN_LATER" ); 263 Log.e(TAG, "dequeueInputBuffer: MediaCodec.INFO_TRY_AGAIN_LATER" );
247 status = MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER; 264 status = MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER;
248 } else { 265 } else {
266 Log.e(TAG, "Unexpected index_or_status: " + index_or_status);
249 assert(false); 267 assert(false);
250 } 268 }
251 } catch(Exception e) { 269 } catch(Exception e) {
252 Log.e(TAG, "Failed to dequeue input buffer: " + e.toString()); 270 Log.e(TAG, "Failed to dequeue input buffer", e);
253 } 271 }
254 return new DequeueInputResult(status, index); 272 return new DequeueInputResult(status, index);
255 } 273 }
256 274
257 @CalledByNative 275 @CalledByNative
258 private int flush() { 276 private int flush() {
259 try { 277 try {
260 mFlushed = true; 278 mFlushed = true;
261 if (mAudioTrack != null) { 279 if (mAudioTrack != null) {
262 mAudioTrack.flush(); 280 mAudioTrack.flush();
263 } 281 }
264 mMediaCodec.flush(); 282 mMediaCodec.flush();
265 } catch(IllegalStateException e) { 283 } catch(IllegalStateException e) {
266 Log.e(TAG, "Failed to flush MediaCodec " + e.toString()); 284 Log.e(TAG, "Failed to flush MediaCodec", e);
267 return MEDIA_CODEC_ERROR; 285 return MEDIA_CODEC_ERROR;
268 } 286 }
269 return MEDIA_CODEC_OK; 287 return MEDIA_CODEC_OK;
270 } 288 }
271 289
272 @CalledByNative 290 @CalledByNative
273 private void stop() { 291 private void stop() {
274 mMediaCodec.stop(); 292 mMediaCodec.stop();
275 if (mAudioTrack != null) { 293 if (mAudioTrack != null) {
276 mAudioTrack.pause(); 294 mAudioTrack.pause();
(...skipping 20 matching lines...) Expand all
297 return mOutputBuffers[index]; 315 return mOutputBuffers[index];
298 } 316 }
299 317
300 @CalledByNative 318 @CalledByNative
301 private int queueInputBuffer( 319 private int queueInputBuffer(
302 int index, int offset, int size, long presentationTimeUs, int flags) { 320 int index, int offset, int size, long presentationTimeUs, int flags) {
303 resetLastPresentationTimeIfNeeded(presentationTimeUs); 321 resetLastPresentationTimeIfNeeded(presentationTimeUs);
304 try { 322 try {
305 mMediaCodec.queueInputBuffer(index, offset, size, presentationTimeUs , flags); 323 mMediaCodec.queueInputBuffer(index, offset, size, presentationTimeUs , flags);
306 } catch(Exception e) { 324 } catch(Exception e) {
307 Log.e(TAG, "Failed to queue input buffer: " + e.toString()); 325 Log.e(TAG, "Failed to queue input buffer", e);
308 return MEDIA_CODEC_ERROR; 326 return MEDIA_CODEC_ERROR;
309 } 327 }
310 return MEDIA_CODEC_OK; 328 return MEDIA_CODEC_OK;
311 } 329 }
312 330
313 @CalledByNative 331 @CalledByNative
332 private void setVideoBitrate(int bps) {
333 Bundle b = new Bundle();
334 b.putInt(MediaCodec.PARAMETER_KEY_VIDEO_BITRATE, bps);
335 mMediaCodec.setParameters(b);
336 }
337
338 @CalledByNative
339 private void requestKeyFrameSoon() {
340 Bundle b = new Bundle();
341 b.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
342 mMediaCodec.setParameters(b);
343 }
344
345 @CalledByNative
314 private int queueSecureInputBuffer( 346 private int queueSecureInputBuffer(
315 int index, int offset, byte[] iv, byte[] keyId, int[] numBytesOfClea rData, 347 int index, int offset, byte[] iv, byte[] keyId, int[] numBytesOfClea rData,
316 int[] numBytesOfEncryptedData, int numSubSamples, long presentationT imeUs) { 348 int[] numBytesOfEncryptedData, int numSubSamples, long presentationT imeUs) {
317 resetLastPresentationTimeIfNeeded(presentationTimeUs); 349 resetLastPresentationTimeIfNeeded(presentationTimeUs);
318 try { 350 try {
319 MediaCodec.CryptoInfo cryptoInfo = new MediaCodec.CryptoInfo(); 351 MediaCodec.CryptoInfo cryptoInfo = new MediaCodec.CryptoInfo();
320 cryptoInfo.set(numSubSamples, numBytesOfClearData, numBytesOfEncrypt edData, 352 cryptoInfo.set(numSubSamples, numBytesOfClearData, numBytesOfEncrypt edData,
321 keyId, iv, MediaCodec.CRYPTO_MODE_AES_CTR); 353 keyId, iv, MediaCodec.CRYPTO_MODE_AES_CTR);
322 mMediaCodec.queueSecureInputBuffer(index, offset, cryptoInfo, presen tationTimeUs, 0); 354 mMediaCodec.queueSecureInputBuffer(index, offset, cryptoInfo, presen tationTimeUs, 0);
323 } catch (MediaCodec.CryptoException e) { 355 } catch (MediaCodec.CryptoException e) {
324 Log.e(TAG, "Failed to queue secure input buffer: " + e.toString()); 356 Log.e(TAG, "Failed to queue secure input buffer", e);
325 // TODO(xhwang): Replace hard coded value with constant/enum. 357 // TODO(xhwang): Replace hard coded value with constant/enum.
326 if (e.getErrorCode() == 1) { 358 if (e.getErrorCode() == 1) {
327 Log.e(TAG, "No key available."); 359 Log.e(TAG, "No key available.");
328 return MEDIA_CODEC_NO_KEY; 360 return MEDIA_CODEC_NO_KEY;
329 } 361 }
330 return MEDIA_CODEC_ERROR; 362 return MEDIA_CODEC_ERROR;
331 } catch(IllegalStateException e) { 363 } catch(IllegalStateException e) {
332 Log.e(TAG, "Failed to queue secure input buffer: " + e.toString()); 364 Log.e(TAG, "Failed to queue secure input buffer", e);
333 return MEDIA_CODEC_ERROR; 365 return MEDIA_CODEC_ERROR;
334 } 366 }
335 return MEDIA_CODEC_OK; 367 return MEDIA_CODEC_OK;
336 } 368 }
337 369
338 @CalledByNative 370 @CalledByNative
339 private void releaseOutputBuffer(int index, boolean render) { 371 private void releaseOutputBuffer(int index, boolean render) {
340 mMediaCodec.releaseOutputBuffer(index, render); 372 mMediaCodec.releaseOutputBuffer(index, render);
341 } 373 }
342 374
343 @CalledByNative 375 @CalledByNative
376 private int getInputBuffersCount() {
377 return mInputBuffers.length;
378 }
379
380 @CalledByNative
381 private int getOutputBuffersCount() {
382 return mOutputBuffers != null ? mOutputBuffers.length : -1;
383 }
384
385 @CalledByNative
386 private int getOutputBuffersCapacity() {
387 return mOutputBuffers != null ? mOutputBuffers[0].capacity() : -1;
388 }
389
390 @CalledByNative
344 private boolean getOutputBuffers() { 391 private boolean getOutputBuffers() {
345 try { 392 try {
346 mOutputBuffers = mMediaCodec.getOutputBuffers(); 393 mOutputBuffers = mMediaCodec.getOutputBuffers();
347 } catch (IllegalStateException e) { 394 } catch (IllegalStateException e) {
348 Log.e(TAG, "Cannot get output buffers " + e.toString()); 395 Log.e(TAG, "Cannot get output buffers", e);
349 return false; 396 return false;
350 } 397 }
351 return true; 398 return true;
352 } 399 }
xhwang 2013/11/19 00:11:25 Move l.375-l.399 to l.317?
Ami GONE FROM CHROMIUM 2013/11/21 22:59:07 Done.
353 400
354 @CalledByNative 401 @CalledByNative
355 private DequeueOutputResult dequeueOutputBuffer(long timeoutUs) { 402 private DequeueOutputResult dequeueOutputBuffer(long timeoutUs) {
356 MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); 403 MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
357 int status = MEDIA_CODEC_ERROR; 404 int status = MEDIA_CODEC_ERROR;
358 int index = -1; 405 int index = -1;
359 try { 406 try {
360 int index_or_status = mMediaCodec.dequeueOutputBuffer(info, timeoutU s); 407 int index_or_status = mMediaCodec.dequeueOutputBuffer(info, timeoutU s);
361 if (info.presentationTimeUs < mLastPresentationTimeUs) { 408 if (info.presentationTimeUs < mLastPresentationTimeUs) {
362 // TODO(qinmin): return a special code through DequeueOutputResu lt 409 // TODO(qinmin): return a special code through DequeueOutputResu lt
363 // to notify the native code the the frame has a wrong presentat ion 410 // to notify the native code the the frame has a wrong presentat ion
364 // timestamp and should be skipped. 411 // timestamp and should be skipped.
365 info.presentationTimeUs = mLastPresentationTimeUs; 412 info.presentationTimeUs = mLastPresentationTimeUs;
366 } 413 }
367 mLastPresentationTimeUs = info.presentationTimeUs; 414 mLastPresentationTimeUs = info.presentationTimeUs;
368 415
369 if (index_or_status >= 0) { // index! 416 if (index_or_status >= 0) { // index!
370 status = MEDIA_CODEC_OK; 417 status = MEDIA_CODEC_OK;
371 index = index_or_status; 418 index = index_or_status;
372 } else if (index_or_status == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED ) { 419 } else if (index_or_status == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED ) {
373 status = MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED; 420 status = MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED;
374 } else if (index_or_status == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { 421 } else if (index_or_status == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
375 status = MEDIA_CODEC_OUTPUT_FORMAT_CHANGED; 422 status = MEDIA_CODEC_OUTPUT_FORMAT_CHANGED;
376 } else if (index_or_status == MediaCodec.INFO_TRY_AGAIN_LATER) { 423 } else if (index_or_status == MediaCodec.INFO_TRY_AGAIN_LATER) {
377 status = MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER; 424 status = MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER;
378 } else { 425 } else {
426 Log.e(TAG, "Unexpected index_or_status: " + index_or_status);
379 assert(false); 427 assert(false);
380 } 428 }
381 } catch (IllegalStateException e) { 429 } catch (IllegalStateException e) {
382 Log.e(TAG, "Failed to dequeue output buffer: " + e.toString()); 430 Log.e(TAG, "Failed to dequeue output buffer", e);
383 } 431 }
384 432
385 return new DequeueOutputResult( 433 return new DequeueOutputResult(
386 status, index, info.flags, info.offset, info.presentationTimeUs, info.size); 434 status, index, info.flags, info.offset, info.presentationTimeUs, info.size);
387 } 435 }
388 436
389 @CalledByNative 437 @CalledByNative
390 private boolean configureVideo(MediaFormat format, Surface surface, MediaCry pto crypto, 438 private boolean configureVideo(MediaFormat format, Surface surface, MediaCry pto crypto,
391 int flags) { 439 int flags) {
392 try { 440 try {
393 mMediaCodec.configure(format, surface, crypto, flags); 441 mMediaCodec.configure(format, surface, crypto, flags);
394 return true; 442 return true;
395 } catch (IllegalStateException e) { 443 } catch (IllegalStateException e) {
396 Log.e(TAG, "Cannot configure the video codec " + e.toString()); 444 Log.e(TAG, "Cannot configure the video codec", e);
397 } 445 }
398 return false; 446 return false;
399 } 447 }
400 448
401 @CalledByNative 449 @CalledByNative
402 private static MediaFormat createAudioFormat(String mime, int SampleRate, in t ChannelCount) { 450 private static MediaFormat createAudioFormat(String mime, int SampleRate, in t ChannelCount) {
403 return MediaFormat.createAudioFormat(mime, SampleRate, ChannelCount); 451 return MediaFormat.createAudioFormat(mime, SampleRate, ChannelCount);
404 } 452 }
405 453
406 @CalledByNative 454 @CalledByNative
407 private static MediaFormat createVideoFormat(String mime, int width, int hei ght) { 455 private static MediaFormat createVideoDecoderFormat(String mime, int width, int height) {
408 return MediaFormat.createVideoFormat(mime, width, height); 456 return MediaFormat.createVideoFormat(mime, width, height);
409 } 457 }
410 458
411 @CalledByNative 459 @CalledByNative
460 private static MediaFormat createVideoEncoderFormat(String mime, int width, int height,
461 int bitRate, int frameRate, int iFrameInterval, int colorFormat) {
462 MediaFormat format = MediaFormat.createVideoFormat(mime, width, height);
463 format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
464 format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
465 format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, iFrameInterval);
466 format.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
467 return format;
468 }
469
470 @CalledByNative
412 private static void setCodecSpecificData(MediaFormat format, int index, byte [] bytes) { 471 private static void setCodecSpecificData(MediaFormat format, int index, byte [] bytes) {
413 String name = null; 472 String name = null;
414 if (index == 0) { 473 if (index == 0) {
415 name = "csd-0"; 474 name = "csd-0";
416 } else if (index == 1) { 475 } else if (index == 1) {
417 name = "csd-1"; 476 name = "csd-1";
418 } 477 }
419 if (name != null) { 478 if (name != null) {
420 format.setByteBuffer(name, ByteBuffer.wrap(bytes)); 479 format.setByteBuffer(name, ByteBuffer.wrap(bytes));
421 } 480 }
(...skipping 16 matching lines...) Expand all
438 AudioFormat.CHANNEL_OUT_STEREO; 497 AudioFormat.CHANNEL_OUT_STEREO;
439 // Using 16bit PCM for output. Keep this value in sync with 498 // Using 16bit PCM for output. Keep this value in sync with
440 // kBytesPerAudioOutputSample in media_codec_bridge.cc. 499 // kBytesPerAudioOutputSample in media_codec_bridge.cc.
441 int minBufferSize = AudioTrack.getMinBufferSize(sampleRate, chan nelConfig, 500 int minBufferSize = AudioTrack.getMinBufferSize(sampleRate, chan nelConfig,
442 AudioFormat.ENCODING_PCM_16BIT); 501 AudioFormat.ENCODING_PCM_16BIT);
443 mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRa te, channelConfig, 502 mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRa te, channelConfig,
444 AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrac k.MODE_STREAM); 503 AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrac k.MODE_STREAM);
445 } 504 }
446 return true; 505 return true;
447 } catch (IllegalStateException e) { 506 } catch (IllegalStateException e) {
448 Log.e(TAG, "Cannot configure the audio codec " + e.toString()); 507 Log.e(TAG, "Cannot configure the audio codec", e);
449 } 508 }
450 return false; 509 return false;
451 } 510 }
452 511
453 @CalledByNative 512 @CalledByNative
454 private void playOutputBuffer(byte[] buf) { 513 private void playOutputBuffer(byte[] buf) {
455 if (mAudioTrack != null) { 514 if (mAudioTrack != null) {
456 if (AudioTrack.PLAYSTATE_PLAYING != mAudioTrack.getPlayState()) { 515 if (AudioTrack.PLAYSTATE_PLAYING != mAudioTrack.getPlayState()) {
457 mAudioTrack.play(); 516 mAudioTrack.play();
458 } 517 }
(...skipping 13 matching lines...) Expand all
472 } 531 }
473 532
474 private void resetLastPresentationTimeIfNeeded(long presentationTimeUs) { 533 private void resetLastPresentationTimeIfNeeded(long presentationTimeUs) {
475 if (mFlushed) { 534 if (mFlushed) {
476 mLastPresentationTimeUs = 535 mLastPresentationTimeUs =
477 Math.max(presentationTimeUs - MAX_PRESENTATION_TIMESTAMP_SHI FT_US, 0); 536 Math.max(presentationTimeUs - MAX_PRESENTATION_TIMESTAMP_SHI FT_US, 0);
478 mFlushed = false; 537 mFlushed = false;
479 } 538 }
480 } 539 }
481 } 540 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698