-
Notifications
You must be signed in to change notification settings - Fork 246
rawVideoData
xinbaicheng edited this page May 27, 2017
·
10 revisions
该方式暂时只在软解的情况下生效
必须在调用 prepareAsync 之前设置
// 输出视频格式为 ABGR8888
ksyMediaPlayer.setOption(KSYMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", KSYMediaPlayer.SDL_FCC_RV32);
// 输出视频格式为 YUV(一般情况是YUV420)
ksyMediaPlayer.setOption(KSYMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", KSYMediaPlayer.SDL_FCC_YV12);
在播放器分配每一帧视频的内存时会对视频的宽
做地址对齐,计算方式如下所示:
/**
* @param width 视频原始宽度
* @param align 地址对齐的基值,输出视频格式不同时,此值亦不同
* @return 地址对齐后的值
*/
public int alignWidth(int width, int align) {
return (width + align - 1) / align * align;
}
开发者需先申请相应的缓存,并交予播放器,播放器方可将视频数据交予开发者。
初始化buffer时,需要根据视频的宽高值计算,视频宽高数据需要在OnPrepared后才是有效数据。
部分MP4
视频自带有旋转信息,播放器在渲染时会根据该信息做出旋转,这会影响getVideoWidth和getVideoHeight这两个接口的返回值,在该情况下这两个接口返回的值是 旋转
之后的视频宽高
而原视频视频数据的回调接口onVideoRawDataAvailable中的视频宽高是原始视频宽高
假设开发者在某Activity实现获取视频原始数据的功能,可参考以下代码
private int mVideoWidth, mVideoHeight; // 原始视频宽高
private int widthAfterAligned; // 地址对齐后的宽
private ByteBuffer rawBuffer[] = new ByteBuffer[5]; // 5 is just an example.
private int mVideoOutputFormat; // 视频原始数据的输出格式
private int mVideoBufferSize = 0; // 视频原始数据所需的Buffer大小
private KSYMediaPlayer mKsyMediaPlayer; // 此处只是使用KSYMediaPlayer作为示例,同样可以使用KSYTextureView,接口一致
private IMediaPlayer.OnPreparedListener mOnPreparedListener = new IMediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(IMediaPlayer iMediaPlayer) {
mVideoWidth = mKsyMediaPlayer.getVideoWidth();
mVideoHeight = mKsyMediaPlayer.getVideoHeight();
initVideoRawData(); // 初始化输出视频原始数据相关
mKsyMediaPlayer.start();
}
};
private KSYMediaPlayer.OnVideoRawDataListener() mVideoRawDataListener = new KSYMediaPlayer.OnVideoRawDataListener(){
@Override
public void onVideoRawDataAvailable(IMediaPlayer mp, byte[] buf, int size, int width, int height, int format, long timeStampMS) {
//You can handle it in another thread, but never forget calling addVideoRawBuffer after it is done
// 使用含有视频原始数据的 buf
// ...
mKsyMediaPlayer.addVideoRawBuffer(buf); //MUST call it after the buf is handled
}
private void initVideoRawData() {
// 根据视频原始数据输出格式计算所需的内存大小
switch (mVideoOutputFormat) {
case KSYMediaPlayer.SDL_FCC_YV12:
widthAfterAligned = alignWidth(mVideoWidth, 16);
mVideoBufferSize = widthAfterAligned * mVideoHeight * 3 / 2;
break;
case KSYMediaPlayer.SDL_FCC_RV32:
widthAfterAligned = alignWidth(mVideoWidth, 4);
mVideoBufferSize = widthAfterAligned * mVideoHeight * 4;
break;
}
mKsyMediaPlayer.setVideoRawDataListener(mVideoRawDataListener); // 设置监听器
for(int index=0; index<rawBuffer.length; index++) {
//注意请在播放初始化之后(比如OnPrepared)再创建buffer
rawBuffer[index] = ByteBuffer.allocate(mVideoBufferSize); // make sure buffer Not smaller than video resolution
mKsyMediaPlayer.addVideoRawBuffer(rawBuffer[index].array());
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mKsyMediaPlayer = new KSYMediaPlayer.Builder(getApplicationContext()).build();
mVideoOutputFormat = KSYMediaPlayer.SDL_FCC_RV32;// 设置输出的视频原始数据格式为ABGR8888
mKsyMediaPlayer.setOption(KSYMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", mVideoOutputFormat);
mKsyMediaPlayer.prepareAsync();
}