android.media.MediaCodec# createEncoderByType ( ) 源码实例Demo

下面列出了android.media.MediaCodec# createEncoderByType ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。


private void initAudioCodec(String audioType, int sampleRate, int channels) {
    try {
        audioCodec = MediaCodec.createEncoderByType(audioType);
        MediaFormat audioFormat = MediaFormat.createAudioFormat(audioType, sampleRate, channels);
        int BIT_RATE = 96000;
        audioFormat.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
        audioFormat.setInteger(MediaFormat.KEY_AAC_PROFILE,
                MediaCodecInfo.CodecProfileLevel.AACObjectLC);
        int MAX_INOUT_SIZE = 8192;
        audioFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, MAX_INOUT_SIZE);

        audioCodec.configure(audioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);

        audioBuffer = new MediaCodec.BufferInfo();

    } catch (IOException e) {
        Log.e(TAG, "initAudioCodec: 音频类型无效");
    }
}
 
源代码2 项目: EZFilter   文件: VideoTrackTranscoder.java

@Override
    public void setup() throws IOException {
        mExtractor.selectTrack(mTrackIndex);
        mEncoder = MediaCodec.createEncoderByType(mOutputFormat.getString(MediaFormat.KEY_MIME));
        mEncoder.configure(mOutputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        mEncoderInputSurfaceWrapper = new InputSurface(mEncoder.createInputSurface());
        mEncoder.start();
        mEncoderStarted = true;

        MediaFormat inputFormat = mExtractor.getTrackFormat(mTrackIndex);
//        if (inputFormat.containsKey(MediaUtil.KEY_ROTATION)) {
//            // Decoded video is rotated automatically in Android 5.0 lollipop.
//            // Turn off here because we don't want to encode rotated one.
//            // refer: https://android.googlesource
//            // .com/platform/frameworks/av/+blame/lollipop-release/media/libstagefright/Utils.cpp
//            inputFormat.setInteger(MediaUtil.KEY_ROTATION, 0);
//        }

        mDecoderOutputSurfaceWrapper = new OutputSurface(mSurfaceRender);
        mDecoder = MediaCodec.createDecoderByType(inputFormat.getString(MediaFormat.KEY_MIME));
        mDecoder.configure(inputFormat, mDecoderOutputSurfaceWrapper.getSurface(), null, 0);
        mDecoder.start();
        mDecoderStarted = true;
    }
 

private void prepareEncoder() {
    MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, mWidth, mHeight);
    format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
    format.setInteger(MediaFormat.KEY_BIT_RATE, mBitRate);
    format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
    format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);

    Log.d(TAG, "created video format: " + format);
    try {
        mEncoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);
    } catch (IOException e) {
        e.printStackTrace();
    }
    mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    mSurface = mEncoder.createInputSurface();
    Log.d(TAG, "created input surface: " + mSurface);
    mEncoder.start();
}
 
源代码4 项目: VideoRecorder   文件: VideoEncoder.java

@Override
protected MediaCodec createEncoder() throws IOException {
    LogUtil.logd(TAG, "createEncoder");
    MediaFormat videoFormat = MediaFormat.createVideoFormat(MIME_TYPE, mVideoSize.getWidth(), mVideoSize.getHeight());
    videoFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
    videoFormat.setInteger(MediaFormat.KEY_BIT_RATE, mBitRate);
    videoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
    videoFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, mIFrameInterval);
    LogUtil.logd(TAG, "format: " + videoFormat);


    MediaCodec encoder = MediaCodec.createEncoderByType(MIME_TYPE);
    encoder.configure(videoFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    mInputSurface = encoder.createInputSurface();
    encoder.start();
    LogUtil.logd(TAG, "createEncoder finishing");
    return encoder;
}
 
源代码5 项目: bcm-android   文件: AudioCodec.java

