コグノスケ


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

link もっと前
2024年12月20日 >>> 2024年12月7日
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月20日 >>> 2024年12月7日
link もっと後

管理用メニュー

link 記事を新規作成

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

最近のコメント5件

  • link 20年8月24日
    すずきさん (08/30 22:06)
    「ですね、自分も今はPulseAudioを...」
  • link 20年8月24日
    hdkさん (08/29 09:32)
    「ALSA懐かしい... PulseAud...」
  • link 16年2月14日
    すずきさん (08/04 01:31)
    「お役に立ったようでしたら幸いです。」
  • link 16年2月14日
    enc28j60さん (08/03 17:40)
    「ちょうど詰まっていたところです。\n非常...」
  • link 25年7月20日
    すずきさん (07/30 00:10)
    「ギクシャクするのは減速時の2速シフトダウ...」

最近の記事20件

  • link 23年4月10日
    すずき (08/31 12:58)
    「[Linux - まとめリンク] 目次: Linux関係の深いまとめリンク。目次: RISC-V目次: ROCK64/ROCK...」
  • link 25年8月25日
    すずき (08/31 12:58)
    「[LinuxでPTPを使う方法] 目次: LinuxNTPより精密な時刻同期の方法PTP(Precision Time Pro...」
  • link 23年5月15日
    すずき (08/30 17:58)
    「[車 - まとめリンク] 目次: 車三菱FTOの話。群馬県へのドライブ1群馬県へのドライブ2将来車を買い替えるとしたら?FTO...」
  • link 25年8月30日
    すずき (08/30 17:58)
    「[日本のガソリンスタンド] 目次: 車ガソリンスタンドは統廃合が進んで、ENEOS、コスモ、出光(apollostation)...」
  • link 20年8月24日
    すずき (08/28 23:30)
    「[ALSAループバックデバイスで簡易リモート再生] 目次: ALSAデスクトップPCにはスピーカーを繋いでいませんが、たまに音...」
  • link 23年6月1日
    すずき (08/21 01:43)
    「[自宅サーバー - まとめリンク] 目次: 自宅サーバーこの日記システム、Wikiの話。カウンターをPerlからPHPに移植日...」
  • link 13年5月10日
    すずき (08/21 01:43)
    「[Debian 7.0 Wheezyにアップデート] 目次: 自宅サーバーリリースノートを読みつつ、apt-get updat...」
  • link 15年4月30日
    すずき (08/21 01:42)
    「[Debian 8.0 Jessieにアップデート] 目次: 自宅サーバーDebianのアップデートが来ていたので、試しに職場...」
  • link 23年6月13日
    すずき (08/21 01:42)
    「[Debian 12 Bookwormにアップデート] 目次: 自宅サーバーDebianの更新はとても簡単でありがたいですが、...」
  • link 25年8月17日
    すずき (08/21 01:40)
    「[Debian 13 Trixieにアップデート] 目次: 自宅サーバー先日8/9にDebian 13がリリースされました。コ...」
  • link 25年8月20日
    すずき (08/21 01:38)
    「[パスポートのオンライン申請] 海外出張の予定が発生してパスポートが必要になりました。以前発行した10年パスポートの発行日を見...」
  • link 25年8月15日
    すずき (08/17 06:26)
    「[帰省終わり、東京へ] 帰ってきました。東京に降り立った瞬間に暑くてイヤになりました……。朝10時...」
  • link 25年8月11日
    すずき (08/17 06:20)
    「[帰省始まり、北海道へ] 北海道に帰省しました。今年は北海道も30℃超え連発で割と暑い年とはいえ、東京と決定的に違う点は湿度で...」
  • link 25年7月25日
    すずき (07/30 01:36)
    「[電装系が微妙なジャガーさん] 目次: 車車を買い替えてから1週間くらい経ちました。通勤路以外は幹線道路や高速をメインにしばし...」
  • link 19年9月1日
    すずき (07/30 01:36)
    「[カーナビを買いました] 目次: 車一昨年にカーナビが壊れて(2017年9月3日の日記参照)以来、カーナビを使わず過ごしていま...」
  • link 25年7月20日
    すずき (07/22 01:56)
    「[ジャガーXE Sを買いました] 目次: 車車を買い替えました。ジャガーXE Sです。マイナー車すぎて会社の人たちもあまり知ら...」
  • link 24年7月7日
    すずき (07/22 00:00)
    「[PC - まとめリンク] 目次: PC一覧が欲しくなったので作りました。 スピーカーGX-D90故障ノートPCの内蔵サウンド...」
  • link 21年4月16日
    すずき (07/21 23:59)
    「[ドキュメントスキャナーで書類を電子化] 目次: PC我が家の本棚は広い方ではないのに、ほとんど参照しない書類が幅を取っていて...」
  • link 21年4月6日
    すずき (07/21 23:58)
    「[ディスプレイアーム] 目次: PC机の奥行きが60cmのためか、ディスプレイの足がキーボードとぶつかって若干邪魔なのと、前か...」
  • link 21年2月27日
    すずき (07/21 23:56)
    「[新キーボードMajestouch購入] 目次: PC先日の在宅勤務環境改善(2021年2月12日の日記参照)にて、デュアルデ...」
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 www.katsuster.net
RDFファイル RSS 1.0

最終更新: 08/31 12:58