Video compression nhìn từ bên dưới

Ghi chép lại một chút về kiến thức cơ bản lượm nhặt được về vấn đề nén video, không đi sâu cụ thể vào điểm nào, chỉ loanh quanh ở dưới …

1. Nếu video không được nén.
Thử ngẫm xem thú vui xem phim ảnh bị ảnh hưởng thế nào nếu video không được nén.
Xét trường hợp phổ biến nhất thời bấy giờ, full-HD (1920×1080), progressive, frame rate 24 fps (phò nhất có thể).
Một pixel được xây dựng từ 3 mã màu RGB (Red-Green-Blue) → 1 pixel cần 8×3 bit.
Vị chi là trong 1 giây sẽ có lượng dữ liệu: 1920 x 1080 x (8×3) x 24 = 1194393600bit ~ 1.2 Gbit.
Vậy bitrate để có thể play được video này là 1.2 Gbits/s
1 bộ phim tầm 1.5h sẽ có dung lượng: 806 GB

Trong khi đó, đĩa Blu-Ray DVD chứa được 25 GB (single layer), tốc độ đọc dữ liệu 36 Mbits/s, tốc độ TV Broadcast (truyền hình KTS) là 1 ~ 20 Mbits/s, tốc độ internet ~100 Mbps/s ( vừa kiểm tra bằng speedtest.net của internet đang dùng).

Con số trên đủ nói lên tất cả về khả năng trải nghiệm video nếu không được nén. Vậy nếu lấy dịch vụ dùng video phổ biến hiện giờ là internet, thì cũng cần ít nhất cần nén xuống > 12 lần mới ngang tầm bitrate của internet, còn nếu lấy theo recommend bitrate của youtube với fHD là 8 Mbits/s, thì cần nén tầm 150 lần.

Vậy nếu birate tầm 8 Mbps/s thì, theo cách tính trên thì sẽ xem được phim trên internet có format lên tới cỡ “kinh hoàng” là 160×120.

Thảm họa cho những ai thích xem phim nhỉ.

2. Nén video theo một cách khác.
Giả sử bỏ qua tất cả những cái gì gọi là phương pháp, thuật toán … nén video. Thử đi nén video bằng các công cụ như vẫn thường hay dùng để nén file thì chuyện gì xẩy ra, ví dụ dùng Zip chẳng hạn. Tạm thời chưa vội bàn về tỉ lệ nén có đạt được hay không (thật ra thì chắc chắn là không), thử xem xét xem sẽ vấp phải vấn đề gì.
Theo hình thức đơn giản nhất, cho 1 file video raw 806 GB ở trên vào, nén Zip, vậy là xong. Vậy khi muốn xem thì làm thế nào, vì chỉ giải nén được khi có toàn bộ file mà không có giải nén từng phần, do đó phải nhận đầy đủ 1 file đó rồi giải nén ra sau đó dùng 1 chương trình nào đó hỗ trợ xử được dữ liệu video raw xem :-). Thêm vào đó, chơi kiểu này thì không thể thực hiện streaming video (broadcast, internet …) vì không thể giải nén được được nếu chỉ nhận được từng phần của file.

Thử cố cải tiến nó lên 1 chút, bằng cách chia video raw đó ra nhỏ thành các picture rời nhau (có tất cả 24 fps * 1.5h * 60p * 60s = 129600 picture), và nén zip từng picture lại, rồi tìm cách truyền nó đi lần lượt để có thể xem được khi dùng dịch vụ xem trực tuyến. Nhưng ta sẽ gặp vấn đề sau.

  • Tỉ lệ nén khó đạt được, vì zip là nén không mất dữ liệu( lossless) thì khó mà lên được nén 150 lần.★
  • Ở trên đang mới xem đến việc xử lý các picture, giờ muốn truyền cái đó hay play như phim ảnh thì cần xem xét các yếu tố: Khi đóng gói đến gửi đi thì phải đánh dấu để phân biệt được vị trí các picture, cần đính kèm cả các thông tin để biết hiển thị video đó thế nào (frame rate, resolution …), cần thông tin thời gian từng picture để đồng bộ với audio … tóm lại cần qui định 1 format như MP4, MKV … để chứa loại dữ liệu video nén bằng zip đấy.

Ở trên ta thấy vấn đề bất khả thi nằm ở chỗ tỉ lệ nén, do zip là cách nén không mất dữ liệu nên không thể đạt được tỉ lệ nén như mong đợi. Thay vì dùng zip để nén từng ảnh thì dùng 1 cách nén lossly khác nén ảnh để đạt tỉ lệ nén cao hơn, ví dụ JPEG, tức là từ video raw, chia ra cách ảnh raw và nén nó lại bằng cách convert thành các ảnh JPEG :), nén JPEG chắc chắn đảm bảo được tỉ lệ nén, cùng lắm thì chất lường fò thôi ;-). Ngon rồi đây, giờ chỉ còn vấn đề số 2 như ở trên, với trường hợp này thì nó đã được giải quyết khi streamming thì nó đóng gói như này, còn lưu thành file thì nó theo format này, do chính Apple xử lý, hay Microsoft hỗ trợ để lưu nó trong file AVI …
Đây là câu chuyển của 1 chuẩn nén video có tên là MJPEG (Motion-JPEG), đúng như tên gọi, nó “đơn giản” chỉ là gồm các ảnh JPEG chuyển động.

Đến thời điểm hiện tại thì MJPEG có thể dùng làm đồ cổ được rồi. Tuy nhiên năm vừa rồi (2017) có tham gia 1 dự án thiết kế SOC cho Automotive (Lexus hẳn hỏi) vẫn có sử dụng MJPEG để record camera phía sau xe vì lý do xử lý nhanh, độ trễ thấp để đảm bảo driver delay thông tin nhìn từ sau xe.

3. Nền tảng cơ sở.
Nén video cơ bản là kiểu nén mất dữ liệu (lossly), cho dù các chuẩn nén mới từ MPEG2-Video trở đi đều hỗ trợ nén lossless, nhưng nó chỉ có ý nghĩa dùng để lưu trữ hơn là dùng trong lĩnh vực sử dụng, do tỉ lệ nén thấp. Khi nén lossless thì chỉ từ AVC/H.264 mới có thể nén thành file có dung lượng nhỏ hơn file gốc, điều này không có gì ngạc nhiên, do việc chuyển từ file video raw thành dạng có format phải mất 1 lượng overhead (thông tin header của các picture …). Tức là chỉ với AVC/H.264 trở đi thì việc nén dữ liệu video mới bù được lượng overhead trên.

Vậy nén mất dữ liệu thì cái gì được mất cái gì cần giữ. Vì ta biết “một nửa sự thật thì không còn là sự thật”, trong khi đó một nửa cục phân đất vẫn là cục đất. Thông tin trong video thuộc loại nào “sự thật” hay cục đất?
Để hiểu cơ sở nén video, thì xem lại chút về truyện ngụ ngôn học hồi lớp 7 (chương trình giáo dục trước khi bị tàn phá cải cách) Ở đây có bán cá tươi, có thể rút ra 2 điểm.

  • Thông tin thừa do bị lặp lại như: ở đây, có
  • Thông tin ít được chút ý, ít tác động đến đối tương cần truyền đạt: tươi
  • Thông tin quan trọng, phải giữ nguyên (trong truyện thì đi bỏ mất, thế mới là truyện ngụ ngôn): bán, cá

