目次: Linux
FFMPEG(ffmpeg)を使ってYUV420やYUV444のrawvideo画像を生成する方法です。元にしたJPEG画像の解像度は1920x1440なので、YUV444の場合は1920 * 1440 * 3 = 8294400バイト、YUV420の場合は1920 * 1440 * 1.5 = 4147200バイトになるはずです。
$ ffmpeg -i test_420.jpg -f rawvideo -pix_fmt yuvj444p output_444.yuv $ ls -la output.yuv -rw-r--r-- 1 katsuhiro katsuhiro 8294400 12月 4 00:43 output_444.yuv $ ffmpeg -i test_420.jpg -f rawvideo -pix_fmt yuvj420p output_420.yuv $ ls -la output_420.yuv -rw-r--r-- 1 katsuhiro katsuhiro 4147200 12月 4 00:44 output_420.yuv
FFMPEG(ffplay)を使ってYUV420やYUV444のrawvideo画像を表示する方法です。ffmpegとffplayはピクセルフォーマットのオプションが微妙に違うのが嫌なところですね……。
$ ffplay -f rawvideo -video_size 1920x1440 -pixel_format yuv420p output_420.yuv
目次: 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になるのでご注意ください。
デコードと対になるような作りです。libjpeg-turboはとても簡単でありがたい。
tj_handle = tjInitCompress();
// Rawvideo
img_stride[0] = width;
img_stride[1] = width / 2;
img_stride[2] = width / 2;
img_buf[0] = (uint8_t *)malloc(img_stride[0] * height);
img_buf[1] = (uint8_t *)malloc(img_stride[1] * height / 2);
img_buf[2] = (uint8_t *)malloc(img_stride[2] * height / 2);
// Encoding
tjCompressFromYUVPlanes(tj_handle, (const uint8_t **)img_buf, width, img_stride, height, subsamp, &jpegbuf, &jpegsize, quality, 0);
// Destroy
free(img_buf[0]);
free(img_buf[1]);
free(img_buf[2]);
tjDestroy(tj_handle);
デコード同様にinitしてエンコードするだけです。デコードと違う点が1つあって、エンコードではJPEGを格納するバッファ(上記だとjpegbuf)のサイズが不明である問題があります。解決方法は2つあります。連続でエンコードする場合など、メモリの確保解放を減らしたい場合は1番目が良いでしょう。1枚だけエンコードするだけならどちらでも構いません。
やってはいけないのが1番目だけどバッファサイズが不足することです。エンコード関数が勝手にバッファmalloc()してポインタを返してきて、元々確保していたバッファが行方不明になってしまいます。メモリリークするので注意が必要です。
私のコードは1番目の方法をとっていて、バッファサイズはYUV420つまり非圧縮時のサイズです。非圧縮時のサイズを上回ることはほぼないらしいのであまり問題ないはず。気になる人はlibjpeg-turboのAPIにJPEGサイズの最大値を返すtjBufSize()があるので、APIが返す値でjpegbufを確保するのが正しいお作法です。
ソースコードを置いておきます。
使い方はコードの先頭にコメントで書いている通りですが、ここでも説明しておきます。引数はありません。ファイル名test_420.yuvのRaw YUV420ファイルを読み込んで、ファイル名turbo2_420.jpgのJPEGファイルを書き出します。
$ g++ -g -O2 -Wall 20241205_turbo2_enc.cpp -lturbojpeg $ ./a.out $ ffplay -i turbo2_420.jpg
エンコード結果はJPEGです。ffplayでも普段お使いの画像ビューアでも、何を使って確認しても構いません。
目次: 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はとても簡単です。
// 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を使うと便利です。
目次: Linux
Debian Testingのapt-get updateをしたら、xrdp経由で起動している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が起動しました。めでたしめでたし……ではありません。どうしてこうなった?
他にも何か起きているだろうか?と調べたらCUDAが使えないし、nvidia-smiがデバイスがないと言っています。NVIDIA系の機能が全滅です。どうやらnvidia.koが消滅していて、GPUカードが認識されなくなったようです。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が復活しました。めでたしめでたし……じゃないんだ、まだ。
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 | > | >> | ||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | - | - | - | - |
合計:
本日: