SO と google を数日間検索した後、私はあきらめ始めたので、ここに投稿したほうがよいと思いました。
ある種のビデオチャットを提供する Android アプリを作成しています。これは可能な限りリアルタイムに近づける必要があるため、さまざまなプロトコルについて読み、最初に MJPEG を試すことにしました (今のところオーディオには関係ありません)。
現在、データのストリーミングは私を夢中にさせています。接続が確立され、アプリはカメラ プレビュー フレームのストリームへの書き込みを開始しますが、VLC も mplayer もビデオの再生を開始しません。接続を監視すると、データが到着していることがわかります。
接続 このコードは非同期タスクによって実行され、成功するとリスナーに通知されます。
try
{
ServerSocket server = new ServerSocket(8080);
socket = server.accept();
server.close();
Log.i(TAG, "New connection to :" + socket.getInetAddress());
stream = new DataOutputStream(socket.getOutputStream());
prepared = true;
}
catch (IOException e)
{
Log.e(TAG, e.getMessage();
}
PC で「mplayer http://tabletIP:8080
」を実行すると、タブレットが接続を登録します (したがって、ストリーマーとカメラのプレビューが開始されます)。これは VLC でも動作します。
ストリーミングこれにより、ヘッダーがストリームに書き込まれます。
if (stream != null)
{
try
{
// send the header
stream.write(("HTTP/1.0 200 OK\r\n" +
"Server: iRecon\r\n" +
"Connection: close\r\n" +
"Max-Age: 0\r\n" +
"Expires: 0\r\n" +
"Cache-Control: no-cache, private\r\n" +
"Pragma: no-cache\r\n" +
"Content-Type: multipart/x-mixed-replace; " +
"boundary=--" + boundary +
"\r\n\r\n").getBytes());
stream.flush();
streaming = true;
}
catch (IOException e)
{
notifyOnEncoderError(this, "Error while writing header: " + e.getMessage());
stop();
}
}
その後、Camera.onPreviewFrame() コールバックを通じてストリーミングがトリガーされます。
@Override
public void onPreviewFrame(byte[] data, Camera camera)
{
frame = data;
if (streaming)
mHandler.post(this);
}
@Override
public void run()
{
// TODO: cache not filling?
try
{
// buffer is a ByteArrayOutputStream
buffer.reset();
switch (imageFormat)
{
case ImageFormat.JPEG:
// nothing to do, leave it that way
buffer.write(frame);
break;
case ImageFormat.NV16:
case ImageFormat.NV21:
case ImageFormat.YUY2:
case ImageFormat.YV12:
new YuvImage(frame, imageFormat, w, h, null).compressToJpeg(area, 100, buffer);
break;
default:
throw new IOException("Error while encoding: unsupported image format");
}
buffer.flush();
// write the content header
stream.write(("--" + boundary + "\r\n" +
"Content-type: image/jpg\r\n" +
"Content-Length: " + buffer.size() +
"\r\n\r\n").getBytes());
// Should omit the array copy
buffer.writeTo(stream);
stream.write("\r\n\r\n".getBytes());
stream.flush();
}
catch (IOException e)
{
stop();
notifyOnEncoderError(this, e.getMessage());
}
}
スローされる例外はありません。mHandler は、独自の HandlerThread で実行されます。念のため、AsyncTask を使用してみましたが、役に立ちませんでした (ところで、これの方が良いですか?)。
エンコードされたフレームは Android 側で問題ありません。それらを jpg ファイルに保存して開くことができました。
私の推測では、どうにかしてデータをクラスター化するか、ソケットなどにいくつかのオプションを設定する必要がありますが、....まあ、私は立ち往生しています。
tl;dr: VLC がストリームを再生していません。mplayer は「キャッシュがいっぱいではありません」と言っています。おそらく最後のコード セグメントに問題があります。助けが必要です ~ :)
よろしくお願いします!