Första delen:
Vad? En videokodex Àr en del av programvaran/hÄrdvaran som komprimerar och/eller avkodar digital video.
Varför? Trots vissa begrÀnsningar av sÄvÀl bandbredd som
lagringsutrymme, krĂ€ver marknaden alltmer högkvalitativ video. Kommer du ihĂ„g hur vi i det förra inlĂ€gget berĂ€knade det nödvĂ€ndiga minimumet för 30 bilder per sekund, 24 bitar per pixel, med upplösningen 480Ă240? Vi fick 82,944 Mbit/s utan komprimering. Komprimering Ă€r fortfarande det enda sĂ€ttet att överhuvudtaget överföra HD/FullHD/4K till TV-skĂ€rmar och internet. Hur uppnĂ„s detta? LĂ„t oss nu kort gĂ„ igenom de viktigaste metoderna.
ĂversĂ€ttningen gjordes med stöd av företaget EDISON Software.Vi sysslar med , samt .
Kodex vs Container
En vanlig nybörjarmisstag Àr att förvÀxla videokodexen och digital video container. En container Àr ett format, ett omslag som innehÄller metadata för video (och kanske ljud). Den komprimerade videon kan ses som en nyttolast i containern.
Vanligtvis indikerar videofilens filÀndelse dess typ av container. Till exempel, filen video.mp4 Àr troligen en container MPEG-4 Part 14, medan en fil med namnet video.mkv troligen Àr en . För att vara helt sÀker pÄ kodexen och containerformatet kan man anvÀnda eller .
Lite historia
Innan vi gÄr över till Hur?, lÄt oss dyka lite in i historien för att förstÄ nÄgra Àldre kodexer bÀttre.
Videokodex H.261 introducerades 1990 (tekniskt sett 1988) och skapades för att arbeta med en överföringshastighet pÄ 64 Kbit/s. Den anvÀnde redan sÄdana idéer som fÀrgsampling, makroblock etc. à r 1995 publicerades standarden för videokodexen H.263, som utvecklades fram till 2001.
Ă r 2003 avslutades den första versionen av H.264/AVC. Samma Ă„r slĂ€ppte företaget "TrueMotion" sin gratis videokodex som komprimerade video med förlust, kallad VP3. Ă r 2008 köpte Google detta företag och slĂ€ppte VP8 samma Ă„r. I december 2012 slĂ€ppte Google VP9, och den stöds av ungefĂ€r Ÿ av marknaden för webblĂ€sare (inklusive mobila enheter).
AV1 â Ă€r en ny gratis videokodare med öppen kĂ€llkod som har utvecklats av Alliansen för öppna media (AOMedia), som bestĂ„r av vĂ€lkĂ€nda företag som: Google, Mozilla, Microsoft, Amazon, Netflix, AMD, ARM, NVidia, Intel och Cisco. Den första versionen av kodaren 0.1.0 publicerades den 7 april 2016.
Födelsetiden för AV1
I början av 2015 arbetade Google med VP10, Xiph (som tillhör Mozilla) arbetade med Daala, och Cisco skapade sin gratis videokodare som heter Thor.
Sedan MPEG LA meddelade först Ärliga begrÀnsningar för HEVC (H.265) och avgifter, som var 8 gÄnger högre Àn för H.264, men snart Àndrade de reglerna igen:
utan Ärlig grÀns,
avgift för innehÄll (0,5% av intÀkten) och
avgift per enhet var ungefÀr 10 gÄnger högre Àn för H.264.
Alliansen för öppna media skapas av företag frÄn olika omrÄden: hÄrdvaruproducenter (Intel, AMD, ARM, Nvidia, Cisco), innehÄllstillverkare (Google, Netflix, Amazon), webblÀsarskapare (Google, Mozilla) och andra.
Företagen hade ett gemensamt mĂ„l â en videokodare utan licensavgifter. Sedan dyker det upp AV1 med en mycket enklare patentlicens. Timothy B. Terriberry gav en enastĂ„ende presentation som blev kĂ€llan till den nuvarande konceptet AV1 och dess licensmodell.
Du kommer att bli förvÄnad över att veta att du kan analysera AV1-kodaren via en webblÀsare (de som Àr intresserade kan besöka).

