Как использовать кодировку Android MediaCodec Данные камеры (YUV420sp)

Спасибо за внимание! Я хочу использовать API Android MediaCodec для кодирования видеофрагмента, который был приобретен с камеры, к сожалению, мне не удалось это сделать! Я до сих пор не знаком с API MediaCodec. Ниже приведены мои коды, мне нужна ваша помощь, чтобы выяснить, что я должен делать.

1, Настройка камеры:

Parameters parameters = mCamera.getParameters(); parameters.setPreviewFormat(ImageFormat.NV21); parameters.setPreviewSize(320, 240); mCamera.setParameters(parameters); 

2, Установите кодировщик:

 private void initCodec() { try { fos = new FileOutputStream(mVideoFile, false); } catch (FileNotFoundException e) { e.printStackTrace(); } mMediaCodec = MediaCodec.createEncoderByType("video/avc"); MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 320, 240); mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 125000); mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15); mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar); mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5); mMediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); mMediaCodec.start(); inputBuffers = mMediaCodec.getInputBuffers(); outputBuffers = mMediaCodec.getOutputBuffers(); } private void encode(byte[] data) { int inputBufferIndex = mMediaCodec.dequeueInputBuffer(0); if (inputBufferIndex >= 0) { ByteBuffer inputBuffer = inputBuffers[inputBufferIndex]; inputBuffer.clear(); inputBuffer.put(data); mMediaCodec.queueInputBuffer(inputBufferIndex, 0, data.length, 0, 0); } else { return; } MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); int outputBufferIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo, 0); Log.i(TAG, "outputBufferIndex-->" + outputBufferIndex); do { if (outputBufferIndex >= 0) { ByteBuffer outBuffer = outputBuffers[outputBufferIndex]; System.out.println("buffer info-->" + bufferInfo.offset + "--" + bufferInfo.size + "--" + bufferInfo.flags + "--" + bufferInfo.presentationTimeUs); byte[] outData = new byte[bufferInfo.size]; outBuffer.get(outData); try { if (bufferInfo.offset != 0) { fos.write(outData, bufferInfo.offset, outData.length - bufferInfo.offset); } else { fos.write(outData, 0, outData.length); } fos.flush(); Log.i(TAG, "out data -- > " + outData.length); mMediaCodec.releaseOutputBuffer(outputBufferIndex, false); outputBufferIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo, 0); } catch (IOException e) { e.printStackTrace(); } } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) { outputBuffers = mMediaCodec.getOutputBuffers(); } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { MediaFormat format = mMediaCodec.getOutputFormat(); } } while (outputBufferIndex >= 0); } 

Я предполагаю, что проблема возникла в методе кодирования, этот метод будет использоваться в обратном вызове Preview Preview камеры, например

 initCodec(); //mCamera.setPreviewCallback(new MyPreviewCallback()); mCamera.setPreviewCallback(new PreviewCallback() { @Override public void onPreviewFrame(byte[] data, Camera camera) { encode(data); } }); 

Я просто не знаю, как правильно это сделать с помощью MediaCodec API. Можете ли вы дать мне несколько советов или ссылок об этом?

Спасибо!

Solutions Collecting From Web of "Как использовать кодировку Android MediaCodec Данные камеры (YUV420sp)"

Я решил проблему. Как следует:

 private synchronized void encode(byte[] data) { inputBuffers = mMediaCodec.getInputBuffers();// here changes outputBuffers = mMediaCodec.getOutputBuffers(); int inputBufferIndex = mMediaCodec.dequeueInputBuffer(-1); Log.i(TAG, "inputBufferIndex-->" + inputBufferIndex); //...... 

И далее вы обнаружите, что ваш кодированный цвет видео неправильный, для получения дополнительной информации перейдите сюда MediaCodec и Camera: цветовые пространства не совпадают

Форматы YUV420, выводимые камерой, несовместимы с форматами, принятыми кодеком MediaCodec AVC. В лучшем случае это, по сути, NV12 vs. NV21 (U и V плоскости обращены), требуя ручного переупорядочения. В худшем случае, начиная с Android 4.2, формат ввода кодера может быть специфичным для устройства.

Вам лучше использовать MediaRecorder для подключения аппаратного обеспечения камеры к кодеру.

Обновление. Теперь можно передать предварительный просмотр камеры в MediaCodec вместо использования данных YUV в ByteBuffer . Это быстрее и портативнее. См. Образец CameraToMpegTest здесь .