Vậy ra truyện ngụ ngôn ông cha ta từ lâu đã có liên hệ với kỹ thuật nén video hiện đại :-D.
Cũng tương tự như vậy, nén video là quá trình loại bỏ các thông tin thừa, giữ lại thông tin quan trọng. Với thông tin thừa do tính lặp lại, hoặc do thông tin đó không cần thiết đến đối tượng sử dụng (cái này không hẳn là thừa) cụ thể nhận thức trực quan của mắt người.
Cụ thể hơn, quá trình nén video là quá trình loại các thông tin dư thừa có thuộc tính dưới đây.

● Dư thừa thuộc tính không gian (Spatial redundancy)
Việc dư thừa này chỉ xét trong từng ảnh, bản thân các vùng không gian trong 1 ảnh luôn có sự liên quan ít nhiều đến nhau, vì hầu hết các vùng trong ảnh thể hiện không gian liên tục. Thuộc tính này được tận dụng khi thực hiện nén video, tìm cách loại bỏ sự tương quan về mặt không gian này.
Cụ thể như hình dưới đây, vùng màu đỏ đã được thực hiện nén trước đó, tiếp đến thực hiện nén block màu xanh. Việc nén block màu xanh, thì thay vì mang toàn bộ dữ liệu block màu xanh thì ta chỉ cần xử lý dựa trên block màu đỏ như sau.
Từ block màu đỏ, thực hiện phép dự đoán (tùy thuộc vào từng loại chuẩn video sẽ qui định cách dự đoán) để tạo ra block trung gian, như trong hình là nó kéo dài toàn bộ các pixel ở rìa bên phải, từ đó có thể tạo ra 1 block nhiều điểm tương đồng với block màu xanh. Thay vì nén toàn bộ block màu xanh, ta chỉ cần thực hiện nén sự khác nhau giữa block màu xanh và block trung gian này. Do 2 block này nhiều điểm giống nhau nên dự liệu cũng giảm đi đáng kể.
spatial
Thuật ngữ của việc này là Intra coding.

Cách làm của MJPEG nói ở trên, không tận dụng được thuộc tính này, do nó là các ảnh JPEG độc lập nhau. Đây vừa là điểm yếu (tỉ lệ nén không cao) vừa là điểm mạnh do thực thi đơn giản của MJPEG, nên dù chuẩn nén cổ nhưng nó vẫn được dùng trong một số trường hợp ở thời điểm hiện tại (2018).

● Dư thừa thuộc tính thời gian (Temporal redundancy)
1 luồng video thì tối thiểu cần lưu giữa 24 ảnh trong 1 giây (do tạo cảm giác liên tục đối với mắt con người). Một điều dễ nhận thấy là các bức ảnh cạnh chứa rất rất nhiều điểm giống nhau (trừ lúc chuyển cảnh), ví dụ như hình dưới đây.
temporal

Vậy khi ảnh Frame 3 đã được nén, thì việc thực hiện nén Frame 4, thay vì nén toàn bộ ảnh Frame 4, ta chỉ cần nén sự khác nhau giữa Frame 4 và Frame 3 tức là Frame 4 -Frame 3. Nhìn vào hình trên ta thấy lượng dữ liệu cần nén chỉ còn vài vùng chỗ khuôn mặt cô gái.

Trên thực tế khi thực hiện ở các chuẩn nén video, còn có các kỹ thuật nằm đưa nó về dạng giống nhau nhất có thể. Cụ thể là việc thay đổi giữa các ảnh do đối tượng trong những ảnh có sự chuyển động theo thời gian, kỹ thuật bù trừ chuyển động (Motion Compensation) chính là để xử lý việc này.
Việc nén này được biết đến với trên gọi là Inter coding.

● Dư thừa thị giác (Perceptual redundancy)
Chung qui lại, đối tượng của video là người xem, cụ thể hơn là con mắt người xem. Do đó trong quá trình nén video cần hiểu cách cảm nhận hình ảnh của mắt người. Mắt con người nhạy cảm với vùng có tần số cao (tức là vùng mà các pixel thay đổi nhiều, ví dụ như tóc cô gái dưới) hơn là vùng có tần số thấp (các pixel không thay đổi nhiều, ví dụ chỗ da ở má cô gái). Thực tế khi xem phim, những chỗ sắc nét (tần số cao) nếu bị nhiễu sẽ tác động rất nhiều đển việc cảm nhận chất lượng của video đó.
Do đó trong nén video cũng ưu tiên hơn việc giữ lại dữ liệu ở tần số cao, loại bỏ dữ liệu tần số thấp. Yêu cầu bitrate càng cao thì càng bỏ càng nhiều. Đây chính là quá trình gây ra mất dữ liệu trong nén video.

Perceptual.png

Trong video nén, quá trình trên được thực thi bằng biến đổi Cosin (DCT) nhằm chuyển dữ liệu sang miền tần số, và sau đó lượng tử hóa (Quantization) để bỏ bớt dữ liệu tần số thấp.

● Dư thừa thống kê (Statistical redundancy)
Sau khi thực hiện 3 quá trình giảm thông tin dư thừa, và cắt bỏ bớt thông tin không cần thiết ở trên, đến giai đoạn cuối cùng, sẽ cố gắng nén bằng các kỹ thuật nén không mất dữ liệu, bằng cách tận dụng sự lặp đi lặp lại của dữ liệu theo đúng ý nghĩa của nó, hoặc là sử dụng mã code có kích thước nhỏ để mã hóa cho những đoạn bit data có tần số xuất hiện lớn .Đến lúc này về cơ bản nó được đối xử như dữ liệu thông thường, tức là sẽ áp dụng các kĩ thuật nén không mất dữ liệu kiểu như Zip, chỉ là “kiểu như thôi”, vì nó phải cân nhắc nhiều yếu tố khác do đặc thù nén video.
Phase này trong nén video còn gọi là Entropy coding.

P/S: ★ Về việc nén lossless, có ai biết về mặt lý thuyết thì nén lossless sẽ bị giới hạn đế mức nào, thì nhờ chỉ bảo. Mình đang nghĩ là sẽ có sự ràng buộc nào đó vì lượng thông tin trong dữ liệu nhất định là cố định. Do tuỳ từng kiểu dữ liệu mà có tỉ lệ nén đạt được khác nhau nên chỉ dám kết luận là khó chứ không hẳn là không thể.

Định ngồi vẽ hình nhưng hơi lười vả có vẽ thì cũng xấu và lại không giá trị lắm, nên các hình vẽ được lấy trong tài liệu [1] dưới ↓

