コグノスケ


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

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

2024年12月13日

nvJPEGとNVJPGとJetson APIその6 - Jetson Linux API JPEG encode編

目次: Linux

半年経ったら完全に忘れるのでメモします。最近JPEGのデコードエンコードが必要になって色々調べていました。Jetson特有のAPI群がありまして、API名はJetson Linux API(のなかのMultimedia APIs)だそうです(Jetson Linux APIドキュメント)。ハードウェアJPEGデコーダ/エンコーダ(NVJPG)を自動的に使用してくれます。

Jetson JPEG encoding

今回はエンコードのAPIをご紹介します。APIの使い方は簡単です。こんな感じでした。

Jetson Linux API JPEG encode API呼び出し順

	NvJPEGEncoder *jpgenc = nullptr;
	NvBuffer *inbuf = nullptr;
	uint8_t *buffer = nullptr;
	size_t bufsize = 0;
	int r;

	// Create
	jpgenc = NvJPEGEncoder::createJPEGEncoder("jpgenc");

	// Align
#define ALIGN_2N(a, b)    (((a) + (b) - 1) & ~((b) - 1))

	NvBuffer::NvBufferPlaneFormat fmts[3];

	fmts[0].width = width;
	fmts[0].height = height;
	fmts[0].bytesperpixel = 1;
	fmts[0].stride = ALIGN_2N(width, 256);
	fmts[0].sizeimage = fmts[0].stride * fmts[0].height;
	fmts[1].width = width / 2;
	fmts[1].height = height / 2;
	fmts[1].bytesperpixel = 1;
	fmts[1].stride = ALIGN_2N(width / 2, 256);
	fmts[1].sizeimage = fmts[1].stride * fmts[1].height;
	fmts[2].width = width / 2;
	fmts[2].height = height / 2;
	fmts[2].bytesperpixel = 1;
	fmts[2].stride = ALIGN_2N(width / 2, 256);
	fmts[2].sizeimage = fmts[2].stride * fmts[2].height;

	inbuf = new NvBuffer(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, V4L2_MEMORY_USERPTR, 3, fmts, 0);
	if (!inbuf) {
		printf("error in %s:%d\n", __func__, __LINE__);
		return -1;
	}

	r = inbuf->allocateMemory();
	if (r) {
		printf("error in %s:%d\n", __func__, __LINE__);
		return -1;
	}

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

	// Encoding
	uint8_t *jpegbuf = buffer;
	size_t jpegsize = bufsize;
	int quality = 80;
	r = jpgenc->encodeFromBuffer(*inbuf, JCS_YCbCr, &jpegbuf, jpegsize, quality);


	// Destroy
	free(buffer);

	delete inbuf;
	delete jpgenc;

若干NvBufferの確保がややこしいです(参考: NvBufferPlaneのドキュメント、その隣のNvBufferPlaneFormatも参考になります)けど、基本的にはencodeFromBuffer()を呼ぶだけです。

実行

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

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

コンパイル、結果確認
$ g++ -g -O2 -g -Wall \
    -I jetson_multimedia_api/include/ \
    -I jetson_multimedia_api/include/libjpeg-8b/ \
    jetson_multimedia_api/samples/common/classes/NvJpegDecoder.cpp \
    jetson_multimedia_api/samples/common/classes/NvJpegEncoder.cpp \
    jetson_multimedia_api/samples/common/classes/NvBuffer.cpp \
    jetson_multimedia_api/samples/common/classes/NvElement.cpp \
    jetson_multimedia_api/samples/common/classes/NvElementProfiler.cpp \
    jetson_multimedia_api/samples/common/classes/NvLogging.cpp \
    jetson_enc.cpp \
    -L /usr/lib/aarch64-linux-gnu/nvidia/ \
    -lnvjpeg

$ ./a.out

$ ffplay -i jetson_420.jpg

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

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

コメント一覧

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



2024年12月11日

