Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DJI SDK LiveStreamManager -3 Error: Failed to Start Stream #1329

Open
George2397 opened this issue Nov 2, 2024 · 3 comments
Open

DJI SDK LiveStreamManager -3 Error: Failed to Start Stream #1329

George2397 opened this issue Nov 2, 2024 · 3 comments

Comments

@George2397
Copy link

George2397 commented Nov 2, 2024

Hi all,

I'm working on a project using the DJI Mobile SDK V4 to stream live video from a drone to an RTMP server. Despite receiving video data consistently, I get a -3 error when trying to start the live stream via LiveStreamManager.startStream().

What I tried:

  • I verified that video data is indeed being received from the drone.
  • My RTMP server works because I tried streaming my mobile's camera feed.
  • I enabled encoding with setVideoEncodingEnabled(true).

Below are the key parts of my code. The VideoFeedView is taken from the sample code

1. Drone Live Stream Manager

class DroneLiveStreamManager(private val primaryVideoFeedView: VideoFeedView) {

        private val maxRetries = 10
        private val retryDelay = 1000L // 1 second delay for retrying

        // Initialize and set up the live stream manager
        fun initLiveStream(retryCount: Int = 0) {
            if (DJISDKManager.getInstance().getLiveStreamManager() == null) {
                if (retryCount < maxRetries) {
                    Log.w(TAG, "LiveStreamManager is not available yet, retrying in ${retryDelay / 1000} seconds...")
                    Handler(Looper.getMainLooper()).postDelayed({
                        initLiveStream(retryCount + 1) // Retry after delay
                    }, retryDelay)
                } else {
                    Log.e(TAG, "LiveStreamManager initialization failed after multiple retries.")
                }
                return
            }

            // Proceed with initialization once LiveStreamManager is available
            primaryVideoFeedView.registerLiveVideo(VideoFeeder.getInstance().primaryVideoFeed, true)


            DJISDKManager.getInstance().getLiveStreamManager().setVideoEncodingEnabled(true)
            DJISDKManager.getInstance().getLiveStreamManager().setVideoSource(LiveStreamManager.LiveStreamVideoSource.Primary)
            DJISDKManager.getInstance().getLiveStreamManager().addLiveErrorStatusListener { errorCode, errorMessage ->
                Log.d(TAG, "Streaming error: Code $errorCode, Message: $errorMessage")
            }

            DJISDKManager.getInstance().getLiveStreamManager().registerListener(object : LiveStreamManager.OnLiveChangeListener {
                override fun onStatusChanged(status: Int) {
                    Log.d(TAG, "Live stream status changed: $status")
                }
            })

            Log.d(TAG, "Live stream manager initialized with RTMP URL.")
        }

        fun startLiveStream() {

            if (DJISDKManager.getInstance().getLiveStreamManager()?.isStreaming == false) {
                Thread {
                    // Set the live URL immediately before starting the stream
                    DJISDKManager.getInstance().getLiveStreamManager().setLiveUrl("rtmp://192.168.0.32:1935/live/test")
                    val result = DJISDKManager.getInstance().getLiveStreamManager().startStream()
                    DJISDKManager.getInstance().getLiveStreamManager().setStartTime()
                    Log.d(TAG, "startStream result: $result")
                    if (result == 0) {
                        Log.d(TAG, "Stream started successfully")
                    } else {
                        Log.e(TAG, "Failed to start stream, error code: $result")
                    }
                }.start()
            } else {
                Log.d(TAG, "Stream already active or LiveStreamManager not available")
            }
        }


        fun stopLiveStream() {
            val liveStreamManager = DJISDKManager.getInstance().liveStreamManager
            if (liveStreamManager?.isStreaming == true) {
                liveStreamManager.stopStream()
                Log.d(TAG, "Stopped live stream")
            } else {
                Log.d(TAG, "Stream is not active or LiveStreamManager not available")
            }
        }
    }

2. Initializing Live Stream Manager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        Log.d(TAG, "MainActivity created")

        // Initialize the handler
        mHandler = Handler(Looper.getMainLooper())

        // Initialize videoFeedView after setting the content view
        videoFeedView = findViewById(R.id.video_feed_view)

        // Initialize the DroneLiveStreamManager
        droneLiveStreamManager = DroneLiveStreamManager(videoFeedView)

        // Check and request permissions if necessary
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            checkAndRequestPermissions()
        }

        // Call the dialog to prompt the user for Simulation or Normal Mode
        showModeSelectionDialog()
    }

3. Calling the StartLiveStream()

    private fun showModeSelectionDialog() {
        val builder = AlertDialog.Builder(this)
        builder.setTitle("Select Mode")
        builder.setMessage("Do you want to use Simulation Mode or Normal Mode?")

        builder.setPositiveButton("Simulation Mode") { _, _ ->
            Log.d(TAG, "User selected Simulation Mode")
            // Start the live stream
            droneLiveStreamManager.startLiveStream()
        }

        builder.setNegativeButton("Normal Mode") { _, _ ->
            Log.d(TAG, "User selected Normal Mode")
            showToast("Normal Mode selected. Attempting to connect to GPS if available.")
            // Start the live stream
            droneLiveStreamManager.startLiveStream()
        }

        builder.setCancelable(false)
        builder.show()
    }

4. Error I get:
Failed to start stream, error code: -3

@dji-dev
Copy link
Contributor

dji-dev commented Nov 4, 2024

Agent comment from yating.liao in Zendesk ticket #120889:

It appears that initLiveStream has not been utilized. The -3 often indicates that the corresponding screen is not displayed on the current page.
https://sdk-forum.dji.net/hc/en-us/articles/360046826494

°°°

@George2397
Copy link
Author

Thank you for your response!

On the link you sent me, it says that I should use DJICodecManager to decode. This is already used though by the VIdeoFeedView which I copied and pasted on my project.

Here is the link of my project: https://github.com/George2397/drone_telemetry_android

Regarding the initLiveStream, I forgot to paste the code that calls this.

                override fun onProductConnect(product: BaseProduct?) {
                    Log.d(TAG, "onProductConnect called with product: $product")
                    if (product != null) {
                        Log.d(TAG, "Connected product model: ${product.model}")
                        // Initialize live stream manager after product is connected
                        droneLiveStreamManager.initLiveStream()
                    } else {
                        Log.w(TAG, "No product detected on connection.")
                    }
                    showToast("Remote Controller Connected")
                    notifyStatusChange()
                }

And here is the link to the file: https://github.com/George2397/drone_telemetry_android/blob/main/app/src/main/java/com/example/sample/MainActivity.kt

@dji-dev
Copy link
Contributor

dji-dev commented Nov 5, 2024

Agent comment from yating.liao in Zendesk ticket #120889:

I think you can retrieve the LiveStreamManager in the onComponentChange function. The onComponentChange will callback the component information when the camera and flight control components are detected. At this point, you should complete primaryVideoFeedView.registerLiveVideo. It's important to note that the live stream can only be started after the camera feed is displayed on primaryVideoFeedView.

Currently, I haven't found any obvious logical errors in the code you provided, but executing primaryVideoFeedView.registerLiveVideo in onProductConnect might cause the camera feed to not display correctly.

°°°

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants