2013-06-21 2 views
13

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

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); 
} 

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

initCodec(); 

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

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

Спасибо!

ответ

7

я решала problem.As следующим образом:

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 and Camera: colorspaces don't match

+1

У меня эта ошибка. Как решить эту проблему pblm .... java.lang.NoClassDefFoundError: android.media.MediaCodec ошибка указывает на эту строку: mMediaCodec = MediaCodec.createEncoderByType ("video/avc"); – Aravi

+1

@Aravi Кажется, вы пытаетесь использовать MediaCodec на Android с API <16 – SILINIK

5

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

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

Update: Теперь можно пройти Поверхностный просмотр камеры в MediaCodec, вместо того, чтобы использовать данные YUV в ByteBuffer. Это быстрее и более портативно. См. Образец CameraToMpegTest here.

+0

Благодарим Вас за help.I записал видеофайл, но данные файла неверны. Исходные данные верны, они представляют собой данные кадра h.264, но примерно три кадра позже, данные кадра h.264 заполняются 0. Может быть, Файловый буфер ошибочен, я думаю, но он не может быть 0 –

+0

Привет, @fadden. О «Лучше использовать MediaRecorder для подключения аппаратного обеспечения камеры к кодировщику». Есть ли какой-нибудь образец кода для этого? Благодарю. –