2017-02-22 5 views
0

私はAndroidデバイスの画面を記録し、rtspを介して別のクライアントにストリームするアプリを開発中です。私はVirtualDisplayとMediaCodecを使っています。MediaCodecとVirtualDisplayでAndroidのストリーミング、クライアントの切断

解決方法がわからないという問題があります。ストリーミングを開始すると、画面が変わるまでクライアントは何も受信しません。私はそれが理にかなっていると思う、バッファには何も含まれていないので、何もクライアントに送信されません。そのコードは次のとおりです。

MediaCodec buildMediaCodec() throws IOException { 
    MediaFormat format = MediaFormat.createVideoFormat(VIDEO_MIME_TYPE, VIDEO_WIDTH, VIDEO_HEIGHT); 

    // Set some required properties. The media codec may fail if these aren't defined. 
    format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface); 
    format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE); 
    format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE); 
    format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1); // 1 seconds between I-frames 

    // Create a MediaCodec encoder and configure it. Get a Surface we can use for recording into. 
    MediaCodec mediaCodec = MediaCodec.createEncoderByType(VIDEO_MIME_TYPE); 
    mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); 
    return mediaCodec; 
} 

// This is passed to buildVirtualDisplay(), and I get it from calling buildMediaCodec() 
Surface mediaCodecSurface = mMediaCodec.createInputSurface(); 

VirtualDisplay buildVirtualDisplay(MediaProjection mediaProjection, Surface mediaCodecSurface, DisplayMetrics displayMetrics) { 
    if (mediaProjection == null || mediaCodecSurface == null || displayMetrics == null) { 
     throw new InvalidParameterException("MediaProjection, Surface and DisplayMetrics are mandatory"); 
    } 
    return mediaProjection.createVirtualDisplay("Recording Display", VIDEO_WIDTH, VIDEO_HEIGHT, SCREEN_DPI, 0 /* flags */, mediaCodecSurface, null /* callback */, null /* handler */); 
} 

... 

mIndex = mMediaCodec.dequeueOutputBuffer(mBufferInfo, 500000); 
if (mIndex >= 0) { 
    mBuffer = mMediaCodec.getOutputBuffer(mIndex); 
    if (mBuffer == null) { 
     throw new RuntimeException("couldn't fetch buffer at index " + mIndex); 
    } 
    mBuffer.position(0); 
    break; 
} else if (mIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { 
    mMediaFormat = mMediaCodec.getOutputFormat(); 
    Log.i(TAG, mMediaFormat.toString()); 
} else if (mIndex == MediaCodec.INFO_TRY_AGAIN_LATER) { 
    Log.v(TAG, "No buffer available..."); 
} else { 
    Log.e(TAG, "Message: " + mIndex); 
} 

ログには、利用可能なバッファがありません...次々と表示されます。画面が変わる瞬間に停止します。

問題は、電話とのやり取りをやめることです。何も変わっていないので、画面は更新されないので、MediaCodec.INFO_TRY_AGAIN_LATERを取得し続けます。 10秒後、クライアントは切断されます。私は何も受け取っていないと思うので、接続をシャットダウンします。

また、私が最初に待つ時間が長いほど、サーバーとクライアントデバイスの間の遅延が大きくなることもわかりました。

私が進捗バーを置いても問題ないですが、バッファには送信されるデータが含まれるように画面が再描画されているようです。

私はこの問題についての情報を探しました。これが起こらないようにするために私が何をするかについての示唆はありますか? MediaCodecとVirtualDisplayの間にもう1つのSurfaceを使用して、レンダリングを強制的に実行する必要がありますか?

ありがとうございました。

答えて

1

少なくとも10秒間データを受信しなかった後にクライアントが切断されることがわかりました。これを防ぐためにMediaFormatからKEY_REPEAT_PREVIOUS_FRAME_AFTERを試してみましたが、これまでのところ運がありません。

+0

あなたはこれを解決する方法を考え出しましたか? –

+1

いいえ、私はそれをハックしました。ステータスバーにアイコンを表示します。このアイコンはアニメーション化されています。私は2つの画像を持つドロウアブルを持っています、これらの2つの画像は同じですので、ユーザーは何も変わって見えません。しかし、Androidのためには、その部分を "再ペイント"しなければならないので、フレームを生成し続けます。 –

+0

haha​​ clever :)ありがとう! –

関連する問題