Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Prima parte: Bazele lucrului cu videoclipuri și imagini

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Ce? Un codec video este o bucată de software/hardware care comprimă și/sau decomprimă videoclipurile digitale.

Pentru ce? În ciuda anumitor limitări atât în ​​ceea ce privește lățimea de bandă, cât și
iar in ceea ce priveste spatiul de stocare a datelor, piata cere video de calitate din ce in ce mai mare. Vă amintiți cum am calculat în ultima postare minimul necesar pentru 30 de cadre pe secundă, 24 de biți pe pixel, cu o rezoluție de 480x240? Am primit 82,944 Mbit/s fără compresie. Compresia este în prezent singura modalitate de a transmite în general HD/FullHD/4K către ecranele de televiziune și pe internet. Cum se realizează acest lucru? Acum să ne uităm pe scurt la principalele metode.

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Traducerea a fost realizată cu suportul EDISON Software.

Suntem logoditi integrarea sistemelor de supraveghere videoși dezvoltăm un microtomograf.

Codec vs Container

O greșeală comună pe care o fac începătorii este confuzia codec-ului video digital și a containerului video digital. Un container este un anumit format. Un wrapper care conține metadate video (și posibil audio). Videoclipul comprimat poate fi considerat ca o sarcină utilă a containerului.

De obicei, extensia unui fișier video indică tipul său de container. De exemplu, fișierul video.mp4 este probabil un container MPEG-4 Partea 14, iar un fișier numit video.mkv este cel mai probabil matrioșca. Pentru a fi complet sigur de formatul de codec și container, puteți utiliza fFmpeg sau MediaInfo.

Un pic de istorie

Înainte să ajungem la Cum?, haideți să ne aruncăm puțin în istorie pentru a înțelege puțin mai bine unele codecuri mai vechi.

Codec video H.261 a apărut în 1990 (tehnic - în 1988) și a fost creat pentru a funcționa la o rată de transfer de date de 64 Kbps. A folosit deja idei precum subeșantionarea culorilor, macroblocuri etc. Standardul de codec video a fost publicat în 1995 H.263, care s-a dezvoltat până în 2001.

Prima versiune a fost finalizată în 2003 H.264 / AVC. În același an, TrueMotion și-a lansat codecul video cu pierderi gratuit numit VP3. Google a cumpărat compania în 2008, lansând VP8 în același an. În decembrie 2012, Google a lansat VP9și este acceptat în aproximativ ¾ din piața browserelor (inclusiv dispozitivele mobile).

AV1 este un nou codec video gratuit și open source dezvoltat de Alianța pentru Media Deschisă (AOMedia), care include cele mai cunoscute companii, precum: Google, Mozilla, Microsoft, Amazon, Netflix, AMD, ARM, NVidia, Intel și Cisco. Prima versiune a codecului, 0.1.0, a fost publicată pe 7 aprilie 2016.

Nașterea AV1

La începutul lui 2015, Google lucra la asta VP10Xiph (care este deținut de Mozilla) lucra la Daala, iar Cisco și-a creat propriul codec video gratuit numit Thor.

atunci MPEG LA primele limite anuale anunțate pentru HEVC (H.265) și o taxă de 8 ori mai mare decât pentru H.264, dar în curând au schimbat din nou regulile:

fără limită anuală,
taxa de continut (0,5% din venituri) si
taxa unitară este de aproximativ 10 ori mai mare decât H.264.

Alianța pentru Media Deschisă a fost creat de companii din diferite domenii: producători de echipamente (Intel, AMD, ARM, Nvidia, Cisco), furnizori de conținut (Google, Netflix, Amazon), creatori de browsere (Google, Mozilla) și alții.

Companiile aveau un obiectiv comun - un codec video fără drepturi de autor. Apoi apare AV1 cu o licență de brevet mult mai simplă. Timothy B. Terryberry a făcut o prezentare uluitoare care a devenit originea conceptului actual AV1 și a modelului său de licențiere.

Vei fi surprins să afli că poți analiza codecul AV1 printr-un browser (cei interesați pot merge la aomanalyzer.org).

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Codec universal

Să ne uităm la principalele mecanisme care stau la baza codecului video universal. Cele mai multe dintre aceste concepte sunt utile și sunt folosite în codecuri moderne, cum ar fi VP9, AV1 и HEVC. Vă avertizez că multe dintre lucrurile explicate vor fi simplificate. Uneori, exemple din lumea reală (ca și în cazul H.264) vor fi folosite pentru a demonstra tehnologiile.

Primul pas - împărțirea imaginii

Primul pas este împărțirea cadrului în mai multe secțiuni, subsecțiuni și nu numai.

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Pentru ce? Sunt multe motive. Când împărțim o imagine, putem prezice mai precis vectorul de mișcare folosind secțiuni mici pentru părțile mici în mișcare. În timp ce pentru un fundal static, vă puteți limita la secțiuni mai mari.

Codecurile organizează de obicei aceste secțiuni în secțiuni (sau bucăți), macroblocuri (sau blocuri arborescente de codare) și mai multe subsecțiuni. Dimensiunea maximă a acestor partiții variază, HEVC o setează la 64x64, în timp ce AVC utilizează 16x16, iar subpartițiile pot fi împărțite până la dimensiuni 4x4.

Vă amintiți tipurile de rame din ultimul articol?! Același lucru poate fi aplicat blocurilor, deci putem avea un fragment I, un bloc B, un macrobloc P etc.

Pentru cei care doresc să exerseze, urmăriți cum imaginea este împărțită în secțiuni și subsecțiuni. Pentru a face acest lucru, îl puteți folosi pe cel deja menționat în articolul anterior. Analizor Intel Video Pro (cea care este plătită, dar cu o versiune de probă gratuită care este limitată la primele 10 cadre). Secțiunile analizate aici VP9:

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Pasul 2 - prognoza

Odată ce avem secțiuni, putem face prognoze astrologice pentru ele. Pentru Prognozele INTER trebuie transferat vectori de mișcare iar restul, iar pentru prognoza INTRA se transmite direcția de prognoză iar restul.

Pasul 3 - transformare

Odată ce avem un bloc rezidual (secțiunea prezisă → secțiunea reală), este posibil să-l transformăm în așa fel încât să știm ce pixeli pot fi aruncați, menținând în același timp calitatea generală. Există unele transformări care oferă comportamentul exact.

Deși există și alte metode, să le analizăm mai detaliat. transformată cosinus discretă (DCT - din transformată cosinus discretă). Principalele funcții ale DCT:

  • Convertește blocuri de pixeli în blocuri de dimensiuni egale de coeficienți de frecvență.
  • Condensează puterea pentru a ajuta la eliminarea redundanței spațiale.
  • Oferă reversibilitate.

2 februarie 2017 Sintra R.J. (Cintra, RJ) și Bayer F.M. (Bayer FM) a publicat un articol despre o transformare asemănătoare DCT pentru compresia imaginii care necesită doar 14 completări.

Nu vă faceți griji dacă nu înțelegeți beneficiile fiecărui articol. Acum să folosim exemple specifice pentru a vedea valoarea lor reală.

Să luăm acest bloc de pixeli de 8x8:

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Acest bloc este redat în următoarea imagine de 8 x 8 pixeli:

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Aplicați DCT acestui bloc de pixeli și obțineți un bloc de coeficienți de 8x8:

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Și dacă redăm acest bloc de coeficienți, vom obține următoarea imagine:

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

După cum puteți vedea, nu arată ca imaginea originală. Puteți vedea că primul coeficient este foarte diferit de toți ceilalți. Acest prim coeficient este cunoscut sub numele de coeficient DC, care reprezintă toate eșantioanele din matricea de intrare, ceva ca o medie.

Acest bloc de coeficienți are o proprietate interesantă: separă componentele de înaltă frecvență de cele de joasă frecvență.

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Într-o imagine, cea mai mare parte a puterii este concentrată la frecvențe mai mici, așa că dacă convertiți imaginea în componentele sale de frecvență și renunțați la coeficienții de frecvență mai mari, puteți reduce cantitatea de date necesare pentru a descrie imaginea fără a sacrifica prea mult calitatea imaginii.

Frecvența se referă la cât de repede se schimbă semnalul.

Să încercăm să aplicăm cunoștințele acumulate în cazul de testare prin conversia imaginii originale la frecvența sa (blocul de coeficienți) folosind DCT și apoi eliminând o parte din coeficienții mai puțin importanți.

Mai întâi îl convertim în domeniul frecvenței.

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

În continuare, aruncăm o parte (67%) din coeficienți, în principal partea din dreapta jos.

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

În cele din urmă, reconstruim imaginea din acest bloc de coeficienți aruncat (rețineți că trebuie să fie inversabilă) și o comparăm cu originalul.

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Vedem că seamănă cu imaginea originală, dar există multe diferențe față de original. Am aruncat 67,1875% și am primit ceva asemănător cu originalul. A fost posibil să se arunce mai atent coeficienții pentru a obține o imagine de o calitate și mai bună, dar acesta este un subiect următor.

Fiecare coeficient este generat folosind toți pixelii

Important: fiecare coeficient nu este mapat direct la un pixel, ci este o sumă ponderată a tuturor pixelilor. Acest grafic uimitor arată cum se calculează primul și al doilea coeficient folosind ponderi unice pentru fiecare indice.

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

De asemenea, puteți încerca să vizualizați DCT uitându-vă la o simplă formare de imagine bazată pe acesta. De exemplu, iată simbolul A generat folosind fiecare pondere a coeficientului:

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Pasul 4 - cuantificare

După ce aruncăm niște coeficienți la pasul anterior, la ultimul pas (transformare) efectuăm o formă specială de cuantizare. În această etapă este acceptabil să pierdeți informații. Sau, mai simplu, vom cuantifica coeficienții pentru a obține compresia.

Cum poți cuantifica un bloc de coeficienți? Una dintre cele mai simple metode este cuantizarea uniformă, atunci când luăm un bloc, îl împărțim la o valoare (cu 10) și rotunjim rezultatul.

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Putem inversa acest bloc de coeficienți? Da, putem, înmulțind cu aceeași valoare cu care am împărțit.

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Această abordare nu este cea mai bună deoarece nu ține cont de importanța fiecărui coeficient. S-ar putea folosi o matrice de cuantificatoare în loc de o singură valoare, iar această matrice ar putea exploata proprietatea DCT prin cuantificarea majorității din dreapta jos și a minorității din stânga sus.

Pasul 5 - codificarea entropiei

Odată ce am cuantificat datele (blocuri de imagini, fragmente, cadre), le putem comprima în continuare fără pierderi. Există multe modalități algoritmice de comprimare a datelor. Vom arunca o privire rapidă asupra unora dintre ele, pentru o înțelegere mai profundă puteți citi cartea Understanding Compression: Data Compression for Modern Developers ("Înțelegerea compresiei: compresia datelor pentru dezvoltatorii moderni").

Codificare video folosind VLC

Să presupunem că avem un flux de personaje: a, e, r и t. Probabilitatea (de la 0 la 1) a cât de des apare fiecare caracter într-un flux este prezentată în acest tabel.

a e r t
probabilitate 0,3 0,3 0,2 0,2

Putem atribui coduri binare unice (de preferință mici) celor mai probabile și coduri mai mari celor mai puțin probabile.

a e r t
probabilitate 0,3 0,3 0,2 0,2
Cod binar 0 10 110 1110

Comprimăm fluxul, presupunând că vom ajunge să cheltuim 8 biți pentru fiecare personaj. Fără compresie, ar fi necesari 24 de biți per caracter. Dacă înlocuiți fiecare caracter cu codul său, obțineți economii!

