Prvi dio:
Što? Video kodek je dio softvera/hardvera koji komprimira i/ili dekomprimira digitalni video.
Zašto? Imajući u vidu određena ograničenja vezana za propusnost i
kapacitet pohrane, tržište zahtijeva sve kvalitetniji video. Sjećate se, kako smo u prošlom postu izračunali minimalne zahtjeve za 30 sličica u sekundi, 24 bita po pikselu, sa rezolucijom 480×240? Dobili smo 82,944 Mbit/s bez kompresije. Kompresija je za sada jedini način za prijenos HD/FullHD/4K sadržaja na televizijske ekrane i Internet. Kako se to postiže? Sada ćemo ukratko obraditi osnovne metode.
Prevod je napravljen uz podršku kompanije EDISON Software.Bavimo se , kao i .
Kodek vs Kontejner
Uobičajena greška početnika je brkanje kodeka digitalnog videa i kontejnera digitalnog videa. Kontejner je određeni format. Omotnica koja sadrži metapodatke videa (i, možda, zvuka). Smanjeni video može se smatrati korisnim teretom kontejnera.
Obično ekstenzija video datoteke ukazuje na njen tip kontejnera. Na primjer, datoteka video.mp4 će vjerojatno biti kontejner MPEG-4 Part 14, dok je datoteka nazvana video.mkv, najvjerojatnije . Da biste bili potpuno sigurni u kodek i format kontejnera, možete koristiti ili .
Malo povijesti
Prije nego što pređemo na Kako?, hajde da malo zaronimo u povijest, kako bismo bolje razumjeli neke stare kodeke.
Video kodek H.261 pojavio se 1990. godine (tehnički — 1988) i osmišljen je za rad sa brzinom prijenosa od 64 Kbit/s. U njemu su već korištene ideje, kao što su subuzorkovanje boja, makroblokovi i slično. Godine 1995. objavljen je standard video kodeka H.263, koji se razvijao do 2001. godine.
Godine 2003. završena je prva verzija H.264/AVC. Iste godine, kompanija „TrueMotion“ je objavila svoj besplatni video kodek, koji komprimira video s gubicima pod nazivom VP3. Godine 2008. Google je kupio tu kompaniju, objavivši VP8 iste godine. U decembru 2012. godine Google je objavio VP9, i podržava se na otprilike ¾ tržišta browsera (uključujući mobilne uređaje).
AV1 — je novi besplatni video kodek s otvorenim kodom, razvijen Savezom za otvorene medije (AOMedia), u kojem sudjeluju poznate tvrtke kao što su: Google, Mozilla, Microsoft, Amazon, Netflix, AMD, ARM, NVidia, Intel i Cisco. Prva verzija kodeka 0.1.0 objavljena je 7. travnja 2016. godine.
Rođenje AV1
Početkom 2015. godine Google je radio na VP10, Xiph (koji pripada Mozilli) radio je na Daala, a Cisco je napravio svoj besplatni video kodek pod nazivom Thor.
Zatim MPEG LA najprije je objavila godišnje limite za HEVC (H.265) i naknadu koja je 8 puta veća nego za H.264, ali ubrzo su ponovno promijenili pravila:
bez godišnjeg limita,
naknada za sadržaj (0,5% prihoda) i
naknada po jedinici proizvoda otprilike 10 puta veća nego za H.264.
Savez za otvorene medije osnovale su tvrtke iz različitih sektora: proizvođači opreme (Intel, AMD, ARM, Nvidia, Cisco), dobavljači sadržaja (Google, Netflix, Amazon), kreatori preglednika (Google, Mozilla) i drugi.
Tvrtke su imale zajednički cilj — video kodek bez licencnih naknada. Zatim se pojavila AV1 s mnogo jednostavnijom patentnom licencom. Timothy B. Terriberry održao je izvanrednu prezentaciju koja je postala izvor trenutne konceptualizacije AV1 i njenog modela licenciranja.
Bit ćete iznenađeni kada saznate da se AV1 kodek može analizirati putem preglednika (zainteresirani mogu posjetiti).

