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.45k stars 761 forks source link

Using av1 #1408

Open artemiskot opened 4 months ago

artemiskot commented 4 months ago

Hi pedro! Currently I'am running extended background example as a streaming option with H264 codec. My phone supports AV1 codec and I've seen that now RTSP supports av1 codec. Can I somehow implement av1 codec to my existing code or I should change to other example activity. Because as I see rn I can't use av1 in background activity.

pedroSG94 commented 4 months ago

Hello,

You only need call setVideoCodec method to do it (this is valid with all clases that use RTMP or RTSP stream, no matter if you use camera1, camera2, display or fromfile):

rtspCamera1.setVideoCodec(VideoCodec.AV1);

You need call it before prepareVideo method. If your device can't encode using your prepareVideo parameters or your device hasn't AV1 encoder the prepareVideo method will return false.

Remember that maybe your device can decode AV1 but maybe you can't encode using AV1. Currently AV1 encoding is only mandatory for devices with Android 14+ and in most of cases only software encoder is implemented. In my case, my Pixel 7 only can encode AV1 using software encoder and only to 1080p or less.

Maybe setVideoCodec to VideoCodec.H265 instead of VideoCodec.AV1 is recommended to get a better quality (it is not AV1 but it is better than H264) because it is more extended and supported in almost all devices.

artemiskot commented 4 months ago

I see. So in terms of BackgroundActivity we can call it in that way

  fun prepare(): Boolean {
    genericCamera2.setVideoCodec(VideoCodec.AV1);
    return genericCamera2.prepareVideo() && genericCamera2.prepareAudio()
  }

But in genericCamera2 we got restriction

    @Override
  protected void setVideoCodecImp(VideoCodec codec) {
    if (codec != VideoCodec.H264 && codec != VideoCodec.H265 ) {
      throw new IllegalArgumentException("Unsupported codec: " + codec.name() + ". Generic only support video " + VideoCodec.H264.name() + " and " + VideoCodec.H265.name());
    }
    rtmpClient.setVideoCodec(codec);
    rtspClient.setVideoCodec(codec);
    srtClient.setVideoCodec(codec);
  }

Changing this method like this

    @Override
  protected void setVideoCodecImp(VideoCodec codec) {
    if (codec != VideoCodec.H264 && codec != VideoCodec.H265 ) {
      throw new IllegalArgumentException("Unsupported codec: " + codec.name() + ". Generic only support video " + VideoCodec.H264.name() + " and " + VideoCodec.H265.name());
    }
    rtmpClient.setVideoCodec(codec);
    rtspClient.setVideoCodec(VideoCodec.AV1);
    srtClient.setVideoCodec(codec);
  }

Worked for me, but it seems that we should add if statement to srtClient in case of passing not H264 or H265. Anyway thx for your reply

pedroSG94 commented 4 months ago

Hello,

This is intentional for all generic classes. I did this because you can't set AV1 codec to a protocol that no support that codec. So in case of codecs (audio and video), only codecs supported by all protocol are supported in generic cases. Using AV1, SRT protocol can't use it so it is restricted. It is the same for G711, SRT protocol can't handle it.

Keep in mind that your implementation of that method is configured to use different codecs depend of the stream protocol and this will produce errors depend of the protocol used.

I recommend you use RtspCamera2 if you only want use RTSP protocol to avoid errors