private MediaCodec createMediaCodec(int bufferSize) throws IOException {
    MediaCodec mediaCodec = MediaCodec.createEncoderByType("audio/mp4a-latm");
    MediaFormat mediaFormat = new MediaFormat();

    mediaFormat.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
    mediaFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, SAMPLE_RATE);
    mediaFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, CHANNELS);
    mediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, bufferSize);
    mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
    mediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);

    try {
        mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    } catch (Exception e) {
        Log.w(TAG, e);
        mediaCodec.release();
        throw new IOException(e);
    }

    return mediaCodec;
}
 
源代码6 项目: RtmpPublisher   文件: AudioEncoder.java

/**
 * prepare the Encoder. call this before start the encoder.
 */
void prepare(int bitrate, int sampleRate, long startStreamingAt) {
    int bufferSize = AudioRecord.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_IN_MONO,
            AudioFormat.ENCODING_PCM_16BIT);
    MediaFormat audioFormat =
            MediaFormat.createAudioFormat(AUDIO_MIME_TYPE, sampleRate, CHANNEL_COUNT);
    audioFormat.setInteger(MediaFormat.KEY_AAC_PROFILE,
            MediaCodecInfo.CodecProfileLevel.AACObjectLC);
    audioFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
    audioFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, bufferSize);
    startedEncodingAt = startStreamingAt;
    try {
        encoder = MediaCodec.createEncoderByType(AUDIO_MIME_TYPE);
        encoder.configure(audioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    } catch (IOException | IllegalStateException e) {
        e.printStackTrace();
    }
}
 
源代码7 项目: grafika   文件: ScreenRecordActivity.java

@RequiresApi(api = Build.VERSION_CODES.M)
private void prepareVideoEncoder(int width, int height) {
  MediaFormat format = MediaFormat.createVideoFormat(VIDEO_MIME_TYPE, width, height);
  int frameRate = 30; // 30 fps

  // Set some required properties. The media codec may fail if these aren't defined.
  format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
          MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
  format.setInteger(MediaFormat.KEY_BIT_RATE, 6000000); // 6Mbps
  format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
  format.setInteger(MediaFormat.KEY_CAPTURE_RATE, frameRate);
  format.setInteger(MediaFormat.KEY_REPEAT_PREVIOUS_FRAME_AFTER, 1000000 / frameRate);
  format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
  format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1); // 1 seconds between I-frames

  // Create a MediaCodec encoder and configure it. Get a Surface we can use for recording into.
  try {
    videoEncoder = MediaCodec.createEncoderByType(VIDEO_MIME_TYPE);
    videoEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    inputSurface = videoEncoder.createInputSurface();
    videoEncoder.setCallback(encoderCallback);
    videoEncoder.start();
  } catch (IOException e) {
    releaseEncoders();
  }
}
 
源代码8 项目: WeiXinRecordedDemo   文件: RecordUtil.java

private void initVideoMediaCodec()throws Exception{
    MediaFormat mediaFormat;
    if(rotation==90 || rotation==270){
        //设置视频宽高
        mediaFormat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, videoHeight, videoWidth);
    }else{
        mediaFormat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, videoWidth, videoHeight);
    }
    //图像数据格式 YUV420
    mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar);
    //码率
    mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, videoWidth*videoHeight*3);
    //每秒30帧
    mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
    //1秒一个关键帧
    mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
    videoMediaCodec = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);
    videoMediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    videoMediaCodec.start();
}
 
源代码9 项目: AAVT   文件: CameraRecorder.java

