MediaExtractor and MediaMuxer的使用 (重制版)

过了一个月了,一直在学习MediaCodec等工具,回头翻了一下上月demux and mux的博客,发现丑到爆炸,于是选择重制,懒得删了。

MediaExtractor 的使用:

在new 一个MediaExtractor的对象后,需要setDataSource,在这里我发现可以不必写到sd卡再设置。

 srcFilePath = getResources().openRawResourceFd(R.raw.shape_of_my_heart);
       
     extractor.setDataSource(srcFilePath);

接下来就是取track并给muxer添加好track

     for (int i = 0; i < extractor.getTrackCount(); i++){
            MediaFormat format = extractor.getTrackFormat(i);
            String MIME = format.getString(MediaFormat.KEY_MIME);
            if (MIME.startsWith("video")){
                videoIndex = i;
                videoInputSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
                continue;
            }
            if (MIME.startsWith("audio")){
                audioIndex = i;
                audioInputSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
            }
        }
        try {
            muxer = new MediaMuxer(filePath,MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (0 > videoTrackIndex){
            MediaFormat format = extractor.getTrackFormat(videoIndex);
            videoTrackIndex = muxer.addTrack(format);
        }
        if (0 > audioTrackIndex){
            MediaFormat format = extractor.getTrackFormat(audioIndex);
            audioTrackIndex = muxer.addTrack(format);
        }
if (!isMuxerStarted && 0 <= audioTrackIndex && 0 <= videoTrackIndex){
                muxer.start();
                isMuxerStarted = true;
            }else{
                throw new IllegalArgumentException("muxer track添加失败");
            }

然后就是塞数据了

 MediaFormat format = extractor.getTrackFormat(index);
        String MIME = format.getString(MediaFormat.KEY_MIME);
        extractor.selectTrack(index);
        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
        while(true) {
            ByteBuffer inputBuffer = ByteBuffer.allocate(inputSize);
            int size = extractor.readSampleData(inputBuffer , 0 );
            if (0 > size){
                Log.v("tag","start release Muxer And Extractor");
                break;
            }else{
                info.presentationTimeUs = extractor.getSampleTime();
                info.flags = extractor.getSampleFlags();
                info.offset = 0;
                info.size = size;
                muxer.writeSampleData(trackIndex,inputBuffer,info);
                extractor.advance();
                Log.d("tag","muxing " + MIME);
            }
        }

然后如果塞数据的操作放在住线程的话,容易因为耗时丢帧,所以建议开线程写

接下来就是完整代码了,感觉上一篇写的真的渣。

demux and mux的核心操作的代码

package com.example.myapplication3;

import android.content.res.AssetFileDescriptor;
import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.util.Log;

import java.io.IOException;
import java.nio.ByteBuffer;

/**
 * Created by weizheng.huang on 2019-10-31.
 */
public class DemuxAndMux {
    private MediaExtractor  extractor;
    private MediaMuxer muxer ;
    private AssetFileDescriptor srcFilePath;
    private String filePath;
    private int videoIndex  = -1;
    private int audioIndex = -1;
    private int videoTrackIndex = -1;
    private int audioTrackIndex = -1;
    private boolean isMuxerStarted = false;
    private int videoInputSize;
    private int audioInputSize;


    public DemuxAndMux(AssetFileDescriptor afd , String filePath){
        this.srcFilePath = afd;
        this.filePath = filePath;
    }

    public void init(){
        initMediaExtractor();
        initMediaMuxer();
    }
    private void initMediaExtractor(){
        extractor = new MediaExtractor();
        try {
            extractor.setDataSource(srcFilePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < extractor.getTrackCount(); i++){
            MediaFormat format = extractor.getTrackFormat(i);
            String MIME = format.getString(MediaFormat.KEY_MIME);
            if (MIME.startsWith("video")){
                videoIndex = i;
                videoInputSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
                continue;
            }
            if (MIME.startsWith("audio")){
                audioIndex = i;
                audioInputSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
            }
        }
    }


    private void initMediaMuxer(){
        try {
            muxer = new MediaMuxer(filePath,MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (0 > videoTrackIndex){
            MediaFormat format = extractor.getTrackFormat(videoIndex);
            videoTrackIndex = muxer.addTrack(format);
        }
        if (0 > audioTrackIndex){
            MediaFormat format = extractor.getTrackFormat(audioIndex);
            audioTrackIndex = muxer.addTrack(format);
        }

    }

    private Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            if (!isMuxerStarted && 0 <= audioTrackIndex && 0 <= videoTrackIndex){
                muxer.start();
                isMuxerStarted = true;
            }else{
                throw new IllegalArgumentException("muxer track添加失败");
            }
            writeIntoBuffer(videoInputSize,videoTrackIndex,videoIndex);
            writeIntoBuffer(audioInputSize,audioTrackIndex,audioIndex);
            muxer.stop();
            muxer.release();
            extractor.release();
            Log.v("tag","released muxer and extractor");
        }
    });

    public void startDemuxAndMux(){
        thread.start();
    }


    private void writeIntoBuffer(int inputSize,int trackIndex , int index){
        MediaFormat format = extractor.getTrackFormat(index);
        String MIME = format.getString(MediaFormat.KEY_MIME);
        extractor.selectTrack(index);
        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
        while(true) {
            ByteBuffer inputBuffer = ByteBuffer.allocate(inputSize);
            int size = extractor.readSampleData(inputBuffer , 0 );
            if (0 > size){
                Log.v("tag","start release Muxer And Extractor");
                break;
            }else{
                info.presentationTimeUs = extractor.getSampleTime();
                info.flags = extractor.getSampleFlags();
                info.offset = 0;
                info.size = size;
                muxer.writeSampleData(trackIndex,inputBuffer,info);
                extractor.advance();
                Log.d("tag","muxing " + MIME);
            }
        }
    }


}

MainActivity的代码,这里只是抽了一部分代码出来,主要是因为项目里还有其他代码不方便拿出来了。

/**
* srcFilePath 这里是视频文件路径 类型是AssertFileDescriptor
* filePath 这里是sd卡存放路径
*/
private DemuxAndMux demuxAndMux = new DemuxAndMux(srcFilePath,filePath);

demuxAndMux.init();

 muxBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (verifyPermission(MainActivity.this)) {
                    demuxAndMux.startDemuxAndMux();
                }
            }
        });

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值