pedroSG94 / RootEncoder

RootEncoder for Android (rtmp-rtsp-stream-client-java) is a stream encoder to push video/audio to media servers using protocols RTMP, RTSP, SRT and UDP with all code written in Java/Kotlin
Apache License 2.0
2.56k stars 773 forks source link

am I missing some thing? While adding library #1578

Closed kishorpise closed 3 weeks ago

kishorpise commented 1 month ago

Hello, Please see the below error.

image

and

image

Let me know how can I resolve this issue ? instead of compiling

pedroSG94 commented 1 month ago

Hello,

Did you add jitpack maven repository to your project?

kishorpise commented 1 month ago

Yes, I have added - here is my setting. image

Then I downloaded code and compiled to produce the aar files at my end. I copied these files to lib folder-

image

Then I added libraries like this -

image

I am not sure on how to get the Connection Checker object.

image

Looks like some thing is wrong.

pedroSG94 commented 1 month ago

Hello,

ConnectChecker is an interface that provide you stream events.

You have examples in the app of the repository

kishorpise commented 1 month ago

Correct, I can see the interface in source code, but its not getting exposed, here is snapshot from the android studio. image

I just want to play rtsp stream from camera. is any library missing or some name spaces are wrongly placed. my code is java and library is in Kotlin. not sure how to resolve.

pedroSG94 commented 1 month ago

Hello,

I think that you should focus on resolve the problem compiling with cradle instead of compile .aar directly. Can you show me all your grade files using the lines recommended in the readme?

kishorpise commented 1 month ago

My entire gradle file is below.

`plugins { id 'com.android.application' }

android { namespace 'com.test' compileSdk 34

defaultConfig {
    applicationId "com.test"
    minSdk 22
    targetSdk 34
    versionCode 1
    versionName "1.0"
}

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}
compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}
buildFeatures {
    viewBinding true
}

}

dependencies { implementation 'androidx.appcompat:appcompat:1.7.0' implementation 'com.google.android.material:material:1.12.0' implementation fileTree(dir: 'libs', include: ['.aar', '.jar'], exclude: [])

}`

I have used approach to compile and put .aar files as com.github.pedro***** is not searchable or found online. please refer first screen shot of this issue.

pedroSG94 commented 1 month ago

Hello,

I checked the gradle url and it is available online so I think that the problem is related with your config. Did you tried with the last Android studio version and a clean app?

kishorpise commented 1 month ago

Finally I am able to compile as below. I downloaded new android studio. Created fresh new project. and below is code.. which is crashing -

`<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rlContainer" android:layout_width="match_parent" android:layout_height="match_parent">

<com.pedro.library.view.OpenGlView
    android:id="@+id/surfaceView"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

</com.pedro.library.view.OpenGlView>

`

and in code

private RtspCamera1 rtspCamera1; private OpenGlView openGlView;

Here is method

` private void LoadCamera() {

    rtspCamera1 = new RtspCamera1(openGlView, new ConnectCheckerEvent() {
        @Override
        public void onStreamEvent(StreamEvent event, String message) {

        }
    });

rtspCamera1.prepareVideo(); rtspCamera1.startStream("rtsp://10.0.0.134:554/11");

}`

This device is api level 19 - old. Any help or guidance is appreciated. Error is - Caused by: java.lang.NullPointerException: getSurfaceTexture(...) must not be null

pedroSG94 commented 1 month ago

Hello,

You need wait until the OpenGlView is ready before call startStream:

    openGlView.getHolder().addCallback(new SurfaceHolder.Callback() {
      @Override
      public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {

      }

      @Override
      public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {
        //openGlView is ready, you can call, startPreview, startStream or startRecord now
        if (rtspCamera1.prepareVideo() && rtspCamera1.prepareAudio()) {
          rtspCamera1.startStream("rtsp://10.0.0.134:554/11");
        }
      }

      @Override
      public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {

      }
    });
kishorpise commented 1 month ago

Here is my error ... Fail to connect to camera service.

My entire class is here. I guess I need to write some service class as given in example. however its in kotlin. is there any java version ?

I am also looking for authentication method as not all cameras have direct access they have user and pass. Once This is running, I will share entire code on GH for some one to refer as java sample.

` private void LoadCamera() {

    rtspCamera1 = new RtspCamera1(openGlView, new ConnectCheckerEvent() {
        @Override
        public void onStreamEvent(StreamEvent event, String message) {
            if (event ==StreamEvent.CONNECTED){
                Toast.makeText(MainActivity.this, "Connected ", Toast.LENGTH_SHORT).show();
            }
            if (event ==StreamEvent.DISCONNECTED){
                Toast.makeText(MainActivity.this, "Connected ", Toast.LENGTH_SHORT).show();
            }

            if (event ==StreamEvent.AUTH_ERROR){
                Toast.makeText(MainActivity.this, "DISCONNECTED ", Toast.LENGTH_SHORT).show();
            }

            if (event ==StreamEvent.AUTH_SUCCESS){
                Toast.makeText(MainActivity.this, "AUTH_SUCCESS ", Toast.LENGTH_SHORT).show();
            }
            if (event ==StreamEvent.FAILED){
                Toast.makeText(MainActivity.this, "FAILED ", Toast.LENGTH_SHORT).show();
            }

            if (event ==StreamEvent.STARTED){
                Toast.makeText(MainActivity.this, "STARTED ", Toast.LENGTH_SHORT).show();
            }

        }
    });

    rtspCamera1.prepareVideo();

    openGlView.getHolder().addCallback(new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {

        }

        @Override
        public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {
            //openGlView is ready, you can call, startPreview, startStream or startRecord now
            if (rtspCamera1.prepareVideo() && rtspCamera1.prepareAudio()) {

                rtspCamera1.startStream("rtsp://10.0.0.134:554/11");
            }
        }

        @Override
        public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {

        }
    });

}

`

pedroSG94 commented 1 month ago

Fail to connect to camera service

You need request and accept camera and microphone permissions before use the library.

kishorpise commented 1 month ago

I made code modifications as below.

1) Device API 19. Permissions are not required. So code modified as -

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { checkPermissions(); } else { LoadCamera(); }

and the entire code as below -

` private void checkPermissions() {

    if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, android.Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {

        requestPermissions(new String[]{android.Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}, PERMISSION_REQUEST_CODE);
    } else {
        LoadCamera();
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode
            == PERMISSION_REQUEST_CODE) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
            LoadCamera();
        } else {

            Toast.makeText(this, "Camera and microphone permissions denied", Toast.LENGTH_SHORT).show();
        }
    }
}

private void LoadCamera() {

    rtspCamera1 = new RtspCamera1(openGlView, new ConnectCheckerEvent() {
        @Override
        public void onStreamEvent(StreamEvent event, String message) {
            if (event == StreamEvent.CONNECTED) {
                Toast.makeText(MainActivity.this, "Connected ", Toast.LENGTH_SHORT).show();
            }
            if (event == StreamEvent.DISCONNECTED) {
                Toast.makeText(MainActivity.this, "Connected ", Toast.LENGTH_SHORT).show();
            }

            if (event == StreamEvent.AUTH_ERROR) {
                Toast.makeText(MainActivity.this, "DISCONNECTED ", Toast.LENGTH_SHORT).show();
            }

            if (event == StreamEvent.AUTH_SUCCESS) {
                Toast.makeText(MainActivity.this, "AUTH_SUCCESS ", Toast.LENGTH_SHORT).show();
            }
            if (event == StreamEvent.FAILED) {
                Toast.makeText(MainActivity.this, "FAILED ", Toast.LENGTH_SHORT).show();
            }

            if (event == StreamEvent.STARTED) {
                Toast.makeText(MainActivity.this, "STARTED ", Toast.LENGTH_SHORT).show();
            }

        }
    });

    rtspCamera1.prepareVideo();

    openGlView.getHolder().addCallback(new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {

        }

        @Override
        public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {
            //openGlView is ready, you can call, startPreview, startStream or startRecord now
            if (rtspCamera1.prepareVideo() && rtspCamera1.prepareAudio()) {

                 rtspCamera1.startStream("rtsp://10.0.0.134:554/11");
               // rtspCamera1.startStream("rtsp://10.0.0.245:1935/");
            }
        }

        @Override
        public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {

        }
    });

}`

log cat - Below errors reported -

Could not find method com.viewer.MainActivity.requestPermissions, referenced from method com.viewer.MainActivity.checkPermissions

Could not find method androidx.core.app.ComponentActivity.onMultiWindowModeChanged, referenced from method androidx.activity.ComponentActivity.onMultiWindowModeChanged

Looks like there is some issue with the androidx. This sample project is api 19 and looks like you have some references in library for androidx. Will do research tomorrow as this is late.

pedroSG94 commented 1 month ago

You don't need request permissions until API 23+ but you still need declare permissions in the manifest. About the not found error, you need make sure that you have androidx dependencies declared (In this case appcompact library) and make your activity extends from AppCompactActivity instead of Activity.

