Első rész:
Mi? A videokodek a szoftver vagy hardver része, amely tömöríti és/vagy dekompresszálja a digitális videót.
Mire? Bár bizonyos korlátai vannak a sávszélesség és a tárolóhely szempontjából, a piac egyre magasabb minőségű videót igényel. Emlékszik, hogy a legutóbbi posztban megbecsültük a minimum szükséges feltételeket 30 képkocka másodpercenként, 24 bit per pixel és 480×240 felbontás mellett? Így 82,944 Mbit/s tömörítetlen formában. A tömörítés jelenleg az egyetlen módja annak, hogy HD/FulHD/4K-t közvetítsünk a televízió képernyőire és az internetre. Hogyan érjük ezt el? Most nézzük meg röviden a fő módszereket.
Foglalkozunk
A fordítást az EDISON Software támogatta.videómegfigyelő rendszerek integrálásával , valamint .
A kezdők gyakori hibája, hogy összekeverik a digitális videó kodekjét és a digitális videó konténerét. A konténer egy bizonyos formátum, amely tartalmazza a videó (és esetleg hang) metaadatait. A tömörített videót a konténer hasznos terheként is lehet kezelni.
Általában a videófájlok kiterjesztése utal az adott konténer típusára. Például a video.mp4 fájl valószínűleg az
MPEG-4 Part 14 , míg a video.mkv nevű fájl valószínűlegmatrioska Mielőtt áttérnénk a vagy .
Egy kis történelem
, nézzük meg egy kicsit a történelmet, hogy jobban értsük a régebbi kodekeket. Hogyan?H.261
Videókodek 1990-ben jelent meg (technikai értelemben 1988-ban), és 64 Kbit/s sebességű adatátvitelre készült. Már ekkor használták az olyan ötleteket, mint a szín alá mintázás, makroblokkok stb. 1995-ben publikálták a videokodek szabványt H.263 , amely 2001-ig fejlődött.2003-ra elkészült az első verziója
H.264/AVC . Ugyanebben az évben a "TrueMotion" kiadta ingyenes videokodekjét, amely a veszteséges tömörítést alkalmaztaVP3 . 2008-ban a Google megvásárolta ezt a céget, és kiadtaVP8 ugyanebben az évben. 2012 decemberében a Google kiadta , és ez körülbelül a böngészők ¾-én támogatott (mobil eszközök is beleértve). VP9ez egy új ingyenes, nyílt forráskódú videokodek, amelyet a
AV1 Nyílt Média Szövetség fejlesztett. (AOMedia), amelyek között olyan jól ismert cégek találhatók, mint: Google, Mozilla, Microsoft, Amazon, Netflix, AMD, ARM, NVidia, Intel és Cisco. Az 0.1.0 verziójú kodek első kiadása 2016. április 7-én történt.
Az AV1 születése
2015 elején a Google dolgozott a VP10, míg a Xiph (amely a Mozilla tulajdonában van) dolgozott a Daala, és a Cisco ingyenes videokódere, a Thor.
Ezután az MPEG LA először éves korlátokat hirdetett meg a HEVC (H.265) és a H.264-nél nyolcszor magasabb díjat, de hamarosan ismét megváltoztatták a szabályokat:
nincs éves korlát,
a tartalom díja (0,5% a bevételből) és
a termékegység díja körülbelül tízszer magasabb, mint a H.264 esetében.
Nyílt Média Szövetség különböző ágazatokból származó cégek által jött létre: hardvergyártók (Intel, AMD, ARM, Nvidia, Cisco), tartalomszolgáltatók (Google, Netflix, Amazon), böngészőfejlesztők (Google, Mozilla) és mások.
A cégek közös célja egy licencdíj nélküli videokodek létrehozása volt. Ezután megjelent AV1 egy sokkal egyszerűbb szabadalmi licenccel. Timothy B. Terryberry lenyűgöző bemutatót tartott, amely forrássá vált az AV1 jelenlegi koncepciója és licencmodellje számára.
Meg fog lepődni, hogy az AV1 kodekeket böngészőn keresztül elemezhetjük (az érdeklődők a címre léphetnek:).

