2016-03-20 47 views
1

我使用波紋管代碼將原始數據編碼爲h264以創建視頻,編碼非常好,但視頻播放速度過快。看起來演示時間有問題。當記錄開始時,我設置「tstart」的值,並且爲每個幀計算當前時間與tstart的差異並將其傳遞給queueinputbuffer,但沒有任何變化。哪部分有問題?我知道在android 4.3中,我可以將表面傳遞給mediacodec,但我想支持android 4.1。提前致謝。android-設置mediacodec的顯示時間

public void onPreviewFrame(final byte[] bytes, Camera camera) { 
        if (recording == true) { 
         long time = System.nanoTime(); 
         time -= tstart; 
         if(mThread.isAlive()&&recording == true) { 
          encode(bytes, time); 

         } 

        } 
} 

private synchronized void encode(byte[] dataInput,long time) 
{ 
    byte[] data=new byte[dataInput.length]; 
    NV21toYUV420Planar(dataInput,data,640,480); 

    inputBuffers = mMediaCodec.getInputBuffers();// here changes 
    outputBuffers = mMediaCodec.getOutputBuffers(); 

    int inputBufferIndex = mMediaCodec.dequeueInputBuffer(-1); 

    if (inputBufferIndex >= 0) { 
     ByteBuffer inputBuffer = inputBuffers[inputBufferIndex]; 
     inputBuffer.clear(); 
     inputBuffer.put(data); 
     time/=1000; 
     mMediaCodec.queueInputBuffer(inputBufferIndex, 0, data.length, time, 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]; 
      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("camera", "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); 
} 

回答

3

你的問題是,你不寫輸出幀到實際存儲任何時間戳的容器。您正在編寫一個純H264文件,其中只包含原始編碼幀,沒有索引,沒有時間戳,沒有音頻,沒有別的。

爲了獲得適當的文件時間戳,您需要使用MediaMuxer(出現在4.3)或類似的第三方庫(例如libavformat或類似的)將編碼的數據包寫入文件。輸出數據包的時間戳在bufferInfo.presentationTimeif (outputBufferIndex >= 0) {子句中,根本不使用它 - 你基本上會丟棄時間戳。

+0

那麼什麼是作爲queueinputbuffer函數的第四個參數的presentationTimeUs? –

+0

這是輸入框的顯示時間。在大多數/所有情況下,它實際上並未包含在編碼數據中,它只與編碼幀一起使用,以便您知道編碼數據包對應的時間戳。將編碼數據包寫入文件時,需要將文件('bufferInfo.presentationTimeUs')提供給文件(將其提供給MediaMuxer API或用於編寫視頻文件的其他庫)。 – mstorsjo

+0

@SajadNorouzi數據包不必以與它們相同的順序從編碼器中出來。因此,如果時間戳未傳遞,您可能在將時間戳與輸出數據包相匹配時遇到問題。 – fadden