Kho tháng 10/2017

Thứ sáu, 13 Tháng mười năm 2017 20:46:16 ICT

Phim hay không phim, đó là cả vấn đề

Hơn một năm nay phải mần một số thứ có liên quan đếm phim và ảnh. Túm lại một miếng cho vui.

MPEG-2 và Transport Steam

PID, PES, PMT và PAT

MPEG-2 là định dạng phim dùng cho DVD (cũ quá hén?). Đây là định dạng được thiết kế cho streaming. Nghe cũng có lý bởi vì đối với phần cứng thì xử lý, giải mã và hiện ngay thì dễ hơn nhiều so với kiểu phần mềm "phân tích mọi thứ, đâu ra đó, xong từ từ xem".

Một "luồng phim" MPEG-2 bao gồm nhiều "luồng con" khác nhau, như phim (H264 hoặc H265, tên chính thức tương ứng là AVC-1 và HEVC). Các luồng khác nhau này được đánh số để phân biệt. Mã số này gọi là PID. Mỗi luồng được cắt thành từng "khúc" gọi là PES. Các gói PES của nhiều luồng khác nhau có thể xuất hiện xen kẽ trong "luồng phim".

Nghe trừu tượng nhưng nếu ai đã biết chút đỉnh về TCP/IP. Có thể đại khái coi một luồng phim (theo PID) như là một kết nối TCP (xác định theo cổng). Thay vì một phim với bốn độ phân giải, hai kênh tiếng, thì coi như một kết nối giữa hay máy với 6 kết nối TCP/IP. Mặt dù thứ tự dữ liệu trong từng kết nối là xác định (byte đầu dĩ nhiên đến trước byte cuối, đại loại thế), dữ liệu giữa các kết nối TCP có thể được gửi xen kẽ, song song với nhau. PES theo cách so sánh này giống như là cách tách gói.

Hừm.. nếu ai biết SCTP thì không chừng so sánh còn dễ hơn. Nguyên một kết nối SCTP là một "phim". Mỗi association id tương ứng với một PID. Bởi vì SCTP gửi theo từng gói một, như UDP, chứ không phải kiểu stream như TCP, nên nó khớp trực tiếp với từng gói "PES" trong MPEG-2.

Đó. Dễ òm. Khi nhận được luồng dữ liệu MPEG-2, ta nhận được nhiều luồng phim khác nhau phân biệt qua PID. Nhưng mà biết PID nào là hình, PID nào là tiếng. Nếu mà hình (hoặc tiếng) thì biết định dạng là gì...?

Đây là lúc cần PAT và PMT. PAT được gửi trên một luồng đặc biệt với PID luông luông là số không. Một khi nhận được PAT, ta có đủ thông tin để tìm PID của PMT. PMT mô tả cụ thể "PID số 10 là phim định dạng H264, PID 12 là tiếng dùng AAC-LC...". Một khi đọc PMT xong là có thể bắt đầu giải mã hình tiếng và xem.

Quay lại lúc đầu có mô tả MPEG-2 (đúng hơn là MPEG2-TS) là định dạng dành cho stream. Đây là một trong những lý do. MPEG-2 là một "stream". Nó không có điểm đầu, không có điểm cuối. Nó không phải là "một tập tin" với kích thước biêt trước. Nếu là một tập tin, PMT có thể quăng ở đầu (hoặc đuôi) một lần là xong.

Với MPEG-2, PMT sẽ được gửi đi gửi lại định kỳ. Thành ra nếu có một tập tin mpeg2, nếu cắt đúng ranh giới (lát nói) thì một tẹo sau là phim vẫn lên. Lý do là khi mới đọc, có thể không biết PID nào là PID nào. Nhưng một tẹo sau thế nào cũng phải thấy PMT và có thể "phục hồi" xem tiếp.

Transport Stream

So MPEG-2 với TCP/IP (hoặc SCTP/IP, rứa) là cũng có lý do của nó. Transport Stream packet là một gói có kích thước cố định 188 bytes vớ một byte đầu "đấu hiệu đặc biệt 0x47, sau đó là một tẹo header và cuối cùng là payload.

Gói TS thiệt tình cũng không khác với gói IP. Một "gói SCTP" có thể to hoặc nhỏ, muốn gửi qua mạng phải cắt nhỏ thành từng "miếng" IP xinh xắn rồi gửi qua mạng. Qua đến bên kia thì ráp các miếng lại với nhau và tạo lại gói SCTP ban đầu.

TS y chang. Một gói PES có kích thước khi to khì nhỏ. Muốn "gửi đi" cũng phải cắt thành từng miếng "TS" (có "dán tem" PID từng gói). Khi "gửi" đển đầu phát rồi thì các gói được ráp lại (theo PID) để tạo lại PES. Có PES rồi thì muốn xem gì xem. Dễ òm.

Hồi nãy ở trên có một cái mở ngoặc về chuyện cắt đúng ranh giới. Cái ranh giới quan trong ở đây chính là TS (188 byte). Cứ cắt 188 byte là ngon. Với một số trình phát (chắc đặt biệt là đầu DVD phần cứng), có khả năng tìm byte đầu TS 0x47 nếu không cắt đúng ranh giới. Nhưng đa số sẽ không thèm tốn thời gian và bỏ cuộc.

H264, H265

Nội dung thực sự bên trong mỗi gói PES tuỳ thuộc vào nội dung nó truyền tải. MPEG-2 TS cho phép khá là nhiều thứ. Như đã nói ở trên, một "luồng" mpeg2ts có thể chứa nhiều hình ở các định dạng/độ phân giải khác nhau, nhiều kênh tiếng khác nhau... Dĩ nhiên nó cũng có thể chứa luôn các luồng phụ đề (Teletext hoặc DVB Subtitles).

Tất cả mấy cái đó thường là cùng một "nhóm". Ví dụ như cho một bộ phim một (Die Hard?). MPEG2-TS còn có một khái niệm là "program", cho phép nó gửi song song nhiều phim (Die Hard và Star Wars!) trong cùng một luồng. Đầu đọc (set top box) có thể chọn chương trình phù hợp và phát.

Đối với hình ảnh, mội khung hình sẽ được gửi trong 1 gói PES. Kích thước gói PES có thể là không xác định (TS stream có khả năng tách gói PES thậm chí không cần biết trước kích thước). Nó cho phép chuyện này vì kích thước một khung hình có thể lớn, nhưng trường chứa kích thước PES hình như chỉ chịu nổi vài megabyte, không nhớ rõ lắm.

Cả H264 và H265 đều chia mỗi khung hình thành một dãy các gói nhỏ hơn gọi là NAL. Định dạng cụ thể cho NAL đối với MP4 và MP2 khác nhau, nhưng khái niệm cũng rứa. NAL chia làm nhiều loại và chỉ ra cách lắp ráp giải nén một khung hình như thế nào. Vụ này không đào sâu tiếp.

Với phần hình, có một cái cần nói là loại khung hình và cách nén. Đa số khung hình sẽ giống nhau rất rất nhiều. Nên cách nén tốt nhất là "lấy lại khung hình trước, sửa một miếng chỗ này, một miếng chỗ kia". Với cách nén kiểu này, để giải mã khung hình A, có thể phải cần có khung hình A-1, A-2....

Nhưng nếu khung hình nào cũng cần khung hình phía trước, thì làm sao giải mã khung hình đầu tiên? Khung hình đầu tiên được nén mà không phụ thuộc vào bất kỳ khung hình nào khác. Nó gọi là I-Frame hay IDR-Frame gì đấy. Đây là một loại khung hình quan trọng sẽ nói tiếp về sau. Có một điểm cần nhấn là khung hình dạng này không phải chỉ xuất hiện một lần duy nhất ở đầu. Nó xuất hiện định kỳ. Và nó giúp hình thành một nhóm khung hình gọi là Group Of Picture (GOP).

Cái ghi chú cuối cùng về hình. Hồi nãy có nói A cần A-1 và A-2 để giải mã. Trên thực tế nó điên hơn một tẹo. A có thể cần khung hình tiếp theo A+1 để giải mã! Bởi vì cái lý do này nên thứ tự giải mã khung hình và thứ tự phát không hẳn như nhau. Thứ tự giải mã trong trường hợp này là

A-2 A-1 A+1 A

nhưng thứ tự phát vẫn là

A-2 A-1 A A+1

Để phân biệt hai cái thứ tự này, nó có hai "trục thời gian" khác nhau. Presentation Timestamp (PTS) cho biết thời điểm cần phát của một khung hình. Decoding Timestamp (DTS) cho biết thời điểm cần giải mã của một khung hình. So lại ví dụ trên, ta sẽ có

Khung hình | A-2 A-1  A  A+1
------------------------------
PTS        |  2   3   4   5
DTS        |  1   2   4   3

Phần giải mã thì cứ mần theo thứ tự DTS. Phần phát cửa làm theo thứ tự PTS.

  • Đến xung nhịp thứ 1, giải mã A-2
  • Đến xung nhịp thừ 2, giải mã A-1 (cần A-2), hiện A-2
  • Đến xung nhịp thừ 3, giải mã A+1, hiện A-1
  • Đến xung nhịp thừ 4, giải mã A (cần A+1), hiện A

Đại loại thế. Dễ òm! Ghi chú nhỏ cuối cùng, cả PTS và DTS trong MPEG2 đề dùng cùng một đồng hồ 90KHz.

AAC, AC3, Teletext, DVB Subtitles, SCTE-35....

Phần hình phức tạp, chứ phần tiếng thì đơn giản. Ít ra là AAC không phức tạp lắm từ góc nhìn "đóng gói". Âm thanh được lấy mẫu định kỳ (vd 32KHz). 1024 mẫu được gom là thành một ADTS frame. Một hoặc nhiều ADTS frame sẽ được cho vào một cục PES. Bởi vì việc giải mã tiếng không có ràng buộc chồng chéo như hình, PTS và DTS lúc nào cũng giống nhau.

Chuyện phụ đề (Teletext, DVB Subtitles) là một trời đau thương. Túm cho nó đơn giản lại là teletext gửi phụ đề dạng chữ, trong khi DVB Subtitles cho phép gửi phụ đề dạng ảnh (nên không cần phông chữ).

Để hỗ trợ quảng cáo, đôi khi luồng MPEG2 cần gửi kèo một vài thông tin phụ như "quản cáo Sunsilk bắt đầu lúc 10 giờ, kết thúc trong 30 giây". Thông tin dạng này được gửi thông qua SCTE-35, đóng gói trong MPEG2-TS.

MPEG-4

Phù. MPEG2 (MP2) "dễ òm" hén! Vậy qua thế hệ mới, MP4.

MP4 tên chính thức là ISO Base Media (đây là một phần trong chữ viết tắt ISOBMFF -- ISO Base Media File Format).

MP4 nhìn trên cao đơn giản thấy ớn. MP4 được cấu trúc như một cái cây (đúng hơn là rừng) với một nút có một cái tên bốn chữ cái. Muốn xem thử, có thể ịn một tập tin mp4 vào mp4parser.com, hoặc dùng mp4tree, hoặc MP4Box.

MP4 có vài nùt quan trọng, moov (hoặc moof) và mdat. Bà con lâu lâu cũng thấy mình trình phát phim càm ràm không thấy "moov". Cái nút (đúng ra thuật ngữ MP4 gọi là "box") moov về cơ bản là "header" của mp4. Nó chứa toàn bộ những thông tin cần thiết để giải mã, trừ dữ liệu phim ảnh thật sự. Dữ liệu phim ảnh thật sự nằm trong mdat.

Trong moov, một trong những nút quan trọng là trun, nó chứa danh sách mỗi khung hình và vị trí dữ liệu của mỗi cái ở đâu trong mdat. moof là cái như moov nhưng dành cho cái gọi là "MP4 Fragment", sẽ nói sau.

MP4 nhìn thấp thấp phức tạp dễ sợ! Có cỡ trăm loại "nút" khác nhau. Đặc tả ISO Base Media (ISO 14496) bao gồm 14 hay 15 cuốn gì đó, mỗi cuốn mộ tả một mặt nhất định, từ hình tới tiếng. Oé!!

Adaptive Bit Rate (ABR)

Hồi xửa hồi xưa, internet chậm rì, xem phim bằng đĩa (hoặc băng!). Đời sung sướng.

Sung sướng ở chỗ không có bị chờ "buffer". Tới lúc có mạng, xem phim qua mạng thì dễ dính phần buffer. Thành ra nhà đài phải tạo ra phim với nhiều độ phân giải khác nhau. Ai mạng yếu thì chọn độ phân giải thấp. Ai giàu chơi broadband thì quốc 4K.

Nhưng mà rủi mạng buồn buồn chậm lên nhanh xuống, chỉnh bằng tay mệt. Khách hàng là thượng đế! Ai đời bắt khách hàng ngồi chỉnh (đặt biệt là khách hàng smart phone bình dân học vụ). Nên cá chương trình xem phim phải khôn lên, tự phát hiện mạng chập và tự chọn phim vừa phải.

Có hai vấn đề với vụ chọn phim này. Thứ nhất, làm sao trình phát phim biết phải chọn cái nào (và có bao nhiêu lựa chọn). Cái này không khó lắm. Miễn sao hai biên thoả thuận được cách liên lạc, "ê tao có hai phim với bitrate bi nhiêu và bí nhiều, ở chỗ ấy và ậy", là ngon.

Sư đời nó phức tạp hơn. Khách hàng là thượng đế mà! Khi đang xem phim mà chuyển sang một luồng phim khác, nếu cái chỗ chuyễn không phải là IDR Frame (xem ở trên) thì không thể hiện ngay được vì thiếu cáck khung hình cần thiết để giải mã. Nên sẽ bị đứng hình một tí (hoặc nổi cục cục vì giải mã không hết).

Thương đế không khoái cục cục như thế. Thành ra phải chiều thượng đế. Cái giải pháp mà chuẩn HLSv4+ (không đề cập HLSv3), MSS và DASH dùng là "cắt phim thành từng khúc đều nhau, mỗi khúc luôn bắt đầu bằng IDR Frame, muốn chuyển thì chuyển nguyên một khúc".

Đó! Nguyên cái đó nó gọi là Adaptive Bit Rate.

(Nhưng mà thiệt ra chuyện cắt khúc còn có một cái lợi khác về mặt caching dùng CDN, thôi bỏ qua)

HTTP Live Streaming (HLS)

Chuẩn này bắt đầu từ cái nền m3u8 playlist. Nó túm lại là một loạt các playlist. Nó có một cái "playlist trùm" (master playlist) chuyên đi mô tả "tao có hai kênh hình với tốc độ bi nhiêu đây, tao có 3 kênh tiếng với ngôn ngữ này này, tao có phụ đề rứa rứa, mấy cái đó nằm ở đây". Nói thiệt ra nó không khác lắm PMT.

Cái "mấy cái đó nó nằm ở đây" là URL tới vài cái playlist phụ (media playlist). Mỗi cái playlist này sẽ miêu tả địa chỉ của "từng khúc" nói ở trên.

HLS chỉ có thế. Bao nhiêu đó thông tin (có một tẹo thông tin phụ khác trong playlist không có nói) là đủ để trình phát phim lấy hình và tiếng về, phát lên, đo mạng, nếu thấy chậm thì chuyển qua luồng phim khác...

HLS tới phiên bản số 7 vẫn dùng MPEG2-TS. HLSv8 (hay 9) cho phép dùng MP4. HLS phiên bản số 4 về sau kêu "hình lưu riêng, tiếng lưu riêng" (trong mấy các khúc bị cắt ở trên). Chuyện trộn hình tiếng do trình phát phim chịu. HLSv3 lưu một khúc chứa cả hình và tiếng. Kiểu lưu chung này có khuyết điểm (tốn đĩa) nên giờ không còn ai xài.

HLS do Apple tạo ra, nên bà con ai cũng phải hỗ trợ (vì iPhone, iPad...). twitch.tv cũng dùng định dạng này.

Microsoft Smooth Streaming (MSS)

MS dĩ nhiên cũng ngứa và muốn nhảy vào mảng phim phiếc. MSS xét về mặt nội dung thực sư cũng chả khác HLS (cả đám nhà ABR cũng một ruột như nhau). Khác biệt là:

  • MSS chỉ có một tập tin playlist (gọi là manifest) thay vì một master playlist và một chục media playlist như HLS.
  • MSS Manifest dựa trên XML (trong khi m3u8 giống với văn bản viết tay hơn)
  • MSS Manifest dĩ nhiên phải mô tả hết tất cả các kênh hình tiếng phụ đề, chỗ lấy.... Tuy nhiên nó có cải thiện để thu nhỏ kích thước tập tin này. Với HLS, ta phải ghi "khúc 1 URL chỗ này, khúc 2 URL chỗ này..." cho mọi khúc. Với MSS ta có thể ghi "dùng cái mẫu URL khúc-n.mp4" để lấy tất cả các khúc, thế "n" bằng mã số khúc.
  • MP4 là định dạng để gửi phim và hình. Cái tiểu tiết bên dưới là nó dùng "MP4 Fragment" chứ không phải "MP4 phim bình thường". MP4 Fragment không cần có một số thông tin nhất định, vì cái đó lấy ở đâu đó rồi. MP4 Fragment dùng moof thay vì moov.

MSS hình như chỉ có mỗi Microsoft xài (và cần ISS thì phải).

Dynamic Adaptive Streaming over HTTP (DASH)

Đây là chuẩn mới lên và lên như diều gặp gió. Nó lên giữ vậy là nhớ các ông bự Apple, Microsoft, Adobe, MPEG... ngồi lại với nhau và thống nhất một chuẩn tốt cho mọi nhà.

DASH dựa trên nền tảng MSS, tiếp tục dùng XML làm nền. DASH cũng tiếp tục dùng MP4 Fragment (nói đúng hơn là nó dùng CMAF) hỗ trợ thượng vàng hạ cám, MP2, MP4, WEBM quốt ráo. So với HLS và MSS được thiết kế chủ yếu cho tường thuật trực tuyến, DASH hỗ trợ mọi loại truyền thông.

DASH phức tạp lém. Hồi nào giờ đọc có một tẹo. Không dám viết nhiều. Nhưng nếu ai tò mò, thì Youtube đang dùng DASH. Hồi đầu Youtube cho phép lấy DASH Manifest luôn. Giờ nó giấu đâu đó. Nếu dùng youtube-dl thì vẫn lấy được.

Digital Right Managment

Giơ cái cờ "Phần mềm tự do" mà viết về DRM thì cũng hơi áy náy. Nhưng giữ áy náy và không có tiền ăn cơm thì dĩ nhiên phải chọn ăn cơm.

Cả ba HLS, MSS và DASH đều hỗ trợ DRM. Bởi vì dĩ nhiên cái đám đó không muốn cho người khác lấy phim về xem.

HLS có hai cách mã hoá luồng phim khác nhau. Cách "AES-128" mã hoá toàn bộ tập tin dùng AES-128. URL để lấy khoá giải mã nằm trong HLS media playlist. Dĩ nhiên là cái URL này sẽ chạy HTTPS và đòi mật khẩu tè lè. Nội dung URL này là 128 bit khoá giãi mã.

Cách thứ nhì là SAMPLE-AES (chọn cách mã hoá nào có ghi trong HLS media playlist). Cách này dữ luồng TS không mã hoá. Thay vào đó nó chỉ mã hoá nội dùng của một số gói PES nhất định, thường thì nó chỉ mã hoá hình chứ cũng chả cần quan tâm tiếng. Có một cái cờ (ở đâu quên mất rồi, Adaptation Field?) để cho biết là một gói PES có bị mã hoá hay không. Nếu có thì giải mã dùng AES-128.

MSS và DASH để từ từ viết tiếp...


Cập nhật 1 lần. Lần cuối: Tue Oct 17 10:17:56+0011 2017

Tác giả: pclouds | Liên kết tĩnh

Thứ bảy, 07 Tháng mười năm 2017 16:37:14 ICT

Design of the RISC-V Instruction Set Architecture

Không nhớ cái gì làm hôm qua nhớ đến Mill CPU. Mò mò Mill thế nào cũng đụng tới Itanium. Rồi không hiểu vì sao mà từ Itanium đi lạc qua RISC-V.

Design of the RISC-V ISA là một tài liệu thú vị vì nó phân tích nhược điểm của các ISA hiện tại (hoặc đã chết). Và một số cái hay khác. Như chuyện dùng 128-bit ISA để có thể dùng một không gian địa chỉ phẳng cho tất cả các tiến trình (thay vì không gian ảo cho mỗi tiến trình).

Nói túm lại là RISC-V trông có vẽ hấp dẫn. Chuyện RISC-V có thể trở thành một trong những ISA quan trọng (hoặc thậm chí ISA thống trị) chắc còn phải chờ vài năm nữa mới thấy. Cả Intel và ARM sẽ kiên quyết không từ bỏ ISA của riêng mình vì nó đem lại quyền lực cho cả hai công ty. Mill không thể dùng RISC-V bởi vì Mill là VLIW.

Òi... túm lại là mất nguyên ngày thứ bảy (và tối thứ sáu) đọc ba cái nhảm nhí. Chắc để cho trọn bộ, không chừ vứt luôn chủ nhật để viết lại c4 hỗ trợ RISC-V, coi nó có lẹp lẹp hơn bản ARM một tí không.


Tác giả: pclouds | Liên kết tĩnh

Thứ hai, 02 Tháng mười năm 2017 18:24:55 ICT

Đặt ảnh nhỏ cho ứng dụng

Không hiểu vì sao Emacs không đặt _NET_WM_ICON nên KDE task switcher hiện cái ảnh phóng to xấu chịu không nổi. Có một chương trình nhỏ nhỏ có thể dùng để thêm _NET_WM_ICON

./xseticon /usr/share/icons/hicolor/128x128/apps/emacs.png

Đẹp thấy ớn luôn (nhưng mà nếu mở cửa sổ mới phải làm lại, hic, phải nói chuyện lại với emacs devs). xseticon bản gốc ở http://www.leonerd.org.uk/code/xseticon/


Tác giả: pclouds | Liên kết tĩnh | Linux