Trình biên dịch

Làm phần mềm ít ai không biết đến cái gọi là trình biên dịch, tuy nhiên cũng đặc thù từng công việc mà mức độ hiểu biết về trình biên dịch có khác nhau.
Tôi làm về hệ thống nhúng (rất không muốn dùng từ này thay từ embedded trong tiếng Anh, nhưng cũng phải dùng cho đậm đà bản sắc dân tộc), là mảng công việc rất rất cần hiểu sâu sắc về trình biên dịch, nhưng đáng buồn là giờ tôi mới tìm hiểu, thôi thì chậm hơn là không.

Trong công việc phần mềm, thì trình biên dịch được hiểu ngắn gọn là phần mềm chuyển từ mã nguồn do lập trình viên viết ra, biến thành mã máy (trong trường hợp dotNET hay Java chắc phải hiểu khác chút).

Trình biên dịch thường là do các công ty phát triển môi trường phát triển (IDE) cho lập trình viên viết ra, nổi bật như Microsoft, với trường hợp này trình biên dịch tích hợp trong môi trường phát triển nên lập trình viên cũng không cần để ý quá nhiều. Bên cạnh đó các trình biên dịch mã nguồn mở cũng chả kém cạnh, mà đứng đầu là GCC.

Có thể tham khảo về các thể loại trình biện dịch trên Wiki, với trình biên dịch cho ngôn ngữ C thì chỗ này.

Trình biên dịch phải được phát triển rất cẩn thận, vì nếu trình biên dịch mà có lỗi thì ảnh hưởng rất lớn trong việc phát triển các phần mềm dùng trình biên dịch đó. Nếu xuất hiện tình huống lỗi phần mềm đang phát triển, mà nó lại do cái lỗi kia của trình biên dịch thì đúng là ác mộng. Tuy nhiên trên thực tế lỗi của trình biên dịch vẫn như sao trời mùa hạ, ví dụ danh sách lỗi dược báo cáo của GCC chẳng hạn, biết làm sao được nó cũng chỉ là phần mềm thôi mà. Cách đấy hơn 2 năm, tôi cũng đã từng ăn quả đắng khi trình biên dịch cho hệ thống firmware bị lỗi khi biên dịch phép tính 64bit, do không thể đợi lỗi này được xử lý ở trình biên dịch, mà phải đi vòng (workaround) bằng cách thay thế toàn bộ tính toán 64bit bằng một thư viện mới xử lý thông qua trình toán 32bit.

Công việc từ trước đến này tôi chỉ dùng GCC, ngoài việc hỗ trợ nhiều ngôn ngữ, nó còn hỗ trợ hầu hết các platform, thành ra tôi luôn nghĩ nó là “độc cô cầu bại” trong thế giới công việc nhúng. Nhưng ai có ngờ lời xưa đã chứng, đâu ra lại xuất hiện 1 thằng clang đã có chiều hướng đè bẹp GCC? Tôi chưa thử so sách xem chất lượng mã máy được biên dịch ra thế nào, còn về tốc độ biên dịch thì GCC hít khói. Nói về clang thì nó chỉ là mặt tiền (bước phân tích mã nguồn) của một thứ đang sợ hơn là LVMM, dự án này bắt đầu từ nghiên cứu của Chris Lattner. Cầu thủ này được Apple thuê hơn 10 năm, trong thời gian đó thì clang xuất hiện và thay thế GCC trong các môi trường phát triển của Apple. Sau khi không đá cho Apple nữa mà chuyển sang chơi ô tô với Elon Musk, nhưng chỉ đá được gần 6 tháng chắc thấy đá không vừa chân nên chuyển qua chơi AI với google.

Cưỡi ngựa xem hoa thế là đủ rồi, đã đến giờ “học đi đôi với hành”, để hiểu hơn về trình biên dịch thì cũng nên một lần trong đời thử viết 1 con compiler be bé xem nó ra cái gì. Để làm được cái “be bé” đó trước hết chắc phải đọc kỹ cái đống dưới.

BOOK.
[1] https://www.amazon.com/dp/0321486811/?tag=stackoverflow17-20
[2] https://www.amazon.com/dp/0471976970/?tag=stackoverflow17-20
[3] https://holub.com/goodies/compiler/compilerDesignInC.pdf

Other.
[1] https://www.quora.com/How-do-I-make-a-compiler-using-C-language
[2] https://holub.com/compiler/
[3] https://norasandler.com/2017/11/29/Write-a-Compiler.html
[4] http://scheme2006.cs.uchicago.edu/11-ghuloum.pdf
[5] https://softwareengineering.stackexchange.com/questions/165543/how-to-write-a-very-basic-compiler
[6] https://www.codeproject.com/articles/30353/designing-a-compiler

Câu chuyện từ khóa Volatile

Về từ khóa volatile thì có rất nhiều bài giải thích rồi, ví dụ như đây, đây đây nữa, tôi không muốn nhai đi nhai lại nhiều nữa.

Tuy nhiên vấn đề các tác giả đề cập đến thường là việc giá trị “biến thay đổi bất thường”, tôi không hiểu ý bất thường ở đây cụ thể là gì, bất thường đối với ai, nhưng có vẻ như là bất thường theo nghĩa trình biên dịch đọc code.
Để chắc bắp, nên tham khảo chính xác đặc tả C (or C++) xem nó nói gì, nhưng sờ vào đặc tả mới thấy nó không dễ đọc như tôi vẫn tưởng 😦

An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine, as described in 5.1.2.3.

Có thời gian nữa thì chắc nên nghiền ngẫm thêm chút vì thuật ngữ nghe là lạ, nhưng có thể tạm hiểu là từ khóa volatile để chỉ ra rằng biến đó có thể được thay đổi theo cách không rõ, không nhận biết được (mk, tiếng việt mình ngu quá, dài dòng vậy chứ có khi dùng từ “bất thường” là hợp lý nhất), cho nên việc tham chiếu biến đó phải tuyệt đối tuân thử đúng qui tắc máy :-o. Kết hợp thêm các ví dụ tham khảo thì tôi đang tạm hiểu ý là những chỗ đã liên quan đến từ khoá volatile thì phải tuyệt đối làm theo đúng từng mệnh lệnh mà mã nguồn đã được viết ra.
Dùng Google tìm kiếm thì có thể tóm tắt vài tình huống dưới, mà biến bị thay đổi một cách bất thường đối với trình biên dịch, làm cho nó không nhận thức được việc thay đổi đó.
– Trong chương trình có xử lý ngắt, vì xử lý ngắt tạo tình huống đặc biệt.
– Xử lý song song đa luồng, các luồng có sử dụng biến chung.
– Vùng nhớ sử dụng cho IO map.
Chính vì trình biên dịch không có khả năng (?) nhận thức, nhận biết được toàn bộ những thay đổi liên quan đến biến có mang từ khoá volatile, do đó nó phải tuân thủ từng dòng code chứ không được suy đoán, mà mục đích thường là để tối ưu khi biên dịch mã nguồn.
Tôi thì vẫn nghĩ chỉ có trường hợp 3 do trình biên dịch không thể đủ thông tin nên mới có thể làm sai khi tiến hành tối ưu code, chứ trường hợp interrupt hay xử lý đa luồng, thì rõ ràng mọi thứ trình biên dịch đều có thể nhận thức được, tôi không cho rằng cái đó là biến được thay đổi một cách bất thường. Tuy nhiên vì chưa có hiểu biết gì về cách tối ưu của trình biên dịch nên tôi cũng chỉ đưa ra nhận định chủ quan.

Sau khi đọc bài viết chỗ này, tôi đã thử 1 sampe code để test với gcc 6.3.0, dùng signal interrupt từ bàn phím, nhưng tối ưu hóa đủ mọi option vẫn không bị lỗi. Sau khi được tác giả gợi ý dùng fake interrupt bằng timer thì lại đúng là bị lỗi nếu không dùng volatile thật.
Dù sao chăng nữa thì tôi vẫn giữ quan điểm volatile chỉ cần trường hợp map IO do tác động thực sự từ yếu tố bên ngoài mà trình biên dịch có mắt cũng chả thấy được, à hoặc có thể một trường hợp là cố tình dump code theo ý người viết, mà thường thấy là tạo delay  cái này thường thấy khi lập trình cho vi điều khiển, do thư viện không hỗ trợ hàm delay, điều này cũng làm cho trình biên dịch phán đoán là đoán mã đó thừa và thực hiện tối ưu, do nó không hiểu “ngu ý” của người viết. Còn lại với những trường hợp mà bản thân trình biên dịch có đầy đủ thông tin nhưng vẫn biên dịch lỗi nếu không có volatile thì tôi nghĩ có khi phải xem xét lại bản thân trình biên dịch.

Tóm lại từ khóa volatile dùng để nói cho trình biên dịch đấy là vùng cấm, code thế nào thì hãy làm đúng như thế, mày mới chỉ biết 1 chứ chưa biết 2, phần mày đang biên dịch chỉ là 1 phần nhỏ trong hệ thống lớn, nên đừng có khôn lỏi vào chỗ đó, đừng dựa vào nhận định chủ quan mà tiến hành thay đổi code để thực hiện tối ưu.

Câu chuyện đến đây có lẽ là xong rồi, tuy nhiên có lẽ  ta dễ thấy có gì đó hơi không tự nhiên lắm, do nó chỉ bị lỗi khi yêu cầu trình biên dịch thực hiện tối ưu, vậy nếu trình biên dịch “ngây thơ” bảo gì làm nấy thì có lẽ là ta chẳng cần từ khóa volatile làm gì. Mà về tính năng tối ưu trong trình biên dịch thì tôi nghĩ nó chỉ phát triển sau này. Lúc xây dựng C không rõ trình biên dịch mà cụ Dennis Ritchie dùng có những tính năng gì (tôi không rõ ông làm thế nào để xây dựng ra C nên chỉ phán đoán thôi, nhưng dù sao chắc cũng phải vừa xây dựng đặc tả thì cũng phải song song xây dựng 1 trình biên dịch để kiểm thử).
Kiểm ra lại đặc cả ngôn ngữ C phiên bản đầu tiên thì chưa có thật, nó chỉ được thêm vào từ phiên bản số 2. Từ đó liệu ta có thể phán đoán là trong quá trình phát triển tính năng tối ưu code của trình biên dịch, nó lại yêu cầu ngược lại đặc tả phải thêm từ khóa volatile?

Như vậy “điều lệ” ban ra đã rõ ràng, tuy nhiên “chi bộ” Kernel Linux lại không tuân thủ, à cũng nói thêm là “chi bộ” này được “đồng chí” Tovard Linux thành lập từ 1990 (chú ý là “đồng chí” Ngô Thời Nhiệm không nằm trong chi bộ này). “chi bộ” này đã ra 1 “thông tư” nói không với volatile cơ bản có 2 điểm.
1. Trong mọi trường hợp trong kernel linux đều không thấy cần volatile.
2. Nếu cần thì đấy là BUG.
“Thông tư” đã viết rất rõ ràng nên ai muốn biết mời tham khảo. Tìm hiểu thêm về “chi bộ” này ta còn bắt gặp nhiều điểm bất thường khác nữa, phải chăng chính điều đó tạo nên đặc trưng cho Kernel Linux.

Tham khảo
http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html
http://publications.gbdirect.co.uk/c_book/

Con đường nào dẫn đến một ngày vui

