Decoding to proces konwersji skompresowanego strumienia multimediów do nieskompresowanego formatu nadającego się do wyświetlenia na ekranie i głośnikach. W urządzeniach mobilnych dekodowanie odbywa się albo programowo przez CPU, albo sprzętowo poprzez wyspecjalizowane bloki GPU i DSP. Według danych MDN Web Docs (2026), nowoczesne kodeki kompresują strumień 100–500 razy, a dekodowanie przywraca oryginalną jakość bez strat przy prawidłowym wyborze profilu kompresji.
Najważniejsze
Decoding to proces konwersji skompresowanych danych cyfrowych z powrotem do oryginalnego nieskompresowanego formatu. W kontekście multimediów dekodowanie przywraca klatki wideo ze skompresowanego strumienia bitów utworzonego przez enkoder. Bez dekodowania użytkownik nie może zobaczyć wideo ani usłyszeć dźwięku, ponieważ wszystkie nowoczesne formaty multimediów wykorzystują kompresję w celu oszczędzania przepustowości i miejsca na dysku.
Typowy strumień wideo w formacie H.264 przy przepływności 5 Mb/s zajmuje 100 razy mniej miejsca niż nieskompresowany strumień RGB o podobnej rozdzielczości. Algorytm dekodowania musi przywrócić każdą klatkę z powrotem do oryginalnej rozdzielczości i przestrzeni kolorów, postępując zgodnie ze specyfikacją kodeka w odwrotnej kolejności względem kodowania. W tym celu dekoder przetwarza dane wewnątrzklatkowe (I-frame) i międzyklatkowe (P-frame, B-frame).
Na urządzeniach mobilnych dekodowanie może odbywać się zarówno na CPU, jak i na dedykowanych blokach sprzętowych. Nowoczesne SoC od Apple (seria A), Qualcomm (Snapdragon) i MediaTek (Dimensity) zawierają wbudowane dekodery dla wszystkich popularnych formatów. Procesor wideo przejmuje ciężką pracę związaną z odwrotną dyskretną transformacją kosinusową i kompensacją ruchu, zwalniając CPU do innych zadań.
Proces dekodowania składa się z kilku kolejnych etapów, które odwracają kroki kodowania. Najpierw ze strumienia bitów wyodrębniane są nagłówki i parametry kompresji — profil, poziom, rozdzielczość, przestrzeń kolorów. Następnie dekoder sekwencyjnie przetwarza skompresowane makrobloki, stosując do nich odwrotne transformacje.
Pierwszy etap — wyodrębnienie kodu entropijnego. Dekodowanie entropijne wykorzystuje algorytmy CABAC lub CAVLC do odtworzenia współczynników dyskretnej transformacji kosinusowej. Ten etap nie zależy od rozdzielczości wideo — przetwarza strumień bitów, a nie pikseli, a jego złożoność określa przepływność, a nie rozmiar klatki.
Drugi etap — odwrotna kwantyzacja i odwrotna DCT. Dekoder mnoży skwantowane współczynniki przez krok kwantyzacji, przywracając przybliżone wartości współczynników DCT, a następnie stosuje odwrotną transformację DCT. Odwrotna DCT przywraca dane przestrzenne z domeny częstotliwości, tworząc makroblok pikseli. Dla chrominancji i luminancji transformacja wykonywana jest niezależnie.
Trzeci etap — kompensacja ruchu. Dla klatek P i B dekoder wykorzystuje wektory ruchu wyodrębnione ze strumienia bitów i odwołuje się do wcześniej zdekodowanych klatek referencyjnych. Kompensacja ruchu tworzy predyktor bieżącego makrobloku, do którego dodawany jest sygnał resztkowy po odwrotnej DCT. Wynik — w pełni przywrócona klatka gotowa do wyświetlenia.
// Pseudokod podstawowego dekodowania klatki wideo
struct DecodedFrame {
uint8_t* y_plane;
uint8_t* u_plane;
uint8_t* v_plane;
int width, height;
};
class Decoder {
public:
bool decodeNALUnit(const uint8_t* nalUnit, size_t size) {
if (!parseNALUHeader(nalUnit, size))
return false;
int sliceType = parseSliceType(nalUnit);
entropyDecode(nalUnit);
inverseQuantize();
inverseDCT();
if (sliceType != I_SLICE)
motionCompensation();
return true;
}
};
W powyższym przykładzie pokazana jest podstawowa struktura dekodera H.264. Funkcja decodeNALUnit przyjmuje jednostkę NAL — podstawowy blok skompresowanego strumienia H.264. Dekoder sekwencyjnie parsuje nagłówek, wyodrębnia typ slajsu, stosuje dekodowanie entropijne, odwrotną kwantyzację i odwrotną DCT. Dla slajsów P i B dodatkowo wykonywana jest kompensacja ruchu z wykorzystaniem klatek referencyjnych z bufora DPB.
Nowoczesne kodeki wideo różnią się algorytmami kompresji, wydajnością i wymaganiami dotyczącymi zasobów obliczeniowych. Wybór formatu bezpośrednio wpływa na rozmiar pliku, jakość obrazu i zużycie energii podczas dekodowania na urządzeniu mobilnym.
| Kodek | Rok | Kompresja | Wsparcie sprzętowe |
|---|---|---|---|
| H.264 | 2003 | 1:100 | Wszystkie nowoczesne SoC |
| H.265 | 2013 | 1:200 | Apple A8+, Snapdragon 805+ |
| VP9 | 2013 | 1:180 | Snapdragon 820+, Exynos |
| AV1 | 2018 | 1:300 | Apple A17+, Snapdragon 8 Gen 2+ |
H.264 to najpopularniejszy kodek wideo obsługiwany przez wszystkie urządzenia mobilne. Jego główną zaletą jest uniwersalność: każdy smartfon z Androidem i iPhone mogą dekodować H.264 sprzętowo. Jednak przy tej samej przepływności H.264 ustępuje jakością nowocześniejszym kodekom H.265 i AV1, wymagając o 30–50% większej przepływności dla analogicznej jakości wizualnej.
H.265 zapewnia dwukrotnie lepszą kompresję w porównaniu z H.264 przy tej samej jakości. Dekodowanie H.265 wymaga wydajniejszego bloku sprzętowego: VideoToolbox na iOS obsługuje H.265 od iPhone 6 (A8), a urządzenia z Androidem — od Snapdragon 805 i wyżej. Przy wyborze H.265 dla aplikacji mobilnej warto uwzględnić, że starsze urządzenia mogą nie mieć wsparcia sprzętowego i będą dekodować ten format programowo, co znacznie zwiększa zużycie energii.
AV1 to otwarty kodek od Alliance for Open Media, zapewniający najlepszą kompresję spośród wszystkich nowoczesnych formatów. AV1 jest o 30% wydajniejszy niż H.265 i o 50% wydajniejszy niż H.264 przy tej samej jakości wizualnej. Sprzętowe dekodowanie AV1 pojawiło się dopiero w SoC z 2023+ lat: Apple A17 Pro, Qualcomm Snapdragon 8 Gen 2 i nowsze. Dla starszych urządzeń dekodowanie AV1 jest możliwe tylko programowo przez bibliotekę dav1d, co powoduje znaczne obciążenie CPU.
Wybór między dekodowaniem programowym a sprzętowym to kluczowa decyzja architektoniczna przy tworzeniu mobilnego odtwarzacza multimediów. Każde podejście ma swoje zalety i ograniczenia, które należy uwzględnić podczas projektowania aplikacji.
Dekodowanie sprzętowe odbywa się na wyspecjalizowanych blokach przetwarzania wideo, które zużywają znacznie mniej energii niż CPU przy wykonywaniu tego samego zadania. Według danych Qualcomm, sprzętowy dekoder H.265 zużywa 5–10 razy mniej energii niż dekodowanie programowe na CPU Snapdragon 8 Gen 1 przy odtwarzaniu wideo 4K. Jest to krytyczne dla urządzeń mobilnych, gdzie każdy miliwat wpływa na czas pracy na baterii.
Dekodowanie programowe z kolei daje maksymalną elastyczność. FFmpeg z biblioteką libavcodec obsługuje dziesiątki kodeków i kontenerów, w tym rzadkie i przestarzałe formaty, które nie mają wsparcia sprzętowego. Deweloper może modyfikować potok dekodowania, dodawać postprocessing i filtry w locie, co jest niemożliwe przy użyciu zamkniętych bloków sprzętowych.
Dekodowanie programowe jest uzasadnione w kilku scenariuszach: przy odtwarzaniu rzadkich formatów (ProRes, DNxHD, Motion JPEG), gdy potrzebna jest precyzyjna kontrola nad każdym etapem przetwarzania klatki, a także przy dekodowaniu AV1 na urządzeniach bez wsparcia sprzętowego. libavcodec z pakietu FFmpeg pozwala dekodować praktycznie każdy znany format, co czyni go standardem de facto dla uniwersalnych odtwarzaczy multimediów.
Ograniczeniem dekodowania programowego jest wydzielanie ciepła. Ciągłe dekodowanie wideo 4K na CPU może nagrzać urządzenie do 45–50 stopni w ciągu 10–15 minut, co prowadzi do throttlingu i spadku liczby klatek na sekundę. Na urządzeniach bez aktywnego chłodzenia (tablety, telefony) jest to szczególnie widoczne. Pobór mocy CPU przy dekodowaniu programowym może sięgać 3–5 W w porównaniu do 0,3–0,5 W przy dekodowaniu sprzętowym tego samego strumienia.
Dekodowanie sprzętowe to domyślny wybór dla każdego produkcyjnego odtwarzacza multimediów. Zapewnia stabilne 60 klatek/s dla wideo 4K przy minimalnym zużyciu energii. VideoToolbox na iOS i MediaCodec na Androidzie udostępniają natywne API do dekodowania sprzętowego, które automatycznie wybiera optymalny blok przetwarzania w zależności od kodeka i rozdzielczości.
API platformowe przejmują zarządzanie buforami klatek (surface pool na Androidzie, CVPixelBufferPool na iOS), synchronizację z wyświetlaczem i optymalizację pamięci. Deweloper musi jedynie otworzyć dekoder z odpowiednimi parametrami i odbierać gotowe klatki. Dekodowanie sprzętowe obsługuje potok end-to-end z minimalnym opóźnieniem: od otrzymania strumienia bitów do wyświetlenia na ekranie mija 5–15 ms w porównaniu do 30–80 ms przy dekodowaniu programowym.
Rozważmy praktyczną implementację dekodowania na obu platformach mobilnych. Na iOS dekodowanie sprzętowe odbywa się przez VideoToolbox, a programowe — przez FFmpeg. Na Androidzie używany jest MediaCodec do dekodowania sprzętowego.
@interface VideoDecoder ()
@property (nonatomic) VTDecompressionSessionRef session;
@end
@implementation VideoDecoder
- (void)setupDecoder {
CMVideoFormatDescriptionRef formatDesc;
CMVideoCodecType codecType = kCMVideoCodecType_H264;
OSStatus status = CMVideoFormatDescriptionCreate(
NULL, codecType, 1920, 1080, NULL, &formatDesc
);
VTDecompressionOutputCallbackRecord callback;
callback.decompressionOutputCallback = &decodingCallback;
VTDecompressionSessionCreate(NULL, formatDesc, NULL,
NULL, &callback, &_session);
}
- (void)decodeFrame: (uint8_t*)nalData length:(size_t)size {
CMBlockBufferRef blockBuffer;
CMBlockBufferCreateWithMemoryBlock(NULL, nalData,
size, NULL, NULL, 0, size, 0, &blockBuffer);
CMSampleBufferRef sampleBuffer;
CMSampleBufferCreate(NULL, blockBuffer, true, NULL,
NULL, NULL, 1, 0, NULL, 0, NULL, &sampleBuffer);
VTDecompressionSessionDecodeFrame(_session,
sampleBuffer, 0, NULL, 0);
}
@end
Kod demonstruje inicjalizację sprzętowego dekodera H.264 na iOS. VTDecompressionSessionCreate tworzy sesję dekodowania, a VTCreate wywołuje callback po pojawieniu się gotowej klatki. Sesja automatycznie używa bloku sprzętowego, jeśli jest dostępny dla określonego kodeka. Do odbierania zdekodowanych klatek w formacie CVPixelBuffer używany jest callback, który przekazuje każdą gotową klatkę z minimalnym opóźnieniem.
MediaCodec decoder = MediaCodec.createDecoderByType("video/avc");
MediaFormat format = MediaFormat.createVideoFormat(
"video/avc", 1920, 1080
);
format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
decoder.configure(format, surface, null, 0);
decoder.start();
ByteBuffer[] inputBuffers = decoder.getInputBuffers();
int inputIndex = decoder.dequeueInputBuffer(10000);
if (inputIndex >= 0) {
ByteBuffer buffer = inputBuffers[inputIndex];
buffer.clear();
buffer.put(nalData);
decoder.queueInputBuffer(inputIndex, 0, nalData.length, pts, 0);
}
Na Androidzie MediaCodec używa do wyjścia Surface, a nie bufora pikseli, co minimalizuje kopiowanie danych między GPU a CPU. Dekoder automatycznie wybiera blok sprzętowy (komponent OMX) na podstawie typu kodeka. Dla H.264 używany jest OMX.google.h264.decoder, który może być zarówno sprzętowy, jak i programowy w zależności od implementacji producenta.
Wybór strategii dekodowania zależy od docelowej grupy odbiorców aplikacji, obsługiwanych formatów i wymagań dotyczących wydajności. Optymalne rozwiązanie często obejmuje podejście hybrydowe: dekodowanie sprzętowe dla głównych formatów (H.264, H.265) z programowym fallbackiem dla rzadkich kodeków.
Jeśli aplikacja jest przeznaczona dla maksymalnej zgodności — używaj H.264, który gwarantuje sprzętowe dekodowanie na każdym urządzeniu. Dla serwisów strumieniowania wideo uzasadniony jest H.265 ze wsparciem sprzętowym na urządzeniach po 2016 roku. AV1 to wybór dla serwisów, gdzie ważna jest oszczędność przepustowości: YouTube, Netflix i inne duże platformy aktywnie wdrażają AV1 w celu obniżenia kosztów CDN przy zachowaniu jakości.
Krytycznym parametrem jest rozmiar bufora dekodera. Sprzętowe dekodery mają stałą pulę buforów (zwykle 4–16 klatek). Przy odtwarzaniu strumienia o wysokiej przepływności bufory mogą się przepełnić, co doprowadzi do pomijania klatek. MediaCodec udostępnia metodę getOutputFrameRate do określenia rzeczywistej wydajności dekodera na konkretnym urządzeniu, a VideoToolbox pozwala kontrolować priorytet czasu rzeczywistego przez kVTDecodeFrame_EnableAsynchronousDecompression.
Throttling termiczny to kolejny czynnik. Nawet sprzętowe dekodowanie może nagrzewać urządzenie podczas długotrwałego odtwarzania wideo 4K HDR. Zaleca się monitorowanie temperatury przez ProcessInfo na iOS i BatteryManager na Androidzie, obniżając jakość lub rozdzielczość strumienia przy przegrzaniu. Jest to szczególnie krytyczne dla gier i aplikacji strumieniowych z długimi sesjami oglądania.
Często zadawane pytania
Kodowanie (encoding) przekształca nieskompresowane dane do skompresowanego formatu, a dekodowanie (decoding) przywraca oryginalne dane ze skompresowanego strumienia. Te procesy są względem siebie odwrotne i wykorzystują te same algorytmy: DCT, kwantyzację, kompensację ruchu. Enkoder wykonuje przekształcenie bezpośrednie, dekoder — odwrotne.
Dla maksymalnej zgodności — H.264, ponieważ jest sprzętowo dekodowany na 100% nowoczesnych urządzeń. Dla lepszej kompresji — H.265 lub AV1. Wybór zależy od grupy docelowej: jeśli 80% użytkowników ma urządzenia z 2021+ lat, H.265 zapewni lepszą jakość przy niższej przepływności. AV1 jest uzasadniony dla flagowych urządzeń ze wsparciem sprzętowym 2023+ lat.
Dekoder sprzętowy to wyspecjalizowany układ (ASIC) zaprojektowany wyłącznie do dekodowania. W przeciwieństwie do CPU, który wykonuje dekodowanie za pomocą sekwencyjnych instrukcji, blok sprzętowy przetwarza makrobloki równolegle. Zużycie energii dekodera sprzętowego jest 5–10 razy niższe, ponieważ układ pracuje na niższej częstotliwości i nie ma zbędnych etapów potoku.
Profil (profile) określa zestaw algorytmów kompresji używanych przez enkoder: Baseline, Main, High. Poziom (level) określa maksymalne parametry strumienia: rozdzielczość, przepływność, rozmiar bufora. Dla urządzeń mobilnych zalecany jest profil High i poziom 4.1–5.2 — to wystarcza dla wideo 1080p–4K ze sprzętowym dekodowaniem.
Na Androidzie użyj MediaCodecList, aby uzyskać listę dostępnych kodeków i sprawdzić, który z nich jest sprzętowy. Na iOS sprawdź wsparcie przez CMVideoFormatDescription z określonym kodekiem — jeśli VTDecompressionSessionCreate jest pomyślne, kodek jest obsługiwany. Dla AV1 na Androidzie sprawdź obecność kodeka OMX.google.aomc.decoder lub jego sprzętowej wersji.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również