2014-01-15 44 views
1

我正在嘗試使用SurfaceView從Android播放視頻。MediaPlayer播放聲音但不是視頻

我可以加載視頻,聲音播放正確但我看不到視頻。

這裏是我的活動:

public class VideoTest extends Activity implements OnBufferingUpdateListener, OnCompletionListener, OnPreparedListener, OnVideoSizeChangedListener, SurfaceHolder.Callback, OnErrorListener { 

    private static final String TAG = "MediaPlayerDemo"; 
    private int mVideoWidth; 
    private int mVideoHeight; 
    private MediaPlayer mMediaPlayer; 
    private SurfaceView mPreview; 
    private SurfaceHolder holder; 
    private String path; 
    private Bundle extras; 
    public static final String MEDIA = "media"; 
    private static final int LOCAL_AUDIO = 1; 
    public static final int STREAM_AUDIO = 2; 
    private static final int RESOURCES_AUDIO = 3; 
    private static final int LOCAL_VIDEO = 4; 
    public static final int STREAM_VIDEO = 5; 
    private boolean mIsVideoSizeKnown = false; 
    private boolean mIsVideoReadyToBePlayed = false; 
    private RelativeLayout layout; 

    /** 
    * 
    * Called when the activity is first created. 
    */ 
    @Override 
    public void onCreate(Bundle icicle) { 
     super.onCreate(icicle); 

     mPreview = new SurfaceView(this); 
     holder = mPreview.getHolder(); 
     holder.addCallback(this); 
     holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
     extras = getIntent().getExtras(); 

     mPreview.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); 

