Implement Aspect ratio preservation in GStreamerSurfaceView. Fix some corner cases that this triggers in the surface size reporting code.

This commit is contained in:
Xavi Artigas 2012-10-18 17:55:43 +02:00
parent aeefdd86bc
commit 334661044f
4 changed files with 38 additions and 13 deletions

View file

@ -304,13 +304,21 @@ static jboolean gst_native_class_init (JNIEnv* env, jclass klass) {
static void gst_native_surface_init (JNIEnv *env, jobject thiz, jobject surface) { static void gst_native_surface_init (JNIEnv *env, jobject thiz, jobject surface) {
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data) return; if (!data) return;
GST_DEBUG ("Received surface %p", surface); ANativeWindow *new_native_window = ANativeWindow_fromSurface(env, surface);
GST_DEBUG ("Received surface %p (native window %p)", surface, new_native_window);
if (data->native_window) { if (data->native_window) {
GST_DEBUG ("Releasing previous native window %p", data->native_window);
ANativeWindow_release (data->native_window); ANativeWindow_release (data->native_window);
if (data->native_window == new_native_window) {
GST_DEBUG ("New native window is the same as the previous one", data->native_window);
if (data->video_sink)
gst_x_overlay_expose(GST_X_OVERLAY (data->video_sink));
return;
} else {
GST_DEBUG ("Released previous native window %p", data->native_window);
}
} }
data->native_window = ANativeWindow_fromSurface(env, surface); data->native_window = new_native_window;
GST_DEBUG ("Got Native Window %p", data->native_window);
if (data->video_sink) { if (data->video_sink) {
GST_DEBUG ("Pipeline already created, notifying it about the native window."); GST_DEBUG ("Pipeline already created, notifying it about the native window.");

View file

@ -15,6 +15,7 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="16dip"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:orientation="horizontal" > android:orientation="horizontal" >
@ -37,8 +38,8 @@
<com.gst_sdk_tutorials.tutorial_3.GStreamerSurfaceView <com.gst_sdk_tutorials.tutorial_3.GStreamerSurfaceView
android:id="@+id/surface_video" android:id="@+id/surface_video"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal" /> android:layout_gravity="center_vertical|center_horizontal" />
</LinearLayout> </LinearLayout>

View file

@ -2,13 +2,14 @@ package com.gst_sdk_tutorials.tutorial_3;
import android.content.Context; import android.content.Context;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceView; import android.view.SurfaceView;
import android.view.View; import android.view.View;
// A simple SurfaceView whose width and height is set from the outside // A simple SurfaceView whose width and height is set from the outside
public class GStreamerSurfaceView extends SurfaceView { public class GStreamerSurfaceView extends SurfaceView {
public int media_width = 320; // Default values, only really meaningful for the layout editor in Eclipse public int media_width = 100; // Default values, only really meaningful for the layout editor in Eclipse
public int media_height = 200; public int media_height = 100;
// Mandatory constructors, they do not do much // Mandatory constructors, they do not do much
public GStreamerSurfaceView(Context context, AttributeSet attrs, public GStreamerSurfaceView(Context context, AttributeSet attrs,
@ -29,11 +30,10 @@ public class GStreamerSurfaceView extends SurfaceView {
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = 0, height = 0; int width = 0, height = 0;
Log.i ("GStreamer", "onMeasure called with " + media_width + "x" + media_height);
// Obey width rules // Obey width rules
switch (View.MeasureSpec.getMode(widthMeasureSpec)) { switch (View.MeasureSpec.getMode(widthMeasureSpec)) {
case View.MeasureSpec.AT_MOST: case View.MeasureSpec.AT_MOST:
width = Math.min (View.MeasureSpec.getSize(widthMeasureSpec), media_width);
break;
case View.MeasureSpec.EXACTLY: case View.MeasureSpec.EXACTLY:
width = View.MeasureSpec.getSize(widthMeasureSpec); width = View.MeasureSpec.getSize(widthMeasureSpec);
break; break;
@ -44,8 +44,6 @@ public class GStreamerSurfaceView extends SurfaceView {
// Obey height rules // Obey height rules
switch (View.MeasureSpec.getMode(heightMeasureSpec)) { switch (View.MeasureSpec.getMode(heightMeasureSpec)) {
case View.MeasureSpec.AT_MOST: case View.MeasureSpec.AT_MOST:
height = Math.min (View.MeasureSpec.getSize(heightMeasureSpec), media_height);
break;
case View.MeasureSpec.EXACTLY: case View.MeasureSpec.EXACTLY:
height = View.MeasureSpec.getSize(heightMeasureSpec); height = View.MeasureSpec.getSize(heightMeasureSpec);
break; break;
@ -53,6 +51,19 @@ public class GStreamerSurfaceView extends SurfaceView {
height = media_height; height = media_height;
} }
// Preserve aspect ratio if we are allowed freedom in both axes
// FIXME: Implement the case where only one axis is free
if (View.MeasureSpec.getMode(heightMeasureSpec) == View.MeasureSpec.AT_MOST &&
View.MeasureSpec.getMode(widthMeasureSpec) == View.MeasureSpec.AT_MOST) {
int correct_height = width * media_height / media_width;
int correct_width = height * media_width / media_height;
if (correct_height < height)
height = correct_height;
else
width = correct_width;
}
// Obey minimum size // Obey minimum size
width = Math.max (getSuggestedMinimumWidth(), width); width = Math.max (getSuggestedMinimumWidth(), width);
height = Math.max (getSuggestedMinimumHeight(), height); height = Math.max (getSuggestedMinimumHeight(), height);

View file

@ -120,9 +120,14 @@ public class Tutorial3 extends Activity implements SurfaceHolder.Callback {
private void onMediaSizeChanged (int width, int height) { private void onMediaSizeChanged (int width, int height) {
Log.i ("GStreamer", "Media size changed to " + width + "x" + height); Log.i ("GStreamer", "Media size changed to " + width + "x" + height);
GStreamerSurfaceView gsv = (GStreamerSurfaceView) this.findViewById(R.id.surface_video); final GStreamerSurfaceView gsv = (GStreamerSurfaceView) this.findViewById(R.id.surface_video);
gsv.media_width = width; gsv.media_width = width;
gsv.media_height = height; gsv.media_height = height;
runOnUiThread(new Runnable() {
public void run() {
gsv.requestLayout();
}
});
} }
static { static {