Univerzalni kodek
Razmotrit ćemo osnovne mehanizme koji čine temelj univerzalnog video kodeka. Većina ovih koncepcija je korisna i koristi se u modernim kodecima, poput VP9, AV1 i HEVC. Upozoravam da će mnoge objašnjene stvari biti pojednostavljene. Ponekad će se koristiti stvarni primjeri (poput H.264) za demonstraciju tehnologija.
1. korak — razdvajanje slike
Prvi korak je podjela okvira na nekoliko dijelova, poddijelova i dalje.

Zašto? Ima mnogo razloga. Kada razdvajamo sliku, možemo preciznije prognozirati vektor kretanja, koristeći male dijelove za male pokretne dijelove. Dok za statičku pozadinu možemo se ograničiti i na veće dijelove.
Codec obično organiziraju ove sekcije u segmentima (ili fragmentima), makroblokovima (ili blokovima kodiranja) i brojnim podsekcijama. Maksimalna veličina ovih sekcija varira, HEVC postavlja 64×64, dok AVC koristi 16×16, a podsekcije se mogu razbiti do veličina 4×4.
Sjećate se vrsta kadrova iz prošlog članka?! To se može primijeniti i na blokove, pa tako možemo imati I-fragment, B-blok, P-makroblok itd.
Za one koji žele vježbati — pogledajte kako će se slika razbiti na sekcije i podsekcije. Za to možete koristiti već spomenutu u prošlom članku. (onaj koji je plaćen, ali s besplatnom probnom verzijom koja ima ograničenje na prvih 10 kadrova). Ovdje su analizirane sekcije. VP9:

2. korak — predviđanje
Čim imamo sekcije, možemo sastavljati astrofizikalne prognoze o njima. Za INTER-predviđanje potrebno je prenijeti vektore kretanja i ostatak, a za INTRA-predviđanje prenosi se smjer predviđanja i ostatak.
3. korak — transformacija
Nakon što dobijemo ostatni blok (predviđena sekcija → stvarna sekcija), moguće ga je transformirati na način da znamo koje piksele možemo odbaciti, a da pritom zadržimo ukupnu kvalitetu. Postoje neka pretvaranja koja osiguravaju točno ponašanje.
Iako postoje i druge metode, razmotrit ćemo detaljnije diskretnu kosinusnu transformaciju (DCT — od diskretne kosinusne transformacije). Glavne funkcije DCT-a:
- Transformira blokove piksela u jednake blokove frekvencijskih koeficijenata.
- Kompresira energiju, pomažući u eliminaciji prostorne redundancije.
- Osigurava povratnost.
2. veljače 2017. godine, Cintra R.J. i Bayer F.M. objavili su članak o DCT-sličnim transformacijama za kompresiju slika, koji zahtijevaju samo 14 dodataka.
Ne brinite ako niste razumjeli prednosti svake točke. Sada ćemo se na konkretnim primjerima uvjeriti u njihovu stvarnu vrijednost.
Uzmimo taj blok piksela 8×8:

Ovaj blok se prikazuje kao sljedeća slika 8 na 8 piksela:

Primijenimo DCT na ovaj blok piksela i dobijamo blok koeficijenata veličine 8×8:

I ako prikažemo ovaj blok koeficijenata, dobit ćemo takvu sliku:

Kao što vidimo, ovo ne izgleda poput izvorne slike. Primijetimo da se prvi koeficijent značajno razlikuje od svih ostalih. Ovaj prvi koeficijent poznat je kao DC-koeficijent, koji predstavlja sve uzorke u ulaznom nizu, nešto poput aritmetičke sredine.
Ovaj blok koeficijenata ima zanimljivu osobinu: odvaja visokofrekventne komponente od niskofrekventnih.

