/** * Video encoding is done by a MediaCodec. */ protectedvoidencodeWithMediaCodec()throws RuntimeException, IOException { if (mMode == MODE_MEDIACODEC_API_2) { // Uses the method MediaCodec.createInputSurface to feed the encoder encodeWithMediaCodecMethod2(); } else { // Uses dequeueInputBuffer to feed the encoder encodeWithMediaCodecMethod1(); } }
/** * Video encoding is done by a MediaCodec. */ @SuppressLint("NewApi") protectedvoidencodeWithMediaCodecMethod1()throws RuntimeException, IOException { // Updates the parameters of the camera if needed createCamera();// 设置相机参数并开启相机 updateCamera();// 更新参数
// Estimates the frame rate of the camera measureFramerate();
// Starts the preview if needed if (!mPreviewStarted) { try { mCamera.startPreview(); mPreviewStarted = true; } catch (RuntimeException e) { destroyCamera(); throw e; } }
EncoderDebuggerdebugger= EncoderDebugger.debug(mSettings, mQuality.resX, mQuality.resY); // 将NV21(yuv420sp)转换成yuv420p(H264编码要求此颜色格式) finalNV21Convertorconvertor= debugger.getNV21Convertor(); // H264编码器 mMediaCodec = MediaCodec.createByCodecName(debugger.getEncoderName()); MediaFormat mediaFormat; if (EncoderDebugger.ROTATE) { mediaFormat = MediaFormat.createVideoFormat("video/avc", mQuality.resY, mQuality.resX); } else { mediaFormat = MediaFormat.createVideoFormat("video/avc", mQuality.resX, mQuality.resY); } mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, mQuality.bitrate); mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, mQuality.framerate); mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,debugger.getEncoderColorFormat()); mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1); mMediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); mMediaCodec.start(); // Camera每一帧的回调 Camera.PreviewCallbackcallback=newCamera.PreviewCallback() { longnow= System.nanoTime()/1000, oldnow = now, i=0; ByteBuffer[] inputBuffers = mMediaCodec.getInputBuffers(); @Override publicvoidonPreviewFrame(finalbyte[] data, final Camera camera) { // 做一些处理 oldnow = now; now = System.nanoTime() / 1000; if (i++ > 3) { i = 0; } try { intbufferIndex= mMediaCodec.dequeueInputBuffer(500000); if (bufferIndex >= 0) { inputBuffers[bufferIndex].clear(); if (data == null) Log.e(TAG, "Symptom of the \"Callback buffer was to small\" problem..."); else {
// The packetizer encapsulates the bit stream in an RTP stream and send it over the network // 这里便回答了上面的一个问题,就是关于打包类的is来源问题 // 这里使用其中自己写的类进行了相应的封装,本质上还是MediaCodec的 mPacketizer.setInputStream(newMediaCodecInputStream(mMediaCodec)); // 开启打包线程 mPacketizer.start(); mStreaming = true; }