2015-07-10 294 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