Većina snage u slici koncentrirana je na nižim frekvencijama, stoga, ako se slika transformira u njene frekvencijske komponente i odbace više frekvencijski koeficijenti, može se smanjiti količina podataka potrebna za opisivanje slike, a da se pritom ne žrtvuje previše kvalitete slike.
Frekvencija označava koliko brzo se signal mijenja.
Pokušajmo primijeniti znanje stečeno u testnoj verziji, pretvarajući izvorni slikovni niz u njegovu frekvenciju (blok koeficijenata), koristeći DCT, a zatim odbacujući dio najmanje važnih koeficijenata.
Prvo ćemo ga pretvoriti u frekvencijsku domenu.

Zatim odbacujemo dio (67%) koeficijenata, većinom donji desni dio.

Na kraju, obnavljamo sliku iz ovog odbacenog bloka koeficijenata (zapamtite, to mora biti obrnuto) i uspoređujemo s originalom.

Vidimo da podsjeća na izvorni prikaz, ali ima mnogo razlika od originala. Odbacili smo 67,1875% i opet dobili nešto što podsjeća na izvor. Moglo se promišljenije odbaciti koeficijente kako bismo dobili sliku još bolje kvalitete, ali to je već sljedeća tema.
Svaki koeficijent formira se korištenjem svih pikselâ.
Važno: svaki koeficijent ne prikazuje izravno jedan piksel, već predstavlja ponderiranu sumu svih pikselâ. Ovaj nevjerojatan graf pokazuje kako se izračunava prvi i drugi koeficijent koristeći težine jedinstvene za svaki indeks.
Također možete pokušati vizualizirati DCT, gledajući jednostavnu formaciju slike na toj osnovi. Na primjer, ovdje je simbol A, formiran korištenjem svake težine koeficijenta:
4. korak — kvantizacija
Nakon što na prethodnom koraku eliminiramo neke koeficijente, na posljednjem koraku (transformacija) provodimo posebnu formu kvantizacije. U ovoj fazi je prihvatljivo izgubiti informacije. Ili, jednostavnim riječima, kvantizirat ćemo koeficijente kako bismo postigli kompresiju.
Kako možemo kvantizirati blok koeficijenata? Jedna od najjednostavnijih metoda bit će ravnomjerna kvantizacija, kada uzmemo blok, podijelimo ga s jednom vrijednošću (s 10) i zaokružimo rezultat.

Možemo li obrnuti ovaj blok koeficijenata? Da, možemo, pomnoživanjem istom vrijednošću s kojom smo dijelili.

Ovaj pristup nije najbolji, jer ne uzima u obzir važnost svakog koeficijenta. Mogli bismo koristiti matricu kvantizatora umjesto jedne vrijednosti, a ta matrica može iskoristiti svojstvo DCT, kvantizirajući većinu donjih desnih i manji dio gornjih lijevih.
Korak 5 — kodiranje entropije
Nakon što smo kvantizirali podatke (blokove slika, fragmente, okvire), još uvijek ih možemo komprimirati bez gubitaka. Postoji mnogo algoritamskih načina za kompresiju podataka. Kratko ćemo se upoznati s nekima od njih, a za dublje razumijevanje možete pročitati knjigu „Razumijevanje kompresije: kompresija podataka za moderne programere“ (»).
Kodiranje videa pomoću VLC-a
Pretpostavimo da imamo tok simbola: a, e, r i t. Vjerojatnost (u rasponu od 0 do 1) kako često se svaki simbol pojavljuje u toku prikazana je u ovoj tablici.
| a | e | r | t | |
|---|---|---|---|---|
| Vjerojatnost | 0,3 | 0,3 | 0,2 | 0,2 |
Možemo dodijeliti jedinstvene binarne kodove (poželjno male) najvjerojatnijim, a veće kodove — manje vjerojatnim.
| a | e | r | t | |
|---|---|---|---|---|
| Vjerojatnost | 0,3 | 0,3 | 0,2 | 0,2 |
| Binarni kod | 0 | 10 | 110 | 1110 |
Kompresiramo tok, pretpostavljajući da ćemo na kraju potrošiti 8 bita po simbolu. Bez kompresije, potreban bi bio 24 bita po simbolu. Ako svaki simbol zamijenimo s njegovim kodom, dolazimo do uštede!
Prvi korak je kodiranje simbola e, koji iznosi 10, a drugi simbol je a, koji se dodaje (ne matematičkim putem): [10] [0], i konačno, treći simbol t, koji čini naš konačni kompresirani bitni tok jednako [10] [0] [1110] ili 1001110, za što je potrebno samo 7 bitova (3,4 puta manje prostora nego u originalu).
Imajte na umu da svaki kod mora biti jedinstveni kod s prefiksom. pomoći će pronaći te brojke. Iako ova metoda nije bez mana, postoje video kodeci koji i dalje nude ovaj algoritamski pristup kompresiji.
I kodirator i dekodator moraju imati pristup tablici likova sa svojim binarnim kodovima. Stoga je također potrebno poslati ulazne podatke zajedno s tablicom.
Aritmetičko kodiranje
Pretpostavimo da imamo tok simbola: a, e, r, s i t, a njihova vjerojatnost prikazana je ovom tablicom.
| a | e | r | s | t | |
|---|---|---|---|---|---|
| Vjerojatnost | 0,3 | 0,3 | 0,15 | 0,05 | 0,2 |
S ovom tablicom ćemo izgraditi opsege koji sadrže sve moguće likove, sortirane prema najvećem broju.