Primul pas este codificarea caracterului e, care este egal cu 10, iar al doilea caracter este a, care se adaugă (nu în mod matematic): [10][0], iar în final al treilea caracter t, ceea ce face ca fluxul nostru de biți comprimat final să fie egal cu [10][0][1110] sau 1001110, care necesită doar 7 biți (de 3,4 ori mai puțin spațiu decât originalul).

Vă rugăm să rețineți că fiecare cod trebuie să fie un cod unic cu un prefix. Algoritmul Huffman vă va ajuta să găsiți aceste numere. Deși această metodă nu este lipsită de defecte, există codecuri video care încă oferă această metodă algoritmică de compresie.

Atât codificatorul, cât și decodorul trebuie să aibă acces la un tabel de simboluri cu codurile lor binare. Prin urmare, este, de asemenea, necesar să trimiteți un tabel ca intrare.

Codare aritmetică

Să presupunem că avem un flux de personaje: a, e, r, s и t, iar probabilitatea lor este prezentată în acest tabel.

a e r s t
probabilitate 0,3 0,3 0,15 0,05 0,2

Folosind acest tabel, vom construi intervale care conțin toate caracterele posibile, sortate după cel mai mare număr.

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Acum să codificăm un flux de trei caractere: mânca.

Mai întâi selectați primul caracter e, care se află în subintervalul de la 0,3 la 0,6 (neincluzând). Luăm această subgamă și o împărțim din nou în aceleași proporții ca înainte, dar pentru această nouă gamă.

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Să continuăm să ne codificăm fluxul mânca. Acum luați al doilea caracter a, care se află în noul subgamă de la 0,3 la 0,39 și apoi luăm ultimul nostru caracter t și repetând din nou același proces, obținem sub-intervalul final de la 0,354 la 0,372.

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Trebuie doar să selectăm un număr din ultimul subgamă de la 0,354 la 0,372. Să alegem 0,36 (dar puteți alege orice alt număr din acest subgamă). Numai cu acest număr vom putea restabili fluxul inițial. Este ca și cum am trasa o linie în intervale pentru a ne codifica fluxul.

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Operația inversă (adică decodare) este la fel de simplu: cu numărul nostru 0,36 și intervalul nostru inițial, putem rula același proces. Dar acum, folosind acest număr, identificăm fluxul codificat folosind acest număr.

Cu primul interval, observăm că numărul nostru corespunde feliei, prin urmare acesta este primul nostru caracter. Acum împărțim din nou acest sub-gamă urmând același proces ca înainte. Aici puteți vedea că 0,36 corespunde simbolului a, iar după repetarea procesului am ajuns la ultimul personaj t (formând fluxul nostru codificat original mânca).

Atat codificatorul cat si decodorul trebuie sa aiba un tabel de probabilitati de simbol, deci este necesar sa-l trimiteti si in datele de intrare.

Destul de elegant, nu-i așa? Cine a venit cu această soluție a fost al naibii de inteligent. Unele codecuri video folosesc această tehnică (sau cel puțin o oferă ca opțiune).

Ideea este să comprimați fără pierderi un flux de biți cuantizat. Cu siguranță acestui articol lipsesc o mulțime de detalii, motive, compromisuri etc. Dar dacă ești dezvoltator, ar trebui să știi mai multe. Noile codecuri încearcă să utilizeze diferiți algoritmi de codare a entropiei, cum ar fi ANS.

Pasul 6 - format bitstream

După ce ați făcut toate acestea, nu mai rămâne decât să despachetați cadrele comprimate în contextul pașilor efectuati. Decodorul trebuie să fie informat în mod explicit cu privire la deciziile luate de codificator. Decodorul trebuie să fie furnizat cu toate informațiile necesare: adâncimea de biți, spațiu de culoare, rezoluție, informații de predicție (vectori de mișcare, predicție INTER direcțională), profil, nivel, frame rate, tip de cadru, număr de cadru și multe altele.