public void startRecord() throws IOException {
        synchronized (REC_LOCK){
            isRecordStarted=true;
            MediaFormat audioFormat=mConfig.getAudioFormat();
            mAudioEncoder=MediaCodec.createEncoderByType(audioFormat.getString(MediaFormat.KEY_MIME));
            mAudioEncoder.configure(audioFormat,null,null,MediaCodec.CONFIGURE_FLAG_ENCODE);
            MediaFormat videoFormat=mConfig.getVideoFormat();
            mVideoEncoder=MediaCodec.createEncoderByType(videoFormat.getString(MediaFormat.KEY_MIME));
            //此处不能用mOutputSurface,会configure失败
            mVideoEncoder.configure(videoFormat,null,null,MediaCodec.CONFIGURE_FLAG_ENCODE);
            mEncodeSurface=mVideoEncoder.createInputSurface();

            mAudioEncoder.start();
            mVideoEncoder.start();
            mMuxer=new MediaMuxer(mOutputPath,MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
            mRecordBufferSize = AudioRecord.getMinBufferSize(mRecordSampleRate,
                    mRecordChannelConfig, mRecordAudioFormat)*2;
//        buffer=new byte[bufferSize];
            mAudioRecord=new AudioRecord(MediaRecorder.AudioSource.MIC,mRecordSampleRate,mRecordChannelConfig,
                    mRecordAudioFormat,mRecordBufferSize);

            mAudioThread=new Thread(new Runnable() {
                @Override
                public void run() {
                    mAudioRecord.startRecording();
                    while (!audioEncodeStep(isTryStopAudio)){};
                    mAudioRecord.stop();
                }
            });
            mAudioThread.start();
            isRecordAudioStarted=true;
        }
    }
 
源代码10 项目: grafika   文件: CodecOpenActivity.java

/**
 * onClick handler for "start" button.
 *
 * We create as many codecs as we can and return without releasing them.  The codecs
 * will remain in use until the next GC.
 */
public void clickStart(@SuppressWarnings("unused") View unused) {
    final String MIME_TYPE = "video/avc";
    final int WIDTH = 320;
    final int HEIGHT = 240;
    final int BIT_RATE = 1000000;
    final int FRAME_RATE = 15;
    final int IFRAME_INTERVAL = 1;
    final boolean START_CODEC = true;

    MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, WIDTH, HEIGHT);

    format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
            MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
    format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
    format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
    format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
    Log.d(TAG, "format: " + format);

    MediaCodec[] codecs = new MediaCodec[MAX_OPEN];
    int i;
    for (i = 0; i < MAX_OPEN; i++) {
        try {
            codecs[i] = MediaCodec.createEncoderByType(MIME_TYPE);
            codecs[i].configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
            if (START_CODEC) {
                codecs[i].createInputSurface();
                codecs[i].start();
            }
        } catch (Exception ex) {
            Log.i(TAG, "Failed on creation of codec #" + i, ex);
            break;
        }
    }

    showCountDialog(i);
}
 
源代码11 项目: VIA-AI   文件: AvcEncoder.java

public AvcEncoder(EncodeParameters encodeParameters, EncodedFrameListener listener) throws IOException {

        mEncodeParameters = new EncodeParameters(encodeParameters);
        mediaCodec = MediaCodec.createEncoderByType("video/avc");
        MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", mEncodeParameters.getWidth(), mEncodeParameters.getHeight());
        mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, mEncodeParameters.getBitrate());
        mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
        mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, mEncodeParameters.getColor_format());
        mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
        mFrameListener = listener;
        mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        if(mEncodeParameters.getColor_format()== MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface) {
            mInputSurface = mediaCodec.createInputSurface();
        }
    }
 
源代码12 项目: Android-Audio-Recorder   文件: MuxerMP4.java