– 2018/09/12
Sau lần đầu tiên chuyển công ty, công việc dường như vẫn không thay đổi nhiều lắm so với cách đây gần 2 năm. Cũng làm hẳn trong dự án với khách hàng, cũng là khách hàng đó luôn :-), tuy trước là mảng video coding còn giờ là 3D sensor, đúng là “mọi nẻo đường đều dẫn tới thành Rome”.

32 tuổi …
Thời điểm này, tôi đang làm ở VTI, một công ty outsource non trẻ, với quyết tâm cùng ông anh người quen xây dựng nhóm embedded software thật mạnh, có được sự tôn trọng từ khách hàng. Trước này toàn bị khách hàng nó miệt thị quen rồi.

Cơ mà, haizz…zz
Đôi lúc đọc page của top programmer, tôi lại tự hỏi không biết mình đang bỏ thời giờ ra làm cái gì thế này?

– 2018/09/16
Tôi rất thích xem phim đối kháng, khi mà chỉ cần 1 sơ suất đều phải trả giá rất đắt. Lúc lâm trận thì chỉ cần thua 1 tí, 1 kĩ năng nhỏ là phải trả giá bằng mạng sống. Nghĩ điều này giúp tôi nghiêm túc hơn để rèn luyện kỹ năng, cũng như cẩn thận hơn khi coding =))

– 2018/10/17
Công ty tôi đang làm cũng có 1 cái tech blog, viết blog kỹ thuật cho công ty là công việc luân phiên, tôi phụ trách nhóm embedded nên cũng sớm đến tay. Có vẻ ai nấy được giao đều cố trả bài cho xong. Tôi thì không ngại lắm, vì tôi copy từ đây ra =))
Cả tháng nay vật lộn với đống code của mấy thằng Bỉ, mk trước giờ toàn code C thuần là C, giờ nó chơi C++11, toàn thư viện lạ hoắc …
Cho đến giờ, tôi vẫn lười nhác nên có nghe C++11 cũng chả quan tâm, thấy mỗi C “cổ điển” theo đại ka Linus là đủ giải cứu thế giới rồi =)).
Nhưng ngẫm kỹ lại, có khi mình đang nghĩ ngu thật. Việc phát triển C++ vẫn chưa dừng, chắc là không bao giờ, ngừng vận động là ngỏm mà. Ghi lại cái link còn xem lý do tại sao nó không chịu dừng cho đỡ mệt.
https://isocpp.org/std/the-standard

À, trong lúc cao hứng nghe lại bài ngày đã đơm bông tôi đặt cái tiêu đề vậy, mà lỡ có tiêu đề rồi thì cũng cố gõ vài dòng mặc dù chả liên quan gì đến cái tiêu đề đã chọn 😀

Cảm biến 3D – TOF

Từ khi ipornX Iphone X của Apple được giới thiệu, cảm biến 3D trở thành 1 hot keyword, làm cho nhà nhà đua nhau tích hợp 3D vào điện thoại, người người thi nhau mua điện thoại có cảm biến 3D. Ông trùm SONY về mảng điện tử một thời của Nhật, mà hiện giờ mảng cảm biến đang mang lại một trong những nguồn sống chính, đã nhanh chân mở ví ra mua luôn Softkinetic, một startup của Bỉ với tầm 77 nhân sự vào 2015.
Tôi vô tình cũng bị cuốn vào xu thế đó khi tham gia dự án làm platform & driver cho con hợi này. Do đó vừa học vừa viết lại đôi điểm cho đỡ quên, nội dung rút ra từ tài liệu [1] ở phần tham khảo. Có thể học thêm về TOF ở kho tài liệu của Texas Instrument [2], rất phong phú và chi tiết.

Trong vấn đề xử lý hình ảnh, việc thu và tái hiện lại hình 3D không phải vấn đề gì mới, trước TOF đã có 2 phương pháp được sử dụng để tái tạo hình ảnh 3D.
Stereo Vision : Sử dụng 2 camera để tái hiện lại 3D, vị trí của 1 điểm sẽ được xác định nhờ vị trí tương đối của nó đối với 2 camera. Phương pháp này sử dụng tương tự hệ thống mắt người.
stereo-vision
Nguyên lý Stereo Vision (Ảnh lấy trong tài liệu[1])