En universell kodare
LÄt oss bryta ner de grundlÀggande mekanismerna bakom den universella videokodaren. MÄnga av dessa koncept Àr anvÀndbara och anvÀnds i moderna kodare, sÄsom VP9, AV1 och HEVC. Jag varnar för att mÄnga av de saker som förklaras kommer att förenklas. Ibland kommer verkliga exempel att anvÀndas (som i fallet med H.264) för att demonstrera teknologier.
Steg 1 â uppdelning av bilden
Det första steget Àr att dela upp ramen i flera sektioner, undersektorer och sÄ vidare.

Varför? Det finns mÄnga skÀl. NÀr vi delar upp bilden kan vi bÀttre förutsÀga rörelsevektorer genom att anvÀnda smÄ sektioner för smÄ rörliga delar. Medan vi för en statisk bakgrund kan nöja oss med större sektioner.
Vanligtvis organiserar codecs dessa sektioner i sektioner (eller fragment), makroblock (eller kodningstrĂ€dblock) och mĂ„nga underavsnitt. Den maximala storleken pĂ„ dessa sektioner varierar, HEVC sĂ€tter 64Ă64, medan AVC anvĂ€nder 16Ă16, och underavsnitt kan delas upp till storlekar pĂ„ 4Ă4.
Kommer du ihÄg typerna av ramar frÄn den tidigare artikeln?! Detta kan ocksÄ tillÀmpas pÄ block, sÄ vi kan ha I-fragment, B-block, P-makroblock osv.
För de som vill öva â se hur bilden delas upp i sektioner och underavsnitt. För detta kan man anvĂ€nda den som nĂ€mndes i den tidigare artikeln. (den som Ă€r betald, men med en gratis provversion som har begrĂ€nsning pĂ„ de första 10 ramarna). HĂ€r analyseras sektionerna. VP9:

Steg 2 â prognostisering
SÄ fort vi har sektioner kan vi göra astrologiska prognoser baserade pÄ dem. För INTER-prognostisering Àr det nödvÀndigt att överföra rörelsevektorer och rester, medan för INTRA-prognostisering överförs prognosriktning och resten.
Steg 3 â omvandling
NĂ€r vi har den resterande blocket (förutsagd sektion â verklig sektion) kan vi omvandla det pĂ„ ett sĂ€tt som gör att vi vet vilka pixlar som kan kasseras, samtidigt som den totala kvaliteten bevaras. Det finns vissa omvandlingar som erbjuder exakt beteende.
Ăven om det finns andra metoder, lĂ„t oss titta nĂ€rmare pĂ„ diskret cosinustransform (DCT â frĂ„n discrete cosine transform). Huvudfunktionerna för DCT:
- Omvandlar block med pixlar till lika stora block med frekvenskoefficienter.
- Kompakterar kraften, vilket hjÀlper till att eliminera rumslig redundans.
- SÀkerstÀller reversibilitet.
Den 2 februari 2017 publicerade Cintra R.J. och Bayer F.M. en artikel om DCT-liknande omvandling för bildkomprimering, vilket krÀver endast 14 additioner.
Oroa dig inte om du inte förstod fördelarna med varje punkt. Nu kommer vi att bevisa deras verkliga vÀrde med konkreta exempel.
LĂ„t oss ta ett sĂ„dant block av pixlar 8Ă8:

Detta block renderas till följande bild av 8 pÄ 8 pixlar:

Vi tillĂ€mpar DCT pĂ„ detta block av pixlar och fĂ„r ett block av koefficienter med storleken 8Ă8:

Och om vi renderar detta block av koefficienter fÄr vi följande bild:

Som vi kan se, liknar detta inte det ursprungliga bilden. Det gÄr att mÀrka att den första koefficienten avviker kraftigt frÄn alla andra. Denna första koefficient Àr kÀnd som DC-koefficienten, som representerar alla prov i ingÄngsarrayen, nÄgot som liknar ett medelvÀrde.
Denna block av koefficienter har en intressant egenskap: den separerar högfrekventa komponenter frÄn lÄgfrekventa.

