ux_host_class_video_transfer_buffer_add()でエラー

e-nakaと申します。

現在、DK-S7G2にUSBカメラ(USB Video Class1.1)を接続し、サンプルプログラムUSBX Host Class Video Module GuideのサンプルプログラムUX_HOST_CLASS_VIDEO_EL_MG_AP_DK-S7G2を試しています。

セマフォの取得で常にTX_NO_INSTANCEが戻るためか、画像が取れていません。

カメラのパラメータリストは取得できて出力されました。 uvc_parameter_list(video);

調べたところ、ux_host_class_video_transfer_buffer_add()で戻り値が145(0x91)になっていることが判明しました。

SSP v1.5.3 Additional Usage NoteのIssue ID: 13036にこのことと思わしき件が載っているのですが、これ以上の情報を調べることができませんでした。

なにかご存じの方がいらっしゃいましたら教えてください。

以下、サンプルのソースsrc/camera_thread_entry.cの抜粋です。(赤字部分がコメント)

よろしくお願いします。

 

VOID uvc_process_function(UX_HOST_CLASS_VIDEO* video)
{
  /* This demo uses two buffers. One buffer is used by video device while the
  application consumes data in the other buffer. */
  UCHAR *buffer_ptr[MAX_NUM_BUFFERS];

  /* Index variable keeping track of the current buffer being used by the video device. */
  ULONG buffer_index;

  /* Maximum buffer requirement reported by the video device. */
  ULONG max_buffer_size;

  UINT status;
  ULONG actual_flags;
  UINT frame_count;

  UX_HOST_CLASS_VIDEO_PARAMETER_CHANNEL channel;

  /* List parameters */
  uvc_parameter_list(video);

  /* Set video parameters. This setting value is a dummy.
  Depending on the application, set the necessary parameters. */
  status = ux_host_class_video_frame_parameters_set(video,
                 UX_HOST_CLASS_VIDEO_VS_FORMAT_MJPEG,
                 320, 240,
                 1333333);

//status=0となる

#ifdef SEMI_HOSTING
  if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk)
  {
    printf("parameters set status = %d\n", status);
  }
#endif

/* Set the user callback function of video class. */
  ux_host_class_video_transfer_callback_set(video, uvc_transfer_request_done_callback);

// プログラムを実行してもuvc_transfer_request_done_callback()内は走りませんでした。

  /* Find out the maximum memory buffer size for the video configuration
  set above. */
  max_buffer_size = ux_host_class_video_max_payload_get(video);

//max_buffer_size=3072となる

#ifdef SEMI_HOSTING
  if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk)
  {
    printf("max_buffer_size = %d\n", (int)max_buffer_size);
  }
#endif

  /* Clear semaphore to zero */
  while (1)
  {
    if(tx_semaphore_get(&g_data_received_semaphore, 0)==TX_NO_INSTANCE)
    {
      break;
    }
  }

#ifdef SEMI_HOSTING
  if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk)
  {
    printf("Start video transfer.\n");
  }
#endif

  /* Start video transfer. */
  status = ux_host_class_video_start(video);

// status = 65(0x41)となる


  if(status!=UX_SUCCESS)
  {
    /* Setting these to zero is a hack since we're mixing old and new APIs (new API does this and is required for reads). */
    video -> ux_host_class_video_transfer_request_start_index = 0;
    video -> ux_host_class_video_transfer_request_end_index = 0;

    channel.ux_host_class_video_parameter_format_requested = video -> ux_host_class_video_current_format;
    channel.ux_host_class_video_parameter_frame_requested = video -> ux_host_class_video_current_frame;
    channel.ux_host_class_video_parameter_frame_interval_requested = video -> ux_host_class_video_current_frame_interval;
    channel.ux_host_class_video_parameter_channel_bandwidth_selection = 10240;

    status = ux_host_class_video_ioctl(video, UX_HOST_CLASS_VIDEO_IOCTL_CHANNEL_START, &channel);

// status = 0となる。channel.ux_host_class_video_parameter_channel_bandwidth_selection=1024(サンプルの元の値)だとstatus=65となる。

  }
#ifdef SEMI_HOSTING
  if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk)
  {
    printf("start status = %d\n", status);
  }
#endif

  /* Allocate space for video buffer. */
  for(buffer_index = 0; buffer_index < MAX_NUM_BUFFERS; buffer_index++)
  {
    buffer_ptr[buffer_index] = &video_buffer[max_buffer_size * buffer_index];

/* Add buffer to the video device for video streaming data. */
    status = ux_host_class_video_transfer_buffer_add(video, buffer_ptr[buffer_index]);

  // status = 145(0x91)となる。(サンプルには元々status = の記述なし)

  }

  buffer_index = 0;
  frame_count = 0;

  while (1)
  {
    /* Suspend here until a transfer callback is called. */
    status = tx_semaphore_get(&g_data_received_semaphore, 0);

// 最初からstatus = 13(0x0d)TX_NO_INSTANCEとなる。

    if(status!=TX_SUCCESS)
    {
      /* Check camera status */
      status = tx_event_flags_get(&g_device_insert_eventflag, EVENTFLAG_USB_DEVICE_INSERTED, TX_OR, (ULONG *)&actual_flags, 0);
      if(status==TX_SUCCESS)
      {
        /* Stop video transfer. */
        ux_host_class_video_stop(video);
      }
      break;
    }

  • Former Member
    Former Member

    masukamiと申します。

    私は、LogicoolのC270 HD Webcamを接続してサンプルプログラムを試しましたが、
    問題なく動作しました。アプリケーションノートにある以下と同じ結果でした。

    parameters set status = 0
    max_buffer_size = 192
    Start video transfer.
    start status = 0

    e-nakaさんの場合、ux_host_class_video_start()の戻り値が65(0x41)となるとのことですが、
    このエラー値は、ux_api.hにあるUX_NO_BANDWIDTH_AVAILABLEになります。
    max_buffer_size = 3072となるそうですが、これが大きいために上記のエラーとなっていると思います。
    これに関連して、ux_hcd_system.hに以下の定義があります。

    #define UX_SYNERGY_HC_AVAILABLE_BANDWIDTH (2304UL)
    /* The macro above is used for checking the available bandwidth for periodic transfers(Isochronous and Interrupt)
    * Maximum bandwidth is calculated as {2048byes(2x ISO PIPEs) + 256bytes(4x INT PIPEs)} for high-speed operation.
    */

    コメントの記述にありますように、Synergy MCU内のUSB 2.0 High-Speed Module (USBHS)のハードウェア仕様の上限が定義されています。
    この上限を超えるので、UX_NO_BANDWIDTH_AVAILABLEエラーが返っていると思われます。

    上記のカメラでは、デバッグ仮想コンソールに以下のようにリストが表示されます。

    (略)
    format UX_HOST_CLASS_VIDEO_VS_FORMAT_MJPEG
    --- frame resolutions
    (略)
    frame 176,144
    interval 333333, 400000, 500000, 666666, 1000000, 2000000
    frame 320,176
    interval 333333, 400000, 500000, 666666, 1000000, 2000000
    frame 320,240
    interval 333333, 400000, 500000, 666666, 1000000, 2000000
    (略)
    frame 800,600
    interval 333333, 400000, 500000, 666666, 1000000, 2000000
    (略)

    サンプルプログラムでは以下のようになっていますが、

    ux_host_class_video_frame_parameters_set(video,
    UX_HOST_CLASS_VIDEO_VS_FORMAT_MJPEG,
    176, 144,
    333333);

    この(176, 144)を(800, 600)に変更すると、同じカメラでも以下のように、max_buffer_sizeが大きくなり、
    start status = 65 となります。

    parameters set status = 0
    max_buffer_size = 3060
    Start video transfer.
    start status = 65

    frame intervalは異なりますが、e-nakaさんと同じサイズで試してみました。

     status = ux_host_class_video_frame_parameters_set(video,
    UX_HOST_CLASS_VIDEO_VS_FORMAT_MJPEG,
    320, 240,
    333333);

    結果は以下となりました。

    parameters set status = 0
    max_buffer_size = 384
    Start video transfer.
    start status = 0

    max_buffer_sizeは、e-nakaさんの3072よりかなり小さい384なので、
    問題なく動作しました。
    使用するカメラによって異なると思われます。

    評価ライセンスではプロテクトされたソースコードはデバッグできませんが、
    開発・生産ライセンスを取得すると、プロテクトされたソースコードの中もデバッグできますので、
    それを使って調査してみてはいかがでしょうか。

  • masukamiさん

     ありがとうございます。
     本日、カメラを別なものに変えたところうまくゆきました。

     使用したカメラは
    バッファローのBSWHD06Mです。
    こちらは1280x720ピクセルでも受信できました。
    ただ、
    max_buffer_sizeは3072
    status = ux_host_class_video_start(video)は65
    から変わりませんでした。

    channel.ux_host_class_video_parameter_channel_bandwidth_selectionは1024でOKでした。

    元々検証で使ったカメラ(うまくゆかなかったほう)は
    アサヒ電子研究所のCM4051Aでした。こちらがうまくゆかない理由については今後検証してゆきます。

    まずはありがとうございました。