Univerzális kodek
Megvizsgáljuk az univerzális videokodek alapvető mechanizmusait. Ezek közül a koncepciók közül sok hasznos és a modern kodekekben is használják, mint például VP9, AV1 és HEVC. Figyelmeztetem, hogy sok mindent leegyszerűsítünk. Néha valós példákat is használunk (mint a H.264 esetében) a technológiák bemutatására.
1. lépés - a kép felbontása
Az első lépés az, hogy a keretet több részre, részletesebb részekre és további alsó részekre bontjuk.

Miért? Számos oka van. Amikor felbontjuk a képet, pontosabban meg tudjuk jósolni a mozgásvektorokat, kis részeket használva a kis mozgó részekhez. Míg a statikus háttérhez nagyobb részek is elegendők lehetnek.
A kodekek ezeket a részeket általában szekciókba (vagy darabokba), makroblokkokba (vagy kódolási fákba) és számos alsó részbe szervezik. A részek maximális mérete változó, az HEVC 64×64-et állít be, míg az AVC 16×16-ot használ, és az alsó részek akár 4×4-es méretűre is felbontódhatnak.
Emlékeznek a keretek különböző típusaira az előző cikkből?! Ezt a blokkokra is alkalmazhatjuk, így lehetnek I-fragmentum, B-blokk, P-makróblokk stb.
Aki szeretne gyakorolni – nézze meg, hogyan oszlik fel a kép részekre és alrészekre. Ehhez használhatja az előző cikkben már említett (a fizetős, de ingyenes próbaverzióval, amely az első 10 keretre korlátozódik). Itt az áttekintésről van szó VP9:

2. lépés – előrejelzés
Amint megvannak a részek, el tudunk készíteni asztrológiai előrejelzéseket azokon. Ehhez az INTER-előrejelzéshez át kell adni a mozgásvektorokat és a maradékot, az INTRA-előrejelzéshez pedig a az előrejelzés irányát és a maradékot kell átadni.
3. lépés – átalakítás
Miután megkaptuk a maradékblokkot (előrejelzett rész → valós rész), lehetőség van annak átalakítására, hogy tudjuk, mely pixelek dobhatók el, miközben megtartjuk a teljes minőséget. Vannak bizonyos átalakítások, amelyek pontos viselkedést biztosítanak.
Bár vannak más módszerek is, vizsgáljuk meg részletesebben a diszkrét koszinusz transzformációt (DCT jelenti — a discrete cosine transform). A DCT fő funkciói:
- A pixelblokkokat azonos méretű frekvencia-koefficiens blokkokká alakítja.
- Sűríti a teljesítményt, segítve a térbeli redundancia megszüntetését.
- Biztosítja a visszafordíthatóságot.
2017. február 2-án Cintra R.J. és Bayer F.M. publikált egy cikket a DCT-szerű átalakításról a képek tömörítésével kapcsolatban, amely csak 14 kiegészítést igényel.
Ne aggódjon, ha nem értette meg az egyes pontok előnyeit. Most konkrét példákon fogjuk bemutatni azok valódi értékét.
Nézzük ezt a 8×8-as pixelblokkot:

Ez a blokk a következő 8x8 pixeles képet rendereli:

Alkalmazzuk a DCT-t erre a pixelblokkra, és kapunk egy 8×8-as koefficiensekből álló blokkot:

És ha ezt a koefficiensekből álló blokkot rendereljük, ilyen képet kapunk:

Ahogy látjuk, nincs hasonlóság az eredeti képhez. Megfigyelhető, hogy az első koefficiens jelentősen eltér az összes többitől. Ez az első koefficiens DC-koefficiensként ismert, amely az összes mintát reprezentálja a bemeneti tömbben, valami olyasmi, mint az átlagérték.
Ennek a koefficiensblokknak van egy érdekes tulajdonsága: elkülöníti a magas frekvenciájú komponenseket az alacsony frekvenciájúaktól.

A képen a teljesítmény nagy része alacsonyabb frekvenciákra összpontosul, ezért ha a képet átkonvertáljuk a frekvenciakomponenseire, és elvetjük a magasabb frekvenciájú koefficienseket, csökkenthetjük a kép leírásához szükséges adatokat, anélkül, hogy túl sokat áldoznánk a kép minőségéből.
A frekvencia azt jelenti, hogy a jel milyen gyorsan változik.
Próbáljuk meg alkalmazni a tesztpéldából szerzett tudást, átkonvertálva az eredeti képet a frekvenciájába (koefficiensblokk), DCT segítségével, majd elvetve a legkevésbé fontos koefficiensek egy részét.
Először konvertáljuk át a frekvenciaterületre.

