0

I created a C# server that sends an Bitmap through a socket to android client. That Bitmap is constantly updating because it's a video feed.

Server C#

private void send_data() {
    ImageConverter converter = new ImageConverter();
    byte[] sendBytes = (byte[]) converter.ConvertTo(master.picturebox_master.Image, typeof(byte[]));

    string_master_frame = System.Text.Encoding.UTF8.GetString(sendBytes);
    string_master_frame = Convert.ToBase64String(sendBytes);

    data = string_master_frame + "\n";

    tcpServer1.Send(data);
}

Client Android

@Override
protected Void doInBackground(Void... arg0) {
    Socket socket = null;
    try {
        socket = new Socket(dstAddress, dstPort);
        Scanner r = new Scanner(new InputStreamReader(socket.getInputStream()));

        while (true) {
            valores[26] = r.nextLine();

            publishProgress(valores[26]);
        }
        return null;
    }

    @Override
    protected void onProgressUpdate(String... values) {

    byte[] decodedString = Base64.decode(values[26], Base64.NO_WRAP);
        Bitmap master_bitmap = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
        master_frame.setImageBitmap(master_bitmap);

    }

The first frame is sent and the Android client displays it correctly. But when the next frame comes, the Android Client Crashes.

Error:

Process: com.example.tiago.java_android, PID: 826 java.lang.IllegalArgumentException: bad base-64 at android.util.Base64.decode(Base64.java:161) at android.util.Base64.decode(Base64.java:136) at android.util.Base64.decode(Base64.java:118) at com.example.tiago.java_android.Cliente.onProgressUpdate(Cliente.java:228) at com.example.tiago.java_android.Cliente.onProgressUpdate(Cliente.java:28) at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:656) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5431) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:914) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:707)

I though the valores[26] data was being corrupted but it's not. I get the data correctly. I used http://codebeautify.org/base64-to-image-converter to check if I get the data correctly.

Any idea?

PS: I lost my account so I had to make this one.

Bitmap master_bitmap;

byte[] decodedString = Base64.decode(values[26],Base64.NO_WRAP);
    master_bitmap = BitmapFactory.decodeByteArray(decodedString,0,decodedString.length);
    if(master_bitmap != null)
    {
        try {
            master_frame.setImageBitmap(master_bitmap);
        }
        catch (IllegalArgumentException e)
        {
            e.printStackTrace();
        }
    }
    master_bitmap.recycle();


}

Didnt work. Error:

java.lang.RuntimeException: Canvas: trying to use a recycled bitmap

  • greenapps i debugged the code and copied the value of valores[26] and used that site to see if it's the image. It worked. –  Aug 19 '16 at 16:10
  • Resolution is 640x360 3 channels RGB –  Aug 19 '16 at 16:11
  • DO not start a new thread every time. And answer the comments in the same post as where they are asked! – greenapps Aug 19 '16 at 16:14
  • SO YOU HAVE THREE ACCOUNTS? http://stackoverflow.com/questions/39042808/android-c-socket-decode-enconde-string64-error-after-1-frame-almost-complete http://stackoverflow.com/questions/39040070/android-receving-an-image-over-the-socket-from-c-sharp-server-almost-complete?noredirect=1#comment65431064_39040070 – greenapps Aug 19 '16 at 16:15
  • And I cant answer the post because I dont have 50 reputation. –  Aug 19 '16 at 16:16
  • I see no reason that you started a new post. You could have stayed with the first one. I was busy helping you. – greenapps Aug 19 '16 at 16:16
  • I forgot my email. sorry. We can continue now. –  Aug 19 '16 at 16:17
  • `And I cant answer the post ` No need that you put an answer to your own post. I ment that you should answer in a comment there where the comments are of course. – greenapps Aug 19 '16 at 16:17

1 Answers1

0

Did you try with try/catch block I explained previously?

Recall:

I had the same problem and I am almost sure this will solve your problem:

    String[] safe = values[26].split("=");
    byte[] decodedString = Base64.decode(safe[0],Base64.NO_WRAP);
    Bitmap master_bitmap = BitmapFactory.decodeByteArray(decodedString,0,decodedString.length);
    master_frame.setImageBitmap(master_bitmap);
    master_bitmap.recycle(); //THIS LINE WAS ENOUGH TO FIX MY CODE

Also, don't forget to use try/catch blocks effectively.

