From bc51ca44fc649d0fba7795d982bea09440e0de84 Mon Sep 17 00:00:00 2001 From: pedro Date: Mon, 18 Sep 2023 21:33:05 +0200 Subject: [PATCH] add encoders error callback --- .../java/com/pedro/encoder/BaseEncoder.java | 19 ++++++++++++++---- .../com/pedro/encoder/EncoderErrorCallback.kt | 16 +++++++++++++++ .../input/audio/MicrophoneManager.java | 20 ++++++++----------- .../com/pedro/library/base/Camera1Base.java | 10 ++++++++++ .../com/pedro/library/base/Camera2Base.java | 10 ++++++++++ .../com/pedro/library/base/DisplayBase.java | 10 ++++++++++ .../com/pedro/library/base/FromFileBase.java | 10 ++++++++++ .../com/pedro/library/base/OnlyAudioBase.java | 9 +++++++++ .../java/com/pedro/library/base/StreamBase.kt | 10 ++++++++++ 9 files changed, 98 insertions(+), 16 deletions(-) create mode 100644 encoder/src/main/java/com/pedro/encoder/EncoderErrorCallback.kt diff --git a/encoder/src/main/java/com/pedro/encoder/BaseEncoder.java b/encoder/src/main/java/com/pedro/encoder/BaseEncoder.java index 431fd549b..c59096df5 100644 --- a/encoder/src/main/java/com/pedro/encoder/BaseEncoder.java +++ b/encoder/src/main/java/com/pedro/encoder/BaseEncoder.java @@ -52,6 +52,11 @@ public abstract class BaseEncoder implements EncoderCallback { protected boolean shouldReset = true; protected boolean prepared = false; private Handler handler; + private EncoderErrorCallback encoderErrorCallback; + + public void setEncoderErrorCallback(EncoderErrorCallback encoderErrorCallback) { + this.encoderErrorCallback = encoderErrorCallback; + } public void restart() { start(false); @@ -86,7 +91,7 @@ private void initCodec() { getDataFromEncoder(); } catch (IllegalStateException e) { Log.i(TAG, "Encoding error", e); - reloadCodec(); + reloadCodec(e); } } }); @@ -108,8 +113,12 @@ protected void fixTimeStamp(MediaCodec.BufferInfo info) { } } - private void reloadCodec() { + private void reloadCodec(IllegalStateException e) { //Sometimes encoder crash, we will try recover it. Reset encoder a time if crash + EncoderErrorCallback callback = encoderErrorCallback; + if (callback != null) { + shouldReset = callback.onEncodeError(TAG, e); + } if (shouldReset) { Log.e(TAG, "Encoder crashed, trying to recover it"); reset(); @@ -254,7 +263,7 @@ public void onInputBufferAvailable(@NonNull MediaCodec mediaCodec, int inBufferI inputAvailable(mediaCodec, inBufferIndex); } catch (IllegalStateException e) { Log.i(TAG, "Encoding error", e); - reloadCodec(); + reloadCodec(e); } } @@ -265,13 +274,15 @@ public void onOutputBufferAvailable(@NonNull MediaCodec mediaCodec, int outBuffe outputAvailable(mediaCodec, outBufferIndex, bufferInfo); } catch (IllegalStateException e) { Log.i(TAG, "Encoding error", e); - reloadCodec(); + reloadCodec(e); } } @Override public void onError(@NonNull MediaCodec mediaCodec, @NonNull MediaCodec.CodecException e) { Log.e(TAG, "Error", e); + EncoderErrorCallback callback = encoderErrorCallback; + if (callback != null) callback.onCodecError(TAG, e); } @Override diff --git a/encoder/src/main/java/com/pedro/encoder/EncoderErrorCallback.kt b/encoder/src/main/java/com/pedro/encoder/EncoderErrorCallback.kt new file mode 100644 index 000000000..6986edce0 --- /dev/null +++ b/encoder/src/main/java/com/pedro/encoder/EncoderErrorCallback.kt @@ -0,0 +1,16 @@ +package com.pedro.encoder + +import android.media.MediaCodec +import java.lang.IllegalStateException + +/** + * Created by pedro on 18/9/23. + */ +interface EncoderErrorCallback { + fun onCodecError(type: String, e: MediaCodec.CodecException) + + /** + * @return indicate if should try reset encoder + */ + fun onEncodeError(type: String, e: IllegalStateException): Boolean = true +} \ No newline at end of file diff --git a/encoder/src/main/java/com/pedro/encoder/input/audio/MicrophoneManager.java b/encoder/src/main/java/com/pedro/encoder/input/audio/MicrophoneManager.java index f319ec6e0..d045f70b3 100644 --- a/encoder/src/main/java/com/pedro/encoder/input/audio/MicrophoneManager.java +++ b/encoder/src/main/java/com/pedro/encoder/input/audio/MicrophoneManager.java @@ -97,7 +97,7 @@ public boolean createMicrophone(int audioSource, int sampleRate, boolean isStere if (noiseSuppressor) audioPostProcessEffect.enableNoiseSuppressor(); String chl = (isStereo) ? "Stereo" : "Mono"; if (audioRecord.getState() != AudioRecord.STATE_INITIALIZED) { - throw new IllegalArgumentException("Some parameters specified is not valid"); + throw new IllegalArgumentException("Some parameters specified are not valid"); } Log.i(TAG, "Microphone created, " + sampleRate + "hz, " + chl); created = true; @@ -138,7 +138,7 @@ public boolean createInternalMicrophone(AudioPlaybackCaptureConfiguration config if (noiseSuppressor) audioPostProcessEffect.enableNoiseSuppressor(); String chl = (isStereo) ? "Stereo" : "Mono"; if (audioRecord.getState() != AudioRecord.STATE_INITIALIZED) { - throw new IllegalArgumentException("Some parameters specified is not valid"); + throw new IllegalArgumentException("Some parameters specified are not valid"); } Log.i(TAG, "Internal microphone created, " + sampleRate + "hz, " + chl); created = true; @@ -164,14 +164,11 @@ public synchronized void start() { handlerThread = new HandlerThread(TAG); handlerThread.start(); Handler handler = new Handler(handlerThread.getLooper()); - handler.post(new Runnable() { - @Override - public void run() { - while (running) { - Frame frame = read(); - if (frame != null) { - getMicrophoneData.inputPCMData(frame); - } + handler.post(() -> { + while (running) { + Frame frame = read(); + if (frame != null) { + getMicrophoneData.inputPCMData(frame); } } }); @@ -183,8 +180,7 @@ private void init() { running = true; Log.i(TAG, "Microphone started"); } else { - Log.e(TAG, "Error starting, microphone was stopped or not created, " - + "use createMicrophone() before start()"); + throw new IllegalStateException("Error starting, microphone was stopped or not created, use createMicrophone() before start()"); } } diff --git a/library/src/main/java/com/pedro/library/base/Camera1Base.java b/library/src/main/java/com/pedro/library/base/Camera1Base.java index 73c31a774..9dd76267d 100644 --- a/library/src/main/java/com/pedro/library/base/Camera1Base.java +++ b/library/src/main/java/com/pedro/library/base/Camera1Base.java @@ -33,6 +33,7 @@ import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; +import com.pedro.encoder.EncoderErrorCallback; import com.pedro.encoder.Frame; import com.pedro.encoder.audio.AudioEncoder; import com.pedro.encoder.audio.GetAacData; @@ -172,6 +173,15 @@ public void setCameraCallbacks(CameraCallbacks callbacks) { cameraManager.setCameraCallbacks(callbacks); } + /** + * Set a callback to know errors related with Video/Audio encoders + * @param encoderErrorCallback callback to use, null to remove + */ + public void setEncoderErrorCallback(EncoderErrorCallback encoderErrorCallback) { + videoEncoder.setEncoderErrorCallback(encoderErrorCallback); + audioEncoder.setEncoderErrorCallback(encoderErrorCallback); + } + /** * Set an audio effect modifying microphone's PCM buffer. */ diff --git a/library/src/main/java/com/pedro/library/base/Camera2Base.java b/library/src/main/java/com/pedro/library/base/Camera2Base.java index b31bf9fc1..11b01097f 100644 --- a/library/src/main/java/com/pedro/library/base/Camera2Base.java +++ b/library/src/main/java/com/pedro/library/base/Camera2Base.java @@ -35,6 +35,7 @@ import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; +import com.pedro.encoder.EncoderErrorCallback; import com.pedro.encoder.Frame; import com.pedro.encoder.audio.AudioEncoder; import com.pedro.encoder.audio.GetAacData; @@ -184,6 +185,15 @@ public void setCameraCallbacks(CameraCallbacks callbacks) { cameraManager.setCameraCallbacks(callbacks); } + /** + * Set a callback to know errors related with Video/Audio encoders + * @param encoderErrorCallback callback to use, null to remove + */ + public void setEncoderErrorCallback(EncoderErrorCallback encoderErrorCallback) { + videoEncoder.setEncoderErrorCallback(encoderErrorCallback); + audioEncoder.setEncoderErrorCallback(encoderErrorCallback); + } + /** * Set an audio effect modifying microphone's PCM buffer. */ diff --git a/library/src/main/java/com/pedro/library/base/DisplayBase.java b/library/src/main/java/com/pedro/library/base/DisplayBase.java index e40a793af..f2b9d8778 100644 --- a/library/src/main/java/com/pedro/library/base/DisplayBase.java +++ b/library/src/main/java/com/pedro/library/base/DisplayBase.java @@ -36,6 +36,7 @@ import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; +import com.pedro.encoder.EncoderErrorCallback; import com.pedro.encoder.Frame; import com.pedro.encoder.audio.AudioEncoder; import com.pedro.encoder.audio.GetAacData; @@ -123,6 +124,15 @@ public void setMicrophoneMode(MicrophoneMode microphoneMode) { } } + /** + * Set a callback to know errors related with Video/Audio encoders + * @param encoderErrorCallback callback to use, null to remove + */ + public void setEncoderErrorCallback(EncoderErrorCallback encoderErrorCallback) { + videoEncoder.setEncoderErrorCallback(encoderErrorCallback); + audioEncoder.setEncoderErrorCallback(encoderErrorCallback); + } + /** * Set an audio effect modifying microphone's PCM buffer. */ diff --git a/library/src/main/java/com/pedro/library/base/FromFileBase.java b/library/src/main/java/com/pedro/library/base/FromFileBase.java index 0dc0c75ee..eb9cd77a9 100644 --- a/library/src/main/java/com/pedro/library/base/FromFileBase.java +++ b/library/src/main/java/com/pedro/library/base/FromFileBase.java @@ -28,6 +28,7 @@ import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; +import com.pedro.encoder.EncoderErrorCallback; import com.pedro.encoder.Frame; import com.pedro.encoder.audio.AudioEncoder; import com.pedro.encoder.audio.GetAacData; @@ -225,6 +226,15 @@ public boolean isAudioDeviceEnabled() { && audioTrackPlayer.getPlayState() == AudioTrack.PLAYSTATE_PLAYING; } + /** + * Set a callback to know errors related with Video/Audio encoders + * @param encoderErrorCallback callback to use, null to remove + */ + public void setEncoderErrorCallback(EncoderErrorCallback encoderErrorCallback) { + videoEncoder.setEncoderErrorCallback(encoderErrorCallback); + audioEncoder.setEncoderErrorCallback(encoderErrorCallback); + } + public void playAudioDevice() { if (audioEnabled) { if (isAudioDeviceEnabled()) { diff --git a/library/src/main/java/com/pedro/library/base/OnlyAudioBase.java b/library/src/main/java/com/pedro/library/base/OnlyAudioBase.java index 3fec1aea7..ba2370c3e 100644 --- a/library/src/main/java/com/pedro/library/base/OnlyAudioBase.java +++ b/library/src/main/java/com/pedro/library/base/OnlyAudioBase.java @@ -25,6 +25,7 @@ import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; +import com.pedro.encoder.EncoderErrorCallback; import com.pedro.encoder.Frame; import com.pedro.encoder.audio.AudioEncoder; import com.pedro.encoder.audio.GetAacData; @@ -86,6 +87,14 @@ public void setMicrophoneMode(MicrophoneMode microphoneMode) { } } + /** + * Set a callback to know errors related with Video/Audio encoders + * @param encoderErrorCallback callback to use, null to remove + */ + public void setEncoderErrorCallback(EncoderErrorCallback encoderErrorCallback) { + audioEncoder.setEncoderErrorCallback(encoderErrorCallback); + } + /** * Set an audio effect modifying microphone's PCM buffer. */ diff --git a/library/src/main/java/com/pedro/library/base/StreamBase.kt b/library/src/main/java/com/pedro/library/base/StreamBase.kt index 00e64ea85..7cdc0aedf 100644 --- a/library/src/main/java/com/pedro/library/base/StreamBase.kt +++ b/library/src/main/java/com/pedro/library/base/StreamBase.kt @@ -13,6 +13,7 @@ import android.view.Surface import android.view.SurfaceView import android.view.TextureView import androidx.annotation.RequiresApi +import com.pedro.encoder.EncoderErrorCallback import com.pedro.encoder.Frame import com.pedro.encoder.audio.AudioEncoder import com.pedro.encoder.audio.GetAacData @@ -267,6 +268,15 @@ abstract class StreamBase( audioManager.changeAudioSourceDisabled() } + /** + * Set a callback to know errors related with Video/Audio encoders + * @param encoderErrorCallback callback to use, null to remove + */ + fun setEncoderErrorCallback(encoderErrorCallback: EncoderErrorCallback?) { + videoEncoder.setEncoderErrorCallback(encoderErrorCallback) + audioEncoder.setEncoderErrorCallback(encoderErrorCallback) + } + /** * Set a custom size of audio buffer input. * If you set 0 or less you can disable it to use library default value.