Hello Tello Pilot!
Join our DJI Tello community & remove this banner.
Sign up

Help with video stream in Android

Harshith

Member
Joined
Aug 6, 2020
Messages
7
Reaction score
0
Location
India
I just want to solve a small problem which is troubling me.
I'm getting the bytes, and also rendering it onto the surface.
Please look at this video:
As you can see, I'm getting only the upper part of the stream as desired and also only if I move my Tello continuously.
Can anyone help me with this please.
My source code:
Java:
package Hello.Tello;

import android.app.Activity;
import android.app.*;
import android.os.*;
import android.view.*;
import android.view.View.*;
import android.widget.*;
import android.content.*;
import android.content.res.*;
import android.graphics.*;
import android.graphics.drawable.*;
import android.media.*;
import android.net.*;
import android.text.*;
import android.text.style.*;
import android.util.*;
import android.webkit.*;
import android.animation.*;
import android.view.animation.*;
import java.util.*;
import java.util.regex.*;
import java.text.*;
import org.json.*;
import android.widget.LinearLayout;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.DialogFragment;
import java.net.*;
import java.io.*;
import java.nio.ByteBuffer;

public class MainActivity extends  Activity {
  
  
    private  MediaCodec m_codec;
    private  DecodeFramesTask m_frameTask;
    private  H264Provider provider;
    private  InetAddress mainIp;
  
    private LinearLayout linear1;
    private TextureView m_surface;
    @Override
    protected void onCreate(Bundle _savedInstanceState) {
        super.onCreate(_savedInstanceState);
        setContentView(R.layout.main);
        initialize(_savedInstanceState);
        initializeLogic();
    }
  
    private void initialize(Bundle _savedInstanceState) {
      
        linear1 = (LinearLayout) findViewById(R.id.linear1);
        m_surface = (TextureView) findViewById(R.id.m_surface);
    }
  
