Audio Encoder для потоковой передачи аудио с iphone на IP-камеру - PullRequest
0 голосов
/ 19 февраля 2020

Я хотел передать аудио с iPhone на IP-камеру, это было сделано в android logi c для android ниже:

import java.nio.ByteBuffer;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.media.MediaRecorder;
import android.os.Build;

class AudioEncoder
{
    private static final String TAG = "AudioEncoder";
    private static final String MIME = "audio/mp4a-latm";
    public static final boolean IS_DOUBLE_AUDIO_CHANNEL = false;

    private static final int DEFAULT_AUDIO_RATE = 128000;
    public static final int DEFAULT_AUDIO_SAMPLE_RATE = 48000;
    private int DEFAULT_AUDIO_CHANEL_COUNT = 1;
    private int DEFAULT_AUDIO_CHANEL_CONFIG = AudioFormat.CHANNEL_IN_STEREO;
    private int DEFAULT_AUDIO_FORMART = AudioFormat.ENCODING_PCM_16BIT;

    private MediaCodec mAudioCodec;
    private int mAudioBufferSize;
    private AudioRecord mAudioRecord;
    private AudioEncodeRunnable mAudioEncodeRunnable;
    private int mAudioTrack = -1;
    private MediaMuxer mMuxer;
    private EncodeCallback mEncodeCallback;
    private Thread mAudioThread;


    public interface EncodeCallback {
        public void onAudioFormartChanged(int track);
        public void onAudioDataChanged(int track, ByteBuffer buffer, MediaCodec.BufferInfo info);
    }

    private class AudioEncodeRunnable implements Runnable{

        private boolean mCanRun;

        public AudioEncodeRunnable(){
            mCanRun = true;
        }

        public void stop(){
            mCanRun = false;
            mEncodeCallback = null;
        }

        @Override
        public void run() {
            // TODO Auto-generated method stub

            mAudioBufferSize = AudioRecord.getMinBufferSize(DEFAULT_AUDIO_SAMPLE_RATE,
                    DEFAULT_AUDIO_CHANEL_CONFIG, DEFAULT_AUDIO_FORMART) * DEFAULT_AUDIO_CHANEL_COUNT;
            mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, DEFAULT_AUDIO_SAMPLE_RATE,
                    DEFAULT_AUDIO_CHANEL_CONFIG, DEFAULT_AUDIO_FORMART, mAudioBufferSize);

            MediaFormat format = MediaFormat.createAudioFormat(MIME, DEFAULT_AUDIO_SAMPLE_RATE, DEFAULT_AUDIO_CHANEL_COUNT);
            format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
            format.setInteger(MediaFormat.KEY_BIT_RATE, DEFAULT_AUDIO_RATE);
            try {
                mAudioCodec = MediaCodec.createEncoderByType(MIME);
                mAudioCodec.configure(format,null,null,MediaCodec.CONFIGURE_FLAG_ENCODE);
            } catch (Exception e) {
                // TODO: handle exception
            }

            mAudioCodec.start();
            mAudioRecord.startRecording();

            while(mCanRun && !Thread.interrupted()){
                if(null != mAudioRecord && null != mAudioCodec){
                    try {
                        readOutputData();
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }

            if(null != mAudioCodec){
                mAudioCodec.stop();
                mAudioCodec.release();
            }
        }
    }

    private boolean readOutputData() throws Exception{
        int index = mAudioCodec.dequeueInputBuffer(-1);
        if(index >= 0){
            final ByteBuffer buffer = getInputBuffer(index);
            buffer.clear();
            int length = mAudioRecord.read(buffer, IS_DOUBLE_AUDIO_CHANNEL ? 4096 : 2048 );
            //Log.d(TAG, "readOutputData LENGTH="+length);
            if(length > 0){
                mAudioCodec.queueInputBuffer(index, 0, length, System.nanoTime() / 1000, 0);
            }
        }

        MediaCodec.BufferInfo mInfo = new MediaCodec.BufferInfo();
        int outIndex;
        do{
            outIndex = mAudioCodec.dequeueOutputBuffer(mInfo,0);
            if(outIndex >= 0){
                ByteBuffer buffer = getOutputBuffer(outIndex);
                buffer.position(mInfo.offset);
                if(mInfo.size > 0){
                    if(null != mEncodeCallback){
                        mEncodeCallback.onAudioDataChanged(mAudioTrack, buffer, mInfo);
                    }
                }
                mAudioCodec.releaseOutputBuffer(outIndex,false);
                if((mInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0){
                    return true;
                }
            }else if(outIndex == MediaCodec.INFO_TRY_AGAIN_LATER){

            }else if(outIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED){
                if(null != mMuxer){
                    mAudioTrack = mMuxer.addTrack(mAudioCodec.getOutputFormat());
                    if(null != mEncodeCallback){
                        mEncodeCallback.onAudioFormartChanged(mAudioTrack);
                    }
                }
            }
        }while (outIndex >= 0);

        return false;
    }

    private ByteBuffer getInputBuffer(int index){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            return mAudioCodec.getInputBuffer(index);
        }else{
            return mAudioCodec.getInputBuffers()[index];
        }
    }

    private ByteBuffer getOutputBuffer(int index){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            return mAudioCodec.getOutputBuffer(index);
        }else{
            return mAudioCodec.getOutputBuffers()[index];
        }
    }

    synchronized public void start(){
        /*if(null != mAudioEncodeRunnable){
            mAudioEncodeRunnable.stop();
            mAudioEncodeRunnable = null;
        }*/

        if(null == mAudioThread){
            mAudioEncodeRunnable = new AudioEncodeRunnable();
            mAudioThread = new Thread(mAudioEncodeRunnable);
            mAudioThread.start();
        }
    }

    synchronized public void stop(){
        if(null != mAudioEncodeRunnable){
            mAudioEncodeRunnable.stop();
            if(null != mAudioThread){
                mAudioThread.interrupt();
                try {
                    mAudioThread.join();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                mAudioThread = null;
            }
        }

        if(mAudioRecord != null){
            mAudioRecord.stop();
            mAudioRecord.release();
        }
    }

    public AudioEncoder(MediaMuxer muxer, EncodeCallback callback){
        mMuxer = muxer;
        mEncodeCallback = callback;
        if(IS_DOUBLE_AUDIO_CHANNEL){
            DEFAULT_AUDIO_CHANEL_COUNT = 2;
            DEFAULT_AUDIO_CHANEL_CONFIG = AudioFormat.CHANNEL_IN_STEREO;
        }else{
            DEFAULT_AUDIO_CHANEL_COUNT = 1;
            DEFAULT_AUDIO_CHANEL_CONFIG = AudioFormat.CHANNEL_IN_MONO;
        }
    }
}

Выше я вставил android код для справки.

Требуется аналогичный код для iOS. Если требуется дополнительная информация, дайте мне знать.

Необходимый аудио кодер для приложения ios.

Заранее спасибо

...