1 前言
使用MediaExtractor、MediaMuxer去掉视频文件中的音频数据 中介绍了 MediaExtractor 类的主要方法,本文主要将使用其 advance() 和 seekTo(timeUs, mode) 方法遍历帧,以获取关键帧的时间戳。
advance() 方法能够从任意关键帧开始,依次往后遍历每一帧;seekTo() 方法能够定位到指定时间戳附近的关键帧。若只使用 advance()方法,则需要从头到尾遍历1遍所有帧;若只使用 seekTo() 方法,则需要知道所有关键帧附近的时间戳。
关键帧间的间隔一般在1~10秒之间,并且间隔不一定是均匀的,帧率一般为29帧/秒。为节省时间成本,本文以1秒为步长遍历视频帧,即每搜索一次,大概能跳过29帧。另外,部分视频是全关键帧的,为避免遍历步长较大,与视频中间处的关键帧间隔作比较,取较小者,作为遍历步长。之所以取中间处的关键帧间隔,因为部分视频的片头和片尾帧变化较小,编码压缩度较高,关键帧间隔较大,不适合用来作为遍历步长。
2 代码
package com.zhyan8.demo;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import java.io.IOException;
import java.util.ArrayList;
public class Demo {
private MediaExtractor mediaExtractor;
private long duration;
public Utils() {
mediaExtractor = new MediaExtractor();
try {
mediaExtractor.setDataSource("/sdcard/Pictures/WeiXin/a.mp4");
int count = mediaExtractor.getTrackCount(); //获取轨道数
for (int i = 0; i < count; i++) {
MediaFormat format = mediaExtractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("video/")) { // mp4为“video/avc”
mediaExtractor.selectTrack(i);
duration = format.getLong(MediaFormat.KEY_DURATION);
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public ArrayList<Long> get_key_frames_time() {
ArrayList<Long> list = new ArrayList();
long step = 1_000_000; //遍历步长
mediaExtractor.seekTo(duration/3, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
long start = mediaExtractor.getSampleTime();
mediaExtractor.advance();
while(true) { //获取遍历步长
if (mediaExtractor.getSampleFlags()==MediaExtractor.SAMPLE_FLAG_SYNC) {
step = Math.min(mediaExtractor.getSampleTime()-start, step);
break;
}
mediaExtractor.advance();
}
list.add(0L);
mediaExtractor.seekTo(step, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
long time = mediaExtractor.getSampleTime();
while(time<duration) { //获取关键帧时间戳列表
long time_temp = mediaExtractor.getSampleTime();
if (time_temp>list.get(list.size()-1)) {
list.add(time_temp);
time = time_temp;
} else {
time += step;
}
mediaExtractor.seekTo(time, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
}
return list;
}
}
声明:本文转自【Android】使用MediaExtractor获取关键帧的时间戳
标签:关键帧,mediaExtractor,遍历,MediaExtractor,步长,time,Android From: https://www.cnblogs.com/zhyan8/p/17233631.html