Ezután elvetünk egy részt (67%) a koefficiensekből, főleg az alsó jobb részt.

Végül helyreállítjuk a képet az elvetett koefficiensblokkból (ne feledje, hogy ennek visszafordíthatónak kell lennie), és összehasonlítjuk az eredetivel.

Látjuk, hogy hasonlít az eredeti képre, de sok különbség van az eredetihez képest. 67,1875%-ot dobtunk el, és mégis kaptunk valamit, ami emlékeztet az eredeti forrásra. Jobban megfontolva is el lehetett volna vetni a koefficienseket, hogy jobb minőségű képet kapjunk, de ez már a következő téma.
Minden koefficiens az összes pixel felhasználásával képződik.
Fontos: minden koefficiens közvetlenül nem egy pixelre vonatkozik, hanem az összes pixel súlyozott összegét képviseli. Ez a lenyűgöző gráf mutatja be, hogyan számítják ki az első és második koefficienst egyedi súlyok felhasználásával minden indexhez.
Megpróbálhatja a DCT-t vizualizálni azáltal, hogy megnézi, hogyan képződik egy egyszerű kép az alapján. Például itt van az A betű, amelyet minden koefficiens súlyának felhasználásával képzünk:
4. lépés – kvantálás
Miután az előző lépésben elvetettük néhány koefficienst, az utolsó lépésben (átszámítás) egy különleges kvantálási formát végzünk. Ezen a ponton elfogadható az információ elvesztése. Vagy egyszerűbben fogalmazva, kvantálni fogjuk a koefficienseket a tömörítés érdekében.
Hogyan lehet kvantálni a koefficiens blokkot? Az egyik legegyszerűbb módszer a lineáris kvantálás, amikor a blokkot elosztjuk egy értékkel (10-zel), és lekerekítjük az eredményt.

Visszafordíthatjuk ezt a koefficiens blokkot? Igen, visszafordíthatjuk, ha ugyanazzal az értékkel szorozzuk meg, amellyel osztottunk.

Ez a megközelítés nem a legjobb, mivel nem veszi figyelembe az egyes koeffiensek fontosságát. Használhatnánk kvantáló mátrixot egyetlen érték helyett, és ez a mátrix kihasználhatja a DCT tulajdonságát, kvantálva a legtöbb alsó jobb és a legkevésbé az alsó bal koefficiens.
5. lépés - entrópia kódolás
Miután kvantáltuk az adatokat (képbólkok, töredékek, keretek), továbbra is tömöríthetjük őket veszteségmentesen. Számos algoritmikus módszer létezik az adatok tömörítésére. Röviden megismerkedünk néhány ilyen módszerrel, a mélyebb megértés érdekében olvassa el a "A tömörítés megértése: Adattömörítés modern fejlesztőknek" című könyvet.»).
Videó kódolás VLC-vel
Tegyük fel, hogy van egy szimbólumáramunk: a, e, r és t. Az egyes szimbólumok előfordulásának valószínűsége (0 és 1 között) az alábbi táblázatban látható.
| a | e | r | t | |
|---|---|---|---|---|
| Valószínűség | 0,3 | 0,3 | 0,2 | 0,2 |
Egyedi bináris kódokat (lehetőleg kisebbeket) rendelhetünk a legvalószínűbb szimbólumokhoz, míg a nagyobb kódokat a kevésbé valószínűekhez.
| a | e | r | t | |
|---|---|---|---|---|
| Valószínűség | 0,3 | 0,3 | 0,2 | 0,2 |
| Bináris kód | 0 | 10 | 110 | 1110 |
A szimbólumok áramát tömörítjük, feltételezve, hogy végül 8 bitet költünk el minden egyes szimbólumra. Tömörítés nélkül 24 bit szükségesne egy szimbólumhoz. Ha minden szimbólumot a kódjára cserélünk, akkor megtakarítást érünk el!
Az első lépés a szimbólum kódolása e, amely 10, a második szimbólum pedig a, amely hozzáadódik (nem matematikai módon): [10] [0], végül a harmadik szimbólum t, amely a végső tömörített bitfolyamot [10] [0] [1110]-re állítja, vagyis 1001110, amihez mindössze 7 bit szükséges (3,4-szer kevesebb hely, mint az eredeti).
Ne feledje, hogy minden kódnak egyedi prefixel kell rendelkeznie. segít megtalálni ezeket a számokat. Bár ez a módszer nem hibátlan, továbbra is léteznek olyan videokodekek, amelyek ezt az algoritmikus módszert használják a tömörítéshez.
A kódolónak és a dekódolónak is hozzáféréssel kell rendelkeznie a saját bináris kódjaival rendelkező karaktertáblához. Ezért a bemenetekben ezt a táblát is el kell küldeni.
Aritmetikai kódolás
Tegyük fel, hogy van egy szimbólumáramunk: a, e, r, s és t, és valószínűségüket ez a táblázat mutatja.
| a | e | r | s | t | |
|---|---|---|---|---|---|
| Valószínűség | 0,3 | 0,3 | 0,15 | 0,05 | 0,2 |
Ezzel a táblázattal építsük fel az összes lehetséges karakter tartományait, amelyeket a legnagyobb mennyiség szerint rendeztünk.

