RootEncoder icon indicating copy to clipboard operation
RootEncoder copied to clipboard

java.lang.NullPointerException: getSurface(...) must not be null

Open orzlenmo opened this issue 1 year ago • 22 comments

When I use GenericFromFile and push local files, I get java.lang.NullPointerException: getSurface(...) must not be null I can confirm that I have implemented the method according to the steps in the document, surfaceView = OpenGlView(context!!) bindingFloatWindow?.frameSurfaceView?.addView(surfaceView) genericFromFile = GenericFromFile(openGlView, this, this, this) It sometimes works, but sometimes it doesn't, and the above error will appear

微信截图_20241013114136

orzlenmo avatar Oct 13 '24 03:10 orzlenmo

Hello,

Are you doing the startStream after the preview is inflated like in the example? (Using the onSurfaceChanged callback)

Can you share the code where you are doing startStream?

pedroSG94 avatar Oct 13 '24 06:10 pedroSG94

微信截图_20241013141331

I added a callback but did not do anything. Because my OpenGlView preview interface is on a float window, when I call startstream, the above error is reported directly. Here is the startStream method

微信截图_20241013141744

orzlenmo avatar Oct 13 '24 06:10 orzlenmo

No matter if you are in a float window. You need wait until that callback is called or the surface will be null or invalid. You can try add a delay to start stream but it is not a secure way to do it

pedroSG94 avatar Oct 13 '24 06:10 pedroSG94

I can confirm that my startStream event is executed after surfaceChanged:Surface(name=null)/@0xf77b5a8 has been executed and has a value. Does it have anything to do with the activity where the float is located?

orzlenmo avatar Oct 13 '24 07:10 orzlenmo

I'm not sure about it but that surface is not ready for some reason. Maybe the surface is created, destroyed and re created. You can check if the surface if ready using this:

surfaceView.holder.surface.isValid

Also, remember that if your preview was detroyed and you need use a different preview you need change the preview:

//go to background, no preview available
genericFromFile.replaceView(context)
//the preview object changed, replace preview with the new view
genericFromFile.replaceView(openglView)

I can help you more if you are able to share a full code example.

pedroSG94 avatar Oct 13 '24 07:10 pedroSG94

This is the log I printed. Can you help me analyze it? Thanks to the author 微信截图_20241013151959

orzlenmo avatar Oct 13 '24 07:10 orzlenmo

This is the status judgment when the push starts, showing that it is ready 微信截图_20241013152515

orzlenmo avatar Oct 13 '24 07:10 orzlenmo

I will need a full code example to reproduce the error. Can you share me a minimal code example? You can share it using email if you want: [email protected]

pedroSG94 avatar Oct 13 '24 07:10 pedroSG94

It's not that I don't want to post it, it's that my apk is hooked through xposed. This OpenGlView uses the acitivity environment intercepted by the host app, and then a floating window pops up on it. It has been working fine before, but suddenly the host app has been updated. I used your library to push the stream. All the codes are normal, but this problem occurred when I started pushing the stream. So I want to ask you whether it is related to the opengl environment of the app used.

orzlenmo avatar Oct 14 '24 02:10 orzlenmo

I did a fix for it: https://github.com/pedroSG94/RootEncoder/pull/1604 Try with this commit:

  implementation 'com.github.pedroSG94.RootEncoder:library:fix~opengl-start-SNAPSHOT'

pedroSG94 avatar Oct 14 '24 06:10 pedroSG94

我对此进行了修复: #1604 尝试使用此提交:

  implementation 'com.github.pedroSG94.RootEncoder:library:fix~opengl-start-SNAPSHOT'

I used this version but it still doesn't work. The following two pictures are new errors. Later, I no longer used the previous host activity. I changed an activity to display the OpenGlView on the floating window. Finally, it will not crash. I don't know why some phones crash on which activity. But I really appreciate your answer. 微信截图_20241014152319 微信截图_20241014152328

orzlenmo avatar Oct 14 '24 07:10 orzlenmo

Hello,

Thank you for the report. It is interesting, the library is not able to get shaders resources. Please, help me to solve the error since I'm not able to reproduce it. I added a new commit that could resolve this error:

  implementation 'com.github.pedroSG94.RootEncoder:library:f0b9aa3fcb'

pedroSG94 avatar Oct 14 '24 08:10 pedroSG94

Same error as before 微信截图_20241014174355

orzlenmo avatar Oct 14 '24 09:10 orzlenmo

Do you still have resources not found error like before?

pedroSG94 avatar Oct 14 '24 11:10 pedroSG94

I used it for nearly a year without any problems. Recently, the host app of the xposed hook seemed to have been hot-updated, which started to cause this problem on some models. After I changed the activity, it became normal. So I suggest you ignore this problem, because it is indeed a problem that only occurs with unconventional apps.

orzlenmo avatar Oct 15 '24 01:10 orzlenmo

Hello,

I will ignore this issue until someone find a way to share a code example to reproduce the error. Marked as help wanted

pedroSG94 avatar Oct 17 '24 17:10 pedroSG94

package com.example.test;

import android.os.Bundle; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.widget.Button; import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.pedro.common.ConnectChecker; import com.pedro.encoder.input.sources.video.Camera2Source; import com.pedro.library.generic.GenericStream; import com.pedro.library.util.BitrateAdapter;

import java.util.Locale;

public class MainActivity extends AppCompatActivity implements ConnectChecker {

private SurfaceView surfaceView;
private Button btnStartStop;
private TextView tvStatus;

private final String streamUrl = "rtmp://localhost:1935/live/test";

private GenericStream genericStream;
private BitrateAdapter bitrateAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    surfaceView = findViewById(R.id.surfaceView);
    btnStartStop = findViewById(R.id.btnStartStop);
    tvStatus = findViewById(R.id.tvStatus);

    genericStream = new GenericStream(this, this);
    genericStream.changeVideoSource(new Camera2Source(this));

    bitrateAdapter = new BitrateAdapter(bitrate -> genericStream.setVideoBitrateOnFly(bitrate));
    bitrateAdapter.setMaxBitrate(1200_000 + 128_000); // video + audio max bitrate

    surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            if (!genericStream.isOnPreview()) {
                genericStream.startPreview(surfaceView);
            }
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            genericStream.getGlInterface().setPreviewResolution(width, height);
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            if (genericStream.isOnPreview()) {
                genericStream.stopPreview();
            }
        }
    });

    boolean prepared = genericStream.prepareVideo(640, 480, 1200_000, 0)
            && genericStream.prepareAudio(32000, true, 128_000);
    if (!prepared) {
        tvStatus.setText("Failed to prepare stream");
        btnStartStop.setEnabled(false);
        return;
    }

    btnStartStop.setOnClickListener(v -> {
        if (!genericStream.isStreaming()) {
            genericStream.startStream(streamUrl);
            btnStartStop.setText("Stop Stream");
            tvStatus.setText("Connecting...");
        } else {
            genericStream.stopStream();
            btnStartStop.setText("Start Stream");
            tvStatus.setText("Stream stopped");
        }
    });
}

@Override
public void onConnectionStarted(String url) {
    runOnUiThread(() -> tvStatus.setText("Connection started"));
}

@Override
public void onConnectionSuccess() {
    runOnUiThread(() -> tvStatus.setText("Connected"));
}

@Override
public void onConnectionFailed(String reason) {
    runOnUiThread(() -> {
        tvStatus.setText("Connection failed: " + reason);
        btnStartStop.setText("Start Stream");
    });
    if (genericStream.getStreamClient().reTry(5000, reason, null)) {
        runOnUiThread(() -> tvStatus.setText("Retrying..."));
    } else {
        genericStream.stopStream();
    }
}

@Override
public void onNewBitrate(long bitrate) {
    final float mbps = bitrate / 1_000_000f;
    runOnUiThread(() -> tvStatus.setText(String.format(Locale.getDefault(), "Bitrate: %.2f Mbps", mbps)));
    bitrateAdapter.adaptBitrate(bitrate, genericStream.getStreamClient().hasCongestion());
}

@Override
public void onDisconnect() {
    runOnUiThread(() -> {
        tvStatus.setText("Disconnected");
        btnStartStop.setText("Start Stream");
    });
}

@Override
public void onAuthError() {
    runOnUiThread(() -> {
        tvStatus.setText("Auth error");
        btnStartStop.setText("Start Stream");
    });
    genericStream.stopStream();
}

@Override
public void onAuthSuccess() {
    runOnUiThread(() -> tvStatus.setText("Auth success"));
}

@Override
protected void onDestroy() {
    super.onDestroy();
    genericStream.release();
}

}

Process: com.example.test, PID: 10775 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.test/com.example.test.MainActivity}: java.lang.NullPointerException: getSurfaceTexture(...) must not be null at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3762) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3929) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2284) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:210) at android.os.Looper.loop(Looper.java:299) at android.app.ActivityThread.main(ActivityThread.java:8302) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:556) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1037) Caused by: java.lang.NullPointerException: getSurfaceTexture(...) must not be null at com.pedro.encoder.input.gl.render.MainRender.getSurfaceTexture(MainRender.kt:182) at com.pedro.library.view.GlStreamInterface.getSurfaceTexture(GlStreamInterface.kt:136) at com.pedro.library.base.StreamBase.changeVideoSource(StreamBase.kt:390) at com.example.test.MainActivity.onCreate(MainActivity.java:39) at android.app.Activity.performCreate(Activity.java:8191) at android.app.Activity.performCreate(Activity.java:8159) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1330) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3735) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3929)  at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)  at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)  at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2284) 

fahimfahadleon avatar Jul 11 '25 18:07 fahimfahadleon

Hello,

Thank you for the report, it is a bug introduced in the last release. For now you can do this that is equivalent and works. Replace this:

    genericStream = new GenericStream(this, this);
    genericStream.changeVideoSource(new Camera2Source(this));

To:

    genericStream = new GenericStream(this, this, new Camera2Source(context), new MicrophoneSource());
   //GenericStream class use Camera2Source and MicrophoneSource by default so the above line is equivalent to
   genericStream = new GenericStream(this, this)

pedroSG94 avatar Jul 11 '25 20:07 pedroSG94

Fixed in the last commit: https://github.com/pedroSG94/RootEncoder/commit/a630ee4d79c64b8ce544da17062b6ea317ca6b1b

pedroSG94 avatar Jul 11 '25 20:07 pedroSG94

hello sir. i am doing a project based on this library. i am almost done. i only have two issues remaining. video streaming on and off. just audio will stream when video is off and show a black screen (optional) and one more is skin (face) smoothening filter. can you please help me here?

    public void toggleCamera(){
        if(isCameraOn){
            isCameraOn = false;
            //these lines are declared above
            //        VideoSource videoSource = genericStream.getVideoSource();
            //        if (videoSource instanceof Camera2Source ) {
            //            source = (Camera2Source)videoSource;
            //            source.enableAutoWhiteBalance(CameraCharacteristics.CONTROL_AWB_MODE_DAYLIGHT);
            //            source.enableAutoExposure();
            //            if(source.getCameraFacing() == Facing.BACK){
            //                source.switchCamera();
            //            }
            //        }
            source.stop();
        }else {
            isCameraOn = true;
            source.start(surfaceView.getSurfaceTexture());//java.lang.NullPointerException: getSurfaceTexture(...) must not be null
            source.start(genericStream.getSurfaceTexture());//IllegalStateException: getSurfaceTexture only available with VideoManager.Source.DISABLED
        }
    }  

i am stuck here. also a little advice for the filter maybe. for your information, my whole code is written above. i am using GenericStream.

fahimfahadleon avatar Nov 09 '25 20:11 fahimfahadleon

Hello,

The first one you have 2 ways:

  • Using muteVideo /unmuteVideo method like this:
genericStream.getGlInterface().muteVideo()
  • Using BlackFilterRender:
genericStream.getGlInterface().addFilter(BlackFilterRender())

For the skin filter you have the beauty filter:

genericStream.getGlInterface().addFilter(BeautyFilterRender())

pedroSG94 avatar Nov 10 '25 21:11 pedroSG94

thank you very much sir. you saved my day.

fahimfahadleon avatar Nov 11 '25 07:11 fahimfahadleon