public void create(EncoderInfo info, MediaFormat format, File out) {
    this.info = info;

    try {
        encoder = MediaCodec.createEncoderByType(format.getString(MediaFormat.KEY_MIME));
        encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        encoder.start();

        muxer = new MediaMuxer(out.getAbsolutePath(), MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
 

/**
 * 开始录制前的准备(目前由SohuMediaMuxerManager在主线程调用)
 *
 * @throws IOException
 */
@Override
public void prepare() throws IOException {
    LogUtils.d(TAG, "---prepare---");
    //
    mTrackIndex = -1;
    //
    mMuxerStarted = mIsEndOfStream = false;

    //-----------------MediaFormat-----------------------
    // mediaCodeC采用的是H.264编码
    final MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
    // 数据来源自surface
    format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
    // 视频码率
    format.setInteger(MediaFormat.KEY_BIT_RATE, calcBitRate());
    // fps
    format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
    //设置关键帧的时间
    format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);

    //-----------------Encoder-----------------------
    mMediaCodec = MediaCodec.createEncoderByType(MIME_TYPE);
    mMediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    // get Surface for encoder input
    // this method only can call between #configure and #start
    mSurface = mMediaCodec.createInputSurface();
    //
    mMediaCodec.start();
    //
    LogUtils.i(TAG, "prepare finishing");
    if (mMediaEncoderListener != null) {
        try {
            mMediaEncoderListener.onPrepared(this);
        } catch (final Exception e) {
            Log.e(TAG, "prepare:", e);
        }
    }
}
 
源代码14 项目: libcommon   文件: AudioEncoder.java

@Override
	protected boolean internalPrepare() throws Exception {
//		if (DEBUG) Log.v(TAG, "internalPrepare:");
        mTrackIndex = -1;
        mRecorderStarted = mIsEOS = false;

// 内蔵マイクから音声を取り込んでAACにエンコードするためのMediaCodecの準備
        final MediaCodecInfo audioCodecInfo = MediaCodecUtils.selectAudioEncoder(MIME_TYPE);
        if (audioCodecInfo == null) {
//			Log.e(TAG, "Unable to find an appropriate codec for " + MIME_TYPE);
            return true;
        }
//		if (DEBUG) Log.i(TAG, "selected codec: " + audioCodecInfo.getName());

        final MediaFormat audioFormat = MediaFormat.createAudioFormat(MIME_TYPE, mSampleRate, mChannelCount);
		audioFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
		audioFormat.setInteger(MediaFormat.KEY_CHANNEL_MASK,
			mChannelCount == 1 ? AudioFormat.CHANNEL_IN_MONO : AudioFormat.CHANNEL_IN_STEREO);
		audioFormat.setInteger(MediaFormat.KEY_BIT_RATE, AbstractAudioEncoder.DEFAULT_BIT_RATE);
		audioFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
//		audioFormat.setLong(MediaFormat.KEY_MAX_INPUT_SIZE, inputFile.length());
//      audioFormat.setLong(MediaFormat.KEY_DURATION, (long)durationInMs );
//		if (DEBUG) Log.i(TAG, "format: " + audioFormat);

		mMediaCodec = MediaCodec.createEncoderByType(MIME_TYPE);
        mMediaCodec.configure(audioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        mMediaCodec.start();
//		if (DEBUG) Log.i(TAG, "internalPrepare:finished");
		return false;
	}
 
源代码15 项目: MusicPlus   文件: AACAudioEncoder.java

private MediaCodec createACCAudioDecoder() throws IOException {
	MediaCodec codec = MediaCodec.createEncoderByType(AUDIO_MIME);
	MediaFormat format = new MediaFormat();
	format.setString(MediaFormat.KEY_MIME, AUDIO_MIME);
	format.setInteger(MediaFormat.KEY_BIT_RATE, 128000);
	format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 2);
	format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100);
	format.setInteger(MediaFormat.KEY_AAC_PROFILE,
			MediaCodecInfo.CodecProfileLevel.AACObjectLC);
	codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
	return codec;
}
 
源代码16 项目: TikTok   文件: VideoEncoderCore.java

/**
 * Configures encoder and muxer state, and prepares the input Surface.
 */
public VideoEncoderCore(int width, int height, int bitRate, File outputFile)
        throws IOException {
    mBufferInfo = new MediaCodec.BufferInfo();

    MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, width, height);

    // Set some properties.  Failing to specify some of these can cause the MediaCodec
    // configure() call to throw an unhelpful exception.
    format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
            MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
    format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
    format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
    format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
    if (VERBOSE) Log.d(TAG, "format: " + format);

    // Create a MediaCodec encoder, and configure it with our format.  Get a Surface
    // we can use for input and wrap it with a class that handles the EGL work.
    mEncoder = MediaCodec.createEncoderByType(MIME_TYPE);
    mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    mInputSurface = mEncoder.createInputSurface();
    mEncoder.start();

    // Create a MediaMuxer.  We can't add the video track and start() the muxer here,
    // because our MediaFormat doesn't have the Magic Goodies.  These can only be
    // obtained from the encoder after it has started processing data.
    //
    // We're not actually interested in multiplexing audio.  We just want to convert
    // the raw H.264 elementary stream we get from MediaCodec into a .mp4 file.
    mMuxer = new MediaMuxer(outputFile.toString(),
            MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);

    mTrackIndex = -1;
    mMuxerStarted = false;
}
 
