音视频开发任务(4)——使用MediaExtract和MediaMuxer分离、合成视频

一、使用MediaExtract将视频分离

目标:用MediaExtract将视频分离成可播放的视频文件和音频文件

  1. 主要步骤:

  2. 初始化MediaExtractor和MediaMuxer

  3. 设置视频源

  4. 获取视频的通道数,并找到音视频通道记录下来

  5. 切换到相应的信道,读取数据到bytebuffer

  6. 记录视频帧/音频帧的信息,使用mediaMuxer把帧数据写入文件

  7. MediaExtractor的关键方法介绍:
    (1).mediaExtractor.setDataSource(SDCARD_PATH + "/test.mp4") 该方法设置数据源
    (2).mediaExtractor.getTrackCount()获取通道数量
    (3).mediaExtractor.selectTrack(videoIndex)切换到指定通道
    (4).mediaExtractor.readSampleData(byteBuffer, offset);读取一帧的数据,offset是在数据在byteoffer中的偏移量
    (5).mediaExtractor.advance()跳到下一帧

  8. MediaMuxerd的关键方法介绍:
    (1).int index=mediaMuxer.addTrack(MediaFormat)添加通道,返回值是通道编号
    (2).mediaMuxer.writeSampleData(mux_index_video, byteBuffer, bufferInfo)写入一帧的数据

  9. 个人对BufferInfo的理解:描述了buffer的一些基本信息,包括尺寸、偏移位、标志、时间戳

  10. 视频分离的主要代码(音频类似)

    private void mediaExvideo() {
        mediaExtractor = new MediaExtractor();
        int videoIndex = -1;
        try {
            mediaExtractor.setDataSource(SDCARD_PATH + "/test.mp4");
    
            for (int i = 0; i < mediaExtractor.getTrackCount(); i++) {
                MediaFormat mediaFormat = mediaExtractor.getTrackFormat(i);
                String mimitype = mediaFormat.getString(MediaFormat.KEY_MIME);
                //取出视频信号
                if (mimitype.startsWith("video")) {
                    videoIndex = i;
                    break;
                }
            }
            //切换到视频信号的信道
            mediaExtractor.selectTrack(videoIndex);
            MediaFormat mediaFormat_mux = mediaExtractor.getTrackFormat(videoIndex);
            mediaMuxer = new MediaMuxer(SDCARD_PATH + "/out_put.mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
            //追踪此信道
            int mux_index_video = mediaMuxer.addTrack(mediaFormat_mux);
            ByteBuffer byteBuffer = ByteBuffer.allocate(500 * 1024);
            MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
            mediaMuxer.start();
    
            long videoSampleTime;
            //获取每帧的时间
            {
                mediaExtractor.readSampleData(byteBuffer, 0);
                //跳过第一个 I 帧
                if (mediaExtractor.getSampleFlags() == MediaExtractor.SAMPLE_FLAG_SYNC)
                    mediaExtractor.advance();
                mediaExtractor.readSampleData(byteBuffer, 0);
    
                long firstVideoPTS = mediaExtractor.getSampleTime();
                mediaExtractor.advance();
                mediaExtractor.readSampleData(byteBuffer, 0);
                long secondeVideoPTS = mediaExtractor.getSampleTime();
                videoSampleTime = Math.abs(secondeVideoPTS - firstVideoPTS);
                Log.i(TAG, "videoSampleTime:" + videoSampleTime);
            }
            //重新切换此信道,不然跳过了3帧会导致帧数模糊
    
            mediaExtractor.unselectTrack(videoIndex);
            mediaExtractor.selectTrack(videoIndex);
            mediaExtractor.readSampleData(byteBuffer, 0);
    
            //读取每一帧数据
            while (true) {
                int readSampleSize = mediaExtractor.readSampleData(byteBuffer, 0);
                if (readSampleSize < 0)
                    break;
                mediaExtractor.advance();
                bufferInfo.size = readSampleSize;
                bufferInfo.offset = 0;
                bufferInfo.flags = mediaExtractor.getSampleFlags();
                bufferInfo.presentationTimeUs += videoSampleTime;
                //写入帧的数据
                mediaMuxer.writeSampleData(mux_index_video, byteBuffer, bufferInfo);
            }
            mediaMuxer.release();
            mediaExtractor.release();
            Log.i(TAG, "video extract finish");
        } catch (IOException e) {
            e.printStackTrace();
        }}
    
  11. 如何把分离后的音视频合成为新的视频:
    思路:通过通道的切换来控制音频数据和视频数据的写入

参考资料: https://blog.csdn.net/u012248972/article/details/80915736

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值