mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
androidmedia: Handle force-keyunit requests
Use API from Android 19 to request a keyframe from the MediaCodec when indicated by the base class.
This commit is contained in:
parent
cfe318ea03
commit
1b8bf1be01
4 changed files with 122 additions and 0 deletions
|
@ -60,6 +60,7 @@ gboolean gst_amc_codec_start (GstAmcCodec * codec, GError **err);
|
||||||
gboolean gst_amc_codec_stop (GstAmcCodec * codec, GError **err);
|
gboolean gst_amc_codec_stop (GstAmcCodec * codec, GError **err);
|
||||||
gboolean gst_amc_codec_flush (GstAmcCodec * codec, GError **err);
|
gboolean gst_amc_codec_flush (GstAmcCodec * codec, GError **err);
|
||||||
gboolean gst_amc_codec_release (GstAmcCodec * codec, GError **err);
|
gboolean gst_amc_codec_release (GstAmcCodec * codec, GError **err);
|
||||||
|
gboolean gst_amc_codec_request_key_frame (GstAmcCodec * codec, GError **err);
|
||||||
|
|
||||||
GstAmcBuffer * gst_amc_codec_get_output_buffer (GstAmcCodec * codec, gint index, GError **err);
|
GstAmcBuffer * gst_amc_codec_get_output_buffer (GstAmcCodec * codec, gint index, GError **err);
|
||||||
GstAmcBuffer * gst_amc_codec_get_input_buffer (GstAmcCodec * codec, gint index, GError **err);
|
GstAmcBuffer * gst_amc_codec_get_input_buffer (GstAmcCodec * codec, gint index, GError **err);
|
||||||
|
|
|
@ -1426,6 +1426,16 @@ gst_amc_video_enc_handle_frame (GstVideoEncoder * encoder,
|
||||||
timestamp = frame->pts;
|
timestamp = frame->pts;
|
||||||
duration = frame->duration;
|
duration = frame->duration;
|
||||||
|
|
||||||
|
if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame)) {
|
||||||
|
if (gst_amc_codec_request_key_frame (self->codec, &err)) {
|
||||||
|
GST_DEBUG_OBJECT (self, "Passed keyframe request to MediaCodec");
|
||||||
|
}
|
||||||
|
if (err) {
|
||||||
|
GST_ELEMENT_WARNING_FROM_ERROR (self, err);
|
||||||
|
g_clear_error (&err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
again:
|
again:
|
||||||
/* Make sure to release the base class stream lock, otherwise
|
/* Make sure to release the base class stream lock, otherwise
|
||||||
* _loop() can't call _finish_frame() and we might block forever
|
* _loop() can't call _finish_frame() and we might block forever
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
#include "gstamcsurfacetexture-jni.h"
|
#include "gstamcsurfacetexture-jni.h"
|
||||||
#include "gstamcsurface.h"
|
#include "gstamcsurface.h"
|
||||||
|
|
||||||
|
#define PARAMETER_KEY_REQUEST_SYNC_FRAME "request-sync"
|
||||||
|
|
||||||
struct _GstAmcCodec
|
struct _GstAmcCodec
|
||||||
{
|
{
|
||||||
jobject object; /* global reference */
|
jobject object; /* global reference */
|
||||||
|
@ -58,6 +60,7 @@ static struct
|
||||||
jmethodID release_output_buffer;
|
jmethodID release_output_buffer;
|
||||||
jmethodID start;
|
jmethodID start;
|
||||||
jmethodID stop;
|
jmethodID stop;
|
||||||
|
jmethodID setParameters;
|
||||||
} media_codec;
|
} media_codec;
|
||||||
|
|
||||||
static struct
|
static struct
|
||||||
|
@ -70,6 +73,13 @@ static struct
|
||||||
jfieldID size;
|
jfieldID size;
|
||||||
} media_codec_buffer_info;
|
} media_codec_buffer_info;
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
jclass klass;
|
||||||
|
jmethodID constructor;
|
||||||
|
jmethodID putInt;
|
||||||
|
} bundle_class;
|
||||||
|
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
jclass klass;
|
jclass klass;
|
||||||
|
@ -263,6 +273,11 @@ gst_amc_codec_static_init (void)
|
||||||
}
|
}
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
media_codec.setParameters =
|
||||||
|
(*env)->GetMethodID (env, media_codec.klass, "setParameters",
|
||||||
|
"(Landroid/os/Bundle;)V");
|
||||||
|
if ((*env)->ExceptionCheck (env))
|
||||||
|
(*env)->ExceptionClear (env);
|
||||||
|
|
||||||
/* Android >= 21 */
|
/* Android >= 21 */
|
||||||
media_codec.get_output_buffer =
|
media_codec.get_output_buffer =
|
||||||
|
@ -278,6 +293,47 @@ gst_amc_codec_static_init (void)
|
||||||
if ((*env)->ExceptionCheck (env))
|
if ((*env)->ExceptionCheck (env))
|
||||||
(*env)->ExceptionClear (env);
|
(*env)->ExceptionClear (env);
|
||||||
|
|
||||||
|
if (media_codec.setParameters != NULL) {
|
||||||
|
/* Bundle needed for parameter setting on Android >= 19 */
|
||||||
|
tmp = (*env)->FindClass (env, "android/os/Bundle");
|
||||||
|
if (!tmp) {
|
||||||
|
ret = FALSE;
|
||||||
|
GST_ERROR ("Failed to get Bundle class");
|
||||||
|
if ((*env)->ExceptionCheck (env)) {
|
||||||
|
(*env)->ExceptionDescribe (env);
|
||||||
|
(*env)->ExceptionClear (env);
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
bundle_class.klass = (*env)->NewGlobalRef (env, tmp);
|
||||||
|
if (!bundle_class.klass) {
|
||||||
|
ret = FALSE;
|
||||||
|
GST_ERROR ("Failed to get Bundle class global reference");
|
||||||
|
if ((*env)->ExceptionCheck (env)) {
|
||||||
|
(*env)->ExceptionDescribe (env);
|
||||||
|
(*env)->ExceptionClear (env);
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
(*env)->DeleteLocalRef (env, tmp);
|
||||||
|
tmp = NULL;
|
||||||
|
|
||||||
|
bundle_class.constructor =
|
||||||
|
(*env)->GetMethodID (env, bundle_class.klass, "<init>", "()V");
|
||||||
|
bundle_class.putInt =
|
||||||
|
(*env)->GetMethodID (env, bundle_class.klass, "putInt",
|
||||||
|
"(Ljava/lang/String;I)V");
|
||||||
|
if (!bundle_class.constructor || !bundle_class.putInt) {
|
||||||
|
ret = FALSE;
|
||||||
|
GST_ERROR ("Failed to get Bundle methods");
|
||||||
|
if ((*env)->ExceptionCheck (env)) {
|
||||||
|
(*env)->ExceptionDescribe (env);
|
||||||
|
(*env)->ExceptionClear (env);
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (tmp)
|
if (tmp)
|
||||||
(*env)->DeleteLocalRef (env, tmp);
|
(*env)->DeleteLocalRef (env, tmp);
|
||||||
|
@ -694,6 +750,52 @@ gst_amc_codec_flush (GstAmcCodec * codec, GError ** err)
|
||||||
media_codec.flush);
|
media_codec.flush);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_amc_codec_set_parameter (GstAmcCodec * codec, JNIEnv * env,
|
||||||
|
GError ** err, const gchar * key, int value)
|
||||||
|
{
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
jobject bundle = NULL;
|
||||||
|
jstring jkey = NULL;
|
||||||
|
|
||||||
|
if (media_codec.setParameters == NULL)
|
||||||
|
goto done; // Not available means we're on Android < 19
|
||||||
|
|
||||||
|
bundle = gst_amc_jni_new_object (env, err, FALSE, bundle_class.klass,
|
||||||
|
bundle_class.constructor);
|
||||||
|
if (!bundle)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
jkey = (*env)->NewStringUTF (env, key);
|
||||||
|
if (!gst_amc_jni_call_void_method (env, err,
|
||||||
|
bundle, bundle_class.putInt, jkey, value))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (!gst_amc_jni_call_void_method (env, err, codec->object,
|
||||||
|
media_codec.setParameters, bundle))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
done:
|
||||||
|
if (jkey)
|
||||||
|
(*env)->DeleteLocalRef (env, jkey);
|
||||||
|
if (bundle)
|
||||||
|
(*env)->DeleteLocalRef (env, bundle);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_amc_codec_request_key_frame (GstAmcCodec * codec, GError ** err)
|
||||||
|
{
|
||||||
|
JNIEnv *env;
|
||||||
|
|
||||||
|
g_return_val_if_fail (codec != NULL, FALSE);
|
||||||
|
|
||||||
|
env = gst_amc_jni_get_env ();
|
||||||
|
return gst_amc_codec_set_parameter (codec, env, err,
|
||||||
|
PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_amc_codec_release (GstAmcCodec * codec, GError ** err)
|
gst_amc_codec_release (GstAmcCodec * codec, GError ** err)
|
||||||
{
|
{
|
||||||
|
|
|
@ -192,6 +192,15 @@ gst_amc_codec_flush (GstAmcCodec * codec, GError ** err)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_amc_codec_request_key_frame (GstAmcCodec * codec, GError ** err)
|
||||||
|
{
|
||||||
|
/* If MagicLeap adds an API for requesting a keyframe, call it here */
|
||||||
|
g_set_error (err, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
|
||||||
|
"Keyframe requests are not available on MagicLeap");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_amc_codec_release (GstAmcCodec * codec, GError ** err)
|
gst_amc_codec_release (GstAmcCodec * codec, GError ** err)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue