package com.github.piasy.videocre; import android.media.MediaCodec; import android.media.MediaFormat; import android.os.Handler; import android.os.HandlerThread; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; import org.webrtc.EglBase; import org.webrtc.MediaCodecVideoEncoder; import org.webrtc.VideoRenderer; /** * Created by Piasy{github.com/Piasy} on 21/07/2017. */ public class HwAvcEncoder implements VideoRenderer.Callbacks, MediaCodecCallback { private final HandlerThread mMediaCodecThread; private final Handler mMediaCodecHandler; private final MediaCodecVideoEncoder mVideoEncoder; private final VideoConfig mVideoConfig; private final List<MediaCodecCallback> mMediaCodecCallbacks; public HwAvcEncoder(final VideoConfig videoConfig, final MediaCodecCallback... callbacks) { mVideoConfig = videoConfig; mMediaCodecThread = new HandlerThread("HwAvcEncoderThread"); mMediaCodecThread.start(); mMediaCodecHandler = new Handler(mMediaCodecThread.getLooper()); mVideoEncoder = new MediaCodecVideoEncoder(); mMediaCodecCallbacks = Arrays.asList(callbacks); } public void start(final EglBase eglBase) { mMediaCodecHandler.post(new Runnable() { @Override public void run() { mVideoEncoder.initEncode(MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_H264, MediaCodecVideoEncoder.H264Profile.CONSTRAINED_BASELINE.getValue(), mVideoConfig.outputWidth(), mVideoConfig.outputHeight(), mVideoConfig.outputBitrate(), mVideoConfig.fps(), eglBase.getEglBaseContext(), HwAvcEncoder.this); } }); } @Override public void renderFrame(final VideoRenderer.I420Frame frame) { mMediaCodecHandler.post(new Runnable() { @Override public void run() { mVideoEncoder.encodeTexture(false, frame.textureId, frame.samplingMatrix, TimeUnit.NANOSECONDS.toMicros(frame.timestamp)); } }); } public void destroy() { mMediaCodecHandler.post(new Runnable() { @Override public void run() { mVideoEncoder.release(); mMediaCodecThread.quit(); } }); } @Override public void onEncodedFrame(final MediaCodecVideoEncoder.OutputBufferInfo frame, final MediaCodec.BufferInfo bufferInfo) { for (int i = 0, n = mMediaCodecCallbacks.size(); i < n; i++) { mMediaCodecCallbacks.get(i).onEncodedFrame(frame, bufferInfo); } } @Override public void onOutputFormatChanged(final MediaCodec codec, final MediaFormat format) { for (int i = 0, n = mMediaCodecCallbacks.size(); i < n; i++) { mMediaCodecCallbacks.get(i).onOutputFormatChanged(codec, format); } } }