HDCP 相容性小註解

數位的視訊輸出一般用 HDCP (High-Bandwidth Digital Content Protection) [1] 保護. 高清影片的 Full HD (full high definition 1080P) 是用 HDCP 1.X 版保護. 現在有了 4K 影片 (3840×2160 或是 4096×2160), 就改用 HDCP 2.X 保護. 

一般人很容易把 HDCP 和 HDMI 的版號搞混, 所以從 [2]  剪了一張圖如下. 除了 HDMI, DVI [3] 也支援 HDCP.

HDMI-vs-HDCP

雖然 HDMI 的版本往前相容, 但 HDCP 可不是. HDCP 2.X 和 1.X 天生就不相容. 如果用 HDCP 1.X 和 2.X 互接, 結果就是無法輸出. 不管誰是 TX (transmitter) 或是 RX (receiver) 都一樣. 世界上最主要的 HDMI receiver 就是電視, 電腦螢幕則是 HDMI / DVI 都有.

如果遇到 TX / RX 的 HDCP 版本不同怎麼辦呢? 據 HDCP 2.2 的規格 [1], 可以用轉換器來連接雙方, 例如 1.X to 2.X converter (P. 42), 或是 2.X to 1.X converter (P. 43). 目前市面可以買到 HDCP 2.2 to 1.4 的轉換盒, 價格約在 175 美金 [4]. 那麼為何找不到 1.X to 2.X 的轉換盒呢? 我猜這是因為電視已經把 2.X 和 1.X 的 HDCP key 都放進去了.

這樣的互通是有限制的. 在 [1] 的 Section 4.2.12 中規定, 如果 Content Stream 的 type = 0, 則視訊內容 (主要是 4K) 還是可以透過 HDCP repeater 傳送到下一級. 反之,  Content Stream 的 type = 1, 則不能傳給 HDCP 1.X compatible device, 以及 HDCP 2.0 compatible 的 repeater. 

要搞懂上面這段, 還要稍微說明一下 receiver 和 repeater. Receiver 本身就是最後一級, 不再把訊號往下一級 (downstream) 送. 而 repeater 會同時有上一級 (upstream) 以及下一級. 前述的 2.X-to-1.X 轉換盒顯然符合 repeater 的描述, 所以某些 HDCP 2.0 保護的影片 (Stream Type = 1) 應該會過不去.

還有一種狀況會發生 “相容性" 問題. 因為 HDCP 1.X 和 2.X 的 key 都被破解過, 所以那些壞 key 已經喪失法律地位了. 因此最上游的 HDCP  (top level HDCP transmitter) 會依序往下檢查下級的 “任何" Receiver ID 是否已經失效? 換言之, 要有個機制來儲存壞 ID 的名單 (revocation list), 而且要不斷更新這個名單. 如果名單舊了, 沒有 renew 過, 可以透過檢查  System Renewability Message (SRM) 的簽名 (signature) 是否正確來判定, 舊的版本要換成新的.

SRM 一代是 5116 bytes, 理論上非揮發記憶體夠大, 就可以每代多 5KB 不斷更新. 不過規範只要求至少支援 5KB, 如果只有 10KB, 那就存第一代和第二代即可. 示意如下圖 [1].

SRM-Size

[REF]

PGP 小註解

PGP [1] 是 pretty Good Privacy 的縮寫, 我們可以用 PGP 幫我們的文件 (含信件) 加密或是驗證. 如果大家收到一個 .PGP 的檔案, 這個文件應該是用對方的 key 和你的 public key 所加密的. 因為你已經把 public key 給過對方, 那麼收到 .PGP 時也不會太意外.  如果對用法上不熟, 可以參考 [2].

有一種加密方式是把整封信加密, 此時很有趣地, 看到 .pgp, 解開之後發現是信上的 logo 而已. 真正信件的內容是穿上 ASCII armor [3] 形式的亂碼. 例如:

—–BEGIN PGP MESSAGE—–
Version: 10.3.2 (Build 15238)
Comment: This message is confidential
Charset: utf-8

vp5hQ3ROXrZ7KVeyDlb3yD2/cmZbznGTN7Rowt2LOuec4CjcOlRB/q3XaalhoXnj

—–END PGP MESSAGE—–

ASCII Armor 的用意是避免 binary 形式傳檔案時, 剛好出現不應該出現的 pattern, 而造成 gateway 的問題, 或是被當作病毒等等. 因此用 binary to textual 逐 byte 轉成 ASCII code. 此外, 根據 [4], DOS/UNIX 的換行符號通常都可以被自動克服.

這時候, 明眼人都看得出來這段文字就是 PGP 檔案. 所以把  —–BEGIN PGP MESSAGE—– 到 —–END PGP MESSAGE—– 剪下來, 貼到一個新的檔案上, 然後存成一個檔案, 就可以解密它.

