自由贴: 免费、免注册、免审查匿名海报板,过期彻底删除,最高64K字节(约1.6万汉字)。图片请用 路过图床, Youimg 等图床
Page up Page up 发布新内容 Previous Page Next Page

MediaMuxer编码h264流文件

MediaMuxer mediaMuxer;
Map<Integer,Integer>map=new HashMap<>();
int save_x=0;
int time=0;
byte[]sps,pps;
int trackIndex;
MediaCodec mediaCodec=null;
class VideoToMp4 implements Runnable {
    byte[] save;
    int offset,length;

    public VideoToMp4(byte[] save, int offset, int length) {
        this.save = save;
        this.offset = offset;
        this.length = length;
    }
    @Override
    public void run() {
        int type=save[4]&0x1f;
 //判断I帧,然后根据具体情况获取sps,pps
        if(type==7){
            for (int i = 0; i < save.length-3; i++) {
                if(save[i]==0&&save[i+1]==0&&save[i+2]==0&&save[i+3]==1){
                    map.put(save_x,i);
                    save_x++;
                }
            }
            int length_sps=map.get(1)-map.get(0)-4;
            int offset_sps=map.get(0)+3;
            sps=new byte[length_sps];
            System.arraycopy(save,offset_sps,sps,0,length_sps);
            int length_pps=map.get(2)-map.get(1)-4;
            int offset_pps=map.get(1)+3;
            pps=new byte[length_pps];
            System.arraycopy(save,offset_pps,pps,0,length_pps);
        }
        if(type==7){
            BaseStatic.videoisStart=true;
            BaseStatic.savaInfoToSD("video is Start");
        }
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.JELLY_BEAN_MR2){
            if (BaseStatic.videoisLaunch&&BaseStatic.videoisStart) {
                synchronized (mediaMuxer) {

                    if (x == 1) {
                        BaseStatic.savaInfoToSD("videoformat is set");
                        //MediaFormat 只设置一次,标志“video/avc”表示h264.这里不是MP4
                        MediaFormat videoformat = MediaFormat.createVideoFormat("video/avc", dect[0], dect[1]);
                        videoformat.setByteBuffer("csd-0", ByteBuffer.wrap(sps));
                        videoformat.setByteBuffer("csd-1", ByteBuffer.wrap(pps));
                        videoformat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
                        videoformat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, dect[0] * dect[1]);
                        videoformat.setInteger("capture-rate", 30);
                        trackIndex = mediaMuxer.addTrack(videoformat);
                        mediaMuxer.start();
                        x++;
                    }
                    ByteBuffer byteBuffer;
                    byteBuffer = ByteBuffer.allocate(length);
                    byteBuffer.put(save);
                    MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
                    bufferInfo.offset = 0;
                    bufferInfo.size = length;
                    time++;
                    bufferInfo.flags = MediaCodec.BUFFER_FLAG_SYNC_FRAME;
                    if(BaseStatic.videoisEnd){
                        bufferInfo.flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
                    }
            //时间戳必须递增
                    bufferInfo.presentationTimeUs = 1000000*time / 30;

                    mediaMuxer.writeSampleData(trackIndex, byteBuffer, bufferInfo);

                    if(BaseStatic.videoisEnd){
                        time=0;
                        x=0;
                        BaseStatic.videoisStart=false;
                        BaseStatic.videoisLaunch=false;
                            BaseStatic.savaInfoToSD("mediaMuxer is stop");
                            mediaMuxer.stop();
                            BaseStatic.savaInfoToSD("mediaMuxer is release");
                            mediaMuxer.release();
                            mediaMuxer=null;
                    }
                }
            }

        }else{
            MyMethod.ShowDialog(getActivity(),"您的手机版本太低(<4.4),无法录像");
            BaseStatic.videoisLaunch=false;
            BaseStatic.videoisStart=false;
            mediaMuxer=null;
        }
    }
}
PID: 1847@2021-02-21 17:01:51 ~