Most kódoljunk le egy három karakterből álló átjárót: eat.
Először válasszuk ki az első karaktert e, amely a 0,3 és 0,6 közötti részhalmazban található (nem beleértve). Ezt a részhalmazt vesszük, és újra felosztjuk a korábbi arányok szerint, de már az új tartományra.

Folytassuk a szálunk kódolását eat. Most válasszuk ki a második karaktert a, amely az új részhalmazban 0,3 és 0,39 között van, majd fogjuk a legutolsó karakterünket t és a folyamat megismétlésével megkapjuk az utolsó részhalmazt 0,354 és 0,372 között.

Csak annyit kell választanunk, hogy a legutolsó részhalmazban 0,354 és 0,372 között legyen. Válasszuk a 0,36-ot (de bármilyen más számot is választhatunk ebben a részhalmazban). Csak ezzel a számmal tudjuk visszaállítani az eredeti szálunkat. Olyan, mintha vonalat húznánk a kódolásunk tartományain belül.

A fordított művelet (azaz dekódolás) ugyanolyan egyszerű: a számunkkal 0,36 és az eredeti tartományunkkal megkezdhetjük ugyanazt a folyamatot. De most, e szám felhasználásával feltárjuk azt a szálat, amelyet e szám segítségével kódoltunk.
Az első tartománynál észrevesszük, hogy a számunk megfelel a szeletnek, tehát ez az első karakterünk. Most újra oszd fel ezt a részhalmazt, végezve a korábban használatban lévő folyamatot. Itt észrevehetjük, hogy a 0,36 a karakterhez tartozik a, és a folyamat megismétlésével eljutottunk az utolsó karakterhez t (megalapozva az eredeti kódolt szálunkat eat).
A kódolónak és a dekódolónak is rendelkezésére kell állnia a karakterek valószínűségi táblájával, ezért szükséges, hogy ezt is elküldjük a bemeneten.
Eléggé elegáns, nem igaz? Aki ezt a megoldást kitalálta, hihetetlenül okos volt. Néhány videokódoló ezt a technikát használja (vagy legalábbis lehetőségként kínálja).
A lényeg abban rejlik, hogy veszteségmentesen tömörítsük a kvantált bitfolyamot. Biztos vagyok benne, hogy ebben a cikkben rengeteg részlet, indoklás, kompromisszum és egyebek hiányoznak. De ha te fejlesztő vagy, akkor többet kell tudnod. Az új kodekek különböző entropikus kódolási algoritmusokat próbálnak használni, mint például ANS.
6. lépés – a bitfolyam formátuma
Miután mindezt megtettük, a tömörített képkockákat a végrehajtott lépések kontextusában kell kibővítenünk. Kifejezetten tájékoztatni kell a dekódert a kódoló által hozott döntésekről. A dekódernek minden szükséges információt biztosítani kell: bitmélység, színtér, felbontás, előrejelzési információk (mozgásvektorok, irányított INTER-előrejelzés), profil, szint, képkocka gyakoriság, képkocka típusa, képkocka száma és sok egyéb.
Felszínesen megismerkedünk a bitfolyammal H.264. Az első lépésünk egy minimális H.264 bitfolyam létrehozása (az FFmpeg alapértelmezés szerint hozzáad minden kódolási paramétert, mint például SEI NAL — ezt kicsit később fogjuk megérteni). Ezt a saját tárolónk és az FFmpeg segítségével végezhetjük el.
.\/s\/ffmpeg -i \/files\/i\/minimal.png -pix_fmt yuv420p \/files\/v\/minimal_yuv420.h264
Ez a parancs egy nyers bitfolyamot generál H.264 egy képpel, 64×64 felbontással, YUV színtérrel. YUV420. Ekkor a következő képet használjuk képként.