我用 Kleopatra [5] 試驗的結果, 只要不是存成 .PGP 檔, 沒有附檔名, 甚至 rename 成 .ZIP 檔或是 .out 檔, Kleopatra 都能將它正確解密, 並且生出 XXX.out 檔. 不過存成 .PGP 檔就不行了. 至於用 GoAnyWhere Open PGP Studio [6] 去解 ASCII Armor, 還沒有成功過.

使用 Kleopatra 容易遇到一個小問題, 第一次可以正常使用. 如果當掉了, 第二次就會開不起來, 抱怨找不到 libkleo.dll. 本來以為它是被防毒軟體誤殺. 想不到是這個軟體的烏龍. 到 Kleopatra 圖示點右鍵, 選 “內容", 把開始位置的 “C:Program Files (x86)GNUGnuPGbin" 砍掉 bin 就 OK 了. 這個 bug 被報了兩年, 據說到 2016/4/8 的版本才解掉 [7].

[REF]

  1. 良好隱私密碼法
  2. 文件認證——Pretty Good Privacy (PGP) 簡介與應用
  3. ASCII-Armor 這個 link 很好, 但是點進去要等一段時間廣告.
  4. Line Breaks in OpenPGP ASCII armor
  5. https://www.gpg4win.org/
  6. http://www.goanywheremft.com/products/openpgp-studio
  7. Bug 333535 – System Error on initialisation – libkleo.dll is missing

SBC vs aptX

這兩個音訊格式都是藍牙所使用的. SBC = sub band CODEC [1], 關於何謂 sub-band, 從頻域來看, 聲音從低頻道高頻都有, 因此可以分成一個個的區段, 這就是 band. 好比手機訊號有 900M, 1800M 這樣.

但人耳對於不同頻段的感知能力不同, 說話的高低音 (300~3KHz) 我們比較容易分辨, 但是對於 16KHz, 20KHz, …這種高音, 聽起來都是很尖而已, 甚至木耳一點就聽不到. 所以我們可分而治之, 在不同的頻段給予不同程度的壓縮. 這就是 SBC.

對於藍牙系統來說, 支援 A2DP (Advenced Audio Distribution Profile) 就要多處理 audio 的壓縮、解壓縮. 如果硬體不夠力, 這樣的小工作也是一個負擔. 在 SBC 的規範當中, 最高可以支援 48KHz 採樣, 單聲道 198 Kbps, 雙聲道 345 kbps. 即使計算量不算太高, 這 bit rate 卻也不低.

至於 aptX [3], 原本叫做 apt-X, 被 CSR 買了之後改為 aptX. Qualcomm 在 2015 年完成對 CSR 的併購, 所以 aptX 算是 Qualcomm 的私有規格. aptX 雖然複雜度比較高, 但仍然是一種 sub band CODEC. 它的好處在於採樣率下降到 44.1 KHz, 所以單聲道最多 176 Kbps, 但雙聲道可以 352 Kbps.

相形之下, aptX 有何種誘因讓大家採用呢? 主要是它的 encode / decode 速度較快. 在 CSR 的官網, 他們大喇喇地宣稱用了其他 audio CODEC 會導致 AV 不 sync [4]. 不過這個說法並不公正. 只不過是因為 audio 到了藍牙裝置後, 被系統視為  HW 輸出, 所以愈接近 real time 的 software audio CODEC 就不會和 video free run. 把它當作一種廣告詞就好了.

[REF]

  1. SBC (codec)
  2. [無線科技] 立體獻聲藍牙人間:淺談Bluetooth技術
  3. aptX
  4. https://youtu.be/e5aG4qIVqSw

IPA 小註解

這裡的 IPA 是指 intermediate physical address. 一般印象中只有 virtual address (VA = 虛擬地址) 和 physical address (PA = 實際地址), 為何又多了不虛不實的中實戶 – 中間實際位址呢? 主要是因為 hypervisor mode 的關係.

首先, CPU 可以透過 MMU (Memory Management Unit) 來完成virtual address 到的 physical address 的映射. 由於需要以位址查位址, 當然就需要有個表格 – translation table. 在 ARM 的 CPU 架構中, 使用 TTBR  (Translation Table Base Register) 來幫忙查詢.

如果 page size 不大, 而 physical address 很大, 那麼就需要使用多層的 page table 分次查詢.  例如 page size = 4 KB, physical address = 1 GB, 那麼 table 就需要 1G/4K = 256 K 個 entry. 分成 3 層表格, 每一層的 entry 數目就會大幅減小. 在這每一層當中所查出來的 “physical address", 因為不是最後的真實值, 就稱之為 level N descriptor PA. 

如果打開 hypervisor mode. CPU 所運行的可能是 guest OS 的 virtual address. 萬一 guest OS 和 hypervisor 的 MMU 映射方式不同, 兩者所看到的同一個 virtual address 就不會是同樣的 physical address 了.

