From 90431d7e2eea03cc9b31783236d723b466e48aa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Sat, 28 Sep 2019 11:50:46 +0200 Subject: [PATCH] Shutdown Decoders on Android --- android/app/src/main/cpp/audio-decoder.c | 44 ++++++++++++++++++----- android/app/src/main/cpp/audio-decoder.h | 2 ++ android/app/src/main/cpp/audio-output.cpp | 2 +- android/app/src/main/cpp/chiaki-jni.c | 3 +- android/app/src/main/cpp/circular-buf.hpp | 2 +- android/app/src/main/cpp/video-decoder.c | 32 ++++++++++++----- android/app/src/main/cpp/video-decoder.h | 2 +- 7 files changed, 66 insertions(+), 21 deletions(-) diff --git a/android/app/src/main/cpp/audio-decoder.c b/android/app/src/main/cpp/audio-decoder.c index 8d52a12..f7a979d 100644 --- a/android/app/src/main/cpp/audio-decoder.c +++ b/android/app/src/main/cpp/audio-decoder.c @@ -41,12 +41,31 @@ ChiakiErrorCode android_chiaki_audio_decoder_init(AndroidChiakiAudioDecoder *dec decoder->settings_cb = NULL; decoder->frame_cb = NULL; - return CHIAKI_ERR_SUCCESS; + return chiaki_mutex_init(&decoder->codec_mutex, true); +} + +void android_chiaki_audio_decoder_shutdown_codec(AndroidChiakiAudioDecoder *decoder) +{ + chiaki_mutex_lock(&decoder->codec_mutex); + ssize_t codec_buf_index = AMediaCodec_dequeueInputBuffer(decoder->codec, -1); + if(codec_buf_index >= 0) + { + CHIAKI_LOGI(decoder->log, "Audio Decoder sending EOS buffer"); + AMediaCodec_queueInputBuffer(decoder->codec, (size_t)codec_buf_index, 0, 0, decoder->timestamp_cur++, AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM); + } + else + CHIAKI_LOGE(decoder->log, "Failed to get input buffer for shutting down Audio Decoder!"); + chiaki_mutex_unlock(&decoder->codec_mutex); + chiaki_thread_join(&decoder->output_thread, NULL); + AMediaCodec_delete(decoder->codec); + decoder->codec = NULL; } void android_chiaki_audio_decoder_fini(AndroidChiakiAudioDecoder *decoder) { - // TODO: shutdown (thread may or may not be running!) + if(decoder->codec) + android_chiaki_audio_decoder_shutdown_codec(decoder); + chiaki_mutex_fini(&decoder->codec_mutex); } void android_chiaki_audio_decoder_get_sink(AndroidChiakiAudioDecoder *decoder, ChiakiAudioSink *sink) @@ -83,20 +102,21 @@ static void *android_chiaki_audio_decoder_output_thread_func(void *user) } } + CHIAKI_LOGI(decoder->log, "Audio Decoder Output Thread exiting"); + return NULL; } static void android_chiaki_audio_decoder_header(ChiakiAudioHeader *header, void *user) { AndroidChiakiAudioDecoder *decoder = user; + chiaki_mutex_lock(&decoder->codec_mutex); memcpy(&decoder->audio_header, header, sizeof(decoder->audio_header)); if(decoder->codec) { - CHIAKI_LOGI(decoder->log, "Audio decoder already initialized, re-creating"); - // TODO: stop thread - AMediaCodec_delete(decoder->codec); - decoder->codec = NULL; + CHIAKI_LOGI(decoder->log, "Audio decoder already initialized, shutting down the old one"); + android_chiaki_audio_decoder_shutdown_codec(decoder); } const char *mime = "audio/opus"; @@ -104,7 +124,7 @@ static void android_chiaki_audio_decoder_header(ChiakiAudioHeader *header, void if(!decoder->codec) { CHIAKI_LOGE(decoder->log, "Failed to create AMediaCodec for mime type %s", mime); - return; + goto beach; } AMediaFormat *format = AMediaFormat_new(); @@ -126,7 +146,6 @@ static void android_chiaki_audio_decoder_header(ChiakiAudioHeader *header, void decoder->codec = NULL; } - uint8_t opus_id_head[0x13]; memcpy(opus_id_head, "OpusHead", 8); opus_id_head[0x8] = 1; // version @@ -157,16 +176,20 @@ static void android_chiaki_audio_decoder_header(ChiakiAudioHeader *header, void if(decoder->settings_cb) decoder->settings_cb(header->channels, header->rate, decoder->cb_user); + +beach: + chiaki_mutex_unlock(&decoder->codec_mutex); } static void android_chiaki_audio_decoder_frame(uint8_t *buf, size_t buf_size, void *user) { AndroidChiakiAudioDecoder *decoder = user; + chiaki_mutex_lock(&decoder->codec_mutex); if(!decoder->codec) { CHIAKI_LOGE(decoder->log, "Received audio data, but decoder is not initialized!"); - return; + goto beach; } while(buf_size > 0) @@ -191,4 +214,7 @@ static void android_chiaki_audio_decoder_frame(uint8_t *buf, size_t buf_size, vo buf += codec_sample_size; buf_size -= codec_sample_size; } + +beach: + chiaki_mutex_unlock(&decoder->codec_mutex); } \ No newline at end of file diff --git a/android/app/src/main/cpp/audio-decoder.h b/android/app/src/main/cpp/audio-decoder.h index 0597758..c237b4b 100644 --- a/android/app/src/main/cpp/audio-decoder.h +++ b/android/app/src/main/cpp/audio-decoder.h @@ -31,6 +31,8 @@ typedef struct android_chiaki_audio_decoder_t { ChiakiLog *log; ChiakiAudioHeader audio_header; + + ChiakiMutex codec_mutex; struct AMediaCodec *codec; uint64_t timestamp_cur; ChiakiThread output_thread; diff --git a/android/app/src/main/cpp/audio-output.cpp b/android/app/src/main/cpp/audio-output.cpp index 1961ff8..32495f5 100644 --- a/android/app/src/main/cpp/audio-output.cpp +++ b/android/app/src/main/cpp/audio-output.cpp @@ -121,7 +121,7 @@ oboe::DataCallbackResult AudioOutputCallback::onAudioReady(oboe::AudioStream *st if(buf_size_delivered < buf_size_requested) { - CHIAKI_LOGW(audio_output->log, "Audio Output Buffer Underflow!"); + CHIAKI_LOGV(audio_output->log, "Audio Output Buffer Underflow!"); memset(buf + buf_size_delivered, 0, buf_size_requested - buf_size_delivered); } diff --git a/android/app/src/main/cpp/chiaki-jni.c b/android/app/src/main/cpp/chiaki-jni.c index 7e1c01e..9e1acc5 100644 --- a/android/app/src/main/cpp/chiaki-jni.c +++ b/android/app/src/main/cpp/chiaki-jni.c @@ -281,7 +281,7 @@ beach: JNIEXPORT void JNICALL Java_com_metallic_chiaki_lib_ChiakiNative_sessionFree(JNIEnv *env, jobject obj, jlong ptr) { AndroidChiakiSession *session = (AndroidChiakiSession *)ptr; - CHIAKI_LOGI(&global_log, "Free JNI Session"); + CHIAKI_LOGI(&global_log, "Shutting down JNI Session"); if(!session) return; chiaki_session_fini(&session->session); @@ -290,6 +290,7 @@ JNIEXPORT void JNICALL Java_com_metallic_chiaki_lib_ChiakiNative_sessionFree(JNI android_chiaki_audio_decoder_fini(&session->audio_decoder); android_chiaki_audio_output_free(session->audio_output); E->DeleteGlobalRef(env, session->java_session); + CHIAKI_LOGI(&global_log, "JNI Session has quit"); } JNIEXPORT jint JNICALL Java_com_metallic_chiaki_lib_ChiakiNative_sessionStart(JNIEnv *env, jobject obj, jlong ptr) diff --git a/android/app/src/main/cpp/circular-buf.hpp b/android/app/src/main/cpp/circular-buf.hpp index 73aa38f..d4fe1dc 100644 --- a/android/app/src/main/cpp/circular-buf.hpp +++ b/android/app/src/main/cpp/circular-buf.hpp @@ -63,7 +63,7 @@ class CircularBuffer ~CircularBuffer() { - delete buffer; + delete [] buffer; } /** diff --git a/android/app/src/main/cpp/video-decoder.c b/android/app/src/main/cpp/video-decoder.c index b2a0437..dc7a72c 100644 --- a/android/app/src/main/cpp/video-decoder.c +++ b/android/app/src/main/cpp/video-decoder.c @@ -34,18 +34,32 @@ ChiakiErrorCode android_chiaki_video_decoder_init(AndroidChiakiVideoDecoder *dec decoder->log = log; decoder->codec = NULL; decoder->timestamp_cur = 0; - return chiaki_mutex_init(&decoder->mutex, false); + return chiaki_mutex_init(&decoder->codec_mutex, false); } void android_chiaki_video_decoder_fini(AndroidChiakiVideoDecoder *decoder) { - // TODO: shutdown (thread may or may not be running!) - chiaki_mutex_fini(&decoder->mutex); + if(decoder->codec) + { + chiaki_mutex_lock(&decoder->codec_mutex); + ssize_t codec_buf_index = AMediaCodec_dequeueInputBuffer(decoder->codec, -1); + if(codec_buf_index >= 0) + { + CHIAKI_LOGI(decoder->log, "Video Decoder sending EOS buffer"); + AMediaCodec_queueInputBuffer(decoder->codec, (size_t)codec_buf_index, 0, 0, decoder->timestamp_cur++, AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM); + } + else + CHIAKI_LOGE(decoder->log, "Failed to get input buffer for shutting down Video Decoder!"); + chiaki_mutex_unlock(&decoder->codec_mutex); + chiaki_thread_join(&decoder->output_thread, NULL); + AMediaCodec_delete(decoder->codec); + } + chiaki_mutex_fini(&decoder->codec_mutex); } void android_chiaki_video_decoder_set_surface(AndroidChiakiVideoDecoder *decoder, JNIEnv *env, jobject surface) { - chiaki_mutex_lock(&decoder->mutex); + chiaki_mutex_lock(&decoder->codec_mutex); if(decoder->codec) { @@ -92,13 +106,13 @@ void android_chiaki_video_decoder_set_surface(AndroidChiakiVideoDecoder *decoder } beach: - chiaki_mutex_unlock(&decoder->mutex); + chiaki_mutex_unlock(&decoder->codec_mutex); } void android_chiaki_video_decoder_video_sample(uint8_t *buf, size_t buf_size, void *user) { AndroidChiakiVideoDecoder *decoder = user; - chiaki_mutex_lock(&decoder->mutex); + chiaki_mutex_lock(&decoder->codec_mutex); if(!decoder->codec) { @@ -121,7 +135,7 @@ void android_chiaki_video_decoder_video_sample(uint8_t *buf, size_t buf_size, vo size_t codec_sample_size = buf_size; if(codec_sample_size > codec_buf_size) { - CHIAKI_LOGD(decoder->log, "Sample is bigger than buffer, splitting"); + //CHIAKI_LOGD(decoder->log, "Sample is bigger than buffer, splitting"); codec_sample_size = codec_buf_size; } memcpy(codec_buf, buf, codec_sample_size); @@ -132,7 +146,7 @@ void android_chiaki_video_decoder_video_sample(uint8_t *buf, size_t buf_size, vo } beach: - chiaki_mutex_unlock(&decoder->mutex); + chiaki_mutex_unlock(&decoder->codec_mutex); } static void *android_chiaki_video_decoder_output_thread_func(void *user) @@ -154,5 +168,7 @@ static void *android_chiaki_video_decoder_output_thread_func(void *user) } } + CHIAKI_LOGI(decoder->log, "Video Decoder Output Thread exiting"); + return NULL; } \ No newline at end of file diff --git a/android/app/src/main/cpp/video-decoder.h b/android/app/src/main/cpp/video-decoder.h index 0bff080..7c60652 100644 --- a/android/app/src/main/cpp/video-decoder.h +++ b/android/app/src/main/cpp/video-decoder.h @@ -29,7 +29,7 @@ typedef struct ANativeWindow ANativeWindow; typedef struct android_chiaki_video_decoder_t { ChiakiLog *log; - ChiakiMutex mutex; + ChiakiMutex codec_mutex; AMediaCodec *codec; ANativeWindow *window; uint64_t timestamp_cur;