2016-03-15 66 views
1

参考:https://android.googlesource.com/platform/cts/+/jb-mr2-release/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.javaEncodeDecodeMux - 三星设备 - 测试在S6 Edge和S5

我使用上面的代码进行编码/解码/ MUX为了使视频分辨率较低和比特率。 它的工作完全正确的所有决议,包括nexus5,LG G3,1加4K视频。

但是,三星设备显示不适当的行为。

  • 如果我把4k视频(3840x2160)作为输入并想将分辨率降低到1920x1080,我会得到例外。

  • 如果我以4k视频(3840x2160)作为输入并想将其分辨率降低到1280x720,我仍然会得到例外。

  • 如果我将目标分辨率设置为640x360,它可以很好地工作。

我认为这可能与三星设备上的编解码器问题有关。

以下是代码片段

MediaCodec encoder = MediaCodec.createByCodecName(codecInfo.getName()); 
     encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); 
     surfaceReference.set(encoder.createInputSurface()); 
     encoder.start(); 

    MediaCodec decoder = MediaCodec.createDecoderByType(getMimeTypeFor(inputFormat)); 
     decoder.configure(inputFormat, surface, null, 0); 
decoder.start(); 

下列语句,异常

decoder.configure(inputFormat, surface, null, 0); 

以下是堆栈跟踪

I/ACodec: [OMX.Exynos.AVC.Encoder] Now Executing 
03-15 14:35:23.801 25357-26008/com.test I/ACodec: [] Now uninitialized 
03-15 14:35:23.801 25357-26036/com.test I/OMXClient: Using client-side OMX mux. 
03-15 14:35:23.811 25357-26036/com.test I/ACodec: can't find wfdsink-exynos-enable 
03-15 14:35:23.811 25357-26036/com.test E/ACodec: configureCodec multi window instance fail appPid : 25357 
03-15 14:35:23.811 25357-26036/com.test E/ACodec: [OMX.Exynos.avc.dec] configureCodec returning error -1021 
03-15 14:35:23.811 25357-26036/com.test E/ACodec: signalError(omxError 0x80001001, internalError -1021) 
03-15 14:35:23.811 25357-26035/com.test E/MediaCodec: Codec reported err 0xfffffc03, actionCode 0, while in state 3 
03-15 14:35:23.811 25357-26008/com.test E/MediaCodec: configure failed with err 0xfffffc03, resetting... 
03-15 14:35:23.811 25357-26036/com.test I/ACodec: [OMX.Exynos.avc.dec] Now uninitialized 
03-15 14:35:23.811 25357-26008/com.test I/ACodec: [] Now uninitialized 
03-15 14:35:23.811 25357-26036/com.test I/OMXClient: Using client-side OMX mux. 
+1

三星总是一场斗争。祝你好运! –

+0

可能是硬件限制,例如编解码器部分的带宽不足以处理4K解码和720p编码。该错误消息通常是无益的。 – fadden

+0

您是否找到了解决此问题的解决方案? –

回答

1

基本上,它似乎有些三星的设备可能只是Exynos解码器有问题。我收到了几乎与您所看到的相同的错误消息。解决方案很复杂,但似乎解决了这个问题。

我取代了这些2行代码:

decoder = MediaCodec.createDecoderByType(mime); 
decoder.configure(format, surface, null, 0); 

使用这种方法:

private MediaCodec configDecoder(MediaFormat format, Surface surface) { 

    if (format == null || surface == null) { 
     return null; 
    } 

    MediaCodec codec; 
    String mime = format.getString(MediaFormat.KEY_MIME); 
    MediaCodecList list = new MediaCodecList(MediaCodecList.REGULAR_CODECS); 
    MediaCodecInfo[] infos = list.getCodecInfos(); 

    for (MediaCodecInfo info : infos) { 

     CodecCapabilities capabilities; 
     boolean formatSupported; 

     // does codec support this mime type 
     try { 
      capabilities = info.getCapabilitiesForType(mime); 
     } catch (IllegalArgumentException ignored) { 
      continue; 
     } 

     // does codec support his video format 
     try { 
      formatSupported = capabilities.isFormatSupported(format); 
     } catch (IllegalArgumentException ignored) { 
      continue; 
     } 

     // can we configure it successfully 
     if (formatSupported) { 
      // try decoder 
      try { 
       codec = MediaCodec.createByCodecName(info.getName()); 
      } catch (IOException e) { 
       continue; 
      } 
      try { 
       codec.configure(format, surface, null, 0); 
      } catch (IllegalArgumentException ignored) { 
       // configure() failed 
       codec.release(); 
       continue; 
      } catch (IllegalStateException ignored) { 
       // configure() failed 
       codec.release(); 
       continue; 
      } 
      // configure() successful 
      return codec; 
     } 
    } // end of for loop 

    // no decoder found 
    return null; 
} 

通常情况下,得到一个编解码器,你只需要调用

MediaCodec.createDecoderByType(mimeType) 

MediaCodecList.findDecoderForFormat(format) 

但是这只给你一个选项。使用上述方法,您可以更好地控制您使用的编解码器。例如,你可以很容易地通过添加

if (!info.getName().contains("Exynos")) 

或类似的东西过滤掉所有的Exynos编解码器。

无论如何,希望这可以帮助别人在未来。这让我感到沮丧了好几天。

最后一点,我老的设备工作正常与老代码,新代码使用一些棒棒糖和更高的方法,所以我最终的解决方案是这样的:

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { 
    decoder = configDecoder(format, surface); 
} else { 
    decoder = MediaCodec.createDecoderByType(mime); 
    decoder.configure(format, surface, null, 0); 
} 

看代码的运行,它在很大程度上仍然使用Exynos,但是当由于某种原因而导致configure()失败时,很高兴看到它无缝移动到下一个编解码器。

相关问题