     layout = new RelativeLayout(this); 
     layout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); 
     layout.addView(mPreview, 0); 

     setContentView(layout); 

    } 

    private void playVideo(Integer Media) { 
     doCleanUp(); 
     try { 
      mMediaPlayer = MediaPlayer.create(this, R.raw.video); 
      mMediaPlayer.setDisplay(holder); 

      mMediaPlayer.setOnBufferingUpdateListener(this); 
      mMediaPlayer.setOnCompletionListener(this); 
      mMediaPlayer.setOnPreparedListener(this); 
      mMediaPlayer.setOnVideoSizeChangedListener(this); 
      mMediaPlayer.setOnErrorListener(this); 

      mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 

     } catch (Exception e) { 
      Log.e(TAG, "error: " + e.getMessage(), e); 
     } 
    } 

    public void onBufferingUpdate(MediaPlayer arg0, int percent) { 
     Log.d(TAG, "onBufferingUpdate percent:" + percent + " pos : " + mMediaPlayer.getCurrentPosition() + "/" + mMediaPlayer.getDuration()); 
     if (mMediaPlayer.isPlaying()) { 
      Log.d(TAG, "Playing"); 
     } else { 
      mMediaPlayer.start(); 
     } 
    } 

    public void onCompletion(MediaPlayer arg0) { 
     Log.d(TAG, "onCompletion called"); 
    } 

    public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { 
     Log.v(TAG, "onVideoSizeChanged called"); 
     if (width == 0 || height == 0) { 
      Log.e(TAG, "invalid video width(" + width + ") or height(" + height 
        + ")"); 
      return; 
     } 
     mIsVideoSizeKnown = true; 
     mVideoWidth = width; 
     mVideoHeight = height; 
     if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) { 
      startVideoPlayback(); 
     } 
    } 

    public void onPrepared(MediaPlayer mediaplayer) { 
     Log.d(TAG, "onPrepared called"); 
     mIsVideoReadyToBePlayed = true; 
     if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) { 
      startVideoPlayback(); 
     } 
    } 

    public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k) { 
     Log.d(TAG, "surfaceChanged called. Width : " + j + ", height : " + k); 
     holder = surfaceholder; 
     mMediaPlayer.setDisplay(holder); 
     mIsVideoSizeKnown = true; 
     mVideoWidth = j; 
     mVideoHeight = k; 
     if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) { 
      startVideoPlayback(); 
     } 
    } 

    public void surfaceDestroyed(SurfaceHolder surfaceholder) { 
     Log.d(TAG, "surfaceDestroyed called"); 
    } 

    public void surfaceCreated(SurfaceHolder holder) { 
     Log.d(TAG, "surfaceCreated called"); 
     playVideo(extras.getInt(MEDIA)); 

    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 
     releaseMediaPlayer(); 
     doCleanUp(); 
    } 

    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 
     releaseMediaPlayer(); 
     doCleanUp(); 
    } 

    private void releaseMediaPlayer() { 
     if (mMediaPlayer != null) { 
      mMediaPlayer.release(); 
      mMediaPlayer = null; 
     } 
    } 

    private void doCleanUp() { 
     mVideoWidth = 0; 
     mVideoHeight = 0; 
     mIsVideoReadyToBePlayed = false; 
     mIsVideoSizeKnown = false; 
    } 

    private void startVideoPlayback() { 
     Log.v(TAG, "startVideoPlayback " + mVideoWidth + "x" + mVideoHeight); 

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

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

     Log.i(TAG, String.format("startVideoPlayback @ video %dx%d - box %dx%d", (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.start(); 
    } 

    public boolean onError(MediaPlayer arg0, int arg1, int arg2) { 
     Log.e(TAG, "ERROR called : " + arg1 + ", " + arg2); 
     return false; 
    } 
} 

onVideoSizeChanged功能是從來沒有所謂,但onPreparedsurfaceChanged被調用。 因此調用startVideoPlayback函數,但視頻寬度和高度爲0.

我的視頻正在播放,因爲我可以聽到聲音,但屏幕上沒有顯示任何內容。 我也嘗試給對象的setFixedSize函數提供原始寬度和高度,但我仍然沒有顯示任何東西。

你能幫我嗎? 我使用的是Android 8

編輯

這裏是日誌的時候我打從資源的視頻,我有:

WARN info/warning (1, 35) 
WARN info/warning (1, 44) 
DEBUG Duration : 101248 
DEBUG surfaceChanged called. Width : 480, height : 270 
INFO Info (1,35) 
INFO Info (1,44) 
DEBUG onPrepared called 
VERBOSE startVideoPlayback 480x270 
INFO startVideoPlayback @ video 0x0 - box 480x270 
INFO Scaled to 480x0 
DEBUG surfaceDestroyed called 

EDIT 2

我嘗試了另一個視頻,它的工作。

這裏是 「不工作」 視頻的規格:

  • 集裝箱:MP4 - 的QuickTime
  • :2 340 Kbps的
  • 格式:H.264/MPEG-4-AVC
  • 大小:1280 * 640
  • 看點像素:未定義
  • 圖片比例:2.000
  • 編碼配置文件[email protected]

這裏是工作視頻規格:

  • 容器:MP4 - QuickTime
  • 費率:537 Kbps
  • 格式:H.264/MPEG-4-AVC
  • 尺寸:640 * 360
  • 看點像素:未定義
  • 圖片比例:16:9
  • 編碼配置文件[email protected]

你知道第一個視頻有什麼問題嗎?

+0

logcat顯示錯誤? – Nfear

+0

@Nfear我編輯我的問題添加日誌。我只有一些警告,但我不知道他們的意思 –

+0

其實它與另一個視頻合作,我更新了我的問題。你知道爲什麼第一個視頻不工作(使用相同的編碼) –

回答

0

有些事情嘗試:

1)如果你在你的playVideo方法調用mMediaPlayer.prepareAsync()?

2)嘗試在onPrepared

3)我會打電話holder.setSizeFromLayout刪除您的if語句();然後從onPrepared回調函數中調用mMediaPlayer.start()(而不是onBufferingUpdate)。

+0

1)應用程序崩潰,因爲構造函數已經調用prepare。 2-3)我的OnPrepare只有一個調用setSizeFromLayout並開始。視頻開始但屏幕上仍然沒有顯示 –

+0

@FabienHenon我認爲你指定了錯誤的寬高比,請檢查它 –