デコードとは、圧縮されたメディアストリームを画面やスピーカーに出力可能な非圧縮形式に変換するプロセスです。モバイルデバイスでは、デコードはCPUを介したソフトウェア方式、または専用のGPUやDSPブロックを介したハードウェア方式で実行されます。MDN Web Docs (2026)によると、最新のコーデックはストリームを100~500倍に圧縮し、デコードは適切な圧縮プロファイルを選択することで損失なく元の品質を復元します。
重要なポイント
デコードとは、圧縮されたデジタルデータを元の非圧縮形式に戻すプロセスです。メディアの文脈では、デコードはエンコーダによって生成された圧縮ビットストリームからビデオフレームを復元します。デコードがなければ、ユーザーはビデオを見たりオーディオを聞いたりできません。なぜなら、すべての最新メディア形式は帯域幅とディスク容量を節約するために圧縮を使用しているからです。
H.264形式の5Mbpsの一般的なビデオストリームは、同じ解像度の非圧縮RGBストリームよりも100倍少ない容量しか占有しません。デコードアルゴリズムは、エンコードとは逆順でコーデック仕様に従い、各フレームを元の解像度と色空間に復元する必要があります。そのために、デコーダはフレーム内(Iフレーム)とフレーム間(Pフレーム、Bフレーム)のデータを処理します。
モバイルデバイスでは、デコードはCPUまたは専用のハードウェアブロックのいずれかで行われます。Apple(Aシリーズ)、Qualcomm(Snapdragon)、MediaTek(Dimensity)の最新SoCには、すべての一般的な形式に対応した内蔵デコーダが搭載されています。ビデオプロセッサは、逆離散コサイン変換と動き補償という負荷の高い処理を担当し、CPUを他のタスクに解放します。
デコードプロセスは、エンコードの各ステップを逆にする複数の連続した段階で構成されます。最初に、ビットストリームからヘッダと圧縮パラメータ(プロファイル、レベル、解像度、色空間)が抽出されます。次に、デコーダは圧縮されたマクロブロックを順次処理し、逆変換を適用します。
第一段階はエントロピーコードの抽出です。エントロピーデコードは、CABACまたはCAVLCアルゴリズムを使用して離散コサイン変換係数を復元します。この段階はビデオ解像度に依存しません。ピクセルではなくビットのストリームを処理し、その複雑さはフレームサイズではなくビットレートによって決まります。
第二段階は逆量子化と逆DCTです。デコーダは量子化された係数に量子化ステップを乗算し、おおよそのDCT係数値を復元した後、逆DCT変換を適用します。逆DCTは周波数領域から空間データを復元し、ピクセルのマクロブロックを形成します。クロマとルマでは変換が独立して実行されます。
第三段階は動き補償です。PフレームとBフレームの場合、デコーダはビットストリームから抽出された動きベクトルを使用し、以前にデコードされた参照フレームを参照します。動き補償は現在のマクロブロックの予測子を作成し、逆DCT後の残差信号が加算されます。結果は、出力準備の整った完全に復元されたフレームです。
// ビデオフレームデコードの基本擬似コード
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;
}
};
上記の例は、H.264デコーダの基本構造を示しています。decodeNALUnit関数は、NALユニット(圧縮H.264ストリームの基本ブロック)を受け取ります。デコーダはヘッダを順次解析し、スライスタイプを抽出し、エントロピーデコード、逆量子化、逆DCTを適用します。PスライスとBスライスの場合は、DPBバッファからの参照フレームを使用して動き補償が追加で実行されます。
最新のビデオコーデックは、圧縮アルゴリズム、効率性、計算リソース要件が異なります。形式の選択は、ファイルサイズ、画質、モバイルデバイスでのデコード時の消費電力に直接影響します。
| コーデック | 年 | 圧縮率 | ハードウェアサポート |
|---|---|---|---|
| H.264 | 2003 | 1:100 | すべての最新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は最も普及しているビデオコーデックで、すべてのモバイルデバイスでサポートされています。その主な利点は汎用性です。どのAndroidスマートフォンやiPhoneでもH.264をハードウェアデコードできます。ただし、同じビットレートでは、H.264はH.265やAV1などのより最新のコーデックに画質で劣り、同等の視覚品質を得るには30~50%多くのビットレートが必要です。
H.265は同じ品質でH.264の2倍の圧縮率を提供します。H.265のデコードにはより強力なハードウェアブロックが必要です。iOSのVideoToolboxはiPhone 6(A8)以降でH.265をサポートし、AndroidデバイスはSnapdragon 805以降でサポートしています。モバイルアプリにH.265を選択する場合、古いデバイスではハードウェアサポートがなく、ソフトウェアでこの形式をデコードすることになり、消費電力が急増することに注意が必要です。
AV1はAlliance for Open Mediaによるオープンコーデックで、すべての最新形式の中で最高の圧縮率を提供します。AV1は同じ視覚品質でH.265より30%、H.264より50%効率的です。ハードウェアAV1デコードは2023年以降のSoC(Apple A17 Pro、Qualcomm Snapdragon 8 Gen 2以降)でのみ登場しました。古いデバイスでは、AV1デコードはdav1dライブラリを介したソフトウェアでのみ可能で、CPUに大きな負荷がかかります。
ソフトウェアデコードとハードウェアデコードの選択は、モバイルメディアプレーヤーを開発する際の重要なアーキテクチャ上の判断です。各アプローチには長所と制限があり、アプリケーション設計時に考慮する必要があります。
ハードウェアデコードは専用のビデオ処理ブロックで実行され、同じタスクを実行するCPUよりも大幅に少ないエネルギーで済みます。Qualcommによると、4Kビデオ再生時、ハードウェアH.265デコーダはSnapdragon 8 Gen 1 CPUでのソフトウェアデコードより5~10倍少ないエネルギー消費です。これは、1ミリワットがバッテリー寿命に影響するモバイルデバイスにとって重要です。
一方、ソフトウェアデコードは最大の柔軟性を提供します。FFmpegとlibavcodecライブラリは、ハードウェアサポートのない希少な形式や旧式の形式を含む数十のコーデックとコンテナをサポートしています。開発者はデコードパイプラインを変更し、リアルタイムで後処理やフィルタを追加できます。これはクローズドなハードウェアブロックを使用する場合には不可能です。
ソフトウェアデコードはいくつかのシナリオで正当化されます。希少な形式(ProRes、DNxHD、Motion JPEG)の再生時、フレーム処理の各段階を精密に制御する必要がある場合、ハードウェアサポートのないデバイスでのAV1デコード時などです。FFmpegのlibavcodecは事実上あらゆる既知の形式をデコードでき、汎用メディアプレーヤーのデファクトスタンダードとなっています。
ソフトウェアデコードの制限は放熱です。CPUでの継続的な4Kビデオデコードは、10~15分でデバイスを45~50度に加熱し、スロットリングとフレームレート低下を引き起こします。アクティブ冷却のないデバイス(タブレット、電話)では特に顕著です。ソフトウェアデコード中のCPU消費電力は、同じストリームのハードウェアデコード中の0.3~0.5Wに対して3~5Wに達する可能性があります。
ハードウェアデコードは、プロダクションメディアプレーヤーのデフォルトの選択肢です。最小限の消費電力で4Kビデオの安定した60fpsを提供します。iOSのVideoToolboxとAndroidのMediaCodecは、コーデックと解像度に応じて最適な処理ブロックを自動選択するハードウェアデコード用のネイティブAPIを提供します。
プラットフォームAPIは、フレームバッファ管理(Androidのsurface pool、iOSのCVPixelBufferPool)、ディスプレイ同期、メモリ最適化を処理します。開発者は必要なパラメータでデコーダを開き、準備完了したフレームを受け取るだけで済みます。ハードウェアデコードは低レイテンシのエンドツーエンドパイプラインをサポートします。ビットストリーム受信から画面表示まで5~15msで、ソフトウェアデコードの30~80msに対して優位です。
両方のモバイルプラットフォームでのデコードの実装例を見てみましょう。iOSでは、ハードウェアデコードはVideoToolboxを介して、ソフトウェアデコードはFFmpegを介して行われます。Androidでは、ハードウェアデコードにMediaCodecが使用されます。
@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
このコードは、iOSでのH.264ハードウェアデコーダの初期化を示しています。VTDecompressionSessionCreateはデコードセッションを作成し、VTCreateはフレーム準備完了時にコールバックを呼び出します。セッションは、指定されたコーデックで利用可能な場合、自動的にハードウェアブロックを使用します。CVPixelBuffer形式でデコードされたフレームを取得するには、各準備完了フレームを最小遅延で渡すコールバックが使用されます。
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);
}
Androidでは、MediaCodecはピクセルバッファではなくSurfaceを出力に使用し、GPUとCPU間のデータコピーを最小限に抑えます。デコーダはコーデックタイプに基づいて自動的にハードウェアブロック(OMXコンポーネント)を選択します。H.264にはOMX.google.h264.decoderが使用され、これはメーカーの実装に応じてハードウェアまたはソフトウェアになります。
デコード戦略の選択は、アプリケーションのターゲットユーザー、サポートする形式、パフォーマンス要件によって決まります。最適なソリューションには、主要形式(H.264、H.265)のハードウェアデコードと、希少なコーデック用のソフトウェアフォールバックを組み合わせたハイブリッドアプローチが含まれます。
アプリケーションが最大互換性を目指す場合は、どのデバイスでもハードウェアデコードが保証されているH.264を使用します。ビデオストリーミングサービスでは、2016年以降のデバイスでハードウェアサポートのあるH.265が適しています。AV1は帯域幅節約が重要なサービス向けの選択肢です。YouTube、Netflix、その他大手プラットフォームは、品質を維持しながらCDNコストを削減するためにAV1を積極的に採用しています。
重要なパラメータはデコーダのバッファサイズです。ハードウェアデコーダには固定のバッファプール(通常4~16フレーム)があります。高ビットレートストリーム再生時にバッファがオーバーフローし、フレームドロップが発生する可能性があります。MediaCodecは特定のデバイスでの実際のデコーダパフォーマンスを判断するgetOutputFrameRateメソッドを提供し、VideoToolboxはkVTDecodeFrame_EnableAsynchronousDecompressionを介してリアルタイム優先度を制御できます。
サーマルスロットリングも要因です。長時間の4K HDRビデオ再生では、ハードウェアデコードでもデバイスが発熱する可能性があります。iOSのProcessInfoやAndroidのBatteryManagerで温度を監視し、オーバーヒート時に品質やストリーム解像度を下げることを推奨します。これは、長時間の視聴セッションがあるゲームやストリーミングアプリケーションで特に重要です。
よくある質問
エンコードは非圧縮データを圧縮形式に変換し、デコードは圧縮ストリームから元のデータを復元します。これらのプロセスは互いに逆であり、DCT、量子化、動き補償といった同じアルゴリズムを使用します。エンコーダは順方向の変換を実行し、デコーダは逆方向を実行します。
最大互換性にはH.264。最新デバイスの100%でハードウェアデコードされます。より良い圧縮にはH.265またはAV1。ユーザーの80%が2021年以降のデバイスを使用している場合、H.265は低ビットレートでより良い品質を提供します。AV1は2023年以降のハードウェアサポートがあるフラッグシップデバイスに適しています。
ハードウェアデコーダはデコード専用に設計された特殊なマイクロチップ(ASIC)です。逐次命令でデコードを実行するCPUとは異なり、ハードウェアブロックはマクロブロックを並列処理します。ハードウェアデコーダの消費電力は5~10倍低いです。なぜなら、チップが低周波数で動作し、不要なパイプラインステージがないからです。
プロファイルはエンコーダが使用する圧縮アルゴリズムのセット(Baseline、Main、High)を定義します。レベルは最大ストリームパラメータ(解像度、ビットレート、バッファサイズ)を設定します。モバイルデバイスには、Highプロファイルとレベル4.1~5.2が推奨されます。これでハードウェアデコードによる1080p~4Kビデオに十分対応できます。
Androidでは、MediaCodecListを使用して利用可能なコーデックの一覧を取得し、どれがハードウェアかを確認します。iOSでは、指定したコーデックでCMVideoFormatDescriptionを使用してサポートを確認します。VTDecompressionSessionCreateが成功すればコーデックはサポートされています。AndroidのAV1については、OMX.google.aomc.decoderコーデックまたはそのハードウェア版の存在を確認します。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。