Sada ćemo kodirati slijed od tri lika: eat.
Prvo odabiremo prvi lik e, koji se nalazi u podopsegu od 0,3 do 0,6 (ne uključujući). Uzimamo taj podopseg i ponovno ga dijelimo u istim omjerima kao prije, ali već za ovaj novi opseg.

Nastavimo kodirati naš slijed eat. Sada uzimamo drugi lik a, koji se nalazi u novom podopsegu od 0,3 do 0,39, a zatim uzimamo naš posljednji lik t i, ponavljajući isti proces ponovno, dobivamo posljednji podopseg od 0,354 do 0,372.

Jednostavno trebamo odabrati broj u posljednjem podopsegu od 0,354 do 0,372. Odaberimo 0,36 (ali možemo izabrati i bilo koji drugi broj u ovom podopsegu). Samo s ovim brojem možemo obnoviti naš izvorni slijed. To je kao da bismo crtali liniju unutar opsega za kodiranje našeg slijeda.

Obratna operacija (odnosno dekodiranje) je također jednostavna: s našim brojem 0,36 i našim izvorim opsegom možemo pokrenuti isti proces. Ali sada, koristeći ovaj broj, otkrivamo slijed, kodiran pomoću ovog broja.
S prvim opsegom primjećujemo da naš broj odgovara presjeku, stoga je to naš prvi lik. Sada ponovno dijelimo ovaj podopseg, provodeći isti proces kao i ranije. Ovde možemo primijetiti da 0,36 odgovara liku a, a nakon ponavljanja procesa došli smo do posljednjeg lika t (formirajući naš izvorni kodirani slijed eat).
I za kodiratora i za dekodatora potrebna je tablica vjerojatnosti likova, stoga je potrebno u ulaznim podacima poslati i nju.
Prilično elegantno, zar ne? Osoba koja je smislila ovo rješenje bila je doista pametna. Neki video kodeci koriste ovu tehniku (ili barem nude kao opciju).
Ideja je da se bez gubitaka komprimira kvantizirani bitstream. Vjerojatno u ovom članku nedostaju mnoge pojedinosti, uzroci, kompromisi itd. No vi, ako ste programer, trebate znati više. Novi kodeci pokušavaju koristiti različite algoritme entropijskog kodiranja, kao što su ANS.
6. korak — format bitstreama
Nakon što ste sve to napravili, preostaje raspakirati komprimirane okvire u kontekstu izvršenih koraka. Potrebno je izričito obavijestiti dekoder o odlukama koje je donio kodera. Dekoderu treba pružiti sve potrebne informacije: dubina bita, prostor boja, razlučivost, informacije o predikcijama (vektori kretanja, usmjereno INTER-predikcija), profil, razina, brzina kadra, tip kadra, broj kadra i mnogo toga drugog.
Površno ćemo pregledati bitstream H.264. Naš prvi korak će biti stvaranje minimalnog H.264 bitstreama (FFmpeg po defaultu dodaje sve parametre kodiranja, kao što su SEI NAL — malo dalje ćemo saznati što to znači). To možemo učiniti koristeći naš vlastiti repozitorij i FFmpeg.
./s/ffmpeg -i /files/i/minimal.png -pix_fmt yuv420p /files/v/minimal_yuv420.h264
Ova komanda će generirati neobrađeni bitstream H.264 s jednim okvirom, razlučivosti 64×64, s prostorom boja YUV420. Pri tome se koristi sljedeća slika kao okvir.

