【问题标题】:VideoVideo - Video Width x Height- MediaPlayer IssueVideoVideo - 视频宽度 x 高度 - MediaPlayer 问题
【发布时间】:2013-01-12 17:47:09
【问题描述】:

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

https://github.com/blundell/VideoRatioProblemPerDevice

VideoView 文档指出:

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

问题是三星 Galaxy S3 对视频做了奇怪的事情,并且不尊重视频的比例。(也发生在 HTC 设备上)。

带有全屏片段的活动:

我发现在三星 Galaxy S3 上播放视频时,它会以不正确的比例播放。看起来它已经被拉伸到视图的高度,而不考虑原始视频的比例。

这里:

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

这里:

如果我强制视频占据片段的完整大小,它在 S3 上看起来没问题(因为屏幕的比例就是视频的比例)。但是我不想这样做,因为它搞砸了在其他地方(例如平板电脑)使用的片段

代码是:

带有片段和 VideoView 的 Activity。可以看这里:GITHUB CODE LINK

如果你想要一些代码在这里是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();
        }
    }
}

【问题讨论】:

  • 您是否尝试从VideoView 切换到MediaPlayerSurfaceView
  • @CommonsWare 我没有,你认为有那么大的区别?我会试一试的。意味着我必须更多地自己照顾国家。
  • 制造商在某个地方进行了修补。他们可以修补的一个相对容易让你恢复的地方是,如果他们修补了VideoView。您甚至可以获取VideoView 源代码,将其放入您的项目中(重构到您的包中),切换到使用您的副本,然后看看会发生什么。如果问题得到解决,请坚持使用您的私人VideoView。如果问题仍然存在,那么问题就在于媒体播放的问题(a.k.a.,“这里有龙”)。
  • @CommonsWare 是的。尝试拉入VideoView,需要MediaPlayer,需要Metadata,这没关系。然而,MediaPlayer System.loadLibrary("media_jni"); 加载了一个本地库并给了我一个 unsatisfied link error。所以我打算试试MediaPlayerSurfaceView 路线。
  • 哇,VideoView 比我上次看到的要复杂得多。它曾经是大约 200 行代码,只是 MediaPlayerSurfaceView 的包装。很抱歉在这方面将您引向错误的方向。

标签: android android-fragments media-player android-videoview


【解决方案1】:

所以VideoViewMediaPlayer + SurfaceView 会出现此问题。

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

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

这可能是 MediaPlayer 处理视频容器/编解码器中的错误,或者是视频文件本身的问题。

无论哪种方式,我都通过将我知道的视频宽度和高度添加到我的代码中来规避它。我已经用这个修复更新了Git Repo黑客警报

这是我找到different size details of my video 的问题的链接。

您可以将此修复应用于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);
    }
}

【讨论】:

  • 我认为这不是一个错误,因为我的元数据中宽度和高度分别为 640x480 和 853x480 的特定视频也存在此问题。代码必须从视频轨道头或 TKHD 元数据中读取宽度。我很快就会发布一个单独的答案。
猜你喜欢
  • 1970-01-01
  • 2013-12-06
  • 2012-08-07
  • 1970-01-01
  • 2018-11-03
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多