自作液晶コントローラで動画再生(改善編)

## はじめに

こちらは鈴鹿高専 Advent Calendar 2021の5日目の記事です．

https://qiita.com/advent-calendar/2021/snct



注意事項としては，ここで記載されているコードを他のプロダクトでそのまま使うのは**禁止**とします．

何かバグがあっても責任を取れないためです．

また，実際に何かを制作する際には必ず一次情報(データシートなど)を参考にしてください．



# 作ったもの

https://twitter.com/LunaTsukinashi/status/1464433627794587650



3日目の記事で作ったものをテスト終わりのテンションで爆速で改善しました．

ついでにPC上でシミュレーション動画を生成することもできるようにしました．




## 何がマズいのか

本来動画を再生させる用途の液晶でもなければそれに合わせたファームウェアでもありません．

何もチューニングしていない頭文字DのAE85状態です．

具体的には以下のような問題が生じました．

- チラつく
- 遅い
- 見にくい

今回はこれらの問題を全て解消していくまでの道のりについて書いていこうと思います．



## 画面のチラつき

動画で見るとそれほど感じないかもしれませんが，肉眼で見ると，ブラウン管テレビの走査線のような波が視認できます．

正直，遠目で見ればそれほど目立たないのですが，やっぱり気になったので修正することにします．



### なぜチラつくのか

原因は大きく2つ

- 変則シングルバッファリング
- 書き換えタイミングと表示タイミングの不一致

まず，前者についてはフレーム受信終了と同時に表示用バッファへmemcpyで転送していましたが，速度的な限界によりティアリングが発生していました．

画像が例です．

![DSC_0156.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545164/4821f858-fd47-8552-2d4a-3285ec74e071.jpeg)


次に，書き換えタイミングと表示タイミングの不一致について．

表示に関してはタイマ+DMAによりほぼほぼ自動で書き込むようなコードを書いていたため今何ライン目なのかについて気にしていませんでした．そのため，上のmemcpyのタイミングと表示タイミングが被り，なんとも言えないチラつきを生んでいました．



### どうしたか

とった対策は以下の２つです

- ダブルバッファリング化
- 垂直同期割り込みの追加

まず，memcpyで転送するのではなく２面のバッファを切り替えて使うようにしました．

また，この切り替えタイミングも垂直同期割り込みに合わせることによりほぼほぼチラつきはなくなりました．

これに合わせて描画割り込みの周期も動画のフレームレートに合わせるようにしました．

残像が残るという液晶そのものの問題はのこりますが，これはもう仕方ないでしょう．



### ハマった点

当初，memcpyが遅いならM2MのDMA転送をすればいいじゃないか！と思いましたが，実装してみるとなぜか動かない．

試しにDMAのチャネルを切り替えたらアッサリ動きました...

CubeMXで自動的に割り当てられた際にはきちんとその組み合わせが動作するのか確認するようにしましょう．

あと，どうやらDMA全転送終了割り込みは無いようなので使いにくそうですね...(半分終了時の割り込みはある)



## 遅い

これは液晶ではなくPCのソフト側の問題です．

とはいっても，階調表示編で作り直したCUI版ではかなり速度は改善されました．

が，いよいよ開発機(Core-M 5Y31,4GB)のパソコンではしんどくなってきました．



また，現行の転送方式ではフレームレートにも制限があります．

実効再生フレームレートは30fps弱で目標の30fpsには届いていません．

これ以上速度を上げるには圧縮するしかありませんがいくつか障壁があります．

- 速度
- 容量
- 液晶の限界

無論伸長処理にもCPUパワーは必要です．4階調化，つまり2bppイメージ転送を行えば今より効率よく，また高フレームレートに対応することも可能ですがいよいよCPUに余裕がなくなってきたので難しいでしょう．

また，伸長したデータを保管するためのRAMも必要です，単純計算で2KBx4面+受信データ8KBで16KB必要ですが，CCMRAM空間足して16KBしかRAMがないSTM32F303K8T6ではどう足掻いても無理でしょう．

最後に液晶の限界があります．3階調でも動きのある動画は厳しいのに4階調化すればもはや何も見えなくなるでしょう(笑)．ロジックアナライザでの観測や，チューニングの結果4階調で30fpsを維持するのは不可能であると判断されたのも要因の一つです．

よって，これ以上の速度改善はマイコン変えない限り不可能だと判断され妥協するしかありませんでした．



## 見にくい

肉眼だとそれほどでもないのですが，スマートフォンで撮影すると絶望的に見にくいです．

グレア液晶のため反射しまくりで撮影難易度が鬼です．そのため反射防止フィルムを貼っています．

また，３階調変換時のパラメタが適当すぎたというのも要因です．

これを改善するために，パラメタを視覚的に確認できるソフトをでっちあげました．

以下に画像を示します．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545164/b4220a17-c579-72ff-890d-275efcd11379.png)


フォルダを選択するとパラメタを適用した状態のプレビューを表示できるというものです．

より液晶っぽくするためにいろいろイジっていますが，これによりDynabookでは本当に動作不可なレベルまで重くなってしまいました...

連番画像の生成には拙作の"Sapphire CLI Commander(以下SCC)"を使用します．

このデータをもとに，SCCで変換するというわけです．

また，ここで制作したプレビュー機能をもとに，プレビュー動画の生成機能まで作ってしまいました．

以下のように，本物以上の見やすさで表示できる優れものです．

https://twitter.com/LunaTsukinashi/status/1464583430012747781

優れすぎているので封印しました．

これにより，冒頭のような割と見やすいデータを生成できるようになりました．



### ハマった点

C#のBitmapはスレッドセーフではないので気をつけましょう．

また，輝度だけでは真っ黒で何も見えなくなったりするので別の方法を考える必要があるかもしれない．

例外処理はきちんとしましょう．今回は自分しか使わないからいいやと思っていたら裏切られました，悲しい．



### 問題点

動画の変換処理が重すぎて大変．

画像のように100%に張り付いたまま数分間動けなくなってしまいます．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545164/b624883d-58cd-77e4-161a-545bd073af26.png)

## おまけ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545164/f4560749-fef5-05b4-3cf0-24fe40a83fb1.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545164/ab1a8cb2-171c-cde6-4810-b4ea725bff24.png)

タイトルだけは中央にだいたいあるので綺麗に映ります．
CIRCUS系のスクロールを多用するタイプの動画であれば違和感なく再生できますが，ましろ色シンフォニーのように上下に情報があるタイプのものは見切れてしまってもはや何がなんだかわからなくなります．
4:1の変則アスペクト比なので再生できる動画を探すのもなかなか大変です．

## 感想

テスト終わりのテンションに任せて土曜の午前中に書き殴ったコードの割にはかなり良くできていると自分でも思います．

とりあえず，次はマイコンを変えて実際に何か使えるものでも作ろうかなーと思っています．