Structured-light: Phương pháp này sử dụng 1 chùm tia sáng với mô hình xác định trước (dạng lưới, quét ngang …) , để chiếu lên vật thể cần quan sát, thu lại hình ảnh khi tia sáng đập lên bề mặt vật thể để xây dựng lại hình ảnh 3D của nó.
structure-ligh
Nguyên lý Structured-light  (Ảnh lấy trong tài liệu[1])
Vậy TOF là gì? TOF là viết tắt của Time Of Flight, dựa trên nguyên lý đo khoảng cách bằng sóng điện từ (sóng ánh sáng ở dải mắt người không nhìn thấy). Trong hệ thống TOF, sử dụng 1 nguồn phát sóng ánh sáng, quan sát nguồn phản hồi từ đối tượng quan sát, bằng cách đo thời gian từ lúc phát ra đến lúc phản hồi thì sẽ tính được vị trí của đối tượng đó.
tof
Nguyên lý TOF (Ảnh lấy trong tài liệu[1])
Dễ thấy nguyên lý của TOF giống hệt như dùng sóng siêu âm để đo độ sâu đáy biển, tất nhiên từ lý thuyết đến thực tiễn là 1 khoảng cách không nhỏ về thời gian cũng như tiền bạc.

Bảng dưới đây cho thấy hình ảnh tổng quan của TOF khi so sánh với 2 kỹ thuật còn lại. Công nghệ thay đổi chóng mặt chả khác gì “chó chạy ngoài đồng” , nên cần chú ý rằng thông tin trong bảng này chỉ đúng với tầm thời điểm hiện tại (~2018).
tof

So sánh TOF với Stereo Vision và Structured-light (Ảnh lấy trong tài liệu[1])

Tham khảo:
[1] http://www.ti.com/lit/wp/sloa190b/sloa190b.pdf
[2] http://www.ti.com/3dtof
[3] https://en.wikipedia.org/wiki/Structured_light
[4] https://en.wikipedia.org/wiki/Time-of-flight_camera
[5] https://en.wikipedia.org/wiki/Computer_stereo_vision

3 định luật XYZ

Sau khi được nhà quí tộc Brahe để lại 1 khối lượng dữ liệu quan sát thiên văn hơn 30 năm, thì Kepler đã hoàn thành thuyết nhật tâm một cách có hệ thống bằng 3 định luật chuyển động thiên thể và những năm 1609 – 1619, lúc đấy ở Đại Việt ta bắt đầu thời kì Trịnh – Nguyễn phân tranh nên chắc chả ai có thời gian đâu mà quan tâm đến thiên với chả thể.
Tuy là tìm ra 3 định luật, nhưng Kepler cũng không hiểu “vì sao lại thế, tại vì sao lại thế, các thiên thể không chuyển động thế này mà lại là thế kia”. Người trong giang hồ phải chờ đến xuất hiện một quái kiệt mới “để tìm ra ngọn ngành”, người mà khiêm tốn nhận mình trông xa hơn vì được đứng trên vai những người khổng lồ, Newton đã đưa ra 3 định luật cơ bản, hình thành nên cơ học cổ điển hay còn gọi là cơ học Newton, cùng với định luật vạn vật hấp dẫn, đã giải thích thấu đáo tại sao qui luật chuyển động thiên thể. Cơ học Newton đã thống trị mọi lĩnh vực của Vật lý học cho đến đầu thế kỉ 19, khi mà mọi ngành nghiên cứu từ chuyển động của phân tử, đến những đối tượng to vật vã như thiên thể, hành tình đều được xây dựng theo các định luật cơ bản của Newton, mà đưa ra nhiều dự đoán đúng. Mô hình vật lý học trở nên thống nhất, rất đẹp đẽ.
Nói đến ngành nghiên cứu về tập hợp các phân tử tuân theo chuyển động cơ học, hay còn gọi là nhiệt động lực học, cũng cho ra đời 3 định luật nhiệt động lực học, trong đó từ định luật số 2 định nghĩa ra một khái niệm mới là entropy, mà nó còn dùng để định nghĩa lượng thông tin trong lý thuyết thông tin.

