mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-10 19:31:12 +00:00
Proper reporting of media size. Now the Android layout controls the appearance of the clip, instead of it always being maximized.
This commit is contained in:
parent
c4a3f608e5
commit
33450c17d2
4 changed files with 110 additions and 6 deletions
|
@ -5,6 +5,7 @@
|
|||
#include <android/native_window_jni.h>
|
||||
#include <gst/gst.h>
|
||||
#include <gst/interfaces/xoverlay.h>
|
||||
#include <gst/video/video.h>
|
||||
#include <pthread.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (debug_category);
|
||||
|
@ -40,6 +41,7 @@ static JavaVM *java_vm;
|
|||
static jfieldID custom_data_field_id;
|
||||
static jmethodID set_message_method_id;
|
||||
static jmethodID on_gstreamer_initialized_method_id;
|
||||
static jmethodID on_media_size_changed_method_id;
|
||||
|
||||
/*
|
||||
* Private methods
|
||||
|
@ -121,6 +123,31 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) {
|
|||
}
|
||||
}
|
||||
|
||||
/* Called when Pad Caps change on the video sink */
|
||||
static void caps_cb (GstPad *pad, GParamSpec *pspec, CustomData *data) {
|
||||
JNIEnv *env = get_jni_env ();
|
||||
GstVideoFormat fmt;
|
||||
int width;
|
||||
int height;
|
||||
GstCaps *caps;
|
||||
|
||||
caps = gst_pad_get_negotiated_caps (pad);
|
||||
if (gst_video_format_parse_caps(caps, &fmt, &width, &height)) {
|
||||
int par_n, par_d;
|
||||
if (gst_video_parse_caps_pixel_aspect_ratio (caps, &par_n, &par_d)) {
|
||||
width = width * par_n / par_d;
|
||||
}
|
||||
GST_DEBUG ("Media size changed to %dx%d", width, height);
|
||||
|
||||
(*env)->CallVoidMethod (env, data->app, on_media_size_changed_method_id, (jint)width, (jint)height);
|
||||
if ((*env)->ExceptionCheck (env)) {
|
||||
GST_ERROR ("Failed to call Java method");
|
||||
(*env)->ExceptionClear (env);
|
||||
}
|
||||
}
|
||||
gst_caps_unref(caps);
|
||||
}
|
||||
|
||||
/* Check if all conditions are met to report GStreamer as initialized.
|
||||
* These conditions will change depending on the application */
|
||||
static void check_initialization_complete (CustomData *data) {
|
||||
|
@ -143,6 +170,7 @@ static void *app_function (void *userdata) {
|
|||
CustomData *data = (CustomData *)userdata;
|
||||
GSource *bus_source;
|
||||
GError *error = NULL;
|
||||
GstPad *video_sink_pad;
|
||||
|
||||
GST_DEBUG ("Creating pipeline in CustomData at %p", data);
|
||||
|
||||
|
@ -166,7 +194,12 @@ static void *app_function (void *userdata) {
|
|||
data->video_sink = gst_bin_get_by_interface(GST_BIN(data->pipeline), GST_TYPE_X_OVERLAY);
|
||||
if (!data->video_sink) {
|
||||
GST_ERROR ("Could not retrieve video sink");
|
||||
return NULL;
|
||||
}
|
||||
/* We want to be notified when the Caps on the video sink's Pad change */
|
||||
video_sink_pad = gst_element_get_static_pad (data->video_sink, "sink");
|
||||
g_signal_connect (G_OBJECT (video_sink_pad), "notify::caps", (GCallback)caps_cb, data);
|
||||
gst_object_unref (video_sink_pad);
|
||||
|
||||
if (data->native_window) {
|
||||
GST_DEBUG ("Native window already received, notifying the pipeline about it.");
|
||||
|
@ -255,12 +288,14 @@ static jboolean gst_native_class_init (JNIEnv* env, jclass klass) {
|
|||
custom_data_field_id = (*env)->GetFieldID (env, klass, "native_custom_data", "J");
|
||||
set_message_method_id = (*env)->GetMethodID (env, klass, "setMessage", "(Ljava/lang/String;)V");
|
||||
on_gstreamer_initialized_method_id = (*env)->GetMethodID (env, klass, "onGStreamerInitialized", "()V");
|
||||
on_media_size_changed_method_id = (*env)->GetMethodID (env, klass, "onMediaSizeChanged", "(II)V");
|
||||
|
||||
if (!custom_data_field_id || !set_message_method_id || !on_gstreamer_initialized_method_id) {
|
||||
if (!custom_data_field_id || !set_message_method_id || !on_gstreamer_initialized_method_id ||
|
||||
!on_media_size_changed_method_id) {
|
||||
/* We emit this message through the Android log instead of the GStreamer log because the later
|
||||
* has not been initialized yet.
|
||||
*/
|
||||
__android_log_print (ANDROID_LOG_ERROR, "tutorial-2", "The calling class does not implement all necessary interface methods");
|
||||
__android_log_print (ANDROID_LOG_ERROR, "tutorial-3", "The calling class does not implement all necessary interface methods");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
return JNI_TRUE;
|
||||
|
|
|
@ -34,11 +34,11 @@
|
|||
android:src="@android:drawable/ic_media_pause"
|
||||
android:text="@string/button_stop" />
|
||||
</LinearLayout>
|
||||
|
||||
<SurfaceView
|
||||
|
||||
<com.gst_sdk_tutorials.tutorial_3.GStreamerSurfaceView
|
||||
android:id="@+id/surface_video"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical|center_horizontal" />
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,62 @@
|
|||
package com.gst_sdk_tutorials.tutorial_3;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
|
||||
// A simple SurfaceView whose width and height is set from the outside
|
||||
public class GStreamerSurfaceView extends SurfaceView {
|
||||
public int media_width = 320; // Default values, only really meaningful for the layout editor in Eclipse
|
||||
public int media_height = 200;
|
||||
|
||||
// Mandatory constructors, they do not do much
|
||||
public GStreamerSurfaceView(Context context, AttributeSet attrs,
|
||||
int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public GStreamerSurfaceView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public GStreamerSurfaceView (Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
// Called by the layout manager to find out our size and give us some rules
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int width = 0, height = 0;
|
||||
|
||||
// Obey width rules
|
||||
switch (View.MeasureSpec.getMode(widthMeasureSpec)) {
|
||||
case View.MeasureSpec.AT_MOST:
|
||||
width = Math.min (View.MeasureSpec.getSize(widthMeasureSpec), media_width);
|
||||
break;
|
||||
case View.MeasureSpec.EXACTLY:
|
||||
width = View.MeasureSpec.getSize(widthMeasureSpec);
|
||||
break;
|
||||
case View.MeasureSpec.UNSPECIFIED:
|
||||
width = media_width;
|
||||
}
|
||||
|
||||
// Obey height rules
|
||||
switch (View.MeasureSpec.getMode(heightMeasureSpec)) {
|
||||
case View.MeasureSpec.AT_MOST:
|
||||
height = Math.min (View.MeasureSpec.getSize(heightMeasureSpec), media_height);
|
||||
break;
|
||||
case View.MeasureSpec.EXACTLY:
|
||||
height = View.MeasureSpec.getSize(heightMeasureSpec);
|
||||
break;
|
||||
case View.MeasureSpec.UNSPECIFIED:
|
||||
height = media_height;
|
||||
}
|
||||
|
||||
// Obey minimum size
|
||||
width = Math.max (getSuggestedMinimumWidth(), width);
|
||||
height = Math.max (getSuggestedMinimumHeight(), height);
|
||||
setMeasuredDimension(width, height);
|
||||
}
|
||||
|
||||
}
|
|
@ -118,6 +118,13 @@ public class Tutorial3 extends Activity implements SurfaceHolder.Callback {
|
|||
});
|
||||
}
|
||||
|
||||
private void onMediaSizeChanged (int width, int height) {
|
||||
Log.i ("GStreamer", "Media size changed to " + width + "x" + height);
|
||||
GStreamerSurfaceView gsv = (GStreamerSurfaceView) this.findViewById(R.id.surface_video);
|
||||
gsv.media_width = width;
|
||||
gsv.media_height = height;
|
||||
}
|
||||
|
||||
static {
|
||||
System.loadLibrary("gstreamer_android");
|
||||
System.loadLibrary("tutorial-3");
|
||||
|
|
Loading…
Reference in a new issue