H.264 bitstream
Standard AVC (H.264) određuje da će informacije biti slane u makrookvirima (u smislu mreže), nazvanim NAL (to je razina apstrakcije u mreži). Glavna svrha NAL-a je pružanje „mreži prijateljskog“ prikaza videa. Ovaj standard bi trebao raditi na televizorima (na temelju streamova), na internetu (na temelju paketa).
![]()
Postoji marker sinkronizacije koji određuje granice NAL elemenata. Svaki marker sinkronizacije sadrži vrijednost 0x00 0x00 0x01, osim prvog, koji je jednak 0x00 0x00 0x00 0x01. Ako pokrenemo hexdump za generirani H.264 bitstream, identificirat ćemo najmanje tri NAL uzorka na početku datoteke.

Kao što je rečeno, dekoder treba znati ne samo podatke o slici, već i detalje o videu, okviru, boji, korištenim parametrima i mnogo više. Prvi bajt svakog NAL-a određuje njegovu kategoriju i tip.
| Identifikator tipa NAL | Opis |
|---|---|
| 0 | Nepoznat tip |
| 1 | Kodirani fragment slike bez IDR |
| 2 | Kodirani deo podataka isječka A |
| 3 | Kodirani deo podataka isječka B |
| 4 | Kodirani deo podataka isječka C |
| 5 | Kodirani IDR-fragment IDR-slike |
| 6 | Dodatne informacije o SEI ekstenziji |
| 7 | Set parametara SPS sekvence |
| 8 | Set parametara PPS slike |
| 9 | Separator za pristup |
| 10 | Kraj sekvence |
| 11 | Kraj toka |
| … | … |
Obično je prvi NAL bitstreama SPS. Ova vrsta NAL-a odgovara za informisanje o opštim varijablama kodiranja, kao što su profil, nivo, razlučivost i drugo.
Ako propustimo prvu sinhronizacijsku oznaku, možemo dekodirati prvi bajt da bismo saznali koji tip NAL je prvi.
Na primer, prvi bajt nakon sinhronizacijske oznake je 01100111, gde je prvi bit (0) u polju forbidden_zero_bit. Sledeća 2 bita (11) nam govori o polju nal_ref_idc, koje ukazuje da li je ovaj NAL referentno polje ili ne. I ostalih 5 bita (00111) nam govori o polju nal_unit_type, u ovom slučaju je to SPS blok (7) NAL.
Drugi bajt (binarni=01100100, heks=0x64, dec=100) u SPS NAL-u je polje profile_idc, koje pokazuje profil koji je koristio kodera. U ovom slučaju korišćen je ograničeni visok profil (tj. visok profil bez podrške za dvosmerni B-segment).

Ako se upoznamo sa specifikacijom bitstreama H.264 za SPS NAL, otkrićemo mnogo vrednosti za ime parametra, kategoriju i opis. Na primer, hajde da pogledamo polja pic_width_in_mbs_minus_1 i pic_height_in_map_units_minus_1.
| Ime parametra | Kategorija | Opis |
|---|---|---|
| pic_width_in_mbs_minus_1 | 0 | ue(v) |
| pic_height_in_map_units_minus_1 | 0 | ue(v) |
Ako uradimo neke matematičke operacije sa vrednostima ovih polja, dobićemo razlučivost. Možemo predstaviti 1920 x 1080 koristeći pic_width_in_mbs_minus_1 sa vrednošću 119 ((119 + 1) * macroblock_size = 120 * 16 = 1920). Ponovo, štedeći prostor, umesto kodiranja 1920, učinili smo to sa 119.
Ako nastavimo proveru našeg kreiranog videa u binarnom obliku (na primer: xxd -b -c 11 v/minimal_yuv420.h264), tada možemo preći na poslednji NAL, koji je sam okvir.

