| | |
| | | |
| | | /** |
| | | * 这个采用ImageReader视频帧来获取视频和处理图片 |
| | | * TODO 关闭录像出现mMediaMuxer 异常 |
| | | * */ |
| | | public class Camera2TextureView4 extends TextureView { |
| | | |
| | |
| | | private void startPreview() { |
| | | //启动预览 |
| | | try { |
| | | if(previewThreadHandler == null){ |
| | | initPreviewThreadHandler(); |
| | | } |
| | | mCaptureSession.setRepeatingRequest(previewCaptureBuilder.build(), null, previewThreadHandler); |
| | | } catch (CameraAccessException e) { |
| | | e.printStackTrace(); |
| | |
| | | byte[] nv12 = new byte[I420size]; |
| | | byte[] nv21 = new byte[I420size]; |
| | | |
| | | YUVUtil.YUVToNV21_NV12(image,nv12,videoWidth,videoHeight,"NV12"); |
| | | YUVUtil.YUVToNV21_NV12(image, nv12, videoWidth, videoHeight, "NV12"); |
| | | long now = image.getTimestamp(); |
| | | image.close(); |
| | | //图片截图 |
| | | SharedPreferences camera2Time = mContext.getSharedPreferences("camera2Time", Context.MODE_PRIVATE); |
| | | long lastTime = camera2Time.getLong("time", 0); |
| | | long secondsGap = (now - lastTime) / 1000000000; |
| | | if (lastTime == 0 || secondsGap > 2) { |
| | | if (lastTime == 0 || secondsGap > 2) { |
| | | camera2Time.edit().putLong("time", now).apply(); |
| | | //需要将nv12转化为nv21后进行图片存储 |
| | | nv21 = convertNV12toNV21(nv12); |
| | |
| | | } |
| | | |
| | | // 提交数据给MediaCodec |
| | | int inputBufferIndex = mMediaCodec.dequeueInputBuffer(0); |
| | | if (inputBufferIndex >= 0) { |
| | | ByteBuffer inputBuffer = mMediaCodec.getInputBuffer(inputBufferIndex); |
| | | inputBuffer.clear(); |
| | | inputBuffer.put(nv12); |
| | | long nanoTime = System.nanoTime(); |
| | | long presentationTimeUs = nanoTime / 1000; // 将纳秒转换为微秒 |
| | | mMediaCodec.queueInputBuffer(inputBufferIndex, 0, nv12.length, presentationTimeUs, 0); |
| | | } |
| | | // 获取编码后的数据汇入H264 封装成mp4 |
| | | MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); |
| | | int outputBufferIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo, 0); |
| | | if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { |
| | | mVideoTrackIndex = mMediaMuxer.addTrack(mMediaCodec.getOutputFormat()); |
| | | if(mVideoTrackIndex != -1){ |
| | | mMediaMuxer.start(); |
| | | try { |
| | | int inputBufferIndex = mMediaCodec.dequeueInputBuffer(0); |
| | | if (inputBufferIndex >= 0) { |
| | | ByteBuffer inputBuffer = mMediaCodec.getInputBuffer(inputBufferIndex); |
| | | inputBuffer.clear(); |
| | | inputBuffer.put(nv12); |
| | | long nanoTime = System.nanoTime(); |
| | | long presentationTimeUs = nanoTime / 1000; // 将纳秒转换为微秒 |
| | | mMediaCodec.queueInputBuffer(inputBufferIndex, 0, nv12.length, presentationTimeUs, 0); |
| | | } |
| | | } |
| | | while (outputBufferIndex >=0){ |
| | | ByteBuffer outputBuffer = mMediaCodec.getOutputBuffer(outputBufferIndex); |
| | | if (mVideoTrackIndex != -1) { |
| | | mMediaMuxer.writeSampleData(mVideoTrackIndex, outputBuffer, bufferInfo); |
| | | // 获取编码后的数据汇入H264 封装成mp4 |
| | | MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); |
| | | int outputBufferIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo, 0); |
| | | if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { |
| | | mVideoTrackIndex = mMediaMuxer.addTrack(mMediaCodec.getOutputFormat()); |
| | | if (mVideoTrackIndex != -1) { |
| | | mMediaMuxer.start(); |
| | | } |
| | | } |
| | | mMediaCodec.releaseOutputBuffer(outputBufferIndex, false); |
| | | outputBufferIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo, 0); |
| | | if((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) !=0){ |
| | | break; |
| | | |
| | | while (outputBufferIndex >= 0) { |
| | | ByteBuffer outputBuffer = mMediaCodec.getOutputBuffer(outputBufferIndex); |
| | | if (mVideoTrackIndex != -1) { |
| | | |
| | | mMediaMuxer.writeSampleData(mVideoTrackIndex, outputBuffer, bufferInfo); |
| | | |
| | | mMediaCodec.releaseOutputBuffer(outputBufferIndex, false); |
| | | outputBufferIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo, 0); |
| | | if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | //中断错误,忽略 |
| | | } |
| | | |
| | | }; |
| | |
| | | try { |
| | | previewThread.quitSafely(); |
| | | previewThread.join(); |
| | | previewThread = null; |
| | | previewThreadHandler = null; |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
| | | }finally { |
| | | previewThread = null; |
| | | previewThreadHandler = null; |
| | | } |
| | | } |
| | | |