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

Unified Diff: webrtc/examples/android/media_demo/src/org/webrtc/webrtcdemo/MediaCodecVideoDecoder.java

Issue 1347083003: Remove the video capture module on Android. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Removed Android Java files 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/build/apk_tests_noop.gyp ('k') | webrtc/modules/modules_java.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/examples/android/media_demo/src/org/webrtc/webrtcdemo/MediaCodecVideoDecoder.java
diff --git a/webrtc/examples/android/media_demo/src/org/webrtc/webrtcdemo/MediaCodecVideoDecoder.java b/webrtc/examples/android/media_demo/src/org/webrtc/webrtcdemo/MediaCodecVideoDecoder.java
deleted file mode 100644
index ba811d0d23ed1b786ed67f686d8a6fbc83aadebb..0000000000000000000000000000000000000000
--- a/webrtc/examples/android/media_demo/src/org/webrtc/webrtcdemo/MediaCodecVideoDecoder.java
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-package org.webrtc.webrtcdemo;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.media.MediaCodec;
-import android.media.MediaCrypto;
-import android.media.MediaExtractor;
-import android.media.MediaFormat;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.util.Log;
-import android.view.Surface;
-import android.view.SurfaceView;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.LinkedList;
-
-class MediaCodecVideoDecoder {
- public static final int DECODE = 0;
- private enum CodecName { ON2_VP8, GOOGLE_VPX, EXYNOX_VP8 }
-
- private void check(boolean value, String message) {
- if (value) {
- return;
- }
- Log.e("WEBRTC-CHECK", message);
- AlertDialog alertDialog = new AlertDialog.Builder(context).create();
- alertDialog.setTitle("WebRTC Error");
- alertDialog.setMessage(message);
- alertDialog.setButton(DialogInterface.BUTTON_POSITIVE,
- "OK",
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- return;
- }
- }
- );
- alertDialog.show();
- }
-
- class Frame {
- public ByteBuffer buffer;
- public long timestampUs;
-
- Frame(ByteBuffer buffer, long timestampUs) {
- this.buffer = buffer;
- this.timestampUs = timestampUs;
- }
- }
-
- // This class enables decoding being run on a separate thread.
- class DecodeHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
- // TODO(dwkang): figure out exceptions just make this thread finish.
- try {
- switch (msg.what) {
- case DECODE:
- decodePendingBuffers();
- long delayMillis = 5; // Don't busy wait.
- handler.sendMessageDelayed(
- handler.obtainMessage(DECODE), delayMillis);
- break;
- default:
- break;
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
-
- private static String TAG;
- private Context context;
- private SurfaceView surfaceView;
-
- private DecodeHandler handler;
- private Thread looperThread;
-
- MediaCodec codec;
- MediaFormat format;
-
- // Buffers supplied by MediaCodec for pushing encoded data to and pulling
- // decoded data from.
- private ByteBuffer[] codecInputBuffers;
- private ByteBuffer[] codecOutputBuffers;
-
- // Frames from the native layer.
- private LinkedList<Frame> frameQueue;
- // Indexes to MediaCodec buffers
- private LinkedList<Integer> availableInputBufferIndices;
- private LinkedList<Integer> availableOutputBufferIndices;
- private LinkedList<MediaCodec.BufferInfo> availableOutputBufferInfos;
-
- // Offset between system time and media time.
- private long deltaTimeUs;
-
- public MediaCodecVideoDecoder(Context context) {
- TAG = context.getString(R.string.tag);
- this.context = context;
- surfaceView = new SurfaceView(context);
- frameQueue = new LinkedList<Frame>();
- availableInputBufferIndices = new LinkedList<Integer>();
- availableOutputBufferIndices = new LinkedList<Integer>();
- availableOutputBufferInfos = new LinkedList<MediaCodec.BufferInfo>();
- }
-
- public void dispose() {
- codec.stop();
- codec.release();
- }
-
- // Return view that is written to by MediaCodec.
- public SurfaceView getView() { return surfaceView; }
-
- // Entry point from the native layer. Called when the class should be ready
- // to start receiving raw frames.
- private boolean start(int width, int height) {
- deltaTimeUs = -1;
- if (!setCodecState(width, height, CodecName.ON2_VP8)) {
- return false;
- }
- startLooperThread();
- // The decoding must happen on |looperThread| thread.
- handler.sendMessage(handler.obtainMessage(DECODE));
- return true;
- }
-
- private boolean setCodecState(int width, int height, CodecName codecName) {
- // TODO(henrike): enable more than ON2_VP8 codec.
- format = new MediaFormat();
- format.setInteger(MediaFormat.KEY_WIDTH, width);
- format.setInteger(MediaFormat.KEY_HEIGHT, height);
- try {
- switch (codecName) {
- case ON2_VP8:
- format.setString(MediaFormat.KEY_MIME, "video/x-vnd.on2.vp8");
- codec = MediaCodec.createDecoderByType("video/x-vnd.on2.vp8");
- break;
- case GOOGLE_VPX:
- // SW VP8 decoder
- codec = MediaCodec.createByCodecName("OMX.google.vpx.decoder");
- break;
- case EXYNOX_VP8:
- // Nexus10 HW VP8 decoder
- codec = MediaCodec.createByCodecName("OMX.Exynos.VP8.Decoder");
- break;
- default:
- return false;
- }
- } catch (Exception e) {
- // TODO(dwkang): replace this instanceof/throw with a narrower catch
- // clause once the SDK advances.
- if (e instanceof IOException) {
- Log.e(TAG, "Failed to create MediaCodec for VP8.", e);
- return false;
- }
- throw new RuntimeException(e);
- }
- Surface surface = surfaceView.getHolder().getSurface();
- MediaCrypto crypto = null; // No crypto.
- int flags = 0; // Decoder (1 for encoder)
- codec.configure(format, surface, crypto, flags);
- codec.start();
- codecInputBuffers = codec.getInputBuffers();
- codecOutputBuffers = codec.getOutputBuffers();
- return true;
- }
-
- private void startLooperThread() {
- looperThread = new Thread() {
- @Override
- public void run() {
- Looper.prepare();
- // Handler that is run by this thread.
- handler = new DecodeHandler();
- // Notify that the thread has created a handler.
- synchronized(MediaCodecVideoDecoder.this) {
- MediaCodecVideoDecoder.this.notify();
- }
- Looper.loop();
- }
- };
- looperThread.start();
- // Wait for thread to notify that Handler has been set up.
- synchronized(this) {
- try {
- wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
-
- // Entry point from the native layer. It pushes the raw buffer to this class.
- private void pushBuffer(ByteBuffer buffer, long renderTimeMs) {
- // TODO(dwkang): figure out why exceptions just make this thread finish.
- try {
- final long renderTimeUs = renderTimeMs * 1000;
- synchronized(frameQueue) {
- frameQueue.add(new Frame(buffer, renderTimeUs));
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- private boolean hasFrame() {
- synchronized(frameQueue) {
- return !frameQueue.isEmpty();
- }
- }
-
- private Frame dequeueFrame() {
- synchronized(frameQueue) {
- return frameQueue.removeFirst();
- }
- }
-
- private void flush() {
- availableInputBufferIndices.clear();
- availableOutputBufferIndices.clear();
- availableOutputBufferInfos.clear();
-
- codec.flush();
- }
-
- // Media time is relative to previous frame.
- private long mediaTimeToSystemTime(long mediaTimeUs) {
- if (deltaTimeUs == -1) {
- long nowUs = System.currentTimeMillis() * 1000;
- deltaTimeUs = nowUs - mediaTimeUs;
- }
- return deltaTimeUs + mediaTimeUs;
- }
-
- private void decodePendingBuffers() {
- int timeoutUs = 0; // Don't block on dequeuing input buffer.
-
- int index = codec.dequeueInputBuffer(timeoutUs);
- if (index != MediaCodec.INFO_TRY_AGAIN_LATER) {
- availableInputBufferIndices.add(index);
- }
- while (feedInputBuffer()) {}
-
- MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
- index = codec.dequeueOutputBuffer(info, timeoutUs);
- if (index > 0) {
- availableOutputBufferIndices.add(index);
- availableOutputBufferInfos.add(info);
- }
- if (index == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
- codecOutputBuffers = codec.getOutputBuffers();
- }
-
- while (drainOutputBuffer()) {}
- }
-
- // Returns true if MediaCodec is ready for more data and there was data
- // available from the native layer.
- private boolean feedInputBuffer() {
- if (availableInputBufferIndices.isEmpty()) {
- return false;
- }
- if (!hasFrame()) {
- return false;
- }
- Frame frame = dequeueFrame();
- ByteBuffer buffer = frame.buffer;
-
- int index = availableInputBufferIndices.pollFirst();
- ByteBuffer codecData = codecInputBuffers[index];
- check(codecData.capacity() >= buffer.capacity(),
- "Buffer is too small to copy a frame.");
- buffer.rewind();
- codecData.rewind();
- codecData.put(buffer);
-
- try {
- int offset = 0;
- int flags = 0;
- codec.queueInputBuffer(index, offset, buffer.capacity(),
- frame.timestampUs, flags);
- } catch (MediaCodec.CryptoException e) {
- check(false, "CryptoException w/ errorCode " + e.getErrorCode() +
- ", '" + e.getMessage() + "'");
- }
- return true;
- }
-
- // Returns true if more output data could be drained.MediaCodec has more data
- // to deliver.
- private boolean drainOutputBuffer() {
- if (availableOutputBufferIndices.isEmpty()) {
- return false;
- }
-
- int index = availableOutputBufferIndices.peekFirst();
- MediaCodec.BufferInfo info = availableOutputBufferInfos.peekFirst();
- if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
- // End of stream is unexpected with streamed video.
- check(false, "Saw output end of stream.");
- return false;
- }
- long realTimeUs = mediaTimeToSystemTime(info.presentationTimeUs);
- long nowUs = System.currentTimeMillis() * 1000;
- long lateUs = nowUs - realTimeUs;
- if (lateUs < -10000) {
- // Frame should not be presented yet.
- return false;
- }
-
- // TODO(dwkang): For some extreme cases, just not doing rendering is not
- // enough. Need to seek to the next key frame.
- boolean render = lateUs <= 30000;
- if (!render) {
- Log.d(TAG, "video late by " + lateUs + " us. Skipping...");
- }
- // Decode and render to surface if desired.
- codec.releaseOutputBuffer(index, render);
- availableOutputBufferIndices.removeFirst();
- availableOutputBufferInfos.removeFirst();
- return true;
- }
-}
« no previous file with comments | « webrtc/build/apk_tests_noop.gyp ('k') | webrtc/modules/modules_java.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698