Ovde vidimo njegovih prvih 6 bajtnih vrednosti: 01100101 10001000 10000100 00000000 00100001 11111111. Pošto je poznato da prvi bajt ukazuje na tip NAL, u ovom slučaju (00101) to je IDR fragment (5), i tada ćemo dodatno istražiti:

Koristeći informacije iz specifikacije, možemo dekodirati tip fragmenta (slice_type) i broj okvira (frame_num) među drugim važnim poljima.
Da bismo dobili vrednosti nekih polja (ue(v), me(v), se(v) ili te(v), potrebno je dekodirati fragment, koristeći specijalni dekoder, zasnovan na . Ova metoda je vrlo učinkovita za kodiranje vrijednosti varijabli, posebno kada postoji mnogo unaprijed definiranih vrijednosti.
Vrijednosti slice_type i frame_num ovog videa su 7 (I-fragment) i 0 (prvi kadar).
Bitstream se može smatrati protokolom. Ako želite saznati više o bitstreamu, trebate pogledati specifikaciju ITU H.264. Ovo je makroshema koja pokazuje gdje se nalaze podaci o slici (YUV u komprimiranom obliku).

Možete istraživati i druge bitstreamove, kao što su VP9, H.265 (HEVC) ili čak naš novi najbolji bitstream AV1. Jesu li svi slični? Ne, ali jednom kada savladate barem jedan, mnogo lakše ćete razumjeti ostale.
Želite li vježbati? Istražite H.264 bitstream
Možete generirati jedno-ključni video i koristiti MediaInfo za istraživanje bitstreama H.264. U stvari, ništa vas ne sprječava da pogledate i izvorni kod koji analizira bitstream H.264 (AVC).
Za vježbu možete koristiti Intel Video Pro Analyzer (već sam spomenuo da je program plaćen, ali postoji besplatna probna verzija koja ima ograničenje na 10 okvira?).
Pregled
Važno je napomenuti da mnogi moderni kodeci koriste isti model koji smo upravo proučili. Hajde da pogledamo dijagram videokodeka. Thor. On sadrži sve korake koje smo prošli. Cjelokupna svrha ove bilješke je da najmanje bolje razumijete inovacije i dokumentaciju iz ovog područja.

Ranije smo izračunali da će biti potrebno 139 GB prostora na disku za pohranu video datoteke dužine jedan sat pri kvaliteti od 720p i 30 fps. Ako se koriste metode razrađene u ovom članku (predikcije između okvira i unutar okvira, transformacija, kvantizacija, entropijsko kodiranje itd.), moguće je postići (uz pretpostavku da trošimo 0,031 bit po pikselu) video zadovoljavajuće kvalitete koji zauzima samo 367,82 MB, a ne 139 GB memorije.
Kako H.265 postiže bolji stupanj kompresije nego H.264?
Sada kada znate više o radu kodeka, lakše je razumjeti kako novi kodeci mogu osigurati veću razlučivost s manjim brojem bitova.
Kada se uspoređuju AVC i HEVC, ne zaboravite da je gotovo uvijek riječ o izboru između većeg opterećenja za CPU i stupnjem kompresije.
HEVC ima više opcija za dijelove (i poddijelove) nego AVC, više pravaca unutarnjeg predviđanja, poboljšano entropijsko kodiranje i još mnogo toga. Sva ta poboljšanja učinila su H.265 sposobnim da kompresira 50% više nego H.264.

Prvi dio:
Izvor: habr.com




