package com.dou361.ijkplayer.widget;
import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.MediaController;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import tv.danmaku.ijk.media.player.AndroidMediaPlayer;
import tv.danmaku.ijk.media.player.IMediaPlayer;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
import tv.danmaku.ijk.media.player.TextureMediaPlayer;
import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
/**
* ========================================
* <p>
* 版 权:dou361.com 版权所有 (C) 2015
* <p>
* 作 者:陈冠明
* <p>
* 个人网站:http://www.dou361.com
* <p>
* 版 本:1.0
* <p>
* 创建日期:2016/8/10 15:29
* <p>
* 描 述:视频渲染界面管理
* <p>
* <p>
* 修订历史:
* <p>
* ========================================
*/
public class IjkVideoView extends FrameLayout implements MediaController.MediaPlayerControl {
private String TAG = this.getClass().getSimpleName();
/**
* settable by the client 播放地址通过客户端可设置
*/
private Uri mUri;
/**
* 播放器的一些基本配置
*/
private Map<String, String> mHeaders;
/**
* mCurrentState is a VideoView object's current state.
* mTargetState is the state that a method caller intends to reach.
* For instance, regardless the VideoView object's current state,
* calling pause() intends to bring the object to a target state
* of STATE_PAUSED.
*/
private int mCurrentState = PlayStateParams.STATE_IDLE;
private int mTargetState = PlayStateParams.STATE_IDLE;
/**
* All the stuff we need for playing and showing a video 所有的东西我们需要播放和显示视频
*/
private IRenderView.ISurfaceHolder mSurfaceHolder = null;
/**
* 视频宽度
*/
private int mVideoWidth;
/**
* 视频高度
*/
private int mVideoHeight;
/**
* 窗口宽度
*/
private int mSurfaceWidth;
/**
* 窗口高度
*/
private int mSurfaceHeight;
/**
* 视频旋转角度
*/
private int mVideoRotationDegree;
/**
* 媒体播放器
*/
private IMediaPlayer mMediaPlayer;
/**
* 媒体控制器
*/
private IMediaController mMediaController;
/**
* 播放完成监听
*/
private IMediaPlayer.OnCompletionListener mOnCompletionListener;
/**
* 播放准备监听
*/
private IMediaPlayer.OnPreparedListener mOnPreparedListener;
/**
* 播放缓冲监听
*/
private int mCurrentBufferPercentage;
/**
* 播放错误监听
*/
private IMediaPlayer.OnErrorListener mOnErrorListener;
/**
* 播放其他信息监听
*/
private IMediaPlayer.OnInfoListener mOnInfoListener;
/**
* recording the seek position while preparing 记录寻求位置而做准备
*/
private long mSeekWhenPrepared;
/**
* 是否可以暂停
*/
private boolean mCanPause = true;
/** Subtitle rendering widget overlaid on top of the video. */
// private RenderingWidget mSubtitleWidget;
/**
* Listener for changes to subtitle data, used to redraw when needed.
*/
// private RenderingWidget.OnChangedListener mSubtitlesChangedListener;
private Context mAppContext;
private IRenderView mRenderView;
private int mVideoSarNum;
private int mVideoSarDen;
/**
* 使用Android播放器
*/
private boolean usingAndroidPlayer = false;
/**
* 使用编解码器硬编码还是软编码,true 硬编码 false 为软编码
*/
private boolean usingMediaCodec = false;
/**
* 使用编解码是否自转
*/
private boolean usingMediaCodecAutoRotate = false;
private boolean usingOpenSLES = false;
/**
* Auto Select=,RGB 565=fcc-rv16,RGB 888X=fcc-rv32,YV12=fcc-yv12,默认为RGB 888X
*/
private String pixelFormat = "";//Auto Select=,RGB 565=fcc-rv16,RGB 888X=fcc-rv32,YV12=fcc-yv12,默认为RGB 888X
private boolean enableBackgroundPlay = false;
public IjkVideoView(Context context) {
super(context);
initVideoView(context);
}
public IjkVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
initVideoView(context);
}
public IjkVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initVideoView(context);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public IjkVideoView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initVideoView(context);
}
// REMOVED: onMeasure
// REMOVED: onInitializeAccessibilityEvent
// REMOVED: onInitializeAccessibilityNodeInfo
// REMOVED: resolveAdjustedSize
/**
* 初始化视频view
*/
private void initVideoView(Context context) {
mAppContext = context.getApplicationContext();
initBackground();
initRenders();
mVideoWidth = 0;
mVideoHeight = 0;
// REMOVED: getHolder().addCallback(mSHCallback);
// REMOVED: getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
/** 设置为可触摸并且获取焦点 */
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
// REMOVED: mPendingSubtitleTracks = new Vector<Pair<InputStream, MediaFormat>>();
mCurrentState = PlayStateParams.STATE_IDLE;
mTargetState = PlayStateParams.STATE_IDLE;
}
/**
* 设置渲染器
*/
public void setRenderView(IRenderView renderView) {
if (mRenderView != null) {
if (mMediaPlayer != null)
mMediaPlayer.setDisplay(null);
View renderUIView = mRenderView.getView();
mRenderView.removeRenderCallback(mSHCallback);
mRenderView = null;
removeView(renderUIView);
}
if (renderView == null)
return;
mRenderView = renderView;
renderView.setAspectRatio(mCurrentAspectRatio);
if (mVideoWidth > 0 && mVideoHeight > 0)
renderView.setVideoSize(mVideoWidth, mVideoHeight);
if (mVideoSarNum > 0 && mVideoSarDen > 0)
renderView.setVideoSampleAspectRatio(mVideoSarNum, mVideoSarDen);
View renderUIView = mRenderView.getView();
/**修复一个bug,宽度不填满问题,感谢热心兄弟的慧眼*/
LayoutParams lp = new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT,
Gravity.CENTER);
renderUIView.setLayoutParams(lp);
addView(renderUIView);
mRenderView.addRenderCallback(mSHCallback);
mRenderView.setVideoRotation(mVideoRotationDegree);
}
/**
* 设置旋转角度
*/
public void setPlayerRotation(int rotation) {
mVideoRotationDegree = rotation;
if (mRenderView != null) {
mRenderView.setVideoRotation(mVideoRotationDegree);
}
}
/**
* 旋转渲染器
*/
public void setRender(int render) {
switch (render) {
case RENDER_TEXTURE_VIEW: {
TextureRenderView renderView = new Te
IjkVideoView
最新推荐文章于 2024-07-10 21:37:49 发布