源代码17 项目: grafika   文件: GeneratedMovie.java

/**
 * Prepares the video encoder, muxer, and an EGL input surface.
 */
protected void prepareEncoder(String mimeType, int width, int height, int bitRate,
        int framesPerSecond, File outputFile) throws IOException {
    mBufferInfo = new MediaCodec.BufferInfo();

    MediaFormat format = MediaFormat.createVideoFormat(mimeType, width, height);

    // Set some properties.  Failing to specify some of these can cause the MediaCodec
    // configure() call to throw an unhelpful exception.
    format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
            MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
    format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
    format.setInteger(MediaFormat.KEY_FRAME_RATE, framesPerSecond);
    format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
    if (VERBOSE) Log.d(TAG, "format: " + format);

    // Create a MediaCodec encoder, and configure it with our format.  Get a Surface
    // we can use for input and wrap it with a class that handles the EGL work.
    mEncoder = MediaCodec.createEncoderByType(mimeType);
    mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    Log.v(TAG, "encoder is " + mEncoder.getCodecInfo().getName());
    Surface surface;
    try {
        surface = mEncoder.createInputSurface();
    } catch (IllegalStateException ise) {
        // This is generally the first time we ever try to encode something through a
        // Surface, so specialize the message a bit if we can guess at why it's failing.
        // TODO: failure message should come out of strings.xml for i18n
        if (isSoftwareCodec(mEncoder)) {
            throw new RuntimeException("Can't use input surface with software codec: " +
                    mEncoder.getCodecInfo().getName(),
                    ise);
        } else {
            throw new RuntimeException("Failed to create input surface", ise);
        }
    }
    mEglCore = new EglCore(null, EglCore.FLAG_RECORDABLE);
    mInputSurface = new WindowSurface(mEglCore, surface, true);
    mInputSurface.makeCurrent();
    mEncoder.start();

    // Create a MediaMuxer.  We can't add the video track and start() the muxer here,
    // because our MediaFormat doesn't have the Magic Goodies.  These can only be
    // obtained from the encoder after it has started processing data.
    //
    // We're not actually interested in multiplexing audio.  We just want to convert
    // the raw H.264 elementary stream we get from MediaCodec into a .mp4 file.
    if (VERBOSE) Log.d(TAG, "output will go to " + outputFile);
    mMuxer = new MediaMuxer(outputFile.toString(),
            MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);

    mTrackIndex = -1;
    mMuxerStarted = false;
}
 

/**
 * Edits a video file, saving the contents to a new file.  This involves decoding and
 * re-encoding, not to mention conversions between YUV and RGB, and so may be lossy.
 * <p>
 * If we recognize the decoded format we can do this in Java code using the ByteBuffer[]
 * output, but it's not practical to support all OEM formats.  By using a SurfaceTexture
 * for output and a Surface for input, we can avoid issues with obscure formats and can
 * use a fragment shader to do transformations.
 */