Tài liệu tham khảo
[1]https://pdfs.semanticscholar.org/presentation/6971/4ffd97c9b8b1af6f64f78dda3b920e576a7b.pdf
[2]https://en.wikipedia.org/wiki/Data_compression#Video

Apple codec & Sony codec

1. Vô đề.
Nghỉ hè dẫn vợ con đi chơi Fuji-Q, vùng dưới chân nói Phú Sỹ. Nhân dịp này mang con Handycam HDR-CX470 của Sony đi quay thằng ku chơi để về up lên cho các cụ ở nhà xem.
Vì không phải dân biết chơi Camcorder nên không có ý định review đánh giá con Handycam, chỉ là về xử lý thấy dung lượng file lớn quá, trong chừng mức có thể (về công cụ lẫn thời gian) thử xem qua xem các thánh Sony đang thiết kế bộ codec thế nào.
Vì đang dùng iphoneSE thần thánh, nên cũng tiện tay lướt qua xem Apple bí hiểm có gì khác không.

2. Công cụ sử dụng.
2.1. FFMPEG.
Trong thế giới multimedia processing, thì ffmpeg thì quá nổi tiểng nên không cần giới thiệu chi tiết. Đây là công cụ mã nguồn mở (opensource) mạnh mẽ, hỗ trợ đủ mọi video/audio đến multimedia file format (container).

FFMPEG được bắt đầu từ hồi “em mong ước đến năm 2000″(nhưng chiến tranh không tàn mà còn sống khỏe) bởi Fabrice Bellard (một trong những lập trình viên đẳng cấp nhất thế gian mà đang còn sống cho đến thời điểm hiện tại 07-2018) cho đến 2004. Sau đó được dẫn dắt bởi Michael Niedermayer Từ 2004 đến 2015.

Đến 13/03/2011, sau một thập kỉ phát triên, do không đồng quan điểm, một số thành viên nhóm phát triển (chắc ngộ Clean Code) muốn ưu tiên nâng cao chất lượng code & API. Các thanh niên đó đã tách thành dự án libav, vụ này gây ra bao nhiêu phiền hà cho cộng đồng :-(. Tuy nhiên các sửa đổi của libav vẫn được merger vào ffmpeg, có vẻ công việc này nhàm chán quá nên Michael Niedermayer đã từ chức leader vào 2015[4].

Ffmpeg được release theo package cho từng os riêng. Nếu không có mục đích tham gia phát triển ffmpeg hoặc cần sửa đổi source code thì strong recommend là lên trang chủ down về mà dùng luôn, vì nó đã enable rất nhiều lib phụ thuộc.

2.2. JM tool.
Trái ngược với ffmpeg, thì không nhiều người biết đến công cụ này, chắc chỉ sử dụng trong giới nghiên cứu về video coding, vốn dĩ đấy cũng là mục đích của nó chứ không phải hướng đến lĩnh vực ứng dụng. JM là viết tắt của Join Model (nghe tên hơi cà rốt), đây là h.264 codec (jvt codec),được nhóm JVT (nhóm hợp tác MPEG và VCEG) phát triển và dùng để xây dựng chuẩn nén h.264. Làm gì có codec nào có trước khi public chuẩn nén, nên dĩ nhiên nó dành quán quân về h.264 codec đầu tiên trên thế giới :-).

JM là full codec,  đầy đủ cả decoder lẫn encoder h.264. Sử dụng decoder của JM cho phép phân tích các thông tin chi tiết hơn về h.264.
JM có thể down trên trang chủ của ITU-T ở đây[3], theo README là có thể biên dịch ^^.

3. Thực hành.
3.1. Chuẩn bị video.
Đặt HDR-CX470 ở chế độ 1080P, 60fps, quay video nhiều cảnh động để đảm bảo bộ encoder làm việc tích cực nhất có thể. Sẽ phân tích tầm 1 phút, thời gian đủ dài để bộ encoder ổn định, do đó cần quay hơn 1 phút.

ffmpeg command cắt lấy 1 phút đầu tiên.

ffmpeg -ss 00:00:00 -to 00:01:00 -i 20180718125711.MTS -c copy sony.mts

3.2. Phân tích thông tin video cơ bản.
Cần tham khảo document của ffmpeg để hiểu các thông tin trong khi phân tích.
● Đầu tiên là xem thông tin cơ bản nhất về các stream video/audio, bằng command dưới.

ffprobe -show_streams sony.mts

Từ output log, lấy ra một số giá trị như dưới.

str1
str2

Từ đó có thể rút ra được vài thông tin sau.
– Birate 27 Mbps
– High profile, level 4.2. xem ý nghĩa profile/level ở [7].
– Khi encode, chỉ sử dụng 1 picture để tham chiếu đối với tham chiếu liên ảnh. (Với level 4.2 thì h.264 support tối đa có thể tham chiếu đồng thời 4 ảnh).

● Phân tích chi tiết hơn chút về thông tin từng ảnh.

ffprobe  -show_frames -select_streams v:0 sony.mts

Chỉ tập trung vào 2 thông tin khoanh đỏ.
str3
Thông tin này thay đổi theo từng picture, hình ở trên chỉ là picture đầu tiên.
Sau khi kiểm tra toàn bộ thông tin ở trên với tất cả các picture thì được như dưới.
Về pict_type thì thấy được cấu trúc I,P,P …I,P,P … Có 29 ảnh P giữa các ảnh I, không có ảnh B.
→ GOP có dạng I,P,P …P (30 ảnh). Việc không có ảnh B làm cho độ phức tạp khi thiết kế bộ codec giảm đi đáng kể.
→ Theo thông tin trên chỉ số ảnh dùng tham chiếu (refs=1), do đó chỉ là ảnh sau tham chiếu ảnh trước.

pts (Presentation Time Stamp) để chỉ thời điểm mà picture đó được hiện thị, xem giá trị này với tất cả các picture thì ta thấy giá trị này tăng đều.
→ Các ảnh không bị thay đổi thứ tự trong quá trình encode.  Từ thông tin chỉ có ảnh I,P (không có B) cũng dễ đoán được điều này.

● Và nhiều thông tin cực kì chi tiết
Dùng ffmpeg bằng các option của nó (ex: debug …) có thể phân tích thông tin rất chi tiết đến cả macroblock, nhưng nó ngoài phạm vi bài viết.

3.3. Phân tích QP của picture.
QP là của mỗi picture, sinh ra từ quá trình rate control xem ở [5]. Xem QP của mỗi picture cho ta hình dung qua được độ phức tạp của chiến lược rate control trong bộ codec.

Tìm mãi không thấy command cho phép ffmpeg log giá trị trung bình QP của từng picture nên đành dùng JM. JM chỉ làm việc với element stream, tức là raw h.264 chứ không chơi với container, như mts, mp4 … Do đó đầu tiên vẫn phải nhờ ffmpeg bóc cái h.264 element stream ra.

ffmpeg.exe -i sony.mts -c:v copy sony.264

Đưa vào JM, và thực hiện decode bằng command dưới.

ldecod.exe -d decoder -P InputFile=sony.264

qp
Ôi, than ơi, các thánh chơi QP cố định = 30 cho các picture cmnl. Vậy ở level picture thì giá trị QP chả điều chỉnh gì hết, tất nhiên xuống mức macroblock có thể điều chỉnh quanh giá trị này.

4. IphoneSE của Apple thì sao.
– Birate 23.7 Mbps
– High profile, level 4.2.
– Khi encode, chỉ sử dụng 1 picture để tham chiếu.
– GOP: I,P,P ..P (60 ảnh).
– Không có ảnh B, tức là không có sự thay đổi thứ tự để hiển thị.
– Rate control có vẻ tích cực hơn, QP thay đổi từ 20 ~ 31 . I picture là ảnh quan trọng ảnh hưởng nhiều đến chất lượng,  vì thế nên nên được encoder với QP thấp hơn.
– Cơ bản Apple dùng QP thấp hơn, độ mất mát thông tin ít hơn, nhưng vẫn nén được bitrate thấp hơn Sony? ( thật ra phải cùng 1 data đầu vào mới nói được vậy).

5. Kết luận.
A/e được học video coding, bao nhiêu thứ phức tạp như ảnh B tham chiếu 2 chiều cả quá khứ lẫn tương lai, h.264 cho phép 1 picture có thể đa tham chiếu (multi refer) lên đến 16 picture, cấu trúc GOP của h.264 rất tự do cho phép reorder, tham chiếu thoải mái …
Nhưng thực tế phũ phàng là để đạt được realtime (chắc là thế) các bộ encoder trong các thiết bị có vẻ phải hi sinh nhiều thứ để giảm độ phức tạp. Thậm chí cấu trúc GOP trên của h.264 còn đơn giản hơn cấu trúc của MPEG2-Video có ảnh B.
Mặc dù có vẻ codec trong IphoneSE chỉnh chu hơn HDR-CX470, nhưng để so sánh codec là vấn đề rất phức tạp mà cái quan trọng nhất là phải chung 1 dữ liệu đầu vào, trong khi đã đóng gói trong sản phẩm thì điều đó là không thể. Bài viết cũng chỉ là ngó qua một số thông tin từ kết quả video để phán đoán 1 chút về bộ encoder.

Tuy nhiên, một thiết bị quay video tốt, thì bộ encoder không phải là tất cả, ngoài ra còn ống kính, tính năng room, chống rung … tác động rất lớn đến chất lượng video và trải nghiệm.

Tham khảo.
[1]https://www.ffmpeg.org/
[2]https://en.wikipedia.org/wiki/FFmpeg
[3]https://www.itu.int/rec/T-REC-H.264.2-201602-I/en
[4]https://ffmpeg.org/pipermail/ffmpeg-devel/2015-July/176489.html
[5]https://vcostudy.com/2018/04/21/rate-control-video-coding
[6]https://www.ffmpeg.org/documentation.html
[7]https://vcostudy.com/2018/04/14/profile-va-level-trong-ma-hoa-video

Raspberry PI transcodes video

1. Transcode là gì.
Transcode là quá trình chuyển đổi từ định dạng mã hóa hiện tại sang một dạng mã hóa khác, ví dụ như chuyển đổi video, audio coding format …
Thông thường thì việc thực hiện transcode có 2 lý do chính:
– Giảm dung lượng lưu trữ mà có thể đảm bảo được chất lượng video, bằng việc sử dụng video coding format tân tiến hơn, tăng khả năng nén hơn, nên các dữ liệu video đang sử dụng coding format cũ thường chuyển sang format mới để giảm dung lượng lưu trữ.
– Thiết bị đầu cuối không hỗ trợ video or audio hiện tại, do đó cần convert sang cái dạng mà nó hỗ trợ.

Trên thực tế hiện nay thì dễ thấy nhất là khi upload 1 file video lên facebook hoặc youtube, thì file video đó luôn được youtube/facebook xử lý thành định dạng khác trong quá trình upload.

Cơ bản thì quá trình transcode có thể hình dung đơn giản như dưới.

input file/stream → |decode| → |encode| → output file/stream

Từ dữ liệu đầu vào, có thể là multimedia file format (MKV, MP4 …) hoặc stream (udp, tcp/ip …). Bước đầu tiên là giải mã (decode) thành phần đầu vào (video or audio tùy thuộc vào cái nào cần transcode) thành raw data. Tiếp đó thực hiện mã hóa (encode) thành định dạng mới ở dữ liệu đầu ra.

Transcode có thể realtime or non-realtime tùy thuộc vào từng yêu cầu của hệ thống. Trong các dữ liệu cần transcode thì video là phức tạp, tốn nhiều hiện năng nhất, và thường quan tâm nhất , do việc nén video theo chuẩn mới có thể tiết kiệm rất nhiều dung lượng or bitrate.

2. Video decoder/encoder trên RPI.
Raspberry pi(RPI) hỗ trợ cả hardware decoder lẫn encoder, do đó rất phù hợp nếu sử dụng nó để thực hiện transcode.
2 bộ decoder và encoder trên RPI được thiết kế theo API của openmax mà cụ thể là openmax-il.
Openmax là chuẩn các api do khronos đưa ra để thiết kế hệ thống xử  lý multimedia, nó gồm có 3 phần tương được với 3 layer, nhìn hình dưới lấy từ trang chủ có nó thì hiểu, khỏi cần giải thích.
media_portability
Cái gì mà được chuẩn hoá thì mục đích cao nhất của nó là giúp giảm thời gian tích hợp, 2 thằng không cần biết nhau trước đó mà chỉ cần cùng tuân theo 1 chuẩn là dễ dàng tích hợp với nhau.
Openmax-il có thể hiểu là lớp trung gian giữa phần cứng (hardware) và application hay còn gọi là firmware, đây cũng là phần API được sử dụng rộng rãi nhất của openmax. Android media framework, ffmpeg, gstreamer đều đã hỗ trợ openmax-il với tư cách là IL client, tức là layer ngay ở trên openmax-il . Do đó nếu bạn rảnh rỗi thiết kế 1 con chip hỗ trợ video decoder tuân thủ theo đúng api của openmax-il thì bạn có thể nhanh chóng tích hợp được vào các hế thống trên :-), và bán con chip đó luôn được để kiếm xèng.

Chi tiết openmax thì vào trang chủ của nó để tham khảo ở đây[3].
Thông tin các openmax-il component trên RPI thì tham khảo chỗ này[5].

3. Thực hiện transcode video trên RPI.
3.1. Thực hành transcode với RPI.
Omxplayer là cli hoạt động rất ổn định khi dùng play video trên RPI. Mình vẫn dùng để mở clip tàu điện Nhật Bản phục vụ ông con thích tàu xe.
Omxplayer sử dụng hardware decoder của RPI, và tất nhiên là thông qua openmax-il, cấu trúc của nó như hình dưới.
dec_rpi

Xuất phát từ ý tưởng dùng RPI để chuyển đổi video streaming mpeg2-video đang có sẵn thành h.264 để giảm bitrate nhằm tiết kiệm băng thông. Dựa trên omxplayer
với một chút sửa đổi nhỏ sau:
– Bỏ audio decoder, vì audio chiếm băng thông không đáng kể, không cần thiết transcode nên audio vào thế nào cho ra thế đó.
– Cắt bỏ phần xử lý hiện thị (render component), vì chỉ cần chuyển đổi sang video format khác, kết quả sẽ streaming hoặc lưu thành file.
– Thêm component encoder, nối vào ngay sau decoder. Để thực hiện encode lại ảnh, kết quả của bộ decoder sau khi giải mã đầu vào.
– Thêm phần xử lý output streamer, module này có nhiệm vụ lưu audio + video sau khi convert thành file hoặc streaming qua udp hoặc tcp/ip hoặc protocol nào đấy.

Sau khi sửa đổi thì cấu trúc nó thay hình đổi dạng như dưới.
transcode_rpi

Source code & readme hướng dẫn sử dụng chứa ở đây

Kết quả chạy thử, đạt được realtime và bitrate giảm 1 nửa.
input http streaming: mpeg2-video,size 720×576, 25fps, bitrate 4mbps.
output udp streaming: h.264, size 720×576, 25fps, bitrate 2mbps.

Khi play stream gốc và stream sau khi đã transcode thì chất lượng theo đánh giá chủ quan là tương đương nhau. Cần chú ý rằng, đây chỉ là về mặt visual, còn nén video là nén mất dữ liệu (lossly) do đó cái output không bao giờ bằng được input nếu nói trên quan điểm thông tin.

●Hiện tại đang có các điểm hạn chế cần điều tra và cải thiện:
– Chạy được tầm 1h ~ 2h thì tự dưng lăn quay là treo → bug cần điều tra.
– Openmax-il có định nghĩa 2 kiểu kết nối để component truyền data cho nhau, là tunnel (kết nối trực tiếp) và non-tunnel (kết nối gián tiếp thông qua IL client). Định dùng tunnel cho đơn giản, nhưng thử mãi không được nên đang dùng non-tunnel, thành ra quản lý buffer đang hơi stupid nên output buffer của decoder được copy sang encoder. → Cần điều tra lại đển dùng tunnel hoặc improve việc quản lý buffer để bỏ xử lý copy.
–  Phần output streamer module cần design là 1 thread độc lập, nhận video/audio buffer ở component trước đó thông qua queue, nhưng hiện tại đang thực hiện như bằng context của video & audio (được buffer nào thì streaming luôn).

3.2. Dùng ffmpeg.
Đợt này có chút thời gian, định quay lại xử lý mấy hạn chế & bug của 3.1 thì mới để ý thấy ffmpeg nó cũng support openmax rồi, như vậy đơn giản thế này thôi.
– Clone ffmpeg và tham khảo chỗ này để enable omx khi compile.
– Nếu ngại complile từ source code thì có thể cài đặt ffmpeg thông qua repo của RPI, package đã được enable omx: sudo apt-get install ffmpeg

Dùng command dưới là xong :-).

ffmpeg -c:v mpeg2_mmal -i http://address_input -c:a copy -c:v h264_omx -b:v 2000k -f mpegts udp://address:port

Tuy nhiên có vẻ có vấn đề với input streaming interlace, ngoài ra chưa stress test nên chưa biết thế nào. Từ POC (proof-of-concept) đến Mass Product là một khoảng cách lớn, haizz …

●24/07/2018 update: Input stream đang sử dụng là interlace, trong khi đó bộ encoder h.264 trên RPI không support interlace nên aspect ratio output stream bị sai. Có thể cần xử lý de-interlace trước khi encode. Hoặc với video hiện tại thì có thể dùng encoder bằng software encoder (libx264) như command dưới, sử dụng option encode performance gần cao nhất, với video size 720×576 thì vẫn đạt được realtime, tuy nhiên con chip nóng quá, không dám chạy stress-test vì sợ nó ngỏm.

ffmpeg -c:v mpeg2_mmal -i http://address_input
-c:v libx264 -preset superfast -f mpegts -b:v 2000k -s 720×576
udp://address:port

P/S: Lưu ý, RPI mặc định chưa enable hardware mpeg2-video codec, muốn dùng phải bỏ tiền ra mua ở đây.

Tham khảo.
[1]https://en.wikipedia.org/wiki/Transcoding
[2]https://www.raspberrypi.org/forums/viewtopic.php?f=72&t=72260
[3]https://www.khronos.org/openmax/
[4]https://source.android.com/devices/media/
[5]http://www.jvcref.com/files/PI/documentation/ilcomponents/
[6]https://github.com/popcornmix/omxplayer
[7]https://github.com/truongpt/rpi_transcode

Zero start with video coding

Hoàn cảnh éo le.
Ra trường giữa 2009, tham gia 1 dự án làm về DTV (Digital Television) đến tận đầu 2012, vậy là 2 năm rưỡi, biết được một chút về video decoding do đàn anh  chỉ dạy cho lúc bắt đầu dự án, còn lại OT vật vã cho kịp deadline. Sau này ngẫm lại thấy đa phần kiến thức cơ bản về video coding bị sai → quá nguy hiểm.
Vào 7/2013 sang Nhật làm việc đến 4/2017 trong dòng dự án về 4k – Television và Camera recorder. Trong thời gian đó có tầm 1 năm rưỡi cuối làm về video encoding. Về công việc thì test nhiều hơn là code. Do  rảnh rỗi không biết làm gì, nên học thêm chút về video encoding cho qua ngày.
Rút ra được vài ba kinh nghiệm quí báu, khi làm việc trong cái mảng việc này (mảng khác chắc cũng thế).
– ① Nên theo từ lúc đang đi học, như thế sẽ được chỉ dạy kiến thức cơ bản bởi những người biết về kiến thức cơ bản.
– ➁ Nếu ko có cơ hội ①, khi vào dự án chiến luôn mà nghe trong team chém gió (sợ nhất là các thánh phán), phải điều tra cẩn thận trước khi coi đó là chân lý.
– ③ Cái số ➁ cực kì nguy hiểm, nếu không may mắn có cái ① thì nên tìm sư huynh cho thật ngon mà học, vừa nhanh vừa an toàn.
Mình là nạn nhân con số ➁, sau nhiều năm mới sửa sai được một số vấn đề cơ bản, mà suýt bị nó làm cho tẩu hỏa nhập ma. Ngoài ra công việc gián đoạn không làm video coding nữa, nên giờ ngồi viết lại, lỡ sau này may mắn có cơ hội làm tiếp về video coding thì có chỗ mà tra cứu cho nhanh :-).

