diff --git a/japanese/README-ja.md b/japanese/README-ja.md index e228bb8..04fa709 100644 --- a/japanese/README-ja.md +++ b/japanese/README-ja.md @@ -2,11 +2,11 @@ # はじめに -ビデオ技術のやさしい入門書です。ソフトウェア開発者/エンジニア向けですが、**誰でも理解できるように**やさしく説明したいと思っています。 [ビデオ技術初心者のためのミニワークショップ](https://docs.google.com/presentation/d/17Z31kEkl_NGJ0M66reqr9_uTG6tI5EDDVXpdPKVuIrs/edit#slide=id.p)からこのアイディアが生まれました。. +ビデオ技術のやさしい入門書です。ソフトウェア開発者/エンジニア向けですが、**誰でも理解できるように**やさしく説明したいと思っています。 [ビデオ技術初心者のためのミニワークショップ](https://docs.google.com/presentation/d/17Z31kEkl_NGJ0M66reqr9_uTG6tI5EDDVXpdPKVuIrs/edit#slide=id.p)からこのアイディアが生まれました。 できるだけ**簡潔な言葉、たくさんの視覚的要素、実質的な例**を使っていくつかのデジタルビデオの概念を紹介し、誰でもこの知識を得る機会を提供することが目標です。どうかご自由に訂正や提案を送ったり、改善したりしてください。 -いくつかの**ハンズオン** セクションでは**dockerがインストール**されて、このレポジトリをクーロンされていることが必要になります。 +いくつかの**ハンズオン** セクションでは**dockerがインストール**されて、このレポジトリがクローンされていることが必要です。 ```bash git clone https://github.com/leandromoreira/digital_video_introduction.git @@ -15,7 +15,7 @@ cd digital_video_introduction ``` > **注意**: `./s/ffmpeg` や `./s/mediainfo` コマンドを見ることがありますが、これらのプログラムの **コンテナ化版** を実行していることを意味します。これらはすでに全ての必要条件を満たしています。 -全ての**ハンズオンはこのレポジトリをクーロンしたフォルダで実行すべきです**。 **jupyter examples**については、`./s/start_jupyter.sh`でサーバーを起動して、URLをコピーして、ブラウザでそれを使う必要があります。 +全ての**ハンズオンはこのレポジトリをクローンしたフォルダで実行してください**。 **jupyter examples**については、`./s/start_jupyter.sh`でサーバーを起動して、URLをコピーして、ブラウザにそれを入力してください。 # 変更履歴 @@ -82,11 +82,11 @@ cd digital_video_introduction **画像**は**二次元マトリクス**として考えることができます。**色**を考慮すると、画像を**色のデータ**を表すための**もう一つの次元**を持った**三次元マトリクス**として捉えることができます。 -これらの色を[原色 (赤、緑、青)](https://ja.wikipedia.org/wiki/%E5%8E%9F%E8%89%B2)で表現することにすると、三つの平面を定義することになります。一つめが**赤**、二つ目が**緑**そして3つ目が**青**色です。 +これらの色を[原色 (赤、緑、青)](https://ja.wikipedia.org/wiki/%E5%8E%9F%E8%89%B2)で表現すると、三つの平面を定義することになります。一つめが**赤**、二つ目が**緑**そして三つ目が**青**色です。 ![an image is a 3d matrix RGB](/i/image_3d_matrix_rgb.png "画像は三次元マトリクスです") -マトリクスのそれぞれの要素を**ピクセル** (画素)と呼びます。. 一つのピクセルはその色の**輝度** (通常は数値)を表します。例えば、**赤ピクセル**は緑が0、青が0、赤が最大を意味します。**ピンク色ピクセル**はこれら三つの値から成り立っています。0から255の数値で表現することにより、ピンクピクセルは**赤=255、緑=192、青=203**と定義されます。 +マトリクスのそれぞれの要素を**ピクセル** (画素)と呼びます。一つのピクセルはその色の**輝度** (通常は数値)を表します。例えば、**赤ピクセル**は緑が0、青が0、赤が最大を意味します。**ピンク色ピクセル**もこれら三つの値で表現できます。0から255の数値で表現することにより、ピンクピクセルは**赤=255、緑=192、青=203**と定義されます。 > #### カラー画像を符号化する別の方法 > 画像を形成する色を表現するためには、他にも多くのモデルが使えます。例えば、色を表現するのにRGBモデルでは3バイト使うのに対して、1バイトしか使わないインデックスパレットを使うことができます。そういったモデルでは、色を表現するために三次元モデルを使わずに二次元モデルを使用できるできるでしょう。メモリを節約できますが、色の選択肢を狭めることになります。 @@ -103,18 +103,18 @@ cd digital_video_introduction > [画像がどのように万物をビットとしてとらえるのか](http://www.cambridgeincolour.com/tutorials/camera-sensors.htm)を学ぶと **良い**でしょう -もう一つの画像のプロパティは **解像度**です。解像度は長さがあたりのピクセルの数です。解像度はよく幅 x 高さとして表現されます。例えば、下記は**4×4**の画像です。 +もう一つの画像のプロパティは **解像度**です。解像度は長さあたりのピクセルの数です。解像度はよく幅 x 高さとして表現されます。例えば、下記は**4×4**の画像です。 ![image resolution](/i/resolution.png "画像解像度") > #### ハンズオン: 画像と色の実験 -> [jupyter](#how-to-use-jupyter) (python、numpy、matplotlib、その他)を使って、[画像と色の実験](/image_as_3d_array.ipynb)ができます。 +> [jupyter](#jupyterの使い方) (python、numpy、matplotlib、その他)を使って、[画像と色の実験](/image_as_3d_array.ipynb)をしましょう。 > -> [(エッジ検出, シャープ化, ぼかし等の)画像フィルタがどのように動くか](/filters_are_easy.ipynb)を学ぶことができます。 +> [(エッジ検出, シャープ化, ぼかし等の)画像フィルタがどのように動くか](/filters_are_easy.ipynb)を学びましょう。 画像やビデオの作業をする時にみるもう一つのプロパティは **アスペクト比**です。アスペクト比は、画像やピクセルの幅と高さの比率を表します。 -動画や画像が**16x9**であると言うときは、たいてい**画面アスペクト比 (DAR)**のことを指します。しかし、個々のピクセルを様々な形状にすることができ、これを **ピクセルアスペクト比 (PAR)**といいます。 +動画や画像が**16x9**であると言うときは、たいてい**画面アスペクト比 (DAR)** のことを指します。しかし、個々のピクセルを様々な形状にすることができ、これを **ピクセルアスペクト比 (PAR)** といいます。 ![display aspect ratio](/i/DAR.png "画面アスペクト比") @@ -123,7 +123,7 @@ cd digital_video_introduction > #### DVDの画面アスペクト比は4:3 > DVDの実際の解像度は704x480ですが、10:11のピクセルアスペクト比を持っているため、4:3のアスペクト比を保っています。(704x10/480x11) -最後に、**ビデオ**を**単位時間**内の** *n*フレームの並び**として定義でき、もう一つの特性と見ることができます。*n*はフレームレートもしくは秒間フレーム数 (FPS)です。 +最後に、**ビデオ**を**単位時間**内の***n*フレームの並び**として定義でき、もう一つの特性と見ることができます。*n*はフレームレートもしくは秒間フレーム数 (FPS)です。 ![video](/i/video.png "ビデオ") @@ -139,7 +139,7 @@ cd digital_video_introduction > > ![constrained vbr](/i/vbr.png "制約付きのvbr") -黎明期に、技術者たちが**帯域幅を増やさずに**ビデオ画面で認識できるフレームレートを倍にする技術を思いつきました。この技術は**インターレース動画**として知られています。基本的には1「フレーム」中で画面の半分を送り、次の「フレーム」で残りの半分を送ります。 +黎明期に、技術者たちが**帯域幅を増やさずに**ビデオ画面で認識できるフレームレートを倍にする技術を思いつきました。この技術は**インターレース動画**として知られています。基本的には一つ目の「フレーム」中で画面の半分を送り、次の「フレーム」で残りの半分を送ります。 今日では **プログレッシブスキャン技術**を使って画面に描画されます。プログレッシブは、動く画像を描画、保存、転送する手段の一つで、各フレームの全走査線を順番に描画します。 @@ -166,11 +166,11 @@ cd digital_video_introduction 左側の**正方形Aと正方形B**の色は**同じ**であることが分からないとしても大丈夫です。私たちの脳は**色よりも明暗に注意をはらう**ことで錯覚を起こさせているのです。右側では、同じ色のコネクターがあるため、私たち(私たちの脳)は、それらは実際は同じ色であるということを簡単に気づきます。 -> **Simplistic explanation of how our eyes work** +> **私たちの目がどのように機能するかの簡単な説明** > > [眼は複雑な器官](http://www.biologymad.com/nervoussystem/eyenotes.htm)で、たくさんのパーツから成り立っていますが、主に錐体細胞と桿体細胞に関心があります。眼は [1億2000万の桿体細胞と600万の錐体細胞を含んでいる](https://en.wikipedia.org/wiki/Photoreceptor_cell)のです。 > -> **ものすごく簡単にする**ため、眼のパーツの機能のうち色と明るさに焦点を当てましょう。**[桿体細胞](https://en.wikipedia.org/wiki/Rod_cell)は主に明るさに対して責任を持っています**。一方**[錐体細胞](https://en.wikipedia.org/wiki/Cone_cell)は色に対して責任を持っています**。異なった色素を持つ3種類の錐体があり、名前は[S錐体(青)、M錐体(緑)、L錐体(赤)](https://upload.wikimedia.org/wikipedia/commons/1/1e/Cones_SMJ2_E.svg)です。 +> **ものすごく簡単にする**ため、眼のパーツの機能のうち色と明るさに焦点を当てましょう。**[桿体細胞](https://en.wikipedia.org/wiki/Rod_cell)は主に明るさに対して責任を持っています**。一方 **[錐体細胞](https://en.wikipedia.org/wiki/Cone_cell)は色に対して責任を持っています**。異なった色素を持つ3種類の錐体があり、名前は[S錐体(青)、M錐体(緑)、L錐体(赤)](https://upload.wikimedia.org/wikipedia/commons/1/1e/Cones_SMJ2_E.svg)です。 > > 私たちは錐体細胞(色)よりも多くの桿体細胞(明るさ)を持っているため、色よりも明暗をより識別することができることが推論できます。 > @@ -190,9 +190,9 @@ cd digital_video_introduction ### YCbCrとRGB間の変換 -中には **緑なしで色**の全てを生成できるかと異議を唱える方もいるでしょう。 +中には **緑なしで色**の全てを生成できるのかと異議を唱える方もいるでしょう。 -この質問に答えるために、RGBからYCbCrへの変換を一通り説明します。**[ITU-Rグループ*](https://en.wikipedia.org/wiki/ITU-R)**によって推奨される**[BT.601標準](https://en.wikipedia.org/wiki/Rec._601)**からの係数を使います。最初のステップは、**輝度を計算する**ことです。ITUに提案されている定数を使い、RGB値を置き換えます。 +この質問に答えるために、RGBからYCbCrへの変換を一通り説明します。**[ITU-Rグループ*](https://en.wikipedia.org/wiki/ITU-R)** によって推奨される **[BT.601標準](https://en.wikipedia.org/wiki/Rec._601)** からの係数を使います。最初のステップは、**輝度を計算する**ことです。ITUに提案されている定数を使い、RGB値を置き換えます。 ``` Y = 0.299R + 0.587G + 0.114B @@ -213,7 +213,7 @@ B = Y + 1.772Cb G = Y - 0.344Cb - 0.714Cr ``` -> * グループと標準はデジタルビデオではよくあることです。彼らは何が標準なのかを定義します。例えば[4Kとは何か?どのフレームレート、解像度、カラーモデルを使うべきか?](https://en.wikipedia.org/wiki/Rec._2020)などです。 +> * グループや標準はデジタルビデオではよくでてきます。彼らは何が標準なのかを定義します。例えば[4Kとは何か?どのフレームレート、解像度、カラーモデルを使うべきか?](https://en.wikipedia.org/wiki/Rec._2020)などです。 一般的に**ディスプレイ** (モニター、テレビ、スクリーン等) は色々な方法で組織化された**RGBモデルだけ**を利用します。下の写真でいくつか拡大したもの示しています。 @@ -267,7 +267,7 @@ G = Y - 0.344Cb - 0.714Cr ![ball 1](/i/smw_background_ball_1.png "ボール1") ![ball 2](/i/smw_background_ball_2.png "ボール2") ![ball 3](/i/smw_background_ball_3.png "ボール3") ![ball 4](/i/smw_background_ball_4.png "ボール4") -**青い背景**のようにフレーム間に**たくさんの繰り返し**を見ることができます。背景はフレーム0からフレーム3まで変化しません。この問題に取り組むために、これらを3種類のフレームに**抽象的に分類する**ことができます。 +**青い背景**のようにフレーム間に**たくさんの繰り返し**を見ることができます。背景はフレーム0からフレーム3まで変化しません。この問題に取り組むために、これらを3種類のフレームに**抽象的に分類**しましょう。 ### Iフレーム (イントラ、キーフレーム) @@ -284,7 +284,7 @@ Iフレーム(参照、キーフレーム、イントラ)は**自己完結的な > #### ハンズオン: Iフレームが1つだけのビデオ > Pフレームはより小さなデータしか使わないので、全体を[Iフレームは1つだけで、他は全てPフレームのビデオ](/encoding_pratical_examples.md#1-i-frame-and-the-rest-p-frames)にエンコードしたらどうでしょう? > -> このビデオをエンコードした後、再生してビデオの**前方にシーク**してください。シーク先に移るのに**時間がかかる**ことに気づくでしょう。これは、描画ために**Pフレームが参照フレームを必要とする** (例えばIフレーム)ためです。 +> このビデオをエンコードした後、再生してビデオの**前方にシーク**してください。シーク先に移るのに**時間がかかる**ことに気づくでしょう。これは、描画のために**Pフレームが参照フレームを必要とする** (例えばIフレーム)ためです。 > > もう1つ手軽にできるテストとして、まず1つのI-Frameだけを使ってビデオをエンコードして、次に[2秒間隔でIフレームを挿入してエンコード](/encoding_pratical_examples.md#1-i-frames-per-second-vs-05-i-frames-per-second)してから、**それぞれのエンコード結果のサイズを比較**してください。 @@ -308,7 +308,7 @@ Iフレーム(参照、キーフレーム、イントラ)は**自己完結的な **時間的繰り返し**を削減するために何ができるか見ていきましょう。この種の冗長性は**インター予測**という技術で解決することができます。 -**できるだけ少ないビットを使って**、連続したフレーム0とフレーム1をエンコードして見ましょう。 +**できるだけ少ないビットを使って**、連続したフレーム0とフレーム1をエンコードしてみましょう。 ![original frames](/i/original_frames.png "元のフレーム") @@ -325,9 +325,9 @@ Iフレーム(参照、キーフレーム、イントラ)は**自己完結的な ボールが`x=0、y=25`から`x=6、y=26`へ移動したと推定することができます。**x**と**y**の値は**動きベクトル**です。ビットを節約するためのもう1つの**さらなるステップ**は、前回のブロック位置と予測されるブロック位置との**動きベクトルの差分だけをエンコードする**ことです。 最終的な動きベクトルは`x=6 (6-0)、y=1 (26-25)`のようになります。 -> 現実世界の状況では、この**ボールはスライスされてn個の区画に入るでしょう**。しかし処理は同じです +> 現実世界の状況では、この**ボールはスライスされてn個の区画にまたがるでしょう**。しかし処理は同じです -フレーム状の物体は**3D方向に動き**、ボールは背景の方に動くと小さくもなります。 ブロックへの**完全なマッチを見つけられない**のは普通のことです。 推定画像と実際の画像を重ねると下記のようになります。 +フレーム状の物体は**3D方向に動き**、ボールは背景の方に動くと小さくもなります。 ブロックへの**完全なマッチを見つけられない**のはよくあることです。 推定画像と実際の画像を重ねると下記のようになります。 ![motion estimation](/i/motion_estimation.png "動き推定") @@ -374,7 +374,7 @@ Iフレーム(参照、キーフレーム、イントラ)は**自己完結的な ![](/i/smw_residual.png) > #### ハンズオン: イントラ予測を調べる -> [generate a video with macro blocks and their predictions with ffmpegでマクロブロックとそれらの予測付きのビデオを生成する](/encoding_pratical_examples.md#generate-debug-video)ことができます。 documentation to understand the [それぞれのブロックの色の意味](https://trac.ffmpeg.org/wiki/Debug/MacroblocksAndMotionVectors)を理解するためにffmpegのドキュメントを調べてください。 +> [ffmpegでマクロブロックとそれらの予測付きのビデオを生成する](/encoding_pratical_examples.md#generate-debug-video)ことができます。[それぞれのブロックの色の意味](https://trac.ffmpeg.org/wiki/Debug/MacroblocksAndMotionVectors)を理解するためにffmpegのドキュメントを調べてください。 > > ![intra prediction (macro blocks) with ffmpeg](/i/macro_blocks_ffmpeg.png "ffmpegでインター予測 (動きベクトル)") > @@ -386,23 +386,23 @@ Iフレーム(参照、キーフレーム、イントラ)は**自己完結的な ## 何か? なぜ? どのように? -**何か?** デジタルビデオを圧縮、解凍するソフトウェア / ハードウェアの部品。**なぜ?** 市場と社会で、制限された帯域とストレージの下でより高い品質のビデオへの要求が高まっているため。30フレーム毎秒、24ビット毎ピクセル、解像度が480x240のビデオに[必要が帯域を計算](#basic-terminology)したのを覚えていますか。圧縮なしでは**82.944 Mbps**でした。テレビやインターネットでHD/FullHD/4Kを配信するためには圧縮するしかありません。**どのように?** ここで主な技法について簡単に見ていきます。 +**何か?** デジタルビデオを圧縮、解凍するソフトウェア / ハードウェアの部品。**なぜ?** 制限された帯域とストレージの下でより高い品質のビデオへの要求が、市場と社会で高まっているため。30フレーム毎秒、24ビット毎ピクセル、解像度が480x240のビデオに[必要な帯域を計算](#basic-terminology)したのを覚えていますか。圧縮なしでは**82.944 Mbps**でした。テレビやインターネットでHD/FullHD/4Kを配信するためには圧縮するしかありません。**どのように?** ここで主な技法について簡単に見ていきます。 -> **CODEC 対 コンテナ** +> **コーデック 対 コンテナ** > -> 初心者がよくやる間違いの1つに、デジタルビデオCODECと[デジタルビデオコンテナ](https://en.wikipedia.org/wiki/Digital_container_format)を混同するというものがあります。**コンテナ**はビデオ(と音声もありえる)のメタデータとペイロードである**圧縮されたビデオ**を含むラッパーフォーマットとして考えることができます。 +> 初心者がよく誤解することの1つに、デジタルビデオコーデックと[デジタルビデオコンテナ](https://en.wikipedia.org/wiki/Digital_container_format)を混同するというものがあります。**コンテナ**はビデオ(と音声もありえる)のメタデータとペイロードである**圧縮されたビデオ**を包括するラッパーフォーマットとして考えることができます。 > -> たいてい、ビデオファイルの拡張子はそのビデオコンテナを定義します。例えば、ファイル`video.mp4`はおそらく**[MPEG-4 Part 14](https://en.wikipedia.org/wiki/MPEG-4_Part_14)**コンテナで、`video.mkv`という名前のファイルはおそらく**[matroska](https://en.wikipedia.org/wiki/Matroska)**です。コーデックとコンテナフォーマットを確実に調べるためには、[ffmpegかmediainfo](/encoding_pratical_examples.md#inspect-stream)を使うことができます。 +> たいてい、ビデオファイルの拡張子はそのビデオコンテナを定義します。例えば、ファイル`video.mp4`はおそらく **[MPEG-4 Part 14](https://en.wikipedia.org/wiki/MPEG-4_Part_14)** コンテナで、`video.mkv`という名前のファイルはおそらく **[matroska](https://en.wikipedia.org/wiki/Matroska)** です。コーデックとコンテナフォーマットを確実に調べるためには、[ffmpegかmediainfo](/encoding_pratical_examples.md#inspect-stream)が使えます。 ## 歴史 -一般的なコーデックの内部動作に入って行く前に、いくつかの古いビデオコーデックについて少し理解するために過去を振り返って見ましょう。 +一般的なコーデックの内部動作に入って行く前に、いくつかの古いビデオコーデックについて少し理解するために過去を振り返ってみましょう。 ビデオコーデックである[H.261](https://en.wikipedia.org/wiki/H.261)は1990年(厳密には1988年)に生まれました。H.261は**64 kbit/sのデータレート**で動作するように設計されました。クロマサブサンプリングやマクロブロックなどの考えをすでに使っていました。1995年に、**H.263**ビデオコーデック標準が発表され2001年まで拡張され続けました。 -2003年に**H.264/AVC**の初版が完成しました。同じ年に**TrueMotion**と呼ばれる会社が、**ロイヤリティーフリー**で非可逆ビデオ圧縮の **VP3**と呼ばれるビデオコーデックをリリースしました。2008年にこの会社を**Googleが買い**、同じ年に**VP8**をリリースしました。2012年の12月にGoogleが**VP9**をリリースしました。VP9は(モバイルを含む)**ブラウザ市場のおよそ¾にサポートされています**。 +2003年に**H.264/AVC**の初版が完成しました。同じ年に**TrueMotion**と呼ばれる会社が、**ロイヤリティーフリー**で非可逆ビデオ圧縮の **VP3**と呼ばれるビデオコーデックをリリースしました。2008年にこの会社を**Googleが買収**し、同じ年に**VP8**をリリースしました。2012年の12月にGoogleが**VP9**をリリースしました。VP9は(モバイルを含む)**ブラウザ市場のおよそ¾にサポートされています**。 - **[AV1](https://en.wikipedia.org/wiki/AOMedia_Video_1)**は新しい**ロイヤリティーフリー**でオープンソースのビデオコーデックで、[Alliance for Open Media (AOMedia)](http://aomedia.org/)によって設計されました。AOMediaは**複数の会社: Google、Mozilla、Microsoft、Amazon、Netflix、AMD、ARM、NVidia、Intel、Cisco**と他のいくつかの会社から成っています。リファレンスコーデックの**初版** 0.1.0が**2016年4月7日に公開されました**。 + **[AV1](https://en.wikipedia.org/wiki/AOMedia_Video_1)**は新しい**ロイヤリティーフリー**でオープンソースのビデオコーデックで、[Alliance for Open Media (AOMedia)](http://aomedia.org/)によって設計されました。AOMediaは**複数の会社: Google、Mozilla、Microsoft、Amazon、Netflix、AMD、ARM、NVidia、Intel、Cisco**と他のいくつかの会社から成り立っています。リファレンスコーデックの**初版** 0.1.0が**2016年4月7日に公開されました**。 ![codec history timeline](/i/codec_history_timeline.png "コーデック歴史年表") @@ -412,12 +412,12 @@ Iフレーム(参照、キーフレーム、イントラ)は**自己完結的な > > MPEG LAは、当初はHEVC (H.265)の年間ロイヤリティーの上限とH.264の8倍高いライセンス料を発表しましたが、すぐにルールを変更しました。: > * **年間ロイヤリティーの上限なし** -> * **コンテント料金** (収入の0.5%) -> * **h264より10倍高い単位あたり料金**. +> * **コンテンツ料金** (収入の0.5%) +> * **h264より10倍高い単位あたり料金** > > [alliance for open media](http://aomedia.org/about-us/)はハードウェアメーカー(Intel、AMD、ARM、Nvidia、Cisco)、コンテンツ配信 (Google、Netflix、Amazon)、ブラウザ開発(Google, Mozilla)、その他の会社によって作られました。 > -> これらの会社にはロイヤリティーフリーのビデオコーデックという共通の目的があり、AV1はもっと [単純な特許ライセンス](http://aomedia.org/license/patent/)で誕生しました。**Timothy B. Terriberry**が [AV1の概念、ライセンスモデル、現状](https://www.youtube.com/watch?v=lzPaldsmJbk)についての素晴らしいプレゼンテーションを行いました。この節はこのプレゼンテーションを元に書いています。 +> これらの会社にはロイヤリティーフリーのビデオコーデックという共通の目的があり、AV1はより [簡単な特許ライセンス](http://aomedia.org/license/patent/)で誕生しました。**Timothy B. Terriberry**が [AV1の概念、ライセンスモデル、現状](https://www.youtube.com/watch?v=lzPaldsmJbk)についての素晴らしいプレゼンテーションを行いました。この節はこのプレゼンテーションを元に書いています。 > > **ブラウザーを使ってAV1コーデックを分析**できることを知って驚くことでしょう。http://aomanalyzer.org/ を見てください。 > @@ -427,7 +427,7 @@ Iフレーム(参照、キーフレーム、イントラ)は**自己完結的な ## 一般的コーデック -**一般的なビデオコーデックの背後にある主な機構**を紹介していきますが、これらの概念のほとんどは VP9、AV1、HEVCのような最新のコーデックでも役に立ち、使われています。物事をかなり単純にして説明することは理解してください。ときどき実際の例(だいたいはH.264)を使って、技法のデモを行います。 +**一般的なビデオコーデックの背後にある主な機構**を紹介していきますが、これらの概念のほとんどは VP9、AV1、HEVCのような最新のコーデックでも役に立ち、使われています。物事をかなり単純にして説明することを理解してください。ときどき実際の例(だいたいはH.264)を使って、技法のデモを行います。 ## ステップ1 - 画像分割 @@ -437,9 +437,9 @@ Iフレーム(参照、キーフレーム、イントラ)は**自己完結的な **しかしなぜ?** たくさんの理由があります。例えば、画像を分割すると小さなパーティションを動きのある小さな部分に使い、より大きなパーティションを静的な背景に使って、予測をより正確に行うことができます。 -通常は、CODECは、スライス(もしくはタイル)、マクロ(もしくは符号ツリーユニット)やたくさんのサブパーティンに **パーティションを構造化します**。これらのパーティションの最大サイズは様々で、HEVCでは64x64、AVC16x16ですが、サブパーティションは4x4までです。 +通常は、コーデックは、スライス(もしくはタイル)、マクロ(もしくは符号ツリーユニット)やたくさんのサブパーティンにと **パーティションを構造化します**。これらのパーティションの最大サイズは様々で、HEVCでは64x64、AVC16x16ですが、サブパーティションは4x4までです。 -**フレームは種類に分けられている**のを学んだことを覚えていますか?**さて、これらの考えをブロックに適用する**こともできます。それで、Iスライス、Bスライス、Iマクロブロックなどを持つことができます。 +**フレームはいくつかのタイプに分けられている**のを学んだことを覚えていますか?**さて、これらの考えをブロックに適用する**こともできます。それで、Iスライス、Bスライス、Iマクロブロックなどを持つことができます。 > ### ハンズオン: パーティションを調べる > [Intel Video Pro Analyzer](https://software.intel.com/en-us/intel-video-pro-analyzer) (有料ですが、最初の10フレームに制限された無料お試し版もあります)を使うこともできます。これが分析された[VP9パーティション](/encoding_pratical_examples.md#transcoding)です。 @@ -448,21 +448,21 @@ Iフレーム(参照、キーフレーム、イントラ)は**自己完結的な ## ステップ2 - 予測 -パーティションに分割すると、それらについて予測を行うことができます。[インター予測](#temporal-redundancy-inter-prediction)のために、**動きベクトルと差分を送る**必要があり、また[イントラ予測](#spatial-redundancy-intra-prediction)のために、**予測方向と差分**を送る必要があります。 +パーティションに分割すると、それらについて予測を行うことができます。[インター予測](#temporal-redundancy-inter-prediction)のために、**動きベクトルと差分を送信する**必要があり、また[イントラ予測](#spatial-redundancy-intra-prediction)のために、**予測方向と差分を送信する**必要があります。 ## ステップ3 - 変換 -差分ブロック (`予測パーティション - 実際のパーティション`)を生成した後、**大まかな画質**を保ったままどの**ピクセルを捨てられるか**が分かるように、**変換**を行うことができる 。まさにそれを行うためにはいくつかの変換が存在します。 +差分ブロック (`予測パーティション - 実際のパーティション`)を生成した後、**変換**することで**大まかな画質**を保ったままどの**ピクセルを捨てられるか**が分かるようになります。それを行うためにはいくつかの変換が存在します。 [他の変換](https://en.wikipedia.org/wiki/List_of_Fourier-related_transforms#Discrete_transforms)もありますが、離散コサイン変換(DCT)をしっかり見ていきます。[**DCT**](https://en.wikipedia.org/wiki/Discrete_cosine_transform)の主な特徴は: -* **ピクセル**のブロックを同じサイズの**周波数係数**ブロックに**変換する**。 +* **ピクセル**ブロックを同じサイズの**周波数係数**ブロックに**変換する**。 * エネルギーを**圧縮**して、空間的冗長性を削減しやすくする。 * **元に戻せる**、またはピクセルに戻せる > 2017年2月2日にCintra, R. J.とBayer, F. Mが[14加算のみの画像圧縮用DCT近似変換](https://arxiv.org/abs/1702.00817)という論文を発表しました。 -箇条書きの利点を全て理解しなかったとしても心配いりません。その本当の価値を見い出すためにいくつかの実験を試みてみます。 +上記の箇条書きの利点を全て理解しなかったとしても心配いりません。その本当の価値を見い出すためにいくつかの実験を試みてみます。 次の**ピクセルのブロック** (8x8)を例にとりましょう: @@ -480,13 +480,13 @@ Iフレーム(参照、キーフレーム、イントラ)は**自己完結的な ![dct coefficients image](/i/dct_coefficient_image.png "dct係数画像") -元の画像とは似ても似つかないことが分かり、**最初の係数**は他の係数とは全く異なっていることに気づくかもしれません。 この最初の係数はDC係数として知られ、入力配列の**サンプル全体**を表します。何か**平均に似てる**ものです。 +元の画像とは似ても似つかないことが分かり、**最初の係数**は他の係数とは全く異なっていることに気づくかもしれません。 この最初の係数はDC係数として知られ、入力配列の**サンプル全体**を表します。**平均に似てる**何かです。 この係数のブロックは高周波数成分を低周波数成分から切り離すという面白い特性を持っています。 ![dct frequency coefficients property](/i/dctfrequ.jpg "dct周波数係数特性") -画像では、**エネルギーのほとんど**は[**低周波数**](https://web.archive.org/web/20150129171151/https://www.iem.thm.de/telekom-labor/zinke/mk/mpeg2beg/whatisit.htm)に集中されます。それで画像を周波数成分に変換して**高周波数係数を捨て**れば、画質をそれほど犠牲にせずに画像を表現するのに必要な**データ量を削減**できます。 +画像では、**エネルギーのほとんど**は[**低周波**](https://web.archive.org/web/20150129171151/https://www.iem.thm.de/telekom-labor/zinke/mk/mpeg2beg/whatisit.htm)に集中されます。それで画像を周波数成分に変換して**高周波数係数を捨て**れば、画質をそれほど犠牲にせずに画像を表現するのに必要な**データ量を削減**できます。 > 周波数は信号がどれだけ速く変化するかを意味します。 @@ -508,13 +508,13 @@ Iフレーム(参照、キーフレーム、イントラ)は**自己完結的な > **それぞれの係数は画素全体を使って形成される** > -> それぞれの係数は、1つの画素に直接マッピングしているわけではなく、画素全体の重み付き合計であることに留意することは重要です。この素晴らしいグラフは、1番目と2番目の係数が、それぞれのインデックスで異なる重みを使って、どのように計算されるかを示しています。 +> それぞれの係数は、1つの画素に直接マッピングしているわけではなく、画素全体の重み付き合計であることに留意することは重要です。下記の素晴らしいグラフは、1番目と2番目の係数が、それぞれのインデックスで異なる重みを使って、どのように計算されるかを示しています。 > > ![dct calculation](/i/applicat.jpg "dct計算") > > 原典: https://web.archive.org/web/20150129171151/https://www.iem.thm.de/telekom-labor/zinke/mk/mpeg2beg/whatisit.htm > -> DCT基底ごとの[単純な画像の形成を見てDCTを視覚化する](/dct_better_explained.ipynb)こともできます。例えば、これはそれぞれの係数の重みをを使って[1つの文字が形成されていく](https://en.wikipedia.org/wiki/Discrete_cosine_transform#Example_of_IDCT)過程です。 +> DCT基底ごとの[単純な画像の形成を見てDCTを視覚化する](/dct_better_explained.ipynb)こともできます。例えば、下記はそれぞれの係数の重みをを使って[1つの文字が形成されていく](https://en.wikipedia.org/wiki/Discrete_cosine_transform#Example_of_IDCT)過程です。 > > ![](https://upload.wikimedia.org/wikipedia/commons/5/5e/Idct-animation.gif ) @@ -524,11 +524,11 @@ Iフレーム(参照、キーフレーム、イントラ)は**自己完結的な
> ### ハンズオン: 種々の係数を捨てる -> [DCT変換](/uniform_quantization_experience.ipynb)を実験できます。 +> [DCT変換](/uniform_quantization_experience.ipynb)を実験しましょう。 ## ステップ4 - 量子化 -前のステップ (変換)で係数をいくつか捨てるときに、量子化のようなものを行いました。 このステップでは、損失する情報(**損失部分**)を選びます。単純な言葉でいうと、**圧縮を成し遂げるために係数を量子化**します。 +前のステップ (変換)で係数をいくつか捨てるときに、量子化のようなものを行いました。 このステップでは、捨てる情報(**損失部分**)を選びます。単純な言葉でいうと、**圧縮を成し遂げるために係数を量子化**します。 どのように係数のブロックを量子化できるでしょうか?1つの単純な方法は、均一量子化でしょう。ブロックを**単一値** (10) **で割り**、小数点を切り捨てます。 @@ -538,10 +538,10 @@ Iフレーム(参照、キーフレーム、イントラ)は**自己完結的な ![re-quantize](/i/re-quantize.png "再量子化") -この**やり方は最適な方法ではありません**。それぞれの係数の重要度を考慮していないからです。 単一値の代わりに**量子化マトリクス**を使うことができました。このマトリクスはDCTの特性を活かすことができます。右下を一番量子化して、左上はあまり量子化しません。[JPEGは似たやり方を使っています](https://www.hdm-stuttgart.de/~maucher/Python/MMCodecs/html/jpegUpToQuant.html)。[ソースコード上でこのマトリクスを見る](https://github.com/google/guetzli/blob/master/guetzli/jpeg_data.h#L40)ことができます。 +この**やり方は最適な方法ではありません**。それぞれの係数の重要度を考慮していないからです。 単一値の代わりに**量子化マトリクス**を使うことができます。このマトリクスでDCTの特性を活かすことができます。右下を一番量子化して、左上はあまり量子化しません。[JPEGは似たやり方を使っています](https://www.hdm-stuttgart.de/~maucher/Python/MMCodecs/html/jpegUpToQuant.html)。[ソースコード上でこのマトリクスを見る](https://github.com/google/guetzli/blob/master/guetzli/jpeg_data.h#L40)ことができます。 > ### ハンズオン: 量子化 -> [量子化](/dct_experiences.ipynb)を実験できます。 +> [量子化](/dct_experiences.ipynb)を実験しましょう。 ## ステップ5 - エントロピー符号化 @@ -555,7 +555,7 @@ Iフレーム(参照、キーフレーム、イントラ)は**自己完結的な |-------------|-----|-----|------|-----| | 確率 | 0.3 | 0.3 | 0.2 | 0.2 | -もっとも確率が大きいものには(より小さな)ユニークなバイナリコードを、もっとも確率が低いものにはより大きなバイナリコードを割り当てることができます。 +もっとも確率が高いものには(より小さな)ユニークなバイナリコードを、もっとも確率が低いものにはより大きなバイナリコードを割り当てることができます。 | | a | e | r | t | |-------------|-----|-----|------|-----| @@ -564,11 +564,11 @@ Iフレーム(参照、キーフレーム、イントラ)は**自己完結的な ストリーム **eat**を圧縮してみましょう。それぞれの記号に8ビット使うと、圧縮なしで**24ビット**使うことになります。しかし、それぞれの記号をそのコードで置き換えると、スペースを節約できます。 -まず記号**e**を符号化して`10`になります。2つ目の記号**a**を符号化すると、足されて(数学の方法ではなく) `[10][0]`となります。最後に3つ目の記号を符号化**t**を符号化すると、最終的な圧縮されたビットストリームは `[10][0][1110]`もしくは`1001110`となり、(もとより3.4倍小さなスペースである)**7ビット**しか使いません。 +まず記号**e**を符号化して`10`になります。2つ目の記号**a**を符号化すると、足されて(算数の方法ではなく) `[10][0]`となります。最後に3つ目の記号**t**を符号化すると、最終的な圧縮されたビットストリームは `[10][0][1110]`もしくは`1001110`となり、(もとより3.4倍小さなスペースである)**7ビット**しか使いません。 -それぞれのコードはユニークな接頭符号である必要があることに注意してください [ハフマンがこれらの数字を見つけることを助けてくれます](https://en.wikipedia.org/wiki/Huffman_coding)。いくつかの問題がありますが、この方法を[今でもサポートするビデオコーデック](https://en.wikipedia.org/wiki/Context-adaptive_variable-length_coding)が存在します。これは圧縮を必要とするたくさんのアプリケーションのためのアルゴリズムです。 +それぞれのコードはユニークな接頭符号を持つ必要があることに注意してください [ハフマンがこれらの数字を見つけることを助けてくれます](https://en.wikipedia.org/wiki/Huffman_coding)。いくつかの問題がありますが、この方法は[いくつかのビデオコーデックでまだサポート](https://en.wikipedia.org/wiki/Context-adaptive_variable-length_coding)しています。これは圧縮を必要とする多くのアプリケーションに有用なアルゴリズムです。 -エンコーダーとデコーダーの両方がそのコードの記号テーブルを**知らなくてはいけません**。それで、テーブルも送る必要があります。 +エンコーダーとデコーダーの両方がそのコードの記号テーブルを**知らなくてはいけません**。それでテーブルも送信する必要があります。 ### 算術符号: @@ -578,11 +578,11 @@ Iフレーム(参照、キーフレーム、イントラ)は**自己完結的な |-------------|-----|-----|------|------|-----| | probability | 0.3 | 0.3 | 0.15 | 0.05 | 0.2 | -この表を考慮に入れて、出現順にソートされた全ての可能な記号を含む範囲のグラフを作ることができます。 +この表を考慮に入れて、出現順にソートされた全ての可能な記号を含む範囲グラフを作ります。 ![initial arithmetic range](/i/range.png "初期算術範囲") -さて、ストリーム **eat**を符号化してみましょう。最初の記号**e**を取り上げます。それは*0.3以上0.6未満**に位置しています。この部分範囲を取り上げ、それを再び同じ割合で分割します。 +さて、ストリーム **eat**を符号化してみましょう。最初の記号**e**を取り上げます。それは**0.3以上0.6未満**に位置しています。この部分範囲を取り上げ、それを再び同じ割合で分割します。 ![second sub range](/i/second_subrange.png "2番目の部分範囲") @@ -590,14 +590,14 @@ Iフレーム(参照、キーフレーム、イントラ)は**自己完結的な ![final arithmetic range](/i/arithimetic_range.png "最終的な算術範囲") -最終範囲**0.354以上0.372未満**から1つの数値を取り上げる必要があります。**0.36**を取り上げましょう。しかしこの部分範囲ないならどんな数値を選んでもかまいません。この数値**だけで**、元のストリーム**eat**を復元することができます。これは、ストリームを符号化する為に範囲の範囲に線を引くかのように捉えることができます。 +最終範囲**0.354以上0.372未満**から1つの数値を取り上げる必要があります。**0.36**を取り上げましょう。しかしこの部分範囲内ならどんな数値を選んでもかまいません。この数値**だけで**、元のストリーム**eat**を復元することができます。これは、ストリームを符号化する為に範囲の範囲に線を引くかのように捉えることができます。 ![final range traverse](/i/range_show.png "最終範囲横断") **逆過程** (別名 復号化) は同様に簡単で、数値**0.36**と元の範囲を使って、同じ処理を行い、この数値から符号化されたストリームを明らかにします。 最初の範囲で、その数値が1つの部分に一致し、それが最初の記号であることに気づきます。それから、その部分範囲を以前行ったようにまた分割します。すると**0.36**が記号**a**に合うことがわかり、同じ処理を繰り返すと、最後の記号である**t**を見つけます(符号前のストリーム*eat*を形成します)。 -符号化と復号化の療法は、記号確率テーブルを**知る必要があります**。それでテーブルを送信する必要があります。 +符号化と復号化の両方は、記号確率テーブルを**知る必要があります**。それでテーブルを送信する必要があります。 素晴らしいですよね。人々は本当に賢く、このような解決策を生み出しました。いくつかの[ビデオコーデック](https://en.wikipedia.org/wiki/Context-adaptive_binary_arithmetic_coding)はこの技法を使っています。(もしくは少なくともオプションとして提供しています)。 @@ -608,7 +608,7 @@ Iフレーム(参照、キーフレーム、イントラ)は**自己完結的な ## ステップ6 - ビットストリームフォーマット -これらのステップ全てを行った後、**圧縮されたフレームとこれらのステップまでの状況をパック**する必要があります。 **エンコーダによってなされた決定**についてデコーダへ明示的に知らせる必要があります。ビット深度、色空間、解像度、予測情報(動きベクトル、イントラ予測方向)、プロファイルレベル、フレームレート、フレームタイプ、フレーム数、その他多数です。 +これらのステップ全てを行った後、**圧縮されたフレームとこれらのステップまでのコンテキストを一つにまとめる**必要があります。 **エンコーダによってなされた決定**についてデコーダへ明示的に知らせる必要があります。ビット深度、色空間、解像度、予測情報(動きベクトル、イントラ予測方向)、プロファイルレベル、フレームレート、フレームタイプ、フレーム数、その他多数です。 H.264ビットストリームについて表面的に学んでいきます。最初のステップは[最小限のH.264 *ビットストリームを生成する](/encoding_pratical_examples.md#generate-a-single-frame-h264-bitstream)ことです。このレポジトリと[ffmpeg](http://ffmpeg.org/)を使って、これができます。 @@ -618,17 +618,17 @@ H.264ビットストリームについて表面的に学んでいきます。最 > * ffmpegは、デフォルトで**SEI NAL**として符号化された全パラメータを加えます。NALがなんであるかはすぐに定義します。 -このコマンドは、**単一フレーム**、64x64、色空間がyuv420、次の画像をフレームとしてつかている生のh264ビットストリームを生成ます。 +このコマンドは、**単一フレーム**、64x64、色空間がyuv420、次の画像をフレームとして使っている生のh264ビットストリームを生成します。 > ![used frame to generate minimal h264 bitstream](/i/minimal.png "最小h264ビットストリームを生成するフレームを使った") ### H.264ビットストリーム -AVC (H.264)標準は、情報が**マクロフレーム** (ネットワーク的には), **[NAL](https://en.wikipedia.org/wiki/Network_Abstraction_Layer)** (Network Abstraction Layer)と呼ばれる形で送られることを定義しています。NALの主な目的は、"ネットワークフレンドリー"なビデオ表現を提供することです。この標準は、TV (ストリームベース)、インターネット(パケットベース)やその他で動作しなければなりません。 +AVC (H.264)標準は、情報が**マクロフレーム** (ネットワーク的には)**[NAL](https://en.wikipedia.org/wiki/Network_Abstraction_Layer)** (Network Abstraction Layer)と呼ばれる形で送信されることを定義しています。NALの主な目的は、"ネットワークフレンドリー"なビデオ表現を提供することです。この標準は、TV (ストリームベース)、インターネット(パケットベース)やその他で動作しなければなりません。 ![NAL units H.264](/i/nal_units.png "NALユニット H.264") -NALユニットの境界を定義する**[同期マーカー](https://en.wikipedia.org/wiki/Frame_synchronization)**があります。それぞれの同期マーカーは、一番最初が`0x00 0x00 0x00 0x01`であることを除き`0x00 0x00 0x01`の値を持つ。もし生成されたh264ビットストリーム上で**16進ダンプ**を行えば、ファイルの最初の方に、少なくとも3つのNALを見つけることができます。 +NALユニットの境界を定義する **[同期マーカー](https://en.wikipedia.org/wiki/Frame_synchronization)**があります。それぞれの同期マーカーは、最初は`0x00 0x00 0x00 0x01`で、それ以降は`0x00 0x00 0x01`の値を持ちます。もし生成されたh264ビットストリーム上で**16進ダンプ**を行えば、ファイルの最初の方に、少なくとも3つのNALを見つけることができます。 ![synchronization marker on NAL units](/i/minimal_yuv420_hex.png "NALユニットの同期マーカー") @@ -652,15 +652,15 @@ NALユニットの境界を定義する**[同期マーカー](https://en.wikiped 普通は、ビットストリームの最初のNALは**SPS**で、このタイプのNALは、**プロファイル**、**レベル**、**解像度**やその他の汎用エンコーディング変数を知らせる役割を持ちます。 -最初の同期マーカーをスキップすると、**最初のバイト**を復号化して**NALのタイプ**が何かを知ることができます。 +最初の同期マーカーを飛ばすと、**最初のバイト**を復号化して**NALのタイプ**が何かを知ることができます。 例えば、同期マーカーの最初のバイトは`01100111`です。最初のビット (`0`)は**forbidden_zero_bit**フィールドで、次の2ビット(`11`)は**nal_ref_idc**フィールドで、このNALが参照フィールドかどうかを示します。残りの5ビット (`00111`)は**nal_unit_type**フィールドで、この例では**SPS** (7) NALユニットです。 -SPS NALの2バイト目(`2進数=01100100、16進数=0x64、10進数=100`)は**profile_idc**フィールドで、エンコーダが使ったプロファイルを示します。この例では、**[制約付きハイプロファイル](https://en.wikipedia.org/wiki/H.264/MPEG-4_AVC#Profiles)**を使っています。これはB (双方向予測)スライスをサポートしないハイプロファイルです。 +SPS NALの2バイト目(`2進数=01100100、16進数=0x64、10進数=100`)は**profile_idc**フィールドで、エンコーダが使ったプロファイルを示します。この例では、 **[制約付きハイプロファイル](https://en.wikipedia.org/wiki/H.264/MPEG-4_AVC#Profiles)** を使っています。これはB (双方向予測)スライスをサポートしないハイプロファイルです。 ![SPS binary view](/i/minimal_yuv420_bin.png "SPSバイナリビュー") -SPS NALについてH.264ビットストリーム仕様を読むと、**パラメータ名**、**カテゴリ**、**説明**に多くの値を見つけるでしょう。例えば、`pic_width_in_mbs_minus_1`と`pic_height_in_map_units_minus_1`フィールドについて見てみましょう。 +SPS NALについてH.264ビットストリーム仕様を読むと、**パラメータ名**、**カテゴリ**、**説明**の表に多くの値を見つけるでしょう。例えば、`pic_width_in_mbs_minus_1`と`pic_height_in_map_units_minus_1`フィールドについて見てみましょう。 | パラメータ名 | カテゴリ | 説明 | |--- |---|---| @@ -669,31 +669,31 @@ SPS NALについてH.264ビットストリーム仕様を読むと、**パラメ > **ue(v)**: 符号なし整数 [Exp-Golomb-coded](https://pythonhosted.org/bitstring/exp-golomb.html) -これらのフィールドの値に対してある計算をすると、**解像度**を得ることができます。`1920 x 1080`を`pic_width_in_mbs_minus_1`が`119 ( (119 + 1) * macroblock_size = 120 * 16 = 1920) `として表現することができます。空間をさらに節約するために、`1920`を符号化する代わりに、`119`を使いました。 +これらのフィールドの値に対してある計算をすると、**解像度**を得ることができます。`1920 x 1080`を`pic_width_in_mbs_minus_1`が`119 ( (119 + 1) * macroblock_size = 120 * 16 = 1920) `として表現することができます。空間をさらに節約するために、`1920`を符号化する代わりに、`119`を使っています。 -生成されたビデオをバイナリビュー (例えば: `xxd -b -c 11 v/minimal_yuv420.h264`)で検査し続けると、最後のNALまでスキップすることができます。それはフレーム自身です。 +生成されたビデオをバイナリビュー (例えば: `xxd -b -c 11 v/minimal_yuv420.h264`)で検査し続けると、最後のNALまで飛ばすことができます。それはフレーム自体です。 ![h264 idr slice header](/i/slice_nal_idr_bin.png "h264 IDRスライスヘッダー") -最初の6バイトの値を見ることができます: `01100101 10001000 10000100 00000000 00100001 11111111`。すでに知ってる通り、最初のバイトでNALが何だかを知ることができます。この例では、(`00101`)で**IDRスライス (5)**です。さらに検査してみます: +最初の6バイトの値を見ましょう: `01100101 10001000 10000100 00000000 00100001 11111111`。すでに知ってる通り、最初のバイトでNALが何かを知ることができます。この例では、(`00101`)で **IDRスライス (5)** です。さらに検査してみます: ![h264 slice header spec](/i/slice_header.png "h264スライスヘッダ仕様") 仕様の情報を使い、スライスのタイプ (**slice_type**)、フレーム番号(**frame_num**)や他の重要なフィールドを復号することができます。 -いくつかのフィールドの値を得るために(`ue(v)、me(v)、se(v)、te(v)`)、それを[Exponential-Golomb](https://pythonhosted.org/bitstring/exp-golomb.html)と呼ばれる特別なデコーダーを使って、デコードする必要があります。この方法は、多くのデフォルト値を持つ場合はたいてい、**変数値を符号化するのにとても効率的**です。 +いくつかのフィールドの値を得るために(`ue(v)、me(v)、se(v)、te(v)`)、それを[Exponential-Golomb](https://pythonhosted.org/bitstring/exp-golomb.html)と呼ばれる特別なデコーダーを使って、デコードする必要があります。この方法は、デフォルト値が多いケースではたいてい、**変数値を符号化するのにとても効率的**です。 > このビデオの**slice_type**と**frame_num**の値は7 (Iスライス)と0 (最初のフレーム)です。 -**ビットストリームをプロトコルとして**見ることができます。このビットストリームについてもっと学びたいもしくは学ぶ必要があるなら、[ITU H.264 spec.]( http://www.itu.int/rec/T-REC-H.264-201610-I)を参照してください。下記はマクロ図表で、ピクチャデータ(圧縮YUV)がどこに位置するかを示しています。 +**ビットストリームをプロトコルとして**見ることができます。このビットストリームについてもっと学びたい、もしくは学ぶ必要があるなら、[ITU H.264 spec.]( http://www.itu.int/rec/T-REC-H.264-201610-I)を参照してください。下記はマクロ図表で、ピクチャデータ(圧縮YUV)がどこに位置するかを示しています。 ![h264 bitstream macro diagram](/i/h264_bitstream_macro_diagram.png "h264ビットストリームマクロ図表") -[VP9ビットストリーム](https://storage.googleapis.com/downloads.webmproject.org/docs/vp9/vp9-bitstream-specification-v0.6-20160331-draft.pdf)や[H.265 (HEVC)](http://handle.itu.int/11.1002/1000/11885-en?locatt=format:pdf)や、さらには**新しいベストフレドである** [**AV1** bitstream](https://medium.com/@mbebenita/av1-bitstream-analyzer-d25f1c27072b#.d5a89oxz8 +[VP9ビットストリーム](https://storage.googleapis.com/downloads.webmproject.org/docs/vp9/vp9-bitstream-specification-v0.6-20160331-draft.pdf)や[H.265 (HEVC)](http://handle.itu.int/11.1002/1000/11885-en?locatt=format:pdf)や、さらには**新しいベストフレドである** [**AV1** ビットストリーム](https://medium.com/@mbebenita/av1-bitstream-analyzer-d25f1c27072b#.d5a89oxz8 )のビットストリームを探索することができます。[それらはみんな似てますか?いいえ](http://www.gpac-licensing.com/2016/07/12/vp9-av1-bitstream-format/)、しかし1つを学ぶと、他のは簡単に理解できます。 > ### ハンズオン: H.264ビットストリームを調べる -> [単一フレームのビデオを生成](https://github.com/leandromoreira/introduction_video_technology/blob/master/encoding_pratical_examples.md#generate-a-single-frame-video)し、[mediainfo](https://en.wikipedia.org/wiki/MediaInfo)を使ってH.264ビットストリームを検査してみましょう。実際、[h264 (AVC)ビットストリームをパースするソースコード](https://github.com/MediaArea/MediaInfoLib/blob/master/Source/MediaInfo/Video/File_Avc.cpp)を見ることさえできます。 +> [単一フレームのビデオを生成](https://github.com/leandromoreira/introduction_video_technology/blob/master/encoding_pratical_examples.md#generate-a-single-frame-video)し、[mediainfo](https://en.wikipedia.org/wiki/MediaInfo)を使ってH.264ビットストリームを検査してみましょう。実際、[h264 (AVC)ビットストリームをパースするソースコード](https://github.com/MediaArea/MediaInfoLib/blob/master/Source/MediaInfo/Video/File_Avc.cpp)を見ることもできます。 > > ![mediainfo details h264 bitstream](/i/mediainfo_details_1.png "mediainfoがh264ビットストリームを詳述する") > @@ -703,11 +703,11 @@ SPS NALについてH.264ビットストリーム仕様を読むと、**パラメ ## おさらい -多くの**現代のコーデックが、これまで学んできた同じモデルを使っている**ことに気づくでしょう。実際、ビデオコーデックのブロック図をみてみましょう。それは学んできた全てのステップを含んでいます。少なくともこのエリアの発明や文献についてより理解することができるはずということです。 +多くの**現代のコーデックが、これまで学んできた同じモデルを使っている**ことに気づくでしょう。実際のビデオコーデックのブロック図をみてみましょう。これは学んできた全てのステップを含んでいます。少なくともコーデック関連の発明や文献についてより理解することができるようになったことになります。 ![thor_codec_block_diagram](/i/thor_codec_block_diagram.png "thor_codec_block_diagram") -先に、[720p解像度で30fpsで1時間のビデオファイルを保存するのに139GBのストレージ](#chroma-subsampling)が必要になることを計算しました。ここで学んだ技法を使えば、つまり**インター予測、イントラ予測、変形、量子化、エントロピー符号化、その他**を使えば、**ピクセルあたり0.031ビット**を使うことを想定して、同じ知覚画質のビデオを保存するのに、**139GBに対して、367.82MBだけ必要**であることを実現できます。 +先に、[720p解像度で30fpsで1時間のビデオファイルを保存するのに139GBのストレージ](#chroma-subsampling)が必要になることを計算しました。ここで学んだ技法を使えば、つまり**インター予測、イントラ予測、変形、量子化、エントロピー符号化、その他**を使えば、**ピクセルあたり0.031ビット**を使うことを想定して、同じ知覚画質のビデオを保存するのに、**139GBに対して、367.82MBだけ必要**になることを実現できます。 > ここで使った例のビデオを元に**ピクセルあたり0.031ビット**を使うことを導きました。 @@ -717,7 +717,7 @@ SPS NALについてH.264ビットストリーム仕様を読むと、**パラメ AVCとHEVCを比較してみましょう。より多くのCPUサイクル(複雑さ)と圧縮率は、ほとんどいつでもトレードオフであることを心に止めておきましょう。 -HEVCはAVCに比べて、より大きく、より多くの**パーティション** (と **サブパーティション**)のオプションを持っています。そしてより多くの**イントラ予測方向**、**改善されたエントロピー符号化**やその他を持っています。全てのこれらの改良のおかげで、H.265はH.264に比べて50%以上の圧縮することができるのです。 +HEVCはAVCに比べて、より大きく、より多くの**パーティション** (と **サブパーティション**)のオプションを持っています。そしてより多くの**イントラ予測方向**、**改善されたエントロピー符号化**やその他を持っています。これら全ての改良のおかげで、H.265はH.264に比べて50%以上の圧縮をすることができるのです。 ![H.264 vs H.265](/i/avc_vs_hevc.png "h264対h265") @@ -738,15 +738,15 @@ HEVCはAVCに比べて、より大きく、より多くの**パーティショ ## コンテンツ保護 -**単純なトークンシステム**を使ってコンテントを保護することができます。トークンを持っていないユーザーはビデオをリクエストしようとしても、CDNが禁止します。一方有効なトークンを持つユーザーはそのコンテントを再生することができます。これはたいていのウェブ認証システムとほとんど同じように動作します。 +**単純なトークンシステム**を使ってコンテンツを保護することができます。トークンを持っていないユーザーはビデオをリクエストしようとしても、CDNが禁止します。一方有効なトークンを持つユーザーはそのコンテンツを再生することができます。これはたいていのウェブ認証システムとほとんど同じように動作します。 ![token_protection](/i/token_protection.png "トークン保護") -このトークンシステムの単一のユーザーは、あるユーザーにビデオをダウンロードさせて、それを配布させることもできます。これを避けるために**DRM (デジタル著作権管理)**システムを使うことができます。 +このトークンシステムの一人のユーザーが、あるユーザーにビデオをダウンロードさせて、それを配布させることもできます。**DRM (デジタル著作権管理)** システムを使ってこれを避けることができます。 ![drm](/i/drm.png "drm") -実際の製品システムで、人々はしばしば両方の技術を使って、承認と認証を提供します。 +実際の製品システムで、人々はしばしばこれら両方の技術を使って、承認と認証を提供します。 ### DRM #### メインシステム @@ -762,7 +762,7 @@ DRMはデジタル著作権管理を意味します。それは、例えばデ #### なぜ? -コンテント製作者(たいていはスタジオ)は、デジタルメディアの不正な再配布を防ぐために、 知的財産がコピーされることから守りたいです。 +コンテンツ製作者(たいていはスタジオ)は、デジタルメディアの不正な再配布を防ぐために、 知的財産がコピーされることから守りたいためです。 #### どのように? @@ -770,7 +770,7 @@ DRMの抽象的で一般的な形式を、とても単純な方法で説明し **コンテンツC1** (例えば hlsやdashビデオストリーミング)と**プレイヤーP1** (例えば shaka-clappr、exo-player、ios)が**デバイスD1** (例えば スマートフォン、テレビ、タブレット、デスクトップ/ノートブック)上にあり、**DRMシステムDRM1** (widevine、playready、FairPlayなど)を使っているとしましょう。 -The コンテンツC1は、システムDRM1からの**対称鍵K1**で暗号化され、**暗号化コンテンツC'1**を生成します。 +コンテンツC1は、システムDRM1からの**対称鍵K1**で暗号化され、**暗号化コンテンツC'1**を生成します。 ![drm general flow](/i/drm_general_flow.jpeg "drm生成フロー") @@ -778,11 +778,11 @@ The コンテンツC1は、システムDRM1からの**対称鍵K1**で暗号化 > **1保護される**: この保護は、**ハードウェアを介して**なされます。例えば、この鍵は、特別な(読み取り専用)チップの中に保存されます。これは、復号を提供する[ブラックボックス](https://en.wikipedia.org/wiki/Black_box)のように働きます。もしくは(あまり安全でない)**ソフトウェアにより** なされます。DRM システムは、与えられたデバイスがどのタイプの保護を持っているかを知る方法を提供します。 -**プレイヤーP1がコンテンツC'1を再生したい**とき、**DRMシステムDRM1**を使う必要があります。公開鍵**PUK1**を与えます。DRMシステムDRM1は **暗号化された鍵K1**をクライアントの公開鍵**PUK1**と一緒に返します。理論上、このレスポンスは.**D1だけが復号可能な**何かです。 +**プレイヤーP1がコンテンツC'1を再生したい**とき、**DRMシステムDRM1**を使う必要があり、まず公開鍵**PUK1**を与えます。DRMシステムDRM1は クライアントの公開鍵**PUK1**で**暗号化された鍵K1**を返します。理論上、このレスポンスは.**D1だけが復号可能**です。 `K1P1D1 = enc(K1, PUK1)` -**P1**は、DRMローカルシステム (それは特別なハードウェアかソフトウェアである[SOC](https://en.wikipedia.org/wiki/System_on_a_chip)もなりえる)を使います。このシステムは、秘密鍵PRK1を使っているコンテンツを**復号することができます**。**K1P1D1からの対称鍵K1**を復号化して、**C'1を再生**することができます。最善の場合では、鍵はRAMを介して外にさらされません。 +**P1**は、DRMローカルシステム (それは特別なハードウェアかソフトウェアである[SOC](https://en.wikipedia.org/wiki/System_on_a_chip)もなりえる)を使います。このシステムは、秘密鍵PRK1を使って、コンテンツを**復号することができます**。**K1P1D1からの対称鍵K1**を復号化して、**C'1を再生**することができます。鍵がRAM上で外にさらされないのがベストです。 ``` K1 = dec(K1P1D1, PRK1)