以下の3つの編集すべてを参照してください
更新:「read()」を「readFully()」に変更し、いくつかの機能を追加しました。'decodeByteArray()'はnullを返さなくなりました。カードに書き込まれるjpegは、実際には完全な画像です。画像はまだ私のビューに描画されていません。作業を続け、必要に応じて別の質問を投稿します。
DataInputStreamから画像を取り込むビデオストリーミングクライアントプログラムを作成しています。
サーバーがこれらの画像に対してcompressToJpeg()を呼び出すため、DataInputStreamからバイト配列を取得してデコードし、decodeByteArray()からSurfaceViewにビットマップを描画できると考えました。残念ながら、そのメソッドでは、decodeByteArray()がnullを返すだけです。
そこで、中間ステップを追加しました。ストリームからバイト配列を取得し、新しいYuvImageインスタンスを作成し、それを使用してcompressToJpeg()を呼び出すcompressFrame()メソッドを作成しました。ただし、実行すると、このメソッドはcompressToJpegでハングし、クライアントアクティビティを閉じます。FCポップアップはなく、ログにエラーはありません。
問題のあるメソッドを呼び出すスレッドのrun()、メソッド自体、およびアプリが閉じる前に出力されるログを提供しました。
編集:念のため、ReceiverUtils.getFrame()も追加しました。
@Override
public void run() {
String fromServer = null;
int jpgSize;
byte[] buffer;
byte[] jpgData;
Bitmap image;
ByteArrayOutputStream jpgBaos = null;
while(isItOK && (receiver.textIn != null)){
if(!holder.getSurface().isValid()){
continue;
}
ReceiverUtils.init(holder);
//Receive 'ready' flag from camcorder
fromServer = ReceiverUtils.receiveText(receiver);
while((fromServer != null)){
Log.e("From server: ", fromServer); //logging here because of null pointers when done in Utils
if(fromServer.startsWith("ANDROID_JPG_READY")){
//Obtain size for byte array
jpgSize = Integer.parseInt(fromServer.substring(18));
Log.e("JPG SIZE", String.valueOf(jpgSize));
//Create byte array of size jpgSize
buffer = new byte[jpgSize];
Log.e("BUFFER SIZE", String.valueOf(buffer.length));
//Send flag and receive image data from camcorder
ReceiverUtils.sendText(receiver, "ANDROID_JPG_SEND");
jpgData = ReceiverUtils.receiveData(receiver, buffer);
//Compress jpgData and write result to jpgBaos
jpgBaos = ReceiverUtils.compressFrame(imgRect, jpgData);
//Decode jpgData into Bitmap
image = ReceiverUtils.getFrame(jpgBaos.toByteArray(), jpgSize);
//image = ReceiverUtils.getFrame(jpgData, jpgSize);
//Set buffer and jpgData to null since we aren't using them
buffer = null;
jpgData = null;
//Draw Bitmap to canvas
ReceiverUtils.draw(image, holder, imgRect);
//break; (testing one run-through)
}
//Receive 'ready' flag from camcorder
fromServer = ReceiverUtils.receiveText(receiver);
if(isItOK == false){
break;
}
}
//break; (testing one run-through)
}
}
これは、前のスニペットで呼び出されたReceiverUtils.compressFrame()です。
/*----------------------------------------
* compressFrame(Rect imgRect, byte[] input): Creates new instance of YuvImage used to compress ARGB
* byte array data to jpeg. Returns ByteArrayOutputStream with data.
*/
public static ByteArrayOutputStream compressFrame(Rect imgRect, byte[] input){
boolean success = false;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
YuvImage yuvImage = new YuvImage(input, ImageFormat.NV21,
imgRect.width(), imgRect.height(), null);
Log.e("HEY", "HEY");
success = yuvImage.compressToJpeg(imgRect, 80, baos);
Log.e("Compression Success:", String.valueOf(success));
return baos;
}
最後に、これはLogCatから取得した出力です。(明らかに急いで書き込まれたデバッグログに注意してください。)
07-03 15:01:19.754: E/From server:(1634): ANDROID_JPG_READY_26907
07-03 15:01:19.754: E/JPG SIZE(1634): 26907
07-03 15:01:19.764: E/BUFFER SIZE(1634): 26907
07-03 15:01:19.764: E/To server:(1634): ANDROID_JPG_SEND
07-03 15:01:19.834: E/jpgIn(1634): Data received successfully.
07-03 15:01:19.834: E/HEY(1634): HEY
07-03 15:01:19.844: D/skia(1634): onFlyCompress
編集:ReceiverUtils.getFrame()
/*---------------------------------------
* getFrame(byte[] jpgData, int jpgSize): Decodes a byte array into a Bitmap and
* returns the Bitmap.
*/
public static Bitmap getFrame(byte[] jpgData, int jpgSize){
Bitmap res = null;
res = BitmapFactory.decodeByteArray(jpgData, 0, jpgSize);
Log.e("Decode success", String.valueOf(!(res == null)));
return res;
}
編集2:圧縮を追加する前のコード
//Compress jpgData and write result to jpgBaos
//jpgBaos = ReceiverUtils.compressFrame(imgRect, jpgData);
//Decode jpgData into Bitmap
//image = ReceiverUtils.getFrame(jpgBaos.toByteArray(), jpgSize);
image = ReceiverUtils.getFrame(jpgData, jpgSize);
編集3:SDカードに保存した後の画像
Androidが最初のコードスニペットの「jpgData」に保持している画像は、画像全体ではありません。新規ユーザーのため投稿できません。テストするために「writeToSD」メソッドを追加しました。デコードできないのは、画像の大部分が空白で、画像の一部しか存在しないためだと思います。