0

查看下面的所有 3 个编辑

更新:将 'read()' 更改为 'readFully()' 并让一些工作正常进行。'decodeByteArray()' 不再返回 null。写入卡片的 jpeg 实际上是一个完整的图像。图像仍未被绘制到我的视野中。如果需要,我将继续工作并发布另一个问题。

我正在编写一个视频流客户端程序,它从 DataInputStream 中获取图像。

因为服务器在这些图像上调用了 compressToJpeg(),所以我想我可以简单地从 DataInputStream 中获取字节数组,对其进行解码,然后将位图从 decodeByteArray() 绘制到我的 SurfaceView。不幸的是,该方法只让我 decodeByteArray() 返回 null。

所以我添加了一个中间步骤。我创建了一个 compressFrame() 方法,它简单地从流中获取字节数组,创建一个新的 YuvImage 实例,并使用它来调用 compressToJpeg()。但是,在运行时,此方法会挂起 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”方法来测试。我认为它无法解码的原因是因为图像的大部分只是空白空间,并且只有一部分图像在那里。

4

0 回答 0