Shutdown Decoders on Android

This commit is contained in:
Florian Märkl 2019-09-28 11:50:46 +02:00
commit 90431d7e2e
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
7 changed files with 66 additions and 21 deletions

View file

@ -41,12 +41,31 @@ ChiakiErrorCode android_chiaki_audio_decoder_init(AndroidChiakiAudioDecoder *dec
decoder->settings_cb = NULL; decoder->settings_cb = NULL;
decoder->frame_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) 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) 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; return NULL;
} }
static void android_chiaki_audio_decoder_header(ChiakiAudioHeader *header, void *user) static void android_chiaki_audio_decoder_header(ChiakiAudioHeader *header, void *user)
{ {
AndroidChiakiAudioDecoder *decoder = user; AndroidChiakiAudioDecoder *decoder = user;
chiaki_mutex_lock(&decoder->codec_mutex);
memcpy(&decoder->audio_header, header, sizeof(decoder->audio_header)); memcpy(&decoder->audio_header, header, sizeof(decoder->audio_header));
if(decoder->codec) if(decoder->codec)
{ {
CHIAKI_LOGI(decoder->log, "Audio decoder already initialized, re-creating"); CHIAKI_LOGI(decoder->log, "Audio decoder already initialized, shutting down the old one");
// TODO: stop thread android_chiaki_audio_decoder_shutdown_codec(decoder);
AMediaCodec_delete(decoder->codec);
decoder->codec = NULL;
} }
const char *mime = "audio/opus"; const char *mime = "audio/opus";
@ -104,7 +124,7 @@ static void android_chiaki_audio_decoder_header(ChiakiAudioHeader *header, void
if(!decoder->codec) if(!decoder->codec)
{ {
CHIAKI_LOGE(decoder->log, "Failed to create AMediaCodec for mime type %s", mime); CHIAKI_LOGE(decoder->log, "Failed to create AMediaCodec for mime type %s", mime);
return; goto beach;
} }
AMediaFormat *format = AMediaFormat_new(); AMediaFormat *format = AMediaFormat_new();
@ -126,7 +146,6 @@ static void android_chiaki_audio_decoder_header(ChiakiAudioHeader *header, void
decoder->codec = NULL; decoder->codec = NULL;
} }
uint8_t opus_id_head[0x13]; uint8_t opus_id_head[0x13];
memcpy(opus_id_head, "OpusHead", 8); memcpy(opus_id_head, "OpusHead", 8);
opus_id_head[0x8] = 1; // version opus_id_head[0x8] = 1; // version
@ -157,16 +176,20 @@ static void android_chiaki_audio_decoder_header(ChiakiAudioHeader *header, void
if(decoder->settings_cb) if(decoder->settings_cb)
decoder->settings_cb(header->channels, header->rate, decoder->cb_user); 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) static void android_chiaki_audio_decoder_frame(uint8_t *buf, size_t buf_size, void *user)
{ {
AndroidChiakiAudioDecoder *decoder = user; AndroidChiakiAudioDecoder *decoder = user;
chiaki_mutex_lock(&decoder->codec_mutex);
if(!decoder->codec) if(!decoder->codec)
{ {
CHIAKI_LOGE(decoder->log, "Received audio data, but decoder is not initialized!"); CHIAKI_LOGE(decoder->log, "Received audio data, but decoder is not initialized!");
return; goto beach;
} }
while(buf_size > 0) 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 += codec_sample_size;
buf_size -= codec_sample_size; buf_size -= codec_sample_size;
} }
beach:
chiaki_mutex_unlock(&decoder->codec_mutex);
} }

View file

@ -31,6 +31,8 @@ typedef struct android_chiaki_audio_decoder_t
{ {
ChiakiLog *log; ChiakiLog *log;
ChiakiAudioHeader audio_header; ChiakiAudioHeader audio_header;
ChiakiMutex codec_mutex;
struct AMediaCodec *codec; struct AMediaCodec *codec;
uint64_t timestamp_cur; uint64_t timestamp_cur;
ChiakiThread output_thread; ChiakiThread output_thread;

View file

@ -121,7 +121,7 @@ oboe::DataCallbackResult AudioOutputCallback::onAudioReady(oboe::AudioStream *st
if(buf_size_delivered < buf_size_requested) 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); memset(buf + buf_size_delivered, 0, buf_size_requested - buf_size_delivered);
} }

View file

@ -281,7 +281,7 @@ beach:
JNIEXPORT void JNICALL Java_com_metallic_chiaki_lib_ChiakiNative_sessionFree(JNIEnv *env, jobject obj, jlong ptr) JNIEXPORT void JNICALL Java_com_metallic_chiaki_lib_ChiakiNative_sessionFree(JNIEnv *env, jobject obj, jlong ptr)
{ {
AndroidChiakiSession *session = (AndroidChiakiSession *)ptr; AndroidChiakiSession *session = (AndroidChiakiSession *)ptr;
CHIAKI_LOGI(&global_log, "Free JNI Session"); CHIAKI_LOGI(&global_log, "Shutting down JNI Session");
if(!session) if(!session)
return; return;
chiaki_session_fini(&session->session); 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_decoder_fini(&session->audio_decoder);
android_chiaki_audio_output_free(session->audio_output); android_chiaki_audio_output_free(session->audio_output);
E->DeleteGlobalRef(env, session->java_session); 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) JNIEXPORT jint JNICALL Java_com_metallic_chiaki_lib_ChiakiNative_sessionStart(JNIEnv *env, jobject obj, jlong ptr)

View file

@ -63,7 +63,7 @@ class CircularBuffer
~CircularBuffer() ~CircularBuffer()
{ {
delete buffer; delete [] buffer;
} }
/** /**

View file

@ -34,18 +34,32 @@ ChiakiErrorCode android_chiaki_video_decoder_init(AndroidChiakiVideoDecoder *dec
decoder->log = log; decoder->log = log;
decoder->codec = NULL; decoder->codec = NULL;
decoder->timestamp_cur = 0; 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) void android_chiaki_video_decoder_fini(AndroidChiakiVideoDecoder *decoder)
{ {
// TODO: shutdown (thread may or may not be running!) if(decoder->codec)
chiaki_mutex_fini(&decoder->mutex); {
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) 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) if(decoder->codec)
{ {
@ -92,13 +106,13 @@ void android_chiaki_video_decoder_set_surface(AndroidChiakiVideoDecoder *decoder
} }
beach: 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) void android_chiaki_video_decoder_video_sample(uint8_t *buf, size_t buf_size, void *user)
{ {
AndroidChiakiVideoDecoder *decoder = user; AndroidChiakiVideoDecoder *decoder = user;
chiaki_mutex_lock(&decoder->mutex); chiaki_mutex_lock(&decoder->codec_mutex);
if(!decoder->codec) 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; size_t codec_sample_size = buf_size;
if(codec_sample_size > codec_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; codec_sample_size = codec_buf_size;
} }
memcpy(codec_buf, buf, codec_sample_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: beach:
chiaki_mutex_unlock(&decoder->mutex); chiaki_mutex_unlock(&decoder->codec_mutex);
} }
static void *android_chiaki_video_decoder_output_thread_func(void *user) 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; return NULL;
} }

View file

@ -29,7 +29,7 @@ typedef struct ANativeWindow ANativeWindow;
typedef struct android_chiaki_video_decoder_t typedef struct android_chiaki_video_decoder_t
{ {
ChiakiLog *log; ChiakiLog *log;
ChiakiMutex mutex; ChiakiMutex codec_mutex;
AMediaCodec *codec; AMediaCodec *codec;
ANativeWindow *window; ANativeWindow *window;
uint64_t timestamp_cur; uint64_t timestamp_cur;