try{ //code here} catch(IllegalArgumentException e){ //code here if you want} (Add more catch statements if necessary.)

My full code for further help:

byte[] bytearray = Base64.decode(dataIn);
Bitmap myBitmap = BitmapFactory.decodeByteArray(bytearray, 0,bytearray.length);
if (myBitmap!=null) {
  //some irrelevant code here to turn bitmap to a PImage (a Processing image class)
}
myBitmap.recycle();

This works perfectly for me.


Try also this:

try { 
  Bitmap master_bitmap; 
  master_bitmap=BitmapFactory.decodeByteArray(decodedString, 0, ‌​decodedString.‌​leng‌​th); 
  if (master_bitmap != null) {  //might be an unnecessary if condidition
    try { 
      if (((BitmapDrawable)master_frame.getDrawable()).getBitmap()!=null) { 
        ((BitmapDrawable)master_frame.getDrawable()).getBitmap().recycle();
      }
      master_frame.setImageBitmap(master_bitmap);
      //maybe try here: master_bitmap.recycle();
    } 
    catch(RuntimeException e) { 
      e.printStackTrace();
    }
  }
} 
catch (IllegalArgumentException e) { 
  e.printStackTrace();
}
  • 'another function to change the master_frame?' what do you mean? This is an android function. –  Aug 19 '16 at 16:21
  • I just want to make the image appear on the imageview. The imageview is called master_frame. –  Aug 19 '16 at 16:21
  • I cant seem to make it work. I did exactly like you. Error: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.Bitmap.recycle()' on a null object reference –  Aug 19 '16 at 16:25
  • You are checking if(master_bitmap!=null) before anything, right? Also can you try declaring master_bitmap as a variable outside of the method? –  Aug 19 '16 at 16:28
  • I will edit my answer with my code. use it outside the method removed the null but the same error persists. –  Aug 19 '16 at 16:30
  • remove the recycle part now and try like that –  Aug 19 '16 at 16:32
  • bad base 64 again. You also had to display a video feed on a ImageView? –  Aug 19 '16 at 16:34
  • Yes, it is actually a video conference app and works without an error. –  Aug 19 '16 at 16:39
  • Doesn't seem likely but can you try without "Base64.NO_WRAP"? –  Aug 19 '16 at 16:40
  • I tried with all of them. Only NO WRAP shows the first frame. –  Aug 19 '16 at 16:42
  • Maybe this can help: http://stackoverflow.com/questions/23241257/bad-base-64-error –  Aug 19 '16 at 16:43
  • You are sure values[26] always has the right data? –  Aug 19 '16 at 17:01
  • Wait, the try is at the wrong line! try{ master_bitmap = BitmapFactory.decodeByteArray(decodedString,0,decodedString.length);} catch (IllegalArgumentException e) { e.printStackTrace(); } if(master_bitmap != null) { master_frame.setImageBitmap(master_bitmap); } –  Aug 19 '16 at 17:04
  • Ok I will try. I never understood try catch xD –  Aug 19 '16 at 17:14
  • 08-19 18:17:55.914 1712-1771/com.example.tiago.java_android E/art: Throwing OutOfMemoryError "Failed to allocate a 21822808 byte allocation with 33554432 free bytes and 52MB until OOM" 08-19 18:17:56.654 1712-1712/com.example.tiago.java_android E/AndroidRuntime: FATAL EXCEPTION: main –  Aug 19 '16 at 17:18
  • Okay my last try:D Lets put the master_bitmap declaration to the method again. I hope this is not a 4K image you are trying to transfer. try { Bitmap master_bitmap; master_bitmap=BitmapFactory.decodeByteArray(decodedString, 0, ‌​decodedString.‌​leng‌​th); if (master_bitmap != null) { try { master_frame.setImageBitmap(master_bitmap); master_bitmap.recycle(); } catch(RuntimeException e) { e.printStackTrace(); } } } catch (IllegalArgumentException e) { e.printStackTrace(); } –  Aug 19 '16 at 17:24
  • It worked! But Still extreme lag and it runs out of memory eventually. Many I need someway to remove previous frames from memory? –  Aug 19 '16 at 17:36
  • 08-19 18:34:34.064 15718-15768/com.example.tiago.java_android E/art: Throwing OutOfMemoryError "Failed to allocate a 23431158 byte allocation with 33554432 free bytes and 37MB until OOM" 08-19 18:34:41.354 15718-15768/com.example.tiago.java_android E/art: Throwing OutOfMemoryError "Failed to allocate a 31857536 byte allocation with 33554432 free bytes and 56MB until OOM" 08-19 18:34:42.024 15718-15768/com.example.tiago.java_android –  Aug 19 '16 at 17:36
  • As fas as I understand, you are updating the master_frame only. It shouldn't be saving previous frames to the memory. There is only one frame, master_frame, and its value is just being updated. –  Aug 19 '16 at 17:38
  • Yeah. I have no idea why it runs out of memory. –  Aug 19 '16 at 17:40
  • I think I understood one second. I will write an answer with several codes and try all of them to see which one works the best. –  Aug 19 '16 at 17:43
  • It also starts to corrupt the other valores[0-25] that I have with the string64 data. Something is not right. How can a simple image lag a socket so much? –  Aug 19 '16 at 17:44
  • i did. if this doesn't work either, you have to try variations of what I suggested so far. –  Aug 19 '16 at 17:56
  • It doesnt give me any error. But I dont get image now. java.lang.NullPointerException: Attempt to invoke virtual method 'android.graphics.Bitmap android.graphics.drawable.BitmapDrawable.getBitmap()' on a null object reference –  Aug 19 '16 at 18:02
  • bad base64 again. I dont see any solution to this. Somehow I think the scanner.readLine is not the best to read here. Maybe there are \n somewhere in the string and doesnt read all the data. Sometimes the string64 data also appears on the other values[0-25] so I guess something is wrong with the reading. –  Aug 19 '16 at 18:17
  • But I dont understand how the first frame is always read well and then it says bad base64 on the second frame. –  Aug 19 '16 at 18:18
  • Thats why I asked "You are sure values[26] always has the right data?". What a waste! Anyway. –  Aug 19 '16 at 18:18
  • It received well the first frame and not the second? That doesnt make sence. –  Aug 19 '16 at 18:21