I had the same symptoms. I decided to use the SurfaceView class but not using android.hardware.camera2 Using android.hardware.camera
Solved parts of codes.
@Override public void onPreviewFrame(byte[] data, Camera camera) { // encoding data encoding(data) ; } /** * byte data encoding * @param data */ private void encoding (byte[] data) { // api 21 ๋ฏธ๋ง์ ๋ํด์ ํ์ ByteBuffer[] inputBuffers = this.mediaCodec.getInputBuffers(); ByteBuffer[] outputBuffers = this.mediaCodec.getOutputBuffers(); int inputBufferIndex = this.mediaCodec.dequeueInputBuffer(TIMEOUT_USEC/* wait time, nagative value is infinite */); // data write ๊ฐ๋ฅ ํ ๊ฒฝ์ฐ if (inputBufferIndex >= 0) { // data null (๋ง์ง๋ง ๋ฐ์ดํฐ) int length = 0, flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM; if (data != null) { ByteBuffer inputBuffer = null; if (CameraUtils.isCamera2()) inputBuffer = this.mediaCodec.getInputBuffer(inputBufferIndex); else inputBuffer = inputBuffers[inputBufferIndex]; inputBuffer.clear(); inputBuffer.put(data); length = data.length; flags = 0; } /* - index : dequeueInputBuffer ์์ return ๋ฐ์ index ๋ฒํธ๋ฅผ ๋ฃ์ต๋๋ค. - offset : ํญ์ 0์ด๊ฒ ์ง๋ง Buffer์ ์ฑ์๋ฃ์ ๋ฐ์ดํฐ์ ์์ ์ ์ ์ง์ ํ ์ ์์ต๋๋ค. - size : Buffer์ ์ฑ์๋ฃ์ ๋ฐ์ดํฐ ์ฌ์ด์ฆ ์ ๋ณด - presentationTimeUs : ๋์ฝ๋ฉ์ ๊ฒฝ์ฐ Play ํ ๋ฐ์ดํฐ์ ์๊ฐ(๋ง์ดํฌ๋ก ์ด) - flags : ์ฝ์ ๋ฒํผ์ ์ ๋ณด๊ฐ ์ค์ ๊ฐ์ธ์ง BUFFER_FLAG_CODEC_CONFIG, ๋ง์ง๋ง ๋ฐ์ดํฐ์ธ์งBUFFER_FLAG_END_OF_STREAM์ ๋ํ ์ ๋ณด๋ฅผ ์ด๊ธฐํ ํ ์ ์์ต๋๋ค. ๋๋ถ๋ถ์ 0์ ์ฑ์๋ฃ๊ณ ๋ง์ง๋ง ๋ฐ์ดํฐ๋ฅผ ์๋ฆฌ๊ธฐ ์ํด์๋ BUFFER_FLAGS_END_OF_STREAM์ ๋ฃ์ต๋๋ค. */ this.mediaCodec.queueInputBuffer(inputBufferIndex, 0, length, computePresentationTimeNsec(), flags); } MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); int outputBufferIndex = this.mediaCodec.dequeueOutputBuffer(bufferInfo, TIMEOUT_USEC/* wait time, nagative value is infinite */); switch (outputBufferIndex) { /* MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED - Buffer ์ ๋ณด๊ฐ 1๋ฒ ๋ณ๊ฒฝ๋๊ฒ ๋ฉ๋๋ค. - API 21์ธ Lollipop ๋ถํฐ๋ ์ด @deprecated ๋์๊ธฐ์ ๋ถํ์ํ์ง๋ง ์ด์ API์์๋ ๊ผญ ํ์ํ ์ ๋ณด์
๋๋ค. ์ด๊ฒ ํธ์ถ๋๋ฉด ์ฒ์์ ์์ฑํ ByteBuffer[] ๋ฐฐ์ด์ ๋ณํ๊ฐ ์ผ์ด๋๊ฒ ๋ฉ๋๋ค. */ case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED: Log.i(TAG, "INFO_OUTPUT_BUFFERS_CHANGED"); outputBuffers = this.mediaCodec.getOutputBuffers(); break; /*MediaCodec.INFO_OUTPUT_FORMAT_CHANGED - ์ฒ์์ ์์ฑํ์๋ MediaFormat์ ๊ธฐ์ตํ์๋์ง์. ๊ทธ MediaFormat์ด ๋ณ๊ฒฝ๋ ์ ๋ณด๋ฅผ ์๋ ค์ฃผ๊ฒ๋ฉ๋๋ค. - ์ด ๊ฒฝ์ฐ๋ Encoder์์๋ง ์ฃผ๋ก ์ฌ์ฉํ๊ณ , ๋์ฝ๋์์๋ ์ฌ์ฉํ ์ผ์ ์์ต๋๋ค. */ case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED: if (this.isMuxerStart) throw new RuntimeException("Format changed twice"); Log.d(TAG, "INFO_OUTPUT_FORMAT_CHANGED format : " + this.mediaCodec.getOutputFormat()); this.trackId = this.mediaMuxer.addTrack(this.mediaCodec.getOutputFormat()); this.mediaMuxer.start(); this.isMuxerStart = true; break; /*MediaCodec.INFO_TRY_AGAIN_LATER - ์ด ํจ์๊ฐ ํธ์ถ๋๋ ๊ฒฝ์ฐ๋ผ๋ฉด ์ฌ์ค ๋ฌด์ํ์ฌ๋ ๋ฉ๋๋ค. */ case MediaCodec.INFO_TRY_AGAIN_LATER: break; /*outputBufferIndex >= 0 - ์ด ๊ฒฝ์ฐ์ ์ค์ ๋์ฝ๋ฉ ๋ ๋ฐ์ดํฐ๊ฐ ๋ค์ด์ค๋ ๊ฒฝ์ฐ์ ํด๋น๋ฉ๋๋ค. */ default: while (outputBufferIndex >= 0 && this.mediaCodec != null && this.mediaMuxer != null) { ByteBuffer outputBuffer = null; if (CameraUtils.isCamera2()) outputBuffer = this.mediaCodec.getOutputBuffer(outputBufferIndex); else outputBuffer = outputBuffers[outputBufferIndex]; // null exception if (outputBuffer == null) throw new RuntimeException("EncoderOutputBuffer " + outputBuffer + " was NULL"); if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) { // The codec config data was pulled out and fed to the muxer when we got // the INFO_OUTPUT_FORMAT_CHANGED status. Ignore it. bufferInfo.size = 0; } if (bufferInfo.size >= 0) { if (!this.isMuxerStart) throw new RuntimeException("MediaMuxer hasn't started"); // ํ๋ ์์ ํ์์คํฌํ ์์ฑ bufferInfo.presentationTimeUs = computePresentationTimeNsec(); this.prevTime = bufferInfo.presentationTimeUs; this.mediaMuxer.writeSampleData(this.trackId, outputBuffer, bufferInfo); } this.mediaCodec.releaseOutputBuffer(outputBufferIndex, false/* true is surface init */); outputBufferIndex = this.mediaCodec.dequeueOutputBuffer(bufferInfo, TIMEOUT_USEC/* wait time, nagative value is infinite */); // end of frame if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { // release releaseRecorder(); // ์ ์ฅ ์๋ฃ onCompleteEncoding(recordPath); stopEncodingThread(); return; } } break; } }
source share