diff --git a/.gitignore b/.gitignore
index ada82881..9aa4ada3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,6 +30,7 @@ Thumbs.db
#.idea/workspace.xml - remove # and delete .idea if it better suit your needs.
.gradle
build/
+app/app.iml
# Compiled JNI libraries folder
**/jniLibs
diff --git a/.gitmodules b/.gitmodules
index d1fb2074..20ae0be9 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,3 @@
-[submodule "app/src/main/jni/jnienet/enet"]
- path = app/src/main/jni/jnienet/enet
- url = https://github.com/cgutman/enet.git
\ No newline at end of file
+[submodule "moonlight-common"]
+ path = moonlight-common
+ url = https://github.com/moonlight-stream/moonlight-common.git
diff --git a/app/app.iml b/app/app.iml
deleted file mode 100644
index d2610c66..00000000
--- a/app/app.iml
+++ /dev/null
@@ -1,153 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- generateNonRootDebugSources
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 1a3c0ee2..25155f88 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -5,14 +5,14 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion 25
- buildToolsVersion '25.0.2'
+ buildToolsVersion '25.0.3'
defaultConfig {
minSdkVersion 16
targetSdkVersion 25
- versionName "4.8.5"
- versionCode = 117
+ versionName "5.0.0"
+ versionCode = 121
}
productFlavors {
@@ -38,17 +38,10 @@ android {
buildTypes {
release {
minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
+ proguardFiles getDefaultProguardFile('proguard-android.txt')
}
}
- // These lines are required to avoid dexing issues with the BouncyCastle library
- // bundled with limelight-common.jar
- packagingOptions {
- exclude 'META-INF/BCKEY.SF'
- exclude 'META-INF/BCKEY.DSA'
- }
-
externalNativeBuild {
ndkBuild {
path "src/main/jni/Android.mk"
@@ -59,10 +52,6 @@ android {
dependencies {
compile 'org.bouncycastle:bcprov-jdk15on:1.52'
compile 'org.bouncycastle:bcpkix-jdk15on:1.52'
- compile 'com.squareup.okhttp:okhttp:2.4.0'
- compile 'com.squareup.okio:okio:1.5.0'
- compile files('libs/jmdns-3.4.2.jar')
- compile files('libs/limelight-common.jar')
- compile files('libs/tinyrtsp.jar')
+ compile project(':moonlight-common')
compile files('libs/jcodec-0.1.9-patched.jar')
}
diff --git a/app/libs/jmdns-3.4.2.jar b/app/libs/jmdns-3.4.2.jar
deleted file mode 100644
index 3112053f..00000000
Binary files a/app/libs/jmdns-3.4.2.jar and /dev/null differ
diff --git a/app/libs/limelight-common.jar b/app/libs/limelight-common.jar
deleted file mode 100644
index a4ae5f99..00000000
Binary files a/app/libs/limelight-common.jar and /dev/null differ
diff --git a/app/libs/tinyrtsp.jar b/app/libs/tinyrtsp.jar
deleted file mode 100644
index 73375ae2..00000000
Binary files a/app/libs/tinyrtsp.jar and /dev/null differ
diff --git a/app/src/main/java/com/limelight/AppView.java b/app/src/main/java/com/limelight/AppView.java
index 989a6e5d..5624a014 100644
--- a/app/src/main/java/com/limelight/AppView.java
+++ b/app/src/main/java/com/limelight/AppView.java
@@ -81,6 +81,10 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
// Get the computer object
computer = managerBinder.getComputer(UUID.fromString(uuidString));
+ if (computer == null) {
+ finish();
+ return;
+ }
try {
appGridAdapter = new AppGridAdapter(AppView.this,
diff --git a/app/src/main/java/com/limelight/Game.java b/app/src/main/java/com/limelight/Game.java
index 13787966..8984c1c7 100644
--- a/app/src/main/java/com/limelight/Game.java
+++ b/app/src/main/java/com/limelight/Game.java
@@ -10,16 +10,15 @@ import com.limelight.binding.input.TouchContext;
import com.limelight.binding.input.driver.UsbDriverService;
import com.limelight.binding.input.evdev.EvdevListener;
import com.limelight.binding.input.virtual_controller.VirtualController;
-import com.limelight.binding.video.EnhancedDecoderRenderer;
import com.limelight.binding.video.MediaCodecDecoderRenderer;
import com.limelight.binding.video.MediaCodecHelper;
import com.limelight.nvstream.NvConnection;
import com.limelight.nvstream.NvConnectionListener;
import com.limelight.nvstream.StreamConfiguration;
-import com.limelight.nvstream.av.video.VideoDecoderRenderer;
import com.limelight.nvstream.http.NvApp;
import com.limelight.nvstream.input.KeyboardPacket;
import com.limelight.nvstream.input.MouseButtonPacket;
+import com.limelight.nvstream.jni.MoonBridge;
import com.limelight.preferences.PreferenceConfiguration;
import com.limelight.ui.GameGestures;
import com.limelight.ui.StreamView;
@@ -35,7 +34,6 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
-import android.content.res.Configuration;
import android.graphics.Point;
import android.hardware.input.InputManager;
import android.media.AudioManager;
@@ -61,8 +59,6 @@ import android.widget.FrameLayout;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
-import java.util.Locale;
-
public class Game extends Activity implements SurfaceHolder.Callback,
OnGenericMotionListener, OnTouchListener, NvConnectionListener, EvdevListener,
@@ -83,7 +79,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
private ControllerHandler controllerHandler;
private VirtualController virtualController;
- private KeyboardTranslator keybTranslator;
private PreferenceConfiguration prefConfig;
@@ -101,12 +96,10 @@ public class Game extends Activity implements SurfaceHolder.Callback,
private ShortcutHelper shortcutHelper;
- private EnhancedDecoderRenderer decoderRenderer;
+ private MediaCodecDecoderRenderer decoderRenderer;
private WifiManager.WifiLock wifiLock;
- private int drFlags = 0;
-
private boolean connectedToUsbDriverService = false;
private ServiceConnection usbDriverServiceConnection = new ServiceConnection() {
@Override
@@ -173,10 +166,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
// Read the stream preferences
prefConfig = PreferenceConfiguration.readPreferences(this);
- if (prefConfig.stretchVideo) {
- drFlags |= VideoDecoderRenderer.FLAG_FILL_SCREEN;
- }
-
// Listen for events on the game surface
streamView = (StreamView) findViewById(R.id.surfaceView);
streamView.setOnGenericMotionListener(this);
@@ -236,20 +225,17 @@ public class Game extends Activity implements SurfaceHolder.Callback,
.setApp(new NvApp(appName, appId))
.setBitrate(prefConfig.bitrate * 1000)
.setEnableSops(prefConfig.enableSops)
- .enableAdaptiveResolution((decoderRenderer.getCapabilities() &
- VideoDecoderRenderer.CAPABILITY_ADAPTIVE_RESOLUTION) != 0)
.enableLocalAudioPlayback(prefConfig.playHostAudio)
.setMaxPacketSize(remote ? 1024 : 1292)
.setRemote(remote)
.setHevcSupported(decoderRenderer.isHevcSupported())
.setAudioConfiguration(prefConfig.enable51Surround ?
- StreamConfiguration.AUDIO_CONFIGURATION_5_1 :
- StreamConfiguration.AUDIO_CONFIGURATION_STEREO)
+ MoonBridge.AUDIO_CONFIGURATION_51_SURROUND :
+ MoonBridge.AUDIO_CONFIGURATION_STEREO)
.build();
// Initialize the connection
- conn = new NvConnection(host, uniqueId, Game.this, config, PlatformBinding.getCryptoProvider(this));
- keybTranslator = new KeyboardTranslator(conn);
+ conn = new NvConnection(host, uniqueId, config, PlatformBinding.getCryptoProvider(this));
controllerHandler = new ControllerHandler(this, conn, this, prefConfig.multiController, prefConfig.deadzonePercentage);
InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE);
@@ -419,11 +405,8 @@ public class Game extends Activity implements SurfaceHolder.Callback,
}
@Override
- protected void onStop() {
- super.onStop();
-
- SpinnerDialog.closeDialogs(this);
- Dialog.closeDialogs();
+ protected void onDestroy() {
+ super.onDestroy();
if (controllerHandler != null) {
InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE);
@@ -438,7 +421,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
}
if (conn != null) {
- VideoDecoderRenderer.VideoFormat videoFormat = conn.getActiveVideoFormat();
+ int videoFormat = decoderRenderer.getActiveVideoFormat();
displayedFailureDialog = true;
stopConnection();
@@ -457,11 +440,11 @@ public class Game extends Activity implements SurfaceHolder.Callback,
}
// Add the video codec to the post-stream toast
- if (message != null && videoFormat != VideoDecoderRenderer.VideoFormat.Unknown) {
- if (videoFormat == VideoDecoderRenderer.VideoFormat.H265) {
+ if (message != null) {
+ if (videoFormat == MoonBridge.VIDEO_FORMAT_H265) {
message += " [H.265]";
}
- else {
+ else if (videoFormat == MoonBridge.VIDEO_FORMAT_H264) {
message += " [H.264]";
}
}
@@ -470,6 +453,14 @@ public class Game extends Activity implements SurfaceHolder.Callback,
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
}
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+
+ SpinnerDialog.closeDialogs(this);
+ Dialog.closeDialogs();
finish();
}
@@ -589,7 +580,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
if (!handled) {
// Try the keyboard handler
- short translated = keybTranslator.translate(event.getKeyCode());
+ short translated = KeyboardTranslator.translate(event.getKeyCode());
if (translated == 0) {
return super.onKeyDown(keyCode, event);
}
@@ -604,8 +595,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
return super.onKeyDown(keyCode, event);
}
- keybTranslator.sendKeyDown(translated,
- getModifierState(event));
+ conn.sendKeyboardInput(translated, KeyboardPacket.KEY_DOWN, getModifierState());
}
return true;
@@ -632,7 +622,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
if (!handled) {
// Try the keyboard handler
- short translated = keybTranslator.translate(event.getKeyCode());
+ short translated = KeyboardTranslator.translate(event.getKeyCode());
if (translated == 0) {
return super.onKeyUp(keyCode, event);
}
@@ -646,8 +636,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
return super.onKeyUp(keyCode, event);
}
- keybTranslator.sendKeyUp(translated,
- getModifierState(event));
+ conn.sendKeyboardInput(translated, KeyboardPacket.KEY_UP, getModifierState(event));
}
return true;
@@ -889,14 +878,14 @@ public class Game extends Activity implements SurfaceHolder.Callback,
}
@Override
- public void stageStarting(Stage stage) {
+ public void stageStarting(String stage) {
if (spinner != null) {
- spinner.setMessage(getResources().getString(R.string.conn_starting)+" "+stage.getName());
+ spinner.setMessage(getResources().getString(R.string.conn_starting)+" "+stage);
}
}
@Override
- public void stageComplete(Stage stage) {
+ public void stageComplete(String stage) {
}
private void stopConnection() {
@@ -913,7 +902,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
}
@Override
- public void stageFailed(Stage stage) {
+ public void stageFailed(String stage, long errorCode) {
if (spinner != null) {
spinner.dismiss();
spinner = null;
@@ -921,17 +910,19 @@ public class Game extends Activity implements SurfaceHolder.Callback,
if (!displayedFailureDialog) {
displayedFailureDialog = true;
+ LimeLog.severe(stage+" failed: "+errorCode);
+
stopConnection();
Dialog.displayDialog(this, getResources().getString(R.string.conn_error_title),
- getResources().getString(R.string.conn_error_msg)+" "+stage.getName(), true);
+ getResources().getString(R.string.conn_error_msg)+" "+stage, true);
}
}
@Override
- public void connectionTerminated(Exception e) {
+ public void connectionTerminated(long errorCode) {
if (!displayedFailureDialog) {
displayedFailureDialog = true;
- e.printStackTrace();
+ LimeLog.severe("Connection terminated: "+errorCode);
stopConnection();
Dialog.displayDialog(this, getResources().getString(R.string.conn_terminated_title),
@@ -993,8 +984,8 @@ public class Game extends Activity implements SurfaceHolder.Callback,
if (!connected && !connecting) {
connecting = true;
- conn.start(PlatformBinding.getDeviceName(), holder, drFlags,
- PlatformBinding.getAudioRenderer(), decoderRenderer);
+ decoderRenderer.setRenderTarget(holder);
+ conn.start(PlatformBinding.getAudioRenderer(), decoderRenderer, Game.this);
}
}
@@ -1053,17 +1044,17 @@ public class Game extends Activity implements SurfaceHolder.Callback,
@Override
public void keyboardEvent(boolean buttonDown, short keyCode) {
- short keyMap = keybTranslator.translate(keyCode);
+ short keyMap = KeyboardTranslator.translate(keyCode);
if (keyMap != 0) {
if (handleSpecialKeys(keyMap, buttonDown)) {
return;
}
if (buttonDown) {
- keybTranslator.sendKeyDown(keyMap, getModifierState());
+ conn.sendKeyboardInput(keyMap, KeyboardPacket.KEY_DOWN, getModifierState());
}
else {
- keybTranslator.sendKeyUp(keyMap, getModifierState());
+ conn.sendKeyboardInput(keyMap, KeyboardPacket.KEY_UP, getModifierState());
}
}
}
diff --git a/app/src/main/java/com/limelight/binding/audio/AndroidAudioRenderer.java b/app/src/main/java/com/limelight/binding/audio/AndroidAudioRenderer.java
index 3b5621e2..bc297ebe 100644
--- a/app/src/main/java/com/limelight/binding/audio/AndroidAudioRenderer.java
+++ b/app/src/main/java/com/limelight/binding/audio/AndroidAudioRenderer.java
@@ -6,34 +6,31 @@ import android.media.AudioTrack;
import com.limelight.LimeLog;
import com.limelight.nvstream.av.audio.AudioRenderer;
+import com.limelight.nvstream.jni.MoonBridge;
public class AndroidAudioRenderer implements AudioRenderer {
private AudioTrack track;
@Override
- public boolean streamInitialized(int channelCount, int channelMask, int samplesPerFrame, int sampleRate) {
+ public int setup(int audioConfiguration) {
int channelConfig;
int bufferSize;
- int bytesPerFrame = (samplesPerFrame * 2);
+ int bytesPerFrame;
- switch (channelCount)
+ switch (audioConfiguration)
{
- case 1:
- channelConfig = AudioFormat.CHANNEL_OUT_MONO;
- break;
- case 2:
- channelConfig = AudioFormat.CHANNEL_OUT_STEREO;
- break;
- case 4:
- channelConfig = AudioFormat.CHANNEL_OUT_QUAD;
- break;
- case 6:
- channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;
- break;
- default:
- LimeLog.severe("Decoder returned unhandled channel count");
- return false;
+ case MoonBridge.AUDIO_CONFIGURATION_STEREO:
+ channelConfig = AudioFormat.CHANNEL_OUT_STEREO;
+ bytesPerFrame = 2 * 240 * 2;
+ break;
+ case MoonBridge.AUDIO_CONFIGURATION_51_SURROUND:
+ channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;
+ bytesPerFrame = 6 * 240 * 2;
+ break;
+ default:
+ LimeLog.severe("Decoder returned unhandled channel count");
+ return -1;
}
// We're not supposed to request less than the minimum
@@ -46,7 +43,7 @@ public class AndroidAudioRenderer implements AudioRenderer {
bufferSize = bytesPerFrame * 2;
track = new AudioTrack(AudioManager.STREAM_MUSIC,
- sampleRate,
+ 48000,
channelConfig,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize,
@@ -61,7 +58,7 @@ public class AndroidAudioRenderer implements AudioRenderer {
} catch (Exception ignored) {}
// Now try the larger buffer size
- bufferSize = Math.max(AudioTrack.getMinBufferSize(sampleRate,
+ bufferSize = Math.max(AudioTrack.getMinBufferSize(48000,
channelConfig,
AudioFormat.ENCODING_PCM_16BIT),
bytesPerFrame * 2);
@@ -70,7 +67,7 @@ public class AndroidAudioRenderer implements AudioRenderer {
bufferSize = (((bufferSize + (bytesPerFrame - 1)) / bytesPerFrame) * bytesPerFrame);
track = new AudioTrack(AudioManager.STREAM_MUSIC,
- sampleRate,
+ 48000,
channelConfig,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize,
@@ -79,24 +76,26 @@ public class AndroidAudioRenderer implements AudioRenderer {
}
LimeLog.info("Audio track buffer size: "+bufferSize);
-
- return true;
- }
-
- @Override
- public void playDecodedAudio(byte[] audioData, int offset, int length) {
- track.write(audioData, offset, length);
- }
-
- @Override
- public void streamClosing() {
- if (track != null) {
- track.release();
- }
- }
-
- @Override
- public int getCapabilities() {
return 0;
}
+
+ @Override
+ public void playDecodedAudio(byte[] audioData) {
+ track.write(audioData, 0, audioData.length);
+ }
+
+ @Override
+ public void start() {}
+
+ @Override
+ public void stop() {
+ // Immediately drop all pending data
+ track.pause();
+ track.flush();
+ }
+
+ @Override
+ public void cleanup() {
+ track.release();
+ }
}
diff --git a/app/src/main/java/com/limelight/binding/input/ControllerHandler.java b/app/src/main/java/com/limelight/binding/input/ControllerHandler.java
index d2479ad4..ed1f7ec2 100644
--- a/app/src/main/java/com/limelight/binding/input/ControllerHandler.java
+++ b/app/src/main/java/com/limelight/binding/input/ControllerHandler.java
@@ -1120,6 +1120,9 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
float rightStickX, float rightStickY,
float leftTrigger, float rightTrigger) {
UsbDeviceContext context = usbDeviceContexts.get(controllerId);
+ if (context == null) {
+ return;
+ }
Vector2d leftStickVector = populateCachedVector(leftStickX, leftStickY);
diff --git a/app/src/main/java/com/limelight/binding/input/KeyboardTranslator.java b/app/src/main/java/com/limelight/binding/input/KeyboardTranslator.java
index f087215f..839cb500 100644
--- a/app/src/main/java/com/limelight/binding/input/KeyboardTranslator.java
+++ b/app/src/main/java/com/limelight/binding/input/KeyboardTranslator.java
@@ -3,14 +3,13 @@ package com.limelight.binding.input;
import android.view.KeyEvent;
import com.limelight.nvstream.NvConnection;
-import com.limelight.nvstream.input.KeycodeTranslator;
/**
* Class to translate a Android key code into the codes GFE is expecting
* @author Diego Waxemberg
* @author Cameron Gutman
*/
-public class KeyboardTranslator extends KeycodeTranslator {
+public class KeyboardTranslator {
/**
* GFE's prefix for every key code
@@ -59,21 +58,12 @@ public class KeyboardTranslator extends KeycodeTranslator {
public static final int VK_QUOTE = 222;
public static final int VK_PAUSE = 19;
- /**
- * Constructs a new translator for the specified connection
- * @param conn the connection to which the translated codes are sent
- */
- public KeyboardTranslator(NvConnection conn) {
- super(conn);
- }
-
/**
* Translates the given keycode and returns the GFE keycode
* @param keycode the code to be translated
* @return a GFE keycode for the given keycode
*/
- @Override
- public short translate(int keycode) {
+ public static short translate(int keycode) {
int translated;
/* There seems to be no clean mapping between Android key codes
diff --git a/app/src/main/java/com/limelight/binding/input/evdev/EvdevCaptureProvider.java b/app/src/main/java/com/limelight/binding/input/evdev/EvdevCaptureProvider.java
index 4a1e02b3..8b60a2d1 100644
--- a/app/src/main/java/com/limelight/binding/input/evdev/EvdevCaptureProvider.java
+++ b/app/src/main/java/com/limelight/binding/input/evdev/EvdevCaptureProvider.java
@@ -2,6 +2,7 @@ package com.limelight.binding.input.evdev;
import android.app.Activity;
import android.os.Build;
+import android.os.Looper;
import android.widget.Toast;
import com.limelight.LimeLog;
@@ -198,6 +199,26 @@ public class EvdevCaptureProvider extends InputCaptureProvider {
});
}
+ private void runInNetworkSafeContextSynchronously(Runnable runnable) {
+ // This function is used to avoid Android's strict NetworkOnMainThreadException.
+ // For our usage, it is highly unlikely to cause problems since we only do
+ // write operations and only to localhost sockets.
+ if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
+ Thread t = new Thread(runnable);
+ t.start();
+ try {
+ t.join();
+ } catch (InterruptedException e) {
+ // The main thread should never be interrupted
+ e.printStackTrace();
+ }
+ }
+ else {
+ // Run the runnable directly
+ runnable.run();
+ }
+ }
+
@Override
public void enableCapture() {
if (!started) {
@@ -207,26 +228,38 @@ public class EvdevCaptureProvider extends InputCaptureProvider {
started = true;
}
else {
- // Send a request to regrab if we're already capturing
- if (!shutdown && evdevOut != null) {
- try {
- evdevOut.write(REGRAB_REQUEST);
- } catch (IOException e) {
- e.printStackTrace();
+ // This may be called on the main thread
+ runInNetworkSafeContextSynchronously(new Runnable() {
+ @Override
+ public void run() {
+ // Send a request to regrab if we're already capturing
+ if (!shutdown && evdevOut != null) {
+ try {
+ evdevOut.write(REGRAB_REQUEST);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
}
- }
+ });
}
}
@Override
public void disableCapture() {
- if (started && !shutdown && evdevOut != null) {
- try {
- evdevOut.write(UNGRAB_REQUEST);
- } catch (IOException e) {
- e.printStackTrace();
+ // This may be called on the main thread
+ runInNetworkSafeContextSynchronously(new Runnable() {
+ @Override
+ public void run() {
+ if (started && !shutdown && evdevOut != null) {
+ try {
+ evdevOut.write(UNGRAB_REQUEST);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
}
- }
+ });
}
@Override
@@ -234,6 +267,8 @@ public class EvdevCaptureProvider extends InputCaptureProvider {
// We need to stop the process in this context otherwise
// we could get stuck waiting on output from the process
// in order to terminate it.
+ //
+ // This may be called on the main thread.
if (!started) {
return;
@@ -242,37 +277,42 @@ public class EvdevCaptureProvider extends InputCaptureProvider {
shutdown = true;
handlerThread.interrupt();
- if (servSock != null) {
- try {
- servSock.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
+ runInNetworkSafeContextSynchronously(new Runnable() {
+ @Override
+ public void run() {
+ if (servSock != null) {
+ try {
+ servSock.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
- if (evdevSock != null) {
- try {
- evdevSock.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
+ if (evdevSock != null) {
+ try {
+ evdevSock.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
- if (evdevIn != null) {
- try {
- evdevIn.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
+ if (evdevIn != null) {
+ try {
+ evdevIn.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
- if (evdevOut != null) {
- try {
- evdevOut.close();
- } catch (IOException e) {
- e.printStackTrace();
+ if (evdevOut != null) {
+ try {
+ evdevOut.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
}
- }
+ });
if (su != null) {
su.destroy();
diff --git a/app/src/main/java/com/limelight/binding/input/virtual_controller/DigitalButton.java b/app/src/main/java/com/limelight/binding/input/virtual_controller/DigitalButton.java
index bccc97ad..6447be84 100644
--- a/app/src/main/java/com/limelight/binding/input/virtual_controller/DigitalButton.java
+++ b/app/src/main/java/com/limelight/binding/input/virtual_controller/DigitalButton.java
@@ -190,8 +190,14 @@ public class DigitalButton extends VirtualControllerElement {
for (DigitalButtonListener listener : listeners) {
listener.onRelease();
}
- timerLongClick.cancel();
- longClickTimerTask.cancel();
+
+ // We may be called for a release without a prior click
+ if (timerLongClick != null) {
+ timerLongClick.cancel();
+ }
+ if (longClickTimerTask != null) {
+ longClickTimerTask.cancel();
+ }
}
@Override
diff --git a/app/src/main/java/com/limelight/binding/video/EnhancedDecoderRenderer.java b/app/src/main/java/com/limelight/binding/video/EnhancedDecoderRenderer.java
deleted file mode 100644
index 7378321f..00000000
--- a/app/src/main/java/com/limelight/binding/video/EnhancedDecoderRenderer.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.limelight.binding.video;
-
-import com.limelight.nvstream.av.video.VideoDecoderRenderer;
-
-public abstract class EnhancedDecoderRenderer extends VideoDecoderRenderer {
- public abstract boolean isHevcSupported();
- public abstract boolean isAvcSupported();
-}
diff --git a/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java b/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java
index 6c858dae..bbf15b1b 100644
--- a/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java
+++ b/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java
@@ -2,17 +2,14 @@ package com.limelight.binding.video;
import java.nio.ByteBuffer;
import java.util.Locale;
-import java.util.concurrent.locks.LockSupport;
import org.jcodec.codecs.h264.H264Utils;
import org.jcodec.codecs.h264.io.model.SeqParameterSet;
import org.jcodec.codecs.h264.io.model.VUIParameters;
import com.limelight.LimeLog;
-import com.limelight.nvstream.av.ByteBufferDescriptor;
-import com.limelight.nvstream.av.DecodeUnit;
import com.limelight.nvstream.av.video.VideoDecoderRenderer;
-import com.limelight.nvstream.av.video.VideoDepacketizer;
+import com.limelight.nvstream.jni.MoonBridge;
import com.limelight.preferences.PreferenceConfiguration;
import android.media.MediaCodec;
@@ -23,7 +20,7 @@ import android.media.MediaCodec.CodecException;
import android.os.Build;
import android.view.SurfaceHolder;
-public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
+public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
private static final boolean USE_FRAME_RENDER_TIME = false;
@@ -34,26 +31,28 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
private MediaCodecInfo hevcDecoder;
private MediaCodec videoDecoder;
- private Thread rendererThread;
+ private Thread rendererThread, spinnerThread;
private boolean needsSpsBitstreamFixup, isExynos4;
- private VideoDepacketizer depacketizer;
private boolean adaptivePlayback, directSubmit;
private boolean constrainedHighProfile;
+ private boolean refFrameInvalidationAvc, refFrameInvalidationHevc;
+ private boolean refFrameInvalidationActive;
private int initialWidth, initialHeight;
- private VideoFormat videoFormat;
+ private int videoFormat;
+ private Object renderTarget;
+ private boolean stopping;
private boolean needsBaselineSpsHack;
private SeqParameterSet savedSps;
private long lastTimestampUs;
- private long totalTimeMs;
private long decoderTimeMs;
+ private long totalTimeMs;
private int totalFrames;
private int numSpsIn;
private int numPpsIn;
private int numVpsIn;
- private int numIframeIn;
private MediaCodecInfo findAvcDecoder() {
MediaCodecInfo decoder = MediaCodecHelper.findProbableSafeDecoder("video/avc", MediaCodecInfo.CodecProfileLevel.AVCProfileHigh);
@@ -91,6 +90,10 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
return decoderInfo;
}
+ public void setRenderTarget(Object renderTarget) {
+ this.renderTarget = renderTarget;
+ }
+
public MediaCodecDecoderRenderer(int videoFormat) {
//dumpDecoders();
@@ -118,25 +121,35 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
if (avcDecoder != null) {
directSubmit = MediaCodecHelper.decoderCanDirectSubmit(avcDecoder.getName());
adaptivePlayback = MediaCodecHelper.decoderSupportsAdaptivePlayback(avcDecoder.getName());
+ refFrameInvalidationAvc = MediaCodecHelper.decoderSupportsRefFrameInvalidationAvc(avcDecoder.getName());
+ refFrameInvalidationHevc = MediaCodecHelper.decoderSupportsRefFrameInvalidationHevc(avcDecoder.getName());
if (directSubmit) {
LimeLog.info("Decoder "+avcDecoder.getName()+" will use direct submit");
}
+ if (refFrameInvalidationAvc) {
+ LimeLog.info("Decoder "+avcDecoder.getName()+" will use reference frame invalidation for AVC");
+ }
+ if (refFrameInvalidationHevc) {
+ LimeLog.info("Decoder "+avcDecoder.getName()+" will use reference frame invalidation for HEVC");
+ }
}
}
- @Override
public boolean isHevcSupported() {
return hevcDecoder != null;
}
- @Override
public boolean isAvcSupported() {
return avcDecoder != null;
}
+ public int getActiveVideoFormat() {
+ return this.videoFormat;
+ }
+
@Override
- public boolean setup(VideoDecoderRenderer.VideoFormat format, int width, int height, int redrawRate, Object renderTarget, int drFlags) {
+ public int setup(int format, int width, int height, int redrawRate) {
this.initialWidth = width;
this.initialHeight = height;
this.videoFormat = format;
@@ -144,13 +157,13 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
String mimeType;
String selectedDecoderName;
- if (videoFormat == VideoFormat.H264) {
+ if (videoFormat == MoonBridge.VIDEO_FORMAT_H264) {
mimeType = "video/avc";
selectedDecoderName = avcDecoder.getName();
if (avcDecoder == null) {
LimeLog.severe("No available AVC decoder!");
- return false;
+ return -1;
}
// These fixups only apply to H264 decoders
@@ -170,19 +183,24 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
if (isExynos4) {
LimeLog.info("Decoder "+selectedDecoderName+" is on Exynos 4");
}
+
+ refFrameInvalidationActive = refFrameInvalidationAvc;
}
- else if (videoFormat == VideoFormat.H265) {
+ else if (videoFormat == MoonBridge.VIDEO_FORMAT_H265) {
mimeType = "video/hevc";
selectedDecoderName = hevcDecoder.getName();
if (hevcDecoder == null) {
LimeLog.severe("No available HEVC decoder!");
- return false;
+ return -2;
}
+
+ refFrameInvalidationActive = refFrameInvalidationHevc;
}
else {
// Unknown format
- return false;
+ LimeLog.severe("Unknown format");
+ return -3;
}
// Codecs have been known to throw all sorts of crazy runtime exceptions
@@ -190,7 +208,8 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
try {
videoDecoder = MediaCodec.createByCodecName(selectedDecoderName);
} catch (Exception e) {
- return false;
+ e.printStackTrace();
+ return -4;
}
MediaFormat videoFormat = MediaFormat.createVideoFormat(mimeType, width, height);
@@ -210,26 +229,38 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
videoFormat.setInteger(MediaFormat.KEY_OPERATING_RATE, Short.MAX_VALUE);
}
- videoDecoder.configure(videoFormat, ((SurfaceHolder)renderTarget).getSurface(), null, 0);
- videoDecoder.setVideoScalingMode(MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT);
+ try {
+ videoDecoder.configure(videoFormat, ((SurfaceHolder)renderTarget).getSurface(), null, 0);
+ videoDecoder.setVideoScalingMode(MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT);
- if (USE_FRAME_RENDER_TIME && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- videoDecoder.setOnFrameRenderedListener(new MediaCodec.OnFrameRenderedListener() {
- @Override
- public void onFrameRendered(MediaCodec mediaCodec, long presentationTimeUs, long renderTimeNanos) {
- long delta = (renderTimeNanos / 1000000L) - (presentationTimeUs / 1000);
- if (delta >= 0 && delta < 1000) {
- if (USE_FRAME_RENDER_TIME) {
- totalTimeMs += delta;
+ if (USE_FRAME_RENDER_TIME && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ videoDecoder.setOnFrameRenderedListener(new MediaCodec.OnFrameRenderedListener() {
+ @Override
+ public void onFrameRendered(MediaCodec mediaCodec, long presentationTimeUs, long renderTimeNanos) {
+ long delta = (renderTimeNanos / 1000000L) - (presentationTimeUs / 1000);
+ if (delta >= 0 && delta < 1000) {
+ if (USE_FRAME_RENDER_TIME) {
+ totalTimeMs += delta;
+ }
}
}
- }
- }, null);
+ }, null);
+ }
+
+ LimeLog.info("Using codec "+selectedDecoderName+" for hardware decoding "+mimeType);
+
+ // Start the decoder
+ videoDecoder.start();
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ legacyInputBuffers = videoDecoder.getInputBuffers();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return -5;
}
- LimeLog.info("Using codec "+selectedDecoderName+" for hardware decoding "+mimeType);
-
- return true;
+ return 0;
}
private void handleDecoderException(Exception e, ByteBuffer buf, int codecFlags) {
@@ -248,7 +279,8 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
}
// Only throw if this happens at the beginning of a stream
- if (totalFrames < 60) {
+ // but not if we're stopping
+ if (totalFrames > 0 && totalFrames < 20 && !stopping) {
if (buf != null || codecFlags != 0) {
throw new RendererException(this, e, buf, codecFlags);
}
@@ -258,7 +290,7 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
}
}
- private void startDirectSubmitRendererThread()
+ private void startRendererThread()
{
rendererThread = new Thread() {
@Override
@@ -314,13 +346,36 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
rendererThread.start();
}
- private int dequeueInputBuffer(boolean wait, boolean infiniteWait) {
- int index;
+ private void startSpinnerThread() {
+ spinnerThread = new Thread() {
+ @Override
+ public void run() {
+ // This thread exists to keep the CPU at a higher DVFS state on devices
+ // where the governor scales clock speed sporadically, causing dropped frames.
+ while (!isInterrupted()) {
+ Thread.yield();
+ }
+ }
+ };
+ spinnerThread.setPriority(Thread.MIN_PRIORITY);
+ spinnerThread.start();
+ }
+
+ private int dequeueInputBuffer() {
+ int index = -1;
long startTime, queueTime;
startTime = MediaCodecHelper.getMonotonicMillis();
- index = videoDecoder.dequeueInputBuffer(wait ? (infiniteWait ? -1 : 3000) : 0);
+ try {
+ while (rendererThread.isAlive() && index < 0 && !stopping) {
+ index = videoDecoder.dequeueInputBuffer(10000);
+ }
+ } catch (Exception e) {
+ handleDecoderException(e, null, 0);
+ return MediaCodec.INFO_TRY_AGAIN_LATER;
+ }
+
if (index < 0) {
return index;
}
@@ -334,185 +389,35 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
return index;
}
- private void startLegacyRendererThread()
- {
- rendererThread = new Thread() {
- @Override
- public void run() {
- BufferInfo info = new BufferInfo();
- DecodeUnit du = null;
- int inputIndex = -1;
- long lastDuDequeueTime = 0;
- while (!isInterrupted())
- {
- // In order to get as much data to the decoder as early as possible,
- // try to submit up to 5 decode units at once without blocking.
- if (inputIndex == -1 && du == null) {
- try {
- for (int i = 0; i < 5; i++) {
- inputIndex = dequeueInputBuffer(false, false);
- du = depacketizer.pollNextDecodeUnit();
- if (du != null) {
- lastDuDequeueTime = MediaCodecHelper.getMonotonicMillis();
- notifyDuReceived(du);
- }
-
- // Stop if we can't get a DU or input buffer
- if (du == null || inputIndex == -1) {
- break;
- }
-
- submitDecodeUnit(du, inputIndex);
-
- du = null;
- inputIndex = -1;
- }
- } catch (Exception e) {
- inputIndex = -1;
- handleDecoderException(e, null, 0);
- }
- }
-
- // Grab an input buffer if we don't have one already.
- // This way we can have one ready hopefully by the time
- // the depacketizer is done with this frame. It's important
- // that this can timeout because it's possible that we could exhaust
- // the decoder's input buffers and deadlocks because aren't pulling
- // frames out of the other end.
- if (inputIndex == -1) {
- try {
- // If we've got a DU waiting to be given to the decoder,
- // wait a full 3 ms for an input buffer. Otherwise
- // just see if we can get one immediately.
- inputIndex = dequeueInputBuffer(du != null, false);
- } catch (Exception e) {
- inputIndex = -1;
- handleDecoderException(e, null, 0);
- }
- }
-
- // Grab a decode unit if we don't have one already
- if (du == null) {
- du = depacketizer.pollNextDecodeUnit();
- if (du != null) {
- lastDuDequeueTime = MediaCodecHelper.getMonotonicMillis();
- notifyDuReceived(du);
- }
- }
-
- // If we've got both a decode unit and an input buffer, we'll
- // submit now. Otherwise, we wait until we have one.
- if (du != null && inputIndex >= 0) {
- long submissionTime = MediaCodecHelper.getMonotonicMillis();
- if (submissionTime - lastDuDequeueTime >= 20) {
- LimeLog.warning("Receiving an input buffer took too long: "+(submissionTime - lastDuDequeueTime)+" ms");
- }
-
- submitDecodeUnit(du, inputIndex);
-
- // DU and input buffer have both been consumed
- du = null;
- inputIndex = -1;
- }
-
- // Try to output a frame
- try {
- int outIndex = videoDecoder.dequeueOutputBuffer(info, 0);
-
- if (outIndex >= 0) {
- long presentationTimeUs = info.presentationTimeUs;
- int lastIndex = outIndex;
-
- // Get the last output buffer in the queue
- while ((outIndex = videoDecoder.dequeueOutputBuffer(info, 0)) >= 0) {
- videoDecoder.releaseOutputBuffer(lastIndex, false);
- lastIndex = outIndex;
- presentationTimeUs = info.presentationTimeUs;
- }
-
- // Render the last buffer
- videoDecoder.releaseOutputBuffer(lastIndex, true);
-
- // Add delta time to the totals (excluding probable outliers)
- long delta = MediaCodecHelper.getMonotonicMillis()-(presentationTimeUs/1000);
- if (delta >= 0 && delta < 1000) {
- decoderTimeMs += delta;
- if (!USE_FRAME_RENDER_TIME) {
- totalTimeMs += delta;
- }
- }
- } else {
- switch (outIndex) {
- case MediaCodec.INFO_TRY_AGAIN_LATER:
- // Getting an input buffer may already block
- // so don't park if we still need to do that
- if (inputIndex >= 0) {
- LockSupport.parkNanos(1);
- }
- break;
- case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
- LimeLog.info("Output format changed");
- LimeLog.info("New output Format: " + videoDecoder.getOutputFormat());
- break;
- default:
- break;
- }
- }
- } catch (Exception e) {
- handleDecoderException(e, null, 0);
- }
- }
- }
- };
- rendererThread.setName("Video - Renderer (MediaCodec)");
- rendererThread.setPriority(Thread.MAX_PRIORITY);
- rendererThread.start();
- }
-
- @SuppressWarnings("deprecation")
@Override
- public boolean start(VideoDepacketizer depacketizer) {
- this.depacketizer = depacketizer;
-
- // Start the decoder
- videoDecoder.start();
-
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
- legacyInputBuffers = videoDecoder.getInputBuffers();
- }
-
- if (directSubmit) {
- startDirectSubmitRendererThread();
- }
- else {
- startLegacyRendererThread();
- }
-
- return true;
+ public void start() {
+ startRendererThread();
+ startSpinnerThread();
}
@Override
public void stop() {
- if (rendererThread != null) {
- // Halt the rendering thread
- rendererThread.interrupt();
- try {
- rendererThread.join();
- } catch (InterruptedException ignored) { }
- }
+ stopping = true;
- // We could stop the decoder here, but it seems to cause some problems
- // so we'll just let release take care of it.
+ // Halt the rendering thread
+ rendererThread.interrupt();
+ try {
+ rendererThread.join();
+ } catch (InterruptedException ignored) { }
+
+ // Halt the spinner thread
+ spinnerThread.interrupt();
+ try {
+ spinnerThread.join();
+ } catch (InterruptedException ignored) { }
}
@Override
- public void release() {
- if (videoDecoder != null) {
- videoDecoder.release();
- }
+ public void cleanup() {
+ videoDecoder.release();
}
- private void queueInputBuffer(int inputBufferIndex, int offset, int length, long timestampUs, int codecFlags) {
+ private boolean queueInputBuffer(int inputBufferIndex, int offset, int length, long timestampUs, int codecFlags) {
// Try 25 times to submit the input buffer before throwing a real exception
int i;
Exception lastException = null;
@@ -529,9 +434,17 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
}
}
- if (i == 25) {
+ if (i == 25 && totalFrames > 0 && totalFrames < 20 && !stopping) {
throw new RendererException(this, lastException, null, codecFlags);
}
+ else if (i != 25) {
+ // Queued input buffer
+ return true;
+ }
+ else {
+ // Failed to queue
+ return false;
+ }
}
// Using the new getInputBuffer() API on Lollipop allows
@@ -570,7 +483,10 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
}
@SuppressWarnings("deprecation")
- private void submitDecodeUnit(DecodeUnit decodeUnit, int inputBufferIndex) {
+ @Override
+ public int submitDecodeUnit(byte[] frameData, int frameLength) {
+ totalFrames++;
+
long timestampUs = System.nanoTime() / 1000;
if (timestampUs <= lastTimestampUs) {
// We can't submit multiple buffers with the same timestamp
@@ -579,39 +495,36 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
}
lastTimestampUs = timestampUs;
+ int inputBufferIndex = dequeueInputBuffer();
+ if (inputBufferIndex < 0) {
+ // We're being torn down now
+ return MoonBridge.DR_OK;
+ }
+
ByteBuffer buf = getEmptyInputBuffer(inputBufferIndex);
int codecFlags = 0;
- int decodeUnitFlags = decodeUnit.getFlags();
- if ((decodeUnitFlags & DecodeUnit.DU_FLAG_CODEC_CONFIG) != 0) {
- codecFlags |= MediaCodec.BUFFER_FLAG_CODEC_CONFIG;
- }
- if ((decodeUnitFlags & DecodeUnit.DU_FLAG_SYNC_FRAME) != 0) {
- codecFlags |= MediaCodec.BUFFER_FLAG_SYNC_FRAME;
- numIframeIn++;
- }
-
boolean needsSpsReplay = false;
- if ((decodeUnitFlags & DecodeUnit.DU_FLAG_CODEC_CONFIG) != 0) {
- ByteBufferDescriptor header = decodeUnit.getBufferHead();
+ // H264 SPS
+ if (frameData[4] == 0x67) {
+ numSpsIn++;
+ codecFlags |= MediaCodec.BUFFER_FLAG_CODEC_CONFIG;
- // H264 SPS
- if (header.data[header.offset+4] == 0x67) {
- numSpsIn++;
+ ByteBuffer spsBuf = ByteBuffer.wrap(frameData);
- ByteBuffer spsBuf = ByteBuffer.wrap(header.data);
+ // Skip to the start of the NALU data
+ spsBuf.position(5);
- // Skip to the start of the NALU data
- spsBuf.position(header.offset+5);
+ // The H264Utils.readSPS function safely handles
+ // Annex B NALUs (including NALUs with escape sequences)
+ SeqParameterSet sps = H264Utils.readSPS(spsBuf);
- // The H264Utils.readSPS function safely handles
- // Annex B NALUs (including NALUs with escape sequences)
- SeqParameterSet sps = H264Utils.readSPS(spsBuf);
-
- // Some decoders rely on H264 level to decide how many buffers are needed
- // Since we only need one frame buffered, we'll set the level as low as we can
- // for known resolution combinations
+ // Some decoders rely on H264 level to decide how many buffers are needed
+ // Since we only need one frame buffered, we'll set the level as low as we can
+ // for known resolution combinations. Reference frame invalidation may need
+ // these, so leave them be for those decoders.
+ if (!refFrameInvalidationActive) {
if (initialWidth == 1280 && initialHeight == 720) {
// Max 5 buffered frames at 1280x720x60
LimeLog.info("Patching level_idc to 32");
@@ -625,123 +538,142 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
else {
// Leave the profile alone (currently 5.0)
}
+ }
- // TI OMAP4 requires a reference frame count of 1 to decode successfully. Exynos 4
- // also requires this fixup.
- //
- // I'm doing this fixup for all devices because I haven't seen any devices that
- // this causes issues for. At worst, it seems to do nothing and at best it fixes
- // issues with video lag, hangs, and crashes.
+ // TI OMAP4 requires a reference frame count of 1 to decode successfully. Exynos 4
+ // also requires this fixup.
+ //
+ // I'm doing this fixup for all devices because I haven't seen any devices that
+ // this causes issues for. At worst, it seems to do nothing and at best it fixes
+ // issues with video lag, hangs, and crashes.
+ //
+ // It does break reference frame invalidation, so we will not do that for decoders
+ // where we've enabled reference frame invalidation.
+ if (!refFrameInvalidationActive) {
LimeLog.info("Patching num_ref_frames in SPS");
sps.num_ref_frames = 1;
+ }
- // GFE 2.5.11 changed the SPS to add additional extensions
- // Some devices don't like these so we remove them here.
- sps.vuiParams.video_signal_type_present_flag = false;
- sps.vuiParams.colour_description_present_flag = false;
- sps.vuiParams.chroma_loc_info_present_flag = false;
+ // GFE 2.5.11 changed the SPS to add additional extensions
+ // Some devices don't like these so we remove them here.
+ sps.vuiParams.video_signal_type_present_flag = false;
+ sps.vuiParams.colour_description_present_flag = false;
+ sps.vuiParams.chroma_loc_info_present_flag = false;
- if (needsSpsBitstreamFixup || isExynos4) {
- // The SPS that comes in the current H264 bytestream doesn't set bitstream_restriction_flag
- // or max_dec_frame_buffering which increases decoding latency on Tegra.
+ if ((needsSpsBitstreamFixup || isExynos4) && !refFrameInvalidationActive) {
+ // The SPS that comes in the current H264 bytestream doesn't set bitstream_restriction_flag
+ // or max_dec_frame_buffering which increases decoding latency on Tegra.
- // GFE 2.5.11 started sending bitstream restrictions
- if (sps.vuiParams.bitstreamRestriction == null) {
- LimeLog.info("Adding bitstream restrictions");
- sps.vuiParams.bitstreamRestriction = new VUIParameters.BitstreamRestriction();
- sps.vuiParams.bitstreamRestriction.motion_vectors_over_pic_boundaries_flag = true;
- sps.vuiParams.bitstreamRestriction.log2_max_mv_length_horizontal = 16;
- sps.vuiParams.bitstreamRestriction.log2_max_mv_length_vertical = 16;
- sps.vuiParams.bitstreamRestriction.num_reorder_frames = 0;
- }
- else {
- LimeLog.info("Patching bitstream restrictions");
- }
-
- // Some devices throw errors if max_dec_frame_buffering < num_ref_frames
- sps.vuiParams.bitstreamRestriction.max_dec_frame_buffering = sps.num_ref_frames;
-
- // These values are the defaults for the fields, but they are more aggressive
- // than what GFE sends in 2.5.11, but it doesn't seem to cause picture problems.
- sps.vuiParams.bitstreamRestriction.max_bytes_per_pic_denom = 2;
- sps.vuiParams.bitstreamRestriction.max_bits_per_mb_denom = 1;
-
- // log2_max_mv_length_horizontal and log2_max_mv_length_vertical are set to more
- // conservative values by GFE 2.5.11. We'll let those values stand.
+ // GFE 2.5.11 started sending bitstream restrictions
+ if (sps.vuiParams.bitstreamRestriction == null) {
+ LimeLog.info("Adding bitstream restrictions");
+ sps.vuiParams.bitstreamRestriction = new VUIParameters.BitstreamRestriction();
+ sps.vuiParams.bitstreamRestriction.motion_vectors_over_pic_boundaries_flag = true;
+ sps.vuiParams.bitstreamRestriction.log2_max_mv_length_horizontal = 16;
+ sps.vuiParams.bitstreamRestriction.log2_max_mv_length_vertical = 16;
+ sps.vuiParams.bitstreamRestriction.num_reorder_frames = 0;
}
else {
- // Devices that didn't/couldn't get bitstream restrictions before GFE 2.5.11
- // will continue to not receive them now
- sps.vuiParams.bitstreamRestriction = null;
+ LimeLog.info("Patching bitstream restrictions");
}
- // If we need to hack this SPS to say we're baseline, do so now
- if (needsBaselineSpsHack) {
- LimeLog.info("Hacking SPS to baseline");
- sps.profile_idc = 66;
- savedSps = sps;
- }
+ // Some devices throw errors if max_dec_frame_buffering < num_ref_frames
+ sps.vuiParams.bitstreamRestriction.max_dec_frame_buffering = sps.num_ref_frames;
- // Patch the SPS constraint flags
- doProfileSpecificSpsPatching(sps);
+ // These values are the defaults for the fields, but they are more aggressive
+ // than what GFE sends in 2.5.11, but it doesn't seem to cause picture problems.
+ sps.vuiParams.bitstreamRestriction.max_bytes_per_pic_denom = 2;
+ sps.vuiParams.bitstreamRestriction.max_bits_per_mb_denom = 1;
- // Write the annex B header
- buf.put(header.data, header.offset, 5);
-
- // The H264Utils.writeSPS function safely handles
- // Annex B NALUs (including NALUs with escape sequences)
- ByteBuffer escapedNalu = H264Utils.writeSPS(sps, header.length);
- buf.put(escapedNalu);
-
- queueInputBuffer(inputBufferIndex,
- 0, buf.position(),
- timestampUs, codecFlags);
-
- depacketizer.freeDecodeUnit(decodeUnit);
- return;
-
- // H264 PPS
- } else if (header.data[header.offset+4] == 0x68) {
- numPpsIn++;
-
- if (needsBaselineSpsHack) {
- LimeLog.info("Saw PPS; disabling SPS hack");
- needsBaselineSpsHack = false;
-
- // Give the decoder the SPS again with the proper profile now
- needsSpsReplay = true;
- }
+ // log2_max_mv_length_horizontal and log2_max_mv_length_vertical are set to more
+ // conservative values by GFE 2.5.11. We'll let those values stand.
}
- else if (header.data[header.offset+4] == 0x40) {
- numVpsIn++;
+ else {
+ // Devices that didn't/couldn't get bitstream restrictions before GFE 2.5.11
+ // will continue to not receive them now
+ sps.vuiParams.bitstreamRestriction = null;
}
- else if (header.data[header.offset+4] == 0x42) {
- numSpsIn++;
+
+ // If we need to hack this SPS to say we're baseline, do so now
+ if (needsBaselineSpsHack) {
+ LimeLog.info("Hacking SPS to baseline");
+ sps.profile_idc = 66;
+ savedSps = sps;
}
- else if (header.data[header.offset+4] == 0x44) {
- numPpsIn++;
+
+ // Patch the SPS constraint flags
+ doProfileSpecificSpsPatching(sps);
+
+ // Write the annex B header
+ buf.put(frameData, 0, 5);
+
+ // The H264Utils.writeSPS function safely handles
+ // Annex B NALUs (including NALUs with escape sequences)
+ ByteBuffer escapedNalu = H264Utils.writeSPS(sps, frameLength);
+ buf.put(escapedNalu);
+
+ if (queueInputBuffer(inputBufferIndex,
+ 0, buf.position(),
+ timestampUs, codecFlags)) {
+ return MoonBridge.DR_OK;
}
+ else {
+ return MoonBridge.DR_NEED_IDR;
+ }
+
+ // H264 PPS
+ } else if (frameData[4] == 0x68) {
+ numPpsIn++;
+ codecFlags |= MediaCodec.BUFFER_FLAG_CODEC_CONFIG;
+
+
+ if (needsBaselineSpsHack) {
+ LimeLog.info("Saw PPS; disabling SPS hack");
+ needsBaselineSpsHack = false;
+
+ // Give the decoder the SPS again with the proper profile now
+ needsSpsReplay = true;
+ }
+ }
+ else if (frameData[4] == 0x40) {
+ numVpsIn++;
+ codecFlags |= MediaCodec.BUFFER_FLAG_CODEC_CONFIG;
+ }
+ else if (frameData[4] == 0x42) {
+ numSpsIn++;
+ codecFlags |= MediaCodec.BUFFER_FLAG_CODEC_CONFIG;
+ }
+ else if (frameData[4] == 0x44) {
+ numPpsIn++;
+ codecFlags |= MediaCodec.BUFFER_FLAG_CODEC_CONFIG;
}
// Copy data from our buffer list into the input buffer
- for (ByteBufferDescriptor desc = decodeUnit.getBufferHead();
- desc != null; desc = desc.nextDescriptor) {
- buf.put(desc.data, desc.offset, desc.length);
+ buf.put(frameData, 0, frameLength);
+
+ if (!queueInputBuffer(inputBufferIndex,
+ 0, frameLength,
+ timestampUs, codecFlags)) {
+ return MoonBridge.DR_NEED_IDR;
}
- queueInputBuffer(inputBufferIndex,
- 0, decodeUnit.getDataLength(),
- timestampUs, codecFlags);
-
- depacketizer.freeDecodeUnit(decodeUnit);
-
if (needsSpsReplay) {
- replaySps();
+ if (!replaySps()) {
+ return MoonBridge.DR_NEED_IDR;
+ }
+
+ LimeLog.info("SPS replay complete");
}
+
+ return MoonBridge.DR_OK;
}
- private void replaySps() {
- int inputIndex = dequeueInputBuffer(true, true);
+ private boolean replaySps() {
+ int inputIndex = dequeueInputBuffer();
+ if (inputIndex < 0) {
+ return false;
+ }
+
ByteBuffer inputBuffer = getEmptyInputBuffer(inputIndex);
// Write the Annex B header
@@ -762,36 +694,35 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
savedSps = null;
// Queue the new SPS
- queueInputBuffer(inputIndex,
+ return queueInputBuffer(inputIndex,
0, inputBuffer.position(),
System.nanoTime() / 1000,
MediaCodec.BUFFER_FLAG_CODEC_CONFIG);
-
- LimeLog.info("SPS replay complete");
}
@Override
public int getCapabilities() {
- int caps = 0;
+ int capabilities = 0;
- caps |= adaptivePlayback ?
- VideoDecoderRenderer.CAPABILITY_ADAPTIVE_RESOLUTION : 0;
+ // We always request 4 slices per frame to speed up decoding on some hardware
+ capabilities |= MoonBridge.CAPABILITY_SLICES_PER_FRAME((byte) 4);
- caps |= directSubmit ?
- VideoDecoderRenderer.CAPABILITY_DIRECT_SUBMIT : 0;
-
- return caps;
- }
-
- @Override
- public int getAverageDecoderLatency() {
- if (totalFrames == 0) {
- return 0;
+ // Enable reference frame invalidation on supported hardware
+ if (refFrameInvalidationAvc) {
+ capabilities |= MoonBridge.CAPABILITY_REFERENCE_FRAME_INVALIDATION_AVC;
}
- return (int)(decoderTimeMs / totalFrames);
+ if (refFrameInvalidationHevc) {
+ capabilities |= MoonBridge.CAPABILITY_REFERENCE_FRAME_INVALIDATION_HEVC;
+ }
+
+ // Enable direct submit on supported hardware
+ if (directSubmit) {
+ capabilities |= MoonBridge.CAPABILITY_DIRECT_SUBMIT;
+ }
+
+ return capabilities;
}
- @Override
public int getAverageEndToEndLatency() {
if (totalFrames == 0) {
return 0;
@@ -799,33 +730,11 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
return (int)(totalTimeMs / totalFrames);
}
- private void notifyDuReceived(DecodeUnit du) {
- long currentTime = MediaCodecHelper.getMonotonicMillis();
- long delta = currentTime-du.getReceiveTimestamp();
- if (delta >= 0 && delta < 1000) {
- totalTimeMs += currentTime-du.getReceiveTimestamp();
- totalFrames++;
- }
- }
-
- @Override
- public void directSubmitDecodeUnit(DecodeUnit du) {
- int inputIndex = -1;
-
- notifyDuReceived(du);
-
- while (!Thread.currentThread().isInterrupted()) {
- try {
- inputIndex = dequeueInputBuffer(true, true);
- break;
- } catch (Exception e) {
- handleDecoderException(e, null, 0);
- }
- }
-
- if (inputIndex >= 0) {
- submitDecodeUnit(du, inputIndex);
+ public int getAverageDecoderLatency() {
+ if (totalFrames == 0) {
+ return 0;
}
+ return (int)(decoderTimeMs / totalFrames);
}
public class RendererException extends RuntimeException {
@@ -855,7 +764,7 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
str += "AVC Decoder: "+((renderer.avcDecoder != null) ? renderer.avcDecoder.getName():"(none)")+"\n";
str += "HEVC Decoder: "+((renderer.hevcDecoder != null) ? renderer.hevcDecoder.getName():"(none)")+"\n";
str += "Initial video dimensions: "+renderer.initialWidth+"x"+renderer.initialHeight+"\n";
- str += "In stats: "+renderer.numVpsIn+", "+renderer.numSpsIn+", "+renderer.numPpsIn+", "+renderer.numIframeIn+"\n";
+ str += "In stats: "+renderer.numVpsIn+", "+renderer.numSpsIn+", "+renderer.numPpsIn+"\n";
str += "Total frames: "+renderer.totalFrames+"\n";
str += "Average end-to-end client latency: "+getAverageEndToEndLatency()+"ms\n";
str += "Average hardware decoder latency: "+getAverageDecoderLatency()+"ms\n";
diff --git a/app/src/main/java/com/limelight/binding/video/MediaCodecHelper.java b/app/src/main/java/com/limelight/binding/video/MediaCodecHelper.java
index 91c7e3a8..153f528d 100644
--- a/app/src/main/java/com/limelight/binding/video/MediaCodecHelper.java
+++ b/app/src/main/java/com/limelight/binding/video/MediaCodecHelper.java
@@ -32,6 +32,8 @@ public class MediaCodecHelper {
private static final List directSubmitPrefixes;
private static final List constrainedHighProfilePrefixes;
private static final List whitelistedHevcDecoders;
+ private static final List refFrameInvalidationAvcPrefixes;
+ private static final List refFrameInvalidationHevcPrefixes;
static {
directSubmitPrefixes = new LinkedList<>();
@@ -45,8 +47,16 @@ public class MediaCodecHelper {
directSubmitPrefixes.add("omx.brcm");
directSubmitPrefixes.add("omx.TI");
directSubmitPrefixes.add("omx.arc");
+ directSubmitPrefixes.add("omx.nvidia");
}
+ static {
+ refFrameInvalidationAvcPrefixes = new LinkedList<>();
+ refFrameInvalidationHevcPrefixes = new LinkedList<>();
+
+ // Qualcomm and NVIDIA may be added at runtime
+ }
+
static {
preferredDecoders = new LinkedList<>();
}
@@ -65,6 +75,8 @@ public class MediaCodecHelper {
}
static {
+ // If a decoder qualifies for reference frame invalidation,
+ // these entries will be ignored for those decoders.
spsFixupBitstreamFixupDecoderPrefixes = new LinkedList<>();
spsFixupBitstreamFixupDecoderPrefixes.add("omx.nvidia");
spsFixupBitstreamFixupDecoderPrefixes.add("omx.qcom");
@@ -113,20 +125,36 @@ public class MediaCodecHelper {
(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo configInfo = activityManager.getDeviceConfigurationInfo();
if (configInfo.reqGlEsVersion != ConfigurationInfo.GL_ES_VERSION_UNDEFINED) {
- // Qualcomm's early HEVC decoders break hard on our HEVC stream. The best check to
- // tell the good from the bad decoders are the generation of Adreno GPU included:
- // 3xx - bad
- // 4xx - good
- //
- // Unfortunately, it's not that easy to get that information here, so I'll use an
- // approximation by checking the GLES level (<= 3.0 is bad).
LimeLog.info("OpenGL ES version: "+configInfo.reqGlEsVersion);
- if (configInfo.reqGlEsVersion > 0x30000) {
- LimeLog.info("Added omx.qcom to supported decoders based on GLES 3.1+ support");
- whitelistedHevcDecoders.add("omx.qcom");
+
+ // Tegra K1 and later can do reference frame invalidation properly
+ if (configInfo.reqGlEsVersion >= 0x30000) {
+ LimeLog.info("Added omx.nvidia to AVC reference frame invalidation support list");
+ refFrameInvalidationAvcPrefixes.add("omx.nvidia");
+
+ LimeLog.info("Added omx.qcom to AVC reference frame invalidation support list");
+ refFrameInvalidationAvcPrefixes.add("omx.qcom");
+
+ LimeLog.info("Added omx.intel to AVC reference frame invalidation support list");
+ refFrameInvalidationAvcPrefixes.add("omx.intel");
+
+ // Qualcomm's early HEVC decoders break hard on our HEVC stream. The best check to
+ // tell the good from the bad decoders are the generation of Adreno GPU included:
+ // 3xx - bad
+ // 4xx - good
+ //
+ // Unfortunately, it's not that easy to get that information here, so I'll use an
+ // approximation by checking the GLES level (<= 3.0 is bad).
+ if (configInfo.reqGlEsVersion > 0x30000) {
+ // FIXME: We prefer reference frame invalidation support (which is only doable on AVC on
+ // older Qualcomm chips) vs. enabling HEVC by default. The user can override using the settings
+ // to force HEVC on.
+ //LimeLog.info("Added omx.qcom to supported HEVC decoders based on GLES 3.1+ support");
+ //whitelistedHevcDecoders.add("omx.qcom");
+ }
}
}
- }
+ }
private static boolean isDecoderInList(List decoderList, String decoderName) {
for (String badPrefix : decoderList) {
@@ -190,6 +218,14 @@ public class MediaCodecHelper {
return isDecoderInList(baselineProfileHackPrefixes, decoderName);
}
+ public static boolean decoderSupportsRefFrameInvalidationAvc(String decoderName) {
+ return isDecoderInList(refFrameInvalidationAvcPrefixes, decoderName);
+ }
+
+ public static boolean decoderSupportsRefFrameInvalidationHevc(String decoderName) {
+ return isDecoderInList(refFrameInvalidationHevcPrefixes, decoderName);
+ }
+
public static boolean decoderIsWhitelistedForHevc(String decoderName) {
// TODO: Shield Tablet K1/LTE?
//
@@ -212,6 +248,16 @@ public class MediaCodecHelper {
return false;
}
+ //
+ // Software decoders are terrible and we never want to use them.
+ // We want to catch decoders like:
+ // OMX.qcom.video.decoder.hevcswvdec
+ // OMX.SEC.hevc.sw.dec
+ //
+ if (decoderName.contains("sw")) {
+ return false;
+ }
+
return isDecoderInList(whitelistedHevcDecoders, decoderName);
}
diff --git a/app/src/main/java/com/limelight/utils/Vector2d.java b/app/src/main/java/com/limelight/utils/Vector2d.java
new file mode 100644
index 00000000..d01b78ba
--- /dev/null
+++ b/app/src/main/java/com/limelight/utils/Vector2d.java
@@ -0,0 +1,47 @@
+package com.limelight.utils;
+
+public class Vector2d {
+ private float x;
+ private float y;
+ private double magnitude;
+
+ public static final Vector2d ZERO = new Vector2d();
+
+ public Vector2d() {
+ initialize(0, 0);
+ }
+
+ public void initialize(float x, float y) {
+ this.x = x;
+ this.y = y;
+ this.magnitude = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
+ }
+
+ public double getMagnitude() {
+ return magnitude;
+ }
+
+ public void getNormalized(Vector2d vector) {
+ vector.initialize((float)(x / magnitude), (float)(y / magnitude));
+ }
+
+ public void scalarMultiply(double factor) {
+ initialize((float)(x * factor), (float)(y * factor));
+ }
+
+ public void setX(float x) {
+ initialize(x, this.y);
+ }
+
+ public void setY(float y) {
+ initialize(this.x, y);
+ }
+
+ public float getX() {
+ return x;
+ }
+
+ public float getY() {
+ return y;
+ }
+}
diff --git a/app/src/main/jni/jnienet/Android.mk b/app/src/main/jni/jnienet/Android.mk
deleted file mode 100644
index 4b5a25f8..00000000
--- a/app/src/main/jni/jnienet/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-# Android.mk for Moonlight's ENet JNI binding
-MY_LOCAL_PATH := $(call my-dir)
-
-include $(call all-subdir-makefiles)
-
-LOCAL_PATH := $(MY_LOCAL_PATH)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := jnienet
-
-LOCAL_SRC_FILES := jnienet.c \
- enet/callbacks.c \
- enet/compress.c \
- enet/host.c \
- enet/list.c \
- enet/packet.c \
- enet/peer.c \
- enet/protocol.c \
- enet/unix.c \
- enet/win32.c \
-
-LOCAL_CFLAGS := -DHAS_SOCKLEN_T=1
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/enet/include
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/app/src/main/jni/jnienet/enet b/app/src/main/jni/jnienet/enet
deleted file mode 160000
index 7546b505..00000000
--- a/app/src/main/jni/jnienet/enet
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 7546b505c12b305ad0245320b46cb2b070bab216
diff --git a/app/src/main/jni/jnienet/jnienet.c b/app/src/main/jni/jnienet/jnienet.c
deleted file mode 100644
index 1ff8a026..00000000
--- a/app/src/main/jni/jnienet/jnienet.c
+++ /dev/null
@@ -1,148 +0,0 @@
-#include "enet/enet.h"
-
-#include
-#include
-
-#include
-
-#define CLIENT_TO_LONG(x) ((intptr_t)(x))
-#define LONG_TO_CLIENT(x) ((ENetHost*)(intptr_t)(x))
-
-#define PEER_TO_LONG(x) ((intptr_t)(x))
-#define LONG_TO_PEER(x) ((ENetPeer*)(intptr_t)(x))
-
-JNIEXPORT jint JNICALL
-Java_com_limelight_nvstream_enet_EnetConnection_initializeEnet(JNIEnv *env, jobject class) {
- return enet_initialize();
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_limelight_nvstream_enet_EnetConnection_createClient(JNIEnv *env, jobject class, jstring address) {
- ENetAddress enetAddress;
- const char *addrStr;
- int err;
-
- // Perform a lookup on the address to determine the address family
- addrStr = (*env)->GetStringUTFChars(env, address, 0);
- err = enet_address_set_host(&enetAddress, addrStr);
- (*env)->ReleaseStringUTFChars(env, address, addrStr);
- if (err < 0) {
- return CLIENT_TO_LONG(NULL);
- }
-
- // Create a client that can use 1 outgoing connection and 1 channel
- return CLIENT_TO_LONG(enet_host_create(enetAddress.address.ss_family, NULL, 1, 1, 0, 0));
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_limelight_nvstream_enet_EnetConnection_connectToPeer(JNIEnv *env, jobject class, jlong client, jstring address, jint port, jint timeout) {
- ENetPeer* peer;
- ENetAddress enetAddress;
- ENetEvent event;
- const char *addrStr;
- int err;
-
- // Initialize the ENet address
- addrStr = (*env)->GetStringUTFChars(env, address, 0);
- err = enet_address_set_host(&enetAddress, addrStr);
- enet_address_set_port(&enetAddress, port);
- (*env)->ReleaseStringUTFChars(env, address, addrStr);
- if (err < 0) {
- return PEER_TO_LONG(NULL);
- }
-
- // Start the connection
- peer = enet_host_connect(LONG_TO_CLIENT(client), &enetAddress, 1, 0);
- if (peer == NULL) {
- return PEER_TO_LONG(NULL);
- }
-
- // Wait for the connect to complete
- if (enet_host_service(LONG_TO_CLIENT(client), &event, timeout) <= 0 || event.type != ENET_EVENT_TYPE_CONNECT) {
- enet_peer_reset(peer);
- return PEER_TO_LONG(NULL);
- }
-
- // Ensure the connect verify ACK is sent immediately
- enet_host_flush(LONG_TO_CLIENT(client));
-
- // Set the max peer timeout to 10 seconds
- enet_peer_timeout(peer, ENET_PEER_TIMEOUT_LIMIT, ENET_PEER_TIMEOUT_MINIMUM, 10000);
-
- return PEER_TO_LONG(peer);
-}
-
-JNIEXPORT jint JNICALL
-Java_com_limelight_nvstream_enet_EnetConnection_readPacket(JNIEnv *env, jobject class, jlong client, jbyteArray data, jint length, jint timeout) {
- jint err;
- jbyte* dataPtr;
- ENetEvent event;
-
- // Wait for a receive event, timeout, or disconnect
- err = enet_host_service(LONG_TO_CLIENT(client), &event, timeout);
- if (err <= 0) {
- return err;
- }
- else if (event.type != ENET_EVENT_TYPE_RECEIVE) {
- return -1;
- }
-
- // Check that the packet isn't too large
- if (event.packet->dataLength > length) {
- enet_packet_destroy(event.packet);
- return event.packet->dataLength;
- }
-
- // Copy the packet data into the caller's buffer
- dataPtr = (*env)->GetByteArrayElements(env, data, 0);
- memcpy(dataPtr, event.packet->data, event.packet->dataLength);
- err = event.packet->dataLength;
- (*env)->ReleaseByteArrayElements(env, data, dataPtr, 0);
-
- // Free the packet
- enet_packet_destroy(event.packet);
-
- return err;
-}
-
-JNIEXPORT jboolean JNICALL
-Java_com_limelight_nvstream_enet_EnetConnection_writePacket(JNIEnv *env, jobject class, jlong client, jlong peer, jbyteArray data, jint length, jint packetFlags) {
- ENetPacket* packet;
- jboolean ret;
- jbyte* dataPtr;
-
- dataPtr = (*env)->GetByteArrayElements(env, data, 0);
-
- // Create the reliable packet that describes our outgoing message
- packet = enet_packet_create(dataPtr, length, packetFlags);
- if (packet != NULL) {
- // Send the message to the peer
- if (enet_peer_send(LONG_TO_PEER(peer), 0, packet) < 0) {
- // This can fail if the peer has been disconnected
- enet_packet_destroy(packet);
- ret = JNI_FALSE;
- }
- else {
- // Force the client to send the packet now
- enet_host_flush(LONG_TO_CLIENT(client));
- ret = JNI_TRUE;
- }
- }
- else {
- ret = JNI_FALSE;
- }
-
- (*env)->ReleaseByteArrayElements(env, data, dataPtr, JNI_ABORT);
-
- return ret;
-}
-
-JNIEXPORT void JNICALL
-Java_com_limelight_nvstream_enet_EnetConnection_destroyClient(JNIEnv *env, jobject class, jlong client) {
- enet_host_destroy(LONG_TO_CLIENT(client));
-}
-
-JNIEXPORT void JNICALL
-Java_com_limelight_nvstream_enet_EnetConnection_disconnectPeer(JNIEnv *env, jobject class, jlong peer) {
- enet_peer_disconnect_now(LONG_TO_PEER(peer), 0);
-}
diff --git a/app/src/main/jni/nv_opus_dec/Android.mk b/app/src/main/jni/nv_opus_dec/Android.mk
deleted file mode 100644
index 97585d1e..00000000
--- a/app/src/main/jni/nv_opus_dec/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-# Android.mk for Limelight's Opus decoder
-MY_LOCAL_PATH := $(call my-dir)
-
-include $(call all-subdir-makefiles)
-
-LOCAL_PATH := $(MY_LOCAL_PATH)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := nv_opus_dec
-LOCAL_SRC_FILES := nv_opus_dec.c nv_opus_dec_jni.c
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/libopus/inc
-
-# Link to libopus library
-LOCAL_STATIC_LIBRARIES := libopus
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/app/src/main/jni/nv_opus_dec/libopus/Android.mk b/app/src/main/jni/nv_opus_dec/libopus/Android.mk
deleted file mode 100644
index 00804bce..00000000
--- a/app/src/main/jni/nv_opus_dec/libopus/Android.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE:= libopus
-LOCAL_SRC_FILES:= $(TARGET_ARCH_ABI)/libopus.a
-LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/inc
-include $(PREBUILT_STATIC_LIBRARY)
diff --git a/app/src/main/jni/nv_opus_dec/libopus/arm64-v8a/libopus.a b/app/src/main/jni/nv_opus_dec/libopus/arm64-v8a/libopus.a
deleted file mode 100644
index 16bcd03f..00000000
Binary files a/app/src/main/jni/nv_opus_dec/libopus/arm64-v8a/libopus.a and /dev/null differ
diff --git a/app/src/main/jni/nv_opus_dec/libopus/armeabi-v7a/libopus.a b/app/src/main/jni/nv_opus_dec/libopus/armeabi-v7a/libopus.a
deleted file mode 100644
index e2a1ccb9..00000000
Binary files a/app/src/main/jni/nv_opus_dec/libopus/armeabi-v7a/libopus.a and /dev/null differ
diff --git a/app/src/main/jni/nv_opus_dec/libopus/build_android.sh b/app/src/main/jni/nv_opus_dec/libopus/build_android.sh
deleted file mode 100644
index a74db72d..00000000
--- a/app/src/main/jni/nv_opus_dec/libopus/build_android.sh
+++ /dev/null
@@ -1,100 +0,0 @@
-ANDROID_API_TARGET=21
-PARALLEL_JOBS=$(nproc)
-
-rm -r ./android
-mkdir android
-
-function build_one
-{
-PREFIX=$(pwd)/android/$CPU
-SYSROOT=$NDK/platforms/android-$ANDROID_API_TARGET/arch-$SYSROOT_CPU
-TOOLCHAIN_PATH=$NDK/toolchains/$TOOLCHAIN_DIR/prebuilt/linux-x86_64
-export PATH=$PATH:$TOOLCHAIN_PATH/bin
-./configure \
- --build=x86_64-unknown-linux-gnu \
- --host=$TOOLCHAIN_BIN_PREFIX \
- --target=$TOOLCHAIN_BIN_PREFIX \
- CFLAGS="--sysroot=$SYSROOT -O2 $ADDI_CFLAGS" \
- $ADDI_CONFIGURE_FLAGS
-make clean
-make -j$PARALLEL_JOBS
-mkdir android/$CPU
-cp .libs/libopus.a android/$CPU
-}
-
-function build_mips
-{
-CPU=mips
-SYSROOT_CPU=mips
-TOOLCHAIN_BIN_PREFIX=mipsel-linux-android
-TOOLCHAIN_DIR=mipsel-linux-android-4.9
-ADDI_CFLAGS="-mips32 -mhard-float -EL -mno-dsp"
-ADDI_CONFIGURE_FLAGS="--enable-fixed-point" # fixed point
-build_one
-}
-
-function build_mips64
-{
-CPU=mips64
-SYSROOT_CPU=mips64
-TOOLCHAIN_BIN_PREFIX=mips64el-linux-android
-TOOLCHAIN_DIR=mips64el-linux-android-4.9
-ADDI_CFLAGS="-mips64r6"
-ADDI_CONFIGURE_FLAGS="--enable-fixed-point" # fixed point
-build_one
-}
-
-function build_x86
-{
-CPU=x86
-SYSROOT_CPU=x86
-TOOLCHAIN_BIN_PREFIX=i686-linux-android
-TOOLCHAIN_DIR=x86-4.9
-ADDI_CFLAGS="-march=i686 -mtune=atom -mstackrealign -msse -msse2 -msse3 -mssse3 -mfpmath=sse -m32"
-ADDI_CONFIGURE_FLAGS="" # floating point for SSE optimizations
-build_one
-}
-
-function build_x86_64
-{
-CPU=x86_64
-SYSROOT_CPU=x86_64
-TOOLCHAIN_BIN_PREFIX=x86_64-linux-android
-TOOLCHAIN_DIR=x86_64-4.9
-ADDI_CFLAGS="-msse -msse2 -msse3 -mssse3 -msse4 -msse4.1 -msse4.2 -mpopcnt -m64"
-ADDI_CONFIGURE_FLAGS="" # floating point for SSE optimizations
-build_one
-}
-
-function build_armv7
-{
-CPU=arm
-SYSROOT_CPU=arm
-TOOLCHAIN_BIN_PREFIX=arm-linux-androideabi
-TOOLCHAIN_DIR=arm-linux-androideabi-4.9
-ADDI_CFLAGS="-marm -mfpu=vfpv3-d16"
-ADDI_LDFLAGS=""
-ADDI_CONFIGURE_FLAGS="--enable-fixed-point" # fixed point for NEON, EDSP, Media
-build_one
-}
-
-# ARMv8 doesn't currently have assembly in the opus project. We still use fixed point
-# anyway in the hopes that it will be more performant even without assembly.
-function build_armv8
-{
-CPU=aarch64
-SYSROOT_CPU=arm64
-TOOLCHAIN_BIN_PREFIX=aarch64-linux-android
-TOOLCHAIN_DIR=aarch64-linux-android-4.9
-ADDI_CFLAGS=""
-ADDI_LDFLAGS=""
-ADDI_CONFIGURE_FLAGS="--enable-fixed-point"
-build_one
-}
-
-build_mips
-build_mips64
-build_x86
-build_x86_64
-build_armv7
-build_armv8
diff --git a/app/src/main/jni/nv_opus_dec/libopus/inc/opus.h b/app/src/main/jni/nv_opus_dec/libopus/inc/opus.h
deleted file mode 100644
index 93a53a2f..00000000
--- a/app/src/main/jni/nv_opus_dec/libopus/inc/opus.h
+++ /dev/null
@@ -1,978 +0,0 @@
-/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited
- Written by Jean-Marc Valin and Koen Vos */
-/*
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/**
- * @file opus.h
- * @brief Opus reference implementation API
- */
-
-#ifndef OPUS_H
-#define OPUS_H
-
-#include "opus_types.h"
-#include "opus_defines.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @mainpage Opus
- *
- * The Opus codec is designed for interactive speech and audio transmission over the Internet.
- * It is designed by the IETF Codec Working Group and incorporates technology from
- * Skype's SILK codec and Xiph.Org's CELT codec.
- *
- * The Opus codec is designed to handle a wide range of interactive audio applications,
- * including Voice over IP, videoconferencing, in-game chat, and even remote live music
- * performances. It can scale from low bit-rate narrowband speech to very high quality
- * stereo music. Its main features are:
-
- * @li Sampling rates from 8 to 48 kHz
- * @li Bit-rates from 6 kb/s to 510 kb/s
- * @li Support for both constant bit-rate (CBR) and variable bit-rate (VBR)
- * @li Audio bandwidth from narrowband to full-band
- * @li Support for speech and music
- * @li Support for mono and stereo
- * @li Support for multichannel (up to 255 channels)
- * @li Frame sizes from 2.5 ms to 60 ms
- * @li Good loss robustness and packet loss concealment (PLC)
- * @li Floating point and fixed-point implementation
- *
- * Documentation sections:
- * @li @ref opus_encoder
- * @li @ref opus_decoder
- * @li @ref opus_repacketizer
- * @li @ref opus_multistream
- * @li @ref opus_libinfo
- * @li @ref opus_custom
- */
-
-/** @defgroup opus_encoder Opus Encoder
- * @{
- *
- * @brief This page describes the process and functions used to encode Opus.
- *
- * Since Opus is a stateful codec, the encoding process starts with creating an encoder
- * state. This can be done with:
- *
- * @code
- * int error;
- * OpusEncoder *enc;
- * enc = opus_encoder_create(Fs, channels, application, &error);
- * @endcode
- *
- * From this point, @c enc can be used for encoding an audio stream. An encoder state
- * @b must @b not be used for more than one stream at the same time. Similarly, the encoder
- * state @b must @b not be re-initialized for each frame.
- *
- * While opus_encoder_create() allocates memory for the state, it's also possible
- * to initialize pre-allocated memory:
- *
- * @code
- * int size;
- * int error;
- * OpusEncoder *enc;
- * size = opus_encoder_get_size(channels);
- * enc = malloc(size);
- * error = opus_encoder_init(enc, Fs, channels, application);
- * @endcode
- *
- * where opus_encoder_get_size() returns the required size for the encoder state. Note that
- * future versions of this code may change the size, so no assuptions should be made about it.
- *
- * The encoder state is always continuous in memory and only a shallow copy is sufficient
- * to copy it (e.g. memcpy())
- *
- * It is possible to change some of the encoder's settings using the opus_encoder_ctl()
- * interface. All these settings already default to the recommended value, so they should
- * only be changed when necessary. The most common settings one may want to change are:
- *
- * @code
- * opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate));
- * opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
- * opus_encoder_ctl(enc, OPUS_SET_SIGNAL(signal_type));
- * @endcode
- *
- * where
- *
- * @arg bitrate is in bits per second (b/s)
- * @arg complexity is a value from 1 to 10, where 1 is the lowest complexity and 10 is the highest
- * @arg signal_type is either OPUS_AUTO (default), OPUS_SIGNAL_VOICE, or OPUS_SIGNAL_MUSIC
- *
- * See @ref opus_encoderctls and @ref opus_genericctls for a complete list of parameters that can be set or queried. Most parameters can be set or changed at any time during a stream.
- *
- * To encode a frame, opus_encode() or opus_encode_float() must be called with exactly one frame (2.5, 5, 10, 20, 40 or 60 ms) of audio data:
- * @code
- * len = opus_encode(enc, audio_frame, frame_size, packet, max_packet);
- * @endcode
- *
- * where
- *
- *
audio_frame is the audio data in opus_int16 (or float for opus_encode_float())
- *
frame_size is the duration of the frame in samples (per channel)
- *
packet is the byte array to which the compressed data is written
- *
max_packet is the maximum number of bytes that can be written in the packet (4000 bytes is recommended).
- * Do not use max_packet to control VBR target bitrate, instead use the #OPUS_SET_BITRATE CTL.
- *
- *
- * opus_encode() and opus_encode_float() return the number of bytes actually written to the packet.
- * The return value can be negative, which indicates that an error has occurred. If the return value
- * is 1 byte, then the packet does not need to be transmitted (DTX).
- *
- * Once the encoder state if no longer needed, it can be destroyed with
- *
- * @code
- * opus_encoder_destroy(enc);
- * @endcode
- *
- * If the encoder was created with opus_encoder_init() rather than opus_encoder_create(),
- * then no action is required aside from potentially freeing the memory that was manually
- * allocated for it (calling free(enc) for the example above)
- *
- */
-
-/** Opus encoder state.
- * This contains the complete state of an Opus encoder.
- * It is position independent and can be freely copied.
- * @see opus_encoder_create,opus_encoder_init
- */
-typedef struct OpusEncoder OpusEncoder;
-
-/** Gets the size of an OpusEncoder structure.
- * @param[in] channels int: Number of channels.
- * This must be 1 or 2.
- * @returns The size in bytes.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_encoder_get_size(int channels);
-
-/**
- */
-
-/** Allocates and initializes an encoder state.
- * There are three coding modes:
- *
- * @ref OPUS_APPLICATION_VOIP gives best quality at a given bitrate for voice
- * signals. It enhances the input signal by high-pass filtering and
- * emphasizing formants and harmonics. Optionally it includes in-band
- * forward error correction to protect against packet loss. Use this
- * mode for typical VoIP applications. Because of the enhancement,
- * even at high bitrates the output may sound different from the input.
- *
- * @ref OPUS_APPLICATION_AUDIO gives best quality at a given bitrate for most
- * non-voice signals like music. Use this mode for music and mixed
- * (music/voice) content, broadcast, and applications requiring less
- * than 15 ms of coding delay.
- *
- * @ref OPUS_APPLICATION_RESTRICTED_LOWDELAY configures low-delay mode that
- * disables the speech-optimized mode in exchange for slightly reduced delay.
- * This mode can only be set on an newly initialized or freshly reset encoder
- * because it changes the codec delay.
- *
- * This is useful when the caller knows that the speech-optimized modes will not be needed (use with caution).
- * @param [in] Fs opus_int32: Sampling rate of input signal (Hz)
- * This must be one of 8000, 12000, 16000,
- * 24000, or 48000.
- * @param [in] channels int: Number of channels (1 or 2) in input signal
- * @param [in] application int: Coding mode (@ref OPUS_APPLICATION_VOIP/@ref OPUS_APPLICATION_AUDIO/@ref OPUS_APPLICATION_RESTRICTED_LOWDELAY)
- * @param [out] error int*: @ref opus_errorcodes
- * @note Regardless of the sampling rate and number channels selected, the Opus encoder
- * can switch to a lower audio bandwidth or number of channels if the bitrate
- * selected is too low. This also means that it is safe to always use 48 kHz stereo input
- * and let the encoder optimize the encoding.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusEncoder *opus_encoder_create(
- opus_int32 Fs,
- int channels,
- int application,
- int *error
-);
-
-/** Initializes a previously allocated encoder state
- * The memory pointed to by st must be at least the size returned by opus_encoder_get_size().
- * This is intended for applications which use their own allocator instead of malloc.
- * @see opus_encoder_create(),opus_encoder_get_size()
- * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
- * @param [in] st OpusEncoder*: Encoder state
- * @param [in] Fs opus_int32: Sampling rate of input signal (Hz)
- * This must be one of 8000, 12000, 16000,
- * 24000, or 48000.
- * @param [in] channels int: Number of channels (1 or 2) in input signal
- * @param [in] application int: Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO/OPUS_APPLICATION_RESTRICTED_LOWDELAY)
- * @retval #OPUS_OK Success or @ref opus_errorcodes
- */
-OPUS_EXPORT int opus_encoder_init(
- OpusEncoder *st,
- opus_int32 Fs,
- int channels,
- int application
-) OPUS_ARG_NONNULL(1);
-
-/** Encodes an Opus frame.
- * @param [in] st OpusEncoder*: Encoder state
- * @param [in] pcm opus_int16*: Input signal (interleaved if 2 channels). length is frame_size*channels*sizeof(opus_int16)
- * @param [in] frame_size int: Number of samples per channel in the
- * input signal.
- * This must be an Opus frame size for
- * the encoder's sampling rate.
- * For example, at 48 kHz the permitted
- * values are 120, 240, 480, 960, 1920,
- * and 2880.
- * Passing in a duration of less than
- * 10 ms (480 samples at 48 kHz) will
- * prevent the encoder from using the LPC
- * or hybrid modes.
- * @param [out] data unsigned char*: Output payload.
- * This must contain storage for at
- * least \a max_data_bytes.
- * @param [in] max_data_bytes opus_int32: Size of the allocated
- * memory for the output
- * payload. This may be
- * used to impose an upper limit on
- * the instant bitrate, but should
- * not be used as the only bitrate
- * control. Use #OPUS_SET_BITRATE to
- * control the bitrate.
- * @returns The length of the encoded packet (in bytes) on success or a
- * negative error code (see @ref opus_errorcodes) on failure.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode(
- OpusEncoder *st,
- const opus_int16 *pcm,
- int frame_size,
- unsigned char *data,
- opus_int32 max_data_bytes
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
-
-/** Encodes an Opus frame from floating point input.
- * @param [in] st OpusEncoder*: Encoder state
- * @param [in] pcm float*: Input in float format (interleaved if 2 channels), with a normal range of +/-1.0.
- * Samples with a range beyond +/-1.0 are supported but will
- * be clipped by decoders using the integer API and should
- * only be used if it is known that the far end supports
- * extended dynamic range.
- * length is frame_size*channels*sizeof(float)
- * @param [in] frame_size int: Number of samples per channel in the
- * input signal.
- * This must be an Opus frame size for
- * the encoder's sampling rate.
- * For example, at 48 kHz the permitted
- * values are 120, 240, 480, 960, 1920,
- * and 2880.
- * Passing in a duration of less than
- * 10 ms (480 samples at 48 kHz) will
- * prevent the encoder from using the LPC
- * or hybrid modes.
- * @param [out] data unsigned char*: Output payload.
- * This must contain storage for at
- * least \a max_data_bytes.
- * @param [in] max_data_bytes opus_int32: Size of the allocated
- * memory for the output
- * payload. This may be
- * used to impose an upper limit on
- * the instant bitrate, but should
- * not be used as the only bitrate
- * control. Use #OPUS_SET_BITRATE to
- * control the bitrate.
- * @returns The length of the encoded packet (in bytes) on success or a
- * negative error code (see @ref opus_errorcodes) on failure.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode_float(
- OpusEncoder *st,
- const float *pcm,
- int frame_size,
- unsigned char *data,
- opus_int32 max_data_bytes
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
-
-/** Frees an OpusEncoder allocated by opus_encoder_create().
- * @param[in] st OpusEncoder*: State to be freed.
- */
-OPUS_EXPORT void opus_encoder_destroy(OpusEncoder *st);
-
-/** Perform a CTL function on an Opus encoder.
- *
- * Generally the request and subsequent arguments are generated
- * by a convenience macro.
- * @param st OpusEncoder*: Encoder state.
- * @param request This and all remaining parameters should be replaced by one
- * of the convenience macros in @ref opus_genericctls or
- * @ref opus_encoderctls.
- * @see opus_genericctls
- * @see opus_encoderctls
- */
-OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
-/**@}*/
-
-/** @defgroup opus_decoder Opus Decoder
- * @{
- *
- * @brief This page describes the process and functions used to decode Opus.
- *
- * The decoding process also starts with creating a decoder
- * state. This can be done with:
- * @code
- * int error;
- * OpusDecoder *dec;
- * dec = opus_decoder_create(Fs, channels, &error);
- * @endcode
- * where
- * @li Fs is the sampling rate and must be 8000, 12000, 16000, 24000, or 48000
- * @li channels is the number of channels (1 or 2)
- * @li error will hold the error code in case of failure (or #OPUS_OK on success)
- * @li the return value is a newly created decoder state to be used for decoding
- *
- * While opus_decoder_create() allocates memory for the state, it's also possible
- * to initialize pre-allocated memory:
- * @code
- * int size;
- * int error;
- * OpusDecoder *dec;
- * size = opus_decoder_get_size(channels);
- * dec = malloc(size);
- * error = opus_decoder_init(dec, Fs, channels);
- * @endcode
- * where opus_decoder_get_size() returns the required size for the decoder state. Note that
- * future versions of this code may change the size, so no assuptions should be made about it.
- *
- * The decoder state is always continuous in memory and only a shallow copy is sufficient
- * to copy it (e.g. memcpy())
- *
- * To decode a frame, opus_decode() or opus_decode_float() must be called with a packet of compressed audio data:
- * @code
- * frame_size = opus_decode(dec, packet, len, decoded, max_size, 0);
- * @endcode
- * where
- *
- * @li packet is the byte array containing the compressed data
- * @li len is the exact number of bytes contained in the packet
- * @li decoded is the decoded audio data in opus_int16 (or float for opus_decode_float())
- * @li max_size is the max duration of the frame in samples (per channel) that can fit into the decoded_frame array
- *
- * opus_decode() and opus_decode_float() return the number of samples (per channel) decoded from the packet.
- * If that value is negative, then an error has occurred. This can occur if the packet is corrupted or if the audio
- * buffer is too small to hold the decoded audio.
- *
- * Opus is a stateful codec with overlapping blocks and as a result Opus
- * packets are not coded independently of each other. Packets must be
- * passed into the decoder serially and in the correct order for a correct
- * decode. Lost packets can be replaced with loss concealment by calling
- * the decoder with a null pointer and zero length for the missing packet.
- *
- * A single codec state may only be accessed from a single thread at
- * a time and any required locking must be performed by the caller. Separate
- * streams must be decoded with separate decoder states and can be decoded
- * in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK
- * defined.
- *
- */
-
-/** Opus decoder state.
- * This contains the complete state of an Opus decoder.
- * It is position independent and can be freely copied.
- * @see opus_decoder_create,opus_decoder_init
- */
-typedef struct OpusDecoder OpusDecoder;
-
-/** Gets the size of an OpusDecoder structure.
- * @param [in] channels int: Number of channels.
- * This must be 1 or 2.
- * @returns The size in bytes.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_size(int channels);
-
-/** Allocates and initializes a decoder state.
- * @param [in] Fs opus_int32: Sample rate to decode at (Hz).
- * This must be one of 8000, 12000, 16000,
- * 24000, or 48000.
- * @param [in] channels int: Number of channels (1 or 2) to decode
- * @param [out] error int*: #OPUS_OK Success or @ref opus_errorcodes
- *
- * Internally Opus stores data at 48000 Hz, so that should be the default
- * value for Fs. However, the decoder can efficiently decode to buffers
- * at 8, 12, 16, and 24 kHz so if for some reason the caller cannot use
- * data at the full sample rate, or knows the compressed data doesn't
- * use the full frequency range, it can request decoding at a reduced
- * rate. Likewise, the decoder is capable of filling in either mono or
- * interleaved stereo pcm buffers, at the caller's request.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusDecoder *opus_decoder_create(
- opus_int32 Fs,
- int channels,
- int *error
-);
-
-/** Initializes a previously allocated decoder state.
- * The state must be at least the size returned by opus_decoder_get_size().
- * This is intended for applications which use their own allocator instead of malloc. @see opus_decoder_create,opus_decoder_get_size
- * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
- * @param [in] st OpusDecoder*: Decoder state.
- * @param [in] Fs opus_int32: Sampling rate to decode to (Hz).
- * This must be one of 8000, 12000, 16000,
- * 24000, or 48000.
- * @param [in] channels int: Number of channels (1 or 2) to decode
- * @retval #OPUS_OK Success or @ref opus_errorcodes
- */
-OPUS_EXPORT int opus_decoder_init(
- OpusDecoder *st,
- opus_int32 Fs,
- int channels
-) OPUS_ARG_NONNULL(1);
-
-/** Decode an Opus packet.
- * @param [in] st OpusDecoder*: Decoder state
- * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss
- * @param [in] len opus_int32: Number of bytes in payload*
- * @param [out] pcm opus_int16*: Output signal (interleaved if 2 channels). length
- * is frame_size*channels*sizeof(opus_int16)
- * @param [in] frame_size Number of samples per channel of available space in \a pcm.
- * If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will
- * not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1),
- * then frame_size needs to be exactly the duration of audio that is missing, otherwise the
- * decoder will not be in the optimal state to decode the next incoming packet. For the PLC and
- * FEC cases, frame_size must be a multiple of 2.5 ms.
- * @param [in] decode_fec int: Flag (0 or 1) to request that any in-band forward error correction data be
- * decoded. If no such data is available, the frame is decoded as if it were lost.
- * @returns Number of decoded samples or @ref opus_errorcodes
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode(
- OpusDecoder *st,
- const unsigned char *data,
- opus_int32 len,
- opus_int16 *pcm,
- int frame_size,
- int decode_fec
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
-
-/** Decode an Opus packet with floating point output.
- * @param [in] st OpusDecoder*: Decoder state
- * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss
- * @param [in] len opus_int32: Number of bytes in payload
- * @param [out] pcm float*: Output signal (interleaved if 2 channels). length
- * is frame_size*channels*sizeof(float)
- * @param [in] frame_size Number of samples per channel of available space in \a pcm.
- * If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will
- * not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1),
- * then frame_size needs to be exactly the duration of audio that is missing, otherwise the
- * decoder will not be in the optimal state to decode the next incoming packet. For the PLC and
- * FEC cases, frame_size must be a multiple of 2.5 ms.
- * @param [in] decode_fec int: Flag (0 or 1) to request that any in-band forward error correction data be
- * decoded. If no such data is available the frame is decoded as if it were lost.
- * @returns Number of decoded samples or @ref opus_errorcodes
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode_float(
- OpusDecoder *st,
- const unsigned char *data,
- opus_int32 len,
- float *pcm,
- int frame_size,
- int decode_fec
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
-
-/** Perform a CTL function on an Opus decoder.
- *
- * Generally the request and subsequent arguments are generated
- * by a convenience macro.
- * @param st OpusDecoder*: Decoder state.
- * @param request This and all remaining parameters should be replaced by one
- * of the convenience macros in @ref opus_genericctls or
- * @ref opus_decoderctls.
- * @see opus_genericctls
- * @see opus_decoderctls
- */
-OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
-
-/** Frees an OpusDecoder allocated by opus_decoder_create().
- * @param[in] st OpusDecoder*: State to be freed.
- */
-OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st);
-
-/** Parse an opus packet into one or more frames.
- * Opus_decode will perform this operation internally so most applications do
- * not need to use this function.
- * This function does not copy the frames, the returned pointers are pointers into
- * the input packet.
- * @param [in] data char*: Opus packet to be parsed
- * @param [in] len opus_int32: size of data
- * @param [out] out_toc char*: TOC pointer
- * @param [out] frames char*[48] encapsulated frames
- * @param [out] size opus_int16[48] sizes of the encapsulated frames
- * @param [out] payload_offset int*: returns the position of the payload within the packet (in bytes)
- * @returns number of frames
- */
-OPUS_EXPORT int opus_packet_parse(
- const unsigned char *data,
- opus_int32 len,
- unsigned char *out_toc,
- const unsigned char *frames[48],
- opus_int16 size[48],
- int *payload_offset
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
-
-/** Gets the bandwidth of an Opus packet.
- * @param [in] data char*: Opus packet
- * @retval OPUS_BANDWIDTH_NARROWBAND Narrowband (4kHz bandpass)
- * @retval OPUS_BANDWIDTH_MEDIUMBAND Mediumband (6kHz bandpass)
- * @retval OPUS_BANDWIDTH_WIDEBAND Wideband (8kHz bandpass)
- * @retval OPUS_BANDWIDTH_SUPERWIDEBAND Superwideband (12kHz bandpass)
- * @retval OPUS_BANDWIDTH_FULLBAND Fullband (20kHz bandpass)
- * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_bandwidth(const unsigned char *data) OPUS_ARG_NONNULL(1);
-
-/** Gets the number of samples per frame from an Opus packet.
- * @param [in] data char*: Opus packet.
- * This must contain at least one byte of
- * data.
- * @param [in] Fs opus_int32: Sampling rate in Hz.
- * This must be a multiple of 400, or
- * inaccurate results will be returned.
- * @returns Number of samples per frame.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_samples_per_frame(const unsigned char *data, opus_int32 Fs) OPUS_ARG_NONNULL(1);
-
-/** Gets the number of channels from an Opus packet.
- * @param [in] data char*: Opus packet
- * @returns Number of channels
- * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_channels(const unsigned char *data) OPUS_ARG_NONNULL(1);
-
-/** Gets the number of frames in an Opus packet.
- * @param [in] packet char*: Opus packet
- * @param [in] len opus_int32: Length of packet
- * @returns Number of frames
- * @retval OPUS_BAD_ARG Insufficient data was passed to the function
- * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1);
-
-/** Gets the number of samples of an Opus packet.
- * @param [in] packet char*: Opus packet
- * @param [in] len opus_int32: Length of packet
- * @param [in] Fs opus_int32: Sampling rate in Hz.
- * This must be a multiple of 400, or
- * inaccurate results will be returned.
- * @returns Number of samples
- * @retval OPUS_BAD_ARG Insufficient data was passed to the function
- * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len, opus_int32 Fs) OPUS_ARG_NONNULL(1);
-
-/** Gets the number of samples of an Opus packet.
- * @param [in] dec OpusDecoder*: Decoder state
- * @param [in] packet char*: Opus packet
- * @param [in] len opus_int32: Length of packet
- * @returns Number of samples
- * @retval OPUS_BAD_ARG Insufficient data was passed to the function
- * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
-
-/** Applies soft-clipping to bring a float signal within the [-1,1] range. If
- * the signal is already in that range, nothing is done. If there are values
- * outside of [-1,1], then the signal is clipped as smoothly as possible to
- * both fit in the range and avoid creating excessive distortion in the
- * process.
- * @param [in,out] pcm float*: Input PCM and modified PCM
- * @param [in] frame_size int Number of samples per channel to process
- * @param [in] channels int: Number of channels
- * @param [in,out] softclip_mem float*: State memory for the soft clipping process (one float per channel, initialized to zero)
- */
-OPUS_EXPORT void opus_pcm_soft_clip(float *pcm, int frame_size, int channels, float *softclip_mem);
-
-
-/**@}*/
-
-/** @defgroup opus_repacketizer Repacketizer
- * @{
- *
- * The repacketizer can be used to merge multiple Opus packets into a single
- * packet or alternatively to split Opus packets that have previously been
- * merged. Splitting valid Opus packets is always guaranteed to succeed,
- * whereas merging valid packets only succeeds if all frames have the same
- * mode, bandwidth, and frame size, and when the total duration of the merged
- * packet is no more than 120 ms.
- * The repacketizer currently only operates on elementary Opus
- * streams. It will not manipualte multistream packets successfully, except in
- * the degenerate case where they consist of data from a single stream.
- *
- * The repacketizing process starts with creating a repacketizer state, either
- * by calling opus_repacketizer_create() or by allocating the memory yourself,
- * e.g.,
- * @code
- * OpusRepacketizer *rp;
- * rp = (OpusRepacketizer*)malloc(opus_repacketizer_get_size());
- * if (rp != NULL)
- * opus_repacketizer_init(rp);
- * @endcode
- *
- * Then the application should submit packets with opus_repacketizer_cat(),
- * extract new packets with opus_repacketizer_out() or
- * opus_repacketizer_out_range(), and then reset the state for the next set of
- * input packets via opus_repacketizer_init().
- *
- * For example, to split a sequence of packets into individual frames:
- * @code
- * unsigned char *data;
- * int len;
- * while (get_next_packet(&data, &len))
- * {
- * unsigned char out[1276];
- * opus_int32 out_len;
- * int nb_frames;
- * int err;
- * int i;
- * err = opus_repacketizer_cat(rp, data, len);
- * if (err != OPUS_OK)
- * {
- * release_packet(data);
- * return err;
- * }
- * nb_frames = opus_repacketizer_get_nb_frames(rp);
- * for (i = 0; i < nb_frames; i++)
- * {
- * out_len = opus_repacketizer_out_range(rp, i, i+1, out, sizeof(out));
- * if (out_len < 0)
- * {
- * release_packet(data);
- * return (int)out_len;
- * }
- * output_next_packet(out, out_len);
- * }
- * opus_repacketizer_init(rp);
- * release_packet(data);
- * }
- * @endcode
- *
- * Alternatively, to combine a sequence of frames into packets that each
- * contain up to TARGET_DURATION_MS milliseconds of data:
- * @code
- * // The maximum number of packets with duration TARGET_DURATION_MS occurs
- * // when the frame size is 2.5 ms, for a total of (TARGET_DURATION_MS*2/5)
- * // packets.
- * unsigned char *data[(TARGET_DURATION_MS*2/5)+1];
- * opus_int32 len[(TARGET_DURATION_MS*2/5)+1];
- * int nb_packets;
- * unsigned char out[1277*(TARGET_DURATION_MS*2/2)];
- * opus_int32 out_len;
- * int prev_toc;
- * nb_packets = 0;
- * while (get_next_packet(data+nb_packets, len+nb_packets))
- * {
- * int nb_frames;
- * int err;
- * nb_frames = opus_packet_get_nb_frames(data[nb_packets], len[nb_packets]);
- * if (nb_frames < 1)
- * {
- * release_packets(data, nb_packets+1);
- * return nb_frames;
- * }
- * nb_frames += opus_repacketizer_get_nb_frames(rp);
- * // If adding the next packet would exceed our target, or it has an
- * // incompatible TOC sequence, output the packets we already have before
- * // submitting it.
- * // N.B., The nb_packets > 0 check ensures we've submitted at least one
- * // packet since the last call to opus_repacketizer_init(). Otherwise a
- * // single packet longer than TARGET_DURATION_MS would cause us to try to
- * // output an (invalid) empty packet. It also ensures that prev_toc has
- * // been set to a valid value. Additionally, len[nb_packets] > 0 is
- * // guaranteed by the call to opus_packet_get_nb_frames() above, so the
- * // reference to data[nb_packets][0] should be valid.
- * if (nb_packets > 0 && (
- * ((prev_toc & 0xFC) != (data[nb_packets][0] & 0xFC)) ||
- * opus_packet_get_samples_per_frame(data[nb_packets], 48000)*nb_frames >
- * TARGET_DURATION_MS*48))
- * {
- * out_len = opus_repacketizer_out(rp, out, sizeof(out));
- * if (out_len < 0)
- * {
- * release_packets(data, nb_packets+1);
- * return (int)out_len;
- * }
- * output_next_packet(out, out_len);
- * opus_repacketizer_init(rp);
- * release_packets(data, nb_packets);
- * data[0] = data[nb_packets];
- * len[0] = len[nb_packets];
- * nb_packets = 0;
- * }
- * err = opus_repacketizer_cat(rp, data[nb_packets], len[nb_packets]);
- * if (err != OPUS_OK)
- * {
- * release_packets(data, nb_packets+1);
- * return err;
- * }
- * prev_toc = data[nb_packets][0];
- * nb_packets++;
- * }
- * // Output the final, partial packet.
- * if (nb_packets > 0)
- * {
- * out_len = opus_repacketizer_out(rp, out, sizeof(out));
- * release_packets(data, nb_packets);
- * if (out_len < 0)
- * return (int)out_len;
- * output_next_packet(out, out_len);
- * }
- * @endcode
- *
- * An alternate way of merging packets is to simply call opus_repacketizer_cat()
- * unconditionally until it fails. At that point, the merged packet can be
- * obtained with opus_repacketizer_out() and the input packet for which
- * opus_repacketizer_cat() needs to be re-added to a newly reinitialized
- * repacketizer state.
- */
-
-typedef struct OpusRepacketizer OpusRepacketizer;
-
-/** Gets the size of an OpusRepacketizer structure.
- * @returns The size in bytes.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_size(void);
-
-/** (Re)initializes a previously allocated repacketizer state.
- * The state must be at least the size returned by opus_repacketizer_get_size().
- * This can be used for applications which use their own allocator instead of
- * malloc().
- * It must also be called to reset the queue of packets waiting to be
- * repacketized, which is necessary if the maximum packet duration of 120 ms
- * is reached or if you wish to submit packets with a different Opus
- * configuration (coding mode, audio bandwidth, frame size, or channel count).
- * Failure to do so will prevent a new packet from being added with
- * opus_repacketizer_cat().
- * @see opus_repacketizer_create
- * @see opus_repacketizer_get_size
- * @see opus_repacketizer_cat
- * @param rp OpusRepacketizer*: The repacketizer state to
- * (re)initialize.
- * @returns A pointer to the same repacketizer state that was passed in.
- */
-OPUS_EXPORT OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1);
-
-/** Allocates memory and initializes the new repacketizer with
- * opus_repacketizer_init().
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusRepacketizer *opus_repacketizer_create(void);
-
-/** Frees an OpusRepacketizer allocated by
- * opus_repacketizer_create().
- * @param[in] rp OpusRepacketizer*: State to be freed.
- */
-OPUS_EXPORT void opus_repacketizer_destroy(OpusRepacketizer *rp);
-
-/** Add a packet to the current repacketizer state.
- * This packet must match the configuration of any packets already submitted
- * for repacketization since the last call to opus_repacketizer_init().
- * This means that it must have the same coding mode, audio bandwidth, frame
- * size, and channel count.
- * This can be checked in advance by examining the top 6 bits of the first
- * byte of the packet, and ensuring they match the top 6 bits of the first
- * byte of any previously submitted packet.
- * The total duration of audio in the repacketizer state also must not exceed
- * 120 ms, the maximum duration of a single packet, after adding this packet.
- *
- * The contents of the current repacketizer state can be extracted into new
- * packets using opus_repacketizer_out() or opus_repacketizer_out_range().
- *
- * In order to add a packet with a different configuration or to add more
- * audio beyond 120 ms, you must clear the repacketizer state by calling
- * opus_repacketizer_init().
- * If a packet is too large to add to the current repacketizer state, no part
- * of it is added, even if it contains multiple frames, some of which might
- * fit.
- * If you wish to be able to add parts of such packets, you should first use
- * another repacketizer to split the packet into pieces and add them
- * individually.
- * @see opus_repacketizer_out_range
- * @see opus_repacketizer_out
- * @see opus_repacketizer_init
- * @param rp OpusRepacketizer*: The repacketizer state to which to
- * add the packet.
- * @param[in] data const unsigned char*: The packet data.
- * The application must ensure
- * this pointer remains valid
- * until the next call to
- * opus_repacketizer_init() or
- * opus_repacketizer_destroy().
- * @param len opus_int32: The number of bytes in the packet data.
- * @returns An error code indicating whether or not the operation succeeded.
- * @retval #OPUS_OK The packet's contents have been added to the repacketizer
- * state.
- * @retval #OPUS_INVALID_PACKET The packet did not have a valid TOC sequence,
- * the packet's TOC sequence was not compatible
- * with previously submitted packets (because
- * the coding mode, audio bandwidth, frame size,
- * or channel count did not match), or adding
- * this packet would increase the total amount of
- * audio stored in the repacketizer state to more
- * than 120 ms.
- */
-OPUS_EXPORT int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
-
-
-/** Construct a new packet from data previously submitted to the repacketizer
- * state via opus_repacketizer_cat().
- * @param rp OpusRepacketizer*: The repacketizer state from which to
- * construct the new packet.
- * @param begin int: The index of the first frame in the current
- * repacketizer state to include in the output.
- * @param end int: One past the index of the last frame in the
- * current repacketizer state to include in the
- * output.
- * @param[out] data const unsigned char*: The buffer in which to
- * store the output packet.
- * @param maxlen opus_int32: The maximum number of bytes to store in
- * the output buffer. In order to guarantee
- * success, this should be at least
- * 1276 for a single frame,
- * or for multiple frames,
- * 1277*(end-begin).
- * However, 1*(end-begin) plus
- * the size of all packet data submitted to
- * the repacketizer since the last call to
- * opus_repacketizer_init() or
- * opus_repacketizer_create() is also
- * sufficient, and possibly much smaller.
- * @returns The total size of the output packet on success, or an error code
- * on failure.
- * @retval #OPUS_BAD_ARG [begin,end) was an invalid range of
- * frames (begin < 0, begin >= end, or end >
- * opus_repacketizer_get_nb_frames()).
- * @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the
- * complete output packet.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
-
-/** Return the total number of frames contained in packet data submitted to
- * the repacketizer state so far via opus_repacketizer_cat() since the last
- * call to opus_repacketizer_init() or opus_repacketizer_create().
- * This defines the valid range of packets that can be extracted with
- * opus_repacketizer_out_range() or opus_repacketizer_out().
- * @param rp OpusRepacketizer*: The repacketizer state containing the
- * frames.
- * @returns The total number of frames contained in the packet data submitted
- * to the repacketizer state.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1);
-
-/** Construct a new packet from data previously submitted to the repacketizer
- * state via opus_repacketizer_cat().
- * This is a convenience routine that returns all the data submitted so far
- * in a single packet.
- * It is equivalent to calling
- * @code
- * opus_repacketizer_out_range(rp, 0, opus_repacketizer_get_nb_frames(rp),
- * data, maxlen)
- * @endcode
- * @param rp OpusRepacketizer*: The repacketizer state from which to
- * construct the new packet.
- * @param[out] data const unsigned char*: The buffer in which to
- * store the output packet.
- * @param maxlen opus_int32: The maximum number of bytes to store in
- * the output buffer. In order to guarantee
- * success, this should be at least
- * 1277*opus_repacketizer_get_nb_frames(rp).
- * However,
- * 1*opus_repacketizer_get_nb_frames(rp)
- * plus the size of all packet data
- * submitted to the repacketizer since the
- * last call to opus_repacketizer_init() or
- * opus_repacketizer_create() is also
- * sufficient, and possibly much smaller.
- * @returns The total size of the output packet on success, or an error code
- * on failure.
- * @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the
- * complete output packet.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1);
-
-/** Pads a given Opus packet to a larger size (possibly changing the TOC sequence).
- * @param[in,out] data const unsigned char*: The buffer containing the
- * packet to pad.
- * @param len opus_int32: The size of the packet.
- * This must be at least 1.
- * @param new_len opus_int32: The desired size of the packet after padding.
- * This must be at least as large as len.
- * @returns an error code
- * @retval #OPUS_OK \a on success.
- * @retval #OPUS_BAD_ARG \a len was less than 1 or new_len was less than len.
- * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
- */
-OPUS_EXPORT int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len);
-
-/** Remove all padding from a given Opus packet and rewrite the TOC sequence to
- * minimize space usage.
- * @param[in,out] data const unsigned char*: The buffer containing the
- * packet to strip.
- * @param len opus_int32: The size of the packet.
- * This must be at least 1.
- * @returns The new size of the output packet on success, or an error code
- * on failure.
- * @retval #OPUS_BAD_ARG \a len was less than 1.
- * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len);
-
-/** Pads a given Opus multi-stream packet to a larger size (possibly changing the TOC sequence).
- * @param[in,out] data const unsigned char*: The buffer containing the
- * packet to pad.
- * @param len opus_int32: The size of the packet.
- * This must be at least 1.
- * @param new_len opus_int32: The desired size of the packet after padding.
- * This must be at least 1.
- * @param nb_streams opus_int32: The number of streams (not channels) in the packet.
- * This must be at least as large as len.
- * @returns an error code
- * @retval #OPUS_OK \a on success.
- * @retval #OPUS_BAD_ARG \a len was less than 1.
- * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
- */
-OPUS_EXPORT int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len, int nb_streams);
-
-/** Remove all padding from a given Opus multi-stream packet and rewrite the TOC sequence to
- * minimize space usage.
- * @param[in,out] data const unsigned char*: The buffer containing the
- * packet to strip.
- * @param len opus_int32: The size of the packet.
- * This must be at least 1.
- * @param nb_streams opus_int32: The number of streams (not channels) in the packet.
- * This must be at least 1.
- * @returns The new size of the output packet on success, or an error code
- * on failure.
- * @retval #OPUS_BAD_ARG \a len was less than 1 or new_len was less than len.
- * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, int nb_streams);
-
-/**@}*/
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* OPUS_H */
diff --git a/app/src/main/jni/nv_opus_dec/libopus/inc/opus_custom.h b/app/src/main/jni/nv_opus_dec/libopus/inc/opus_custom.h
deleted file mode 100644
index 41f36bf2..00000000
--- a/app/src/main/jni/nv_opus_dec/libopus/inc/opus_custom.h
+++ /dev/null
@@ -1,342 +0,0 @@
-/* Copyright (c) 2007-2008 CSIRO
- Copyright (c) 2007-2009 Xiph.Org Foundation
- Copyright (c) 2008-2012 Gregory Maxwell
- Written by Jean-Marc Valin and Gregory Maxwell */
-/*
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/**
- @file opus_custom.h
- @brief Opus-Custom reference implementation API
- */
-
-#ifndef OPUS_CUSTOM_H
-#define OPUS_CUSTOM_H
-
-#include "opus_defines.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef CUSTOM_MODES
-# define OPUS_CUSTOM_EXPORT OPUS_EXPORT
-# define OPUS_CUSTOM_EXPORT_STATIC OPUS_EXPORT
-#else
-# define OPUS_CUSTOM_EXPORT
-# ifdef OPUS_BUILD
-# define OPUS_CUSTOM_EXPORT_STATIC static OPUS_INLINE
-# else
-# define OPUS_CUSTOM_EXPORT_STATIC
-# endif
-#endif
-
-/** @defgroup opus_custom Opus Custom
- * @{
- * Opus Custom is an optional part of the Opus specification and
- * reference implementation which uses a distinct API from the regular
- * API and supports frame sizes that are not normally supported.\ Use
- * of Opus Custom is discouraged for all but very special applications
- * for which a frame size different from 2.5, 5, 10, or 20 ms is needed
- * (for either complexity or latency reasons) and where interoperability
- * is less important.
- *
- * In addition to the interoperability limitations the use of Opus custom
- * disables a substantial chunk of the codec and generally lowers the
- * quality available at a given bitrate. Normally when an application needs
- * a different frame size from the codec it should buffer to match the
- * sizes but this adds a small amount of delay which may be important
- * in some very low latency applications. Some transports (especially
- * constant rate RF transports) may also work best with frames of
- * particular durations.
- *
- * Libopus only supports custom modes if they are enabled at compile time.
- *
- * The Opus Custom API is similar to the regular API but the
- * @ref opus_encoder_create and @ref opus_decoder_create calls take
- * an additional mode parameter which is a structure produced by
- * a call to @ref opus_custom_mode_create. Both the encoder and decoder
- * must create a mode using the same sample rate (fs) and frame size
- * (frame size) so these parameters must either be signaled out of band
- * or fixed in a particular implementation.
- *
- * Similar to regular Opus the custom modes support on the fly frame size
- * switching, but the sizes available depend on the particular frame size in
- * use. For some initial frame sizes on a single on the fly size is available.
- */
-
-/** Contains the state of an encoder. One encoder state is needed
- for each stream. It is initialized once at the beginning of the
- stream. Do *not* re-initialize the state for every frame.
- @brief Encoder state
- */
-typedef struct OpusCustomEncoder OpusCustomEncoder;
-
-/** State of the decoder. One decoder state is needed for each stream.
- It is initialized once at the beginning of the stream. Do *not*
- re-initialize the state for every frame.
- @brief Decoder state
- */
-typedef struct OpusCustomDecoder OpusCustomDecoder;
-
-/** The mode contains all the information necessary to create an
- encoder. Both the encoder and decoder need to be initialized
- with exactly the same mode, otherwise the output will be
- corrupted.
- @brief Mode configuration
- */
-typedef struct OpusCustomMode OpusCustomMode;
-
-/** Creates a new mode struct. This will be passed to an encoder or
- * decoder. The mode MUST NOT BE DESTROYED until the encoders and
- * decoders that use it are destroyed as well.
- * @param [in] Fs int: Sampling rate (8000 to 96000 Hz)
- * @param [in] frame_size int: Number of samples (per channel) to encode in each
- * packet (64 - 1024, prime factorization must contain zero or more 2s, 3s, or 5s and no other primes)
- * @param [out] error int*: Returned error code (if NULL, no error will be returned)
- * @return A newly created mode
- */
-OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error);
-
-/** Destroys a mode struct. Only call this after all encoders and
- * decoders using this mode are destroyed as well.
- * @param [in] mode OpusCustomMode*: Mode to be freed.
- */
-OPUS_CUSTOM_EXPORT void opus_custom_mode_destroy(OpusCustomMode *mode);
-
-
-#if !defined(OPUS_BUILD) || defined(CELT_ENCODER_C)
-
-/* Encoder */
-/** Gets the size of an OpusCustomEncoder structure.
- * @param [in] mode OpusCustomMode *: Mode configuration
- * @param [in] channels int: Number of channels
- * @returns size
- */
-OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_encoder_get_size(
- const OpusCustomMode *mode,
- int channels
-) OPUS_ARG_NONNULL(1);
-
-# ifdef CUSTOM_MODES
-/** Initializes a previously allocated encoder state
- * The memory pointed to by st must be the size returned by opus_custom_encoder_get_size.
- * This is intended for applications which use their own allocator instead of malloc.
- * @see opus_custom_encoder_create(),opus_custom_encoder_get_size()
- * To reset a previously initialized state use the OPUS_RESET_STATE CTL.
- * @param [in] st OpusCustomEncoder*: Encoder state
- * @param [in] mode OpusCustomMode *: Contains all the information about the characteristics of
- * the stream (must be the same characteristics as used for the
- * decoder)
- * @param [in] channels int: Number of channels
- * @return OPUS_OK Success or @ref opus_errorcodes
- */
-OPUS_CUSTOM_EXPORT int opus_custom_encoder_init(
- OpusCustomEncoder *st,
- const OpusCustomMode *mode,
- int channels
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
-# endif
-#endif
-
-
-/** Creates a new encoder state. Each stream needs its own encoder
- * state (can't be shared across simultaneous streams).
- * @param [in] mode OpusCustomMode*: Contains all the information about the characteristics of
- * the stream (must be the same characteristics as used for the
- * decoder)
- * @param [in] channels int: Number of channels
- * @param [out] error int*: Returns an error code
- * @return Newly created encoder state.
-*/
-OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomEncoder *opus_custom_encoder_create(
- const OpusCustomMode *mode,
- int channels,
- int *error
-) OPUS_ARG_NONNULL(1);
-
-
-/** Destroys a an encoder state.
- * @param[in] st OpusCustomEncoder*: State to be freed.
- */
-OPUS_CUSTOM_EXPORT void opus_custom_encoder_destroy(OpusCustomEncoder *st);
-
-/** Encodes a frame of audio.
- * @param [in] st OpusCustomEncoder*: Encoder state
- * @param [in] pcm float*: PCM audio in float format, with a normal range of +/-1.0.
- * Samples with a range beyond +/-1.0 are supported but will
- * be clipped by decoders using the integer API and should
- * only be used if it is known that the far end supports
- * extended dynamic range. There must be exactly
- * frame_size samples per channel.
- * @param [in] frame_size int: Number of samples per frame of input signal
- * @param [out] compressed char *: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
- * @param [in] maxCompressedBytes int: Maximum number of bytes to use for compressing the frame
- * (can change from one frame to another)
- * @return Number of bytes written to "compressed".
- * If negative, an error has occurred (see error codes). It is IMPORTANT that
- * the length returned be somehow transmitted to the decoder. Otherwise, no
- * decoding is possible.
- */
-OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode_float(
- OpusCustomEncoder *st,
- const float *pcm,
- int frame_size,
- unsigned char *compressed,
- int maxCompressedBytes
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
-
-/** Encodes a frame of audio.
- * @param [in] st OpusCustomEncoder*: Encoder state
- * @param [in] pcm opus_int16*: PCM audio in signed 16-bit format (native endian).
- * There must be exactly frame_size samples per channel.
- * @param [in] frame_size int: Number of samples per frame of input signal
- * @param [out] compressed char *: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
- * @param [in] maxCompressedBytes int: Maximum number of bytes to use for compressing the frame
- * (can change from one frame to another)
- * @return Number of bytes written to "compressed".
- * If negative, an error has occurred (see error codes). It is IMPORTANT that
- * the length returned be somehow transmitted to the decoder. Otherwise, no
- * decoding is possible.
- */
-OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode(
- OpusCustomEncoder *st,
- const opus_int16 *pcm,
- int frame_size,
- unsigned char *compressed,
- int maxCompressedBytes
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
-
-/** Perform a CTL function on an Opus custom encoder.
- *
- * Generally the request and subsequent arguments are generated
- * by a convenience macro.
- * @see opus_encoderctls
- */
-OPUS_CUSTOM_EXPORT int opus_custom_encoder_ctl(OpusCustomEncoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
-
-
-#if !defined(OPUS_BUILD) || defined(CELT_DECODER_C)
-/* Decoder */
-
-/** Gets the size of an OpusCustomDecoder structure.
- * @param [in] mode OpusCustomMode *: Mode configuration
- * @param [in] channels int: Number of channels
- * @returns size
- */
-OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_decoder_get_size(
- const OpusCustomMode *mode,
- int channels
-) OPUS_ARG_NONNULL(1);
-
-/** Initializes a previously allocated decoder state
- * The memory pointed to by st must be the size returned by opus_custom_decoder_get_size.
- * This is intended for applications which use their own allocator instead of malloc.
- * @see opus_custom_decoder_create(),opus_custom_decoder_get_size()
- * To reset a previously initialized state use the OPUS_RESET_STATE CTL.
- * @param [in] st OpusCustomDecoder*: Decoder state
- * @param [in] mode OpusCustomMode *: Contains all the information about the characteristics of
- * the stream (must be the same characteristics as used for the
- * encoder)
- * @param [in] channels int: Number of channels
- * @return OPUS_OK Success or @ref opus_errorcodes
- */
-OPUS_CUSTOM_EXPORT_STATIC int opus_custom_decoder_init(
- OpusCustomDecoder *st,
- const OpusCustomMode *mode,
- int channels
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
-
-#endif
-
-
-/** Creates a new decoder state. Each stream needs its own decoder state (can't
- * be shared across simultaneous streams).
- * @param [in] mode OpusCustomMode: Contains all the information about the characteristics of the
- * stream (must be the same characteristics as used for the encoder)
- * @param [in] channels int: Number of channels
- * @param [out] error int*: Returns an error code
- * @return Newly created decoder state.
- */
-OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomDecoder *opus_custom_decoder_create(
- const OpusCustomMode *mode,
- int channels,
- int *error
-) OPUS_ARG_NONNULL(1);
-
-/** Destroys a an decoder state.
- * @param[in] st OpusCustomDecoder*: State to be freed.
- */
-OPUS_CUSTOM_EXPORT void opus_custom_decoder_destroy(OpusCustomDecoder *st);
-
-/** Decode an opus custom frame with floating point output
- * @param [in] st OpusCustomDecoder*: Decoder state
- * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss
- * @param [in] len int: Number of bytes in payload
- * @param [out] pcm float*: Output signal (interleaved if 2 channels). length
- * is frame_size*channels*sizeof(float)
- * @param [in] frame_size Number of samples per channel of available space in *pcm.
- * @returns Number of decoded samples or @ref opus_errorcodes
- */
-OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode_float(
- OpusCustomDecoder *st,
- const unsigned char *data,
- int len,
- float *pcm,
- int frame_size
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
-
-/** Decode an opus custom frame
- * @param [in] st OpusCustomDecoder*: Decoder state
- * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss
- * @param [in] len int: Number of bytes in payload
- * @param [out] pcm opus_int16*: Output signal (interleaved if 2 channels). length
- * is frame_size*channels*sizeof(opus_int16)
- * @param [in] frame_size Number of samples per channel of available space in *pcm.
- * @returns Number of decoded samples or @ref opus_errorcodes
- */
-OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode(
- OpusCustomDecoder *st,
- const unsigned char *data,
- int len,
- opus_int16 *pcm,
- int frame_size
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
-
-/** Perform a CTL function on an Opus custom decoder.
- *
- * Generally the request and subsequent arguments are generated
- * by a convenience macro.
- * @see opus_genericctls
- */
-OPUS_CUSTOM_EXPORT int opus_custom_decoder_ctl(OpusCustomDecoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
-
-/**@}*/
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* OPUS_CUSTOM_H */
diff --git a/app/src/main/jni/nv_opus_dec/libopus/inc/opus_defines.h b/app/src/main/jni/nv_opus_dec/libopus/inc/opus_defines.h
deleted file mode 100644
index 32b7c976..00000000
--- a/app/src/main/jni/nv_opus_dec/libopus/inc/opus_defines.h
+++ /dev/null
@@ -1,726 +0,0 @@
-/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited
- Written by Jean-Marc Valin and Koen Vos */
-/*
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/**
- * @file opus_defines.h
- * @brief Opus reference implementation constants
- */
-
-#ifndef OPUS_DEFINES_H
-#define OPUS_DEFINES_H
-
-#include "opus_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** @defgroup opus_errorcodes Error codes
- * @{
- */
-/** No error @hideinitializer*/
-#define OPUS_OK 0
-/** One or more invalid/out of range arguments @hideinitializer*/
-#define OPUS_BAD_ARG -1
-/** Not enough bytes allocated in the buffer @hideinitializer*/
-#define OPUS_BUFFER_TOO_SMALL -2
-/** An internal error was detected @hideinitializer*/
-#define OPUS_INTERNAL_ERROR -3
-/** The compressed data passed is corrupted @hideinitializer*/
-#define OPUS_INVALID_PACKET -4
-/** Invalid/unsupported request number @hideinitializer*/
-#define OPUS_UNIMPLEMENTED -5
-/** An encoder or decoder structure is invalid or already freed @hideinitializer*/
-#define OPUS_INVALID_STATE -6
-/** Memory allocation has failed @hideinitializer*/
-#define OPUS_ALLOC_FAIL -7
-/**@}*/
-
-/** @cond OPUS_INTERNAL_DOC */
-/**Export control for opus functions */
-
-#ifndef OPUS_EXPORT
-# if defined(WIN32)
-# ifdef OPUS_BUILD
-# define OPUS_EXPORT __declspec(dllexport)
-# else
-# define OPUS_EXPORT
-# endif
-# elif defined(__GNUC__) && defined(OPUS_BUILD)
-# define OPUS_EXPORT __attribute__ ((visibility ("default")))
-# else
-# define OPUS_EXPORT
-# endif
-#endif
-
-# if !defined(OPUS_GNUC_PREREQ)
-# if defined(__GNUC__)&&defined(__GNUC_MINOR__)
-# define OPUS_GNUC_PREREQ(_maj,_min) \
- ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
-# else
-# define OPUS_GNUC_PREREQ(_maj,_min) 0
-# endif
-# endif
-
-#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
-# if OPUS_GNUC_PREREQ(3,0)
-# define OPUS_RESTRICT __restrict__
-# elif (defined(_MSC_VER) && _MSC_VER >= 1400)
-# define OPUS_RESTRICT __restrict
-# else
-# define OPUS_RESTRICT
-# endif
-#else
-# define OPUS_RESTRICT restrict
-#endif
-
-#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
-# if OPUS_GNUC_PREREQ(2,7)
-# define OPUS_INLINE __inline__
-# elif (defined(_MSC_VER))
-# define OPUS_INLINE __inline
-# else
-# define OPUS_INLINE
-# endif
-#else
-# define OPUS_INLINE inline
-#endif
-
-/**Warning attributes for opus functions
- * NONNULL is not used in OPUS_BUILD to avoid the compiler optimizing out
- * some paranoid null checks. */
-#if defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4)
-# define OPUS_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
-#else
-# define OPUS_WARN_UNUSED_RESULT
-#endif
-#if !defined(OPUS_BUILD) && defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4)
-# define OPUS_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x)))
-#else
-# define OPUS_ARG_NONNULL(_x)
-#endif
-
-/** These are the actual Encoder CTL ID numbers.
- * They should not be used directly by applications.
- * In general, SETs should be even and GETs should be odd.*/
-#define OPUS_SET_APPLICATION_REQUEST 4000
-#define OPUS_GET_APPLICATION_REQUEST 4001
-#define OPUS_SET_BITRATE_REQUEST 4002
-#define OPUS_GET_BITRATE_REQUEST 4003
-#define OPUS_SET_MAX_BANDWIDTH_REQUEST 4004
-#define OPUS_GET_MAX_BANDWIDTH_REQUEST 4005
-#define OPUS_SET_VBR_REQUEST 4006
-#define OPUS_GET_VBR_REQUEST 4007
-#define OPUS_SET_BANDWIDTH_REQUEST 4008
-#define OPUS_GET_BANDWIDTH_REQUEST 4009
-#define OPUS_SET_COMPLEXITY_REQUEST 4010
-#define OPUS_GET_COMPLEXITY_REQUEST 4011
-#define OPUS_SET_INBAND_FEC_REQUEST 4012
-#define OPUS_GET_INBAND_FEC_REQUEST 4013
-#define OPUS_SET_PACKET_LOSS_PERC_REQUEST 4014
-#define OPUS_GET_PACKET_LOSS_PERC_REQUEST 4015
-#define OPUS_SET_DTX_REQUEST 4016
-#define OPUS_GET_DTX_REQUEST 4017
-#define OPUS_SET_VBR_CONSTRAINT_REQUEST 4020
-#define OPUS_GET_VBR_CONSTRAINT_REQUEST 4021
-#define OPUS_SET_FORCE_CHANNELS_REQUEST 4022
-#define OPUS_GET_FORCE_CHANNELS_REQUEST 4023
-#define OPUS_SET_SIGNAL_REQUEST 4024
-#define OPUS_GET_SIGNAL_REQUEST 4025
-#define OPUS_GET_LOOKAHEAD_REQUEST 4027
-/* #define OPUS_RESET_STATE 4028 */
-#define OPUS_GET_SAMPLE_RATE_REQUEST 4029
-#define OPUS_GET_FINAL_RANGE_REQUEST 4031
-#define OPUS_GET_PITCH_REQUEST 4033
-#define OPUS_SET_GAIN_REQUEST 4034
-#define OPUS_GET_GAIN_REQUEST 4045 /* Should have been 4035 */
-#define OPUS_SET_LSB_DEPTH_REQUEST 4036
-#define OPUS_GET_LSB_DEPTH_REQUEST 4037
-#define OPUS_GET_LAST_PACKET_DURATION_REQUEST 4039
-#define OPUS_SET_EXPERT_FRAME_DURATION_REQUEST 4040
-#define OPUS_GET_EXPERT_FRAME_DURATION_REQUEST 4041
-#define OPUS_SET_PREDICTION_DISABLED_REQUEST 4042
-#define OPUS_GET_PREDICTION_DISABLED_REQUEST 4043
-
-/* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */
-
-/* Macros to trigger compilation errors when the wrong types are provided to a CTL */
-#define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
-#define __opus_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr)))
-#define __opus_check_uint_ptr(ptr) ((ptr) + ((ptr) - (opus_uint32*)(ptr)))
-#define __opus_check_val16_ptr(ptr) ((ptr) + ((ptr) - (opus_val16*)(ptr)))
-/** @endcond */
-
-/** @defgroup opus_ctlvalues Pre-defined values for CTL interface
- * @see opus_genericctls, opus_encoderctls
- * @{
- */
-/* Values for the various encoder CTLs */
-#define OPUS_AUTO -1000 /**opus_int32: Allowed values: 0-10, inclusive.
- *
- * @hideinitializer */
-#define OPUS_SET_COMPLEXITY(x) OPUS_SET_COMPLEXITY_REQUEST, __opus_check_int(x)
-/** Gets the encoder's complexity configuration.
- * @see OPUS_SET_COMPLEXITY
- * @param[out] x opus_int32 *: Returns a value in the range 0-10,
- * inclusive.
- * @hideinitializer */
-#define OPUS_GET_COMPLEXITY(x) OPUS_GET_COMPLEXITY_REQUEST, __opus_check_int_ptr(x)
-
-/** Configures the bitrate in the encoder.
- * Rates from 500 to 512000 bits per second are meaningful, as well as the
- * special values #OPUS_AUTO and #OPUS_BITRATE_MAX.
- * The value #OPUS_BITRATE_MAX can be used to cause the codec to use as much
- * rate as it can, which is useful for controlling the rate by adjusting the
- * output buffer size.
- * @see OPUS_GET_BITRATE
- * @param[in] x opus_int32: Bitrate in bits per second. The default
- * is determined based on the number of
- * channels and the input sampling rate.
- * @hideinitializer */
-#define OPUS_SET_BITRATE(x) OPUS_SET_BITRATE_REQUEST, __opus_check_int(x)
-/** Gets the encoder's bitrate configuration.
- * @see OPUS_SET_BITRATE
- * @param[out] x opus_int32 *: Returns the bitrate in bits per second.
- * The default is determined based on the
- * number of channels and the input
- * sampling rate.
- * @hideinitializer */
-#define OPUS_GET_BITRATE(x) OPUS_GET_BITRATE_REQUEST, __opus_check_int_ptr(x)
-
-/** Enables or disables variable bitrate (VBR) in the encoder.
- * The configured bitrate may not be met exactly because frames must
- * be an integer number of bytes in length.
- * @warning Only the MDCT mode of Opus can provide hard CBR behavior.
- * @see OPUS_GET_VBR
- * @see OPUS_SET_VBR_CONSTRAINT
- * @param[in] x opus_int32: Allowed values:
- *
- *
0
Hard CBR. For LPC/hybrid modes at very low bit-rate, this can
- * cause noticeable quality degradation.
- *
1
VBR (default). The exact type of VBR is controlled by
- * #OPUS_SET_VBR_CONSTRAINT.
- *
- * @hideinitializer */
-#define OPUS_SET_VBR(x) OPUS_SET_VBR_REQUEST, __opus_check_int(x)
-/** Determine if variable bitrate (VBR) is enabled in the encoder.
- * @see OPUS_SET_VBR
- * @see OPUS_GET_VBR_CONSTRAINT
- * @param[out] x opus_int32 *: Returns one of the following values:
- *
- *
0
Hard CBR.
- *
1
VBR (default). The exact type of VBR may be retrieved via
- * #OPUS_GET_VBR_CONSTRAINT.
- *
- * @hideinitializer */
-#define OPUS_GET_VBR(x) OPUS_GET_VBR_REQUEST, __opus_check_int_ptr(x)
-
-/** Enables or disables constrained VBR in the encoder.
- * This setting is ignored when the encoder is in CBR mode.
- * @warning Only the MDCT mode of Opus currently heeds the constraint.
- * Speech mode ignores it completely, hybrid mode may fail to obey it
- * if the LPC layer uses more bitrate than the constraint would have
- * permitted.
- * @see OPUS_GET_VBR_CONSTRAINT
- * @see OPUS_SET_VBR
- * @param[in] x opus_int32: Allowed values:
- *
- *
0
Unconstrained VBR.
- *
1
Constrained VBR (default). This creates a maximum of one
- * frame of buffering delay assuming a transport with a
- * serialization speed of the nominal bitrate.
- *
- * @hideinitializer */
-#define OPUS_SET_VBR_CONSTRAINT(x) OPUS_SET_VBR_CONSTRAINT_REQUEST, __opus_check_int(x)
-/** Determine if constrained VBR is enabled in the encoder.
- * @see OPUS_SET_VBR_CONSTRAINT
- * @see OPUS_GET_VBR
- * @param[out] x opus_int32 *: Returns one of the following values:
- *
- *
0
Unconstrained VBR.
- *
1
Constrained VBR (default).
- *
- * @hideinitializer */
-#define OPUS_GET_VBR_CONSTRAINT(x) OPUS_GET_VBR_CONSTRAINT_REQUEST, __opus_check_int_ptr(x)
-
-/** Configures mono/stereo forcing in the encoder.
- * This can force the encoder to produce packets encoded as either mono or
- * stereo, regardless of the format of the input audio. This is useful when
- * the caller knows that the input signal is currently a mono source embedded
- * in a stereo stream.
- * @see OPUS_GET_FORCE_CHANNELS
- * @param[in] x opus_int32: Allowed values:
- *
- * @hideinitializer */
-#define OPUS_GET_FORCE_CHANNELS(x) OPUS_GET_FORCE_CHANNELS_REQUEST, __opus_check_int_ptr(x)
-
-/** Configures the maximum bandpass that the encoder will select automatically.
- * Applications should normally use this instead of #OPUS_SET_BANDWIDTH
- * (leaving that set to the default, #OPUS_AUTO). This allows the
- * application to set an upper bound based on the type of input it is
- * providing, but still gives the encoder the freedom to reduce the bandpass
- * when the bitrate becomes too low, for better overall quality.
- * @see OPUS_GET_MAX_BANDWIDTH
- * @param[in] x opus_int32: Allowed values:
- *
- * @hideinitializer */
-#define OPUS_GET_MAX_BANDWIDTH(x) OPUS_GET_MAX_BANDWIDTH_REQUEST, __opus_check_int_ptr(x)
-
-/** Sets the encoder's bandpass to a specific value.
- * This prevents the encoder from automatically selecting the bandpass based
- * on the available bitrate. If an application knows the bandpass of the input
- * audio it is providing, it should normally use #OPUS_SET_MAX_BANDWIDTH
- * instead, which still gives the encoder the freedom to reduce the bandpass
- * when the bitrate becomes too low, for better overall quality.
- * @see OPUS_GET_BANDWIDTH
- * @param[in] x opus_int32: Allowed values:
- *
- *
#OPUS_AUTO
(default)
- *
#OPUS_BANDWIDTH_NARROWBAND
4 kHz passband
- *
#OPUS_BANDWIDTH_MEDIUMBAND
6 kHz passband
- *
#OPUS_BANDWIDTH_WIDEBAND
8 kHz passband
- *
#OPUS_BANDWIDTH_SUPERWIDEBAND
12 kHz passband
- *
#OPUS_BANDWIDTH_FULLBAND
20 kHz passband
- *
- * @hideinitializer */
-#define OPUS_SET_BANDWIDTH(x) OPUS_SET_BANDWIDTH_REQUEST, __opus_check_int(x)
-
-/** Configures the type of signal being encoded.
- * This is a hint which helps the encoder's mode selection.
- * @see OPUS_GET_SIGNAL
- * @param[in] x opus_int32: Allowed values:
- *
- *
#OPUS_AUTO
(default)
- *
#OPUS_SIGNAL_VOICE
Bias thresholds towards choosing LPC or Hybrid modes.
- *
#OPUS_SIGNAL_MUSIC
Bias thresholds towards choosing MDCT modes.
- *
- * @hideinitializer */
-#define OPUS_SET_SIGNAL(x) OPUS_SET_SIGNAL_REQUEST, __opus_check_int(x)
-/** Gets the encoder's configured signal type.
- * @see OPUS_SET_SIGNAL
- * @param[out] x opus_int32 *: Returns one of the following values:
- *
- *
#OPUS_AUTO
(default)
- *
#OPUS_SIGNAL_VOICE
Bias thresholds towards choosing LPC or Hybrid modes.
- *
#OPUS_SIGNAL_MUSIC
Bias thresholds towards choosing MDCT modes.
- *
- * @hideinitializer */
-#define OPUS_GET_SIGNAL(x) OPUS_GET_SIGNAL_REQUEST, __opus_check_int_ptr(x)
-
-
-/** Configures the encoder's intended application.
- * The initial value is a mandatory argument to the encoder_create function.
- * @see OPUS_GET_APPLICATION
- * @param[in] x opus_int32: Returns one of the following values:
- *
- *
#OPUS_APPLICATION_VOIP
- *
Process signal for improved speech intelligibility.
- *
#OPUS_APPLICATION_AUDIO
- *
Favor faithfulness to the original input.
- *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
- *
Configure the minimum possible coding delay by disabling certain modes
- * of operation.
- *
- * @hideinitializer */
-#define OPUS_SET_APPLICATION(x) OPUS_SET_APPLICATION_REQUEST, __opus_check_int(x)
-/** Gets the encoder's configured application.
- * @see OPUS_SET_APPLICATION
- * @param[out] x opus_int32 *: Returns one of the following values:
- *
- *
#OPUS_APPLICATION_VOIP
- *
Process signal for improved speech intelligibility.
- *
#OPUS_APPLICATION_AUDIO
- *
Favor faithfulness to the original input.
- *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
- *
Configure the minimum possible coding delay by disabling certain modes
- * of operation.
- *
- * @hideinitializer */
-#define OPUS_GET_APPLICATION(x) OPUS_GET_APPLICATION_REQUEST, __opus_check_int_ptr(x)
-
-/** Gets the total samples of delay added by the entire codec.
- * This can be queried by the encoder and then the provided number of samples can be
- * skipped on from the start of the decoder's output to provide time aligned input
- * and output. From the perspective of a decoding application the real data begins this many
- * samples late.
- *
- * The decoder contribution to this delay is identical for all decoders, but the
- * encoder portion of the delay may vary from implementation to implementation,
- * version to version, or even depend on the encoder's initial configuration.
- * Applications needing delay compensation should call this CTL rather than
- * hard-coding a value.
- * @param[out] x opus_int32 *: Number of lookahead samples
- * @hideinitializer */
-#define OPUS_GET_LOOKAHEAD(x) OPUS_GET_LOOKAHEAD_REQUEST, __opus_check_int_ptr(x)
-
-/** Configures the encoder's use of inband forward error correction (FEC).
- * @note This is only applicable to the LPC layer
- * @see OPUS_GET_INBAND_FEC
- * @param[in] x opus_int32: Allowed values:
- *
- *
0
Disable inband FEC (default).
- *
1
Enable inband FEC.
- *
- * @hideinitializer */
-#define OPUS_SET_INBAND_FEC(x) OPUS_SET_INBAND_FEC_REQUEST, __opus_check_int(x)
-/** Gets encoder's configured use of inband forward error correction.
- * @see OPUS_SET_INBAND_FEC
- * @param[out] x opus_int32 *: Returns one of the following values:
- *
- *
0
Inband FEC disabled (default).
- *
1
Inband FEC enabled.
- *
- * @hideinitializer */
-#define OPUS_GET_INBAND_FEC(x) OPUS_GET_INBAND_FEC_REQUEST, __opus_check_int_ptr(x)
-
-/** Configures the encoder's expected packet loss percentage.
- * Higher values with trigger progressively more loss resistant behavior in the encoder
- * at the expense of quality at a given bitrate in the lossless case, but greater quality
- * under loss.
- * @see OPUS_GET_PACKET_LOSS_PERC
- * @param[in] x opus_int32: Loss percentage in the range 0-100, inclusive (default: 0).
- * @hideinitializer */
-#define OPUS_SET_PACKET_LOSS_PERC(x) OPUS_SET_PACKET_LOSS_PERC_REQUEST, __opus_check_int(x)
-/** Gets the encoder's configured packet loss percentage.
- * @see OPUS_SET_PACKET_LOSS_PERC
- * @param[out] x opus_int32 *: Returns the configured loss percentage
- * in the range 0-100, inclusive (default: 0).
- * @hideinitializer */
-#define OPUS_GET_PACKET_LOSS_PERC(x) OPUS_GET_PACKET_LOSS_PERC_REQUEST, __opus_check_int_ptr(x)
-
-/** Configures the encoder's use of discontinuous transmission (DTX).
- * @note This is only applicable to the LPC layer
- * @see OPUS_GET_DTX
- * @param[in] x opus_int32: Allowed values:
- *
- *
0
Disable DTX (default).
- *
1
Enabled DTX.
- *
- * @hideinitializer */
-#define OPUS_SET_DTX(x) OPUS_SET_DTX_REQUEST, __opus_check_int(x)
-/** Gets encoder's configured use of discontinuous transmission.
- * @see OPUS_SET_DTX
- * @param[out] x opus_int32 *: Returns one of the following values:
- *
- *
0
DTX disabled (default).
- *
1
DTX enabled.
- *
- * @hideinitializer */
-#define OPUS_GET_DTX(x) OPUS_GET_DTX_REQUEST, __opus_check_int_ptr(x)
-/** Configures the depth of signal being encoded.
- * This is a hint which helps the encoder identify silence and near-silence.
- * @see OPUS_GET_LSB_DEPTH
- * @param[in] x opus_int32: Input precision in bits, between 8 and 24
- * (default: 24).
- * @hideinitializer */
-#define OPUS_SET_LSB_DEPTH(x) OPUS_SET_LSB_DEPTH_REQUEST, __opus_check_int(x)
-/** Gets the encoder's configured signal depth.
- * @see OPUS_SET_LSB_DEPTH
- * @param[out] x opus_int32 *: Input precision in bits, between 8 and
- * 24 (default: 24).
- * @hideinitializer */
-#define OPUS_GET_LSB_DEPTH(x) OPUS_GET_LSB_DEPTH_REQUEST, __opus_check_int_ptr(x)
-
-/** Configures the encoder's use of variable duration frames.
- * When variable duration is enabled, the encoder is free to use a shorter frame
- * size than the one requested in the opus_encode*() call.
- * It is then the user's responsibility
- * to verify how much audio was encoded by checking the ToC byte of the encoded
- * packet. The part of the audio that was not encoded needs to be resent to the
- * encoder for the next call. Do not use this option unless you really
- * know what you are doing.
- * @see OPUS_GET_EXPERT_VARIABLE_DURATION
- * @param[in] x opus_int32: Allowed values:
- *
- *
OPUS_FRAMESIZE_ARG
Select frame size from the argument (default).
- *
OPUS_FRAMESIZE_2_5_MS
Use 2.5 ms frames.
- *
OPUS_FRAMESIZE_5_MS
Use 2.5 ms frames.
- *
OPUS_FRAMESIZE_10_MS
Use 10 ms frames.
- *
OPUS_FRAMESIZE_20_MS
Use 20 ms frames.
- *
OPUS_FRAMESIZE_40_MS
Use 40 ms frames.
- *
OPUS_FRAMESIZE_60_MS
Use 60 ms frames.
- *
OPUS_FRAMESIZE_VARIABLE
Optimize the frame size dynamically.
- *
- * @hideinitializer */
-#define OPUS_SET_EXPERT_FRAME_DURATION(x) OPUS_SET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int(x)
-/** Gets the encoder's configured use of variable duration frames.
- * @see OPUS_SET_EXPERT_VARIABLE_DURATION
- * @param[out] x opus_int32 *: Returns one of the following values:
- *
- *
OPUS_FRAMESIZE_ARG
Select frame size from the argument (default).
- *
OPUS_FRAMESIZE_2_5_MS
Use 2.5 ms frames.
- *
OPUS_FRAMESIZE_5_MS
Use 2.5 ms frames.
- *
OPUS_FRAMESIZE_10_MS
Use 10 ms frames.
- *
OPUS_FRAMESIZE_20_MS
Use 20 ms frames.
- *
OPUS_FRAMESIZE_40_MS
Use 40 ms frames.
- *
OPUS_FRAMESIZE_60_MS
Use 60 ms frames.
- *
OPUS_FRAMESIZE_VARIABLE
Optimize the frame size dynamically.
- *
- * @hideinitializer */
-#define OPUS_GET_EXPERT_FRAME_DURATION(x) OPUS_GET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int_ptr(x)
-
-/** If set to 1, disables almost all use of prediction, making frames almost
- completely independent. This reduces quality. (default : 0)
- * @hideinitializer */
-#define OPUS_SET_PREDICTION_DISABLED(x) OPUS_SET_PREDICTION_DISABLED_REQUEST, __opus_check_int(x)
-/** Gets the encoder's configured prediction status.
- * @hideinitializer */
-#define OPUS_GET_PREDICTION_DISABLED(x) OPUS_GET_PREDICTION_DISABLED_REQUEST, __opus_check_int_ptr(x)
-
-/**@}*/
-
-/** @defgroup opus_genericctls Generic CTLs
- *
- * These macros are used with the \c opus_decoder_ctl and
- * \c opus_encoder_ctl calls to generate a particular
- * request.
- *
- * When called on an \c OpusDecoder they apply to that
- * particular decoder instance. When called on an
- * \c OpusEncoder they apply to the corresponding setting
- * on that encoder instance, if present.
- *
- * Some usage examples:
- *
- * @code
- * int ret;
- * opus_int32 pitch;
- * ret = opus_decoder_ctl(dec_ctx, OPUS_GET_PITCH(&pitch));
- * if (ret == OPUS_OK) return ret;
- *
- * opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE);
- * opus_decoder_ctl(dec_ctx, OPUS_RESET_STATE);
- *
- * opus_int32 enc_bw, dec_bw;
- * opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&enc_bw));
- * opus_decoder_ctl(dec_ctx, OPUS_GET_BANDWIDTH(&dec_bw));
- * if (enc_bw != dec_bw) {
- * printf("packet bandwidth mismatch!\n");
- * }
- * @endcode
- *
- * @see opus_encoder, opus_decoder_ctl, opus_encoder_ctl, opus_decoderctls, opus_encoderctls
- * @{
- */
-
-/** Resets the codec state to be equivalent to a freshly initialized state.
- * This should be called when switching streams in order to prevent
- * the back to back decoding from giving different results from
- * one at a time decoding.
- * @hideinitializer */
-#define OPUS_RESET_STATE 4028
-
-/** Gets the final state of the codec's entropy coder.
- * This is used for testing purposes,
- * The encoder and decoder state should be identical after coding a payload
- * (assuming no data corruption or software bugs)
- *
- * @param[out] x opus_uint32 *: Entropy coder state
- *
- * @hideinitializer */
-#define OPUS_GET_FINAL_RANGE(x) OPUS_GET_FINAL_RANGE_REQUEST, __opus_check_uint_ptr(x)
-
-/** Gets the encoder's configured bandpass or the decoder's last bandpass.
- * @see OPUS_SET_BANDWIDTH
- * @param[out] x opus_int32 *: Returns one of the following values:
- *
- *
#OPUS_AUTO
(default)
- *
#OPUS_BANDWIDTH_NARROWBAND
4 kHz passband
- *
#OPUS_BANDWIDTH_MEDIUMBAND
6 kHz passband
- *
#OPUS_BANDWIDTH_WIDEBAND
8 kHz passband
- *
#OPUS_BANDWIDTH_SUPERWIDEBAND
12 kHz passband
- *
#OPUS_BANDWIDTH_FULLBAND
20 kHz passband
- *
- * @hideinitializer */
-#define OPUS_GET_BANDWIDTH(x) OPUS_GET_BANDWIDTH_REQUEST, __opus_check_int_ptr(x)
-
-/** Gets the sampling rate the encoder or decoder was initialized with.
- * This simply returns the Fs value passed to opus_encoder_init()
- * or opus_decoder_init().
- * @param[out] x opus_int32 *: Sampling rate of encoder or decoder.
- * @hideinitializer
- */
-#define OPUS_GET_SAMPLE_RATE(x) OPUS_GET_SAMPLE_RATE_REQUEST, __opus_check_int_ptr(x)
-
-/**@}*/
-
-/** @defgroup opus_decoderctls Decoder related CTLs
- * @see opus_genericctls, opus_encoderctls, opus_decoder
- * @{
- */
-
-/** Configures decoder gain adjustment.
- * Scales the decoded output by a factor specified in Q8 dB units.
- * This has a maximum range of -32768 to 32767 inclusive, and returns
- * OPUS_BAD_ARG otherwise. The default is zero indicating no adjustment.
- * This setting survives decoder reset.
- *
- * gain = pow(10, x/(20.0*256))
- *
- * @param[in] x opus_int32: Amount to scale PCM signal by in Q8 dB units.
- * @hideinitializer */
-#define OPUS_SET_GAIN(x) OPUS_SET_GAIN_REQUEST, __opus_check_int(x)
-/** Gets the decoder's configured gain adjustment. @see OPUS_SET_GAIN
- *
- * @param[out] x opus_int32 *: Amount to scale PCM signal by in Q8 dB units.
- * @hideinitializer */
-#define OPUS_GET_GAIN(x) OPUS_GET_GAIN_REQUEST, __opus_check_int_ptr(x)
-
-/** Gets the duration (in samples) of the last packet successfully decoded or concealed.
- * @param[out] x opus_int32 *: Number of samples (at current sampling rate).
- * @hideinitializer */
-#define OPUS_GET_LAST_PACKET_DURATION(x) OPUS_GET_LAST_PACKET_DURATION_REQUEST, __opus_check_int_ptr(x)
-
-/** Gets the pitch of the last decoded frame, if available.
- * This can be used for any post-processing algorithm requiring the use of pitch,
- * e.g. time stretching/shortening. If the last frame was not voiced, or if the
- * pitch was not coded in the frame, then zero is returned.
- *
- * This CTL is only implemented for decoder instances.
- *
- * @param[out] x opus_int32 *: pitch period at 48 kHz (or 0 if not available)
- *
- * @hideinitializer */
-#define OPUS_GET_PITCH(x) OPUS_GET_PITCH_REQUEST, __opus_check_int_ptr(x)
-
-/**@}*/
-
-/** @defgroup opus_libinfo Opus library information functions
- * @{
- */
-
-/** Converts an opus error code into a human readable string.
- *
- * @param[in] error int: Error number
- * @returns Error string
- */
-OPUS_EXPORT const char *opus_strerror(int error);
-
-/** Gets the libopus version string.
- *
- * @returns Version string
- */
-OPUS_EXPORT const char *opus_get_version_string(void);
-/**@}*/
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* OPUS_DEFINES_H */
diff --git a/app/src/main/jni/nv_opus_dec/libopus/inc/opus_multistream.h b/app/src/main/jni/nv_opus_dec/libopus/inc/opus_multistream.h
deleted file mode 100644
index ae599793..00000000
--- a/app/src/main/jni/nv_opus_dec/libopus/inc/opus_multistream.h
+++ /dev/null
@@ -1,660 +0,0 @@
-/* Copyright (c) 2011 Xiph.Org Foundation
- Written by Jean-Marc Valin */
-/*
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/**
- * @file opus_multistream.h
- * @brief Opus reference implementation multistream API
- */
-
-#ifndef OPUS_MULTISTREAM_H
-#define OPUS_MULTISTREAM_H
-
-#include "opus.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** @cond OPUS_INTERNAL_DOC */
-
-/** Macros to trigger compilation errors when the wrong types are provided to a
- * CTL. */
-/**@{*/
-#define __opus_check_encstate_ptr(ptr) ((ptr) + ((ptr) - (OpusEncoder**)(ptr)))
-#define __opus_check_decstate_ptr(ptr) ((ptr) + ((ptr) - (OpusDecoder**)(ptr)))
-/**@}*/
-
-/** These are the actual encoder and decoder CTL ID numbers.
- * They should not be used directly by applications.
- * In general, SETs should be even and GETs should be odd.*/
-/**@{*/
-#define OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST 5120
-#define OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST 5122
-/**@}*/
-
-/** @endcond */
-
-/** @defgroup opus_multistream_ctls Multistream specific encoder and decoder CTLs
- *
- * These are convenience macros that are specific to the
- * opus_multistream_encoder_ctl() and opus_multistream_decoder_ctl()
- * interface.
- * The CTLs from @ref opus_genericctls, @ref opus_encoderctls, and
- * @ref opus_decoderctls may be applied to a multistream encoder or decoder as
- * well.
- * In addition, you may retrieve the encoder or decoder state for an specific
- * stream via #OPUS_MULTISTREAM_GET_ENCODER_STATE or
- * #OPUS_MULTISTREAM_GET_DECODER_STATE and apply CTLs to it individually.
- */
-/**@{*/
-
-/** Gets the encoder state for an individual stream of a multistream encoder.
- * @param[in] x opus_int32: The index of the stream whose encoder you
- * wish to retrieve.
- * This must be non-negative and less than
- * the streams parameter used
- * to initialize the encoder.
- * @param[out] y OpusEncoder**: Returns a pointer to the given
- * encoder state.
- * @retval OPUS_BAD_ARG The index of the requested stream was out of range.
- * @hideinitializer
- */
-#define OPUS_MULTISTREAM_GET_ENCODER_STATE(x,y) OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST, __opus_check_int(x), __opus_check_encstate_ptr(y)
-
-/** Gets the decoder state for an individual stream of a multistream decoder.
- * @param[in] x opus_int32: The index of the stream whose decoder you
- * wish to retrieve.
- * This must be non-negative and less than
- * the streams parameter used
- * to initialize the decoder.
- * @param[out] y OpusDecoder**: Returns a pointer to the given
- * decoder state.
- * @retval OPUS_BAD_ARG The index of the requested stream was out of range.
- * @hideinitializer
- */
-#define OPUS_MULTISTREAM_GET_DECODER_STATE(x,y) OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST, __opus_check_int(x), __opus_check_decstate_ptr(y)
-
-/**@}*/
-
-/** @defgroup opus_multistream Opus Multistream API
- * @{
- *
- * The multistream API allows individual Opus streams to be combined into a
- * single packet, enabling support for up to 255 channels. Unlike an
- * elementary Opus stream, the encoder and decoder must negotiate the channel
- * configuration before the decoder can successfully interpret the data in the
- * packets produced by the encoder. Some basic information, such as packet
- * duration, can be computed without any special negotiation.
- *
- * The format for multistream Opus packets is defined in the
- * Ogg
- * encapsulation specification and is based on the self-delimited Opus
- * framing described in Appendix B of RFC 6716.
- * Normal Opus packets are just a degenerate case of multistream Opus packets,
- * and can be encoded or decoded with the multistream API by setting
- * streams to 1 when initializing the encoder or
- * decoder.
- *
- * Multistream Opus streams can contain up to 255 elementary Opus streams.
- * These may be either "uncoupled" or "coupled", indicating that the decoder
- * is configured to decode them to either 1 or 2 channels, respectively.
- * The streams are ordered so that all coupled streams appear at the
- * beginning.
- *
- * A mapping table defines which decoded channel i
- * should be used for each input/output (I/O) channel j. This table is
- * typically provided as an unsigned char array.
- * Let i = mapping[j] be the index for I/O channel j.
- * If i < 2*coupled_streams, then I/O channel j is
- * encoded as the left channel of stream (i/2) if i
- * is even, or as the right channel of stream (i/2) if
- * i is odd. Otherwise, I/O channel j is encoded as
- * mono in stream (i - coupled_streams), unless it has the special
- * value 255, in which case it is omitted from the encoding entirely (the
- * decoder will reproduce it as silence). Each value i must either
- * be the special value 255 or be less than streams + coupled_streams.
- *
- * The output channels specified by the encoder
- * should use the
- * Vorbis
- * channel ordering. A decoder may wish to apply an additional permutation
- * to the mapping the encoder used to achieve a different output channel
- * order (e.g. for outputing in WAV order).
- *
- * Each multistream packet contains an Opus packet for each stream, and all of
- * the Opus packets in a single multistream packet must have the same
- * duration. Therefore the duration of a multistream packet can be extracted
- * from the TOC sequence of the first stream, which is located at the
- * beginning of the packet, just like an elementary Opus stream:
- *
- * @code
- * int nb_samples;
- * int nb_frames;
- * nb_frames = opus_packet_get_nb_frames(data, len);
- * if (nb_frames < 1)
- * return nb_frames;
- * nb_samples = opus_packet_get_samples_per_frame(data, 48000) * nb_frames;
- * @endcode
- *
- * The general encoding and decoding process proceeds exactly the same as in
- * the normal @ref opus_encoder and @ref opus_decoder APIs.
- * See their documentation for an overview of how to use the corresponding
- * multistream functions.
- */
-
-/** Opus multistream encoder state.
- * This contains the complete state of a multistream Opus encoder.
- * It is position independent and can be freely copied.
- * @see opus_multistream_encoder_create
- * @see opus_multistream_encoder_init
- */
-typedef struct OpusMSEncoder OpusMSEncoder;
-
-/** Opus multistream decoder state.
- * This contains the complete state of a multistream Opus decoder.
- * It is position independent and can be freely copied.
- * @see opus_multistream_decoder_create
- * @see opus_multistream_decoder_init
- */
-typedef struct OpusMSDecoder OpusMSDecoder;
-
-/**\name Multistream encoder functions */
-/**@{*/
-
-/** Gets the size of an OpusMSEncoder structure.
- * @param streams int: The total number of streams to encode from the
- * input.
- * This must be no more than 255.
- * @param coupled_streams int: Number of coupled (2 channel) streams
- * to encode.
- * This must be no larger than the total
- * number of streams.
- * Additionally, The total number of
- * encoded channels (streams +
- * coupled_streams) must be no
- * more than 255.
- * @returns The size in bytes on success, or a negative error code
- * (see @ref opus_errorcodes) on error.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_encoder_get_size(
- int streams,
- int coupled_streams
-);
-
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_surround_encoder_get_size(
- int channels,
- int mapping_family
-);
-
-
-/** Allocates and initializes a multistream encoder state.
- * Call opus_multistream_encoder_destroy() to release
- * this object when finished.
- * @param Fs opus_int32: Sampling rate of the input signal (in Hz).
- * This must be one of 8000, 12000, 16000,
- * 24000, or 48000.
- * @param channels int: Number of channels in the input signal.
- * This must be at most 255.
- * It may be greater than the number of
- * coded channels (streams +
- * coupled_streams).
- * @param streams int: The total number of streams to encode from the
- * input.
- * This must be no more than the number of channels.
- * @param coupled_streams int: Number of coupled (2 channel) streams
- * to encode.
- * This must be no larger than the total
- * number of streams.
- * Additionally, The total number of
- * encoded channels (streams +
- * coupled_streams) must be no
- * more than the number of input channels.
- * @param[in] mapping const unsigned char[channels]: Mapping from
- * encoded channels to input channels, as described in
- * @ref opus_multistream. As an extra constraint, the
- * multistream encoder does not allow encoding coupled
- * streams for which one channel is unused since this
- * is never a good idea.
- * @param application int: The target encoder application.
- * This must be one of the following:
- *
- *
#OPUS_APPLICATION_VOIP
- *
Process signal for improved speech intelligibility.
- *
#OPUS_APPLICATION_AUDIO
- *
Favor faithfulness to the original input.
- *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
- *
Configure the minimum possible coding delay by disabling certain modes
- * of operation.
- *
- * @param[out] error int *: Returns #OPUS_OK on success, or an error
- * code (see @ref opus_errorcodes) on
- * failure.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_encoder_create(
- opus_int32 Fs,
- int channels,
- int streams,
- int coupled_streams,
- const unsigned char *mapping,
- int application,
- int *error
-) OPUS_ARG_NONNULL(5);
-
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_surround_encoder_create(
- opus_int32 Fs,
- int channels,
- int mapping_family,
- int *streams,
- int *coupled_streams,
- unsigned char *mapping,
- int application,
- int *error
-) OPUS_ARG_NONNULL(5);
-
-/** Initialize a previously allocated multistream encoder state.
- * The memory pointed to by \a st must be at least the size returned by
- * opus_multistream_encoder_get_size().
- * This is intended for applications which use their own allocator instead of
- * malloc.
- * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
- * @see opus_multistream_encoder_create
- * @see opus_multistream_encoder_get_size
- * @param st OpusMSEncoder*: Multistream encoder state to initialize.
- * @param Fs opus_int32: Sampling rate of the input signal (in Hz).
- * This must be one of 8000, 12000, 16000,
- * 24000, or 48000.
- * @param channels int: Number of channels in the input signal.
- * This must be at most 255.
- * It may be greater than the number of
- * coded channels (streams +
- * coupled_streams).
- * @param streams int: The total number of streams to encode from the
- * input.
- * This must be no more than the number of channels.
- * @param coupled_streams int: Number of coupled (2 channel) streams
- * to encode.
- * This must be no larger than the total
- * number of streams.
- * Additionally, The total number of
- * encoded channels (streams +
- * coupled_streams) must be no
- * more than the number of input channels.
- * @param[in] mapping const unsigned char[channels]: Mapping from
- * encoded channels to input channels, as described in
- * @ref opus_multistream. As an extra constraint, the
- * multistream encoder does not allow encoding coupled
- * streams for which one channel is unused since this
- * is never a good idea.
- * @param application int: The target encoder application.
- * This must be one of the following:
- *
- *
#OPUS_APPLICATION_VOIP
- *
Process signal for improved speech intelligibility.
- *
#OPUS_APPLICATION_AUDIO
- *
Favor faithfulness to the original input.
- *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
- *
Configure the minimum possible coding delay by disabling certain modes
- * of operation.
- *
- * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
- * on failure.
- */
-OPUS_EXPORT int opus_multistream_encoder_init(
- OpusMSEncoder *st,
- opus_int32 Fs,
- int channels,
- int streams,
- int coupled_streams,
- const unsigned char *mapping,
- int application
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
-
-OPUS_EXPORT int opus_multistream_surround_encoder_init(
- OpusMSEncoder *st,
- opus_int32 Fs,
- int channels,
- int mapping_family,
- int *streams,
- int *coupled_streams,
- unsigned char *mapping,
- int application
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
-
-/** Encodes a multistream Opus frame.
- * @param st OpusMSEncoder*: Multistream encoder state.
- * @param[in] pcm const opus_int16*: The input signal as interleaved
- * samples.
- * This must contain
- * frame_size*channels
- * samples.
- * @param frame_size int: Number of samples per channel in the input
- * signal.
- * This must be an Opus frame size for the
- * encoder's sampling rate.
- * For example, at 48 kHz the permitted values
- * are 120, 240, 480, 960, 1920, and 2880.
- * Passing in a duration of less than 10 ms
- * (480 samples at 48 kHz) will prevent the
- * encoder from using the LPC or hybrid modes.
- * @param[out] data unsigned char*: Output payload.
- * This must contain storage for at
- * least \a max_data_bytes.
- * @param [in] max_data_bytes opus_int32: Size of the allocated
- * memory for the output
- * payload. This may be
- * used to impose an upper limit on
- * the instant bitrate, but should
- * not be used as the only bitrate
- * control. Use #OPUS_SET_BITRATE to
- * control the bitrate.
- * @returns The length of the encoded packet (in bytes) on success or a
- * negative error code (see @ref opus_errorcodes) on failure.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode(
- OpusMSEncoder *st,
- const opus_int16 *pcm,
- int frame_size,
- unsigned char *data,
- opus_int32 max_data_bytes
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
-
-/** Encodes a multistream Opus frame from floating point input.
- * @param st OpusMSEncoder*: Multistream encoder state.
- * @param[in] pcm const float*: The input signal as interleaved
- * samples with a normal range of
- * +/-1.0.
- * Samples with a range beyond +/-1.0
- * are supported but will be clipped by
- * decoders using the integer API and
- * should only be used if it is known
- * that the far end supports extended
- * dynamic range.
- * This must contain
- * frame_size*channels
- * samples.
- * @param frame_size int: Number of samples per channel in the input
- * signal.
- * This must be an Opus frame size for the
- * encoder's sampling rate.
- * For example, at 48 kHz the permitted values
- * are 120, 240, 480, 960, 1920, and 2880.
- * Passing in a duration of less than 10 ms
- * (480 samples at 48 kHz) will prevent the
- * encoder from using the LPC or hybrid modes.
- * @param[out] data unsigned char*: Output payload.
- * This must contain storage for at
- * least \a max_data_bytes.
- * @param [in] max_data_bytes opus_int32: Size of the allocated
- * memory for the output
- * payload. This may be
- * used to impose an upper limit on
- * the instant bitrate, but should
- * not be used as the only bitrate
- * control. Use #OPUS_SET_BITRATE to
- * control the bitrate.
- * @returns The length of the encoded packet (in bytes) on success or a
- * negative error code (see @ref opus_errorcodes) on failure.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode_float(
- OpusMSEncoder *st,
- const float *pcm,
- int frame_size,
- unsigned char *data,
- opus_int32 max_data_bytes
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
-
-/** Frees an OpusMSEncoder allocated by
- * opus_multistream_encoder_create().
- * @param st OpusMSEncoder*: Multistream encoder state to be freed.
- */
-OPUS_EXPORT void opus_multistream_encoder_destroy(OpusMSEncoder *st);
-
-/** Perform a CTL function on a multistream Opus encoder.
- *
- * Generally the request and subsequent arguments are generated by a
- * convenience macro.
- * @param st OpusMSEncoder*: Multistream encoder state.
- * @param request This and all remaining parameters should be replaced by one
- * of the convenience macros in @ref opus_genericctls,
- * @ref opus_encoderctls, or @ref opus_multistream_ctls.
- * @see opus_genericctls
- * @see opus_encoderctls
- * @see opus_multistream_ctls
- */
-OPUS_EXPORT int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
-
-/**@}*/
-
-/**\name Multistream decoder functions */
-/**@{*/
-
-/** Gets the size of an OpusMSDecoder structure.
- * @param streams int: The total number of streams coded in the
- * input.
- * This must be no more than 255.
- * @param coupled_streams int: Number streams to decode as coupled
- * (2 channel) streams.
- * This must be no larger than the total
- * number of streams.
- * Additionally, The total number of
- * coded channels (streams +
- * coupled_streams) must be no
- * more than 255.
- * @returns The size in bytes on success, or a negative error code
- * (see @ref opus_errorcodes) on error.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_decoder_get_size(
- int streams,
- int coupled_streams
-);
-
-/** Allocates and initializes a multistream decoder state.
- * Call opus_multistream_decoder_destroy() to release
- * this object when finished.
- * @param Fs opus_int32: Sampling rate to decode at (in Hz).
- * This must be one of 8000, 12000, 16000,
- * 24000, or 48000.
- * @param channels int: Number of channels to output.
- * This must be at most 255.
- * It may be different from the number of coded
- * channels (streams +
- * coupled_streams).
- * @param streams int: The total number of streams coded in the
- * input.
- * This must be no more than 255.
- * @param coupled_streams int: Number of streams to decode as coupled
- * (2 channel) streams.
- * This must be no larger than the total
- * number of streams.
- * Additionally, The total number of
- * coded channels (streams +
- * coupled_streams) must be no
- * more than 255.
- * @param[in] mapping const unsigned char[channels]: Mapping from
- * coded channels to output channels, as described in
- * @ref opus_multistream.
- * @param[out] error int *: Returns #OPUS_OK on success, or an error
- * code (see @ref opus_errorcodes) on
- * failure.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSDecoder *opus_multistream_decoder_create(
- opus_int32 Fs,
- int channels,
- int streams,
- int coupled_streams,
- const unsigned char *mapping,
- int *error
-) OPUS_ARG_NONNULL(5);
-
-/** Intialize a previously allocated decoder state object.
- * The memory pointed to by \a st must be at least the size returned by
- * opus_multistream_encoder_get_size().
- * This is intended for applications which use their own allocator instead of
- * malloc.
- * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
- * @see opus_multistream_decoder_create
- * @see opus_multistream_deocder_get_size
- * @param st OpusMSEncoder*: Multistream encoder state to initialize.
- * @param Fs opus_int32: Sampling rate to decode at (in Hz).
- * This must be one of 8000, 12000, 16000,
- * 24000, or 48000.
- * @param channels int: Number of channels to output.
- * This must be at most 255.
- * It may be different from the number of coded
- * channels (streams +
- * coupled_streams).
- * @param streams int: The total number of streams coded in the
- * input.
- * This must be no more than 255.
- * @param coupled_streams int: Number of streams to decode as coupled
- * (2 channel) streams.
- * This must be no larger than the total
- * number of streams.
- * Additionally, The total number of
- * coded channels (streams +
- * coupled_streams) must be no
- * more than 255.
- * @param[in] mapping const unsigned char[channels]: Mapping from
- * coded channels to output channels, as described in
- * @ref opus_multistream.
- * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
- * on failure.
- */
-OPUS_EXPORT int opus_multistream_decoder_init(
- OpusMSDecoder *st,
- opus_int32 Fs,
- int channels,
- int streams,
- int coupled_streams,
- const unsigned char *mapping
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
-
-/** Decode a multistream Opus packet.
- * @param st OpusMSDecoder*: Multistream decoder state.
- * @param[in] data const unsigned char*: Input payload.
- * Use a NULL
- * pointer to indicate packet
- * loss.
- * @param len opus_int32: Number of bytes in payload.
- * @param[out] pcm opus_int16*: Output signal, with interleaved
- * samples.
- * This must contain room for
- * frame_size*channels
- * samples.
- * @param frame_size int: The number of samples per channel of
- * available space in \a pcm.
- * If this is less than the maximum packet duration
- * (120 ms; 5760 for 48kHz), this function will not be capable
- * of decoding some packets. In the case of PLC (data==NULL)
- * or FEC (decode_fec=1), then frame_size needs to be exactly
- * the duration of audio that is missing, otherwise the
- * decoder will not be in the optimal state to decode the
- * next incoming packet. For the PLC and FEC cases, frame_size
- * must be a multiple of 2.5 ms.
- * @param decode_fec int: Flag (0 or 1) to request that any in-band
- * forward error correction data be decoded.
- * If no such data is available, the frame is
- * decoded as if it were lost.
- * @returns Number of samples decoded on success or a negative error code
- * (see @ref opus_errorcodes) on failure.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode(
- OpusMSDecoder *st,
- const unsigned char *data,
- opus_int32 len,
- opus_int16 *pcm,
- int frame_size,
- int decode_fec
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
-
-/** Decode a multistream Opus packet with floating point output.
- * @param st OpusMSDecoder*: Multistream decoder state.
- * @param[in] data const unsigned char*: Input payload.
- * Use a NULL
- * pointer to indicate packet
- * loss.
- * @param len opus_int32: Number of bytes in payload.
- * @param[out] pcm opus_int16*: Output signal, with interleaved
- * samples.
- * This must contain room for
- * frame_size*channels
- * samples.
- * @param frame_size int: The number of samples per channel of
- * available space in \a pcm.
- * If this is less than the maximum packet duration
- * (120 ms; 5760 for 48kHz), this function will not be capable
- * of decoding some packets. In the case of PLC (data==NULL)
- * or FEC (decode_fec=1), then frame_size needs to be exactly
- * the duration of audio that is missing, otherwise the
- * decoder will not be in the optimal state to decode the
- * next incoming packet. For the PLC and FEC cases, frame_size
- * must be a multiple of 2.5 ms.
- * @param decode_fec int: Flag (0 or 1) to request that any in-band
- * forward error correction data be decoded.
- * If no such data is available, the frame is
- * decoded as if it were lost.
- * @returns Number of samples decoded on success or a negative error code
- * (see @ref opus_errorcodes) on failure.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode_float(
- OpusMSDecoder *st,
- const unsigned char *data,
- opus_int32 len,
- float *pcm,
- int frame_size,
- int decode_fec
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
-
-/** Perform a CTL function on a multistream Opus decoder.
- *
- * Generally the request and subsequent arguments are generated by a
- * convenience macro.
- * @param st OpusMSDecoder*: Multistream decoder state.
- * @param request This and all remaining parameters should be replaced by one
- * of the convenience macros in @ref opus_genericctls,
- * @ref opus_decoderctls, or @ref opus_multistream_ctls.
- * @see opus_genericctls
- * @see opus_decoderctls
- * @see opus_multistream_ctls
- */
-OPUS_EXPORT int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
-
-/** Frees an OpusMSDecoder allocated by
- * opus_multistream_decoder_create().
- * @param st OpusMSDecoder: Multistream decoder state to be freed.
- */
-OPUS_EXPORT void opus_multistream_decoder_destroy(OpusMSDecoder *st);
-
-/**@}*/
-
-/**@}*/
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* OPUS_MULTISTREAM_H */
diff --git a/app/src/main/jni/nv_opus_dec/libopus/inc/opus_types.h b/app/src/main/jni/nv_opus_dec/libopus/inc/opus_types.h
deleted file mode 100644
index b28e03ae..00000000
--- a/app/src/main/jni/nv_opus_dec/libopus/inc/opus_types.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/* (C) COPYRIGHT 1994-2002 Xiph.Org Foundation */
-/* Modified by Jean-Marc Valin */
-/*
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/* opus_types.h based on ogg_types.h from libogg */
-
-/**
- @file opus_types.h
- @brief Opus reference implementation types
-*/
-#ifndef OPUS_TYPES_H
-#define OPUS_TYPES_H
-
-/* Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h) */
-#if (defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H))
-#include
-
- typedef int16_t opus_int16;
- typedef uint16_t opus_uint16;
- typedef int32_t opus_int32;
- typedef uint32_t opus_uint32;
-#elif defined(_WIN32)
-
-# if defined(__CYGWIN__)
-# include <_G_config.h>
- typedef _G_int32_t opus_int32;
- typedef _G_uint32_t opus_uint32;
- typedef _G_int16 opus_int16;
- typedef _G_uint16 opus_uint16;
-# elif defined(__MINGW32__)
- typedef short opus_int16;
- typedef unsigned short opus_uint16;
- typedef int opus_int32;
- typedef unsigned int opus_uint32;
-# elif defined(__MWERKS__)
- typedef int opus_int32;
- typedef unsigned int opus_uint32;
- typedef short opus_int16;
- typedef unsigned short opus_uint16;
-# else
- /* MSVC/Borland */
- typedef __int32 opus_int32;
- typedef unsigned __int32 opus_uint32;
- typedef __int16 opus_int16;
- typedef unsigned __int16 opus_uint16;
-# endif
-
-#elif defined(__MACOS__)
-
-# include
- typedef SInt16 opus_int16;
- typedef UInt16 opus_uint16;
- typedef SInt32 opus_int32;
- typedef UInt32 opus_uint32;
-
-#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
-
-# include
- typedef int16_t opus_int16;
- typedef u_int16_t opus_uint16;
- typedef int32_t opus_int32;
- typedef u_int32_t opus_uint32;
-
-#elif defined(__BEOS__)
-
- /* Be */
-# include
- typedef int16 opus_int16;
- typedef u_int16 opus_uint16;
- typedef int32_t opus_int32;
- typedef u_int32_t opus_uint32;
-
-#elif defined (__EMX__)
-
- /* OS/2 GCC */
- typedef short opus_int16;
- typedef unsigned short opus_uint16;
- typedef int opus_int32;
- typedef unsigned int opus_uint32;
-
-#elif defined (DJGPP)
-
- /* DJGPP */
- typedef short opus_int16;
- typedef unsigned short opus_uint16;
- typedef int opus_int32;
- typedef unsigned int opus_uint32;
-
-#elif defined(R5900)
-
- /* PS2 EE */
- typedef int opus_int32;
- typedef unsigned opus_uint32;
- typedef short opus_int16;
- typedef unsigned short opus_uint16;
-
-#elif defined(__SYMBIAN32__)
-
- /* Symbian GCC */
- typedef signed short opus_int16;
- typedef unsigned short opus_uint16;
- typedef signed int opus_int32;
- typedef unsigned int opus_uint32;
-
-#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
-
- typedef short opus_int16;
- typedef unsigned short opus_uint16;
- typedef long opus_int32;
- typedef unsigned long opus_uint32;
-
-#elif defined(CONFIG_TI_C6X)
-
- typedef short opus_int16;
- typedef unsigned short opus_uint16;
- typedef int opus_int32;
- typedef unsigned int opus_uint32;
-
-#else
-
- /* Give up, take a reasonable guess */
- typedef short opus_int16;
- typedef unsigned short opus_uint16;
- typedef int opus_int32;
- typedef unsigned int opus_uint32;
-
-#endif
-
-#define opus_int int /* used for counters etc; at least 16 bits */
-#define opus_int64 long long
-#define opus_int8 signed char
-
-#define opus_uint unsigned int /* used for counters etc; at least 16 bits */
-#define opus_uint64 unsigned long long
-#define opus_uint8 unsigned char
-
-#endif /* OPUS_TYPES_H */
diff --git a/app/src/main/jni/nv_opus_dec/libopus/mips/libopus.a b/app/src/main/jni/nv_opus_dec/libopus/mips/libopus.a
deleted file mode 100644
index e8b55fb4..00000000
Binary files a/app/src/main/jni/nv_opus_dec/libopus/mips/libopus.a and /dev/null differ
diff --git a/app/src/main/jni/nv_opus_dec/libopus/mips64/libopus.a b/app/src/main/jni/nv_opus_dec/libopus/mips64/libopus.a
deleted file mode 100644
index 460f5b4c..00000000
Binary files a/app/src/main/jni/nv_opus_dec/libopus/mips64/libopus.a and /dev/null differ
diff --git a/app/src/main/jni/nv_opus_dec/libopus/x86/libopus.a b/app/src/main/jni/nv_opus_dec/libopus/x86/libopus.a
deleted file mode 100644
index 0907e0f2..00000000
Binary files a/app/src/main/jni/nv_opus_dec/libopus/x86/libopus.a and /dev/null differ
diff --git a/app/src/main/jni/nv_opus_dec/libopus/x86_64/libopus.a b/app/src/main/jni/nv_opus_dec/libopus/x86_64/libopus.a
deleted file mode 100644
index e9c0d3a8..00000000
Binary files a/app/src/main/jni/nv_opus_dec/libopus/x86_64/libopus.a and /dev/null differ
diff --git a/app/src/main/jni/nv_opus_dec/nv_opus_dec.c b/app/src/main/jni/nv_opus_dec/nv_opus_dec.c
deleted file mode 100644
index 084f0022..00000000
--- a/app/src/main/jni/nv_opus_dec/nv_opus_dec.c
+++ /dev/null
@@ -1,42 +0,0 @@
-#include
-#include
-#include "nv_opus_dec.h"
-
-OpusMSDecoder* decoder;
-
-// This function must be called before
-// any other decoding functions
-int nv_opus_init(int sampleRate, int channelCount, int streams,
- int coupledStreams, const unsigned char *mapping) {
- int err;
- decoder = opus_multistream_decoder_create(
- sampleRate,
- channelCount,
- streams,
- coupledStreams,
- mapping,
- &err);
- return err;
-}
-
-// This function must be called after
-// decoding is finished
-void nv_opus_destroy(void) {
- if (decoder != NULL) {
- opus_multistream_decoder_destroy(decoder);
- }
-}
-
-// packets must be decoded in order
-// a packet loss must call this function with NULL indata and 0 inlen
-// returns the number of decoded samples
-int nv_opus_decode(unsigned char* indata, int inlen, short* outpcmdata, int framesize) {
- int err;
-
- // Decoding to 16-bit PCM with FEC off
- // Maximum length assuming 48KHz sample rate
- err = opus_multistream_decode(decoder, indata, inlen,
- outpcmdata, framesize, 0);
-
- return err;
-}
diff --git a/app/src/main/jni/nv_opus_dec/nv_opus_dec.h b/app/src/main/jni/nv_opus_dec/nv_opus_dec.h
deleted file mode 100644
index 2ccb31c6..00000000
--- a/app/src/main/jni/nv_opus_dec/nv_opus_dec.h
+++ /dev/null
@@ -1,4 +0,0 @@
-int nv_opus_init(int sampleRate, int channelCount, int streams,
- int coupledStreams, const unsigned char *mapping);
-void nv_opus_destroy(void);
-int nv_opus_decode(unsigned char* indata, int inlen, short* outpcmdata, int framesize);
diff --git a/app/src/main/jni/nv_opus_dec/nv_opus_dec_jni.c b/app/src/main/jni/nv_opus_dec/nv_opus_dec_jni.c
deleted file mode 100644
index 33169d37..00000000
--- a/app/src/main/jni/nv_opus_dec/nv_opus_dec_jni.c
+++ /dev/null
@@ -1,71 +0,0 @@
-#include "nv_opus_dec.h"
-
-#include
-#include
-
-static int SamplesPerChannel;
-static int ChannelCount;
-
-// This function must be called before
-// any other decoding functions
-JNIEXPORT jint JNICALL
-Java_com_limelight_nvstream_av_audio_OpusDecoder_init(JNIEnv *env, jobject this, int sampleRate,
- int samplesPerChannel, int channelCount, int streams,
- int coupledStreams, jbyteArray mapping) {
- jbyte* jni_mapping_data;
- jint ret;
-
- SamplesPerChannel = samplesPerChannel;
- ChannelCount = channelCount;
-
- jni_mapping_data = (*env)->GetByteArrayElements(env, mapping, 0);
- ret = nv_opus_init(sampleRate, channelCount, streams, coupledStreams,
- (const unsigned char*)jni_mapping_data);
- (*env)->ReleaseByteArrayElements(env, mapping, jni_mapping_data, JNI_ABORT);
-
- return ret;
-}
-
-// This function must be called after
-// decoding is finished
-JNIEXPORT void JNICALL
-Java_com_limelight_nvstream_av_audio_OpusDecoder_destroy(JNIEnv *env, jobject this) {
- nv_opus_destroy();
-}
-
-// packets must be decoded in order
-// a packet loss must call this function with NULL indata and 0 inlen
-// returns the number of decoded bytes
-JNIEXPORT jint JNICALL
-Java_com_limelight_nvstream_av_audio_OpusDecoder_decode(
- JNIEnv *env, jobject this, // JNI parameters
- jbyteArray indata, jint inoff, jint inlen, // Input parameters
- jbyteArray outpcmdata) // Output parameter
-{
- jint ret;
- jbyte* jni_input_data;
- jbyte* jni_pcm_data;
-
- jni_pcm_data = (*env)->GetByteArrayElements(env, outpcmdata, 0);
- if (indata != NULL) {
- jni_input_data = (*env)->GetByteArrayElements(env, indata, 0);
-
- ret = nv_opus_decode((unsigned char*)&jni_input_data[inoff], inlen,
- (jshort*)jni_pcm_data, SamplesPerChannel);
-
- // The input data isn't changed so it can be safely aborted
- (*env)->ReleaseByteArrayElements(env, indata, jni_input_data, JNI_ABORT);
- }
- else {
- ret = nv_opus_decode(NULL, 0, (jshort*)jni_pcm_data, SamplesPerChannel);
- }
-
- // Convert samples (2 bytes) per channel to total bytes returned
- if (ret > 0) {
- ret *= ChannelCount * 2;
- }
-
- (*env)->ReleaseByteArrayElements(env, outpcmdata, jni_pcm_data, 0);
-
- return ret;
-}
diff --git a/app/src/main/res/layout-land/activity_pc_view.xml b/app/src/main/res/layout-land/activity_pc_view.xml
index 0b0c3f43..dcfdee1c 100644
--- a/app/src/main/res/layout-land/activity_pc_view.xml
+++ b/app/src/main/res/layout-land/activity_pc_view.xml
@@ -50,6 +50,7 @@
android:layout_height="65dp"
android:cropToPadding="false"
android:scaleType="fitXY"
+ android:nextFocusForward="@id/helpButton"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
@@ -62,6 +63,7 @@
android:layout_height="65dp"
android:cropToPadding="false"
android:scaleType="fitXY"
+ android:nextFocusForward="@id/manuallyAddPc"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_below="@id/settingsButton"
diff --git a/app/src/main/res/layout/pc_grid_view.xml b/app/src/main/res/layout/pc_grid_view.xml
index bce5a0e2..1ad5d141 100644
--- a/app/src/main/res/layout/pc_grid_view.xml
+++ b/app/src/main/res/layout/pc_grid_view.xml
@@ -10,5 +10,6 @@
android:columnWidth="160dp"
android:focusable="true"
android:focusableInTouchMode="true"
+ android:nextFocusLeft="@id/settingsButton"
android:gravity="center"/>
\ No newline at end of file
diff --git a/app/src/main/res/layout/pc_grid_view_small.xml b/app/src/main/res/layout/pc_grid_view_small.xml
index 1dde64e4..c1e6ca35 100644
--- a/app/src/main/res/layout/pc_grid_view_small.xml
+++ b/app/src/main/res/layout/pc_grid_view_small.xml
@@ -10,5 +10,6 @@
android:columnWidth="105dp"
android:focusable="true"
android:focusableInTouchMode="true"
+ android:nextFocusLeft="@id/settingsButton"
android:gravity="center"/>
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 1c2d0680..f6627fcf 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,7 +4,7 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.3.1'
+ classpath 'com.android.tools.build:gradle:2.3.2'
}
}
diff --git a/moonlight-common b/moonlight-common
new file mode 160000
index 00000000..4c2dc16a
--- /dev/null
+++ b/moonlight-common
@@ -0,0 +1 @@
+Subproject commit 4c2dc16aefbb516da42399c0fb06bff19a2629e6
diff --git a/settings.gradle b/settings.gradle
index e7b4def4..c6a62006 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1 +1 @@
-include ':app'
+include ':app', ':moonlight-common'