NvDRMRenderer DisplayPort - No suitable encoder

Hello guys,
I’d like to use NvDrmRenderer with DisplayPort. It works with HDMI. The DisplayPort works with other components like GStreamer or console output, but not with NvDRMRenderer.

I get the error: “Unable to find suitable encoder.”

When creating NvDRMRenderer I need to set CRTC and connector. For HDMI it just worked with setting both to 0, but for DisplayPort setting connector to 1, no CRTC seems to be working. How can I display available CRTC so I can see which ones are right or could this be another problem?

Best regards,
jb

Hi,
Are you able to try nvsrmvideosink plugin? Since you mention gstreamer works, not sure if you try with this plugin. You may need to set the properties:

  conn-id             : Sets CONN ID.
                        flags: readable, writable
                        Integer. Range: 0 - 2147483647 Default: 2147483647
  plane-id            : Sets PLANE ID
                        flags: readable, writable
                        Integer. Range: 0 - 2147483647 Default: 2147483647
  set-mode            : Selects whether user wants to choose the default mode which is
                        already set by connector (set_mode = 0) or wants to select the mode
                        of the video stream (set_mode = 1). In the latter case, error is
                        thrown when the input stream resolution does not match with
                        the supported modes of the connector.
                        flags: readable, writable
                        Boolean. Default: false

nvdrmvideosink plugin works on the same hardware setup.
set-mode=0 or set-mode=1 both work with conn-id=1.

Hi,
So we should able to replicate the issue in running 08_video_dec_drm. Please share steps and a command so that we can set up and run the command to reproduce it. And share a working gstreamer command for comparison.

Please also provide your release version( $ head -1 /etc/nv_tegra_release ).

Sorry, it took me so long to reply!

Output of head -1 /etc/nv_tegra_release :

R32 (release), REVISION: 5.0, GCID: 25531747, BOARD: t210ref, EABI: aarch64, DATE: Fri Jan 15 22:55:35 UTC 2021

Working GStreamer pipeline:

gst-launch-1.0 nvarguscamerasrc ! nvdrmvideosink conn-id=1

video_dec_drm example :

./video_dec_drm --disable-video -connector 1

gives me same error:

[ERROR] (NvDrmRenderer.cpp:268) Unable to find suitable encoder

Thank you for your help!

Do you think you can fix this one also? Let me know when you can reproduce it.

Thanks for all your help!
Best regards,
jb

EDIT:
This is my output when I plugin the DisplayPort monitor:

[ +9.482652] tegradc tegradc.1: dp: plug event received
[ +0.000256] hpd: state 3 (Disabled), hpd 1, pending_hpd_evt 1
[ +0.000043] hpd: switching from state 3 (Disabled) to state 0 (Reset)
[ +0.103870] hpd: state 0 (Reset), hpd 1, pending_hpd_evt 0
[ +0.000099] tegradc tegradc.1: blank - powerdown
[ +0.000691] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x200000 did not specify bpp
[ +0.000694] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x200000 did not specify bpp
[ +0.008260] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x200000 did not specify bpp
[ +0.000109] extcon-disp-state extcon:disp-state: cable 44 state 0 already set.
[ +0.000019] Extcon DP: HPD disabled
[ +0.000017] hpd: hpd_switch 0
[ +0.000024] hpd: switching from state 0 (Reset) to state 1 (Check Plug)
[ +0.000049] hpd: state 1 (Check Plug), hpd 1, pending_hpd_evt 0
[ +0.000027] hpd: switching from state 1 (Check Plug) to state 2 (Check EDID)
[ +0.005906] hpd: state 2 (Check EDID), hpd 1, pending_hpd_evt 0
[ +0.017219] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x200000 did not specify bpp
[ +0.000516] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x80 did not specify bpp
[ +0.000521] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x400000 did not specify bpp
[ +0.000511] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x80 did not specify bpp
[ +0.000519] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x0 did not specify bpp
[ +0.000442] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x0 did not specify bpp
[ +0.000753] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x10400000 did not specify bpp
[ +0.000607] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x0 did not specify bpp
[ +0.000613] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x10400000 did not specify bpp
[ +0.000602] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x80 did not specify bpp
[ +0.000606] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x0 did not specify bpp
[ +0.000734] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x80 did not specify bpp
[ +0.000666] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x0 did not specify bpp
[ +0.000626] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x200000 did not specify bpp
[ +0.000595] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x200000 did not specify bpp
[ +0.000595] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x200000 did not specify bpp
[ +0.000586] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x10400000 did not specify bpp
[ +0.000597] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x10400000 did not specify bpp
[ +0.000660] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x10400000 did not specify bpp
[ +0.000632] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x10400000 did not specify bpp
[ +0.000591] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x10400000 did not specify bpp
[ +0.000629] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x10400000 did not specify bpp
[ +0.000591] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x10400000 did not specify bpp
[ +0.000604] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x10400000 did not specify bpp
[ +0.000621] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x10400000 did not specify bpp
[ +0.000653] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x10400000 did not specify bpp
[ +0.000625] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x10400000 did not specify bpp
[ +0.000696] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x400000 did not specify bpp
[ +0.000615] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x10420000 did not specify bpp
[ +0.000638] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x10420000 did not specify bpp
[ +0.000771] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x10420000 did not specify bpp
[ +0.000697] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x10420000 did not specify bpp
[ +0.000657] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x10420000 did not specify bpp
[ +0.000617] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x10420000 did not specify bpp
[ +0.000039] tegradc tegradc.1: blank - powerdown
[ +0.000637] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x200000 did not specify bpp
[ +0.000749] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x200000 did not specify bpp
[ +0.048294] tegradc tegradc.1: unblank
[ +0.030936] tegradc tegradc.1: nominal-pclk:533250000 parent:533250000 div:1.0 pclk:533250000 527917500~581242500
[ +0.001009] tegradc tegradc.1: dp: aux read defer (0x10020000) – 6
[ +0.003023] tegradc tegradc.1: dp: aux read defer (0x10020000) – 6
[ +0.001362] tegradc tegradc.1: tegra_dp_get_bpp: vmode=0x200000 did not specify bpp
[ +0.003810] tegradc tegradc.1: DP: no prod_c_hbr2 prod settings node in device tree
[ +0.003631] tegradc tegradc.1: dp: aux write defer (0x10020000) – 6
[ +0.001663] tegradc tegradc.1: dp: aux write defer (0x10020000) – 6
[ +0.001662] tegradc tegradc.1: dp: aux read defer (0x10020000) – 6
[ +0.002083] tegradc tegradc.1: dp: aux read defer (0x10020000) – 6
[ +0.001750] dp lt: state 4 (link training fail/disable), pending_lt_evt 1
[ +0.000002] dp lt: switching from state 4 (link training fail/disable) to state 0 (Reset)
[ +0.000003] dp lt: state 0 (Reset), pending_lt_evt 0
[ +0.001857] tegradc tegradc.1: DP: no prod_c_hbr2 prod settings node in device tree
[ +0.000142] dp lt: switching from state 0 (Reset) to state 2 (clock recovery)
[ +0.000004] dp lt: state 2 (clock recovery), pending_lt_evt 0
[ +0.000439] tegradc tegradc.1: dp: aux write defer (0x10020000) – 6
[ +0.001251] dp lt: config: lane 0: vs level: 0, pe level: 0, pc2 level: 0
[ +0.000011] dp lt: config: lane 1: vs level: 0, pe level: 0, pc2 level: 0
[ +0.000011] dp lt: config: lane 2: vs level: 0, pe level: 0, pc2 level: 0
[ +0.000010] dp lt: config: lane 3: vs level: 0, pe level: 0, pc2 level: 0
[ +0.000005] dp lt: tx_pu: 0x20
[ +0.000463] tegradc tegradc.1: dp: aux write defer (0x10020000) – 6
[ +0.001241] tegradc tegradc.1: dp: aux write defer (0x10020000) – 5
[ +0.001672] tegradc tegradc.1: dp: aux write defer (0x10020000) – 6
[ +0.001289] tegradc tegradc.1: dp: aux write defer (0x10020000) – 5
[ +0.002757] dp lt: CR not done
[ +0.001337] dp lt: new config: lane 0: vs level: 1, pe level: 0, pc2 level: 0
[ +0.000002] dp lt: new config: lane 1: vs level: 1, pe level: 0, pc2 level: 0
[ +0.000002] dp lt: new config: lane 2: vs level: 1, pe level: 0, pc2 level: 0
[ +0.000002] dp lt: new config: lane 3: vs level: 1, pe level: 0, pc2 level: 0
[ +0.000002] dp lt: CR retry
[ +0.000002] dp lt: switching from state 2 (clock recovery) to state 2 (clock recovery)
[ +0.000005] dp lt: state 2 (clock recovery), pending_lt_evt 0
[ +0.000014] dp lt: config: lane 0: vs level: 1, pe level: 0, pc2 level: 0
[ +0.000011] dp lt: config: lane 1: vs level: 1, pe level: 0, pc2 level: 0
[ +0.000010] dp lt: config: lane 2: vs level: 1, pe level: 0, pc2 level: 0
[ +0.000010] dp lt: config: lane 3: vs level: 1, pe level: 0, pc2 level: 0
[ +0.000004] dp lt: tx_pu: 0x30
[ +0.000891] tegradc tegradc.1: dp: aux write defer (0x10020000) – 6
[ +0.001235] tegradc tegradc.1: dp: aux write defer (0x10020000) – 5
[ +0.002760] dp lt: CR not done
[ +0.001302] dp lt: new config: lane 0: vs level: 2, pe level: 0, pc2 level: 0
[ +0.000002] dp lt: new config: lane 1: vs level: 2, pe level: 0, pc2 level: 0
[ +0.000002] dp lt: new config: lane 2: vs level: 2, pe level: 0, pc2 level: 0
[ +0.000002] dp lt: new config: lane 3: vs level: 2, pe level: 0, pc2 level: 0
[ +0.000001] dp lt: CR retry
[ +0.000003] dp lt: switching from state 2 (clock recovery) to state 2 (clock recovery)
[ +0.000003] dp lt: state 2 (clock recovery), pending_lt_evt 0
[ +0.000015] dp lt: config: lane 0: vs level: 2, pe level: 0, pc2 level: 0
[ +0.000011] dp lt: config: lane 1: vs level: 2, pe level: 0, pc2 level: 0
[ +0.000010] dp lt: config: lane 2: vs level: 2, pe level: 0, pc2 level: 0
[ +0.000010] dp lt: config: lane 3: vs level: 2, pe level: 0, pc2 level: 0
[ +0.000004] dp lt: tx_pu: 0x40
[ +0.000891] tegradc tegradc.1: dp: aux write defer (0x10020000) – 6
[ +0.001278] tegradc tegradc.1: dp: aux write defer (0x10020000) – 5
[ +0.002747] dp lt: CR done
[ +0.000003] dp lt: switching from state 2 (clock recovery) to state 3 (channel equalization)
[ +0.000003] dp lt: state 3 (channel equalization), pending_lt_evt 0
[ +0.001381] tegradc tegradc.1: dp: aux read defer (0x10020000) – 6
[ +0.001287] tegradc tegradc.1: dp: aux read defer (0x10020000) – 5
[ +0.002111] dp lt: CE not done
[ +0.001332] dp lt: new config: lane 0: vs level: 3, pe level: 0, pc2 level: 0
[ +0.000003] dp lt: new config: lane 1: vs level: 3, pe level: 0, pc2 level: 0
[ +0.000002] dp lt: new config: lane 2: vs level: 3, pe level: 0, pc2 level: 0
[ +0.000002] dp lt: new config: lane 3: vs level: 3, pe level: 0, pc2 level: 0
[ +0.000012] dp lt: config: lane 0: vs level: 3, pe level: 0, pc2 level: 0
[ +0.000012] dp lt: config: lane 1: vs level: 3, pe level: 0, pc2 level: 0
[ +0.000010] dp lt: config: lane 2: vs level: 3, pe level: 0, pc2 level: 0
[ +0.000011] dp lt: config: lane 3: vs level: 3, pe level: 0, pc2 level: 0
[ +0.000005] dp lt: tx_pu: 0x60
[ +0.000899] tegradc tegradc.1: dp: aux write defer (0x10020000) – 6
[ +0.001346] tegradc tegradc.1: dp: aux write defer (0x10020000) – 5
[ +0.001685] dp lt: CE retry
[ +0.000004] dp lt: switching from state 3 (channel equalization) to state 3 (channel equalization)
[ +0.000004] dp lt: state 3 (channel equalization), pending_lt_evt 0
[ +0.003366] dp lt: CE done
[ +0.000003] dp lt: switching from state 3 (channel equalization) to state 5 (link training pass)
[ +0.000063] extcon-disp-state extcon:disp-state: cable 46 state 1
[ +0.000002] Extcon AUX0(DP): enable
[ +0.000001] dp_audio switch 1
[ +0.017981] tegradc tegradc.1: sync windows ret = 246
[ +0.052374] extcon-disp-state extcon:disp-state: cable 44 state 1
[ +0.000003] Extcon DP: HPD enabled
[ +0.000019] hpd: Display connected, hpd_switch 1
[ +0.000003] hpd: switching from state 2 (Check EDID) to state 4 (Enabled)

Any news?

Hi,
We are trying to reproduce the issue. This would take some time due to pandemic. Will update.

1 Like

If you need help with the debugging, let me know :)

Hi,
r32_5_x_TEST_0001-mm_api-video_dec_drm-use-the-proper-plane-index.zip (2.7 KB)

Please apply attached patch to and give it a try. We have verified it with the command:

$ sudo ./video_dec_drm --disable-video -connector 1 -crtc 1

Thank you! I’ll try as soon as possible.

One day before I got off to vacation I also fixed it by comparing the way planes are calculated with the one from nvdrmvideosink. I was about to post my solution also, but I guess yours is better.

I don’t think your solution is solving my problem.
You created a new api call, which is then used from video_dec_drm to render correctly the UI.
But the error is also coming when using the api with enqueBuffer. If I see it correctly you did not change anything on that workflow. The new function is not called from inside NvDrmRenderer itself.
So the video should not be disabled for your test.

I modified the setPlane function to have the same algorithm to find the plane id like in nvdrmvideosink GStreamer element. The new function looks like this:

int NvDrmRenderer::setPlane(uint32_t pl_index,
                            uint32_t fb_id,
                            uint32_t crtc_x,
                            uint32_t crtc_y,
                            uint32_t crtc_w,
                            uint32_t crtc_h,
                            uint32_t src_x,
                            uint32_t src_y,
                            uint32_t src_w,
                            uint32_t src_h)
{
    drmModePlaneResPtr plane_res_info = NULL;
    drmModePlanePtr plane_info = NULL;
    int plane_result;
    int plane_count;
    int ret = -1;

    // Set Plane Info
    plane_res_info = drmModeGetPlaneResources( drm_fd);
    plane_count = plane_res_info->count_planes;
    if (!plane_res_info) {
        printf ("Unable to get plane resource info \n");
        goto error;
    }
    // Check bound
    if ((pl_index >= plane_count) || (pl_index < 0)) {
        printf ("Invalid plane id \n");
        goto error;
    }

    for (int i = 0; i < plane_count; i++) {
        int plane_id = plane_res_info->planes[i];
        plane_info = drmModeGetPlane (drm_fd, plane_id);
        if (!plane_info) {
            printf ("Unable to get plane info\n");
        }
        if (plane_info->possible_crtcs & (1 << drm_crtc_index)) {
            if (pl_index == 0) {
                plane_result = plane_id;
                break;
            } else {
                pl_index--;
            }
        }
    }
    if (pl_index != 0) {
        goto error;
    }
    ret = drmModeSetPlane(drm_fd, plane_result, drm_crtc_id,
                          fb_id, 0, crtc_x, crtc_y, crtc_w,
                          crtc_h, src_x, src_y,
                          src_w, src_h);

error:
    drmModeFreePlane(plane_info);
    drmModeFreePlaneResources(plane_res_info);
    return ret;
}

This is the initialization part, which is also borrowed from nvdrmvideosink:

drm_fd = drmOpen(DRM_DEVICE_NAME, NULL);
  if (drm_fd == -1) {
    COMP_ERROR_MSG("Couldn't open device: " << DRM_DEVICE_NAME);
    goto error;
  }

  if (drmSetClientCap (drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)) {
      COMP_ERROR_MSG ("Failed to set universal planes \n");
      goto error;
  }

  // Obtain DRM-KMS resources
  drm_res_info = drmModeGetResources(drm_fd);
  if (!drm_res_info) {
    COMP_ERROR_MSG("Couldn't obtain DRM-KMS resources ");
    goto error;
  }
  COMP_DEBUG_MSG("Obtained device information ");

  // If a specific crtc was requested, make sure it exists
  if (crtc >= drm_res_info->count_crtcs) {
    COMP_ERROR_MSG("Requested crtc index " << crtc << " exceeds count " << drm_res_info->count_crtcs);
    goto error;
  }

  // Query info for requested connector
  if (conn >= drm_res_info->count_connectors) {
    COMP_ERROR_MSG("Requested connector index " << conn << " exceeds count " << drm_res_info->count_connectors);
    goto error;
  }

  drm_conn_id = drm_res_info->connectors[conn];
  drm_conn_info = drmModeGetConnector(drm_fd, drm_conn_id);
  if (!drm_conn_info) {
    COMP_ERROR_MSG("Unable to obtain info for connector " << drm_conn_id);
    goto error;
  } else if (drm_conn_info->connection != DRM_MODE_CONNECTED) {
    COMP_ERROR_MSG("Requested connnector is not connected ");
    goto error;
  } else if (drm_conn_info->count_modes <= 0) {
    COMP_ERROR_MSG("Requested connnector has no available modes ");
    goto error;
  }
  COMP_DEBUG_MSG("Obtained connector information\n");

  // If there is already an encoder attached to the connector, choose
  //   it unless not compatible with crtc/plane
  drm_enc_id = drm_conn_info->encoder_id;
  drm_enc_info = drmModeGetEncoder(drm_fd, drm_enc_id);
  if (!drm_enc_info) {
      // If connector does not have a connected encoder use first one
      drm_enc_id = drm_conn_info->encoders[0];
      drm_enc_info = drmModeGetEncoder (drm_fd, drm_enc_id);

      if (!drm_enc_info) {
          COMP_DEBUG_MSG("Unable to find suitable encoder \n");
          goto error;
      }
  }


  // Set CRTC info
  drm_crtc_id = drm_enc_info->crtc_id;
  drm_crtc_info = drmModeGetCrtc (drm_fd, drm_crtc_id);

  // If the encoder has no connected CRTC, use the first one supported
  if (!drm_crtc_info && drm_enc_info->possible_crtcs) {
      drm_crtc_id = drm_res_info->crtcs[(drm_enc_info->possible_crtcs) - 1];
      drm_crtc_info = drmModeGetCrtc (drm_fd, drm_crtc_id);
  }

  if (hdrSupported()) {
    ret = setHDRMetadataSmpte2086(metadata);
    if(ret!=0)
      COMP_DEBUG_MSG("Error while getting HDR mastering display data\n");
  }
  else {
    COMP_DEBUG_MSG("APP_INFO : HDR not supported \n");
  }
  // Query info for crtc
  drm_crtc_info = drmModeGetCrtc(drm_fd, drm_crtc_id);
  if (!drm_crtc_info) {
    COMP_ERROR_MSG("Unable to obtain info for crtc " << drm_crtc_id);
    goto error;
  }

  if (!drm_crtc_info) {
      printf ("Unable to find usable crtc for encoder \n");
      goto error;
  }

  for (int is = 0; is < drm_res_info->count_crtcs; is++) {
      if (drm_res_info->crtcs[is] == drm_crtc_id) {
          drm_crtc_index = is;
          break;
      }
  }
  if (drm_crtc_index == -1) {
      printf ("Unable to locate crtc_id=%d in resource list\n", drm_crtc_id);
      goto error;
  }

  COMP_DEBUG_MSG("Obtained crtc information\n");

I added

uint32_t drm_crtc_index;

as a new private class variable in NvDrmRenderer.h

Do you think my solution is legit? It seems to work so far.

Hi,
We have verified the patch on r32.5.1/Jetson Nano. It should work fine if you apply it to default 08_video_dec_drm. Your use-case may be a little bit different so it does not work for you. Since the code is open source, it is fine to make adaptation per your use-case.