Android 最简单的播放器之MediaExtractor封装(一)
一、概述
案例:使用MediaExtractor+MediaFormat加载媒体文件信息。为后面使用MediaCodec硬件解码提供基础封装工具类
二、封装代码
1.IExtractor接口(定义公共方法)
public interface IExtractor {
/**
* 获取媒体格式
*
* @return
*/
MediaFormat getFormat();
/**
* 读取媒体数据
*
* @param byteBuffer 媒体数据(音频或视频、这里仅音频被使用)
* @return 读取的有效字节数
*/
int readBuffer(ByteBuffer byteBuffer);
/**
* 获取当前帧时间
* BaseExtractor
* @return
*/
long getCurrentTimestamp();
/**
* 获取当前帧flag
*
* @return
*/
long getSampleFlag();
/**
* Seek到指定位置,并返回实际帧的时间戳
*
* @param pos
* @return
*/
long seek(long pos);
/**
* 设置开始解码时间戳
*
* @param pos
*/
void setStartPos(long pos);
/**
* 停止读取数据
*/
void stop();
}
2.BaseExtractor 解析器基类
public abstract class BaseExtractor implements IExtractor {
private static final String TAG = "BaseExtractor";
enum MIME_TYPE {
MIME_VIDEO("video/"),
MIME_AUDIO("audio/");
MIME_TYPE(String video) {
}
}
/**
* 媒体提取器
*/
private MediaExtractor mediaExtractor;
/**
* 音频轨道
*/
private int mAudioTrackIndex = -1;
/**
* 视频轨道
*/
private int mVideoTrackIndex = -1;
/**
* 当前帧时间戳
*/
private long mCurSampleTime = 0;
/**
* 当前帧标志位
*/
private int mCurSampleFlag = 0;
/**
* 开始解码时间点
*/
private long mStartDecodeSampleTime = 0;
public BaseExtractor(@NonNull String mediaPath) {
//设置数据源
try {
mediaExtractor = new MediaExtractor();
mediaExtractor.setDataSource(mediaPath);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取视频轨
*
* @return
*/
public MediaFormat getVideoFormat() {
//获取轨道总数量
int trackCount = mediaExtractor.getTrackCount();
MediaFormat mediaFormat = null;
for (int i = 0; i < trackCount; i++) {
//获取MediaFormat
mediaFormat = mediaExtractor.getTrackFormat(i);
String mime = mediaFormat.getString(MediaFormat.KEY_MIME);
//如果
if (mime.startsWith("video/")) {
mVideoTrackIndex = i;
}
}
if (mVideoTrackIndex >= 0) {
return mediaFormat;
}
Log.e(TAG,"MediaFormat为空:mVideoTrackIndex-->"+mVideoTrackIndex);
return null;
}
/**
* 获取音频轨
*
* @return
*/
public MediaFormat getAudioFormat() {
int tackCount = mediaExtractor.getTrackCount();
MediaFormat mediaFormat = null;
for (int i = 0; i < tackCount; i++) {
mediaFormat = mediaExtractor.getTrackFormat(i);
String mime = mediaFormat.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("audio/")) {
mAudioTrackIndex = i;
}
}
if (mAudioTrackIndex >= 0) {
return mediaFormat;
}
return null;
}
/**
* 读取媒体数据
*
* @param byteBuffer
* @return
*/
public int readBuffer(ByteBuffer byteBuffer) {
byteBuffer.clear();
selectTrack();
int readSampleCount = mediaExtractor.readSampleData(byteBuffer, 0);
if (readSampleCount < 0) {
return -1;
}
//记录当前帧时间戳
mCurSampleTime = mediaExtractor.getSampleTime();
//记录当前帧标志位
mCurSampleFlag = mediaExtractor.getSampleFlags();
//进入下一帧
mediaExtractor.advance();
return readSampleCount;
}
/**
* 选择媒体轨道
*/
private void selectTrack() {
if (mVideoTrackIndex >= 0) {
mediaExtractor.selectTrack(mVideoTrackIndex);
} else if (mAudioTrackIndex >= 0) {
mediaExtractor.selectTrack(mAudioTrackIndex);
}
}
/**
* seek到指定的位置,并返回实际时间戳
*
* @param pos seek到的位置
* @return
*/
public long seek(long pos) {
mediaExtractor.seekTo(pos, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
return mediaExtractor.getSampleTime();
}
/**
* 停止读取数据
*/
public void stop() {
if (mediaExtractor != null) {
mediaExtractor.release();
mediaExtractor = null;
}
}
/**
* 获取视频轨索引
*
* @return
*/
public int getVideoTrackIndex() {
return mVideoTrackIndex;
}
/**
* 获取音频轨索引
*
* @return
*/
public int getAudioTrackIndex() {
return mAudioTrackIndex;
}
/**
* 设置开始解码时间戳
*
* @param pos
*/
public void setStartPos(long pos) {
mStartDecodeSampleTime = pos;
}
/**
* 获取当前帧时间
*
* @return
*/
public long getCurrentTimestamp() {
return mCurSampleTime;
}
/**
* 获取当前帧标志位
*
* @return
*/
public long getCurrentSampleFlag() {
return mCurSampleFlag;
}
}
3.VideoExtractor 视频格式解析器
public class VideoExtractor extends BaseExtractor{
public VideoExtractor(@NonNull String mediaPath) {
super(mediaPath);
}
@Override
public MediaFormat getFormat() {
return getVideoFormat();
}
@Override
public long getSampleFlag() {
return getCurrentSampleFlag();
}
}
public class AudioExtractor extends BaseExtractor {
public AudioExtractor(@NonNull String mediaPath) {
super(mediaPath);
}
@Override
public MediaFormat getFormat() {
return getAudioFormat();
}
@Override
public long getSampleFlag() {
return getCurrentSampleFlag();
}
}
4.AudioExtractor 音频格式解析器
5.MediaExtractorActivity 音视频格式测试类(主要打印基础信息,有写信息可以打印出啦,有些信息打印不出来)
浙公网安备 33010602011771号