Vom arunca o privire rapidă asupra fluxului de biți H.264. Primul nostru pas este să creăm un flux de biți H.264 minim (FFmpeg adaugă în mod implicit toate opțiunile de codificare, cum ar fi SEI NAL — vom afla despre ce este vorba un pic mai departe). Putem face acest lucru folosind propriul nostru depozit și FFmpeg.

./s/ffmpeg -i /files/i/minimal.png -pix_fmt yuv420p /files/v/minimal_yuv420.h264

Această comandă va genera un flux de biți brut H.264 cu un cadru, rezoluție 64×64, cu spațiu de culoare YUV420. În acest caz, următoarea imagine este folosită ca cadru.

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Flux de biți H.264

Standard AVC (H.264) determină că informațiile vor fi trimise în macrocadre (în sensul rețelei), numite nal (acesta este un nivel de abstractizare a rețelei). Scopul principal al NAL este de a oferi o prezentare video „prietenoasă pentru web”. Acest standard ar trebui să funcționeze pe televizoare (pe baza de flux), pe Internet (pe baza de pachete).

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Există un marcator de sincronizare pentru a defini limitele elementelor NAL. Fiecare simbol de sincronizare conține o valoare 0x00 0x00 0x01, cu excepția primului, care este egal cu 0x00 0x00 0x00 0x01. Dacă lansăm hexdump pentru fluxul de biți H.264 generat, identificăm cel puțin trei modele NAL la începutul fișierului.

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

După cum sa menționat, decodorul trebuie să cunoască nu numai datele imaginii, ci și detaliile videoclipului, cadrul, culorile, parametrii utilizați și multe altele. Primul octet al fiecărui NAL își definește categoria și tipul.

identificator de tip NAL descriere
0 Tip necunoscut
1 Fragment de imagine codificat fără IDR
2 Secțiunea de date codificată a feliei A
3 Secțiunea de date codificată a feliei B
4 Secțiunea de date codificată a feliei C
5 Fragment IDR codificat al unei imagini IDR
6 Mai multe informații despre extensia SEI
7 Set de parametri ai secvenței SPS
8 Set de parametri de imagine PPS
9 Separator de acces
10 Sfârșitul secvenței
11 Sfârșitul firului
... ...

De obicei, primul NAL al unui flux de biți este PLC. Acest tip de NAL este responsabil pentru informarea despre variabilele comune de codare, cum ar fi profilul, nivelul, rezoluția etc.

Dacă sărim peste primul marcator de sincronizare, putem decoda primul octet pentru a afla care tip NAL este primul.

De exemplu, primul octet după marcatorul de sincronizare este 01100111, unde primul bit (0) este în câmpul forbidden_zero_bit. Următorii 2 biți (11) ne spune domeniul nal_ref_idc, care indică dacă acest NAL este un câmp de referință sau nu. Și restul de 5 biți (00111) ne spune domeniul tip_unitate_nal, în acest caz este blocul SPS (7) NAL.

Al doilea octet (binar=01100100, hex=0x64, dec=100) în SPS NAL este câmpul profile_idc, care arată profilul pe care l-a folosit codificatorul. În acest caz, a fost utilizat un profil înalt limitat (adică un profil înalt fără suport bidirecțional pentru segmentul B).

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Dacă te uiți la specificația bitstream H.264 pentru SPS NAL, vom găsi multe valori pentru numele parametrului, categoria și descrierea. De exemplu, să ne uităm la câmpuri pic_width_in_mbs_minus_1 и pic_height_in_map_units_minus_1.

Numele parametrului categorie descriere
pic_width_in_mbs_minus_1 0 ue(v)
pic_height_in_map_units_minus_1 0 ue(v)

Dacă efectuam unele operații matematice cu valorile acestor câmpuri, vom obține rezoluție. Se poate reprezenta 1920 x 1080 folosind pic_width_in_mbs_minus_1 cu o valoare de 119 ((119 + 1) * macroblock_size = 120 * 16 = 1920). Din nou, pentru a economisi spațiu, în loc să codificăm 1920, am făcut-o cu 119.

