5

問題を再現するサンプルアプリを作成しました。

https://github.com/blundell/VideoRatioProblemPerDevice

VideoViewのドキュメントには次のように記載されています。

ビデオファイルを表示します。...ビデオからの測定値の計算を処理して、任意のレイアウトマネージャーで使用できるようにし、スケーリングなどのさまざまな表示オプションを提供します

問題は、Samsung Galaxy S3がビデオに対して奇妙なことをしていて、ビデオの比率を尊重していないことです。(HTCデバイスでも発生します)。

フルスクリーンフラグメントを使用したアクティビティ:

私が見つけたのは、ビデオがサムスンギャラクシーS3で再生されると、間違った比率で再生されるということです。元のビデオの比率に関係なく、ビューの高さまで引き伸ばされているように見えます。

ここ: s3

ただし、Samsung Galaxy Nexusでビデオを再生すると、ビデオは正しい比率になります。

ここ: n

ビデオにフラグメントのフルサイズを強制的に取り込むと、S3では問題ないように見えます(画面の比率がビデオの比率であるため)。ただし、他の場所、つまりタブレットで使用されているフラグメントを台無しにするため、これは実行したくありません。

コードは次のとおりです。

VideoViewを使用したフラグメントを含むアクティビティ。ここで見ることができます:GITHUB CODE LINK

ここにいくつかのコードが必要な場合は、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();
        }
    }
}
4

1 に答える 1

6

したがって、この問題は+で発生VideoViewします。MediaPlayerSurfaceView

システムがビデオに幅x高さを要求すると、852x480を返す必要があるのに640x480を返します。

すなわち

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

これは、ビデオコンテナ/コーデックの処理のバグかMediaPlayer、ビデオファイル自体の問題のいずれかです。

GSpotの詳細

いずれにせよ、ビデオの幅と高さがコードにあることがわかっているものを追加することで、これを回避しました。この修正でGitリポジトリを更新しました。ハックアラート

これは、ビデオのさまざまなサイズの詳細を見つけた質問へのリンクです。

+この修正は、VideoViewまたは直接選択に適用できます。答えは次のとおりです。MediaPlayerSurfaceViewVideoView

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);
    }
}
于 2013-01-13T11:50:11.173 に答える