コグノスケ


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

link もっと前
2024年9月28日 >>> 2024年9月15日
link もっと後

2024年9月28日

TAS動画をニコニコ動画にアップロードできない

クラッキングでぶっ壊されてしまったニコニコ動画が復活し、シン・ニコニコ動画になって帰ってきました。いちユーザーとしては嬉しい気分でいっぱいです。

しかし前と比べて困ったことが起きていて、BizHawkで出力した動画をシン・ニコニコ動画にアップロードしようとすると「この動画の映像形式には対応していません」とエラーが出てしまって投稿できません。試行錯誤の末、解決方法を見つけたのでメモしておきます。

端的に言えば原因はピクセルフォーマットでした。BizHawkは特に何も言わないとYUV444で出力しますが、ニコニコ動画はYUV420でないと受け付けてくれないようです。どこにもそんな制約は書いていないため、仕様か?バグか?どちらともわかりません。

YUV420にする方法ですけども、BizHawkの出力設定を[Custom]にして、下記のようにピクセルフォーマットを明示的に指定すればYUV420で出力してくれました。

BizHawkの[Custom]動画出力設定の例
-c:a aac -c:v libx264 -preset ultrafast -pix_fmt yuv420p -f mp4

もしすでにYUV444で出力済みの動画ならば、ffmpegを使って再エンコードすれば良いです。

ピクセルフォーマットYUV420で再エンコード
$ ffmpeg -i input.mp4 \
    -vcodec libx264 -vb 2048000 -r 60 -s 1280x720 -pix_fmt yuv420p \
    -acodec aac -ar 44100 -ab 192000 output.mp4

動画ビットレート(-vb)、フレームレート(-r)、動画サイズ(-s)は元の動画に応じて調整してください。

編集者:すずき(2024/10/03 01:07)

コメント一覧

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



2024年9月24日

OpenSBIを調べる - CPUの列挙

目次: Linux

以前、OpenSBIがRISC-V CPUの拡張機能をどのように認識し有効にするか調べました。今回はどのようにCPUの数を認識するか調べます。OpenSBIのプラットフォームは今まで同様にgenericを使います。

実はそんなに難しくなく、デバイスツリーの/cpuノードを読みに行くだけのようです。/cpuノードの例としてQEMU virtマシン、4CPUで起動したときにQEMUが生成するデバイスツリーを下記に示します。長いのでCPU_2, 3は省略しています。名前やラベル、regが2や3になるだけです。

デバイスツリーのCPUノードの例
/ {
	cpus {
		#address-cells = <1>;
		#size-cells = <0>;
		timebase-frequency = <10000000>;

		cpu0: cpu@0 {
			compatible = "riscv";
			reg = <0>;
			device_type = "cpu";
			riscv,cbop-block-size = <64>;
			riscv,cboz-block-size = <64>;
			riscv,cbom-block-size = <64>;
			riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "h",
				"zic64b", "zicbom", "zicbop", "zicboz",
				"ziccamoa", "ziccif", "zicclsm", "ziccrse",
				"zicntr", "zicsr", "zifencei", "zihintntl",
				"zihintpause", "zihpm", "za64rs", "zawrs",
				"zfa", "zca", "zcd", "zba", "zbb", "zbc", "zbs",
				"ssccptr", "sscounterenw", "sstc", "sstvala",
				"sstvecd", "svadu";
			riscv,isa-base = "rv64i";
			riscv,isa = "rv64imafdch_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_zicntr_zicsr_zifencei_zihintntl_zihintpause_zihpm_za64rs_zawrs_zfa_zca_zcd_zba_zbb_zbc_zbs_ssccptr_sscounterenw_sstc_sstvala_sstvecd_svadu";
			mmu-type = "riscv,sv57";

			status = "okay";

			cpu0_intc: interrupt-controller {
				compatible = "riscv,cpu-intc";
				interrupt-controller;
				#interrupt-cells = <1>;
			};
		};

		cpu1: cpu@1 {
			compatible = "riscv";
			reg = <1>;
			device_type = "cpu";
			riscv,cbop-block-size = <64>;
			riscv,cboz-block-size = <64>;
			riscv,cbom-block-size = <64>;
			riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "h",
				"zic64b", "zicbom", "zicbop", "zicboz",
				"ziccamoa", "ziccif", "zicclsm", "ziccrse",
				"zicntr", "zicsr", "zifencei", "zihintntl",
				"zihintpause", "zihpm", "za64rs", "zawrs",
				"zfa", "zca", "zcd", "zba", "zbb", "zbc", "zbs",
				"ssccptr", "sscounterenw", "sstc", "sstvala",
				"sstvecd", "svadu";
			riscv,isa-base = "rv64i";
			riscv,isa = "rv64imafdch_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_zicntr_zicsr_zifencei_zihintntl_zihintpause_zihpm_za64rs_zawrs_zfa_zca_zcd_zba_zbb_zbc_zbs_ssccptr_sscounterenw_sstc_sstvala_sstvecd_svadu";
			mmu-type = "riscv,sv57";

			status = "okay";

			cpu1_intc: interrupt-controller {
				compatible = "riscv,cpu-intc";
				interrupt-controller;
				#interrupt-cells = <1>;
			};
		};

		cpu2: cpu@2 {
			/* 省略 */
		};

		cpu3: cpu@3 {
			/* 省略 */
		};

OpenSBIがCPU数を確認するコードは下記のようになっています。

OpenSBIがCPU数を確認するコード

// opensbi/platform/generic/platform.c

unsigned long fw_platform_init(unsigned long arg0, unsigned long arg1,
				unsigned long arg2, unsigned long arg3,
				unsigned long arg4)
{
	const char *model;
	void *fdt = (void *)arg1;    //★★デバイスツリーのアドレス、レジスタa1を使ってOpenSBIに渡す★★
	u32 hartid, hart_count = 0;
	int rc, root_offset, cpus_offset, cpu_offset, len;

	//...

	cpus_offset = fdt_path_offset(fdt, "/cpus");
	if (cpus_offset < 0)
		goto fail;

	fdt_for_each_subnode(cpu_offset, fdt, cpus_offset) {
		//★★device_typeがcpu、regプロパティに値が入っていれば、CPUのノードとみなす★★
		rc = fdt_parse_hart_id(fdt, cpu_offset, &hartid);
		if (rc)
			continue;

		if (SBI_HARTMASK_MAX_BITS <= hartid)
			continue;

		//★★statusプロパティがokかokayなら有効なCPUとみなす★★
		if (!fdt_node_is_enabled(fdt, cpu_offset))
			continue;

		//★★ハート数を1つ増やす★★
		//★★hartidは連番とは限らないため、hartindexとhartidの対応表を作る★★
		generic_hart_index2id[hart_count++] = hartid;
	}

	//★★platform領域に記録する★★
	platform.hart_count = hart_count;
	platform.heap_size = fw_platform_calculate_heap_size(hart_count);
	platform_has_mlevel_imsic = fdt_check_imsic_mlevel(fdt);

デバイスツリー(正確にはFDT: flattened device tree)の/cpuノードを見て、子ノードがCPUの定義であり、有効ならばhart_countを+1するシンプルなコードです。hartidは連番とは限らないため、hartindex(0からCPU数 - 1までの連番)とhartidの対応表generic_hart_index2id[]も同時に作ります。

無効なCPUはどうなるか?

無効なCPUの扱いも見ておきます。先程のコードからわかる通りstatus = "disabled"つまり無効なCPUの場合は、hartindexとhartidの対応表(platform.hart_index2id[])にhartidが載りません。例としてQEMUにてCPU 4つで起動し、デバイスツリーでCPU 2だけstatus = "disabled"にしたときのhartindexとhartidの対応表をダンプします。

4CPU, CPU2だけ無効のときのhartindexとhartidの対応表
(gdb) p platform
$11 = {opensbi_version = 65541, platform_version = 1,
  name = "riscv-virtio,qemo", '\000' <repeats 46 times>, features = 2,
  hart_count = 3, hart_stack_size = 8192, heap_size = 39936, reserved = 0,
  platform_ops_addr = 2148010200, firmware_context = 0,
  hart_index2id = 0x80083700 <generic_hart_index2id>}

(gdb) p generic_hart_index2id
$15 = {0, 1, 3, 0 <repeats 125 times>}

全CPUが有効ならば0, 1, 2, 3となりますが、CPU 2が無効なので0, 1, 3となっていることがわかります。

次にメインCPUがサブCPUを起こしに行くコードを見ます。アセンブラなので若干分かりづらいですが、hartindexとhartidの対応表に自CPUのhartidが登録されていればCPUを起動し、登録されていない場合はCPUを起動しません。

OpenSBIがサブCPUを起こす処理

// opensbi/firmware/fw_base.S

_fdt_reloc_done:
	//★★メインCPUはこちら★★
	//★★初期化処理が終わるとここに到達する★★
	//★★_boot_statusにBOOT_STATUS_BOOT_HART_DONEを書き込むとサブCPU側がループを抜ける★★
	/* mark boot hart done */
	li	t0, BOOT_STATUS_BOOT_HART_DONE
	lla	t1, _boot_status
	fence	rw, rw
	REG_S	t0, 0(t1)
	j	_start_warm

	//★★サブCPUはこちら★★
	//★★_boot_statusを読みながらループで待っている★★
	/* waiting for boot hart to be done (_boot_status == 2) */
_wait_for_boot_hart:
	li	t0, BOOT_STATUS_BOOT_HART_DONE
	lla	t1, _boot_status
	REG_L	t1, 0(t1)
	/* Reduce the bus traffic so that boot hart may proceed faster */
	div	t2, t2, zero
	div	t2, t2, zero
	div	t2, t2, zero
	bne	t0, t1, _wait_for_boot_hart

_start_warm:
	/* Reset all registers except ra, a0, a1, a2, a3 and a4 for non-boot HART */
	li	ra, 0
	call	_reset_regs

	/* Disable all interrupts */
	csrw	CSR_MIE, zero

	//★★platform.hart_index2idを見て、hartidと一致する要素があるか確かめる★★
	/* Find HART count and HART stack size */
	lla	a4, platform
#if __riscv_xlen > 32
	lwu	s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4)
	lwu	s8, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(a4)
#else
	lw	s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4)
	lw	s8, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(a4)
#endif
	//★★s9はplatform.hart_index2id[0]のアドレス★★
	REG_L	s9, SBI_PLATFORM_HART_INDEX2ID_OFFSET(a4)

	/* Find HART id */
	csrr	s6, CSR_MHARTID

	//★★platform.hart_index2idがNULLだったら処理を止める★★
	/* Find HART index */
	beqz	s9, 3f
	li	a4, 0

	//★★a4 = hartindex
	//★★a5 = platform.hart_index2id[hartindex]の値(hartindexに対応するhartid)
	//★★s6 = CPUのhartid
	//★★s7 = hart数
	//★★s9 = platform.hart_index2id[hartindex]のアドレス
1:
#if __riscv_xlen > 32
	lwu	a5, (s9)
#else
	lw	a5, (s9)
#endif
	//★★hartidとplatform.hart_index2id[n]が一致していたら、ループを抜ける★★
	beq	a5, s6, 2f

	//★★s9を進めて、platform.hart_index2id[0], [1], [2], ...を順に調べる★★
	add	s9, s9, 4
	add	a4, a4, 1
	blt	a4, s7, 1b
	//★★s6 = hartindex
2:	add	s6, a4, zero
	//★★hartindexがhart数を超えているか?
	//★★  超える  : CPUが無効である、サブCPUを起動しない -> _start_hangへ
	//★★  超えない: CPUが有効である、サブCPUを起動する -> ブランチ命令の先へ
3:	bge	s6, s7, _start_hang

	//...

OpenSBIのロゴが出たあたりでブレークして各スレッドの実行している関数名を見ると、下記のようになります。

無効なCPU 2が_start_hang()で止まっている様子
(gdb) info thr
  Id   Target Id                    Frame
  1    Thread 1.1 (CPU#0 [halted ]) sbi_hsm_hart_wait (scratch=0x8008c000, hartid=0)
    at opensbi/lib/sbi/sbi_hsm.c:177
  2    Thread 1.2 (CPU#1 [running]) 0x0000000080020ffe in fdt32_to_cpu (x=50331648)
    at opensbi/lib/utils/libfdt/libfdt_env.h:57
* 3    Thread 1.3 (CPU#2 [halted ]) _start_hang ()
    at opensbi/firmware/fw_base.S:409
  4    Thread 1.4 (CPU#3 [halted ]) sbi_hsm_hart_wait (scratch=0x80088000, hartid=3)
    at opensbi/lib/sbi/sbi_hsm.c:177

Thread Id 3つまりCPU 2(※)だけ_start_hang()に居ることがわかりますね。

(※)GDBのThread Idは1スタートなのでThread Id 1, 2, 3, 4がCPU 0, 1, 2, 3に相当します。

編集者:すずき(2024/10/17 04:19)

コメント一覧

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



2024年9月17日

Yoctoの並列Fetchでエラーが起きるとき

目次: Yocto

Yoctoは特に何も指定せずにビルドすると全スレッドを使おうとします。この挙動はコンパイルだけでなくFetchでも同様のようです。最近のCPUは一般向けでも8〜16スレッドが珍しくないので、何も考えずにbitbakeを実行すると16接続同時にFetchを試みて、サーバー側の同時接続数制限か何かに引っかかってエラーで落ちます。

このエラーが鬱陶しくて困っていたのですが、並列数を2〜4程度(サーバーに蹴られない接続数)に制限して、最初にFetchだけ実行してしまうとよさそうです。

並列数を2に制限してFetchのみ実行
BB_NUMBER_THREADS=2 bitbake core-image-sato --runall=fetch

一度Fetchが終わればその後はFetchしませんから、並列数を16でも32でも好きな数にして良いです。

編集者:すずき(2024/09/21 23:22)

コメント一覧

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



link もっと前
2024年9月28日 >>> 2024年9月15日
link もっと後

管理用メニュー

link 記事を新規作成

<2024>
<<<09>>>
1234567
891011121314
15161718192021
22232425262728
2930-----

最近のコメント20件

  • 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...」
  • link 24年5月17日
    すずきさん (05/19 03:41)
    「Standardだと下記の設定になってい...」
  • link 24年5月17日
    hdkさん (05/18 22:16)
    「ドメインを変えたせいで別サイト扱いになっ...」

最近の記事3件

  • link 24年10月31日
    すずき (11/04 15:17)
    「[DENSOの最終勤務日] 最終勤務日でした、入門カードや会社のPCを返却してきました。在籍期間はNSITEXE(品川のオフィ...」
  • link 22年7月8日
    すずき (11/02 20:34)
    「[マンガ紹介 - まとめリンク] 目次: マンガ紹介一覧が欲しくなったので作りました。5作品乙女ゲームの破滅フラグしかない悪役...」
  • link 24年10月30日
    すずき (11/02 20:33)
    「[マンガ紹介] 目次: マンガ紹介お気に入りのマンガ紹介シリーズ。最近完結した短めの作品を紹介します。マイナススキル持ち四人が...」
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

最終更新: 11/04 15:17