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

Side by Side Diff: talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoDecoder.java

Issue 1338033003: Log to webrtc logging stream from java code. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: not lose tag Created 5 years, 3 months 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
OLDNEW
1 /* 1 /*
2 * libjingle 2 * libjingle
3 * Copyright 2014 Google Inc. 3 * Copyright 2014 Google Inc.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright notice, 8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer. 9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, 10 * 2. Redistributions in binary form must reproduce the above copyright notice,
(...skipping 20 matching lines...) Expand all
31 import android.media.MediaCodec; 31 import android.media.MediaCodec;
32 import android.media.MediaCodecInfo; 32 import android.media.MediaCodecInfo;
33 import android.media.MediaCodecInfo.CodecCapabilities; 33 import android.media.MediaCodecInfo.CodecCapabilities;
34 import android.media.MediaCodecList; 34 import android.media.MediaCodecList;
35 import android.media.MediaFormat; 35 import android.media.MediaFormat;
36 import android.opengl.EGL14; 36 import android.opengl.EGL14;
37 import android.opengl.EGLContext; 37 import android.opengl.EGLContext;
38 import android.opengl.GLES11Ext; 38 import android.opengl.GLES11Ext;
39 import android.opengl.GLES20; 39 import android.opengl.GLES20;
40 import android.os.Build; 40 import android.os.Build;
41 import android.util.Log;
42 import android.view.Surface; 41 import android.view.Surface;
43 42
43 import org.webrtc.Logging;
44
44 import java.nio.ByteBuffer; 45 import java.nio.ByteBuffer;
45 46
46 // Java-side of peerconnection_jni.cc:MediaCodecVideoDecoder. 47 // Java-side of peerconnection_jni.cc:MediaCodecVideoDecoder.
47 // This class is an implementation detail of the Java PeerConnection API. 48 // This class is an implementation detail of the Java PeerConnection API.
48 // MediaCodec is thread-hostile so this class must be operated on a single 49 // MediaCodec is thread-hostile so this class must be operated on a single
49 // thread. 50 // thread.
50 public class MediaCodecVideoDecoder { 51 public class MediaCodecVideoDecoder {
51 // This class is constructed, operated, and destroyed by its C++ incarnation, 52 // This class is constructed, operated, and destroyed by its C++ incarnation,
52 // so the class and its methods have non-public visibility. The API this 53 // so the class and its methods have non-public visibility. The API this
53 // class exposes aims to mimic the webrtc::VideoDecoder API as closely as 54 // class exposes aims to mimic the webrtc::VideoDecoder API as closely as
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 String name = null; 123 String name = null;
123 for (String mimeType : info.getSupportedTypes()) { 124 for (String mimeType : info.getSupportedTypes()) {
124 if (mimeType.equals(mime)) { 125 if (mimeType.equals(mime)) {
125 name = info.getName(); 126 name = info.getName();
126 break; 127 break;
127 } 128 }
128 } 129 }
129 if (name == null) { 130 if (name == null) {
130 continue; // No HW support in this codec; try the next one. 131 continue; // No HW support in this codec; try the next one.
131 } 132 }
132 Log.v(TAG, "Found candidate decoder " + name); 133 Logging.v(TAG, "Found candidate decoder " + name);
133 134
134 // Check if this is supported decoder. 135 // Check if this is supported decoder.
135 boolean supportedCodec = false; 136 boolean supportedCodec = false;
136 for (String codecPrefix : supportedCodecPrefixes) { 137 for (String codecPrefix : supportedCodecPrefixes) {
137 if (name.startsWith(codecPrefix)) { 138 if (name.startsWith(codecPrefix)) {
138 supportedCodec = true; 139 supportedCodec = true;
139 break; 140 break;
140 } 141 }
141 } 142 }
142 if (!supportedCodec) { 143 if (!supportedCodec) {
143 continue; 144 continue;
144 } 145 }
145 146
146 // Check if codec supports either yuv420 or nv12. 147 // Check if codec supports either yuv420 or nv12.
147 CodecCapabilities capabilities = 148 CodecCapabilities capabilities =
148 info.getCapabilitiesForType(mime); 149 info.getCapabilitiesForType(mime);
149 for (int colorFormat : capabilities.colorFormats) { 150 for (int colorFormat : capabilities.colorFormats) {
150 Log.v(TAG, " Color: 0x" + Integer.toHexString(colorFormat)); 151 Logging.v(TAG, " Color: 0x" + Integer.toHexString(colorFormat));
151 } 152 }
152 for (int supportedColorFormat : supportedColorList) { 153 for (int supportedColorFormat : supportedColorList) {
153 for (int codecColorFormat : capabilities.colorFormats) { 154 for (int codecColorFormat : capabilities.colorFormats) {
154 if (codecColorFormat == supportedColorFormat) { 155 if (codecColorFormat == supportedColorFormat) {
155 // Found supported HW decoder. 156 // Found supported HW decoder.
156 Log.d(TAG, "Found target decoder " + name + 157 Logging.d(TAG, "Found target decoder " + name +
157 ". Color: 0x" + Integer.toHexString(codecColorFormat)); 158 ". Color: 0x" + Integer.toHexString(codecColorFormat));
158 return new DecoderProperties(name, codecColorFormat); 159 return new DecoderProperties(name, codecColorFormat);
159 } 160 }
160 } 161 }
161 } 162 }
162 } 163 }
163 return null; // No HW decoder. 164 return null; // No HW decoder.
164 } 165 }
165 166
166 public static boolean isVp8HwSupported() { 167 public static boolean isVp8HwSupported() {
(...skipping 29 matching lines...) Expand all
196 } else if (type == VideoCodecType.VIDEO_CODEC_H264) { 197 } else if (type == VideoCodecType.VIDEO_CODEC_H264) {
197 mime = H264_MIME_TYPE; 198 mime = H264_MIME_TYPE;
198 supportedCodecPrefixes = supportedH264HwCodecPrefixes; 199 supportedCodecPrefixes = supportedH264HwCodecPrefixes;
199 } else { 200 } else {
200 throw new RuntimeException("Non supported codec " + type); 201 throw new RuntimeException("Non supported codec " + type);
201 } 202 }
202 DecoderProperties properties = findDecoder(mime, supportedCodecPrefixes); 203 DecoderProperties properties = findDecoder(mime, supportedCodecPrefixes);
203 if (properties == null) { 204 if (properties == null) {
204 throw new RuntimeException("Cannot find HW decoder for " + type); 205 throw new RuntimeException("Cannot find HW decoder for " + type);
205 } 206 }
206 Log.d(TAG, "Java initDecode: " + type + " : "+ width + " x " + height + 207 Logging.d(TAG, "Java initDecode: " + type + " : "+ width + " x " + height +
207 ". Color: 0x" + Integer.toHexString(properties.colorFormat) + 208 ". Color: 0x" + Integer.toHexString(properties.colorFormat) +
208 ". Use Surface: " + useSurface); 209 ". Use Surface: " + useSurface);
209 if (sharedContext != null) { 210 if (sharedContext != null) {
210 Log.d(TAG, "Decoder shared EGL Context: " + sharedContext); 211 Logging.d(TAG, "Decoder shared EGL Context: " + sharedContext);
211 } 212 }
212 mediaCodecThread = Thread.currentThread(); 213 mediaCodecThread = Thread.currentThread();
213 try { 214 try {
214 Surface decodeSurface = null; 215 Surface decodeSurface = null;
215 this.width = width; 216 this.width = width;
216 this.height = height; 217 this.height = height;
217 this.useSurface = useSurface; 218 this.useSurface = useSurface;
218 stride = width; 219 stride = width;
219 sliceHeight = height; 220 sliceHeight = height;
220 221
221 if (useSurface) { 222 if (useSurface) {
222 // Create shared EGL context. 223 // Create shared EGL context.
223 eglBase = new EglBase(sharedContext, EglBase.ConfigType.PIXEL_BUFFER); 224 eglBase = new EglBase(sharedContext, EglBase.ConfigType.PIXEL_BUFFER);
224 eglBase.createDummyPbufferSurface(); 225 eglBase.createDummyPbufferSurface();
225 eglBase.makeCurrent(); 226 eglBase.makeCurrent();
226 227
227 // Create output surface 228 // Create output surface
228 textureID = GlUtil.generateTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES); 229 textureID = GlUtil.generateTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);
229 Log.d(TAG, "Video decoder TextureID = " + textureID); 230 Logging.d(TAG, "Video decoder TextureID = " + textureID);
230 surfaceTexture = new SurfaceTexture(textureID); 231 surfaceTexture = new SurfaceTexture(textureID);
231 surface = new Surface(surfaceTexture); 232 surface = new Surface(surfaceTexture);
232 decodeSurface = surface; 233 decodeSurface = surface;
233 } 234 }
234 235
235 MediaFormat format = MediaFormat.createVideoFormat(mime, width, height); 236 MediaFormat format = MediaFormat.createVideoFormat(mime, width, height);
236 if (!useSurface) { 237 if (!useSurface) {
237 format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat); 238 format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
238 } 239 }
239 Log.d(TAG, " Format: " + format); 240 Logging.d(TAG, " Format: " + format);
240 mediaCodec = 241 mediaCodec =
241 MediaCodecVideoEncoder.createByCodecName(properties.codecName); 242 MediaCodecVideoEncoder.createByCodecName(properties.codecName);
242 if (mediaCodec == null) { 243 if (mediaCodec == null) {
243 return false; 244 return false;
244 } 245 }
245 mediaCodec.configure(format, decodeSurface, null, 0); 246 mediaCodec.configure(format, decodeSurface, null, 0);
246 mediaCodec.start(); 247 mediaCodec.start();
247 colorFormat = properties.colorFormat; 248 colorFormat = properties.colorFormat;
248 outputBuffers = mediaCodec.getOutputBuffers(); 249 outputBuffers = mediaCodec.getOutputBuffers();
249 inputBuffers = mediaCodec.getInputBuffers(); 250 inputBuffers = mediaCodec.getInputBuffers();
250 Log.d(TAG, "Input buffers: " + inputBuffers.length + 251 Logging.d(TAG, "Input buffers: " + inputBuffers.length +
251 ". Output buffers: " + outputBuffers.length); 252 ". Output buffers: " + outputBuffers.length);
252 return true; 253 return true;
253 } catch (IllegalStateException e) { 254 } catch (IllegalStateException e) {
254 Log.e(TAG, "initDecode failed", e); 255 Logging.e(TAG, "initDecode failed", e);
255 return false; 256 return false;
256 } 257 }
257 } 258 }
258 259
259 private void release() { 260 private void release() {
260 Log.d(TAG, "Java releaseDecoder"); 261 Logging.d(TAG, "Java releaseDecoder");
261 checkOnMediaCodecThread(); 262 checkOnMediaCodecThread();
262 try { 263 try {
263 mediaCodec.stop(); 264 mediaCodec.stop();
264 mediaCodec.release(); 265 mediaCodec.release();
265 } catch (IllegalStateException e) { 266 } catch (IllegalStateException e) {
266 Log.e(TAG, "release failed", e); 267 Logging.e(TAG, "release failed", e);
267 } 268 }
268 mediaCodec = null; 269 mediaCodec = null;
269 mediaCodecThread = null; 270 mediaCodecThread = null;
270 if (useSurface) { 271 if (useSurface) {
271 surface.release(); 272 surface.release();
272 if (textureID != 0) { 273 if (textureID != 0) {
273 Log.d(TAG, "Delete video decoder TextureID " + textureID); 274 Logging.d(TAG, "Delete video decoder TextureID " + textureID);
274 GLES20.glDeleteTextures(1, new int[] {textureID}, 0); 275 GLES20.glDeleteTextures(1, new int[] {textureID}, 0);
275 textureID = 0; 276 textureID = 0;
276 } 277 }
277 eglBase.release(); 278 eglBase.release();
278 eglBase = null; 279 eglBase = null;
279 } 280 }
280 } 281 }
281 282
282 // Dequeue an input buffer and return its index, -1 if no input buffer is 283 // Dequeue an input buffer and return its index, -1 if no input buffer is
283 // available, or -2 if the codec is no longer operative. 284 // available, or -2 if the codec is no longer operative.
284 private int dequeueInputBuffer() { 285 private int dequeueInputBuffer() {
285 checkOnMediaCodecThread(); 286 checkOnMediaCodecThread();
286 try { 287 try {
287 return mediaCodec.dequeueInputBuffer(DEQUEUE_INPUT_TIMEOUT); 288 return mediaCodec.dequeueInputBuffer(DEQUEUE_INPUT_TIMEOUT);
288 } catch (IllegalStateException e) { 289 } catch (IllegalStateException e) {
289 Log.e(TAG, "dequeueIntputBuffer failed", e); 290 Logging.e(TAG, "dequeueIntputBuffer failed", e);
290 return -2; 291 return -2;
291 } 292 }
292 } 293 }
293 294
294 private boolean queueInputBuffer( 295 private boolean queueInputBuffer(
295 int inputBufferIndex, int size, long timestampUs) { 296 int inputBufferIndex, int size, long timestampUs) {
296 checkOnMediaCodecThread(); 297 checkOnMediaCodecThread();
297 try { 298 try {
298 inputBuffers[inputBufferIndex].position(0); 299 inputBuffers[inputBufferIndex].position(0);
299 inputBuffers[inputBufferIndex].limit(size); 300 inputBuffers[inputBufferIndex].limit(size);
300 mediaCodec.queueInputBuffer(inputBufferIndex, 0, size, timestampUs, 0); 301 mediaCodec.queueInputBuffer(inputBufferIndex, 0, size, timestampUs, 0);
301 return true; 302 return true;
302 } 303 }
303 catch (IllegalStateException e) { 304 catch (IllegalStateException e) {
304 Log.e(TAG, "decode failed", e); 305 Logging.e(TAG, "decode failed", e);
305 return false; 306 return false;
306 } 307 }
307 } 308 }
308 309
309 // Helper struct for dequeueOutputBuffer() below. 310 // Helper struct for dequeueOutputBuffer() below.
310 private static class DecoderOutputBufferInfo { 311 private static class DecoderOutputBufferInfo {
311 public DecoderOutputBufferInfo( 312 public DecoderOutputBufferInfo(
312 int index, int offset, int size, long presentationTimestampUs) { 313 int index, int offset, int size, long presentationTimestampUs) {
313 this.index = index; 314 this.index = index;
314 this.offset = offset; 315 this.offset = offset;
(...skipping 11 matching lines...) Expand all
326 // buffer available or -2 if error happened. 327 // buffer available or -2 if error happened.
327 private DecoderOutputBufferInfo dequeueOutputBuffer(int dequeueTimeoutUs) { 328 private DecoderOutputBufferInfo dequeueOutputBuffer(int dequeueTimeoutUs) {
328 checkOnMediaCodecThread(); 329 checkOnMediaCodecThread();
329 try { 330 try {
330 MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); 331 MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
331 int result = mediaCodec.dequeueOutputBuffer(info, dequeueTimeoutUs); 332 int result = mediaCodec.dequeueOutputBuffer(info, dequeueTimeoutUs);
332 while (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED || 333 while (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED ||
333 result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { 334 result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
334 if (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) { 335 if (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
335 outputBuffers = mediaCodec.getOutputBuffers(); 336 outputBuffers = mediaCodec.getOutputBuffers();
336 Log.d(TAG, "Decoder output buffers changed: " + outputBuffers.length); 337 Logging.d(TAG, "Decoder output buffers changed: " + outputBuffers.leng th);
337 } else if (result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { 338 } else if (result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
338 MediaFormat format = mediaCodec.getOutputFormat(); 339 MediaFormat format = mediaCodec.getOutputFormat();
339 Log.d(TAG, "Decoder format changed: " + format.toString()); 340 Logging.d(TAG, "Decoder format changed: " + format.toString());
340 width = format.getInteger(MediaFormat.KEY_WIDTH); 341 width = format.getInteger(MediaFormat.KEY_WIDTH);
341 height = format.getInteger(MediaFormat.KEY_HEIGHT); 342 height = format.getInteger(MediaFormat.KEY_HEIGHT);
342 if (!useSurface && format.containsKey(MediaFormat.KEY_COLOR_FORMAT)) { 343 if (!useSurface && format.containsKey(MediaFormat.KEY_COLOR_FORMAT)) {
343 colorFormat = format.getInteger(MediaFormat.KEY_COLOR_FORMAT); 344 colorFormat = format.getInteger(MediaFormat.KEY_COLOR_FORMAT);
344 Log.d(TAG, "Color: 0x" + Integer.toHexString(colorFormat)); 345 Logging.d(TAG, "Color: 0x" + Integer.toHexString(colorFormat));
345 // Check if new color space is supported. 346 // Check if new color space is supported.
346 boolean validColorFormat = false; 347 boolean validColorFormat = false;
347 for (int supportedColorFormat : supportedColorList) { 348 for (int supportedColorFormat : supportedColorList) {
348 if (colorFormat == supportedColorFormat) { 349 if (colorFormat == supportedColorFormat) {
349 validColorFormat = true; 350 validColorFormat = true;
350 break; 351 break;
351 } 352 }
352 } 353 }
353 if (!validColorFormat) { 354 if (!validColorFormat) {
354 Log.e(TAG, "Non supported color format"); 355 Logging.e(TAG, "Non supported color format");
355 return new DecoderOutputBufferInfo(-1, 0, 0, -1); 356 return new DecoderOutputBufferInfo(-1, 0, 0, -1);
356 } 357 }
357 } 358 }
358 if (format.containsKey("stride")) { 359 if (format.containsKey("stride")) {
359 stride = format.getInteger("stride"); 360 stride = format.getInteger("stride");
360 } 361 }
361 if (format.containsKey("slice-height")) { 362 if (format.containsKey("slice-height")) {
362 sliceHeight = format.getInteger("slice-height"); 363 sliceHeight = format.getInteger("slice-height");
363 } 364 }
364 Log.d(TAG, "Frame stride and slice height: " 365 Logging.d(TAG, "Frame stride and slice height: "
365 + stride + " x " + sliceHeight); 366 + stride + " x " + sliceHeight);
366 stride = Math.max(width, stride); 367 stride = Math.max(width, stride);
367 sliceHeight = Math.max(height, sliceHeight); 368 sliceHeight = Math.max(height, sliceHeight);
368 } 369 }
369 result = mediaCodec.dequeueOutputBuffer(info, dequeueTimeoutUs); 370 result = mediaCodec.dequeueOutputBuffer(info, dequeueTimeoutUs);
370 } 371 }
371 if (result >= 0) { 372 if (result >= 0) {
372 return new DecoderOutputBufferInfo(result, info.offset, info.size, 373 return new DecoderOutputBufferInfo(result, info.offset, info.size,
373 info.presentationTimeUs); 374 info.presentationTimeUs);
374 } 375 }
375 return null; 376 return null;
376 } catch (IllegalStateException e) { 377 } catch (IllegalStateException e) {
377 Log.e(TAG, "dequeueOutputBuffer failed", e); 378 Logging.e(TAG, "dequeueOutputBuffer failed", e);
378 return new DecoderOutputBufferInfo(-1, 0, 0, -1); 379 return new DecoderOutputBufferInfo(-1, 0, 0, -1);
379 } 380 }
380 } 381 }
381 382
382 // Release a dequeued output buffer back to the codec for re-use. Return 383 // Release a dequeued output buffer back to the codec for re-use. Return
383 // false if the codec is no longer operable. 384 // false if the codec is no longer operable.
384 private boolean releaseOutputBuffer(int index, boolean render) { 385 private boolean releaseOutputBuffer(int index, boolean render) {
385 checkOnMediaCodecThread(); 386 checkOnMediaCodecThread();
386 try { 387 try {
387 if (!useSurface) { 388 if (!useSurface) {
388 render = false; 389 render = false;
389 } 390 }
390 mediaCodec.releaseOutputBuffer(index, render); 391 mediaCodec.releaseOutputBuffer(index, render);
391 return true; 392 return true;
392 } catch (IllegalStateException e) { 393 } catch (IllegalStateException e) {
393 Log.e(TAG, "releaseOutputBuffer failed", e); 394 Logging.e(TAG, "releaseOutputBuffer failed", e);
394 return false; 395 return false;
395 } 396 }
396 } 397 }
397 } 398 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698