Android: Mediaplayer: как использовать SurfaceView или mediaplayer для воспроизведения видео в правильном размере - PullRequest
19 голосов
/ 29 января 2011

Я играю локальный видеофайл, используя MediaPlayer и SurfaceView. SurfaceView - единственный элемент управления в действии, в то время как мои видеофайлы QVGA или другие. Проблема в том, что видео растягивается, как я могу воспроизвести видео в его оригинальном размере, например QVGA с оставшейся областью черного цвета.

Из итерации,

Когда я принудительно устанавливаю layout_height / width Surfaceview в XML, видео отображается нормально. surface_holder.setFixedSize(w,h) не имеет никакого эффекта, ни mp.setdisplay ().

Пожалуйста, направьте в этом.

UPDATE

XML flie

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
            android:id="@+id/home_container"  
            android:layout_width="fill_parent" 
            android:layout_height="fill_parent">

<SurfaceView 
        android:id="@+id/surface" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:paddingTop="10dip" />
</framelayout>

Использование MediaPlayer по следующей ссылке

http://davanum.wordpress.com/2007/12/29/android-videomusic-player-sample-from-local-disk-as-well-as-remote-urls/

Заранее спасибо.

Ответы [ 3 ]

79 голосов
/ 08 июня 2011

Если установить макет SurfaceView равным wrap_content, не увеличит размер видео для воспроизведения с правильным соотношением сторон.

  • SurfaceView - это оптимизированная поверхность рисования
  • Видео отображается в SurfaceView, не содержится в нем

wrap_content является синонимом fill_parent для SurfaceView.

То, что вы хотите сделать, - это получить размеры вашего видео из объекта MediaPlayer.Затем вы можете установить соотношение сторон SurfaceView для соответствия видео.

Некоторая базовая инициализация

public class YourMovieActivity extends Activity implements SurfaceHolder.Callback {
    private MediaPlayer mp = null;
    //...

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mp = new MediaPlayer();
        mSurfaceView = (SurfaceView) findViewById(R.id.surface);
        //...
    }
}

Тогда хорошие вещи.Я опустил проверку ошибок здесь, чтобы уменьшить код, вызовы MediaPlayer должны быть обернуты в попытку {}.

@Override
public void surfaceCreated(SurfaceHolder holder) {

    mp.setDataSource("/sdcard/someVideo.mp4");
    mp.prepare();

    //Get the dimensions of the video
    int videoWidth = mp.getVideoWidth();
    int videoHeight = mp.getVideoHeight();

    //Get the width of the screen
    int screenWidth = getWindowManager().getDefaultDisplay().getWidth();

    //Get the SurfaceView layout parameters
    android.view.ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams();

    //Set the width of the SurfaceView to the width of the screen
    lp.width = screenWidth;

    //Set the height of the SurfaceView to match the aspect ratio of the video 
    //be sure to cast these as floats otherwise the calculation will likely be 0
    lp.height = (int) (((float)videoHeight / (float)videoWidth) * (float)screenWidth);

    //Commit the layout parameters
    mSurfaceView.setLayoutParams(lp);        

    //Start video
    mp.start();
}

Обратите внимание, что этот код делает некоторые предположения относительно размеров вашего видео.Как есть, он максимизирует ширину и предполагает, что высота не превышает высоту экрана.

Возможно, вы захотите указать высоту вместо ширины, также вы можете проверить расчет размера и убедиться, что он не больше экрана или экрана - other_layout_elements.

4 голосов
/ 23 января 2012

вот код, который я сейчас использую в проекте:

private MediaPlayer mMediaPlayer;
private SurfaceView mSurfaceView;
private SurfaceHolder holder;
private int mPos = 0;

...

int width = mSurfaceView.getWidth();
int height = mSurfaceView.getHeight();
float boxWidth = width;
float boxHeight = height;

float videoWidth = mMediaPlayer.getVideoWidth();
float videoHeight = mMediaPlayer.getVideoHeight();

Log.i(TAG, String.format("startVideoPlayback @ %d - video %dx%d - box %dx%d", mPos, (int) videoWidth, (int) videoHeight, width, height));

float wr = boxWidth / videoWidth;
float hr = boxHeight / videoHeight;
float ar = videoWidth / videoHeight;

if (wr > hr)
    width = (int) (boxHeight * ar);
else
    height = (int) (boxWidth / ar);

Log.i(TAG, String.format("Scaled to %dx%d", width, height));

holder.setFixedSize(width, height);
mMediaPlayer.seekTo(mPos);
mMediaPlayer.start();

используемый мной макет (вы можете просто игнорировать индикатор выполнения)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical" >

<ProgressBar
    android:id="@+id/progressBar1"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

<SurfaceView
    android:id="@+id/surface"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center" >
</SurfaceView>

0 голосов
/ 29 января 2011

В вашем SurfaceView в XML вы используете wrap_content?Это должно исправить вашу проблему, если нет.Возможно, вам придется вставить немного больше кода для дальнейшего изучения, если это не решит вашу проблему.

Также измените ширину вида поверхности на wrap_content.

...