Tưởng chừng như “con thuyền Vật lý học cấp bến bình yên” như huân tước Kelvin (nhiều tài liệu dẫn tuyên bố này của Kelvin, tuy nhiên thực tế hình như không có thông tin chính thống), thì “2 gợn mây nhỏ” đã nổi lên thành 2 cơn giông tố làm rung chuyển và thay đổi hẳn bộ mặt ngành Vật lý. Trong cơn giông lượng tử, ta lại bắt gặp 3 định luật quang điện

Con số 3 chưa dừng ở đó, ta lại tiếp tục gặp 3 định luật về di truyền Mendel khi học sinh học hình như tầm năm lớp 9.
Hôm nay vô tình biết đến tồn lại 3 định luật hơi bị hay của Arthur C.Clarke, người nổi tiếng về những dự đoán của ông trong các tác phẩm khoa học viễn tưởng đã dần dần thành hiện thực. Nguyên văn của nó như sau:
1. When a distinguished but elderly scientist states that something is possible, he is almost certainly right. When he states that something is impossible, he is very probably wrong.
2. The only way of discovering the limits of the possible is to venture a little way past them into the impossible.
3. Any sufficiently advanced technology is indistinguishable from magic.

Tạm dịch nó như sau:
1. Khi một bậc lão thành cho rằng một chuyện gì đó là có thể xảy ra được thì ông ta hầu như chắc chắn đúng. Song khi vị này bảo rằng chuyện gì đó là không thể được, thì phần chắc là ông ta sai.
2. Cách duy nhất để xác định biên giới của cái có thể là mạo hiểm vượt qua lằn ranh đó để đi về hướng cái không thể.
3. Bất kỳ công nghệ tiên tiến nào đều không khác gì phép thần thông.

P/S: Áp dụng định luật Clarke ở trên, ta dễ dàng thấy được tuyên bố sau của Steve Wozniak là sai, thật là một định luật thú vị 🙂
http://genk.vn/dong-sang-lap-apple-tri-tue-nhan-tao-se-khong-bao-gio-du-thong-minh-de-dieu-khien-mot-chiec-o-to-20181001104135133.chn

Biên dịch Linux OS từ mã nguồn

Bắt đầu đi làm vào giữa 2009, tôi bắt đầu được tiếp xúc với Linux, nhưng trải qua gần 9 năm từ đó đến nay, hiểu biết về Linux rất ổn định như tham nhũng, không có gì thay đổi. Lý do thứ nhất là vì các dự án làm với Linux chỉ là sử dụng môi trường Linux để phát triển, nên cơ bản chỉ biết cái Makefile là xong, chẳng lúc nào cần mó tay một cách chỉnh chu thấu đáo vào các thứ như device driver, hay memory management …, để biết cái gì đủ hay ho mà kể chuyện. Thật ra là có một chút nhưng không ăn thua, mấy thứ cơ bản như system call, char driver, block driver … thì nó phổ cập cmnr, với lại khoảng cách giữa biết tên và biết để kể chuyện được nó cũng quá xa. Lý do thứ 2 là lười & nhác tìm hiểu.

Đang ôn tập lại chút kiến thức để chuẩn bị do dự án làm driver trên Linux, thì bắt gặp trang dưới (ko hiểu sao giờ mới biết, chắc lại do nhác & lười).
http://linuxfromscratch.org/lfs

Trước giờ hay có sở thích, là thử distribution (Linux OS) của Linux, hết Ubuntu đến Backtrack, với mục đích rất đáng sợ là để học sâu thêm về Linux nhưng cài xong  chiêm ngưỡng cái desktop xong  rồi thì sau đó là chỉ để duyệt web ~.~

