2015-07-10 326 views
3

我在嘗試使用Androids軟件解碼器(OMX.google.h264.decoder)提取和解碼H264視頻時遇到問題。這個問題似乎跨越了多個設備。Android軟件解碼器(OMX.google.h264.decoder)無法解碼H264視頻

使用Nexus 5硬件解碼器(OMX.qcom.video.decoder.avc),該視頻的播放效果不錯。

下面的示例代碼展示了該問題,並且是使用android MediaCodec和MediaExtractor類的相當標準的示例。

我得到的異常是第一個緩衝區傳遞給解碼器時的非法狀態異常。

該視頻是720x480 20fps編碼在基線配置文件,因此應該符合兼容性準則。

Here is a video sample to accompany the code

我將不勝感激上正確地獲取軟件視頻解碼器H264視頻工作的指導意見。

public void doMp4Test() 
{ 
    try 
    { 
     //String filename = "webserver_h264.mp4"; 
     String filename = "toodee-720p.mp4"; 
     MediaExtractor extractor = new MediaExtractor(); 
     extractor.setDataSource(Constants.RootDirectory + File.separator + filename); 

     MediaCodec decoder = null; 

     for (int i = 0; i < extractor.getTrackCount(); i++) 
     { 
      MediaFormat format = extractor.getTrackFormat(i); 
      String mime = format.getString(MediaFormat.KEY_MIME); 
      if (mime.startsWith("video/")) 
      { 
       extractor.selectTrack(i); 
       decoder = MediaCodec.createByCodecName("OMX.google.h264.decoder"); 
       // decoder = MediaCodec.createDecoderByType("OMX.qcom.video.decoder.avc"); // working decoder type 
       decoder.configure(format, m_surface, null, 0); 
       break; 
      } 
     } 

     if (decoder == null) 
     { 
      Log.e("DecodeActivity", "Can't find video info!"); 
      return; 
     } 

     decoder.start(); 

     ByteBuffer[] inputBuffers = decoder.getInputBuffers(); 
     ByteBuffer[] outputBuffers = decoder.getOutputBuffers(); 
     BufferInfo info = new BufferInfo(); 
     boolean isEOS = false; 
     long startMs = System.currentTimeMillis(); 

     while (!Thread.interrupted()) 
     { 
      if (!isEOS) 
      { 
       int inIndex = decoder.dequeueInputBuffer(10000); 
       if (inIndex >= 0) 
       { 
        ByteBuffer buffer = inputBuffers[inIndex]; 
        int sampleSize = extractor.readSampleData(buffer, 0); 
        if (sampleSize < 0) 
        { 
         Log.d("DecodeActivity", "InputBuffer BUFFER_FLAG_END_OF_STREAM"); 
         decoder.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); 
         isEOS = true; 
        } 
        else 
        { 
         int flags = 0;// extractor.getSampleFlags(); 
         decoder.queueInputBuffer(inIndex, 0, sampleSize, extractor.getSampleTime(), flags); 
         extractor.advance(); 
        } 
       } 
      } 

      int outIndex = decoder.dequeueOutputBuffer(info, 10000); 
      switch (outIndex) 
      { 
      case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED: 
       Log.d("DecodeActivity", "INFO_OUTPUT_BUFFERS_CHANGED"); 
       outputBuffers = decoder.getOutputBuffers(); 
       break; 
      case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED: 
       Log.d("DecodeActivity", "New format " + decoder.getOutputFormat()); 
       break; 
      case MediaCodec.INFO_TRY_AGAIN_LATER: 
       Log.d("DecodeActivity", "dequeueOutputBuffer timed out!"); 
       break; 
      default: 
       ByteBuffer buffer = outputBuffers[outIndex]; 
       Log.v("DecodeActivity", "We can't use this buffer but render it due to the API limit, " + buffer); 

       // We use a very simple clock to keep the video FPS, or the 
       // video 
       // playback will be too fast 
       while (info.presentationTimeUs/1000 > System.currentTimeMillis() - startMs) 
       { 
        try 
        { 
         Thread.sleep(10); 
        } 
        catch (InterruptedException e) 
        { 
         e.printStackTrace(); 
         break; 
        } 
       } 
       decoder.releaseOutputBuffer(outIndex, true); 
       break; 
      } 

      if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) 
      { 
       Log.d("DecodeActivity", "OutputBuffer BUFFER_FLAG_END_OF_STREAM"); 
       break; 
      } 
     } 

      decoder.stop(); 
      decoder.release(); 
      extractor.release(); 
    } 
    catch (Exception e) 
    { 
     e.printStackTrace(); 
    } 
} 
+0

測試了大約六個H.264視頻。此Google解碼器僅適用於其中一種。 – Hong

回答

2

尋找與ffprobe視頻看起來它實際上是很高的知名度,而不是基本輪廓:

流#0:0(ENG):視頻:H264(高)(AVC1/0x31637661),YUV420P,720×480 [SAR 1:1 DAR 3:2],515 kb/s的,24.66幀,1000K TBR,1000K TBN,2000K TBC(默認)

作爲題外話,視頻似乎玩,但只是在筆記本電腦上試用時在幾個瀏覽器上播放時顯示黑屏。

+0

謝謝你指出這一點。我曾嘗試在英特爾編碼器中將格式更改爲基準,但仍無法播放。我想象有很多其他設置可能會破壞兼容性。你有沒有權限訪問一個例子.mp4或.h264文件,這些文件是兼容的,並可以使用上面的代碼?這會極大地幫助我正確配置編碼器。 –

+0

@MichaelDavidKnight這個鏈接有一個h.264 mp4視頻應該可以工作 - 我只是在Android 4.2上測試它,並用Android瀏覽器和Chrome瀏覽器進行播放:http://www.quirksmode.org/html5/tests/ video.html – Mick