    private void initializeLogic() {
        try{
                mainIp = InetAddress.getByName("192.168.10.1");
        }catch(Exception e){}
        _extra();
        m_surface.setSurfaceTextureListener(new TextureView.SurfaceTextureListener(){
                public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
                        provider = new H264Provider();
                        provider.execute();
                        MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 480, 360);
                        format.setByteBuffer("csd-0", ByteBuffer.wrap(provider.csd0));
                        format.setByteBuffer("csd-1", ByteBuffer.wrap(provider.csd1));
                        format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 960*720);
                        try {
                                m_codec = MediaCodec.createDecoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);
                                m_codec.configure(format, new Surface(m_surface.getSurfaceTexture()), null, 0);
                                m_codec.start();
                                m_frameTask = new DecodeFramesTask();
                                m_frameTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
                            }catch(Exception e){
                                Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
                            }
                }
              
                public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
                }
              
                public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
                        return false;
                }
              
                public void onSurfaceTextureUpdated(SurfaceTexture surface) {
                }
        });
    }
  
    @Override
    protected void onActivityResult(int _requestCode, int _resultCode, Intent _data) {
      
        super.onActivityResult(_requestCode, _resultCode, _data);
      
        switch (_requestCode) {
          
            default:
            break;
        }
    }
  
    public void _extra () {
        new Thread(new Runnable(){
                @Override
                public void run(){
                        try{
                                DatagramSocket socket = new DatagramSocket(8889);
                                DatagramPacket packet1 = new DatagramPacket("command".getBytes(), "command".getBytes().length, mainIp, 8889);
                                DatagramPacket packet2 = new DatagramPacket("streamon".getBytes(), "streamon".getBytes().length, mainIp, 8889);
                                socket.send(packet1);
                                socket.send(packet2);
                            }catch(Exception e){Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();}
                    }
        }).start();
    }
  
    private class DecodeFramesTask extends AsyncTask<String, String, String> {
            @Override
            protected String doInBackground(String... data) {
                    while(!isCancelled()) {
                            byte[] frame = provider.nextFrame();
                            int inputIndex = m_codec.dequeueInputBuffer(-1);
                            if(inputIndex>=0) {
                                    ByteBuffer buffer = m_codec.getInputBuffer(inputIndex);
                                    buffer.put(frame);
                                    m_codec.queueInputBuffer(inputIndex, 0, frame.length, 0, 0);
                            }
                          
                            MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
                            int outputIndex = m_codec.dequeueOutputBuffer(info, 0);
                            if (outputIndex >= 0) {
                                    m_codec.releaseOutputBuffer(outputIndex, true);
                            }
                    }
                    return "";
            }
    }
  
    private class H264Provider extends AsyncTask<String, String, String> {
            public byte[] frame = new byte[960*720];
            private DatagramSocket socket;
            private InetSocketAddress address;
            public byte[] csd0 = {0, 0, 0, 1, 103, 66, 0, 42, (byte) 149, (byte) 168, 30, 0, (byte) 137, (byte) 249, 102, (byte) 224, 32, 32, 32, 64};
            public byte[] csd1 = {0, 0, 0, 1, 104, (byte) 206, 60, (byte) 128, 0, 0, 0, 1, 6, (byte) 229, 1, (byte) 151, (byte) 128};
          
            public H264Provider(){
                    try{
                            socket = new DatagramSocket(11111);
                    }catch(Exception e){Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();}
            }
          
            @Override
            protected String doInBackground(String... data) {
                    while(!isCancelled()) {
                            DatagramPacket packet = new DatagramPacket(frame, frame.length);
                            try{
                                    socket.receive(packet);
                            }catch(Exception e){Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();}
                            frame = packet.getData();
                    }
                    return "";
            }
          
            public byte[] nextFrame(){
                    return frame;
            }
          
            public void release(){
                    m_codec.stop();
                    m_codec.release();
                    socket.close();
                    m_frameTask.cancel(true);
                    this.cancel(true);
            }
    }
  
  
  
    @Deprecated
    public void showMessage(String _s) {
        Toast.makeText(getApplicationContext(), _s, Toast.LENGTH_SHORT).show();
    }
  
    @Deprecated
    public int getLocationX(View _v) {
        int _location[] = new int[2];
        _v.getLocationInWindow(_location);
        return _location[0];
    }
  
    @Deprecated
    public int getLocationY(View _v) {
        int _location[] = new int[2];
        _v.getLocationInWindow(_location);
        return _location[1];
    }
  
    @Deprecated
    public int getRandom(int _min, int _max) {
        Random random = new Random();
        return random.nextInt(_max - _min + 1) + _min;
    }
  
    @Deprecated
    public ArrayList<Double> getCheckedItemPositionsToArray(ListView _list) {
        ArrayList<Double> _result = new ArrayList<Double>();
        SparseBooleanArray _arr = _list.getCheckedItemPositions();
        for (int _iIdx = 0; _iIdx < _arr.size(); _iIdx++) {
            if (_arr.valueAt(_iIdx))
            _result.add((double)_arr.keyAt(_iIdx));
        }
        return _result;
    }
  
    @Deprecated
    public float getDip(int _input){
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, _input, getResources().getDisplayMetrics());
    }
  
    @Deprecated
    public int getDisplayWidthPixels(){
        return getResources().getDisplayMetrics().widthPixels;
    }
  
    @Deprecated
    public int getDisplayHeightPixels(){
        return getResources().getDisplayMetrics().heightPixels;
    }
  
}

Please don't care about extras. Only H264Provider task, DecodeFramesTask and initializeLogic() are the part of video streaming. Please help me with this.
Thankyou
Please note: I'm 15 years and I'm still learning.
 
Last edited:
Ive figured out that I'm not combining the slices into the frame. I'm just rendering the slices ?. But ive tried combining the frames, but now the app has been crashing. Can someone give a more detailed information regarding the video stream?

Thanks
Harshith
 

Members online

No members online now.

Forum statistics

Threads
5,696
Messages
39,955
Members
17,054
Latest member
Soccer843