A H.264 bitfolyam
A szabványt AVC (H.264) meghatározza, hogy az információ makroképként (hálózati értelemben) kerül továbbításra, amelyeket NAL (ez egy ilyen hálózati absztrakciós szint). A NAL fő célja, hogy 'hálózatra barátságos' videó ábrázolást biztosítson. Ennek a szabványnak működnie kell tévékészülékeken (folyam alapú) és az interneten (csomag alapú).
![]()
Van egy szinkronizáló jelző a NAL elemek határainak meghatározására. Minden szinkronizáló jelző tartalmaz egy értéket, 0x00 0x00 0x01, kivéve az elsőt, amely értéke 0x00 0x00 0x00 0x01. Ha futtatjuk hexdump a generált H.264 bitfolyamra, legalább három NAL mintázatot azonosítunk a fájl elején.

Ahogy említettem, a dekódernek nemcsak a képadatokat, hanem a videó, a képkocka, a színek, a használt paraméterek részleteit és sok egyebet is ismernie kell. Minden NAL első bájtja meghatározza annak kategóriáját és típusát.
| A NAL típusazonosító | Leírás |
|---|---|
| 0 | Ismeretlen típus |
| 1 | Kódolt képrészlet IDR nélkül |
| 2 | A kódolt adatmező szelete A |
| 3 | A kódolt adatmező szelete B |
| 4 | A kódolt adatmező szelete C |
| 5 | A kódolt IDR-rész IDR-képének |
| 6 | További információk az SEI kiterjesztésről |
| 7 | SPS-sorozat paramétereinek készlete |
| 8 | PPS-kép paramétereinek készlete |
| 9 | Hozzáférési szeparátor |
| 10 | Szekvencia vége |
| 11 | Áramlás vége |
| … | … |
A bitfolyam első NAL-ja általában SPS. Ez a NAL típus a kódolás általános változóinak, például profil, szint, felbontás és egyéb információknak a közlésére szolgál.
Ha átugorjuk az első szinkronizáló jelzőt, dekódolhatjuk az első bájtot, hogy megtudjuk, milyen NAL típus az első.
Például a szinkronizáló jelző után az első bájt értéke 01100111, ahol az első bit (0) az f mezőben vanorbidden_zero_bit. A következő 2 bit (11) megmutatja nekünk a mezőt nal_ref_idc, ami azt mutatja, hogy ez a NAL hivatkozási mező-e vagy sem. A maradék 5 bit (00111) megmutatja nekünk a mezőt nal_unit_type, ez az SPS blokk (7) NAL.
A második bájt (bináris=01100100, hex=0x64, dec=100) az SPS NAL-ban a mező profile_idc, ami azt mutatja, hogy a kódoló mely profilt használta. Ebben az esetben a korlátozott magas profil volt használva (azaz a magas profil, amely nem támogatja a bidirekcionális B-szeletet).