Một vài điểm bắt đầu.
Có mail hỏi 1 ông anh, chuyên gia video coding ở Đức, thì đại ka gợi ý đọc quyển này. Mình nhai mãi chưa xong (vẫn tiếp tục nhai khi có thời gian), toàn kiến thức nền tảng, phù hợp cho ai thích đi theo hướng nghiên cứu. Còn giờ đang cần tiếp cận theo hướng ứng dụng.
Bắt đầu một vài gạch đầu dòng cơ bản.
– Video thực ra là một chuỗi ảnh(picture) sắp xếp liên tục theo thời gian (có lẽ ai cũng biết?), vì vậy nén video chẳng qua là nén lần lượt các ảnh này.
– Nén video cơ bản là nén mất dữ liệu (lossly), nhưng bất kì chuẩn nén video nào cũng chứa 2 giai đoạn. Giai đoạn 1 nén lossly (transform + quantization) và giai đoạn 2 nén lossless (entropy coding). Một số chuẩn nén như AVC/H.264, HEVC/H.265… cho phép chỉ nén lossless bằng cách cho phép bỏ quá trình nén lossly.
– Xét ở đặc điểm sau khi nén của picture, có thể chia thành 2 loại kỹ thuật nén là INTRA (nén trong ảnh) & INTER (nén liên ảnh). INTRA là cách nén picture chỉ dựa vào thông tin chứa trong bản thân picture đó, ngược lại INTER có sử dụng thông tin các picture lân cận để thực hiện nén picture đó.
– Quá trình nén picture được thực hiện theo từng block có kích thước vuông giống nhau. Đối với chuẩn nén H.264 trở về trước gọi là Macroblock kích thước 16×16 pixel, còn đối với H.265 gọi là Coding Tree Unit và nó cho phép chọn từ 16×16 ~ 64×64 pixel. Với các chuẩn nén không phải của ISO or ITU-T, ví dụ VP8, VP9 của google, tên gọi các block đó có thể khác nhưng cơ bản đều mang ý nghĩa giống nhau.

Sẽ có rất nhiều thắc mắc, ví dụ INTRA & INTER được thực thi cụ thể thế nào? nó thể hiện thế nào trong quá trình xử lý các block trong từng picture?, google phát toàn ra 1 đống như motion vector nó nằm ở đâu trong khái niệm trên? vân vân và vân vân. Với một cơ số khái niệm, cùng với đống tài liệu trên mạng (rác cũng nhiều), vội vàng dễ bị chết đuối cho nên đừng vội tham lam, đi từ từ rồi sẽ đến.
P/S: Kiến thức mình chia sẻ thuộc trường hợp số ➁, cẩn thận khi có ý định sử dụng nhé!

Versatile Video Coding

1. Tên gọi chuẩn nén video mới.
Cuộc cuộc họp thứ 10 diễn ra ở San Diego – Mẽo, từ 10~20/04/2018 của JVET, nhóm hợp tác để thiết kế chuẩn nén video mới của ISO/IEC và ITU-T, đã đánh dấu mốc quan trọng của dự án, khi toàn bộ các đề xuất công cụ nén bắt đầu được đánh giá, thảo luận để tích hợp vào đặc tả. Thêm vào đó tên của chuẩn video tiếp theo sau HEVC được chính thức đặt là VVC, viết tắt của cụm từ Versatile Video Coding, nghe có vẻ khá uyên bác, và trông nguy hiểm.
Bản thân ISO/IEC và ITU-T sẽ quản lý chuẩn nén bằng tên mã riêng của từng tổ chức nên thường có qui định rõ của mỗi bên, còn cái tên VVC một kiểu tên riêng của dự án, thường đặt do ngẫu hứng nên nó trở nên rất thú vị, mặc dù chỉ mang tính hình thức. Trước đó đã có ý kiến thảo luận muốn chấm dứt kiểu tên gọi xVC bằng một kiểu đặt tên mới, đại loại như đặt theo địa điểm mà đội JVET chưa bao giờ đặt chân tới là Antarctica (châu Nam Cực)… Tuy nhiên với tên gọi VVC thì ISO/IEC và ITU-T vẫn tiếp tục duy trì phong cách như 2 chuẩn video trước đây AVC, HEVC. Xem chừng tiếng anh khá phong phú.
Về quá trình thành lập dự án và cách làm việc có thể xem lại tại đây

2. Kết quả hiện tại và kế hoạch tiếp theo.
Hưởng ứng kêu gọi đề xuất, trong cuộc họp lần thứ 10 này 32 tổ chức (công ty, học viện, trường đại học) khác nhau đã công bố 46 đề xuất. Các công cụ mã hoá được đề xuất gồm có 22 thuật toán nén cho SDR (standard dynamic range) , 12 mục HRD (high dynamic range), và 12 đề xuất cho video 360.
Toàn bộ các đề xuất được thảo luận vào đánh giá, chi tiết có thể tham khảo ở tài liệu[1].

Kết quả hiện tại đã đạt được khả năng nén lên tới 40% so với HEVC. Bản đặc tả chuẩn nén phiên bản tạm đầu tiên đã được thiết lập[2].
Cuộc họp lần này cũng đã quyết định sử dụng test model mới có tên là VTM (Versatile Video Coding Test Model)[3] thay thế cho JEM. Bản chất VTM được tái cấu trúc từ JEM do Fraunhofer HHI[6] thực hiện và đề xuất. So với JEM thì VTM được cải thiện thiết kế phần mềm, hiệu năng, nên dễ dàng tích hợp các thuật toán đề xuất vào hơn, đồng thời cho phép disable/enable các coding tool lúc runtime trong khi đó JEM bắt buộc phải biên dịch lại giúp tăng hiệu suất làm việc.

Như vậy theo như kế hoạch lúc JVET đưa ra lúc kêu gọi các đề xuất[7] thì còn tầm 30 tháng nữa, phiên bản đặc tả chính thức sẽ ra mắt, cùng lúc với Olympic ở Tokyo.

2018/04 Test model selection process begins
2018/10 Test model selection established
2020/10 Final standard completed

Tài liệu tham khảo.
[1]http://phenix.it-sudparis.eu/jvet/doc_end_user/current_document.php?id=3489
[2]http://phenix.it-sudparis.eu/jvet/doc_end_user/current_document.php?id=3538
[3]http://phenix.it-sudparis.eu/jvet/doc_end_user/current_document.php?id=3539
[4]http://blog.chiariglione.org/the-mpeg-machine-is-reasy-to-start-again/
[5]http://www.streamingmedia.com/PressRelease/Versatile-Video-Coding-(VVC)-Project-Starts-Strong-with-the-Joint-Video-Experts-Team_47071.aspx
[6]https://www.hhi.fraunhofer.de/en.html
[7]https://www.itu.int/en/ITU-T/studygroups/2017-2020/16/Documents/video/JVET-H1002-CFP-VCBHEVC-Final-v6.pdf

Ẩn dấu dữ liệu bằng motion vector

