2016-06-15 6 views
0

サーバからH264ストリーミングビデオをデコードし、SurfaceViewでレンダリングする一連のクラスを設定しました。今、このコードは私がエミュレータを含めて試したすべてのデバイスで完璧に動作していますが、突然私はS7を買ってしまい、このデバイスではもはや正しく動作しません。MediaCodecがS7で失敗する

奇妙なことには、いくつかの回は、それがその後、他のいくつかの時間が、それは、このエラーがスローされます、完璧に動作することである。

06-15 16:41:40.249 13300-24605/cm.myapp E/ACodec: [OMX.Exynos.avc.dec] ERROR(0x90000012) 
06-15 16:41:40.249 13300-24605/cm.myapp E/ACodec: signalError(omxError 0x90000012, internalError -2147483648) 
06-15 16:41:40.249 13300-24604/cm.myapp E/MediaCodec: Codec reported err 0x90000012, actionCode 0, while in state 6 
06-15 16:41:40.249 13300-24578/cm.myapp W/MediaStreamerThread: Failed to draw media. 

時にはそれがdequeueInputBuffersにクラッシュするには、呼び出し:

java.lang.IllegalStateException 
                       at android.media.MediaCodec.native_dequeueOutputBuffer(Native Method) 
                       at android.media.MediaCodec.dequeueOutputBuffer(MediaCodec.java:2379) 

そして、もう一度、この非常に異なるエラーが発生することがあります。

06-15 16:34:57.239 13300-16625/cm.myapp W/System.err: java.lang.IllegalArgumentException: The surface has been released 
06-15 16:34:57.239 13300-16625/cm.myapp W/System.err:  at android.media.MediaCodec.native_configure(Native Method) 
06-15 16:34:57.239 13300-16625/cm.myapp W/System.err:  at android.media.MediaCodec.configure(MediaCodec.java:1778) 
                     java.lang.RuntimeException: Could not create h264 decoder 

これらのエラー自体はあまり冗長ではないので、どこに問題があるのか​​理解できません。

もう一度私のコードはほとんどのデバイスで完全に動作しますが、これは失敗しています。これはどのように可能ですか?何か案は?

これは私の復号化コードです:

public class H264Decoder 
{ 
    static private final long TIMEOUT_US = 10000L; 

    private MediaCodec mDecoder; 
    private Surface mSurface; 

    private static final List<byte[]> EMPTY_ENCODE_RESULT = new ArrayList<>(); 
    public void init() 
    { 

       try 
       { 
        mDecoder = MediaCodec.createDecoderByType("video/avc"); 

        MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 640, 480); 

        mDecoder.configure(mediaFormat, mSurface, null, 0); 
        mDecoder.start(); 

       } 
       catch(NoClassDefFoundError ex) { 
        ex.printStackTrace(); 
        throw new RuntimeException("Could not create h264 decoder", ex); 
       }   
    } 

    public List<byte[]> offer(byte[] data) 
    { 
     List<byte[]> returnValue = new ArrayList<>(); 
     returnValue.add(decode(data, true)); 
     return returnValue; 
    } 

    public void release() 
    { 
     assert mSurface != null; 
     assert mDecoder != null; 

     mDecoder.stop(); 
     mDecoder.release(); 
     mDecoder = null; 
    } 

    public H264Decoder(Surface surface) 
    { 
     mSurface = surface; 
    } 

    public byte[] decode(byte[] data, boolean updateRender) 
    { 
     if (mSurface == null) 
     { 
      return null; 
     } 
     // INPUT ----------------------------------------------------------------------------------- 

     int inputBufferIndex = mDecoder.dequeueInputBuffer(TIMEOUT_US); 

     if (inputBufferIndex >= 0) 
     { 
      // Get an input buffer from the codec, fill it with data, give it back 
      ByteBuffer inputBuffer = mDecoder.getInputBuffers()[inputBufferIndex]; 
      inputBuffer.put(data); 
      mDecoder.queueInputBuffer(inputBufferIndex, 0, data.length, 0, 0); 
     } 

     // OUTPUT ---------------------------------------------------------------------------------- 

     MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); 
     int outputBufferIndex = mDecoder.dequeueOutputBuffer(info, TIMEOUT_US); 

     if (outputBufferIndex >= 0) 
     { 
      final ByteBuffer[] outputBuffer = mDecoder.getOutputBuffers(); 
      mDecoder.releaseOutputBuffer(outputBufferIndex, updateRender); 

     } 
     else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) 
     { 
      //outputBuffers = codec.getOutputBuffers(); 
     } 
     else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) 
     { 
      MediaFormat format = mDecoder.getOutputFormat(); 
     } 
     return null; 
    } 
} 
+0

私はビデオをデコードするいくつかのコードであなたの質問を拡張することをお勧めします。私は 'dequeueOutputBuffer'が間違った状態のメディアコーデックで呼び出されていると思います。 2.メディアコーデックを設定しようとするとSurfaceViewがサーフェスを有効にしません。 –

+0

@VladimirLichonos私はちょうどそれをした – MichelReap

答えて

1

間違って行くことができるものとは言い難いです。一つは、私は、出力バッファから配列を返すことをお勧めしません

mDecoder.releaseOutputBuffer(outputBufferIndex, updateRender); 
if(!updateRender) { 
    return outputBuffer[outputBufferIndex].array(); 
} 

かかわらずです。 According to documentationそれはあなたが本当にサンプルをエンコードしている必要がある場合、私はより良い出力バッファ、呼解放のコピーを作成し、そのコピーを返します

Once an output buffer is released to the codec, it MUST NOT be used

を述べています。

返されたバイト配列が何らかの方法で処理されていた場合は、このメソッドをループに抜き出してバイトバッファ(出力バッファ)を処理し、出力バッファを解放することをお勧めします。詳細については、MediaCodecをご覧ください

+0

ありがとう@VladimirLichonos。私は実際にそのビットを削除し、同じ結果を得ました。私が見つけたのは、私がタイムアウトを上回ればそれはよりうまくいくようだが、私がより低い価値を置くなら、それはほぼすべて失敗するということだ。 – MichelReap

+0

両方のエラーは、表面に何かがあることを示しています。表面はリリースされています。releaseOutputBufferがupdateRender = trueで呼び出されました。 –

+0

実際、私はupdateRender = falseを設定しようとしましたが、明らかに画面上に何も表示されませんが、同じ例外が発生しています。場合によっては 'dequeueOutputBuffers'で、時には' dequeueInputBuffers'呼び出しで発生します。 – MichelReap

0

サムスンS7では、デコーダに挿入された最初のH264フレームがIフレームであることを確認する必要があります。

関連する問題