nvJPEGとNVJPGとJetson APIその5 - Jetson Linux API JPEG decode編

目次: Linux

半年経ったら完全に忘れるのでメモします。最近JPEGのデコードエンコードが必要になって色々調べていました。Jetson特有のAPI群がありまして、API名はJetson Linux API(のなかのMultimedia APIs)だそうです(Jetson Linux APIドキュメント)。ハードウェアJPEGデコーダ/エンコーダ(NVJPG)を自動的に使用してくれます。

Jetson JPEG decoding

今回はデコードのAPIをご紹介します。APIの使い方は簡単でこんな感じでした。

Jetson Linux API JPEG decode API呼び出し順

	NvJPEGDecoder *jpgdec = nullptr;
	NvBuffer *outbuf = nullptr;
	int r;

	// Create
	jpgdec = NvJPEGDecoder::createJPEGDecoder("jpgdec");

	// Decoding
	uint32_t jpeg_pixfmt;
	uint32_t jpeg_width;
	uint32_t jpeg_height;
	r = jpgdec->decodeToBuffer(&outbuf, jpegbuf, jpegsize, &jpeg_pixfmt, &jpeg_width, &jpeg_height);

	// Destroy
	delete outbuf;
	delete jpgdec;

注意すべき点は2つあります。1つ目はdecodeToBuffer()が勝手にoutbufを確保して返してくるので、delete outbufしなければならないことです。Turbo JPEGと異なり、予めバッファを確保しておけばメモリ確保処理を回避するような仕組みはなさそうでした。イマイチです。

2つ目はProgressive JPEGがデコードできないことです。デコードしようとするとdecodeToBuffer()でハングします。どんなJPEGファイルが来るかわからない状況で使う場合、JPEGファイルの中身をチェックしてBaseline JPEGはハードウェアデコード、Progressive JPEGはソフトウェアデコードする仕組みが必要です。

しかし前に話したとおりJetson APIの裏にいるlibnvjpeg.soが謎にIJG JPEGのAPIを実装しているため、本家IJG JPEGのlibjpeg.soがリンクできません。この状態でどうやってProgressive JPEGをソフトウェアデコードすれば良いのでしょう。Jetson APIの裏にいるlibnvjpeg.soをIJG JPEGだと思って呼べば動作するんでしょうか?

実行

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

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

コンパイル、結果確認
$ g++ -g -O2 -g -Wall \
    -I jetson_multimedia_api/include/ \
    -I jetson_multimedia_api/include/libjpeg-8b/ \
    jetson_multimedia_api/samples/common/classes/NvJpegDecoder.cpp \
    jetson_multimedia_api/samples/common/classes/NvJpegEncoder.cpp \
    jetson_multimedia_api/samples/common/classes/NvBuffer.cpp \
    jetson_multimedia_api/samples/common/classes/NvElement.cpp \
    jetson_multimedia_api/samples/common/classes/NvElementProfiler.cpp \
    jetson_multimedia_api/samples/common/classes/NvLogging.cpp \
    jetson_dec.cpp \
    -L /usr/lib/aarch64-linux-gnu/nvidia/ \
    -lnvjpeg

$ ./a.out

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

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

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

コメント一覧

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



2024年12月9日

nvJPEGとNVJPGとJetson APIその4 - Jetson Linux API

目次: Linux

半年経ったら完全に忘れるのでメモします。最近JPEGのデコードエンコードが必要になって色々調べていました。Jetson特有のAPI群がありまして、API名はJetson Linux API(のなかのMultimedia APIs)だそうです(Jetson Linux APIドキュメント)。

セットアップ方法

Jetsonを持っていないと使えません。最新機種はJetson AGX OrinかJetson Orin Nanoですが、AGX Orinは40万円、Orin Nanoは10万円近くするボッタクリ価格です。Xavierまではそこそこ安かったのにねえ……。

Jetson Linux APIがもしシステムにインストールされていなければapt-get install nvidia-l4t-jetson-multimedia-apiで使えるようになるはずです。Jetson用のパッケージは一覧があります(一覧へのリンク)ので、手動でダウンロードしたいときにはありがたいですね。

Jetson APIの実装

Jetson Linux APIは実装も使い方もかなり独特というか……はっきり言って変です。

変な点その1、APIの提供方法です。API実装は/usr/src/jetson_multimedia_api/samples/common/classesにソースコードで置かれています。ライセンスはBSDライセンスです。なぜ*.soや*.aで提供しないのでしょう?

後ほど紹介するJPEGデコード、エンコードのコンパイルにはNvJpegDecoder.cppとNvJpegEncoder.cppとお供のツール類が必要ですから、あえてディレクトリ名を省かずに書くと、下記のようなコマンドでコンパイルできます。面倒ならばjetson_multimedia_api/samples/common/classes/*.cppで良いです、NVIDIA提供のサンプルもワイルドカードを使っていました。

Jetson Linux APIのJPEG機能を使ったアプリケーションのコンパイル方法

g++ -O2 -g -Wall \
  -I jetson_multimedia_api/include/ \
  -I jetson_multimedia_api/include/libjpeg-8b/ \
  jetson_multimedia_api/samples/common/classes/NvJpegDecoder.cpp \
  jetson_multimedia_api/samples/common/classes/NvJpegEncoder.cpp \
  jetson_multimedia_api/samples/common/classes/NvBuffer.cpp \
  jetson_multimedia_api/samples/common/classes/NvElement.cpp \
  jetson_multimedia_api/samples/common/classes/NvElementProfiler.cpp \
  jetson_multimedia_api/samples/common/classes/NvLogging.cpp \
  (自分のソースコード) \
  -L /usr/lib/aarch64-linux-gnu/nvidia/ \
  -lnvjpeg

変な点その2、JPEG機能のヘッダ名です。jetson_multimedia_api/include/NvJpegDecoder.hを見ると、JPEG関連の機能はjetson_multimedia_api/include/libjpeg-8b/jpeglib.hにあるjpeglib.hヘッダにて定義されています。そう、このヘッダ名はIJG JPEGライブラリのヘッダと同じ名前です。なぜそんな場所にヘッダを置くのか?IJG JPEGと互換性がない(APIが増えている)のになぜ同じ名前?

変な点その3、JPEG機能のライブラリ名です。jpeglib.hだからlibjpeg.soかと思うじゃないですか、それは罠でリンクすべきはlibnvjpeg.soです。良くないことにlibjpeg.soも存在していて、さらに良くないことにデコード機能だけ使っている場合は間違ってlibjpeg.soを指定してもリンクできてしまい、

libjpeg.soを間違ってリンクしたときの実行時エラー
$ ./a.out

JPEG parameter struct mismatch: library thinks size is 656, caller expects 776

実行時にこのようなエラーが出るだけでうんともすんとも動きません。IJG JPEGと同じAPI名にするならTurbo JPEGのようにlibjpeg.soの方も置き換えれば問題は起きなかったのに、なぜ中途半端な実装に?

変な点その4、Jetson APIとNVJPEGの衝突です。以前紹介したNVJPEGはJetsonでも動きますがインストールはオススメしないです。

  • Jetsonのlibnvjpeg.so: IJG JPEGみたいなAPI実装、API名はjpeg_から始まります、インストール場所は/usr/lib/aarch64-linux-gnu/nvidiaです。
  • CUDAのlibnvjpeg.so: NVJPEGのAPI実装、API名はnvjpegから始まります、インストール場所は/usr/local/cuda-12.x/lib64らへんが多いです。

この2つが両方ともインストールされ、同じ-lnvjpegでリンクしてもライブラリパスによってリンクエラーになったり実行時のダイナミックリンクエラーになります。全く違う機能とAPI体系なのに、なぜ同じライブラリ名になっているの?

JPEGデコードの話は次にしたいと思います。Jetsonは適当なのか突貫なのか知りませんが、すっごい変だしちょっと使っただけなのに無限に疑問が出てきます。みんな良くこんなの使ってるなあ……。

編集者:すずき(2024/12/19 11:01)

コメント一覧

  • hyfanさん(2025/03/13 07:21)
    Hello from Santa Clara, CA! Landed on your page with the same complaints. Spend all the effort setting Jetson Multimedia API up only to find it is conflicting with libjpeg. Bummer!
  • すずきさん(2025/03/14 00:42)
    Thanks for your comment. Agree with you. I could not find the way to use both IJG JPEG and Jetson NVJPG in same app...
open/close この記事にコメントする



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

管理用メニュー

link 記事を新規作成

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

最近のコメント20件

  • link 24年6月17日
    すずきさん (06/05 23:32)
    「Thnaks for your info...」
  • link 24年6月17日
    Bobさん (06/04 09:25)
    「BindIPv6Only=no does...」
  • link 18年8月12日
    すずきさん (05/29 16:57)
    「コメントありがとうございます。\n\nこ...」
  • link 18年8月12日
    ARM926EJ-Sさん (05/29 14:27)
    「この記事が書かれたのは2018年ですが、...」
  • link 17年9月3日
    すずきさん (05/26 23:59)
    「>ちょさんさん\nご参考になれば幸いです...」
  • link 17年9月3日
    ちょさんさん (05/26 20:34)
    「自分もこの機種と全く同じCN-SP700...」
  • link 25年2月19日
    katanaさん (03/21 05:30)
    「katana」
  • link 25年1月23日
    katanaさん (03/20 18:50)
    「katana」
  • link 24年12月9日
    すずきさん (03/14 00:42)
    「Thanks for your comm...」
  • link 24年12月9日
    hyfanさん (03/13 07:21)
    「Hello from Santa Cla...」
  • link 25年2月10日
    すずきさん (02/13 02:03)
    「解読しました。なるほど、exitの引数が...」
  • link 25年2月10日
    hdkさん (02/12 08:06)
    「あ、すみません、比較元に間違いがありまし...」
  • link 25年2月10日
    hdkさん (02/12 08:01)
    「なるほど、最後に%rdiを0にするのはこ...」
  • link 20年6月29日
    すずきさん (02/12 00:12)
    「お役に立ったようであれば幸いです。」
  • link 25年2月7日
    すずきさん (02/12 00:11)
    「なるほど。動きそうなのになんで動かないん...」
  • link 20年6月29日
    うどん?さん (02/11 17:04)
    「私のLenovoタブレットも87%にした...」
  • link 25年2月7日
    hdkさん (02/10 22:31)
    「push $0x3e0002のかわりにm...」
  • link 20年7月2日
    すずきさん (01/30 22:40)
    「ちょっと何を言っているのか良くわからなか...」
  • link 20年7月2日
    初心者さん (01/29 07:34)
    「Steamを見たとき、AmazonよりU...」
  • link 21年9月20日
    すずきさん (11/19 01:04)
    「It was my pleasure.」

最近の記事3件

  • link 21年12月28日
    すずき (06/22 23:33)
    「[ゲーム - まとめリンク] 目次: ゲーム一覧が欲しくなったので作りました。Wizardry(囚われし亡霊の街)敵が強すぎる...」
  • link 25年6月19日
    すずき (06/22 23:33)
    「[歴代据え置きハードのCPUとGPU] 目次: ゲーム最近、据え置きハードのCPUとGPUがNVIDIAとAMDに収束していま...」
  • link 25年6月18日
    すずき (06/22 23:33)
    「[Nintendo Switch 2当選] 目次: ゲームSwitch 2の抽選4回目で当選してました。わーい。今回も落選だっ...」
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 2025年
open/close 過去日記について

その他の情報

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

合計:  counter total
本日:  counter today

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

最終更新: 06/22 23:33