Commit 19144c4c by olly Committed by Oliver Woodman

Allow to disable libyuv dependency on LIBVPX

Goal: reduce binary size.
PiperOrigin-RevId: 231198579
parent 866835ea
...@@ -41,6 +41,9 @@ ...@@ -41,6 +41,9 @@
* Add `Handler` parameter to `ConcatenatingMediaSource` methods which take a * Add `Handler` parameter to `ConcatenatingMediaSource` methods which take a
callback `Runnable`. callback `Runnable`.
* Remove `player` and `isTopLevelSource` parameters from `MediaSource.prepare`. * Remove `player` and `isTopLevelSource` parameters from `MediaSource.prepare`.
* VP9 extension: Remove RGB output mode and libyuv dependency, and switch to
surface YUV output as the default. Remove constructor parameters `scaleToFit`
and `useSurfaceYuvOutput`.
* Change signature of `PlayerNotificationManager.NotificationListener` to better * Change signature of `PlayerNotificationManager.NotificationListener` to better
fit service requirements. Remove ability to set a custom stop action. fit service requirements. Remove ability to set a custom stop action.
......
...@@ -34,26 +34,6 @@ VP9_EXT_PATH="${EXOPLAYER_ROOT}/extensions/vp9/src/main" ...@@ -34,26 +34,6 @@ VP9_EXT_PATH="${EXOPLAYER_ROOT}/extensions/vp9/src/main"
NDK_PATH="<path to Android NDK>" NDK_PATH="<path to Android NDK>"
``` ```
* Fetch libvpx and libyuv:
```
cd "${VP9_EXT_PATH}/jni" && \
git clone https://chromium.googlesource.com/webm/libvpx libvpx && \
git clone https://chromium.googlesource.com/libyuv/libyuv libyuv
```
* Checkout the appropriate branches of libvpx and libyuv (the scripts and
makefiles bundled in this repo are known to work only at these versions of the
libraries - we will update this periodically as newer versions of
libvpx/libyuv are released):
```
cd "${VP9_EXT_PATH}/jni/libvpx" && \
git checkout tags/v1.7.0 -b v1.7.0 && \
cd "${VP9_EXT_PATH}/jni/libyuv" && \
git checkout 996a2bbd
```
* Run a script that generates necessary configuration files for libvpx: * Run a script that generates necessary configuration files for libvpx:
``` ```
...@@ -78,10 +58,6 @@ ${NDK_PATH}/ndk-build APP_ABI=all -j4 ...@@ -78,10 +58,6 @@ ${NDK_PATH}/ndk-build APP_ABI=all -j4
* Android config scripts should be re-generated by running * Android config scripts should be re-generated by running
`generate_libvpx_android_configs.sh` `generate_libvpx_android_configs.sh`
* Clean and re-build the project. * Clean and re-build the project.
* If you want to use your own version of libvpx or libyuv, place it in
`${VP9_EXT_PATH}/jni/libvpx` or `${VP9_EXT_PATH}/jni/libyuv` respectively. But
please note that `generate_libvpx_android_configs.sh` and the makefiles need
to be modified to work with arbitrary versions of libvpx and libyuv.
## Using the extension ## ## Using the extension ##
......
...@@ -114,7 +114,7 @@ public class VpxPlaybackTest { ...@@ -114,7 +114,7 @@ public class VpxPlaybackTest {
@Override @Override
public void run() { public void run() {
Looper.prepare(); Looper.prepare();
LibvpxVideoRenderer videoRenderer = new LibvpxVideoRenderer(true, 0); LibvpxVideoRenderer videoRenderer = new LibvpxVideoRenderer(0);
DefaultTrackSelector trackSelector = new DefaultTrackSelector(); DefaultTrackSelector trackSelector = new DefaultTrackSelector();
player = ExoPlayerFactory.newInstance(context, new Renderer[] {videoRenderer}, trackSelector); player = ExoPlayerFactory.newInstance(context, new Renderer[] {videoRenderer}, trackSelector);
player.addListener(this); player.addListener(this);
......
...@@ -15,8 +15,6 @@ ...@@ -15,8 +15,6 @@
*/ */
package com.google.android.exoplayer2.ext.vp9; package com.google.android.exoplayer2.ext.vp9;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.SystemClock; import android.os.SystemClock;
...@@ -109,7 +107,6 @@ public class LibvpxVideoRenderer extends BaseRenderer { ...@@ -109,7 +107,6 @@ public class LibvpxVideoRenderer extends BaseRenderer {
/** The default input buffer size. */ /** The default input buffer size. */
private static final int DEFAULT_INPUT_BUFFER_SIZE = 768 * 1024; // Value based on cs/SoftVpx.cpp. private static final int DEFAULT_INPUT_BUFFER_SIZE = 768 * 1024; // Value based on cs/SoftVpx.cpp.
private final boolean scaleToFit;
private final boolean disableLoopFilter; private final boolean disableLoopFilter;
private final long allowedJoiningTimeMs; private final long allowedJoiningTimeMs;
private final int maxDroppedFramesToNotify; private final int maxDroppedFramesToNotify;
...@@ -119,7 +116,6 @@ public class LibvpxVideoRenderer extends BaseRenderer { ...@@ -119,7 +116,6 @@ public class LibvpxVideoRenderer extends BaseRenderer {
private final TimedValueQueue<Format> formatQueue; private final TimedValueQueue<Format> formatQueue;
private final DecoderInputBuffer flagsOnlyBuffer; private final DecoderInputBuffer flagsOnlyBuffer;
private final DrmSessionManager<ExoMediaCrypto> drmSessionManager; private final DrmSessionManager<ExoMediaCrypto> drmSessionManager;
private final boolean useSurfaceYuvOutput;
private Format format; private Format format;
private Format pendingFormat; private Format pendingFormat;
...@@ -133,7 +129,6 @@ public class LibvpxVideoRenderer extends BaseRenderer { ...@@ -133,7 +129,6 @@ public class LibvpxVideoRenderer extends BaseRenderer {
private @ReinitializationState int decoderReinitializationState; private @ReinitializationState int decoderReinitializationState;
private boolean decoderReceivedBuffers; private boolean decoderReceivedBuffers;
private Bitmap bitmap;
private boolean renderedFirstFrame; private boolean renderedFirstFrame;
private long initialPositionUs; private long initialPositionUs;
private long joiningDeadlineMs; private long joiningDeadlineMs;
...@@ -158,16 +153,14 @@ public class LibvpxVideoRenderer extends BaseRenderer { ...@@ -158,16 +153,14 @@ public class LibvpxVideoRenderer extends BaseRenderer {
protected DecoderCounters decoderCounters; protected DecoderCounters decoderCounters;
/** /**
* @param scaleToFit Whether video frames should be scaled to fit when rendering.
* @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer * @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer
* can attempt to seamlessly join an ongoing playback. * can attempt to seamlessly join an ongoing playback.
*/ */
public LibvpxVideoRenderer(boolean scaleToFit, long allowedJoiningTimeMs) { public LibvpxVideoRenderer(long allowedJoiningTimeMs) {
this(scaleToFit, allowedJoiningTimeMs, null, null, 0); this(allowedJoiningTimeMs, null, null, 0);
} }
/** /**
* @param scaleToFit Whether video frames should be scaled to fit when rendering.
* @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer * @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer
* can attempt to seamlessly join an ongoing playback. * can attempt to seamlessly join an ongoing playback.
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be * @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
...@@ -176,23 +169,22 @@ public class LibvpxVideoRenderer extends BaseRenderer { ...@@ -176,23 +169,22 @@ public class LibvpxVideoRenderer extends BaseRenderer {
* @param maxDroppedFramesToNotify The maximum number of frames that can be dropped between * @param maxDroppedFramesToNotify The maximum number of frames that can be dropped between
* invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}. * invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}.
*/ */
public LibvpxVideoRenderer(boolean scaleToFit, long allowedJoiningTimeMs, public LibvpxVideoRenderer(
Handler eventHandler, VideoRendererEventListener eventListener, long allowedJoiningTimeMs,
Handler eventHandler,
VideoRendererEventListener eventListener,
int maxDroppedFramesToNotify) { int maxDroppedFramesToNotify) {
this( this(
scaleToFit,
allowedJoiningTimeMs, allowedJoiningTimeMs,
eventHandler, eventHandler,
eventListener, eventListener,
maxDroppedFramesToNotify, maxDroppedFramesToNotify,
/* drmSessionManager= */ null, /* drmSessionManager= */ null,
/* playClearSamplesWithoutKeys= */ false, /* playClearSamplesWithoutKeys= */ false,
/* disableLoopFilter= */ false, /* disableLoopFilter= */ false);
/* useSurfaceYuvOutput= */ false);
} }
/** /**
* @param scaleToFit Whether video frames should be scaled to fit when rendering.
* @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer * @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer
* can attempt to seamlessly join an ongoing playback. * can attempt to seamlessly join an ongoing playback.
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be * @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
...@@ -208,26 +200,21 @@ public class LibvpxVideoRenderer extends BaseRenderer { ...@@ -208,26 +200,21 @@ public class LibvpxVideoRenderer extends BaseRenderer {
* permitted to play clear regions of encrypted media files before {@code drmSessionManager} * permitted to play clear regions of encrypted media files before {@code drmSessionManager}
* has obtained the keys necessary to decrypt encrypted regions of the media. * has obtained the keys necessary to decrypt encrypted regions of the media.
* @param disableLoopFilter Disable the libvpx in-loop smoothing filter. * @param disableLoopFilter Disable the libvpx in-loop smoothing filter.
* @param useSurfaceYuvOutput Directly output YUV to the Surface via ANativeWindow.
*/ */
public LibvpxVideoRenderer( public LibvpxVideoRenderer(
boolean scaleToFit,
long allowedJoiningTimeMs, long allowedJoiningTimeMs,
Handler eventHandler, Handler eventHandler,
VideoRendererEventListener eventListener, VideoRendererEventListener eventListener,
int maxDroppedFramesToNotify, int maxDroppedFramesToNotify,
DrmSessionManager<ExoMediaCrypto> drmSessionManager, DrmSessionManager<ExoMediaCrypto> drmSessionManager,
boolean playClearSamplesWithoutKeys, boolean playClearSamplesWithoutKeys,
boolean disableLoopFilter, boolean disableLoopFilter) {
boolean useSurfaceYuvOutput) {
super(C.TRACK_TYPE_VIDEO); super(C.TRACK_TYPE_VIDEO);
this.scaleToFit = scaleToFit;
this.disableLoopFilter = disableLoopFilter; this.disableLoopFilter = disableLoopFilter;
this.allowedJoiningTimeMs = allowedJoiningTimeMs; this.allowedJoiningTimeMs = allowedJoiningTimeMs;
this.maxDroppedFramesToNotify = maxDroppedFramesToNotify; this.maxDroppedFramesToNotify = maxDroppedFramesToNotify;
this.drmSessionManager = drmSessionManager; this.drmSessionManager = drmSessionManager;
this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys; this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys;
this.useSurfaceYuvOutput = useSurfaceYuvOutput;
joiningDeadlineMs = C.TIME_UNSET; joiningDeadlineMs = C.TIME_UNSET;
clearReportedVideoSize(); clearReportedVideoSize();
formatHolder = new FormatHolder(); formatHolder = new FormatHolder();
...@@ -586,18 +573,14 @@ public class LibvpxVideoRenderer extends BaseRenderer { ...@@ -586,18 +573,14 @@ public class LibvpxVideoRenderer extends BaseRenderer {
*/ */
protected void renderOutputBuffer(VpxOutputBuffer outputBuffer) throws VpxDecoderException { protected void renderOutputBuffer(VpxOutputBuffer outputBuffer) throws VpxDecoderException {
int bufferMode = outputBuffer.mode; int bufferMode = outputBuffer.mode;
boolean renderRgb = bufferMode == VpxDecoder.OUTPUT_MODE_RGB && surface != null;
boolean renderSurface = bufferMode == VpxDecoder.OUTPUT_MODE_SURFACE_YUV && surface != null; boolean renderSurface = bufferMode == VpxDecoder.OUTPUT_MODE_SURFACE_YUV && surface != null;
boolean renderYuv = bufferMode == VpxDecoder.OUTPUT_MODE_YUV && outputBufferRenderer != null; boolean renderYuv = bufferMode == VpxDecoder.OUTPUT_MODE_YUV && outputBufferRenderer != null;
lastRenderTimeUs = SystemClock.elapsedRealtime() * 1000; lastRenderTimeUs = SystemClock.elapsedRealtime() * 1000;
if (!renderRgb && !renderYuv && !renderSurface) { if (!renderYuv && !renderSurface) {
dropOutputBuffer(outputBuffer); dropOutputBuffer(outputBuffer);
} else { } else {
maybeNotifyVideoSizeChanged(outputBuffer.width, outputBuffer.height); maybeNotifyVideoSizeChanged(outputBuffer.width, outputBuffer.height);
if (renderRgb) { if (renderYuv) {
renderRgbFrame(outputBuffer, scaleToFit);
outputBuffer.release();
} else if (renderYuv) {
outputBufferRenderer.setOutputBuffer(outputBuffer); outputBufferRenderer.setOutputBuffer(outputBuffer);
// The renderer will release the buffer. // The renderer will release the buffer.
} else { // renderSurface } else { // renderSurface
...@@ -675,8 +658,7 @@ public class LibvpxVideoRenderer extends BaseRenderer { ...@@ -675,8 +658,7 @@ public class LibvpxVideoRenderer extends BaseRenderer {
this.surface = surface; this.surface = surface;
this.outputBufferRenderer = outputBufferRenderer; this.outputBufferRenderer = outputBufferRenderer;
if (surface != null) { if (surface != null) {
outputMode = outputMode = VpxDecoder.OUTPUT_MODE_SURFACE_YUV;
useSurfaceYuvOutput ? VpxDecoder.OUTPUT_MODE_SURFACE_YUV : VpxDecoder.OUTPUT_MODE_RGB;
} else { } else {
outputMode = outputMode =
outputBufferRenderer != null ? VpxDecoder.OUTPUT_MODE_YUV : VpxDecoder.OUTPUT_MODE_NONE; outputBufferRenderer != null ? VpxDecoder.OUTPUT_MODE_YUV : VpxDecoder.OUTPUT_MODE_NONE;
...@@ -739,8 +721,7 @@ public class LibvpxVideoRenderer extends BaseRenderer { ...@@ -739,8 +721,7 @@ public class LibvpxVideoRenderer extends BaseRenderer {
NUM_OUTPUT_BUFFERS, NUM_OUTPUT_BUFFERS,
initialInputBufferSize, initialInputBufferSize,
mediaCrypto, mediaCrypto,
disableLoopFilter, disableLoopFilter);
useSurfaceYuvOutput);
decoder.setOutputMode(outputMode); decoder.setOutputMode(outputMode);
TraceUtil.endSection(); TraceUtil.endSection();
long decoderInitializedTimestamp = SystemClock.elapsedRealtime(); long decoderInitializedTimestamp = SystemClock.elapsedRealtime();
...@@ -940,23 +921,6 @@ public class LibvpxVideoRenderer extends BaseRenderer { ...@@ -940,23 +921,6 @@ public class LibvpxVideoRenderer extends BaseRenderer {
return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS; return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS;
} }
private void renderRgbFrame(VpxOutputBuffer outputBuffer, boolean scale) {
if (bitmap == null
|| bitmap.getWidth() != outputBuffer.width
|| bitmap.getHeight() != outputBuffer.height) {
bitmap = Bitmap.createBitmap(outputBuffer.width, outputBuffer.height, Bitmap.Config.RGB_565);
}
bitmap.copyPixelsFromBuffer(outputBuffer.data);
Canvas canvas = surface.lockCanvas(null);
if (scale) {
canvas.scale(
((float) canvas.getWidth()) / outputBuffer.width,
((float) canvas.getHeight()) / outputBuffer.height);
}
canvas.drawBitmap(bitmap, 0, 0, null);
surface.unlockCanvasAndPost(canvas);
}
private void setJoiningDeadlineMs() { private void setJoiningDeadlineMs() {
joiningDeadlineMs = allowedJoiningTimeMs > 0 joiningDeadlineMs = allowedJoiningTimeMs > 0
? (SystemClock.elapsedRealtime() + allowedJoiningTimeMs) : C.TIME_UNSET; ? (SystemClock.elapsedRealtime() + allowedJoiningTimeMs) : C.TIME_UNSET;
......
...@@ -31,8 +31,7 @@ import java.nio.ByteBuffer; ...@@ -31,8 +31,7 @@ import java.nio.ByteBuffer;
public static final int OUTPUT_MODE_NONE = -1; public static final int OUTPUT_MODE_NONE = -1;
public static final int OUTPUT_MODE_YUV = 0; public static final int OUTPUT_MODE_YUV = 0;
public static final int OUTPUT_MODE_RGB = 1; public static final int OUTPUT_MODE_SURFACE_YUV = 1;
public static final int OUTPUT_MODE_SURFACE_YUV = 2;
private static final int NO_ERROR = 0; private static final int NO_ERROR = 0;
private static final int DECODE_ERROR = 1; private static final int DECODE_ERROR = 1;
...@@ -52,7 +51,6 @@ import java.nio.ByteBuffer; ...@@ -52,7 +51,6 @@ import java.nio.ByteBuffer;
* @param exoMediaCrypto The {@link ExoMediaCrypto} object required for decoding encrypted * @param exoMediaCrypto The {@link ExoMediaCrypto} object required for decoding encrypted
* content. Maybe null and can be ignored if decoder does not handle encrypted content. * content. Maybe null and can be ignored if decoder does not handle encrypted content.
* @param disableLoopFilter Disable the libvpx in-loop smoothing filter. * @param disableLoopFilter Disable the libvpx in-loop smoothing filter.
* @param enableSurfaceYuvOutputMode Whether OUTPUT_MODE_SURFACE_YUV is allowed.
* @throws VpxDecoderException Thrown if an exception occurs when initializing the decoder. * @throws VpxDecoderException Thrown if an exception occurs when initializing the decoder.
*/ */
public VpxDecoder( public VpxDecoder(
...@@ -60,8 +58,7 @@ import java.nio.ByteBuffer; ...@@ -60,8 +58,7 @@ import java.nio.ByteBuffer;
int numOutputBuffers, int numOutputBuffers,
int initialInputBufferSize, int initialInputBufferSize,
ExoMediaCrypto exoMediaCrypto, ExoMediaCrypto exoMediaCrypto,
boolean disableLoopFilter, boolean disableLoopFilter)
boolean enableSurfaceYuvOutputMode)
throws VpxDecoderException { throws VpxDecoderException {
super(new VpxInputBuffer[numInputBuffers], new VpxOutputBuffer[numOutputBuffers]); super(new VpxInputBuffer[numInputBuffers], new VpxOutputBuffer[numOutputBuffers]);
if (!VpxLibrary.isAvailable()) { if (!VpxLibrary.isAvailable()) {
...@@ -71,7 +68,7 @@ import java.nio.ByteBuffer; ...@@ -71,7 +68,7 @@ import java.nio.ByteBuffer;
if (exoMediaCrypto != null && !VpxLibrary.vpxIsSecureDecodeSupported()) { if (exoMediaCrypto != null && !VpxLibrary.vpxIsSecureDecodeSupported()) {
throw new VpxDecoderException("Vpx decoder does not support secure decode."); throw new VpxDecoderException("Vpx decoder does not support secure decode.");
} }
vpxDecContext = vpxInit(disableLoopFilter, enableSurfaceYuvOutputMode); vpxDecContext = vpxInit(disableLoopFilter, true);
if (vpxDecContext == 0) { if (vpxDecContext == 0) {
throw new VpxDecoderException("Failed to initialize decoder"); throw new VpxDecoderException("Failed to initialize decoder");
} }
...@@ -86,8 +83,8 @@ import java.nio.ByteBuffer; ...@@ -86,8 +83,8 @@ import java.nio.ByteBuffer;
/** /**
* Sets the output mode for frames rendered by the decoder. * Sets the output mode for frames rendered by the decoder.
* *
* @param outputMode The output mode. One of {@link #OUTPUT_MODE_NONE}, {@link #OUTPUT_MODE_RGB} * @param outputMode The output mode. One of {@link #OUTPUT_MODE_NONE} and {@link
* and {@link #OUTPUT_MODE_YUV}. * #OUTPUT_MODE_YUV}.
*/ */
public void setOutputMode(int outputMode) { public void setOutputMode(int outputMode) {
this.outputMode = outputMode; this.outputMode = outputMode;
......
...@@ -60,8 +60,8 @@ public final class VpxOutputBuffer extends OutputBuffer { ...@@ -60,8 +60,8 @@ public final class VpxOutputBuffer extends OutputBuffer {
* Initializes the buffer. * Initializes the buffer.
* *
* @param timeUs The presentation timestamp for the buffer, in microseconds. * @param timeUs The presentation timestamp for the buffer, in microseconds.
* @param mode The output mode. One of {@link VpxDecoder#OUTPUT_MODE_NONE}, * @param mode The output mode. One of {@link VpxDecoder#OUTPUT_MODE_NONE} and {@link
* {@link VpxDecoder#OUTPUT_MODE_RGB} and {@link VpxDecoder#OUTPUT_MODE_YUV}. * VpxDecoder#OUTPUT_MODE_YUV}.
*/ */
public void init(long timeUs, int mode) { public void init(long timeUs, int mode) {
this.timeUs = timeUs; this.timeUs = timeUs;
...@@ -69,27 +69,11 @@ public final class VpxOutputBuffer extends OutputBuffer { ...@@ -69,27 +69,11 @@ public final class VpxOutputBuffer extends OutputBuffer {
} }
/** /**
* Resizes the buffer based on the given dimensions. Called via JNI after decoding completes.
* @return Whether the buffer was resized successfully.
*/
public boolean initForRgbFrame(int width, int height) {
this.width = width;
this.height = height;
this.yuvPlanes = null;
if (!isSafeToMultiply(width, height) || !isSafeToMultiply(width * height, 2)) {
return false;
}
int minimumRgbSize = width * height * 2;
initData(minimumRgbSize);
return true;
}
/**
* Resizes the buffer based on the given stride. Called via JNI after decoding completes. * Resizes the buffer based on the given stride. Called via JNI after decoding completes.
*
* @return Whether the buffer was resized successfully. * @return Whether the buffer was resized successfully.
*/ */
public boolean initForYuvFrame(int width, int height, int yStride, int uvStride, public boolean initForYuvFrame(int width, int height, int yStride, int uvStride, int colorspace) {
int colorspace) {
this.width = width; this.width = width;
this.height = height; this.height = height;
this.colorspace = colorspace; this.colorspace = colorspace;
......
...@@ -17,12 +17,6 @@ ...@@ -17,12 +17,6 @@
WORKING_DIR := $(call my-dir) WORKING_DIR := $(call my-dir)
include $(CLEAR_VARS) include $(CLEAR_VARS)
LIBVPX_ROOT := $(WORKING_DIR)/libvpx LIBVPX_ROOT := $(WORKING_DIR)/libvpx
LIBYUV_ROOT := $(WORKING_DIR)/libyuv
# build libyuv_static.a
LOCAL_PATH := $(WORKING_DIR)
LIBYUV_DISABLE_JPEG := "yes"
include $(LIBYUV_ROOT)/Android.mk
# build libvpx.so # build libvpx.so
LOCAL_PATH := $(WORKING_DIR) LOCAL_PATH := $(WORKING_DIR)
...@@ -37,7 +31,7 @@ LOCAL_CPP_EXTENSION := .cc ...@@ -37,7 +31,7 @@ LOCAL_CPP_EXTENSION := .cc
LOCAL_SRC_FILES := vpx_jni.cc LOCAL_SRC_FILES := vpx_jni.cc
LOCAL_LDLIBS := -llog -lz -lm -landroid LOCAL_LDLIBS := -llog -lz -lm -landroid
LOCAL_SHARED_LIBRARIES := libvpx LOCAL_SHARED_LIBRARIES := libvpx
LOCAL_STATIC_LIBRARIES := libyuv_static cpufeatures LOCAL_STATIC_LIBRARIES := cpufeatures
include $(BUILD_SHARED_LIBRARY) include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/cpufeatures) $(call import-module,android/cpufeatures)
...@@ -30,8 +30,6 @@ ...@@ -30,8 +30,6 @@
#include <cstring> #include <cstring>
#include <new> #include <new>
#include "libyuv.h" // NOLINT
#define VPX_CODEC_DISABLE_COMPAT 1 #define VPX_CODEC_DISABLE_COMPAT 1
#include "vpx/vpx_decoder.h" #include "vpx/vpx_decoder.h"
#include "vpx/vp8dx.h" #include "vpx/vp8dx.h"
...@@ -61,7 +59,6 @@ ...@@ -61,7 +59,6 @@
(JNIEnv* env, jobject thiz, ##__VA_ARGS__)\ (JNIEnv* env, jobject thiz, ##__VA_ARGS__)\
// JNI references for VpxOutputBuffer class. // JNI references for VpxOutputBuffer class.
static jmethodID initForRgbFrame;
static jmethodID initForYuvFrame; static jmethodID initForYuvFrame;
static jfieldID dataField; static jfieldID dataField;
static jfieldID outputModeField; static jfieldID outputModeField;
...@@ -393,11 +390,7 @@ class JniBufferManager { ...@@ -393,11 +390,7 @@ class JniBufferManager {
}; };
struct JniCtx { struct JniCtx {
JniCtx(bool enableBufferManager) { JniCtx() { buffer_manager = new JniBufferManager(); }
if (enableBufferManager) {
buffer_manager = new JniBufferManager();
}
}
~JniCtx() { ~JniCtx() {
if (native_window) { if (native_window) {
...@@ -440,9 +433,8 @@ int vpx_release_frame_buffer(void* priv, vpx_codec_frame_buffer_t* fb) { ...@@ -440,9 +433,8 @@ int vpx_release_frame_buffer(void* priv, vpx_codec_frame_buffer_t* fb) {
return buffer_manager->release(*(int*)fb->priv); return buffer_manager->release(*(int*)fb->priv);
} }
DECODER_FUNC(jlong, vpxInit, jboolean disableLoopFilter, jlong vpxInit(JNIEnv* env, jboolean disableLoopFilter) {
jboolean enableBufferManager) { JniCtx* context = new JniCtx();
JniCtx* context = new JniCtx(enableBufferManager);
context->decoder = new vpx_codec_ctx_t(); context->decoder = new vpx_codec_ctx_t();
vpx_codec_dec_cfg_t cfg = {0, 0, 0}; vpx_codec_dec_cfg_t cfg = {0, 0, 0};
cfg.threads = android_getCpuCount(); cfg.threads = android_getCpuCount();
...@@ -469,14 +461,12 @@ DECODER_FUNC(jlong, vpxInit, jboolean disableLoopFilter, ...@@ -469,14 +461,12 @@ DECODER_FUNC(jlong, vpxInit, jboolean disableLoopFilter,
} }
#endif #endif
} }
if (enableBufferManager) { err = vpx_codec_set_frame_buffer_functions(
err = vpx_codec_set_frame_buffer_functions( context->decoder, vpx_get_frame_buffer, vpx_release_frame_buffer,
context->decoder, vpx_get_frame_buffer, vpx_release_frame_buffer, context->buffer_manager);
context->buffer_manager); if (err) {
if (err) { LOGE("ERROR: Failed to set libvpx frame buffer functions, error = %d.",
LOGE("ERROR: Failed to set libvpx frame buffer functions, error = %d.", err);
err);
}
} }
// Populate JNI References. // Populate JNI References.
...@@ -484,8 +474,6 @@ DECODER_FUNC(jlong, vpxInit, jboolean disableLoopFilter, ...@@ -484,8 +474,6 @@ DECODER_FUNC(jlong, vpxInit, jboolean disableLoopFilter,
"com/google/android/exoplayer2/ext/vp9/VpxOutputBuffer"); "com/google/android/exoplayer2/ext/vp9/VpxOutputBuffer");
initForYuvFrame = env->GetMethodID(outputBufferClass, "initForYuvFrame", initForYuvFrame = env->GetMethodID(outputBufferClass, "initForYuvFrame",
"(IIIII)Z"); "(IIIII)Z");
initForRgbFrame = env->GetMethodID(outputBufferClass, "initForRgbFrame",
"(II)Z");
dataField = env->GetFieldID(outputBufferClass, "data", dataField = env->GetFieldID(outputBufferClass, "data",
"Ljava/nio/ByteBuffer;"); "Ljava/nio/ByteBuffer;");
outputModeField = env->GetFieldID(outputBufferClass, "mode", "I"); outputModeField = env->GetFieldID(outputBufferClass, "mode", "I");
...@@ -494,6 +482,15 @@ DECODER_FUNC(jlong, vpxInit, jboolean disableLoopFilter, ...@@ -494,6 +482,15 @@ DECODER_FUNC(jlong, vpxInit, jboolean disableLoopFilter,
return reinterpret_cast<intptr_t>(context); return reinterpret_cast<intptr_t>(context);
} }
DECODER_FUNC(jlong, vpxInit, jboolean disableLoopFilter,
jboolean enableBufferManager) {
return vpxInit(env, disableLoopFilter);
}
DECODER_FUNC(jlong, vpxInitilization, jboolean disableLoopFilter) {
return vpxInit(env, disableLoopFilter);
}
DECODER_FUNC(jlong, vpxDecode, jlong jContext, jobject encoded, jint len) { DECODER_FUNC(jlong, vpxDecode, jlong jContext, jobject encoded, jint len) {
JniCtx* const context = reinterpret_cast<JniCtx*>(jContext); JniCtx* const context = reinterpret_cast<JniCtx*>(jContext);
const uint8_t* const buffer = const uint8_t* const buffer =
...@@ -537,28 +534,10 @@ DECODER_FUNC(jint, vpxGetFrame, jlong jContext, jobject jOutputBuffer) { ...@@ -537,28 +534,10 @@ DECODER_FUNC(jint, vpxGetFrame, jlong jContext, jobject jOutputBuffer) {
} }
const int kOutputModeYuv = 0; const int kOutputModeYuv = 0;
const int kOutputModeRgb = 1; const int kOutputModeSurfaceYuv = 1;
const int kOutputModeSurfaceYuv = 2;
int outputMode = env->GetIntField(jOutputBuffer, outputModeField); int outputMode = env->GetIntField(jOutputBuffer, outputModeField);
if (outputMode == kOutputModeRgb) { if (outputMode == kOutputModeYuv) {
// resize buffer if required.
jboolean initResult = env->CallBooleanMethod(jOutputBuffer, initForRgbFrame,
img->d_w, img->d_h);
if (env->ExceptionCheck() || !initResult) {
return -1;
}
// get pointer to the data buffer.
const jobject dataObject = env->GetObjectField(jOutputBuffer, dataField);
uint8_t* const dst =
reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(dataObject));
libyuv::I420ToRGB565(img->planes[VPX_PLANE_Y], img->stride[VPX_PLANE_Y],
img->planes[VPX_PLANE_U], img->stride[VPX_PLANE_U],
img->planes[VPX_PLANE_V], img->stride[VPX_PLANE_V],
dst, img->d_w * 2, img->d_w, img->d_h);
} else if (outputMode == kOutputModeYuv) {
const int kColorspaceUnknown = 0; const int kColorspaceUnknown = 0;
const int kColorspaceBT601 = 1; const int kColorspaceBT601 = 1;
const int kColorspaceBT709 = 2; const int kColorspaceBT709 = 2;
...@@ -616,9 +595,6 @@ DECODER_FUNC(jint, vpxGetFrame, jlong jContext, jobject jOutputBuffer) { ...@@ -616,9 +595,6 @@ DECODER_FUNC(jint, vpxGetFrame, jlong jContext, jobject jOutputBuffer) {
} }
} else if (outputMode == kOutputModeSurfaceYuv && } else if (outputMode == kOutputModeSurfaceYuv &&
img->fmt != VPX_IMG_FMT_I42016) { img->fmt != VPX_IMG_FMT_I42016) {
if (!context->buffer_manager) {
return -1; // enableBufferManager was not set in vpxInit.
}
int id = *(int*)img->fb_priv; int id = *(int*)img->fb_priv;
context->buffer_manager->add_ref(id); context->buffer_manager->add_ref(id);
JniFrameBuffer* jfb = context->buffer_manager->get_buffer(id); JniFrameBuffer* jfb = context->buffer_manager->get_buffer(id);
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# Constructors accessed via reflection in DefaultRenderersFactory # Constructors accessed via reflection in DefaultRenderersFactory
-dontnote com.google.android.exoplayer2.ext.vp9.LibvpxVideoRenderer -dontnote com.google.android.exoplayer2.ext.vp9.LibvpxVideoRenderer
-keepclassmembers class com.google.android.exoplayer2.ext.vp9.LibvpxVideoRenderer { -keepclassmembers class com.google.android.exoplayer2.ext.vp9.LibvpxVideoRenderer {
<init>(boolean, long, android.os.Handler, com.google.android.exoplayer2.video.VideoRendererEventListener, int); <init>(long, android.os.Handler, com.google.android.exoplayer2.video.VideoRendererEventListener, int);
} }
-dontnote com.google.android.exoplayer2.ext.opus.LibopusAudioRenderer -dontnote com.google.android.exoplayer2.ext.opus.LibopusAudioRenderer
-keepclassmembers class com.google.android.exoplayer2.ext.opus.LibopusAudioRenderer { -keepclassmembers class com.google.android.exoplayer2.ext.opus.LibopusAudioRenderer {
......
...@@ -233,7 +233,6 @@ public class DefaultRenderersFactory implements RenderersFactory { ...@@ -233,7 +233,6 @@ public class DefaultRenderersFactory implements RenderersFactory {
Class<?> clazz = Class.forName("com.google.android.exoplayer2.ext.vp9.LibvpxVideoRenderer"); Class<?> clazz = Class.forName("com.google.android.exoplayer2.ext.vp9.LibvpxVideoRenderer");
Constructor<?> constructor = Constructor<?> constructor =
clazz.getConstructor( clazz.getConstructor(
boolean.class,
long.class, long.class,
android.os.Handler.class, android.os.Handler.class,
com.google.android.exoplayer2.video.VideoRendererEventListener.class, com.google.android.exoplayer2.video.VideoRendererEventListener.class,
...@@ -242,7 +241,6 @@ public class DefaultRenderersFactory implements RenderersFactory { ...@@ -242,7 +241,6 @@ public class DefaultRenderersFactory implements RenderersFactory {
Renderer renderer = Renderer renderer =
(Renderer) (Renderer)
constructor.newInstance( constructor.newInstance(
true,
allowedVideoJoiningTimeMs, allowedVideoJoiningTimeMs,
eventHandler, eventHandler,
eventListener, eventListener,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment