MediaStream.java 27.5 KB
Newer Older
jinlong0603's avatar
jinlong0603 已提交
1
/*
2
	Copyright (c) 2012-2017 EasyDarwin.ORG.  All rights reserved.
jinlong0603's avatar
jinlong0603 已提交
3 4 5 6 7 8 9 10
	Github: https://github.com/EasyDarwin
	WEChat: EasyDarwin
	Website: http://www.easydarwin.org
*/

package org.easydarwin.easyipcamera.camera;

import android.content.Context;
jinlong0603's avatar
jinlong0603 已提交
11
import android.content.res.Configuration;
jinlong0603's avatar
jinlong0603 已提交
12 13 14 15
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.media.MediaCodec;
import android.media.MediaFormat;
16 17 18 19
import android.os.Build;
import android.os.Bundle;
import android.os.Process;
import android.preference.PreferenceManager;
20
import android.util.Base64;
jinlong0603's avatar
jinlong0603 已提交
21 22 23 24 25 26
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import org.easydarwin.easyipcamera.hw.EncoderDebugger;
import org.easydarwin.easyipcamera.hw.NV21Convertor;
27 28
import org.easydarwin.easyipcamera.sw.JNIUtil;
import org.easydarwin.easyipcamera.sw.X264Encoder;
jinlong0603's avatar
jinlong0603 已提交
29
import org.easydarwin.easyipcamera.util.Util;
jinlong0603's avatar
jinlong0603 已提交
30
import org.easydarwin.easyipcamera.view.StatusInfoView;
jinlong0603's avatar
jinlong0603 已提交
31 32 33 34

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
35
import java.lang.ref.WeakReference;
jinlong0603's avatar
jinlong0603 已提交
36 37 38 39
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Iterator;
import java.util.List;
40
import java.util.concurrent.ArrayBlockingQueue;
jinlong0603's avatar
jinlong0603 已提交
41 42 43 44 45

public class MediaStream implements EasyIPCamera.IPCameraCallBack {
    EasyIPCamera mEasyIPCamera;
    static final String TAG = "MediaStream";
    int width = 640, height = 480;
jinlong0603's avatar
jinlong0603 已提交
46
    int framerate = 25;
jinlong0603's avatar
jinlong0603 已提交
47 48 49
    int bitrate;
    int mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
    MediaCodec mMediaCodec;
jinlong0603's avatar
jinlong0603 已提交
50
    SurfaceView mSurfaceView;
jinlong0603's avatar
jinlong0603 已提交
51 52 53
    SurfaceHolder mSurfaceHolder;
    Camera mCamera;
    NV21Convertor mConvertor;
54
    private int mChannelState = 0;
55 56 57 58
//    AudioStream audioStream;
    private boolean mSWCodec;
    private X264Encoder x264;
    private Consumer mConsumer;
jinlong0603's avatar
jinlong0603 已提交
59 60 61 62 63 64
    private boolean isCameraBack = true;
    private int mDgree;
    private Context mApplicationContext;
    Thread pushThread;
    boolean codecAvailable = false;
    private int mChannelId = 1;
65 66 67 68 69
    boolean mChannelOpen = false;//是否要推送数据
    byte[] mVps = new byte[255];
    byte[] mSps = new byte[255];
    byte[] mPps = new byte[128];
    byte[] mMei = new byte[128];
jinlong0603's avatar
jinlong0603 已提交
70
    private boolean mPortraitScreen = true;
jinlong0603's avatar
jinlong0603 已提交
71

jinlong0603's avatar
jinlong0603 已提交
72
    public MediaStream(Context context, SurfaceView mSurfaceView) {
jinlong0603's avatar
jinlong0603 已提交
73
        mApplicationContext = context;
jinlong0603's avatar
jinlong0603 已提交
74 75
        this.mSurfaceView = mSurfaceView;
        mSurfaceHolder = mSurfaceView.getHolder();
jinlong0603's avatar
jinlong0603 已提交
76
        mEasyIPCamera = new EasyIPCamera();
77
//        audioStream = new AudioStream(mEasyIPCamera);
jinlong0603's avatar
jinlong0603 已提交
78 79 80 81 82 83
    }

    public void setDgree(int dgree) {
        mDgree = dgree;
    }

jinlong0603's avatar
jinlong0603 已提交
84 85 86 87 88 89 90 91 92 93
    /**
     * 是否竖屏
     */
    public void changeScreenOrientation(){
        mPortraitScreen = !mPortraitScreen;
    }
    public boolean getScreenOrientation(){
        return mPortraitScreen;
    }

jinlong0603's avatar
jinlong0603 已提交
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
    /**
     * 更新分辨率
     */
    public void updateResolution(int width, int height) {
        this.width = width;
        this.height = height;
    }

    /**
     * 重新开始
     */
    public void reStartStream() {
        if (mCamera == null) return;
        mCamera.stopPreview();//停掉原来摄像头的预览
        mCamera.release();//释放资源
109
        stopPush();
jinlong0603's avatar
jinlong0603 已提交
110 111
        mEasyIPCamera.unrigisterCallback(this);
        mChannelId = mEasyIPCamera.registerCallback(this);
112 113
//        audioStream.setChannelId(mChannelId);
        initEncoder();
jinlong0603's avatar
jinlong0603 已提交
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
        createCamera();
        startPreview();
    }

    public static int[] determineMaximumSupportedFramerate(Camera.Parameters parameters) {
        int[] maxFps = new int[]{0, 0};
        List<int[]> supportedFpsRanges = parameters.getSupportedPreviewFpsRange();
        for (Iterator<int[]> it = supportedFpsRanges.iterator(); it.hasNext(); ) {
            int[] interval = it.next();
            if (interval[1] > maxFps[1] || (interval[0] > maxFps[0] && interval[1] == maxFps[1])) {
                maxFps = interval;
            }
        }
        return maxFps;
    }

130 131 132
    public static final boolean useSWCodec() {
        return Build.VERSION.SDK_INT >= 23;
    }
jinlong0603's avatar
jinlong0603 已提交
133 134 135 136 137 138 139 140 141 142 143 144 145

    public boolean createCamera() {
        try {
            mCamera = Camera.open(mCameraId);
            Camera.Parameters parameters = mCamera.getParameters();
            int[] max = determineMaximumSupportedFramerate(parameters);
            Camera.CameraInfo camInfo = new Camera.CameraInfo();
            Camera.getCameraInfo(mCameraId, camInfo);
            int cameraRotationOffset = camInfo.orientation;
            if (mCameraId == Camera.CameraInfo.CAMERA_FACING_FRONT)
                cameraRotationOffset += 180;
            int rotate = (360 + cameraRotationOffset - mDgree) % 360;
            parameters.setRotation(rotate);
146 147
            mSWCodec = PreferenceManager.getDefaultSharedPreferences(mApplicationContext).getBoolean("key-sw-codec", useSWCodec());
            parameters.setPreviewFormat(mSWCodec ? ImageFormat.YV12 : ImageFormat.NV21);
jinlong0603's avatar
jinlong0603 已提交
148 149
            List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
            parameters.setPreviewSize(width, height);
jinlong0603's avatar
jinlong0603 已提交
150
            parameters.setPreviewFrameRate(20);
jinlong0603's avatar
jinlong0603 已提交
151 152 153
            mCamera.setParameters(parameters);
            int displayRotation;
            displayRotation = (cameraRotationOffset - mDgree + 360) % 360;
jinlong0603's avatar
jinlong0603 已提交
154

jinlong0603's avatar
jinlong0603 已提交
155
            mCamera.setDisplayOrientation(displayRotation);
jinlong0603's avatar
jinlong0603 已提交
156 157 158 159 160 161 162
//            if(mApplicationContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
//                Log.i("info", "landscape");
//            } else if (mApplicationContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
//                Log.i("info", "portrait");
//                mCamera.setDisplayOrientation(displayRotation);
//            }

jinlong0603's avatar
jinlong0603 已提交
163 164 165 166 167 168 169 170 171
            mCamera.setPreviewDisplay(mSurfaceHolder);
            return true;
        } catch (Exception e) {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            e.printStackTrace(pw);
            String stack = sw.toString();
            destroyCamera();
            e.printStackTrace();
172
            Util.showDbgMsg(StatusInfoView.DbgLevel.DBG_LEVEL_WARN, "Create camera failed!");
jinlong0603's avatar
jinlong0603 已提交
173 174 175 176
            return false;
        }
    }

177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
    Object lock = new byte[0];

    private class TimedBuffer {
        byte[] buffer;
        long time;

        public TimedBuffer(byte[] data) {
            buffer = data;
            time = System.currentTimeMillis();
        }
    }

    private ArrayBlockingQueue<TimedBuffer> yuvs = new ArrayBlockingQueue<TimedBuffer>(5);
    private ArrayBlockingQueue<byte[]> yuv_caches = new ArrayBlockingQueue<byte[]>(10);

    class Consumer extends Thread {
        ByteBuffer[] inputBuffers;
        ByteBuffer[] outputBuffers;
        byte[] mPpsSps = new byte[0];
        int keyFrmHelperCount = 0;
        private long timeStamp = System.currentTimeMillis();

        public Consumer() {
            super("Consumer");
        }

        @Override
        public void run() {
            Process.setThreadPriority(Process.THREAD_PRIORITY_AUDIO);
            Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
            byte[] h264 = new byte[(int) (previewSize.width * previewSize.height * 3/2)];
            try {
                if(mSWCodec){
                    initSWEncoder();
                } else {
                    startMediaCodec();
                }

                while (mConsumer != null && codecAvailable) {
                    TimedBuffer tb;
//                    Log.i(TAG, String.format("cache yuv:%d", yuvs.size()));
                    tb = yuvs.take();
                    if(!codecAvailable){
                        break;
                    }

                    byte[] data = tb.buffer;
                    long stamp = tb.time;
                    int[] outLen = new int[1];
jinlong0603's avatar
jinlong0603 已提交
226
                    if (mDgree == 0 && mPortraitScreen) {
227 228
                        Camera.CameraInfo camInfo = new Camera.CameraInfo();
                        Camera.getCameraInfo(mCameraId, camInfo);
jinlong0603's avatar
jinlong0603 已提交
229

230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
                        int cameraRotationOffset = camInfo.orientation;
                        if (cameraRotationOffset == 90) {
                            if (mSWCodec) {
                                Util.yuvRotate(data, 0, previewSize.width, previewSize.height, 90);
                            } else {
                                Util.yuvRotate(data, 1, previewSize.width, previewSize.height, 90);
                            }
                        } else if (cameraRotationOffset == 270) {
                            if (mSWCodec) {
                                Util.yuvRotate(data, 0, previewSize.width, previewSize.height, 270);
                            } else {
                                Util.yuvRotate(data, 1, previewSize.width, previewSize.height, 270);
                            }
                        }
                    }
                    int r = 0;
                    byte[] newBuf = null;
                    synchronized (lock) {
                        if (mSWCodec && x264 != null) {
                            byte[] keyFrm = new byte[1];
                            if (false) {
                                if (keyFrmHelperCount++ > 50) {
                                    keyFrmHelperCount = 0;
                                    keyFrm[0] = 1;
                                } else {
                                    keyFrm[0] = 0;
                                }
                            }
                            long begin = System.currentTimeMillis();
                            r = x264.encode(data, 0, h264, 0, outLen, keyFrm);
                            if (r > 0) {
                                Log.i(TAG, String.format("encode spend:%d ms. keyFrm:%d", System.currentTimeMillis() - begin, keyFrm[0]));
//                                newBuf = new byte[outLen[0]];
//                                System.arraycopy(h264, 0, newBuf, 0, newBuf.length);
                            }
                        }
                    }
                    if (mSWCodec) {
                        if (r > 0) {
                            if(mChannelState == EasyIPCamera.ChannelState.EASY_IPCAMERA_STATE_REQUEST_PLAY_STREAM) {
                                mEasyIPCamera.pushFrame(mChannelId, EasyIPCamera.FrameFlag.EASY_SDK_VIDEO_FRAME_FLAG, stamp, h264, 0, outLen[0]);
                            }
                        }
                    } else {
                        inputBuffers = mMediaCodec.getInputBuffers();
                        outputBuffers = mMediaCodec.getOutputBuffers();
                        int bufferIndex = mMediaCodec.dequeueInputBuffer(5000);
                        if (bufferIndex >= 0) {
                            inputBuffers[bufferIndex].clear();
                            mConvertor.convert(data, inputBuffers[bufferIndex]);
                            mMediaCodec.queueInputBuffer(bufferIndex, 0, inputBuffers[bufferIndex].position(), stamp* 1000, 0);

                            MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
                            int outputBufferIndex = 0;
                            do {
                                 outputBufferIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo, 0);
                                if (outputBufferIndex<0){
                                    break;
                                }
                                ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
                                //记录pps和sps
                                int type = outputBuffer.get(4) & 0x1F;

                                Log.d(TAG, String.format("type is %d", type));
                                if (type == 7 || type == 8) {
                                    byte[] outData = new byte[bufferInfo.size];
                                    outputBuffer.get(outData, 0, bufferInfo.size);
                                    mPpsSps = outData;
                                } else if (type == 5) {
jinlong0603's avatar
jinlong0603 已提交
299 300 301
                                    //在关键帧前面加上pps和sps数据
                                    System.arraycopy(mPpsSps, 0, h264, 0, mPpsSps.length);
                                    outputBuffer.get(h264, mPpsSps.length, bufferInfo.size);
302
                                    if(mChannelState == EasyIPCamera.ChannelState.EASY_IPCAMERA_STATE_REQUEST_PLAY_STREAM) {
jinlong0603's avatar
jinlong0603 已提交
303
                                        mEasyIPCamera.pushFrame(mChannelId, EasyIPCamera.FrameFlag.EASY_SDK_VIDEO_FRAME_FLAG, bufferInfo.presentationTimeUs / 1000, h264, 0, mPpsSps.length + bufferInfo.size);
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
                                    }
                                } else {
                                    outputBuffer.get(h264, 0, bufferInfo.size);
                                    if (System.currentTimeMillis() - timeStamp >= 3000) {
                                        timeStamp = System.currentTimeMillis();
                                        if (Build.VERSION.SDK_INT >= 23) {
                                            Bundle params = new Bundle();
                                            params.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
                                            mMediaCodec.setParameters(params);
                                        }
                                    }

                                    if(mChannelState == EasyIPCamera.ChannelState.EASY_IPCAMERA_STATE_REQUEST_PLAY_STREAM) {
                                        mEasyIPCamera.pushFrame(mChannelId, EasyIPCamera.FrameFlag.EASY_SDK_VIDEO_FRAME_FLAG, bufferInfo.presentationTimeUs / 1000, h264, 0, bufferInfo.size);
                                    }
                                }
                                mMediaCodec.releaseOutputBuffer(outputBufferIndex, false);
                            }
                            while(outputBufferIndex >= 0);
                        }
                    }
                    yuv_caches.offer(data);

                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                if (mMediaCodec != null) {
                    mMediaCodec.stop();
                    mMediaCodec.release();
                    mMediaCodec = null;
                }

                synchronized (lock) {
                    if (x264 != null) {
                        x264.close();
                        x264 = null;
                        codecAvailable = false;
                    }
                }
            }
        }
    }

jinlong0603's avatar
jinlong0603 已提交
348 349 350 351 352
    /**
     * 开启预览
     */
    public synchronized void startPreview() {
        if (mCamera != null) {
353 354
            yuv_caches.clear();
            yuvs.clear();
jinlong0603's avatar
jinlong0603 已提交
355 356 357 358 359 360
            mCamera.startPreview();
            try {
                mCamera.autoFocus(null);
            } catch (Exception e) {
                //忽略异常
                Log.i(TAG, "auto foucus fail");
361
                Util.showDbgMsg(StatusInfoView.DbgLevel.DBG_LEVEL_WARN, "Camera auto foucus failed!");
jinlong0603's avatar
jinlong0603 已提交
362 363 364 365 366 367 368 369 370 371 372 373 374 375
            }

            int previewFormat = mCamera.getParameters().getPreviewFormat();
            Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
            int size = previewSize.width * previewSize.height
                    * ImageFormat.getBitsPerPixel(previewFormat)
                    / 8;
            mCamera.addCallbackBuffer(new byte[size]);
            mCamera.setPreviewCallbackWithBuffer(previewCallback);
        }
    }

    Camera.PreviewCallback previewCallback = new Camera.PreviewCallback() {
        @Override
376
        public synchronized void onPreviewFrame(byte[] data, Camera camera) {
377 378 379 380 381 382
            if(data == null || camera == null){
                return;
            }

            if (!mChannelOpen || !codecAvailable || mConsumer == null) {
                camera.addCallbackBuffer(data);
383 384 385 386 387
                return;
            }

            if((EasyIPCamera.ChannelState.EASY_IPCAMERA_STATE_REQUEST_MEDIA_INFO != mChannelState) &&
                    (EasyIPCamera.ChannelState.EASY_IPCAMERA_STATE_REQUEST_PLAY_STREAM != mChannelState)){
388
                camera.addCallbackBuffer(data);
jinlong0603's avatar
jinlong0603 已提交
389 390
                return;
            }
391

392
            Camera.Size previewSize = camera.getParameters().getPreviewSize();
jinlong0603's avatar
jinlong0603 已提交
393
            if (data.length != previewSize.width * previewSize.height * 3 / 2) {
394
                camera.addCallbackBuffer(data);
jinlong0603's avatar
jinlong0603 已提交
395 396 397
                return;
            }

398 399 400
            byte[] buffer = yuv_caches.poll();
            if (buffer == null || buffer.length != data.length) {
                buffer = new byte[data.length];
jinlong0603's avatar
jinlong0603 已提交
401
            }
402 403 404 405
            yuvs.offer(new TimedBuffer(data));
            camera.addCallbackBuffer(buffer);
        }
    };
jinlong0603's avatar
jinlong0603 已提交
406

407 408 409 410 411 412 413 414 415 416 417
    private void initSWEncoder(){
        if (mSWCodec) {
            synchronized (lock) {
                x264 = new X264Encoder();
                int bitrate;
                if (width >= 1920) {
                    bitrate = 3200;
                } else if (width >= 1280) {
                    bitrate = 1600;
                } else if (width >= 640) {
                    bitrate = 400;
jinlong0603's avatar
jinlong0603 已提交
418
                } else {
419
                    bitrate = 300;
jinlong0603's avatar
jinlong0603 已提交
420
                }
jinlong0603's avatar
jinlong0603 已提交
421 422

                if (mDgree == 0 && mPortraitScreen) {
423 424 425 426 427
                    x264.create(height, width, 15, bitrate);
                } else {
                    x264.create(width, height, 15, bitrate);
                }
                codecAvailable = true;
jinlong0603's avatar
jinlong0603 已提交
428
            }
429 430
        }
    }
431

432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
    private void x264GetSPSPPS(){
        int[] spsLen = new int[1];
        int[] ppsLen = new int[1];
        byte[] sps = new byte[1024];
        byte[] pps = new byte[1024];

        initSWEncoder();
        int iRet = x264.getSpsPps(sps, spsLen, pps, ppsLen);
        if(iRet >= 0){
            if(spsLen[0] > 0 && spsLen[0] <= 255) {
                mSps = new byte[spsLen[0]];
                System.arraycopy(sps, 0, mSps, 0, spsLen[0]);
            }
            if(ppsLen[0] > 0 && ppsLen[0] <= 255) {
                mPps = new byte[ppsLen[0]];
                System.arraycopy(pps, 0, mPps, 0, ppsLen[0]);
448
            }
449 450
        } else {
            Log.e(TAG, "sw get sps pps failed!");
jinlong0603's avatar
jinlong0603 已提交
451 452
        }

453 454
        x264.close();
    }
jinlong0603's avatar
jinlong0603 已提交
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527

    /**
     * 停止预览
     */
    public synchronized void stopPreview() {
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.setPreviewCallbackWithBuffer(null);
        }
    }

    public Camera getCamera() {
        return mCamera;
    }

    /**
     * 切换前后摄像头
     */
    public void switchCamera() {
        int cameraCount = 0;
        if (isCameraBack) {
            isCameraBack = false;
        } else {
            isCameraBack = true;
        }
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        cameraCount = Camera.getNumberOfCameras();//得到摄像头的个数
        for (int i = 0; i < cameraCount; i++) {
            Camera.getCameraInfo(i, cameraInfo);//得到每一个摄像头的信息
            if (mCameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                //现在是后置,变更为前置
                if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表摄像头的方位,CAMERA_FACING_FRONT前置      CAMERA_FACING_BACK后置
                    mCamera.stopPreview();//停掉原来摄像头的预览
                    mCamera.release();//释放资源
                    mCamera = null;//取消原来摄像头
                    mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
                    createCamera();
                    startPreview();
                    break;
                }
            } else {
                //现在是前置, 变更为后置
                if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位,CAMERA_FACING_FRONT前置      CAMERA_FACING_BACK后置
                    mCamera.stopPreview();//停掉原来摄像头的预览
                    mCamera.release();//释放资源
                    mCamera = null;//取消原来摄像头
                    mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
                    createCamera();
                    startPreview();
                    break;
                }
            }
        }
    }

    /**
     * 销毁Camera
     */
    public synchronized void destroyCamera() {
        if (mCamera != null) {
            mCamera.stopPreview();
            try {
                mCamera.release();
            } catch (Exception e) {

            }
            mCamera = null;
        }
    }

    /**
     * 初始化编码器
     */
528
    private void initMediaCodec() {
jinlong0603's avatar
jinlong0603 已提交
529
        framerate = 25;
530 531 532 533 534 535 536

        //bitrate = 2 * width * height * framerate / 20;
        bitrate = (int) (width * height * 20 * 2 * 0.05f);
        if (width >= 1920 || height >= 1920) bitrate *= 0.3;
        else if (width >= 1280 || height >= 1280) bitrate *= 0.4;
        else if (width >= 720 || height >= 720) bitrate *= 0.6;

jinlong0603's avatar
jinlong0603 已提交
537 538 539 540 541
        EncoderDebugger debugger;
        if(mPortraitScreen)
            debugger = EncoderDebugger.debug(mApplicationContext, width, height);//width, height
        else
            debugger = EncoderDebugger.debug(mApplicationContext, height, width);//width, height
542 543 544 545 546 547
        mConvertor = debugger.getNV21Convertor();

        mSps = Base64.decode(debugger.getB64SPS(), Base64.NO_WRAP);
        mPps = Base64.decode(debugger.getB64PPS(), Base64.NO_WRAP);
    }

jinlong0603's avatar
jinlong0603 已提交
548
    private void startMediaCodec() {
jinlong0603's avatar
jinlong0603 已提交
549 550 551 552 553 554
        EncoderDebugger debugger;
        if(mPortraitScreen)
            debugger = EncoderDebugger.debug(mApplicationContext, width, height);//width, height
        else
            debugger = EncoderDebugger.debug(mApplicationContext, height, width);//width, height

555 556 557
        try {
            mMediaCodec = MediaCodec.createByCodecName(debugger.getEncoderName());
            MediaFormat mediaFormat;
jinlong0603's avatar
jinlong0603 已提交
558
            if (mDgree == 0 && mPortraitScreen) {
559 560 561
                mediaFormat = MediaFormat.createVideoFormat("video/avc", height, width);
            } else {
                mediaFormat = MediaFormat.createVideoFormat("video/avc", width, height);
jinlong0603's avatar
jinlong0603 已提交
562
            }
563 564
            mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
            mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, framerate);
565
            mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,debugger.getEncoderColorFormat());
566 567 568 569 570
            mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
            mMediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
            mMediaCodec.start();
            codecAvailable = true;
        } catch (IOException e) {
571
            Util.showDbgMsg(StatusInfoView.DbgLevel.DBG_LEVEL_INFO, "start MediaCodec failed!");
572
            e.printStackTrace();
jinlong0603's avatar
jinlong0603 已提交
573 574 575
        }
    }

576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
    private void initEncoder(){
        if(mSWCodec){
            x264GetSPSPPS();
        } else {
            initMediaCodec();
        }
    }

    private void startPush(){
        yuv_caches.clear();
        yuvs.clear();

        Thread t = mConsumer;
        if (t != null) {
            mConsumer = null;
            t.interrupt();
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        mConsumer = new Consumer();
        mConsumer.start();
    }

    private void stopPush(){
        codecAvailable = false;

        Thread t = mConsumer;
        if (t != null) {
            t.interrupt();
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            mConsumer = null;
jinlong0603's avatar
jinlong0603 已提交
615 616 617
        }
    }

618
    private void setChannelState(int state){
jinlong0603's avatar
jinlong0603 已提交
619
        if(state <= 2) {
620
            mChannelState = state;
621
//            audioStream.setChannelState(state);
jinlong0603's avatar
jinlong0603 已提交
622 623 624
        }
    }

625 626 627 628 629
    public boolean isOpen() {
        return mChannelOpen;
    }

    public void startChannel(String ip, String port, final String id) {
jinlong0603's avatar
jinlong0603 已提交
630 631
        final int iport = Integer.parseInt(port);

632 633
        mChannelOpen = true;

jinlong0603's avatar
jinlong0603 已提交
634
        mChannelId = mEasyIPCamera.registerCallback(this);
635
//        audioStream.setChannelId(mChannelId);
jinlong0603's avatar
jinlong0603 已提交
636

jinlong0603's avatar
jinlong0603 已提交
637
        //int result = mEasyIPCamera.startup(iport, EasyIPCamera.AuthType.AUTHENTICATION_TYPE_BASIC,"", "admin", "admin", 0, mChannelId, id.getBytes());
638
        int result = mEasyIPCamera.startup(iport, EasyIPCamera.AuthType.AUTHENTICATION_TYPE_BASIC,"", "", "", 0, mChannelId, id.getBytes(), -1, null);
639
        Log.d(TAG, "startup result="+result);
jinlong0603's avatar
jinlong0603 已提交
640
        //mEasyIPCamera.configUser("admin", "admin");
jinlong0603's avatar
jinlong0603 已提交
641

642 643
        initEncoder();
        Util.showDbgMsg(StatusInfoView.DbgLevel.DBG_LEVEL_INFO, "EasyIPCamera started");
jinlong0603's avatar
jinlong0603 已提交
644 645
    }

646
    public void stopChannel() {
647
        setChannelState(0);
648 649
//        audioStream.stop();
        stopPush();
650

jinlong0603's avatar
jinlong0603 已提交
651 652
        mEasyIPCamera.resetChannel(mChannelId);
        int result = mEasyIPCamera.shutdown();
653
        Log.d(TAG, "shutdown result="+result);
jinlong0603's avatar
jinlong0603 已提交
654 655

        mEasyIPCamera.unrigisterCallback(this);
656
        mChannelOpen = false;
jinlong0603's avatar
jinlong0603 已提交
657 658
    }

659
    public void destroyChannel() {
jinlong0603's avatar
jinlong0603 已提交
660 661 662
        if (pushThread != null) {
            pushThread.interrupt();
        }
663 664
        setChannelState(0);

jinlong0603's avatar
jinlong0603 已提交
665
        destroyCamera();
666
        stopPush();
jinlong0603's avatar
jinlong0603 已提交
667 668
        mEasyIPCamera.resetChannel(mChannelId);
        mEasyIPCamera.shutdown();
669
        mChannelOpen = true;
jinlong0603's avatar
jinlong0603 已提交
670 671 672 673
    }

    @Override
    public void onIPCameraCallBack(int channelId, int channelState, byte[] mediaInfo, int userPtr) {
674
//        Log.d(TAG, "kim onIPCameraCallBack, channelId="+channelId+", mChannelId="+mChannelId+", channelState="+channelState);
jinlong0603's avatar
jinlong0603 已提交
675 676 677
        if(channelId != mChannelId)
            return;

678 679
        setChannelState(channelState);

jinlong0603's avatar
jinlong0603 已提交
680 681
        switch(channelState){
            case EasyIPCamera.ChannelState.EASY_IPCAMERA_STATE_ERROR:
jinlong0603's avatar
jinlong0603 已提交
682
                Log.d(TAG, "kim EASY_IPCAMERA_STATE_ERROR");
683
                Util.showDbgMsg(StatusInfoView.DbgLevel.DBG_LEVEL_WARN, "EASY_IPCAMERA_STATE_ERROR");
jinlong0603's avatar
jinlong0603 已提交
684 685
                break;
            case EasyIPCamera.ChannelState.EASY_IPCAMERA_STATE_REQUEST_MEDIA_INFO:
686 687
                /* 媒体信息 */
                Util.showDbgMsg(StatusInfoView.DbgLevel.DBG_LEVEL_INFO, "EASY_IPCAMERA_STATE_REQUEST_MEDIA_INFO");
jinlong0603's avatar
jinlong0603 已提交
688

jinlong0603's avatar
jinlong0603 已提交
689 690 691 692
                ByteBuffer buffer = ByteBuffer.wrap(mediaInfo);
                buffer.order(ByteOrder.LITTLE_ENDIAN);
                buffer.putInt(EasyIPCamera.VideoCodec.EASY_SDK_VIDEO_CODEC_H264);
                buffer.putInt(framerate);
693
                buffer.putInt(0);
jinlong0603's avatar
jinlong0603 已提交
694

695 696 697 698
                buffer.putInt(0);
                buffer.putInt(0);
                buffer.putInt(0);
                buffer.putInt(0);
699
                buffer.putInt(0);
700

jinlong0603's avatar
jinlong0603 已提交
701
                buffer.putInt(0);//vps length
702

jinlong0603's avatar
jinlong0603 已提交
703 704 705 706 707
                buffer.putInt(mSps.length);
                buffer.putInt(mPps.length);
                buffer.putInt(0);
                buffer.put(mVps);
                buffer.put(mSps,0,mSps.length);
708 709
                if(mSps.length < 255) {
                    buffer.put(mVps, 0, 255 - mSps.length);
jinlong0603's avatar
jinlong0603 已提交
710 711
                }
                buffer.put(mPps,0,mPps.length);
712 713
                if(mPps.length < 128) {
                    buffer.put(mVps, 0, 128 - mPps.length);
jinlong0603's avatar
jinlong0603 已提交
714 715 716 717
                }
                buffer.put(mMei);
                break;
            case EasyIPCamera.ChannelState.EASY_IPCAMERA_STATE_REQUEST_PLAY_STREAM:
718 719 720
                Util.showDbgMsg(StatusInfoView.DbgLevel.DBG_LEVEL_INFO, "EASY_IPCAMERA_STATE_REQUEST_PLAY_STREAM");
                startPush();
//                audioStream.startRecord();
jinlong0603's avatar
jinlong0603 已提交
721

jinlong0603's avatar
jinlong0603 已提交
722 723
                break;
            case EasyIPCamera.ChannelState.EASY_IPCAMERA_STATE_REQUEST_STOP_STREAM:
724 725 726
                Util.showDbgMsg(StatusInfoView.DbgLevel.DBG_LEVEL_INFO, "EASY_IPCAMERA_STATE_REQUEST_STOP_STREAM");
                stopPush();
//                audioStream.stop();
jinlong0603's avatar
jinlong0603 已提交
727 728 729 730 731 732
                break;
            default:
                break;
        }
    }
}