Việc hay thử Linux OS, nó cũng bắt nguồn từ hồi mới ra trường, được bố mẹ bán hết lúa gạo lợn gà cho mua con hp pavilion, không nhớ chính xác tên nhưng giá là 12 hay 17 chai gì đấy. Đen đủi thế nào lúc ra lúc bắt đầu đi làm 1 năm thì bị trộm nó thó mất, lương thấp ăn chưa đủ nói gì đến mua lại máy. May thay ông anh trong dự án có con T40 thinkpad hỏng main đang đắp chiếu, bảo cầm về sửa mà dùng. Sau thay main cũ hết 1 triệu, cài luôn ubuntu, có hơi rùa bò tí những nó vẫn dùng để kết nối tốt với internet. Vì rùa bò nên nghĩ ra việc dùng các bản Linux OS cho máy cấu hình thấp, nhưng rồi cũng thấy chẳng ăn thua lắm nên mới sinh ra trò thử cài Ubuntu xong gỡ hết gói màu mè về giao diện ra thì tốc độ có thấy cải thiện kha khá. Từ đó có thêm trò ngược đời là cài xong Linux OS thì gỡ bớt gói không cần thiết ra, đôi khi không biết nên gỡ quá tay làm nó chẳng start up luôn được cả giao diện =]]. Dùng được hơn 1 năm thì T40 cũng đi vì cái màn hình hỏng.

Đến 2011, đi công tác ở Nhật, nhịn ăn nên cũng mua được con CF-W5MW8AJR Panasonic đồ cũ cùi bắp, mua xong cài luôn Ubuntu đè lên con Win Vista bản quyền luôn.
Riêng con này từ lúc mua ngoài làm mất thứ vớ vẩn thì cũng kiếm đc chút từ việc
data hiding, do muốn mua con len Nikon 50mm f/1.8G, nhưng lương chỉ đủ nuôi con nên đành kiếm tí việc đánh thêm, đỡ phạm đến phần tiền mua sữa cho con 😦

Nói dài dòng, nhưng tóm lại giờ có con CF5 cùi bắp, tính  cho mấy thằng em ở quê, nhưng chắc là nó không thèm lấy, mà công nhận đồ của Panasonic rất chất, nhẹ, pin trâu vẫn duy trì hơn tầm 1.5h, phím bấm cực đã không bị rung, ai dùng dòng Let’s Note của Panasonic rồi thì biết, chỉ có điều giá trên trời. Như  đề cập ở trên, tự dưng biết 1 dự án rất có tâm, hướng dẫn biên dịch hẳn Linux OS từ source code (có khi google đủ các kiểu + bỏ thời gian ra chắc cũng tự build được), tóm lại từ Linux kernel, đến các gói mã nguồn GNU & non-GNU …

Dù là việc biên dịch chỉ là việc chân tay, nhưng trải nghiệm 1 lần biên dịch ra OS từ mã nguồn nó cũng hay hay, dù sao cũng tạo hứng thú vượt qua lười & nhác để có thể bắt đầu tìm hiểu thêm chút về Linux. Thêm vào đó hi vọng do tự điều chỉnh được các gói cần thiết nên sẽ có được con OS nhỏ gọn để chạy với cái đồ cùi bắp như CF-W5MW8AJR.

Có 1 điểm chú ý khi bắt đầu biên dịch là nên chuẩn bị 1 con USB stick hoặc CD live có thể chạy live Linux OS nào đó (ex: ubuntu), để phòng trường hợp lỗi khi chia ổ cứng này nọ thì còn có cách mà xử lý.
Về phần dữ liệu quan trọng trong máy thì theo tôi không cần phải backup, vì nếu bị lỗi thì có cơ hội học cách cứu dữ liệu, nếu cứu không được thì coi như cái giá phải trả để nhớ bài học hơn =]].

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.

● 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.

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 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