【问题标题】:Android: Mediaplayer: How to use SurfaceView or mediaplayer to play video in correct sizeAndroid:Mediaplayer:如何使用 SurfaceView 或 mediaplayer 以正确大小播放视频
【发布时间】:2011-01-29 04:00:01
【问题描述】:

我正在使用 MediaPlayer 和 SurfaceView 播放本地视频文件。 SurfaceView 是活动中的唯一控件,而我的视频文件是 QVGA 或其他。问题是视频被拉伸了,我怎样才能以原始大小播放视频,例如qvga,剩余区域为黑色。

从迭代中,

当我在 XML 中强制设置 Surfaceview 的 layout_height/width 时,视频显示正常。 surface_holder.setFixedSize(w,h) 无效,mp.setdisplay() 也无效。

请在此指导。

更新

XML 文件

<?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/

提前致谢。

【问题讨论】:

    标签: android media-player


    【解决方案1】:

    将 SurfaceView 布局设置为 wrap_content 将不会调整视频大小以以适当的纵横比播放。

    • SurfaceView 是优化的绘图表面
    • 视频被绘制到 SurfaceView,而不是包含在其中

    wrap_content 与 SurfaceView 的 fill_parent 同义。

    您想要做的是从 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 调用应该包含在 try{} 中。

    @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。

    【讨论】:

    • 注意:上例中getVideoWidth和getVideoHeight是相反的
    • 谢谢,已在最新版本中修复。
    • 您好,我在这个示例中只有一个有声音的黑屏...我该怎么做才能解决它?
    • 这应该是公认的答案,就像一个魅力!谢谢!
    • 好吧,"wrap_content 是 SurfaceView 的 fill_parent 的同义词。"在 XMlL 中将 "height" 设置为 "wrap_content" 或 "fill_parent" 并使用下面的代码时,这可能不是真的。当使用 @987654323 @ 不是 mSurfaceView.setLayoutParams 它运作良好。
    【解决方案2】:

    这是我目前在项目中使用的代码:

    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>
    

    【讨论】:

    • 请写完整的代码...你还没有创建MediaPlayer 实例,也没有显示持有者与媒体播放器之间的关系。
    • 我现在用VideoView,它是一个可以直接在布局中使用的小部件,它自己处理纵横比
    【解决方案3】:

    在 XML 中的 SurfaceView 上,您使用的是 wrap_content 吗?如果没有,这应该可以解决您的问题。如果这不能解决您的问题,您可能需要粘贴更多代码以进行进一步调查。

    将您的表面视图宽度也更改为 wrap_content。

    【讨论】:

    • 我在 XML 中使用 wrap_content,添加了源代码。静态视频是一种全屏,拉伸,我想以原始大小显示视频。
    • 我更新了我的答案,请更改您的宽度以换行内容。设置其中任何一个来填充它都会导致布局在任一方向上按比例拉伸视频。
    • 这不是答案。它包含有关 SurfaceView 和 wrap_content 的虚假信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多