コグノスケ


link 未来から過去へ表示(*)  link 過去から未来へ表示

link もっと前
2024年12月4日 >>> 2024年11月21日
link もっと後

2024年12月4日

libjpeg-turboのAPIその1 - decode

目次: Linux

半年経ったら完全に忘れるのでメモします。最近JPEGのデコードエンコードが必要になって色々調べていました。libjpeg-turboを使ってJPEGのデコードとエンコードを行う方法を紹介します(公式ドキュメントへのリンク)。

以前(2024年11月25日の日記参照)紹介したようにlibjpeg-turboは2.x系と3.x系の2系統のAPIがありまして、今回は2.x系APIの使い方を紹介します。DebianやUbuntuのaptパッケージだと2.x系が使われているので特に困らないと思いますが、最新版をビルドして使う場合は3.x系APIになるのでご注意ください。

デコード

前に使ったnvJPEGは訳のわからん儀式が必要でしたが、libjpeg-turboはとても簡単です。

libjpeg-turbo decodingのAPI呼び出し順

	// Create
	tj_handle = tjInitDecompress();
		
	// Rawvideo
	img_stride[0] = width;
	img_stride[1] = width / 2;
	img_stride[2] = width / 2;
	img_sz[0] = img_stride[0] * height;
	img_sz[1] = img_stride[1] * height / 2;
	img_sz[2] = img_stride[2] * height / 2;
	img_buf[0] = (uint8_t *)malloc(img_sz[0]);
	img_buf[1] = (uint8_t *)malloc(img_sz[1]);
	img_buf[2] = (uint8_t *)malloc(img_sz[2]);

	// Decoding
	tjDecompressToYUVPlanes(tj_handle, jpegbuf, jpegsize, img_buf, width, img_stride, height, 0);

	// Destroy
	free(img_buf[0]);
	free(img_buf[1]);
	free(img_buf[2]);

	tjDestroy(tj_handle);

基本的にはinitしてデコードするだけです。

実行

ソースコードを置いておきます。

使い方はコードの先頭にコメントで書いている通りですが、ここでも説明しておきます。引数はありません。ファイル名test_420.jpgのJPEGファイルを読み込んで、ファイル名turbo2_420.yuvのRawvideoファイルを書き出します。

コンパイル、結果確認
$ g++ -g -O2 -Wall 20241204_turbo2_dec.cpp -lturbojpeg
$ ./a.out

$ ffplay -f rawvideo -video_size 1920x1440 -pixel_format yuv420p -i turbo2_420.yuv

デコード結果のRawvideoを確認するときはffplayを使うと便利です。

編集者:すずき(2024/12/08 15:00)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2024年12月2日

Debian TestingでX.orgが起動しなくなった

目次: Linux

Debian Testingのapt-get updateをしたら、xrdp経由で起動しているX.orgがエラーで起動しなくなりました。こんなエラーが出ています。

X.orgの起動ログ
[  1416.016] (EE)
[  1416.016] (EE) Backtrace:
[  1416.016] (EE) 0: /usr/lib/xorg/Xorg (OsLookupColor+0x14d) [0x556fb13c8dad]
[  1416.017] (EE) 1: /lib/x86_64-linux-gnu/libc.so.6 (__sigaction+0x40) [0x7f084f9dad20]
[  1416.017] (EE) 2: /lib/x86_64-linux-gnu/libc.so.6 (pthread_key_delete+0x14c) [0x7f084fa2ee5c]
[  1416.017] (EE) 3: /lib/x86_64-linux-gnu/libc.so.6 (gsignal+0x12) [0x7f084f9dac82]
[  1416.018] (EE) 4: /lib/x86_64-linux-gnu/libc.so.6 (abort+0xd3) [0x7f084f9c34f0]
[  1416.018] (EE) 5: /lib/x86_64-linux-gnu/libc.so.6 (perror+0xcb7) [0x7f084f9c432d]
[  1416.018] (EE) 6: /lib/x86_64-linux-gnu/libc.so.6 (timer_settime+0x395) [0x7f084fa389e5]
[  1416.019] (EE) 7: /lib/x86_64-linux-gnu/libc.so.6 (timer_settime+0x59c) [0x7f084fa38bec]
[  1416.019] (EE) 8: /lib/x86_64-linux-gnu/libc.so.6 (__libc_free+0xb8) [0x7f084fa3d548]
[  1416.019] (EE) 9: /lib/x86_64-linux-gnu/libdrm.so.2 (drmFreeDevice+0x7d) [0x7f084febf13d]
[  1416.020] (EE) 10: /lib/x86_64-linux-gnu/libdrm.so.2 (drmFreeDevices+0x2e) [0x7f084febf2ae]
[  1416.020] (EE) 11: /lib/x86_64-linux-gnu/libnvidia-egl-gbm.so.1 (loadEGLExternalPlatform+0x8a8) [0x7f084477dd18]
[  1416.020] (EE) 12: /lib/x86_64-linux-gnu/libEGL_nvidia.so.0 (NvEglwlaf47906in+0x6e240) [0x7f08404ad480]
[  1416.020] (EE) 13: /lib/x86_64-linux-gnu/libEGL_nvidia.so.0 (NvEglwlaf47906in+0xd73c) [0x7f084044c97c]
[  1416.020] (EE) unw_get_proc_name failed: no unwind info found [-10]
[  1416.020] (EE) 14: /lib/x86_64-linux-gnu/libEGL.so.1 (?+0x0) [0x7f0844a6ead5]
[  1416.020] (EE) unw_get_proc_name failed: no unwind info found [-10]
[  1416.020] (EE) 15: /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so (?+0x0) [0x7f0844aaf3f3]
[  1416.021] (EE) unw_get_proc_name failed: no unwind info found [-10]
[  1416.021] (EE) 16: /usr/lib/xorg/modules/extensions/libglx.so (?+0x0) [0x7f084f65cbe3]
[  1416.021] (EE) unw_get_proc_name failed: no unwind info found [-10]
[  1416.021] (EE) 17: /usr/lib/xorg/modules/extensions/libglx.so (?+0x0) [0x7f084f65ba1f]
[  1416.021] (EE) 18: /usr/lib/xorg/Xorg (_CallCallbacks+0x3c) [0x556fb125002c]
[  1416.021] (EE) 19: /usr/lib/xorg/Xorg (dri3_send_open_reply+0x111f) [0x556fb138334f]
[  1416.021] (EE) 20: /usr/lib/xorg/Xorg (InitExtensions+0x89) [0x556fb12bde29]
[  1416.021] (EE) 21: /usr/lib/xorg/Xorg (InitFonts+0x1f8) [0x556fb124e968]
[  1416.022] (EE) 22: /lib/x86_64-linux-gnu/libc.so.6 (__libc_init_first+0x88) [0x7f084f9c4d68]
[  1416.022] (EE) 23: /lib/x86_64-linux-gnu/libc.so.6 (__libc_start_main+0x85) [0x7f084f9c4e25]
[  1416.022] (EE) 24: /usr/lib/xorg/Xorg (_start+0x21) [0x556fb12373f1]
[  1416.022] (EE)
[  1416.022] (EE)
Fatal server error:
[  1416.022] (EE) Caught signal 6 (Aborted). Server aborting
[  1416.022] (EE)
[  1416.022] (EE)
Please consult the The X.Org Foundation support
         at http://wiki.x.org
 for help.
[  1416.022] (EE) Please also check the log file at ".xorgxrdp.10.log" for additional information.
[  1416.022] (EE)
[  1416.022] rdpLeaveVT:
[  1416.022] (EE) Server terminated with error (1). Closing log file.

エラーの原因であるlibEGL_nvidia.soを削除すれば起動しそうだったので、libegl-nvidia0パッケージを消したところX.orgが起動しました。めでたしめでたし……ではありません。どうしてこうなった?

NVIDIAドライバを復活させる

他にも何か起きているだろうか?と調べたらCUDAが使えないし、nvidia-smiがデバイスがないと言っています。NVIDIA系の機能が全滅です。どうやらnvidia.koが消滅していて、GPUカードが認識されなくなったようです。NVIDIAドライバパッケージを再インストールするとこんなメッセージが出ました。

NVIDIAのドライバパッケージのエラーメッセージ
nvidia-kernel-dkms (535.216.03-1) を設定しています ...
Loading new nvidia-current-535.216.03 DKMS files...
Building for 6.11.10-amd64
Module build for kernel 6.11.10-amd64 was skipped since the
kernel headers for this kernel do not seem to be installed.

メッセージはカーネルヘッダをインストールしないとカーネルモジュールがビルドされないとおっしゃっています。カーネルヘッダパッケージlinux-headers-6.11.10-amd64をインストールしたところ無事/lib/modules/6.11.10-amd64/updates/dkms/の下にnvidia-current.ko.xzが生成され、CUDAが復活しました。めでたしめでたし……じゃないんだ、まだ。

DRMを復活させる

X.orgは/dev/driの下にあるデバイスファイルにアクセスするので、DRM関連のドライバも必要です。DRM用のドライバパッケージをインストールするとnvidia-current-drm.ko.xzが生成されます。たしかパッケージ名はnvidia-vdpau-driverだったと思います。

カーネルモジュールが生成されたらmodprobe nvidia-drmでロードすれば/dev/dri/card0が出現します。先ほど削除したlibegl-nvidia0パッケージを再インストールしてもX.orgの起動に失敗しなくなりました。めでたしめでたし。

