Hatena::Grouptechmemo

USBカメラを使って色々遊ぶ日記(仮)

2008-04-08Video4Linuxアプリをいくつか試す

ffmpegで録画してみる

| 00:03 | ffmpegで録画してみる - USBカメラを使って色々遊ぶ日記(仮) を含むブックマーク はてなブックマーク - ffmpegで録画してみる - USBカメラを使って色々遊ぶ日記(仮)

昨日は、純粋に画面にリアルタイムでキャプチャした映像を映したかったのでluvcviewを利用したが、録画ならばffmpegでできるらしい。

$ ffmpeg -s 320x240 -f audio_device -i /dev/audio1 -f video4linux2 -i /dev/video0 out.mpg

このコマンドを実行すると、録画モードに入り、qボタンで終了するまで録画してくれる。

これは見事なまでに簡単。ただし、-sで指定する動画サイズは、

大きくしても解像度がよくなるということはないようだ。残念。

もうちょっと画質をよくする方法はないだろうか。

Video4Linuxについて調べてみる

| 00:10 | Video4Linuxについて調べてみる - USBカメラを使って色々遊ぶ日記(仮) を含むブックマーク はてなブックマーク - Video4Linuxについて調べてみる - USBカメラを使って色々遊ぶ日記(仮)

そんなに深く追究したわけではないけれど。

Linux上でビデオキャプチャーカード(主にBT8x8)を制御するためのAPI

Video4Linuxとは - はてなダイアリー

あら、あっさり。

どうやらVideo4Linux(v4l)と、Video4Linux2(v4l2)の2種類があるらしい。

v4l

is the original video capture/overlay API of the linux kernel. It appeared late the 2.1.x development cycle in the linux kernel.

v4l2

is the second generation of the video4linux API which fixes a number of design bugs of the first version. It was integrated into the standard kernel in 2.5.x.

Althrough v4l2 is integrated into the standard kernel a number of drivers don't support the new v4l2 API yet, so we'll likely see v4l and v4l2 coexist for some time.

video4linux

組み込まれるベースとなるカーネルのバージョンが違うのね。2.5以降のカーネルではv4l2が入っていると考えていいのかしら。要調査。

v4lのリンク集みたいなのもあった。

Synapticで検索して出てくるものをインストールしてみる

| 00:28 | Synapticで検索して出てくるものをインストールしてみる - USBカメラを使って色々遊ぶ日記(仮) を含むブックマーク はてなブックマーク - Synapticで検索して出てくるものをインストールしてみる - USBカメラを使って色々遊ぶ日記(仮)

  • camorama: エラーダイアログが出て起動しない
  • gqcam: 起動はするが「Error reading image...」が繰り返し出力され映像が出ない。

xawtvも出ないし、デバイスの読み込みに難があるのかな?

luvcviewのソースを読んでみる(1)

| 23:22 | luvcviewのソースを読んでみる(1) - USBカメラを使って色々遊ぶ日記(仮) を含むブックマーク はてなブックマーク - luvcviewのソースを読んでみる(1) - USBカメラを使って色々遊ぶ日記(仮)

(1)とか付けてみたけど続くかどうかは不明。

まずは、初期化や設定はさておいて、どこでカメラから取得したデータを読んでいるのかを追ってみる。

メインのループは、luvcview.cの485行目付近。

    /* main big loop */
    while (videoIn->signalquit) {
	currtime = SDL_GetTicks();
	if (currtime - lasttime > 0) {
		frmrate = 1000/(currtime - lasttime);
	}
	lasttime = currtime;
	if (uvcGrab(videoIn) < 0) {
	    printf("Error grabbing\n");
	    break;
	}

    /* if we're grabbing video, show the frame rate */
    if (videoIn->toggleAvi)
        printf("\rframe rate: %d     ",frmrate);

	SDL_LockYUVOverlay(overlay);
	memcpy(p, videoIn->framebuffer,
	       videoIn->width * (videoIn->height) * 2);
	SDL_UnlockYUVOverlay(overlay);
	SDL_DisplayYUVOverlay(overlay, &drect);

	if (videoIn->getPict) { 
		switch(videoIn->formatIn){
		case V4L2_PIX_FMT_MJPEG:
			get_picture(videoIn->tmpbuffer,videoIn->buf.bytesused);
			break;
		case V4L2_PIX_FMT_YUYV:
			get_pictureYV2(videoIn->framebuffer,videoIn->width,videoIn->height);
			break;
		default:
		break;
		}
		videoIn->getPict = 0;
		printf("get picture !\n");
	}

	SDL_LockMutex(affmutex);
	ptdata.frmrate = frmrate;
	SDL_WM_SetCaption(videoIn->status, NULL);
	SDL_UnlockMutex(affmutex);
	SDL_Delay(10);

    }

さらに、実際に読んでいるのはuvcGrabという関数(v4l2uvc.c)のようだ。

デバイスを制御するのにはioctl関数を使い、なおかつVIDIOC_で始まるコマンドでvideoデバイス関連のコマンドを実行している。

    ret = ioctl(vd->fd, VIDIOC_DQBUF, &vd->buf);

これが、デバイスのバッファにある撮影したフレームを取り出す部分のようだ。

本関数の最後の方に、

    ret = ioctl(vd->fd, VIDIOC_QBUF, &vd->buf);

とバッファをエンキューしている部分があるので、複数あるバッファに対して、フレームを読み出す→空いたバッファを再度エンキューする、という繰り返しかと想像。

時間のあるときにもうちょっと頑張る。