vpl-rs

May 15, 2026 · View on GitHub

crates.io docs.rs License GitHub Actions Discord

About Shiguredo's open source software

We will not respond to PRs or issues that have not been discussed on Discord. Also, Discord is only available in Japanese.

Please read https://github.com/shiguredo/oss before use.

時雨堂のオープンソースソフトウェアについて

利用前に https://github.com/shiguredo/oss をお読みください。

概要

Intel VPL (Video Processing Library) を利用したハードウェアビデオエンコーダーおよびデコーダーの Rust バインディングです。

libvpl を static link するため、実行時に Intel VPL 共有ライブラリは不要です。

特徴

  • Intel VPL によるハードウェアエンコード (H.264 / H.265 / VP9 / AV1)
  • Intel VPL によるハードウェアデコード (H.264 / H.265 / VP9 / AV1)
  • libvpl を static link してビルド (CMake で自動ビルド)
  • ビルド時に GitHub から libvpl ヘッダーを自動取得
  • エンコード入力フォーマット選択 (NV12 / I420 / YV12 / BGRA / P010)
  • デコード出力は NV12 フォーマット
  • フレーム単位のエンコードオプション (IDR フレーム強制)
  • CBR / VBR / CQP / ICQ / QVBR / LA / AVBR / VCM / LA_ICQ / LA_HRD レート制御モード
  • エンコーダーパラメータの動的変更 (MFXVideoENCODE_Reset)
  • パラメータのサポート可否検証 (MFXVideoENCODE_Query)

動作要件

  • Linux (x86_64)
  • Intel GPU (第 6 世代 Core 以降)
  • ビルド時: git、clang (bindgen 依存)

ビルド

cargo build

ビルド時に GitHub から libvpl を自動取得し、CMake で static build します。

docs.rs 向けビルド

libvpl がない環境では、docs.rs 向けのドキュメント生成のみ可能です。

DOCS_RS=1 cargo doc --no-deps

使い方

GPU アダプタの指定

アダプタは Intel VPL が利用する Intel GPU デバイスのことで、Linux 上では /dev/dri/renderD<N> の DRM render node 番号で識別します。

エンコーダーおよびデコーダーの初期化には、使用する GPU アダプタを AdapterSelector で指定する必要があります。 システムに搭載されている Intel GPU は list_adapters() で列挙できます。

use shiguredo_vpl::{AdapterSelector, list_adapters};

let adapters = list_adapters()?;
for adapter in &adapters {
    println!(
        "DRM render node {}: {} ({})",
        adapter.drm_render_node, adapter.device_name, adapter.impl_name,
    );
}

// 使用する GPU アダプタを DRM render node 番号で指定する
let adapter = AdapterSelector::DrmRenderNode(adapters[0].drm_render_node);

エンコード

use shiguredo_vpl::{
    AdapterSelector, CodecConfig, EncodeOptions, EncodedFrame, Encoder, EncoderConfig,
    Error, FnEncodeHandler, FrameFormat, H264EncoderConfig, H264Profile,
    RateControlMode, frame_type, list_adapters,
};
use std::sync::mpsc;

let adapter = AdapterSelector::DrmRenderNode(list_adapters()?[0].drm_render_node);
let mut config = EncoderConfig::new(
    adapter,
    CodecConfig::H264(H264EncoderConfig {
        profile: Some(H264Profile::High),
    }),
    1920,                    // width
    1080,                    // height
    FrameFormat::Nv12,
    30,                      // framerate_num
    1,                       // framerate_den
    RateControlMode::Cbr,
);
config.target_kbps = Some(5_000);

let (tx, rx) = mpsc::channel();
let mut encoder = Encoder::new(config, FnEncodeHandler::new(move |result| {
    tx.send(result).expect("failed to send callback result");
}))?;

// フレームデータをエンコード
let (coded_width, coded_height) = encoder.coded_size();
let frame_size = FrameFormat::Nv12
    .frame_size(coded_width, coded_height)
    .ok_or("frame size overflowed")?;
let frame_data = vec![0u8; frame_size];
let options = EncodeOptions { frame_type: frame_type::UNKNOWN };
encoder.encode(&frame_data, "normal", &options)?;

// IDR フレームを強制してエンコード
encoder.encode(&frame_data, "force-idr", &EncodeOptions {
    frame_type: frame_type::IDR | frame_type::I | frame_type::REF,
})?;

// 残りのフレームをすべて取得する
encoder.finish()?;
for _ in 0..2 {
    let encoded = rx.recv().expect("failed to receive callback result")?;
    println!("encoded bytes: {}", encoded.data().len());
    println!("timestamp: {}", encoded.timestamp());
    println!("picture type: {:?}", encoded.picture_type());
    println!("user_data: {:?}", encoded.user_data());
}

デコード

use shiguredo_vpl::{
    AdapterSelector, Decoder, DecoderCodec, DecoderConfig, DecodedFrame, Error, FnDecodeHandler,
    list_adapters,
};
use std::sync::mpsc;

let adapter = AdapterSelector::DrmRenderNode(list_adapters()?[0].drm_render_node);
let config = DecoderConfig::new(adapter, DecoderCodec::H264);

let (tx, rx) = mpsc::channel();
let mut decoder = Decoder::new(config, FnDecodeHandler::new(move |result| {
    tx.send(result).expect("failed to send callback result");
}))?;

// ビットストリームデータをデコード (value で任意のユーザーデータを紐付け可能)
let bitstream_data = vec![0u8; 1024];
decoder.decode(&bitstream_data, "frame-0")?;
decoder.decode(&bitstream_data, "frame-1")?;

// 残りのフレームをすべて取得する
decoder.finish()?;

// コールバック経由でデコード結果を受け取る
while let Ok(result) = rx.try_recv() {
    let frame = result?;
    println!("decoded: {}x{}, Y plane: {} bytes, UV plane: {} bytes, user_data: {:?}",
        frame.width(), frame.height(), frame.y().len(), frame.uv().len(), frame.user_data());
}

サポートコーデック

エンコード

コーデックCodecConfig
H.264CodecConfig::H264(H264EncoderConfig)
H.265CodecConfig::Hevc(HevcEncoderConfig)
VP9CodecConfig::Vp9(Vp9EncoderConfig)
AV1CodecConfig::Av1(Av1EncoderConfig)

デコード

コーデックDecoderCodec
H.264DecoderCodec::H264
H.265DecoderCodec::Hevc
VP9DecoderCodec::Vp9
AV1DecoderCodec::Av1

サポートフォーマット

エンコード入力フォーマット (FrameFormat)

フォーマットFrameFormat説明
NV12FrameFormat::Nv12Semi-Planar YUV 4:2:0 8bit
YUY2FrameFormat::Yuy2Packed YUV 4:2:2 8bit
BGRAFrameFormat::BgraPacked BGRA 8bit

デコード出力フォーマット

フォーマット説明
NV12Semi-Planar YUV 4:2:0 8bit

サポートプロファイル

H.264 (H264Profile)

プロファイルH264Profile
BaselineH264Profile::Baseline
Constrained BaselineH264Profile::ConstrainedBaseline
MainH264Profile::Main
HighH264Profile::High
Constrained HighH264Profile::ConstrainedHigh
High 10H264Profile::High10
High 4:2:2H264Profile::High422

H.265 (HevcProfile)

プロファイルHevcProfile
MainHevcProfile::Main
Main 10HevcProfile::Main10
Main SPHevcProfile::MainSp
RExtHevcProfile::Rext
SCCHevcProfile::Scc

VP9 (Vp9Profile)

プロファイルVp9Profile説明
Profile 0Vp9Profile::Profile08bit YUV 4:2:0
Profile 1Vp9Profile::Profile18bit YUV 4:2:2 または 4:4:4
Profile 2Vp9Profile::Profile210/12bit YUV 4:2:0
Profile 3Vp9Profile::Profile310/12bit YUV 4:2:2 または 4:4:4

AV1 (Av1Profile)

プロファイルAv1Profile
MainAv1Profile::Main

Intel VPL ライセンス

https://github.com/intel/libvpl/blob/main/LICENSE

MIT License

Copyright (c) 2020 Intel Corporation

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

ライセンス

Apache License 2.0

Copyright 2026-2026, Shiguredo Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.