VideoVideo-视频宽度x高度-MediaPlayer问题 [英] VideoVideo - Video Width x Height- MediaPlayer Issue

查看:717
本文介绍了VideoVideo-视频宽度x高度-MediaPlayer问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个可重现该问题的示例应用程序:

https://github.com/blundell/VideoRatioProblemPerDevice

VideoView 文档指出:

显示视频文件. ...负责根据视频计算其度量,以便可以在任何布局管理器中使用它,并提供各种显示选项,例如缩放

问题在于三星Galaxy S3对视频做奇怪的事情,不尊重视频的比例.(在HTC设备上也是如此).

具有全屏片段的活动:

我发现,当视频在Samsung Galaxy S3上播放时,它将以不正确的比例播放.看起来它已经拉伸到视图的高度,而没有考虑原始视频的比例.

在这里:

但是,如果我在Samsung Galaxy Nexus上播放视频,则视频的比例正确.

在这里:

如果我强迫视频占用片段的全部大小,则在S3上看起来还可以(因为屏幕的比例就是视频的比例).但是,我不想这样做,因为它会弄碎在其他地方(例如平板电脑)上使用的碎片.

代码是:

一个带有视频视图片段的活动.可以在此处看到: GITHUB代码链接

如果您想要一些代码,请使用VideoPlayerFragment:

public class VideoPlayerFragment extends Fragment {

    private static final String TAG = "VideoPlayer";

    private FitVideoView videoView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.fragment_video_player, container, false);

        videoView = (FitVideoView) root.findViewById(R.id.surface);

        return root;
    }

    public void playVideo() {
        Uri uri = Uri.parse("android.resource://" + getActivity().getPackageName() + "/" + R.raw.test_vid);
        Log.d(TAG, "Uri is: " + uri);
        setVideoLocation(uri);
        if (!videoView.isPlaying()) {
            videoView.start();
        }
    }

    private void setVideoLocation(Uri uri) {
        try {
            videoView.setVideoURI(uri);
        } catch (Exception e) {
            Log.e(TAG, "VideoPlayer uri was invalid", e);
            Toast.makeText(getActivity(), "Not found", Toast.LENGTH_SHORT).show();
        }
    }

    public void pauseVideo() {
        if (videoView.isPlaying()) {
            videoView.pause();
        }
    }
}

解决方案

因此,此问题出现在VideoViewMediaPlayer + SurfaceView上.

当系统询问视频的宽度x高度时,它将返回640x480,而应返回852x480.

@Override
public void onPrepared(MediaPlayer mp) {
    mp.getVideoWidth();
    mp.getVideoHeight();
}

这要么是视频容器/编解码器的MediaPlayer处理中的错误,要么是视频文件本身的问题.

无论哪种方式,我都通过在代码中添加我知道的视频的宽度和高度来规避它.我已经使用此修复程序更新了 Git Repo . 黑客警报

这里是指向我发现不同尺寸的问题的链接我的视频的详细信息.

您可以将此修复程序应用于VideoView或直接应用于您选择的MediaPlayer + SurfaceView.这是VideoView答案:

public class FitVideoView extends VideoView {

    private final int mVideoWidth = 853;
    private final int mVideoHeight = 480;
    private boolean applyFix = true;

    public FitVideoView(Context context) {
        super(context);
    }

    public FitVideoView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FitVideoView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (applyFix) { // A Toggle so I can see both results
            // This doesn't ask the video for it's size, but uses my hardcoded size
            applyFix(widthMeasureSpec, heightMeasureSpec);
        } else {
            // This asks the video for its size (which gives an incorrect WxH) then does the same code as below
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    private void applyFix(int widthMeasureSpec, int heightMeasureSpec) {
        int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
        int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
        if (mVideoWidth > 0 && mVideoHeight > 0) {
            if (mVideoWidth * height > width * mVideoHeight) {
                Log.d("TAG", "image too tall, correcting");
                height = width * mVideoHeight / mVideoWidth;
            } else if (mVideoWidth * height < width * mVideoHeight) {
                Log.d("TAG", "image too wide, correcting");
                width = height * mVideoWidth / mVideoHeight;
            } else {
                Log.d("TAG", "aspect ratio is correct: " + width + "/" + height + "=" + mVideoWidth + "/" + mVideoHeight);
            }
        }
        Log.d("TAG", "setting size: " + width + 'x' + height);
        setMeasuredDimension(width, height);
    }
}

I have written a sample app that reproduces the problem:

https://github.com/blundell/VideoRatioProblemPerDevice

The VideoView documentation states:

Displays a video file. ... takes care of computing its measurement from the video so that it can be used in any layout manager, and provides various display options such as scaling

The problem is the Samsung Galaxy S3 is doing weird things to the video and not respecting the ratio of the video. (also happening on an HTC device).

Activity with full screen fragment:

What I have found is when the video is played on the Samsung Galaxy S3 it will play in an incorrect ratio. It looks like it has been stretched to the height of the view without any regard for the ratio of the original video.

here:

However if I play the video on a Samsung Galaxy Nexus the video is in the correct ratio.

here:

If I force the video to take up the full size of the fragment it looks ok on the S3 (because the ratio of the screen is the ratio of the video). However I don't want to do this as it screws up the fragment being used in other places i.e. tablets.

The code is:

An Activity with a Fragment with a VideoView. It can be seen here: GITHUB CODE LINK

if you want some code here is hte VideoPlayerFragment:

public class VideoPlayerFragment extends Fragment {

    private static final String TAG = "VideoPlayer";

    private FitVideoView videoView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.fragment_video_player, container, false);

        videoView = (FitVideoView) root.findViewById(R.id.surface);

        return root;
    }

    public void playVideo() {
        Uri uri = Uri.parse("android.resource://" + getActivity().getPackageName() + "/" + R.raw.test_vid);
        Log.d(TAG, "Uri is: " + uri);
        setVideoLocation(uri);
        if (!videoView.isPlaying()) {
            videoView.start();
        }
    }

    private void setVideoLocation(Uri uri) {
        try {
            videoView.setVideoURI(uri);
        } catch (Exception e) {
            Log.e(TAG, "VideoPlayer uri was invalid", e);
            Toast.makeText(getActivity(), "Not found", Toast.LENGTH_SHORT).show();
        }
    }

    public void pauseVideo() {
        if (videoView.isPlaying()) {
            videoView.pause();
        }
    }
}

解决方案

So this issue occurs with VideoView and with MediaPlayer + SurfaceView.

When the system asks the video for it's width x height it is returning 640x480 when it should be returning 852x480.

i.e.

@Override
public void onPrepared(MediaPlayer mp) {
    mp.getVideoWidth();
    mp.getVideoHeight();
}

This is either a bug in the MediaPlayer handling of the video container/codec or an issue with the video file itself.

Either way I have circumvented it by adding what I know the video's width and height is to my code. I have updated the Git Repo with this fix. hack alert

Here's a link to the question where I found out the different size details of my video.

You can apply this fix to the VideoView or directly to MediaPlayer + SurfaceView your choice. Here's the VideoView answer:

public class FitVideoView extends VideoView {

    private final int mVideoWidth = 853;
    private final int mVideoHeight = 480;
    private boolean applyFix = true;

    public FitVideoView(Context context) {
        super(context);
    }

    public FitVideoView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FitVideoView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (applyFix) { // A Toggle so I can see both results
            // This doesn't ask the video for it's size, but uses my hardcoded size
            applyFix(widthMeasureSpec, heightMeasureSpec);
        } else {
            // This asks the video for its size (which gives an incorrect WxH) then does the same code as below
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    private void applyFix(int widthMeasureSpec, int heightMeasureSpec) {
        int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
        int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
        if (mVideoWidth > 0 && mVideoHeight > 0) {
            if (mVideoWidth * height > width * mVideoHeight) {
                Log.d("TAG", "image too tall, correcting");
                height = width * mVideoHeight / mVideoWidth;
            } else if (mVideoWidth * height < width * mVideoHeight) {
                Log.d("TAG", "image too wide, correcting");
                width = height * mVideoWidth / mVideoHeight;
            } else {
                Log.d("TAG", "aspect ratio is correct: " + width + "/" + height + "=" + mVideoWidth + "/" + mVideoHeight);
            }
        }
        Log.d("TAG", "setting size: " + width + 'x' + height);
        setMeasuredDimension(width, height);
    }
}

这篇关于VideoVideo-视频宽度x高度-MediaPlayer问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