使用MediaExtractor和MediaMuxer分类和合成视频

api16之后添加MediaExtractor可以分别操作视频音频,api18之后MediaMuxer可以进行视频的合成和分类。

项目截图


package com.example.lk.myradio;

import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

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

import static android.R.attr.format;

public class MainActivity extends AppCompatActivity {

    private String MP3PATH=Environment.getExternalStorageDirectory().getPath()+"/ma/abd.mp3";
    private String MP4PATH=Environment.getExternalStorageDirectory().getPath()+"/ma/abd.mp4";
    private String COMPOSITINGPATH=Environment.getExternalStorageDirectory().getPath()+"/ma/compositing.mp4";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new Thread(new Runnable() {
            @Override
            public void run() {
                deMP3();
            }
        }).start();
    }
    public void deMP3(){
        MediaExtractor extractor = new MediaExtractor();
        try {
            AssetManager am = this.getAssets();
            AssetFileDescriptor afd = am.openFd("weq.mp4");
            extractor.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(), afd.getLength());
        } catch (IOException e) {
            e.printStackTrace();
        }
        int audioIndex = -1;//音频通道
        int videoIndex = -1;//视频通道
        //获取多媒体文件信息
        MediaFormat audioFormat=null;
        MediaFormat videoFormat=null;
        MediaFormat trackFormat;
        for (int i = 0; i < extractor.getTrackCount()/*轨道数*/; i++) {
             trackFormat = extractor.getTrackFormat(i);
            if (trackFormat.getString(MediaFormat.KEY_MIME).startsWith("audio/")) {
                audioIndex = i;
                audioFormat=trackFormat;
            }
            if (trackFormat.getString(MediaFormat.KEY_MIME).startsWith("video/")) {
                videoIndex = i;
                videoFormat=trackFormat;
            }
        }
        extractor.selectTrack(audioIndex);//切换到音频通道
        File file=new File(Environment.getExternalStorageDirectory().getPath()+"/ma/");
        if(!file.exists()){
            file.mkdirs();
        }else{
            new File(Environment.getExternalStorageDirectory().getPath()+"/ma/abd.mp3");
            new File(Environment.getExternalStorageDirectory().getPath()+"/ma/abd.mp4");
        }
        doMp3(audioFormat,extractor,audioIndex);
        //释放音频的轨道
        extractor.unselectTrack(audioIndex);
        extractor.selectTrack(videoIndex);//切换到视频通道
        doMP4(videoFormat,extractor,videoIndex);
        extractor.release();
        compositing();
    }

    /**
     * 提取MP3
     * @param trackFormat
     * @param extractor
     * @param audioIndex
     */
    public void doMp3(MediaFormat trackFormat,MediaExtractor extractor,int audioIndex){
        MediaMuxer   mediaMuxer = null;
        try {

            mediaMuxer = new MediaMuxer( MP3PATH, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
        } catch (IOException e) {
            Log.e("IOException",""+e.toString());
            e.printStackTrace();
        }

        //添加轨道 得到轨道所在的index
        int writeAudioIndex = mediaMuxer.addTrack(trackFormat);
        mediaMuxer.start();
        //声明缓冲去,用于读取一帧的数据存放
        ByteBuffer byteBuffer = ByteBuffer.allocate(trackFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE));
        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
        long stampTime = 0;
        //获取相邻帧之间的间隔时间
        {
            //读取一帧
            extractor.readSampleData(byteBuffer, 0);
            if (extractor.getSampleFlags() == MediaExtractor.SAMPLE_FLAG_SYNC) {
                extractor.advance();
            }
            extractor.readSampleData(byteBuffer, 0);
            long secondTime = extractor.getSampleTime();
            //跳到下一帧
            extractor.advance();
            extractor.readSampleData(byteBuffer, 0);
            //得到这一帧的时间
            long thirdTime = extractor.getSampleTime();
            stampTime = Math.abs(thirdTime - secondTime);
        }
        //重新切换此信道,不然上面跳过了3帧,造成前面的帧数模糊
        extractor.unselectTrack(audioIndex);
        extractor.selectTrack(audioIndex);
        while (true) {
            int readSampleSize = extractor.readSampleData(byteBuffer, 0);
            if (readSampleSize < 0) {
                break;
            }
            extractor.advance();//移动到下一帧
            bufferInfo.size = readSampleSize;
            bufferInfo.flags = extractor.getSampleFlags();
            bufferInfo.offset = 0;
            bufferInfo.presentationTimeUs += stampTime;

            mediaMuxer.writeSampleData(writeAudioIndex, byteBuffer, bufferInfo);
        }
        mediaMuxer.stop();
        mediaMuxer.release();
    }

    /**
     * 提取MP4
     * @param trackFormat
     * @param extractor
     * @param videoIndex
     */
    public void doMP4(MediaFormat trackFormat,MediaExtractor extractor,int videoIndex){
        MediaMuxer   mediaMuxer = null;
        try {
            mediaMuxer = new MediaMuxer(MP4PATH, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
        } catch (IOException e) {
            Log.e("IOException",""+e.toString());
            e.printStackTrace();
        }

        int writevideoIndex = mediaMuxer.addTrack(trackFormat);
        mediaMuxer.start();
        ByteBuffer byteBuffer = ByteBuffer.allocate(trackFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE));
        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
        long stampTime = 0;
        //获取相邻帧之间的间隔时间
        {
            extractor.readSampleData(byteBuffer, 0);
            if (extractor.getSampleFlags() == MediaExtractor.SAMPLE_FLAG_SYNC) {
                extractor.advance();
            }
            extractor.readSampleData(byteBuffer, 0);
            long secondTime = extractor.getSampleTime();
            extractor.advance();
            extractor.readSampleData(byteBuffer, 0);
            long thirdTime = extractor.getSampleTime();
            stampTime = Math.abs(thirdTime - secondTime);
        }
        //重新切换此信道,不然上面跳过了3帧,造成前面的帧数模糊
        extractor.unselectTrack(videoIndex);
        extractor.selectTrack(videoIndex);
        while (true) {
            int readSampleSize = extractor.readSampleData(byteBuffer, 0);
            if (readSampleSize < 0) {
                break;
            }
            extractor.advance();//移动到下一帧
            bufferInfo.size = readSampleSize;
            bufferInfo.flags = extractor.getSampleFlags();
            bufferInfo.offset = 0;
            bufferInfo.presentationTimeUs += stampTime;

            //往往对应的轨道填写数据
            mediaMuxer.writeSampleData(writevideoIndex, byteBuffer, bufferInfo);
        }
        mediaMuxer.stop();
        mediaMuxer.release();
    }

    /**
     * 合成视频和音频
     */
    public void compositing(){
        MediaExtractor videoExtractor = new MediaExtractor();
        try {
            videoExtractor.setDataSource(MP4PATH);

        MediaFormat videoFormat = null;
        int videoTrackIndex = -1;
        int videoTrackCount = videoExtractor.getTrackCount();
        for (int i = 0; i < videoTrackCount; i++) {
            videoFormat = videoExtractor.getTrackFormat(i);
            String mimeType = videoFormat.getString(MediaFormat.KEY_MIME);
            if (mimeType.startsWith("video/")) {
                videoTrackIndex = i;
                break;
            }
        }
            MediaExtractor audioExtractor = new MediaExtractor();
            audioExtractor.setDataSource(MP3PATH);
            MediaFormat audioFormat = null;
            int audioTrackIndex = -1;
            int audioTrackCount = audioExtractor.getTrackCount();
            for (int i = 0; i < audioTrackCount; i++) {
                audioFormat = audioExtractor.getTrackFormat(i);
                String mimeType = audioFormat.getString(MediaFormat.KEY_MIME);
                if (mimeType.startsWith("audio/")) {
                    audioTrackIndex = i;
                    break;
                }
            }
            videoExtractor.selectTrack(videoTrackIndex);
            audioExtractor.selectTrack(audioTrackIndex);
            MediaCodec.BufferInfo videoBufferInfo = new MediaCodec.BufferInfo();
            MediaCodec.BufferInfo audioBufferInfo = new MediaCodec.BufferInfo();

            MediaMuxer mediaMuxer = new MediaMuxer(COMPOSITINGPATH, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
            int writeVideoTrackIndex = mediaMuxer.addTrack(videoFormat);
            int writeAudioTrackIndex = mediaMuxer.addTrack(audioFormat);
            mediaMuxer.start();

            ByteBuffer byteBuffer = ByteBuffer.allocate(500 * 1024);
            long sampleTime = 0;
            {
                videoExtractor.readSampleData(byteBuffer, 0);
                if (videoExtractor.getSampleFlags() == MediaExtractor.SAMPLE_FLAG_SYNC) {
                    videoExtractor.advance();
                }
                videoExtractor.readSampleData(byteBuffer, 0);
                long secondTime = videoExtractor.getSampleTime();
                videoExtractor.advance();
                long thirdTime = videoExtractor.getSampleTime();
                sampleTime = Math.abs(thirdTime - secondTime);
            }
            videoExtractor.unselectTrack(videoTrackIndex);
            videoExtractor.selectTrack(videoTrackIndex);

            while (true) {
                int readVideoSampleSize = videoExtractor.readSampleData(byteBuffer, 0);
                if (readVideoSampleSize < 0) {
                    break;
                }
                videoBufferInfo.size = readVideoSampleSize;
                videoBufferInfo.presentationTimeUs += sampleTime;
                videoBufferInfo.offset = 0;
                videoBufferInfo.flags = videoExtractor.getSampleFlags();
                mediaMuxer.writeSampleData(writeVideoTrackIndex, byteBuffer, videoBufferInfo);
                videoExtractor.advance();
            }

            while (true) {
                int readAudioSampleSize = audioExtractor.readSampleData(byteBuffer, 0);
                if (readAudioSampleSize < 0) {
                    break;
                }

                audioBufferInfo.size = readAudioSampleSize;
                audioBufferInfo.presentationTimeUs += sampleTime;
                audioBufferInfo.offset = 0;
                audioBufferInfo.flags = videoExtractor.getSampleFlags();
                mediaMuxer.writeSampleData(writeAudioTrackIndex, byteBuffer, audioBufferInfo);
                audioExtractor.advance();
            }

            mediaMuxer.stop();
            mediaMuxer.release();
            videoExtractor.release();
            audioExtractor.release();

        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值