private VideoChunks editVideoFile(VideoChunks inputData) {
    if (VERBOSE) Log.d(TAG, "editVideoFile " + mWidth + "x" + mHeight);
    VideoChunks outputData = new VideoChunks();
    MediaCodec decoder = null;
    MediaCodec encoder = null;
    InputSurface inputSurface = null;
    OutputSurface outputSurface = null;
    try {
        MediaFormat inputFormat = inputData.getMediaFormat();
        // Create an encoder format that matches the input format.  (Might be able to just
        // re-use the format used to generate the video, since we want it to be the same.)
        MediaFormat outputFormat = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
        outputFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
                MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
        outputFormat.setInteger(MediaFormat.KEY_BIT_RATE,
                inputFormat.getInteger(MediaFormat.KEY_BIT_RATE));
        outputFormat.setInteger(MediaFormat.KEY_FRAME_RATE,
                inputFormat.getInteger(MediaFormat.KEY_FRAME_RATE));
        outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL,
                inputFormat.getInteger(MediaFormat.KEY_I_FRAME_INTERVAL));
        outputData.setMediaFormat(outputFormat);
        encoder = MediaCodec.createEncoderByType(MIME_TYPE);
        encoder.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        inputSurface = new InputSurface(encoder.createInputSurface());
        inputSurface.makeCurrent();
        encoder.start();
        // OutputSurface uses the EGL context created by InputSurface.
        decoder = MediaCodec.createDecoderByType(MIME_TYPE);
        outputSurface = new OutputSurface();
        outputSurface.changeFragmentShader(FRAGMENT_SHADER);
        decoder.configure(inputFormat, outputSurface.getSurface(), null, 0);
        decoder.start();
        editVideoData(inputData, decoder, outputSurface, inputSurface, encoder, outputData);
    } finally {
        if (VERBOSE) Log.d(TAG, "shutting down encoder, decoder");
        if (outputSurface != null) {
            outputSurface.release();
        }
        if (inputSurface != null) {
            inputSurface.release();
        }
        if (encoder != null) {
            encoder.stop();
            encoder.release();
        }
        if (decoder != null) {
            decoder.stop();
            decoder.release();
        }
    }
    return outputData;
}
 

/**
 * Prepares the video encoder, muxer, and an EGL input surface.
 */
protected void prepareEncoder(String mimeType, int width, int height, int bitRate,
        int framesPerSecond, File outputFile) throws IOException {
    mBufferInfo = new MediaCodec.BufferInfo();

    MediaFormat format = MediaFormat.createVideoFormat(mimeType, width, height);

    // Set some properties.  Failing to specify some of these can cause the MediaCodec
    // configure() call to throw an unhelpful exception.
    format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
            MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
    format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
    format.setInteger(MediaFormat.KEY_FRAME_RATE, framesPerSecond);
    format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
    if (VERBOSE) Log.d(TAG, "format: " + format);

    // Create a MediaCodec encoder, and configure it with our format.  Get a Surface
    // we can use for input and wrap it with a class that handles the EGL work.
    mEncoder = MediaCodec.createEncoderByType(mimeType);
    mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    Log.v(TAG, "encoder is " + mEncoder.getCodecInfo().getName());
    Surface surface;
    try {
        surface = mEncoder.createInputSurface();
    } catch (IllegalStateException ise) {
        // This is generally the first time we ever try to encode something through a
        // Surface, so specialize the message a bit if we can guess at why it's failing.
        // TODO: failure message should come out of strings.xml for i18n
        if (isSoftwareCodec(mEncoder)) {
            throw new RuntimeException("Can't use input surface with software codec: " +
                    mEncoder.getCodecInfo().getName(),
                    ise);
        } else {
            throw new RuntimeException("Failed to create input surface", ise);
        }
    }
    mEglCore = new EglCore(null, EglCore.FLAG_RECORDABLE);
    mInputSurface = new WindowSurface(mEglCore, surface, true);
    mInputSurface.makeCurrent();
    mEncoder.start();

    // Create a MediaMuxer.  We can't add the video track and start() the muxer here,
    // because our MediaFormat doesn't have the Magic Goodies.  These can only be
    // obtained from the encoder after it has started processing data.
    //
    // We're not actually interested in multiplexing audio.  We just want to convert
    // the raw H.264 elementary stream we get from MediaCodec into a .mp4 file.
    if (VERBOSE) Log.d(TAG, "output will go to " + outputFile);
    mMuxer = new MediaMuxer(outputFile.toString(),
            MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);

    mTrackIndex = -1;
    mMuxerStarted = false;
}
 