Dacă continuăm să verificăm videoclipul creat în formă binară (de exemplu: xxd -b -c 11 v/minimal_yuv420.h264), apoi puteți merge la ultimul NAL, care este cadrul în sine.

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Aici vedem primele sale valori de 6 octeți: 01100101 10001000 10000100 00000000 00100001 11111111. Deoarece se știe că primul octet indică tipul NAL, în acest caz (00101) este un fragment IDR (5), apoi îl puteți explora în continuare:

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Folosind informațiile de specificație, va fi posibilă decodarea tipului de fragment (slice_type) și numărul cadrului (cadru_num) printre alte domenii importante.

Pentru a obține valorile unor câmpuri (ue(v), me(v), se(v) sau te(v)), trebuie să decodificăm fragmentul folosind un decodor special bazat pe codul Golomb exponenţial. Această metodă este foarte eficientă pentru codificarea valorilor variabilelor, mai ales când există multe valori implicite.

sens slice_type и cadru_num din acest videoclip sunt 7 (I-fragment) și 0 (primul cadru).

Un flux de biți poate fi gândit ca un protocol. Dacă doriți să aflați mai multe despre fluxul de biți, ar trebui să vă referiți la specificație ITU H.264. Iată o diagramă macro care arată unde sunt datele imaginii (YUV în formă comprimată).

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Alte fluxuri de biți pot fi examinate, cum ar fi VP9, H.265 (HEVC) sau chiar noul nostru cel mai bun bitstream AV1. Sunt toate asemănătoare? Nu, dar odată ce înțelegi cel puțin unul, este mult mai ușor să înțelegi restul.

Vrei să exersezi? Explorați fluxul de biți H.264

Puteți genera un videoclip cu un singur cadru și puteți utiliza MediaInfo pentru a examina fluxul de biți H.264. De fapt, nimic nu vă împiedică să vă uitați măcar la codul sursă care analizează fluxul de biți H.264 (AVC).

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Pentru practică, puteți folosi Intel Video Pro Analyzer (am spus deja că programul este plătit, dar există o versiune de probă gratuită cu o limită de 10 cadre?).

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Revizuire

Rețineți că multe codecuri moderne folosesc același model pe care tocmai l-am studiat. Aici, să aruncăm o privire la schema bloc a codecului video Thor. Conține toți pașii prin care am trecut. Scopul acestei postări este să vă ofere cel puțin o mai bună înțelegere a inovațiilor și a documentației din acest domeniu.

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Anterior, s-a calculat că ar fi necesar 139 GB de spațiu pe disc pentru a stoca un fișier video cu o durată de o oră la calitate 720p și 30 fps. Dacă folosiți metodele discutate în acest articol (predicții inter-cadre și interne, transformare, cuantizare, codare entropică etc.), atunci puteți realiza (pe baza faptului că cheltuim 0,031 biți pe pixel), un videoclip destul de calitate satisfăcătoare, ocupând doar 367,82 MB, nu 139 GB de memorie.

Cum realizează H.265 un raport de compresie mai bun decât H.264?

Acum că știm mai multe despre cum funcționează codecurile, este mai ușor de înțeles cum codecurile mai noi pot oferi rezoluții mai mari cu mai puțini biți.

Dacă comparați AVC и HEVC, merită să ne amintim că aceasta este aproape întotdeauna o alegere între sarcina mai mare a CPU și raportul de compresie.

HEVC are mai multe opțiuni de secțiune (și subsecțiune) decât AVC, mai multe direcții interne de predicție, codare entropică îmbunătățită și multe altele. Toate aceste îmbunătățiri au fost făcute H.265 capabil să comprima cu 50% mai mult decât H.264.

Cum funcționează un codec video? Partea 2. Ce, de ce, cum

Prima parte: Bazele lucrului cu videoclipuri și imagini

Sursa: www.habr.com

Adauga un comentariu