I bilden Àr den största delen av kraften koncentrerad pÄ lÀgre frekvenser, dÀrför, om vi omvandlar bilden till dess frekvenser och kastar bort de högre frekventa koefficienterna, kan vi minska mÀngden data som krÀvs för att beskriva bilden utan att offra för mycket bildkvalitet.
Frekvens betyder hur snabbt signalen förÀndras.
LÄt oss försöka tillÀmpa kunskapen vi fÄtt i testexemplet genom att omvandla den ursprungliga bilden till dess frekvens (koefficientblock) med hjÀlp av DCT, och dÀrefter kasta bort en del av de minst viktiga koefficienterna.
Först konverterar vi den till frekvensomrÄdet.

DÀrefter kastar vi bort en del (67%) av koefficienterna, frÀmst den nedre högra delen.

Slutligen Äterskapar vi bilden frÄn detta bortkastade koefficientblock (kom ihÄg att det mÄste vara omvÀnt) och jÀmför med originalet.

Vi ser att den liknar den ursprungliga bilden, men det finns mÄnga skillnader frÄn originalet. Vi har kastat bort 67,1875% och ÀndÄ fÄtt nÄgot som pÄminner om ursprunget. Det skulle kunna ha varit mer genomtÀnkt att kasta bort koefficienterna för att fÄ en bild av Ànnu högre kvalitet, men det Àr redan nÀsta Àmne.
Varje koefficient bildas med hjÀlp av alla pixlar
Viktigt: varje koefficient avbildas inte direkt pÄ en pixel, utan representerar en viktad summa av alla pixlar. Denna fantastiska graf visar hur den första och andra koefficienten berÀknas med vikter som Àr unika för varje index.
Du kan ocksÄ försöka visualisera DCT genom att titta pÄ en enkel bildformation baserad pÄ den. Till exempel, hÀr Àr bokstaven A som bildas med hjÀlp av varje koefficientvÀg.
FjÀrde steget Àr kvantisering
Efter att ha tagit bort vissa koefficienter i det föregÄende steget, utför vi en speciell form av kvantisering i det sista steget (omvandling). I detta skede Àr det acceptabelt att förlora information. Eller, enklare sagt, vi kvantiserar koefficienterna för att uppnÄ kompression.
Hur kan vi kvantisera en block av koefficienter? En av de enklaste metoderna Àr jÀmn kvantisering, dÀr vi tar blocket, delar det med ett vÀrde (med 10) och rundar det som vi fÄtt.

Kan vi ÄterstÀlla detta block av koefficienter? Ja, det kan vi, genom att multiplicera med samma vÀrde som vi delade med.

Denna metod Àr inte den bÀsta, eftersom den inte tar hÀnsyn till varje koefficients betydelse. Vi skulle kunna anvÀnda en kvantiseringsmatris istÀllet för ett enda vÀrde, och denna matris kan utnyttja egenskapen DCT, vilket kvantiserar de flesta av de nedre högra och ett fÄtal av de övre vÀnstra.
Steg 5 - entropikodning
Efter att vi har kvantiserat data (bildblock, fragment, ramar) kan vi fortfarande komprimera dem utan förlust. Det finns mÄnga algoritmiska sÀtt att komprimera data. Vi kommer kort att introducera nÄgra av dem, för en djupare förstÄelse kan du lÀsa boken "Understanding Compression: Data Compression for Modern Developers".»).
Videoinkodning med VLC
LÄt oss anta att vi har en ström av tecken: a, e, Àr lika med noll. och t. Sannolikheten (inom intervallet 0 till 1) för hur ofta varje tecken förekommer i strömmen presenteras i denna tabell.
| a | e | Àr lika med noll. | t | |
|---|---|---|---|---|
| Sannolikhet | 0,3 | 0,3 | 0,2 | 0,2 |
Vi kan tilldela unika binÀra koder (helst smÄ) till de mest sannolika, och större koder till mindre sannolika.
| a | e | Àr lika med noll. | t | |
|---|---|---|---|---|
| Sannolikhet | 0,3 | 0,3 | 0,2 | 0,2 |
| BinÀrkod | 0 | 10 | 110 | 1110 |
Vi komprimerar strömmen, och antar att vi fÄr slösa 8 bitar per tecken. Utan kompression skulle det krÀvas 24 bitar per tecken. Om varje tecken ersÀtts med sin kod, sÄ ger det en besparing!
Det första steget innebÀr att koda tecknet e, vilket Àr 10, och det andra tecknet Àr a, vilket lÀggs till (inte pÄ ett matematiskt sÀtt): [10] [0], och slutligen det tredje tecknet t, vilket gör vÄr slutgiltiga komprimerade bitström lika [10] [0] [1110] eller 1001110, vilket krÀver bara 7 bitar (3,4 gÄnger mindre utrymme Àn originalet).
Observera att varje kod mĂ„ste vara en unik prefixkod. hjĂ€lper att hitta dessa siffror. Ăven om denna metod inte Ă€r utan brister, finns det videokodekar som fortfarande erbjuder denna algoritmiska metod för komprimering.
BÄde kodaren och avkodaren mÄste ha tillgÄng till en teckentabell med sina binÀra koder. DÀrför Àr det ocksÄ nödvÀndigt att skicka med tabellen i indata.
Arithmetisk kodning
LÄt oss anta att vi har en ström av tecken: a, e, Àr lika med noll., s och t, och deras sannolikhet presenteras i denna tabell.
| a | e | Àr lika med noll. | s | t | |
|---|---|---|---|---|---|
| Sannolikhet | 0,3 | 0,3 | 0,15 | 0,05 | 0,2 |
Med denna tabell bygger vi intervall som innehÄller alla möjliga tecken, sorterade efter största antal.

