mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-26 02:00:33 +00:00
Implement Aspect ratio preservation in GStreamerSurfaceView. Fix some corner cases that this triggers in the surface size reporting code.
This commit is contained in:
parent
aeefdd86bc
commit
334661044f
4 changed files with 38 additions and 13 deletions
|
@ -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.");
|
||||||
|
|
|
@ -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>
|
|
@ -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);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue