0

ウェブカメラに問題があります。ハードウェアの可能性もありますが、そうではないと確信しています。すべてのアプリでストリームを表示できますが、突然フリーズします。問題が発生したときの使用済みアプリからの次の出力のため:

v4l: timeout (got SIGALRM), hardware/driver problems?

コードと興味深い部分をチェックアウトしました。

/* How many seconds to wait before deciding it's a driver problem. */
#define SYNC_TIMEOUT 3

int alarms;

void sigalarm(int signal)
{
    alarms++;
}

.................................................................................

void wait_for_frame_v4l1( input_t *vidin, int frameid )
{
    alarms = 0;
    alarm(SYNC_TIMEOUT);
    if (ioctl(vidin->fd, VIDIOCSYNC, vidin->buf + frameid) < 0 )
        fprintf(stderr, "input: Can't wait for frame %d: %s\n", frameid, strerror(errno));
    if (alarms)
        fprintf(stderr, "v4l: timeout (got SIGALRM), hardware/driver problems?");
    alarm(0);
}

そこから、SYNC_TIMEOUT が問題になる可能性があると結論付けました。値は 3 秒で、これで十分だと思われます。

私の要求は、コードを変更して、フレームを無期限にブロックしないようにすることです。

100 ミリ秒以内にフレームが到着しない場合は、タイムアウトになり、GUI がそれ自体を更新する機会が与えられます。すべてのデバイスでホイールを解放できるわけではないため、アプリは GUI をブロックせずにそのようなデバイスをサポートする必要があります。

1秒未満の待機を行うにはどうすればよいですか?

v4l2 デバイスはこれで非常にうまく機能します:

/* How many milliseconds to wait before deciding it's a driver problem. */
#define SYNC_TIMEOUT_MSECS 100

int wait_for_frame_v4l2(input_t * vidin)
{
        struct timeval timeout;
        fd_set rdset;
        int n;

        FD_ZERO(&rdset);
        FD_SET(vidin->fd, &rdset);

        timeout.tv_sec = 0;
        timeout.tv_usec = SYNC_TIMEOUT_MSECS * 1000;

        n = select(vidin->fd + 1, &rdset, 0, 0, &timeout);
        if(n == -1) {
            fprintf(stderr, "input: Can't wait for frame: %s\n", strerror(errno));
        } else if(n == 0) {
            sigalarm(0);
            return 1;
        }
        return 0;
}

しかし、私は v4l1 デバイスを持っています。

4

1 に答える 1

1

使用している (usb) ウェブカメラとカーネルのバージョンは何ですか?

  1. ドライバー/カーネルを更新する
  2. USB-Cam の場合は、USB ハブなしで接続してみてください

vidin->fd の VIDIOCSYNC ioctl は、vidin->buf がいっぱいになるまで実行を中断します。select または poll を介して、満たされたバッファーが使用可能になるのを待つことができます。

于 2014-12-16T12:25:43.443 に答える