LÄt oss nu koda strömmen av tre tecken: eat.
Först vÀljer vi det första tecknet e, som ligger i intervallet frÄn 0,3 till 0,6 (exklusive). Vi tar detta intervall och delar det igen i samma proportioner som tidigare, men för detta nya intervall.

LÄt oss fortsÀtta koda vÄr ström eat. Nu tar vi det andra tecknet a, som ligger i det nya intervallet frÄn 0,3 till 0,39, och sedan tar vi vÄrt sista tecken t och, genom att upprepa samma process igen, fÄr vi det sista intervallet frÄn 0,354 till 0,372.

Vi behöver bara vÀlja ett nummer i det sista intervallet frÄn 0,354 till 0,372. LÄt oss vÀlja 0,36 (men vi kan ocksÄ vÀlja vilket annat nummer som helst inom detta intervall). Endast med detta nummer kan vi ÄterstÀlla vÄr ursprungliga ström. Det Àr som att vi ritade en linje inom intervallen för att koda vÄr ström.

Den omvÀnda operationen (d.v.s. avkodning) Àr lika enkel: med vÄrt nummer 0,36 och vÄrt ursprungliga intervall kan vi köra samma process. Men nu, med detta nummer, identifierar vi strömmen som kodades med hjÀlp av detta nummer.
Med det första intervallet mÀrker vi att vÄrt nummer motsvarar skÀrningen, sÄ detta Àr vÄrt första tecken. LÄt oss nu dela upp detta intervall igen och följa samma process som tidigare. HÀr kan vi se att 0,36 motsvarar tecknet a, och efter att ha upprepat processen har vi kommit till det sista tecknet t (och formar vÄr ursprungliga kodade ström. eat).
BÄde kodaren och avkodaren mÄste ha en sannolikhetstabell för tecken tillgÀnglig, sÄ det Àr nödvÀndigt att skicka med den i indata.
Ganska elegant, eller hur? Den som kom pÄ denna lösning var verkligen smart. Vissa videokodekar anvÀnder denna teknik (eller erbjuder Ätminstone den som ett alternativ).
Idén handlar om att förlora komprimering av en kvantiserad bitström. Denna artikel saknar sÀkert en massa detaljer, orsaker, kompromisser osv. Men om du Àr utvecklare bör du veta mer. Nya codecs försöker anvÀnda olika algoritmer för entropikodning, sÄsom ANS.
Steg 6 - bitströmformat
NÀr allt detta Àr gjort ÄterstÄr det att packa upp de komprimerade ramverken i kontext av de utförda stegen. Det Àr nödvÀndigt att tydligt informera dekodern om de beslut som kodaren har fattat. Dekodern mÄste ges all nödvÀndig information: bitdjup, fÀrgrymd, upplösning, prognosinformation (rörelsevektorer, riktad INTER-prognos), profil, nivÄ, bildhastighet, bildtyp, bildnummer och mycket mer.
Vi kommer att bekanta oss ytligt med bitströmmen H.264. VĂ„rt första steg Ă€r att skapa en minimal H.264 bitström (FFmpeg lĂ€gger som standard till alla kodningsparametrar, sĂ„som SEI NAL â vi kommer att fĂ„ veta vad det Ă€r lĂ€ngre fram). Vi kan göra detta med vĂ„rt eget arkiv och FFmpeg.
./s/ffmpeg -i /files/i/minimal.png -pix_fmt yuv420p /files/v/minimal_yuv420.h264
Detta kommando kommer att generera en rĂ„ bitström H.264 med en bild, upplösning 64Ă64, med fĂ€rgrymden YUV420. AnvĂ€nds som bild Ă€r följande bild.

