コグノスケ


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ドキュメント)。

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/15 05:15)

コメント一覧

  • コメントはありません。
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ドキュメント)。

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/15 05:10)

コメント一覧

  • コメントはありません。
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_から始まります。
  • CUDAのlibnvjpeg.so: NVJPEGのAPI実装、API名はnvjpegから始まります。

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

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

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

コメント一覧

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



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

管理用メニュー

link 記事を新規作成

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

最近のコメント20件

  • 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サーバーに繋ぐ使い方をした...」
  • link 24年10月1日
    hdkさん (10/03 08:30)
    「おー、面白いですね。xrdpはすでに立ち...」
  • link 14年6月13日
    2048player...さん (09/26 01:04)
    「最後に、この式を出すのに紙4枚(A4)も...」
  • link 14年6月13日
    2048playerさん (09/26 01:00)
    「今のところ最も簡略化した式です。\n--...」
  • link 14年6月13日
    2048playerさん (09/16 01:00)
    「返信ありがとうございます。\nコメントが...」
  • link 14年6月13日
    すずきさん (09/12 21:19)
    「コメントありがとうございます。同じ結果に...」
  • link 14年6月13日
    2048playerさん (09/08 17:30)
    「私も2048の最高スコアを求めたのですが...」
  • link 14年6月13日
    2048さん (09/08 17:16)
    「私も2048の最高スコアを求めたのですが...」
  • link 14年6月13日
    2048playerさん (09/08 16:10)
    「私も2048の最高スコアを求めたのですが...」
  • link 02年8月4日
    lxbfYeaaさん (07/12 10:11)
    「555」
  • link 24年6月17日
    すずきさん (06/23 00:12)
    「ありがとうございます。バルコニーではない...」
  • link 24年6月17日
    hdkさん (06/22 22:08)
    「GPSの最初の同期を取る時は見晴らしのい...」
  • link 24年5月16日
    すずきさん (05/21 11:41)
    「あー、確かにdpkg-reconfigu...」
  • link 24年5月16日
    hdkさん (05/21 08:55)
    「システム全体のlocale設定はDebi...」
  • link 24年5月17日
    すずきさん (05/20 13:16)
    「そうですねえ、普通はStandardなの...」
  • link 24年5月17日
    hdkさん (05/19 07:45)
    「なるほど、そういうことなんですね。Exc...」

最近の記事3件

  • link 24年12月9日
    すずき (12/15 15:17)
    「[nvJPEGとNVJPGとJetson APIその4 - Jetson Linux API] 目次: Linux半年経ったら...」
  • link 24年12月13日
    すずき (12/15 05:15)
    「[nvJPEGとNVJPGとJetson APIその6 - Jetson Linux API JPEG encode編] 目次...」
  • link 23年4月10日
    すずき (12/15 05:13)
    「[Linux - まとめリンク] 目次: Linux関係の深いまとめリンク。目次: RISC-V目次: ROCK64/ROCK...」
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 www2.katsuster.net
RDFファイル RSS 1.0

最終更新: 12/15 15:17