1. Information Hiding, Digital Watermarking and Steganography
Đây là các khái niệm nói việc việc mã hóa, nhúng thông tin vào trong đối tượng (có thể là picture, audio, video …), có liên quan đến vấn đề bảo mật thông tin, hoặc bảo vệ bản quyền.
Đây là vấn đề rộng, chỉ đưa ra keyword chứ không dám lạm bàn, kẻo thành nói ngu, mà nói ngu thì cực kì nguy hiểm cho cả bản thân với ai đó chưa biết mà không may đọc phải.

2. Ẩn dấu dữ liệu bằng motion vector
Motion compensation (bù chuyển động) là thuộc loại công cụ nén quan trọng và mang về tỉ lệ nén rất cao trong việc nén video.
Với các ảnh liên tiếp nhau, về cơ bản là đối tượng trong ảnh phần lớn giống nhau (trừ tình huống chuyển cảnh), chỉ khác nhau do vị trí của nó bị xê dịch. Kỹ thuật bù chuyển động đưa ra nhằm tận dụng đặc trưng này của luồng video, thay vì lưu lại toàn bộ ảnh thì nó chỉ lưu lại phần chuyển động của bằng các vector, gọi là motion vector. Dĩ nhiên là cả điểm khác nhau sau khi đã bù chuyển động (DPCM), nhưng sự khác nhau này đã giảm đi đáng kể sau khi có tính đến bù chuyển động. Trong việc nén video, thì quá trình tìm kiếm vùng giống nhau giữa các ảnh sẽ quyết định motion vector tối ưu.
mv1

Vấn đề muốn đề cập ở đây, là ta có thể tận dụng chính bộ vector này để đồng thời mã hóa dữ liệu mong muốn trong quá trình nén video. Đầu tiên bộ encoder sẽ tìm motion vector tối ưu, trước khi đưa motion vector đó vào thực hiện nén video, thì chỉnh sửa nó một cách có chủ ý nhằm nhúng dữ liệu vào đấy, tất nhiên giá trị motion vector không còn tối ưu nữa, nên ảnh hưởng ít nhiều đến chất lượng video. Việc chỉnh sửa thế nào tuân theo 1 qui tắc nào đó mà chỉ có encoder, và tiết lộ cho bên decoder mà được phép nhận chia sẻ dữ liệu đó biết, bên phía decoder khi giải mã video đó thì dựa vào motion vector sẽ lấy được thông tin được ẩn dấu trong đó.
Để dễ hình dung có thể xem hình vẽ dưới.
hidedata1

3. Thử chơi với H.264
Áp dụng cho H.264, bằng cách chọn một codec có sẵn nào đó, sửa motion vector theo 1 qui luật nhất định.
Để dễ dàng thực hiện thì sử dụng codec hàn lâm nhất jvt codec[2], cái này là codec do JVT sử dụng trong quá trình xây dựng chuẩn nén H.264.
Nếu xem xét motion vector nhỏ hơn 1 giá trị ngưỡng nào đấy (threshold value) thì sẽ sửa nó về giá trị nhỏ hơn hoặc bằng sqrt(2), tức là motion vector nhỏ hơn giá trị ngưỡng luôn có giá trị trong tập (0,0); (0,1) ; (1,0) ; (0,-1);(1,1)… Bằng cách qui định dữ liệu ứng với với các giá trị này thì ta có thể mã hóa 1 chuỗi bit nhị phân bằng motion vector (tham khảo file insert_data.c trong source code[3]).
Sau khi chỉnh sửa jvt codec[2], bộ codec mới của H.264 ở [3] đã hỗ trợ việc sử dụng motion vector để nhúng dữ liệu vào ở bộ encoder, còn bộ decoder thì có thể giải mã nó và lưu thành 1 file có kết quả giống như dữ liệu đã nhúng.

h264_1
Thông tin và cách sử dụng có thể tham khảo readme.txt của source code[3], khi thay đổi data video đầu vào như frame size, số frame thực hiện mã hóa … thì cần sửa lại file cấu hình (config) của bộ encoder cho phù hợp.

Hạn chế: làm lâu rồi nên không nhớ, nhưng hình như khi nhúng data bằng cả motion vector trước và sau (backward & forward) thì có bug, ai đó fix hộ đi 😀 .

Tài liệu tham khảo
[1] https://en.wikipedia.org/wiki/Digital_watermarking
[2] http://iphome.hhi.de/suehring/tml
[3] https://github.com/truongpt/jm19.0_watermarking

 

Rate control in video coding

1. Rate control là gì.
Cụm từ này không biết nên dịch sang tiếng việt thế nào, nên thôi tạm để nguyên từ gốc của nó.
Rate control là một trong những phần quan trọng nhất trong bộ encoder để quyết định video sau khi nén có đạt được bitrate đúng yêu cầu hay không. Ngoài ra nó còn có ảnh hưởng rất lớn đến việc giữ cho chất lượng của các hình ảnh (picture) trong video sau khi nén, có được sự ổn định, chất lượng đồng đều nhau.
Đây thuộc phần tốn rất nhiều mồ hôi và cả “chửi tục” của các kỹ sư trong quá trình phát triển video encoder. Do việc có được một xử lý rate control tốt cần rất nhiều thời gian, cũng như cần người giàu kinh nghiệm để có thể hiệu chỉnh được các hệ số hợp lý, và rất nhiều trường hợp mong muốn ra con bò thì nó ra con dê.

Các bộ encoder gần như được tự do sử dụng các phương pháp, các chiến lược (strategy) cho rate control, vì vấn đề này xem như nằm ngoài phạm vi phủ sóng của đặc tả chuẩn nén.

2. Vai trò của rate control.
Một bộ encoder khi thực hiện nén video luôn xác định mức độ cần nén là bao nhiêu, việc này được bởi yêu cầu bitrate đầu vào. Dựa trên thông tin đó, rate control sẽ quyết định mức độ nén của video, mà mang tính chất quyết định nhất là giá trị QP (Quantilization Parameter: Thông số lượng tử), con số này càng cao thì độ nén video càng lớn, và tất nhiên được cái lọ thì phải bỏ cái chai, độ mất mát thông tin cũng lớn theo tức là chất lượng video sẽ kém đi.

Ngoài giá trị độ lớn thì mỗi mảng ứng dụng lại có một yêu cầu riêng về thuộc tính đối với bitrate, ví dụ broadcast video thì thường yêu cầu bitrate cố định (constant bitrate, dĩ nhiên cũng chỉ là tương đối thôi), với IP television thì lại cho phép bitrate có thể thay đổi trong một phạm vi giới hạn.

Quay lại về việc thực hiện nén video, một điều hiển nhiên là các ảnh trong một luồng video luôn có mức độ nén không giống nhau, ảnh I sẽ có size (dung lượng) lớn hơn ảnh P,B, do 2 ảnh này được phép sử dụng tham chiếu đến ảnh khác, nên độ nén tăng lên đáng kể. Trong khi đó frame rate (số hình ảnh được hiển thị trong 1 giây) thường là cố định, do đó nếu không có sự điều chỉnh hợp lý thì bitrate sẽ thay đổi không phù hợp với ứng dụng tương ứng. Đây là nhiệm vụ cơ bản của rate control.

Về vấn đề ổn định chất lượng, nếu xem video lúc thì hình ảnh rõ nét, lúc thì xấu như ma lem thì thà xấu toàn bộ chắc xem còn dễ chịu hơn. Rate control cũng là nhân tố quan trọng trong vấn đề này. Do rate control liên tục điều chỉnh độ nén của từng ảnh liên tiếp để thỏa mãn yêu cầu bitrate, nhưng nó cũng phải ràng buộc để các ảnh liên tiếp nhau chất lượng không quá khác nhau nhiều quá, tránh tạo ra video dek thằng nào muốn xem. Một video tốt cần có chất lượng đồng đều nếu có thay đổi cũng nhẹ nhàng như chứng khoán chứ không được đột biến như đồ thị bitcoin. Dĩ nhiên đến làm được điều này thì không chỉ mỗi rate control mà còn các xử lý khác, nhưng có thể nói rate control là con bài át chủ.

3. Rate control làm việc như thế nào.
Trên thực tế cũng như lý thuyết đây là một phạm vi rất rộng, vì rate control thực ra là một mô hình dự đoán trước để quyết định tham số nén quan trọng là QP, do đó với mỗi chuẩn nén khác nhau lại cần một phương pháp khác nhau. Mỗi khi một chuẩn nén ra đời lại kéo theo một mớ chuyên gia mò ra chiến lược rate control phù hợp, âu cũng là tạo công ăn việc làm cho xã hội.

Trong ứng dụng thực tế, phải chấp nhận điểm cân bằng giữa chất lượng rate control đạt được và độ phức tạp của nó. Thậm chí có nhiều bộ encoder còn sử dụng luôn giá trị cố định QP cho từng loại picture.

Về cơ bản có thể hiểu một cách đơn giản thì rate control diễn ra như hình vẽ dưới. (Chú ý các khái niệm GOP, I,P,B picture đang hiểu theo định nghĩa của MPEG2-Video. Đây là khái niệm cơ bản cần nắm vững nên sẽ có bài ôn lại về cái mớ lộn xộn này sau).

rate1

GOP là 1 nhóm picture có tính lặp đi lặp lại trong một chuỗi video, do đó rate control thường đi theo đơn vị là GOP.

●Bước 1: Ở lớp GOP, từ bitrate và frame rate thì dễ dàng tính được cần nén 1 GOP đạt được size bao nhiêu. Nếu GOP này là xuất phát của video thì cứ theo giá trị đó sử dụng, nếu không thì cần cân nhắc bù trừ vớ sai lệnh của GOP trước đó.

●Bước 2: Mỗi GOP thông thường có 1 ảnh I và số lượng ảnh P,B cố định. Từ size của GOP sẽ ước lượng được size ảnh I,P,B mà bộ nén cần đạt được, tất nhiên có cân nhắc đến độ lớn của ảnh I,P,B bằng các hệ số, mà hệ số này liên tục được thay đổi sau mỗi lần thực hiện nén ảnh để đảm bảo dần dần có độ chính xác nhất.
Từ size của mỗi ảnh, ví dụ ảnh I thì rate control sẽ dựa vào mô hình ước lượng đển ước tính giá trị QP của ảnh I đó.

●Bước 3: Từ size của ảnh, tiếp tục ước lượng giá trị size của MB(macroblock) cần đạt được, kết hợp với giá trị QP ở bước 2 sẽ ước lượng ra được giá trị QP của MB đó.

Sau bước 3 thì MB đã đủ điều kiện và sang bước tiếp theo để thực hiện chính thức nén. Sau khi có kết quả size thực tế của MB đó sau khi nén thì rate control lại so sánh với size dự đoán, dựa vào độ sai lệch đó để bù vào MB tiếp theo và cập nhật lại thông số mô hình dự đoán. Quá trình này tiếp diễn lên đến lớp GOP.

Tuy nhiên đời không như mơ, thực tế thì có những bộ encoder mà GOP có thể thay đổi, số ảnh trong GOP không cố định. Hay là có những vị trí chuyển cảnh (scene change), hay mức độ sai khác với ảnh trước rất lớn (fade in/out) thì nếu điểm đó là ảnh P, thì ngay cả ảnh P cũng cần chọn giảm hệ số nén để giữ chấp lượng vì sẽ ảnh hưởng lớn đến các ảnh sau. Do đó tùy sự ưu tiên của từng bộ encoder mà chiến lược rate control khác nhau.

4. Tương thích với đặc tả.
Mặc dù rate control là phạm vi nằm ngoài đặc tả chuẩn nén video, nhưng chuẩn nén cũng có một số ràng buộc tương đối khi kiểm tra video đó có tương thích với bộ decoder hay không.
Ở các mục lục của đặc tả chuẩn nén, với H.264 thì ở Annex C Hypothetical reference decoder, đều đưa ra yêu cầu nhằm đảm bảo bộ decoder sẽ không bị mất data hay data không đến kịp đển thực hiện decode mặc dù nó đã thực hiện tuân theo đặc tả chuẩn nén.

Hình vẽ dưới miêu tả tình trạng CPB (Coded picture buffer: vùng nhớ chứa dữ liệu đầu vào của bộ decoder). Dữ liệu vào vùng nhớ này tăng tuyến tính (giả sử với constant bitrate) vì đến thời điểm ảnh nào được decode thì bộ decoder sẽ lấy ảnh đó ra khỏi bộ đệm. Do đó nếu ảnh quá lớn thì sẽ gây CPB bị underflow như vùng màu xanh, ảnh tiếp theo không kịp đến là cho quá trình play video bị giật. Ngược lại nếu ảnh quá nhỏ thì sẽ gây CPB overflow dễ gây mất dữ liệu đầu vào.

hrd1

Để xử lý vấn đề này thì ở encoder luôn có mô hình giả lập để đảm bảo size các ảnh luôn ở phạm vi cho phép mà không xẩy ra tình trạng trên. Đây cũng là một việc của rate control.

5. TM5 (test model 5).
Về phương pháp rate control cho đến H.264 có thể tham khảo tài liệu [1], viết rất đầy đủ và chi tiết (tuy tác giả là của các chú Tàu khựa, nhưng mình nghĩ a/e nên đọc kỹ).
TM5 là chiến lược rate control cho MPEG2-Video, được giới thiệu vào 1993, tức là cách đây 25 năm. Đến hôm nay thì vẫn có công ty sừng sỏ về video của Nhật Bản vẫn dùng cho H.264, H.265 tất nhiên kèm sau sự chỉnh sửa đang kể.
Tham khảo [3] để biết chi tiết hơn về phương pháp này.

6.Tài liệu tham khảo.
[1]https://www.intechopen.com/books/recent-advances-on-video-coding/rate-control-in-video-coding
[2]THE H.264 ADVANCED VIDEO COMPRESSION STANDARD Second Edition, Iain E.Richardson
[3]http://www.mpeg.org/MPEG/MSSG/tm5/Ch10/Ch10.html