此時需要第二度的轉換 (所謂 stage 2 [ref 1]).  每一次的 level N descriptor PA , 就相當於 level N+1 descriptor 的 IPA, 根據它, 透過  VTTBR (virtual TTBR) 轉出 level N+1 descriptor 的 PA.

因此, IPA 的功能是表彰 hypervisor mode 中的特殊 level N descriptor PA.

[REF]

  1. ARM Virtualization Extensions – Memory and Interrupts (Part 2) – See more at: http://www.futurechips.org/understanding-chips/arm-virtualization-part-2-memory-interrupts.html#sthash.wtHYHshp.dpuf

Android 6.0 記憶卡擴充小註解

雖然 Android 6.0 有了把外部 SD Card 變成內部記憶體的能力, 但是各家廠商都捨不得這個賺錢的法門, 老大哥 iphone 的手機就是用內部記憶體大小定價的啊, 不然 128GB 以後要賣誰? Android 廠商都快活不下去了, 當然比照辦理, 硬是把這個功能給隱藏了. 原本想說 Android 親生的 Nexus 系列總該以身作則吧!? 想不到 Nexus 竟然連插卡功能都不給, 這樣就不能說他們違反 CTS 了.

以 Samsung S7 系列為例, 雖然上個月才出來, 網路上已經有一大堆 adaptive storage (SD card) 的教學, 中文英文都有 [1,2]. 不過按圖施工也不一定會成功, 這邊就讓我來做 debug 的小註解吧!

  1. 首先要備份 SD card, 因為裝好之內內容會被清掉. 卡要選速度快的, 容量愈大愈好. (see 11)
  2. 安裝 adb, Windows / Mac 都可以裝. Windows 裝 adb 的方法很多, Mac 參考這一篇 [3] 的 option 1.
  3. 手機要連到電腦 – 不過我的 Windows 10 從來沒有成功過, 兩台Macbook 都可以. 至於 Windows 8.1 應該沒問題, 因為大部分的人都是用這個環境. 其中要把開發人員選項叫出來, 才能打開 USB debug 功能 [2].
  4. adb devices 要能看到 device. 如果看不到, 可能之一是手機進入休眠, 所以沒點到螢幕上是否同意連接 adb 的選單. 允許之後就  OK.
  5. 如果 adb devices 還是失敗, 請參考 [4].
  6. 進入 adb shell 之後, 大概就可以順利執行 sm list-disks, 長相是這樣: 文字或數字 179.xxx  這個文字或是數字就是 SD Card 的代號. 如果 xxx 不是 0, 後面就簡單了.
  7. 用 sm partition disk:179,xxx private 把整個 SD Card 指定成內部記憶體, 用  sm partition disk:179,xxx  mixed 50, 其中 50 代表切給內部的 ratio.
  8. 可以用 sm list-volumes all 看到所有的內容. 完整指令如下:sm-command-1-620x200
  9. 如果很不幸地, 看到 SD Card 是 179.0, 那麼可能會伴隨各種 Java error…etc. 網路上災情不少. 例如: Error: java.lang.IllegalStateException: java.util.concurrent.TimeoutException: Thread Binder_B gave up waiting for partitionPrivate after 180000ms, 或者
    Error: java.lang.IllegalArgumentException: command ’45 volume partition disk:179:0 private’ failed with ‘500 45 Unknown disk’
  10. 這要麼辦呢? 我想應該是 Java 版本的關係. 當我在第一台比較少用的 Macbook 看到上述第二種錯誤後, 試了各種網路上建議的: 重新 format SD 卡, 改變 USB 連接方式….等等. 但是拿到另外一台 Macbook 卻是簡單地過關.
  11. 這樣做有沒有風險呢? 我認為有, 包括我自己的平台, 以及網路上其他人貼的圖. 系統把實際記憶體高估了, 也就是內部+外部記憶體, 對我來說是 32 + 64 = 96 (GB), 但系統顯示有 128GB, 其中 64GB 已使用 [1-2].
  12. 做了個實驗, 如果是內建 32GB + 外插 128GB, 合併之後, 系統認為總共是 256GB. 所以手機會固定把外部記憶體 x 2 當作總記憶體數. 已使用的部分再細項的部分都是正確的, 但是合併之後的"已使用", 包含虛胖的 128GB (假內部) – 32GB (真內部) = 96GB, 然後再加上真正已使用的部分.
  13. 不過根據 [2], 這個動作可以還原, 所以至少不影響保固.

[REF]

  1. Here’s how to configure adoptable storage on your S7 / S7 Edge
  2. 三星不給你的自己來!Galaxy S7 / Edge 合併記憶卡空間【免 Root】
  3. Installing ADB on MAC OS X
  4. ADB server didn’t ACK