H.264 bitström
Standard AVC (H.264) definierar att informationen kommer att överföras i makroblock (i nÀtverksbemÀrkelse), kallade NAL (detta Àr en sÄdan abstraktionsnivÄ i nÀtverket). Den huvudsakliga mÄlsÀttningen för NAL Àr att tillhandahÄlla en "nÀtverksvÀnlig" representation av video. Denna standard bör fungera pÄ TV-apparater (baserat pÄ strömmar), pÄ internet (baserat pÄ paket).
![]()
Det finns en synkroniseringsmarkering för att bestÀmma grÀnserna för NAL-elementen. Varje synkroniseringsmarkering innehÄller ett vÀrde 0x00 0x00 0x01, förutom den första, som Àr 0x00 0x00 0x00 0x01. Om vi kör hexdump för den genererade H.264 bitströmmen, kan vi identifiera Ätminstone tre NAL-mönster i början av filen.

Som nÀmnts mÄste dekodern veta inte bara bilddata utan Àven detaljer om videon, ramen, fÀrgerna, de anvÀnda parametrarna och mycket mer. Den första byten av varje NAL bestÀmmer dess kategori och typ.
| NAL typ-ID | Beskrivning |
|---|---|
| 0 | OkÀnd typ |
| 1 | Kodad bildfragment utan IDR |
| 2 | Kodad del av slice-data A |
| 3 | Kodad del av slice-data B |
| 4 | Kodad del av slice-data C |
| 5 | Kodad IDR-fragment av IDR-bild |
| 6 | Ytterligare information om SEI-tillÀgget |
| 7 | SPS-sekvensparametrar |
| 8 | PPS-bildparametrar |
| 9 | Ă tkomstseparator |
| 10 | Sekvensens slut |
| 11 | Strömens slut |
| ⊠| ⊠|
Vanligtvis Àr den första NAL-biten i bitströmmen SPS. Denna typ av NAL ansvarar för att informera om allmÀnna kodningsvariabler, sÄsom profil, nivÄ, upplösning och mer.
Om vi hoppar över den första synkroniseringsmarkören kan vi avkoda den första byten för att ta reda pÄ vilken typ av NAL den första Àr.
Till exempel, den första byten efter synkroniseringsmarkören Àr 01100111, dÀr den första biten (0) finns i fÀltet forbidden_zero_bit. De följande 2 bitarna (11) meddelar oss fÀltet nal_ref_idc, som anger om denna NAL Àr en referensfÀlt eller inte. Och de ÄterstÄende 5 bitarna (00111) meddelar oss fÀltet nal_unit_type, i detta fall Àr det en SPS-block (7) NAL.
Den andra byten (binÀr=01100100, hex=0x64, dec=100) i SPS NAL Àr fÀltet profile_idc, som visar den profil som anvÀnds av kodaren. I det hÀr fallet anvÀndes den begrÀnsade högprofilen (dvs. högprofil utan stöd för bidirektionell B-slice).

Om vi ser över bitströmspecifikationen H.264 för SPS NAL, kommer vi att upptÀcka mÄnga vÀrden för parameterets namn, kategori och beskrivning. Till exempel, lÄt oss titta pÄ fÀlten pic_width_in_mbs_minus_1 och pic_height_in_map_units_minus_1.
| Parameternamn | Kategori | Beskrivning |
|---|---|---|
| pic_width_in_mbs_minus_1 | 0 | ue(v) |
| pic_height_in_map_units_minus_1 | 0 | ue(v) |
Om vi utför vissa matematiska operationer med vÀrdena i dessa fÀlt, fÄr vi upplösningen. Vi kan representera 1920 x 1080 med pic_width_in_mbs_minus_1 vÀrdet 119 ((119 + 1) * macroblock_size = 120 * 16 = 1920). à terigen, för att spara plats, istÀllet för att koda 1920 gjorde vi det med 119.
Om vi fortsÀtter att kontrollera vÄr skapade video i binÀr form (t.ex.: xxd -b -c 11 v/minimal_yuv420.h264), kan vi gÄ till sista NAL, som Àr sjÀlva ramen.

HÀr ser vi dess första 6 byte-vÀrden: 01100101 10001000 10000100 00000000 00100001 11111111. Eftersom det Àr kÀnt att den första byten anger typ av NAL, i detta fall (00101) Àr detta ett IDR-fragment (5), och dÄ kan vi undersöka det vidare:

Genom att anvÀnda specifikationsinformationen kan vi avkoda fragmentets typ (slice_type) och ramenummer (frame_num) bland andra viktiga fÀlt.
För att fÄ vÀrdena för vissa fÀlt (ue(v), me(v), se(v) eller te(v), mÄste vi avkoda fragmentet med hjÀlp av en speciell avkodare, baserad pÄ . Denna metod Àr mycket effektiv för att koda vÀrden pÄ variabler, sÀrskilt nÀr det finns mÄnga standardvÀrden.
VÀrden slice_type och frame_num i denna video Àr 7 (I-fragment) och 0 (första bildrutan).
En bitström kan ses som ett protokoll. Om du vill veta mer om bitströmmen, bör du hÀnvisa till specifikationen ITU H.264. HÀr Àr en makroskiss som visar var bilddata finns (YUV i komprimerad form).

Du kan ocksĂ„ utforska andra bitströmmer, som VP9, H.265 (HEVC) eller till och med vĂ„r nya bĂ€sta bitström AV1. Ăr de alla lika? Nej, men om du förstĂ„r Ă„tminstone en, blir det mycket lĂ€ttare att förstĂ„ de andra.
Vill du öva? Utforska H.264 bitströmmen
Du kan generera en enskild bildvideo och anvÀnda MediaInfo för att undersöka bitströmmen H.264. Faktum Àr att inget hindrar dig frÄn att titta pÄ kÀllkoden som analyserar bitströmmen H.264 (AVC).
För praktiken kan du anvÀnda Intel Video Pro Analyzer (jag nÀmnde visst att programmet Àr betalt, men det finns en gratis provversion med en grÀns pÄ 10 bilder?).
Ăversikt
Notera att mÄnga moderna kodekar anvÀnder samma modell som vi just har lÀrt oss. LÄt oss ta en titt pÄ blockschemat för videokodeken Thor. Det innehÄller alla steg vi har gÄtt igenom. Hela poÀngen med detta meddelande Àr att du Ätminstone ska fÄ en bÀttre förstÄelse för innovationer och dokumentation inom detta omrÄde.

Tidigare berÀknade vi att det skulle krÀvas 139 GB lagringsutrymme för att lagra en videofil som varar en timme vid kvalitet 720p och 30 fps. Om man anvÀnder metoderna som vi har diskuterat i denna artikel (inter-frame och intra-frame förutsÀgelser, transformering, kvantisering, entropikodning, osv.) kan man uppnÄ (givet att vi spenderar 0,031 bitar per pixel) en video av ganska god kvalitet som bara tar 367,82 MB istÀllet för 139 GB.
Hur uppnÄr H.265 en bÀttre komprimeringsgrad Àn H.264?
Nu nÀr vi vet mer om hur kodekar fungerar Àr det lÀttare att förstÄ hur nya kodekar kan ge högre upplösning med fÀrre bitar.
NÀr du jÀmför AVC och HEVC, kom ihÄg att det nÀstan alltid Àr ett val mellan högre CPU-belastning och grad av komprimering.
HEVC har fler avsnitt (och underavsnitt) Àn AVC, fler riktningar för intern prognos, förbÀttrad entropikodning och mycket mer. Alla dessa förbÀttringar har gjort H.265 kapabel att komprimera 50% mer Àn H.264.

Första delen:
KĂ€lla: habr.com




