首页 > 其他分享 >【Android】使用MediaExtractor获取关键帧的时间戳

【Android】使用MediaExtractor获取关键帧的时间戳

时间:2023-03-19 17:13:53浏览次数:53  
标签:关键帧 mediaExtractor 遍历 MediaExtractor 步长 time Android

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

相关文章