private void doEncode() throws IOException {
        MediaFormat inputFormat = mExtractor.getTrackFormat(mVideoIndex);
        //初始化编码器
        int frameRate = inputFormat.containsKey(MediaFormat.KEY_FRAME_RATE) ? inputFormat.getInteger(inputFormat.KEY_FRAME_RATE) : DEFAULT_FRAME_RATE;
        MediaFormat outputFormat = MediaFormat.createVideoFormat(VideoProcessor.OUTPUT_MIME_TYPE, mResultWidth, mResultHeight);
        outputFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
        outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, mBitrate);
        outputFormat.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
        outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, mIFrameInterval);

        mEncoder = MediaCodec.createEncoderByType(VideoProcessor.OUTPUT_MIME_TYPE);
        mEncoder.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        mSurface = mEncoder.createInputSurface();

//        mInputSurface = new InputSurface(encodeSurface);
//        mInputSurface.makeCurrent();
        mEncoder.start();
        mEglContextLatch.countDown();

        boolean signalEncodeEnd = false;
        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
        int encodeTryAgainCount = 0;
        //开始编码
        //输出
        while (true) {
            if (mDecodeDone.get() && !signalEncodeEnd) {
                signalEncodeEnd = true;
                mEncoder.signalEndOfInputStream();
            }
            int outputBufferIndex = mEncoder.dequeueOutputBuffer(info, TIMEOUT_USEC);
            CL.i("encode outputBufferIndex = " + outputBufferIndex);
            if (signalEncodeEnd && outputBufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
                encodeTryAgainCount++;
                if (encodeTryAgainCount > 10) {
                    //三星S8上出现signalEndOfInputStream之后一直tryAgain的问题
                    CL.e("INFO_TRY_AGAIN_LATER 10 times,force End!");
                    break;
                }
            } else {
                encodeTryAgainCount = 0;
            }
            if (outputBufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
                continue;
            } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                MediaFormat newFormat = mEncoder.getOutputFormat();
                CL.i("encode newFormat = " + newFormat);
            } else if (outputBufferIndex < 0) {
                //ignore
                CL.e("unexpected result from decoder.dequeueOutputBuffer: " + outputBufferIndex);
            } else {
                //编码数据可用
                ByteBuffer outputBuffer = mEncoder.getOutputBuffer(outputBufferIndex);
                info.presentationTimeUs += mBaseMuxerFrameTimeUs;
                if (!mIsFirst && info.flags == MediaCodec.BUFFER_FLAG_CODEC_CONFIG) {
                    //非第一个片段跳过写入Config
                    continue;
                }
                if (!mIsLast && info.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM) {
                    //非最后一个片段不写入End
                    CL.i("encoderDone");
                    mEncoder.releaseOutputBuffer(outputBufferIndex, false);
                    break;
                }
                if (info.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM && info.presentationTimeUs < 0) {
                    info.presentationTimeUs = 0;
                }
                CL.i("writeSampleData,size:" + info.size + " time:" + info.presentationTimeUs / 1000 + " flag:" + info.flags);
                mMuxer.writeSampleData(mMuxerVideoTrackIndex, outputBuffer, info);
                if (mLastFrametimeUs < info.presentationTimeUs) {
                    mLastFrametimeUs = info.presentationTimeUs;
                }
                mEncoder.releaseOutputBuffer(outputBufferIndex, false);
                if (info.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM) {
                    CL.i("encoderDone");
                    break;
                }
            }
        }
    }