とはいえxrdp経由で起動していると、DRMが有効でも"unsupported render mode"と言われてしまってHWアクセラレーションが効いてなさそうに見えます。せっかく直したのに悲しいですね……。

編集者:すずき(2024/12/05 23:07)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2024年11月28日

BIOS/UEFI画面に入る方法

PCは起動時にあるキーを押すとBIOS/UEFIの設定画面に遷移します。良く見るパターンはF1, F2, DELキー辺りですが、メーカーごとに完全にバラバラで統一感なしです。私の場合、初めて見るPCのBIOS/UEFI画面を拝みたいときはEsc, F1, F2, F12, DEL辺りを乱打しながら起動します。これでもたまに普通に起動してしまうPCがあってイライラします。

Twitterでこの話に言及したら、いくつか知らないパターンを教えてもらいましたのでそれも紹介します。

こんなものに独自性を出して誰が幸せになるんでしょうか?実に不毛です。PCメーカーとBIOSメーカーはさっさとキーを統一してください……。

編集者:すずき(2024/12/01 00:53)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2024年11月25日

libjpeg-turboのライブラリは2つある

目次: Linux

高速なJPEGデコード/エンコードライブラリで有名なlibjpeg-turboですが、ライブラリというかAPIが2系統あります(公式ドキュメントへのリンクlibjpeg-turboのソースコード)。系統その1はlibjpeg(IJG: Independent JPEG Groupのライブラリ)互換のAPIで、系統その2は独自のTurboJPEG APIです。パッケージの名前もややこしくて、しばらくしたら忘れてしまいそうなのでメモしておきます。

libjpeg系
ライブラリlibjpeg.so、ヘッダjpeglib.h、パッケージlibjpeg-turbo8、API名はjpeg_から始まります。
TurboJPEG系
ライブラリlibturbojpeg.so、ヘッダturbojpeg.h、パッケージlibturbojpeg、API名はtj(バージョン2.x系)もしくはtj3(バージョン3.x系)から始まります。

各パッケージに含まれるファイルも示しておきます。

Ubuntu 22.04 AArch64向け各パッケージのファイル一覧
libjpeg-turbo8

/usr/lib/aarch64-linux-gnu/libjpeg.so.8
/usr/lib/aarch64-linux-gnu/libjpeg.so.8.2.2

libjpeg-turbo8-dev

/usr/include/aarch64-linux-gnu/jconfig.h
/usr/include/jerror.h
/usr/include/jmorecfg.h
/usr/include/jpegint.h
/usr/include/jpeglib.h
/usr/lib/aarch64-linux-gnu/libjpeg.a
/usr/lib/aarch64-linux-gnu/libjpeg.so
/usr/lib/aarch64-linux-gnu/pkgconfig/libjpeg.pc


libturbojpeg

/usr/lib/aarch64-linux-gnu/libturbojpeg.so.0
/usr/lib/aarch64-linux-gnu/libturbojpeg.so.0.2.0

libturbojpeg0-dev

/usr/include/turbojpeg.h
/usr/lib/aarch64-linux-gnu/libturbojpeg.a
/usr/lib/aarch64-linux-gnu/libturbojpeg.so
/usr/lib/aarch64-linux-gnu/pkgconfig/libturbojpeg.pc

例としてUbuntu 22.04 AArch64向けのものを示しましたが、他のアーキテクチャやバージョンでも構造は同じです。

編集者:すずき(2024/12/09 00:30)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2024年11月22日

nvJPEGとNVJPGとJetson APIその3 - nvJPEG encode API

目次: Linux

半年経ったら完全に忘れるのでメモします。最近JPEGのデコードエンコードが必要になって色々調べていました。NVIDIA GPUとCUDAを使ってJPEGが扱えるそうで、API名はnvJPEGだそうです(nvJPEGのAPIドキュメント)。

nvJPEG encoding

前回まではデコード処理でした。今回はエンコードのAPIをご紹介します。decoupled decodingのような複雑なAPIは存在しないようです。

Raw YUV420の画素データを置くメモリを確保する際はcudaMalloc()ではなく、cudaMallocHost()を使う点がデコードと異なります。エンコードはこんな感じでした。

nvJPEG encodingのAPI呼び出し順

	cudaStream_t stream = nullptr;
	nvjpegHandle_t nvj_handle = nullptr;
	nvjpegEncoderState_t nvj_state = nullptr;
	nvjpegEncoderParams_t nvj_param = nullptr;
	nvjpegImage_t inbuf = {0};
	uint8_t *jpegbuf = nullptr;
	size_t bufsize = 0;
	int r;

	// Create
	cudaStreamCreateWithFlags(&stream, cudaStreamNonBlocking);

	nvjpegCreateEx(NVJPEG_BACKEND_DEFAULT, nullptr, nullptr, NVJPEG_FLAGS_DEFAULT, &nvj_handle);
	nvjpegEncoderStateCreate(nvj_handle, &nvj_state, stream);
	nvjpegEncoderParamsCreate(nvj_handle, &nvj_param, stream);

	// Set JPEG parameters
	nvjpegEncoderParamsSetQuality(nvj_param, 80, stream);
	nvjpegEncoderParamsSetSamplingFactors(nvj_param, NVJPEG_CSS_420, stream);


	// 2のべき乗境界に切り上げる
#define ALIGN_2N(a, b)    (((a) + (b) - 1) & ~((b) - 1))

	inbuf.pitch[0] = ALIGN_2N(width, 256);
	inbuf.pitch[1] = ALIGN_2N(width, 256);
	inbuf.pitch[2] = ALIGN_2N(width, 256);
	cudaMallocHost((void **)&inbuf.channel[0], inbuf.pitch[0] * height);
	cudaMallocHost((void **)&inbuf.channel[1], inbuf.pitch[1] * height);
	cudaMallocHost((void **)&inbuf.channel[2], inbuf.pitch[2] * height);

	bufsize = width * height * 3 / 2;
	jpegbuf = (uint8_t *)malloc(bufsize);

	// YUVデータをinbufにロードする
	// 詳細はソースコードを参照

	// Encoding
	nvjpegChromaSubsampling_t jpegsamp = NVJPEG_CSS_420;
	size_t jpegsize = bufsize;

	nvjpegEncodeYUV(nvj_handle, nvj_state, nvj_param, &inbuf, jpegsamp, width, height, stream);
	nvjpegEncodeRetrieveBitstream(nvj_handle, nvj_state, jpegbuf, &jpegsize, stream);

	cudaStreamSynchronize(stream);

	// Destroy
	free(jpegbuf);

	cudaFree(inbuf.channel[0]);
	cudaFree(inbuf.channel[1]);
	cudaFree(inbuf.channel[2]);

	nvjpegEncoderParamsDestroy(nvj_param);
	nvjpegEncoderStateDestroy(nvj_state);
	nvjpegDestroy(nvj_handle);

	cudaStreamDestroy(stream);

YUV420Pのロード部分は本質と関係ないことと、若干長いので省略しました。nvJPEG APIの数は少なくてシンプルです。nvJPEGやNVJPGは機械学習用データ(JPEGファイルのことが多いらしい)を高速に入力するため?らしく、デコード命なのでしょう。エンコードもできるけど主眼ではないから、APIもシンプルなものしかないのかな?

実行

前回同様にソースコードを置いておきます。

使い方はコードの先頭にコメントで書いている通りですが、ここでも説明しておきます。引数はありません。ファイル名test_420.yuvのRaw YUV420ファイルを読み込んで、ファイル名simple_420.jpgのJPEGファイルを書き出します。

コンパイル、結果確認
$ g++ -g -O2 -Wall 20241120_nvjpeg_simple_enc.cpp -lnvjpeg -lcudart
$ ./a.out

$ ffplay -i simple_420.jpg

エンコード結果はJPEGです。ffplayでも普段お使いの画像ビューアでも、何を使って確認しても構いません。

編集者:すずき(2024/12/08 15:24)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
2024年12月4日 >>> 2024年11月21日
link もっと後

管理用メニュー

link 記事を新規作成

<2024>
<<<12>>>
1234567
891011121314
15161718192021
22232425262728
293031----

最近のコメント5件

  • link 21年9月20日
    すずきさん (11/19 01:04)
    「It was my pleasure.」
  • link 21年9月20日
    whtさん (11/17 23:41)
    「This blog solves my ...」
  • link 24年10月1日
    すずきさん (10/06 03:41)
    「xrdpで十分動作しているので、Wayl...」
  • link 24年10月1日
    hdkさん (10/03 19:05)
    「GNOMEをお使いでしたら今はWayla...」
  • link 24年10月1日
    すずきさん (10/03 10:12)
    「私は逆にVNCサーバーに繋ぐ使い方をした...」

最近の記事3件

  • link 24年11月25日
    すずき (12/09 00:30)
    「[libjpeg-turboのライブラリは2つある] 目次: Linux高速なJPEGデコード/エンコードライブラリで有名なl...」
  • link 24年12月6日
    すずき (12/09 00:08)
    「[YUVのrawvideo画像を生成、表示する方法] 目次: LinuxFFMPEG(ffmpeg)を使ってYUV420やYU...」
  • link 24年11月18日
    すずき (12/08 23:40)
    「[nvJPEGとNVJPGとJetson APIその1 - nvJPEG decoupled API] 目次: Linux半年...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 12/09 00:30