1. 程式人生 > >V4L2文件翻譯(二)

V4L2文件翻譯(二)

視訊標準

視訊裝置通常支援一種或多種不同的視訊標準或更多的標準衍生體。每一個視訊輸入和輸出支援一組標準。這項設定由VIDIOC_ENUMINPUT和VIDIOC_ENUMOUTPUT ioctl返回的v4l2_input和v4l2_output結構體中的std成員體現。

V4L2位每一種現今世界的模擬視訊標準定義了一個位,且為驅動定義標準留出了一些位。比如,在PAL TV上觀看NTSC視訊的混合標準。應用程式可以使用預定義的位來選擇一個特殊標準,推薦向用戶展示所支援標準的選單。應用程式可以使用VIDIOC_ENUMSTD ioctl來列舉和查詢所支援標準的屬性。

所定義的標準中,許多都是一些主要標準的變種。實際上,硬體不必去區分他們,或者在內部做自動切換。因此,列舉出來的標準也包含了一個或多個標準位。

假設一個調諧器能夠解調B/PAL,G/PAL和I/PAL訊號。首先列舉出來的是B和G/PAL標準,根據UHF或VHF波段的無線頻率實現自動切換。列舉給出PAL-B/G或PAL-I的選擇。像一些複合輸入會使標準崩潰,如PAL-B/G/H/I,NTSC-M和SECAM-D/K。

應用程式可通過VIDIOC_G_STD和VIDIOC_S_STD ioctl查詢和選擇當前視訊輸入或輸出的標準。可通過VIDIOC_QUERYSTD ioctl感知接收到的標準。注意,所有這些ioctl的引數是v4l2_std_id型別指標,並不是列舉出的標準的索引號。若裝置擁有一個或以上的視訊輸入或輸出,其驅動必須宣告所有視訊標準的ioctl。

一些適用於裝置的特殊規則(如USB相機的毫無意義的視訊標準),也可用於任何符合下列情況的捕捉或輸出裝置:

  • 使用視訊標準標稱速率無法捕捉欄位或幀
  • 不支援任何視訊標準格式

這些驅動應該將v4l2_input或v4l2_output結構體中的std成員設為0,且VIDIOC_G_STD,VIDIOC_S_STD,VIDIOC_QUERYSTD,VIDIOC_ENUMSTD ioctl應返回ENOTTY或EINVAL錯誤碼。

應用程式可以使用下表中的標誌來判斷是否給定的輸入或輸出支援視訊標準ioctl:

Table A.38. Input capabilities

V4L2_IN_CAP_DV_TIMINGS    0x00000002    This input supports setting video timings by using VIDIOC_S_DV_TIMINGS.
V4L2_IN_CAP_STD    0x00000004    This input supports setting the TV standard by using VIDIOC_S_STD.

Table A.41. Output capabilities

V4L2_OUT_CAP_DV_TIMINGS    0x00000002    This output supports setting video timings by using VIDIOC_S_DV_TIMINGS.
V4L2_OUT_CAP_STD    0x00000004    This output supports setting the TV standard by using VIDIOC_S_STD.

例 1.5 當前視訊標準資訊

v4l2_std_id std_id;
struct v4l2_standard standard;

if (-1 == ioctl(fd, VIDIOC_G_STD, &std_id)) {
    /* Note when VIDIOC_ENUMSTD always returns ENOTTY this
       is no video device or it falls under the USB exception,
       and VIDIOC_G_STD returning ENOTTY is no error. */

    perror("VIDIOC_G_STD");
    exit(EXIT_FAILURE);
}

memset(&standard, 0, sizeof(standard));
standard.index = 0;

while (0 == ioctl(fd, VIDIOC_ENUMSTD, &standard)) {
    if (standard.id & std_id) {
           printf("Current video standard: %s\n", standard.name);
           exit(EXIT_SUCCESS);
    }

    standard.index++;
}

/* EINVAL indicates the end of the enumeration, which cannot be
   empty unless this device falls under the USB exception. */

if (errno == EINVAL || standard.index == 0) {
    perror("VIDIOC_ENUMSTD");
    exit(EXIT_FAILURE);
}

例 1.6 列出當前輸入支援的視訊標準

struct v4l2_input input;
struct v4l2_standard standard;

memset(&input, 0, sizeof(input));

if (-1 == ioctl(fd, VIDIOC_G_INPUT, &input.index)) {
    perror("VIDIOC_G_INPUT");
    exit(EXIT_FAILURE);
}

if (-1 == ioctl(fd, VIDIOC_ENUMINPUT, &input)) {
    perror("VIDIOC_ENUM_INPUT");
    exit(EXIT_FAILURE);
}

printf("Current input %s supports:\n", input.name);

memset(&standard, 0, sizeof(standard));
standard.index = 0;

while (0 == ioctl(fd, VIDIOC_ENUMSTD, &standard)) {
    if (standard.id & input.std)
        printf("%s\n", standard.name);

    standard.index++;
}

/* EINVAL indicates the end of the enumeration, which cannot be
   empty unless this device falls under the USB exception. */

if (errno != EINVAL || standard.index == 0) {
    perror("VIDIOC_ENUMSTD");
    exit(EXIT_FAILURE);
}

例 1.7 選擇新的視訊標準

struct v4l2_input input;
v4l2_std_id std_id;

memset(&input, 0, sizeof(input));

if (-1 == ioctl(fd, VIDIOC_G_INPUT, &input.index)) {
    perror("VIDIOC_G_INPUT");
    exit(EXIT_FAILURE);
}

if (-1 == ioctl(fd, VIDIOC_ENUMINPUT, &input)) {
    perror("VIDIOC_ENUM_INPUT");
    exit(EXIT_FAILURE);
}

if (0 == (input.std & V4L2_STD_PAL_BG)) {
    fprintf(stderr, "Oops. B/G PAL is not supported.\n");
    exit(EXIT_FAILURE);
}

/* Note this is also supposed to work when only B
   or G/PAL is supported. */

std_id = V4L2_STD_PAL_BG;

if (-1 == ioctl(fd, VIDIOC_S_STD, &std_id)) {
    perror("VIDIOC_S_STD");
    exit(EXIT_FAILURE);
}

數字視訊(DV)時序

目前為止所討論過的視訊標準是關於模擬TV及相關視訊時序。現如今已經有更多不同的硬體介面,如HDMI,VGA,DVI等等,有必要對API進行擴充套件來選擇這些介面的視訊時序。由於v4l2_std_id的位限制不能用來擴充套件,則添加了一組新的ioctl來在輸入、輸出時設定、獲取視訊時序。

這些ioctl處理每種視訊格式的詳細的數字視訊時序。其引數包含了例如有效視訊的寬度和高度、訊號極性、前沿、後沿、同步寬度等等。linux/v4l2-dv-timings.h標頭檔案可以用來獲取CEA-861-E和VESA_DMT標準格式的時序。

應用程式可以通過VIDIOC_ENUM_DV_TIMINGS和VIDIOC_DV_TIMINGS_CAP ioctl來對裝置所支援的DV序列進行列舉和屬性查詢。應用程式可通過VIDIOC_S_DV_TIMINGS ioctl設定DV時序,通過VIDIOC_G_DV_TIMINGS獲取當前DV時序。VIDIOC_QUERY_DV_TIMINGS ioctl用來探測視訊接收器的DV時序。

應用程式同樣可以使用表Table A.38. Input capabilities和Table A.41. Output capabilities中的標誌判斷給定的輸入或輸出是否可以使用數字視訊ioctl。