Ha áttekintjük a bitfolyam specifikációját H.264 az SPS NAL-hoz, akkor sok értéket találunk a paraméter nevéhez, kategóriájához és leírásához. Például nézzük meg a mezőket pic_width_in_mbs_minus_1 és pic_height_in_map_units_minus_1.
| Paraméter neve | Kategória | Leírás |
|---|---|---|
| pic_width_in_mbs_minus_1 | 0 | ue(v) |
| pic_height_in_map_units_minus_1 | 0 | ue(v) |
Ha néhány matematikai műveletet hajtunk végre e mezők értékein, megkapjuk a felbontást. A 1920 x 1080-at a következőképpen lehet ábrázolni pic_width_in_mbs_minus_1 a 119 értékkel ((119 + 1) * macroblock_size = 120 * 16 = 1920). Ismét, helyet spórolva, a 1920-at a 119 kódolásával oldották meg.
Ha folytatjuk a létrehozott videónk bináris ellenőrzését (például: xxd -b -c 11 v/minimal_yuv420.h264), akkor elérhetjük az utolsó NAL-t, ami magát a keretet képviseli.

Itt látjuk az első 6 bájt értékét: 01100101 10001000 10000100 00000000 00100001 11111111. Mivel tudjuk, hogy az első bájt jelzi a NAL típusát, ebben az esetben (00101) ez egy IDR rész (5), és így további vizsgálatot végzünk rajta:

A specifikáció információit felhasználva dekódolhatjuk a rész típusát (slice_type) és a keretszámot (frame_num) más fontos mezők mellett.
A mezők egyes értékeinek megszerzéséhez (ue(v), me(v), se(v) vagy %Dátum(v), szükségünk van a rész dekódolására, egy speciális dekóder segítségével, amely a Ez a módszer nagyon hatékony a változók értékeinek kódolásában, különösen akkor, ha sok alapértelmezett érték van.
Értékek slice_type és frame_num ennek a videónak az I-szegmense és az első képkockája egyenlő 7-el és 0-val.
A bites folyam egy protokollként is felfogható. Ha többet szeretne tudni a bites folyamról, érdemes a specifikációra figyelni. ITU H.264. Itt van egy makrosémája, amely megmutatja, hol találhatóak a képadatok (YUV tömörített formában).

Feltérképezheti a többi bites folyamot is, mint például VP9, H.265 (HEVC) vagy akár a legújabb legjobb bites folyamunkat. AV1Ezek mind hasonlóak? Nem, de ha legalább az egyikkel tisztában van, sokkal könnyebb megérteni a többit.
Szeretne gyakorolni? Fedezze fel a H.264 bites folyamot.
Egyszerűen generálhat egy képkockás videót, és használhatja a MediaInfo-t a bites folyama kutatásához. H.264Valójában semmi sem akadályozza meg, hogy megnézze a kódot, amely elemzi a bites folyamot. H.264 (AVC).
Gyakorlásra használhatja az Intel Video Pro Analyzer-t (mintha már említettem volna, hogy a program fizetős, de van ingyenes próbaverzió is, amely 10 képkockára korlátozott?).
Áttekintés
Érdemes megjegyezni, hogy sok modern kodek ugyanazt a modellt használja, amit most tanulmányoztunk. Nézzük meg a videokodek folyamatábráját. ThorEz tartalmazza az összes lépést, amit megtettünk. Ennek a jegyzetnek az a lényege, hogy legalább jobban megértse az innovációkat és a terület dokumentációját.

Korábban kiszámoltuk, hogy 139 GB lemezterület szükséges egy 720p és 30 fps-es minőségű, egy órás videófájl tárolására. Ha a cikkben tárgyalt módszereket (kép közötti és belső előrejelzések, transzformáció, kvantálás, entrópiai kódolás stb.) használjuk, elérhetjük (figyelembe véve, hogy 0,031 bit pixelre fordítunk), egy kielégítő minőségű videót, amely mindössze 367,82 MB-ot foglal el, nem pedig 139 GB-ot.
Hogyan éri el az H.265 a kisebb tömörítési arányt, mint az H.264?
Most, hogy többet tudunk arról, hogyan működnek a kodekek, könnyebb megérteni, hogyan képesek az új kodekek magasabb felbontást biztosítani kevesebb bit felhasználásával.
Ha összehasonlítunk AVC és HEVC, ne feledje, hogy ez szinte mindig egy választás a CPU nagyobb terhelése és a tömörítési arány között.
HEVC több szakasz (és alfejezet) variációval rendelkezik, mint AVC, több irányban való belső előrejelzés, javított entrópiakódolás és még sok más. Mindezek a fejlesztések lehetővé tették, hogy H.265 50%-kal többet tömörítsen, mint H.264.

Első rész:
Forrás: habr.com