kishorpise commented 1 month ago

Unfortunately, It does not work.

Here is manifest.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <uses-sdk android:minSdkVersion="19" />
    <uses-feature
        android:name="android.hardware.camera"
        android:required="false" />

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA"/>
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <application

Here is code after change -

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.widget.Toast;

import androidx.activity.EdgeToEdge;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;

import androidx.activity.ComponentActivity;

import com.pedro.common.ConnectCheckerEvent;
import com.pedro.common.StreamEvent;
import com.pedro.library.rtsp.RtspCamera1;
import com.pedro.library.view.OpenGlView;

public class MainActivity extends AppCompatActivity {
    private static final int PERMISSION_REQUEST_CODE = 100;
    private RtspCamera1 rtspCamera1;
    private OpenGlView openGlView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
        openGlView = findViewById(R.id.surfaceView);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            checkPermissions();
        } else {
            LoadCamera();
        }
    }

    private void checkPermissions() {

        if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, android.Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {

            requestPermissions(new String[]{android.Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}, PERMISSION_REQUEST_CODE);
        } else {
            LoadCamera();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode
                == PERMISSION_REQUEST_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
                LoadCamera();
            } else {

                Toast.makeText(this, "Camera and microphone permissions denied", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void LoadCamera() {

        rtspCamera1 = new RtspCamera1(openGlView, new ConnectCheckerEvent() {
            @Override
            public void onStreamEvent(StreamEvent event, String message) {
                if (event == StreamEvent.CONNECTED) {
                    Toast.makeText(MainActivity.this, "Connected ", Toast.LENGTH_SHORT).show();
                }
                if (event == StreamEvent.DISCONNECTED) {
                    Toast.makeText(MainActivity.this, "Connected ", Toast.LENGTH_SHORT).show();
                }

                if (event == StreamEvent.AUTH_ERROR) {
                    Toast.makeText(MainActivity.this, "DISCONNECTED ", Toast.LENGTH_SHORT).show();
                }

                if (event == StreamEvent.AUTH_SUCCESS) {
                    Toast.makeText(MainActivity.this, "AUTH_SUCCESS ", Toast.LENGTH_SHORT).show();
                }
                if (event == StreamEvent.FAILED) {
                    Toast.makeText(MainActivity.this, "FAILED ", Toast.LENGTH_SHORT).show();
                }

                if (event == StreamEvent.STARTED) {
                    Toast.makeText(MainActivity.this, "STARTED ", Toast.LENGTH_SHORT).show();
                }

            }
        });

        rtspCamera1.prepareVideo();

        openGlView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {

            }

            @Override
            public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {
                //openGlView is ready, you can call, startPreview, startStream or startRecord now
                if (rtspCamera1.prepareVideo() && rtspCamera1.prepareAudio()) {

                  //   rtspCamera1.startStream("rtsp://10.0.0.134:554/11");
                    rtspCamera1.startStream("rtsp://10.0.0.245:1935/");
                }
            }

            @Override
            public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {

            }
        });

    }

}
pedroSG94 commented 1 month ago

Your code fixed to works. The problem was that you declare the openglview callbacks after that the event is called, you should declare it in the onCreate method to handle it correctly:

public class MainActivity extends AppCompatActivity {
  private static final int PERMISSION_REQUEST_CODE = 100;
  private RtspCamera1 rtspCamera1;
  private OpenGlView openGlView;

  private final String[] permissions = new String[] {
      Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA
  };

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    EdgeToEdge.enable(this);
    setContentView(R.layout.activity_main);
    openGlView = findViewById(R.id.surfaceView);
    loadCamera();
  }

  @Override
  public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == PERMISSION_REQUEST_CODE) {
      if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
        startStream();
      } else {
        Toast.makeText(this, "Camera and microphone permissions denied", Toast.LENGTH_SHORT).show();
      }
    }
  }

  private void startStream() {
    if (rtspCamera1.prepareVideo() && rtspCamera1.prepareAudio()) {
      rtspCamera1.startStream("rtsp://10.0.0.245:1935/");
    }
  }

  private void loadCamera() {
    rtspCamera1 = new RtspCamera1(openGlView, new ConnectCheckerEvent() {
      @Override
      public void onStreamEvent(StreamEvent event, String message) {
        if (event == StreamEvent.CONNECTED) {
          Toast.makeText(MainActivity.this, "Connected ", Toast.LENGTH_SHORT).show();
        }
        if (event == StreamEvent.DISCONNECTED) {
          Toast.makeText(MainActivity.this, "Connected ", Toast.LENGTH_SHORT).show();
        }

        if (event == StreamEvent.AUTH_ERROR) {
          Toast.makeText(MainActivity.this, "DISCONNECTED ", Toast.LENGTH_SHORT).show();
        }

        if (event == StreamEvent.AUTH_SUCCESS) {
          Toast.makeText(MainActivity.this, "AUTH_SUCCESS ", Toast.LENGTH_SHORT).show();
        }
        if (event == StreamEvent.FAILED) {
          Toast.makeText(MainActivity.this, "FAILED ", Toast.LENGTH_SHORT).show();
        }

        if (event == StreamEvent.STARTED) {
          Toast.makeText(MainActivity.this, "STARTED ", Toast.LENGTH_SHORT).show();
        }

      }
    });
    openGlView.getHolder().addCallback(new SurfaceHolder.Callback() {
      @Override
      public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {

      }

      @Override
      public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {
        //openGlView is ready, you can call, startPreview, startStream or startRecord now
        ActivityCompat.requestPermissions(MainActivity.this, permissions, PERMISSION_REQUEST_CODE);
      }

      @Override
      public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {

      }
    });

  }

}

This code is not ideal because you are not closing the camera or handle the activity lifecycle correctly. Please check this code to know how to do it correctly. The only difference is that this class use a TextureView to suport device with API 16+. You can continue using OpenGlView: https://github.com/pedroSG94/RootEncoder/blob/master/app/src/main/java/com/pedro/streamer/oldapi/OldApiActivity.kt

pedroSG94 commented 1 month ago

This issue will be moved to discussion tomorrow because it is only a question

kishorpise commented 1 month ago

I have copied exact code provided as above. Still does not work, but now application does not crash. It shows local camera instead of remote camera. Tested multiple camera address.

Error reported - Error configure stream, announce failed

Here is truncated logcat - output

`VideoEncoder com.viewer I prepared MicrophoneManager com.viewer I Microphone created, 32000hz, Stereo 2024-09-17 16:57:48.823 29704-29704 AudioEncoder com.viewer I 2 encoders found 2024-09-17 16:57:48.824 29704-29704 AudioEncoder com.viewer I Encoder selected c2.android.aac.encoder SurfaceManager com.viewer E GL already released

libc com.viewer W Access denied finding property "vendor.mali.platform.config" 2024-09-17 16:57:48.958 29704-29849 libc com.viewer W Access denied finding property "vendor.mali.debug.config" SurfaceManager com.viewer E GL already released CommandsManager com.viewer I OPTIONS rtsp://10.0.0.134:554/11 RTSP/1.0

CommandsManager com.viewer I RTSP/1.0 200 OK CSeq: 1 Server: Hipcam RealServer/V1.0 Public: OPTIONS,DESCRIBE,SETUP,TEARDOWN,PLAY,SET_PARAMETER,GET_PARAMETER 2024-09-17 16:57:49.995 29704-29893 CommandsManager com.viewer I ANNOUNCE rtsp://10.0.0.134:554/11 RTSP/1.0 Content-Type: application/sdp CSeq: 2 Content-Length: 447

                                                                                                v=0
                                                                                                o=- 0 0 IN IP4 127.0.0.1
                                                                                                s=Unnamed
                                                                                                i=N/A
                                                                                                c=IN IP4 10.0.0.134
                                                                                                t=0 0
                                                                                                a=recvonly
                                                                                                m=video 0 RTP/AVP 96
                                                                                                a=rtpmap:96 H264/90000
                                                                                                a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z0LAH42NUFAek1BgEGQAAAMABAAAAwDyPCIRqA==,aM48gA==
                                                                                                a=control:streamid=0
                                                                                                m=audio 0 RTP/AVP 97
                                                                                                a=rtpmap:97 MPEG4-GENERIC/32000/2
                                                                                                a=fmtp:97 profile-level-id=1; mode=AAC-hbr; config=1290; sizelength=13; indexlength=3; indexdeltalength=3
                                                                                                a=control:streamid=1

2024-09-17 16:57:50.093 29704-29893 CommandsManager com.viewer I RTSP/1.0 400 Bad Request CSeq: 1 Server: Hipcam RealServer/V1.0

`

pedroSG94 commented 1 month ago

Hello,

Yes, that is the expected.

This library is used to send video/audio to a media server as you can see in the readme. Not to receive data from an IP camera.

If you want to reproduce an IP camera try with VLC or exoplayer