package com.sc.lesa.mediashar.jlib.media;

import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.view.Surface;

import java.nio.ByteBuffer;

/**
 * Created by Lesa on 2018/12/03.
 */

public class Encoder extends Thread {

    private MediaCodec codec;
    private EncoderListener encoderListener;

    private int videoW;
    private int videoH;
    private int videoBitrate;
    private int videoFrameRate;
    private Surface mSurface;

    private final int TIMEOUT_USEC = 12000;
    private byte[] configbyte;

    private boolean exit = false;

    private static final String TAG = "Encoder";
    private static final String MIME = "Video/AVC";

    public Encoder(int videoW, int videoH, int videoBitrate, int videoFrameRate, EncoderListener encoderListener) {
        super(TAG);
        this.videoW = videoW;
        this.videoH = videoH;
        this.videoBitrate = videoBitrate;
        this.videoFrameRate = videoFrameRate;
        this.encoderListener = encoderListener;

        initMediaCodec();
    }

    public Surface getmSurface() {
        return mSurface;
    }

    private void initMediaCodec() {
        try {
            MediaFormat format = MediaFormat.createVideoFormat(MIME, videoW, videoH);
            format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
                    MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);//颜色格式
            format.setInteger(MediaFormat.KEY_BIT_RATE, videoBitrate);//码流
            format.setInteger(MediaFormat.KEY_FRAME_RATE, videoFrameRate);//帧数
            format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, -1); // 关键帧 5秒
            
            codec = MediaCodec.createEncoderByType(MIME);
            codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
            mSurface = codec.createInputSurface();
            codec.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取h264数据
     * **/
    @Override
    public void run(){
        try
        {
            while(!exit){
                if(codec == null) return;

                MediaCodec.BufferInfo mBufferInfo = new MediaCodec.BufferInfo();
                int outputBufferIndex  = codec.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);
                while (outputBufferIndex >= 0){
                    ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferIndex);
                    byte[] outData = new byte[mBufferInfo.size];
                    outputBuffer.get(outData);
                    if(mBufferInfo.flags == 2){
                        configbyte = new byte[mBufferInfo.size];
                        configbyte = outData;
                    }

                    else if(mBufferInfo.flags == 1){
                        byte[] keyframe = new byte[mBufferInfo.size + configbyte.length];
                        System.arraycopy(configbyte, 0, keyframe, 0, configbyte.length);
                        System.arraycopy(outData, 0, keyframe, configbyte.length, outData.length);
                        encoderListener.onH264(keyframe,1,mBufferInfo.presentationTimeUs);

                    }else{
                        //其他帧末
                        encoderListener.onH264(outData,2,mBufferInfo.presentationTimeUs);

                    }
                    codec.releaseOutputBuffer(outputBufferIndex, false);
                    outputBufferIndex = codec.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);
                }
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
        close();

    }

    private void close(){
        codec.stop();
        codec.release();
        codec = null;
        encoderListener.onCloseH264();
        encoderListener=null;
    }

    public void releaseMediaCodec() {
        exit = true;
    }

    public interface EncoderListener {
        void onH264(byte[] buffer, int type,long ts);
        void onCloseH264();
    }
}