記事ディレクトリ
-
- 共通API
-
- avformat_open_input
- avformat_find_stream_info
- by_find_best_stream
- avfromat_close_input
- avformat_alloc_context
- avformat_free_context
- by_guess_format
- avformat_alloc_output_context2
- avio_open2
- avformat_new_stream
- avcodec_parameters_copy
- avformat_write_header
- by_read_frame
- シークフレームの
- av_rescale_q_rnd
- av_interleaved_write_frame
- by_rescale_q
- of_packet_rescale_ts
- of_packet_unref
- by_packet_free
- of_packet_move_ref
- by_calloc
- of_fifo_alloc2
- by_fifo_read
- by_fifo_write
- by_fifo_freep2
- avcodec_alloc_context3
- avcodec_free_context
- avcodec_find_encoder
- avcodec_find_encoder_by_name
- of_frame_alloc
- av_frame_get_buffer
- avcodec_send_frame
- avcodec_receive_frame
- av_frame_free
- avcodec_find_decoder
- avcodec_send_packet
- avcodec_receive_packet
- avcodec_open2
- av_frame_make_writeable
- avchannel_layout_copy
- avcodec_parameters_to_context
- sws_getContext
- sws_scale
- swr_alloc
- swr_init
- swr_alloc_set_opts2
- swr_convert
- swr_free
- av_samples_get_buffer_size
- of_fast_malloc
- av_guess_sample_aspect_ratio
- by_guess_frame_rate
- of_get_bytes_per_sample
- by_strdup
- AV合理的
- 一般的なデータ構造
- 他の
共通API
avformat_open_input
avformat_open_input
は、入力ファイルを開き、構造を割り当てて初期化するAVFormatContext
ために FFmpeg で使用される関数です。その関数プロトタイプは次のとおりです。
int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);
以下に関数パラメータの説明を示します。
ps
AVFormatContext
:構造体へのポインタへのポインタ。url
:ファイルのURLまたはファイルパスを入力します。fmt
: 入力ファイルの形式コンテキストを指定します。通常はNULL
、ファイル名の接尾辞に従って自動的に検出されます。(このような状況が存在します: ファイルの拡張子が実際のパッケージ化されたコンテンツと異なる場合。たとえば、ファイルの拡張子は flv ですが、中には mp4 ファイルが保存されます。)options
: 入力ストリームを開くための追加オプションを指定します。追加パラメータは指定せず、デフォルト値を指定しますNULL
。
この関数の戻り値は、成功の場合は 0、それ以外の場合は失敗です。関数が負のエラー コードを返した場合は、av_err2str
変換関数を使用して対応するエラー メッセージに変換できます。
サンプルコードは次のとおりです。
AVFormatContext *fmt_ctx = NULL;
const char *filename = "input.mp4";
int ret = 0;
// 打开输入文件并分配AVFormatContext结构体
if ((ret = avformat_open_input(&fmt_ctx, filename, NULL, NULL)) < 0) {
// av_err2str是FFmpeg中的一个函数,用于将错误代码转换为错误消息的字符串表示形式。 它的函数原型如下:
printf("Could not open input file '%s' (error '%s')\n", filename, av_err2str(ret));
return ret;
}
// 获取文件流信息
if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
printf("Could not find stream information\n");
return -1;
}
// 操作文件内容
// ...
// 最后,释放分配的内存
avformat_close_input(&fmt_ctx);
上記のコードでは、まずavformat_open_input
関数を使用して入力ファイルを開き、新しいAVFormatContext
構造体を割り当てました。次に、avformat_find_stream_info
関数を使用してファイル ストリーム情報を取得しました。次に、AVFormatContext
変数fmt_ctx
に保存されている情報を使用してファイルのデータを処理できます。最後に、割り当てられたメモリを解放し、入力ファイルを閉じます。
avformat_find_stream_info
avformat_find_stream_info 関数は、ストリーム タイプ、エンコード情報、フレーム レート、解像度など、オーディオ ファイルおよびビデオ ファイル内のすべてのストリームの詳細情報を取得するために使用される関数です。
関数プロトタイプ:
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
パラメータの説明:
ic
: オーディオおよびビデオ ファイルのコンテキストを示す AVFormatContext 型のポインター。options
: AVDictionary タイプのポインタ。追加のオプション パラメータを示します。NULL にすることもできます。
この関数は、成功した場合は値 0 を返し、それ以外の場合は失敗した場合に値 0 を返します。関数の実行後、AVFormatContext のメンバー変数 AVStream には、オーディオ ファイルとビデオ ファイル内のすべてのストリームの詳細情報が格納されます。
by_find_best_stream
av_find_best_stream 関数の機能は、複数のストリームから特定のタイプの最適なオーディオおよびビデオ ストリームを自動的に検索することです。ビデオ ストリーム、オーディオ ストリーム、字幕ストリームなどを検索するために使用できます。
「最適なオーディオおよびビデオ ストリーム」とは、オーディオ ファイルおよびビデオ ファイルの再生または処理に最も適したオーディオおよびビデオ ストリームを指します。どのストリームを最適なストリームとして選択するかは、ユーザーのニーズと使用シナリオによって異なります。通常、次の要素を考慮する必要があります。
- ストリームの種類: オーディオ ストリーム、ビデオ ストリーム、字幕ストリームなど。
- メディア品質: ビットレート、解像度、フレームレートなど。
- エンコード形式: 一般的なオーディオ エンコード形式には、MP3、AAC などが含まれます。一般的なビデオ エンコード形式には、H.264、H.265 などが含まれます。エンコード形式が異なると、デコードに異なるデコーダが必要になります。
一般に、ユーザーは、メディア品質が高く、デバイスと互換性のあるエンコード形式を備えたストリームを最適なストリームとして選択したいと考えます。
関数プロトタイプ:
int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type, int wanted_stream_nb, int related_stream, AVCodec **decoder_ret, int flags);
パラメータの説明:
ic
: 入力の AVFormatContext。type
: 目的の AVMediaType。(オーディオストリーム、ビデオストリーム、メディアストリームの取得など)wanted_stream_nb
: 検索対象のストリームのインデックス -1 の場合、検索対象のストリームが不明であることを意味し、最初に検索対象のストリームのインデックスを返します。related_stream
: このパラメータは、検索時に参照ストリームとして使用でき、一部のメディア ファイルの照合に役立ちます。-1 に設定すると、関連付けられたストリームは発生しません。(通常は -1 に設定されます)decoder_ret
: 使用するデコーダを示す AVCodec 型のポインタ。NULL の場合、デコーダは自動的に選択されます。flags
: このパラメータは、検索中に追加のヒントを提供します。に設定するAVFIND_BEST_STREAM_SKIP_STREAM
と、関数はフレーム番号がゼロの最初のストリームをスキップします。AVFIND_BEST_STREAM_AUTOISO
に設定すると、この機能は最適な ISO ビットレート設定を自動的に選択します。(通常は 0 に設定されます)
関数の戻り値は見つかったストリームのインデックスです。-1 は見つからないことを意味します。
サンプルコード:
int video_stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0);
if (video_stream_index < 0) {
printf("Failed to find a video stream\n");
return -1;
}
この例では、av_find_best_stream
関数を使用して入力ファイル内で最適なビデオ ストリームを検索し、そのインデックスをvideo_stream_index
変数に保存します。この関数では、目的のメディア タイプ (ビデオ) を指定し、他のパラメータをデフォルト値に設定します。適切なストリームが見つかった場合、関数はストリームのデコーダ情報 (存在する場合) を設定します。
avfromat_close_input
は入力カプセル化形式のコンテキストを閉じるために使用される関数です。関数のプロトタイプは次のとおりです。
void avformat_close_input(AVFormatContext **ps);
- ps: 閉じる入力フォーマットコンテキストへのポインタへのポインタ。
この関数は、開いている入力フォーマット コンテキストを閉じ、そのメモリ空間を解放するために使用されます。この関数は、開いているファイル、デコーダ、さまざまなバッファなど、コンテキスト オブジェクトによって占有されているすべてのリソースを したがって、入力フォーマット コンテキスト オブジェクトが不要になった場合は、メモリ リークを避けるために、この関数を呼び出してメモリ領域を解放する必要があります。
渡された ps パラメータが NULL の場合、関数は何も行いません。
たとえば、次のコードを使用して、開いている入力形式コンテキストを閉じることができます。
AVFormatContext *fmtCtx;
avformat_open_input(&fmtCtx, "input.mp4", NULL, NULL);
// ... do something ...
avformat_close_input(&fmtCtx);
このコードは、「input.mp4」というファイルを開き、それにいくつかの操作を行った後、avformat_close_input 関数を使用して入力形式コンテキストを閉じます。
avformat_alloc_context
avformat_alloc_context 関数の機能は、AVFormatContext タイプの構造体にスペースを割り当て、それを初期化することです。
この関数のプロトタイプは次のとおりです。
AVFormatContext *avformat_alloc_context(void);
この関数を呼び出すと、AVFormatContext
構造体への割り当てられたポインタが返されます。
avformat_free_context
avformat_free_context は、フォーマット コンテキスト メモリ領域を解放するために使用される関数です。関数のプロトタイプは次のとおりです。
void avformat_free_context(AVFormatContext *s);
- s: メモリ空間を解放する必要があるフォーマット コンテキスト オブジェクト。
この関数は、フォーマット コンテキスト オブジェクトによって占有されているメモリ領域を解放し、オブジェクトを NULL に設定するために使用されます。avformat_close_input 関数とは異なり、この関数はフォーマット コンテキスト自体が占有しているメモリ領域を解放するだけで、開いているファイル、デコーダ、さまざまなバッファなど、オブジェクトが占有している他のリソースは解放しません。したがって、フォーマット コンテキスト オブジェクトを使用する必要がなくなった場合、他のリソースを解放する必要がない場合は、この関数を直接呼び出してメモリ領域を解放できます。
渡された s パラメータが NULL の場合、関数は何も行いません。
たとえば、次のコードを使用して、フォーマット コンテキスト オブジェクトが占有しているメモリ領域を解放できます。
AVFormatContext *fmtCtx;
avformat_open_input(&fmtCtx, "input.mp4", NULL, NULL);
// ... do something ...
avformat_free_context(fmtCtx);
このコードは、「input.mp4」という名前のファイルを開き、それにいくつかの操作を行った後、avformat_free_context 関数を使用してそのメモリ領域を解放します。
by_guess_format
av_guess_format 関数は、指定されたファイルの入力または出力形式を自動的に推測するために使用されます。ファイル拡張子または既知のファイル形式によって推測されます。通常、これは、ファイルを開く前にファイル形式を自動的に検出し、正しいデマルチプレクサまたはマルチプレクサが AVFormatContext 構造に設定されるようにするために使用されます。
関数プロトタイプ:
AVOutputFormat *av_guess_format(const char *short_name,
const char *filename,
const char *mime_type);
関数パラメータの説明:
- short_name: 「mp4」、「mpeg」などの短い形式名。
- filename: 推測するファイル形式のファイル名。NULL の場合、形式の推測に short_name のみが使用されることを意味します。
- mime_type: オプションの MIME タイプに使用されます。NULL の場合、形式を推測するために short_name と filename のみを使用することを意味します。
この関数は AVOutputFormat 構造体へのポインタを返します。入力または出力形式が一致しない場合、関数は NULL を返します。
av_guess_format
次に、動作を見てみましょう。
- null でない場合は
short_name
、名前に基づいてファイル形式を推測し、ファイル形式が見つかった場合はそのファイル形式へのポインタを返し、それ以外の場合は NULL を返します。 - null でない場合は
filename
、ファイル名の拡張子に基づいてファイル形式を推測し、ファイル形式が見つかった場合はそのファイル形式へのポインタを返し、それ以外の場合は NULL を返します。 - null でない場合は
mime_type
、ファイルの MIME タイプに基づいてファイル形式を推測し、ファイル形式が見つかった場合はそのファイル形式へのポインタを返し、それ以外の場合は NULL を返します。 short_name
、 、filename
および がすべて空の場合はmime_type
、NULL を返します。AVOutputFormat
構造内のフィールドname
は形式の名前を表し、extensions
フィールドは形式のサポートされているすべての拡張子を表し、mime_type
フィールドは形式の MIME タイプを表します。
AVOutputFormat
したがって、返された構造に従って、フォーマット名、サポートされている拡張子、MIME タイプなどのフォーマットに関する情報を取得できます。
avformat_alloc_output_context2
avformat_alloc_output_context2 は FFmpeg ライブラリの関数であり、オーディオおよびビデオのエンコード データをファイルまたはその他のメディア出力ストリームに書き込むための出力形式を持つ AVFormatContext オブジェクトを生成するために使用されます。
(avformat_alloc_contextとav_guess_formatの組み合わせ)と同等
関数のプロトタイプは次のとおりです。
int avformat_alloc_output_context2(AVFormatContext **ctx,
AVOutputFormat *oformat,
const char *format_name,
const char *filename);
このうち、パラメータの意味は次のとおりです。
- ctx: 出力フォーマットの AVFormatContext オブジェクト ポインタ
- offormat: 出力形式の AVOutputFormat オブジェクト。出力データの形式を指定するために使用されます。
- format_name: 出力形式の名前を推測するために使用されます。ofat が NULL の場合、このパラメーターに従って推測されます。NULL にすることもできます。、NULL にすることもできます。
- filename: 出力ファイルのファイル名を記述する文字列パラメータ。NULL にすることもできます。
この関数は、出力形式を自動的に推測することも、ofat パラメーターに従って出力形式を手動で指定することもできます。offormat パラメータと format_name パラメータの両方が指定されている場合は、offormat パラメータが優先されます。
関数の戻り値はゼロで、AVFormatContext オブジェクトが正常に生成されたことを示します。それ以外の場合は、負のエラー コードが返されます。
avio_open2
avio_open2 の主な機能は、AVIOContext オブジェクトをバインドし、指定された URL に関連付けることです。関数のプロトタイプは次のとおりです。
int avio_open2(AVIOContext **s, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options);
この関数のパラメータは次の意味を持ちます。
-
**s: AVIOContext、入力および出力コンテキストへのポインター。
-
url: 開く URL。ローカル ファイルまたはネットワーク アドレスを指定できます。
-
flags: URL を開くためのオプション フラグ。次のフラグを組み合わせることができます。
AVIO_FLAG_READ
: URL を読み取りモードで開きます。AVIO_FLAG_WRITE
: URL を書き込みモードで開きます。AVIO_FLAG_READ_WRITE
: URL を読み取り/書き込みモードで開きます。AVIO_FLAG_NONBLOCK
: URL をノンブロッキング モードで開きます。AVIO_FLAG_DIRECT
: キャッシュを無効にして直接操作します。AVIO_FLAG_EXCL
: URL を排他モードで開きます。AVIO_FLAG_CREAT
: URL が存在しない場合は作成します。AVIO_FLAG_TRUNC
: URL コンテンツをクリアします。AVIO_FLAG_APPEND
:URLの最後に記載します。AVIO_FLAG_NOBUFFER
: キャッシュを無効にします。
-
int_cb: int_cb は、割り込み要求を検出するためのコールバック関数ポインタであり、データの読み取りまたは書き込み時に割り込み信号を検出できます。ユーザーが null 以外のコールバック関数を指定した場合、FFmpeg はそれを定期的に呼び出して中断を許可します。コールバック関数が設定されていない場合は、NULL に設定します。
-
options: 指定されるその他のオプションはオプションであり、多くの場合、使用するトランスポート プロトコル、タイムアウト、プロキシ設定などのアプリケーション固有のオプションを渡すために使用されます。コールバック関数が設定されていない場合は、NULL に設定します。
// 输出文件上下文(&oFmtCtx->pb)与目标文件(dst)进行绑定
avio_open2(&oFmtCtx->pb, dst, AVIO_FLAG_WRITE, NULL, NULL);
// 写多媒体文件头到目的文件
ret = avformat_write_header(oFmtCtx, NULL);
// 用于将音频数据写入到目标文件中
av_interleaved_write_frame(oFmtCtx, &pkt);
//写多媒体文件尾到文件中
av_write_trailer(oFmtCtx);
私の理解は次のとおりです。出力ファイルのコンテキストを通じてターゲットファイルとバインドします。VIOContext オブジェクト oFmtCtx->pb は、ターゲット ファイル (つまり、dst が指すファイル) に関連付けられます。avformat_write_header(oFmtCtx, NULL),av_interleaved_write_frame(oFmtCtx, &pkt);av_write_trailer(oFmtCtx);
対象ファイルに書き込むことです。
avformat_new_stream
avformat_new_stream()
Function はFFmpeg で新しいストリーム (Stream) を作成するために使用される関数です。
関数プロトタイプ:
AVStream *avformat_new_stream(AVFormatContext *ctx, const AVCodec *codec);
関数パラメータ:
ctx
: AVFormatContext タイプ。FFmpeg のフォーマット コンテキストを指し、さまざまなマルチメディア ファイル形式の読み書きに使用されます。codec
: AVCodec タイプ。コーデックの AVCodec 構造を指します。
関数は次を返します。
- 成功: 新しく作成された AVStream ポインター。
- 失敗: NULL。
avcodec_parameters_copy
avcodec_parameters_copy 関数は、ある AVCodecParameters 構造体のパラメータを別の AVCodecParameters 構造体にコピーするために使用されます。
関数プロトタイプ:
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src);
関数パラメータ:
dst
: AVCodecParameters タイプ。ターゲットの AVCodecParameters 構造体ポインターを指します。src
: AVCodecParameters タイプ。ソース AVCodecParameters 構造体ポインターを指します。
src
エンコーダのパラメータ情報は に格納されます。からコピーされたエンコーダのパラメータ情報をdst
格納するために使用されます。src
関数は次を返します。
- 成功: 0。
- 失敗: 負のエラー コード。
この関数は主に、出力ファイルのエンコーダ パラメータが入力ファイルと一致するように、入力ストリームのエンコーダ パラメータから出力ストリームのエンコーダ パラメータをコピーするために使用されます。この関数を使用してエンコーダ パラメータをコピーする場合、ターゲットの AVCodecParmaeters 構造体にメモリが割り当てられている必要があり、割り当てられていない場合はエラーが発生することに注意してください。
avformat_write_header
avformat_write_header()
この関数は FFmpeg でマルチメディア フォーマット ヘッダー関数をために使用され、その宣言は次のとおりです。
int avformat_write_header(AVFormatContext *s, AVDictionary **options);
このうち、パラメータはs
出力ファイルの AVFormatContext 構造体へのポインタです。パラメータoptions
は辞書オブジェクトへのポインタでありAVDictionary
、追加情報を渡すために使用されるオプションのパラメータです。通常は NULL に設定できます。これは、特別なオプションは必要なく、デフォルト値が使用されることを意味します。
関数の戻り値:
関数の戻り値はエラー コードであり、0 が返された場合は操作が成功したことを意味し、負の数が返された場合は操作が失敗したことを意味します。
この関数を使用する前に、フォーマット パラメーターやメディア ストリーム情報の設定を含め、最初に AVFormatContext 構造を初期化する必要があります。さらに、この関数を呼び出す前に、このavio_open2
関数を使用して出力ファイルを開き、それをパッケージ化形式コンテキストに関連付ける必要があります。
by_read_frame
av_read_frame()
この関数を呼び出す主な目的は、入力ファイル内のデータの次のフレームを読み取ることです。この関数は、入力ファイルからデータのフレームを自動的にデコードし、AVPacket 構造に格納します。呼び出し元は、読み取りが完了した後、pkt データ用にメモリを解放する必要があります。その宣言は次のとおりです。
int av_read_frame(AVFormatContext *s, AVPacket *pkt);
このうちパラメータは、入力マルチメディア形式のコンテキスト、つまり入力ファイルの基本情報と属性を表すために使用される構造体へのポインタですs
。パラメータは、読み取られたデータ フレームを表すために使用されるデータ パケット構造へのポインタです。AVFormatContext
pkt
AVPacket
この関数のサンプルコードは次のとおりです。
int ret;
AVPacket pkt;
while (av_read_frame(inputFormatContext, &pkt) >= 0) {
/* 处理pkt中的音频、视频或字幕数据 */
av_packet_unref(&pkt);
}
上記の例では、while ループを使用して入力ファイルの次のフレームのデータを読み取ります。関数の戻り値が 0 未満の場合は、ファイルの終わりを読み取ったか、エラーが発生したことを意味します。 、この時点でループは終了します。毎回データのフレームを読み取った後、 av_packet_unref を呼び出してメモリを解放する必要があります。pkt データを処理する場合、pkt の stream_index フィールドを使用してデータのタイプを取得し、タイプごとに異なる処理を実行できます。
シークフレームの
av_seek_frame
は、メディア ファイル内の特定のタイムスタンプ ** を見つけるために使用される FFmpeg ライブラリ内の関数 ** です。通常、ビデオまたはオーディオ ファイル内の特定のフレームまたは時間位置に移動するために使用されます。AVFormatContext (ストリーム形式情報を保存する)、ストリーム インデックス、タイムスタンプ、シーク フラグなどのパラメータを受け入れます。
関数のプロトタイプは次のとおりです。
int av_seek_frame(AVFormatContext *format_context, int stream_index,
int64_t timestamp, int flags)
AVFormatContext *format_context
: メディア ファイルのフォーマット コンテキスト構造。メディア ファイルのフォーマット情報とメディア ストリームの関連情報が含まれます。int stream_index
: 検索対象のメディア ストリームのインデックス値を表します。int64_t timestamp
: 特定されるタイムスタンプをマイクロ秒単位で表します。int flags
: 位置を表すフラグ。検索モードを指定するために使用されます。次の値のいずれかを選択できます。AVSEEK_FLAG_BACKWARD
: 逆方向に見ること、つまり、指定されたタイムスタンプより前の最も近いフレームに位置することを示します。AVSEEK_FLAG_BYTE
: 正確な検索、つまり、指定されたタイムスタンプの場所を特定することを示します。AVSEEK_FLAG_ANY
: 無制限の検索、つまり任意の位置から指定されたタイムスタンプを検索することを示します。AVSEEK_FLAG_FRAME
: フレーム単位で検索すること、つまり、指定されたタイムスタンプに最も近いキー フレームの位置を特定することを示します。
最後に、この関数は成功した場合は負でない整数を返し、失敗した場合はエラー コードを返します。この関数は通常、メディア ファイル内の特定のフレームまたは時間位置を見つけるために使用されます。
av_rescale_q_rnd
av_rescale_q_rnd()
FFmpeg でタイムスタンプ値の変換に使用される関数です。オーディオおよびビデオ コーデック、フィルタリング、その他の操作では、タイムスタンプ値を入力情報の時間ベース (サンプリング レート、フレーム レートなど) から出力情報の時間ベース (出力サンプリング レート、フレーム レートなど) に変換する必要があることがよくあります。フレームレート)。av_rescale_q_rnd()
このプロセスはより便利に実行できます。
関数の宣言は次のとおりです。
int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq, enum AVRounding rnd);
このうちパラメータはa
タイムスタンプに変換する値を示し、bqはソースタイムスタンプのタイムベース、cqはターゲットタイムスタンプのタイムベース、rndは指定された丸め方法を示します。
この関数は、タイムスタンプ値をtimebasea
からbq
timebase に変換し、cq
丸め方法に従ってrnd
丸め、変換されたタイムスタンプ値を返します。
たとえば、100 サンプル ポイントのタイムスタンプを入力サンプリング レート 44100 から出力サンプリング レート 48000 に変換する必要があります。これは、次のコード スニペットで実現できます。
AVRational in_timebase = {
1, 44100};
AVRational out_timebase = {
1, 48000};
for (int i = 0; i < 100; i++) {
int64_t ts = av_rescale_q_rnd(i * in_timebase.num, in_timebase, out_timebase, AV_ROUND_NEAR_INF);
// 进行相应的处理
......
}
上記のコードでは、まず入力および出力のサンプリング レートに対応するタイム ベースをそれぞれ 1/44100 および 1/48000 として定義します。次に、av_rescale_q_rnd()
関数を使用してサンプリング ポイントのタイムスタンプを入力タイムベースから出力タイムベースに変換し、変換されたタイムスタンプをts
変数に格納します。変換が完了したら、対応するサンプリング処理を実行できます。
av_rescale_q_rnd()
タイムスタンプ変換に関数を使用する場合、入力および出力のタイムベースを明確に定義する必要があり、特定のシナリオに従って適切な丸め方法を選択する必要があることに注意してください。丸め方法には次の 4 つがあります。
AV_ROUND_ZERO
:0に丸めるAV_ROUND_INF
: 切り上げ (線から最も遠い整数を取得します)AV_ROUND_DOWN
:切り捨てAV_ROUND_NEAR_INF
: 最も近い値に切り上げます。
タイムスタンプ変換を実行するときは、特定のシナリオに従って適切な丸め方法を選択する必要があります。
av_interleaved_write_frame
av_interleaved_write_frame関数は、エンコードされたオーディオ データとビデオ データを出力ファイルに書き込むために使用されます。この関数のプロトタイプは次のとおりです。
int av_interleaved_write_frame(AVFormatContext *context, AVPacket *packet);
パラメータの説明:
- context: 開かれたメディア ファイルの AVFormatContext 構造体へのポインタ。
- packet: 書き込まれるオーディオまたはビデオ フレーム データを含む AVPacket 構造体へのポインタ。
関数の使用結果は明確な戻り値ではありませんが、AVOutputFormat 構造体の write_packet コールバック関数を参照することで、マルチメディア ファイル出力のステータスを取得できます。コールバック関数が負の数を返した場合は、データの書き込み中にエラーが発生したことを意味します。
by_rescale_q
FFmpeg では、av_rescale_q 関数を使用して2 つの異なるタイムベースの値を変換します。ある時間軸の値を別の時間軸の値にスケールします。この関数は、AVRatioal 構造体を使用してタイムベースを定義します。
関数定義:
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq);
パラメータの説明:
- a: 変換する値
- bq: 変換する値の時間軸
- cq: 変換先のタイムベース
戻り値:変換後の値、型は int64_t
of_packet_rescale_ts
av_packet_rescale_ts() 関数は、AVPacket 構造体のタイムスタンプ (pts、dts) をあるタイムベースから別のタイムベースに変換できます。その関数プロトタイプは次のとおりです。
int av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb);
このうち、パラメータ pkt はタイムスタンプに変換される AVPacket 構造体を指し、src_tb は pkt 内のタイムスタンプのタイムベースを示し、dst_tb はタイムスタンプを変換する必要があるタイムベースを示します。
av_rescale_q より手間が少ない
of_packet_unref
av_packet_unref 関数は、AVPacket 構造内のリソースを解放するために使用されます。
AVPacket 構造内のリソースの解放は、通常、オーディオおよびビデオ データ パケットが使用された後にメモリ リソースを再利用する操作です。この関数は、AVPacket 構造内のすべてのリソース (メモリ、参照カウント 1 など) をクリアし、その後の再利用のために AVPacket 構造自体を予約します。これは、構造全体を直接解放するよりも効率的です。
この関数のプロトタイプは次のとおりです。
void av_packet_unref(AVPacket *pkt);
このうち、pkt は AVPacket 構造体であり、解放する必要があります。
by_packet_free
この関数は、AVPacket 構造体とその中のすべてのリソース (メモリ、参照カウントなど) を解放し、AVPacket 構造体自体も解放します。そのため、AVPacket 構造体は将来使用できなくなります。
この関数の関数プロトタイプは次のとおりです。
void av_packet_free(AVPacket **pkt);
of_packet_move_ref
AVPacket パケット オブジェクトへのバッファ参照の転送用。
この関数のプロトタイプは次のとおりです。
void av_packet_move_ref(AVPacket *dst, AVPacket *src);
そのパラメータは、ターゲット AVPacket オブジェクト ポインタ dst とソース AVPacket オブジェクト ポインタ src です。
機能:ターゲット AVPacket オブジェクトのバッファ参照値をソース AVPacket オブジェクトのバッファ参照値に設定します。ソース src オブジェクトが占有しているスペースを解放しますが、src 構造体は解放しません。
by_calloc
av_calloc は FFmpeg のメモリ割り当て関数であり、関数のプロトタイプは次のとおりです。
void *av_calloc (size_t nmemb, size_t size);
この関数の機能は、nmemb 要素で構成されるメモリ空間を割り当て、各要素のサイズが size バイトであり、空間内の各ビットを 0 に初期化することです。av_calloc 関数は C 言語の calloc 関数に似ていますが、av_calloc はメモリ割り当てに FFmpeg の内部メモリ マネージャーを使用するため、割り当てられたメモリ ブロックが FFmpeg でサポートされているアライメント方法であることを保証でき、メモリ アライメントを効果的に回避できます。問題、読み取りおよび書き込みエラー。
av_calloc 関数を使用してメモリ領域を割り当てるサンプル コードは次のとおりです。
int *p = (int *)av_calloc(10, sizeof(int));
if (p == NULL) {
// 内存分配失败,进行相关处理
} else {
// 成功分配内存,进行相关操作
p[0] = 1;
p[1] = 2;
// ...
av_free(p); // 使用完后需要释放空间
}
av_calloc 関数を使用して割り当てられたメモリは、av_free 関数を使用して解放する必要があり、解放されたメモリ アドレスが av_calloc パラメータで返されたポインタ アドレスと一致していることを確認する必要があることに注意してください。そうしないと、メモリ リークやその他の問題が発生する可能性があります。
of_fifo_alloc2
機能: AVFifo を割り当てて初期化します。
関数のプロトタイプは次のとおりです。
AVFifo* av_fifo_alloc2 ( size_t elems,
size_t elem_size,
unsigned int flags )
パラメータ:
- elmes: 元のキューの数
- elem_size: 各要素のバイト単位のサイズ。
- flags: AV_FIFO_FLAG_NONBLOCK などの FIFO バッファのフラグを指定します。これは、バッファがいっぱいまたは空の場合にブロックせず、ただちにエラーを返すことを意味します。AV_FIFO_FLAG_AUTO_GROW は、FIFO バッファがいっぱいの場合、エラーを返さずにバッファのサイズが自動的に拡張されることを意味します。
成功すると AVFIifo を割り当てます。
by_fifo_read
av_fifo_read() 関数は、FIFO キューからデータを読み取るためにFFmpeg ライブラリで使用される関数であり、その関数プロトタイプは次のとおりです。
int av_fifo_read ( AVFifo * f,
void * buf,
size_t nb_elems
)
関数パラメータには次の意味があります。
f
: データを読み取る AVFifo ポインタへのポインタ。buf
: バッファ nb_elems を指す * av_fifo_elem_size(f) バイトは、成功すると buf に書き込まれます。- nb_elems: 要素の数。
この関数は、成功した場合は負でない値を返し、失敗した場合は負の値を返します。
by_fifo_write
関数の役割: av_fifo にデータを書き込む
int av_fifo_write ( AVFifo * f,
const void * buf,
size_t nb_elems )
パラメータ:
- f: 書き込まれる AVfifo キュー
- buf: 書き込まれるデータ。
- nb_elems: 書き込まれた要素の数。
戻り値:
成功した場合は負ではない数値を返し、失敗した場合は負の数値を返します。
by_fifo_freep2
void av_fifo_freep2 ( AVFifo ** f )
AVFifo を解放し、ポインタを NULL にリセットします。
-
パラメーター
解放するAVFifoへの fPointer 。*f == NULL は許可されます。
avcodec_alloc_context3
コーデックの割り当てと初期化に使用されるコンテキスト
avcodec_alloc_context3 関数のプロトタイプは次のとおりです。
AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);
codec は、使用するコーデックへのポインタです。特定のコーデックを指定する必要がない場合は、NULL に設定します。
戻り値は、割り当てられ初期化された AVCodecContext 構造体へのポインタ、またはエラーが発生した場合、またはメモリを割り当てられなかった場合は NULL です。
avcodec_free_context
avcodec_free_context は、AVCodecContext 構造体のメモリを解放するためにFFmpeg で使用される関数です。
次に、avcodec_free_context 関数の宣言を示します。
void avcodec_free_context(AVCodecContext **avctx);
この関数は、AVCodecContext 構造体によって適用されたメモリ空間を解放します。パラメータ avctx は、AVCodecContext 構造体ポインタへのポインタです。この関数を使用する場合、渡される AVCodecContext 構造体ポインターは avcodec_alloc_context3 関数を通じて適用する必要があることに注意してください。
avcodec_find_encoder
avcodec_find_encoder()
これは FFmpeg の関数であり、エンコーダ ID または名前に従って一致するエンコーダを検索し、ポインタを返すために使用されます。この関数は、エンコーダを使用する前にエンコーダを登録する必要があります
その関数プロトタイプは次のとおりです。
AVCodec *avcodec_find_encoder(enum AVCodecID id);
avcodec_find_encoder()
エンコーダー ID に基づいて一致するエンコーダーを検索し、ポインターを返します。
ここで、はタイプのエンコーダ IDid
ですenum AVCodecID
avcodec_find_encoder_by_name
avcodec_find_encoder_by_name は、指定されたエンコーダーを検索するために FFmpeg で使用される関数で、指定されたエンコーダー名に従って、対応する AVCodec 構造体ポインターを検索して返します。
以下は、avcodec_find_encoder_by_name 関数の関数プロトタイプです。
AVCodec *avcodec_find_encoder_by_name(const char *name);
このうち、nameパラメータは検索対象のエンコーダの名前です。指定された名前のエンコーダーが見つかった場合は、AVCodec 構造体へのポインターが返されます。見つからない場合は NULL を返します。
サンプルコード:
// 查找x264编码器
AVCodec *codec = avcodec_find_encoder_by_name("libx264");
if (codec == NULL) {
fprintf(stderr, "Could not find the x264 encoder.\n");
return -1;
}
// 初始化AVCodecContext结构体
AVCodecContext *codec_context = avcodec_alloc_context3(codec);
if (codec_context == NULL) {
fprintf(stderr, "Could not allocate codec context.\n");
return -1;
}
// 设置编码参数
codec_context->bit_rate = 500000;
codec_context->width = 1280;
codec_context->height = 720;
codec_context->time_base = (AVRational) {
1, 25};
// ...
上記のコードでは、指定されたエンコーダー (ここでは x264 エンコーダー) は、avcodec_find_encoder_by_name 関数を呼び出すことによって検索されます。指定された名前のエンコーダが見つかった場合は AVCodec 構造体へのポインタを返し、見つからない場合は NULL を返します。このポインターを使用してエンコーダー関連の情報とパラメーターを取得し、その後のエンコード操作を実行できます。実際の使用では、上の例に示すように、AVCodecContext 構造体にいくつかのエンコーダ パラメータを設定する必要もあります。
of_frame_alloc
av_frame_alloc は、AVFrame 構造のメモリを適用するために使用される関数です。AVFrame 構造体に必要なメモリを適用して初期化し、AVFrame 構造体へのポインタを返します。一般に、AVFrame 構造体を使用する前に、av_frame_alloc を呼び出して初期化し、メモリを適用する必要があります。
次のように定義されます。
AVFrame *av_frame_alloc(void);
この関数は、AVFrame 構造体を動的に割り当て、そのメモリをすべてクリアして、その構造体へのポインタを返します。
av_frame_alloc 関数を使用して AVFrame を割り当てるサンプル コードは次のとおりです。
AVFrame *frame = av_frame_alloc();
if (!frame) {
// 处理分配内存失败的情况
}
割り当てられた AVFrame を使用した後、 av_frame_free 関数を呼び出してメモリを解放する必要があります。
av_frame_get_buffer
av_frame_get_buffer() は FFmpeg の関数で、AVFrame 構造体のデータ フィールドにメモリ領域を割り当てるために使用されます。
ビデオのエンコードとデコードに FFmpeg を使用する場合、プログラムは AVFrame 構造を使用してビデオ フレーム データを保存する必要があります。この構造体を使用する前に、メモリ領域を割り当てる必要があります。
av_frame_get_buffer() 関数は、AVFrame 構造体にメモリを割り当てるのに役立ちます。av_frame_get_buffer 関数は、AVFrame 内の各データ ポインタにメモリを割り当てます。その関数プロトタイプは次のとおりです。
int av_frame_get_buffer(AVFrame *frame, int align);
このうち、frame はメモリ空間を割り当てる必要がある AVFrame 構造で、align はメモリ アライメントのサイズを示し、通常はデフォルトのメモリ アライメントを示す 0 に設定されます。
この関数は、AVFrame にメモリが正常に割り当てられたかどうかを表す整数値を返し、成功した場合は 0 を返し、失敗した場合は AVERROR を返します。
この関数は、AVFrame 構造のメモリ空間を割り当てて初期化し、後で操作しやすくします。AVFrame 構造体を使用した後は、メモリ リークを避けるために av_frame_free() 関数を使用してメモリ空間を解放する必要があることに注意してください。
av_frame_alloc と av_frame_get_buffer の関係に注意してください。
まず、メモリの適用とメモリの割り当てという 2 つの概念を理解します。
メモリの申請: システムにスペースを申請します。
メモリの割り当て:すでに適用されている場所の特定の場所にデータを与えることです。
メモリを申請することは、地主(システム)に土地の一部を求めることに相当し、メモリの割り当ては、その土地の一定のエリアで小麦を栽培すること(割り当て)に相当します。
メモリの申請と割り当てのプロセスは、多くの場合相互に連携します。つまり、最初にメモリ空間のセクションを申請し、次にメモリ空間のこのセクションに基づいていくつかの小さなメモリ領域を割り当て、これらの小さなメモリ領域を使用します。データを保存するため。この方法により、一般にメモリ使用率が向上し、メモリの断片化が軽減されます。
したがって、関係は次のようになります。
Av_frame_alloc は一般的に使用されるメモリ アプリケーション関数で、AVFrame 構造体が必要とするメモリを適用して初期化し、AVFrame 構造体へのポインタを返します。
av_frame_get_buffer は、既に適用されている AVFrame 構造体にメモリを割り当てる関数で、AVFrame に既に設定されているパラメータ (幅、高さ、ピクセル形式、サンプリング形式など) に従ってメモリを割り当てます。av_frame_get_buffer 関数を使用すると、AVFrame のデータ領域をサンプリング データまたはピクセル データの保存に使用できるようになります。
avcodec_send_frame
avcodec_send_frame 関数は FFmpeg ライブラリ内の関数で、フレーム データをエンコーダに送信するために使用されます。この関数はビデオ フレームのデータをエンコーダに送信し、対応するエンコーダがフレームをエンコードします。具体的な使用方法と関連パラメータは次のように分析されます。
関数プロトタイプ:
int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame);
パラメータの説明:
- AVCodecContext *avctx:
エンコーダーのコンテキスト。 - const AVFrame *frame:
ビデオ ピクセル データとオーディオ サンプル データを含む、エンコードされるビデオ フレーム データ。
戻り値:
- 成功した場合は 0 を返します。
- 他の値が返された場合は、送信が失敗したか、送信バッファがいっぱいになったことを意味します。
関数関数:
avcodec_send_frame 関数は、エンコードするビデオ フレーム データをエンコーダーに送信し、エンコード プロセスを開始するために使用されます。ビデオフレームには、ビデオピクセルデータ、オーディオサンプルデータなどが含まれる。関数の実行後、すべてのデータがエンコーダーの送信バッファーにロードされ、エンコーダーがエンコードするまで待機します。
avcodec_receive_frame
その役割は、コーデックの出力キューからデコードされた出力フレームを取得し、それを AVFrame 構造に格納することです。この関数の使用法を詳しく分析してみましょう。
関数のプロトタイプは次のとおりです。
int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
このうち、avctx はコーデックに関する情報を含む AVCodecContext 構造体へのポインタであり、frame はデコードされた出力フレームを格納するために使用される AVFrame 構造体へのポインタです。
この関数の戻り値の具体的な意味は次のとおりです。
-
戻り値は 0 です。通常の状態。関数が正常に実行され、有効な出力フレームが取得されたことを示します。
-
AVERROR_EOF: 「ファイルの終わり」、つまりファイルが終了したことを示します。その戻り値は通常、データ ストリームがオーディオおよびビデオのデコーダやエンコーダなどの関連関数で処理された状況を記述し、入力ストリームの終わりに達し、これ以上データが生成されないことを呼び出し元に通知するために使用されます。 。
ファイルの破損やネットワークの異常などにより、入力された音声や映像のストリームが正常に終了せず、データストリームが切り詰められる場合があることに注意してください。この時点で、AVERROR_EOF は正しい終了信号ではなく、現在のデータ ストリームが終了したことを意味するだけです。
デコーダは入力ストリーム内のデータを完全にデコードしました。
-
評者(また):
AVERROR(EAGAIN) は FFmpeg ライブラリのマクロ定義で、「Try again」、つまり再試行を意味します。通常、その戻り値はエラーではありませんが、現在の操作がいくつかの準備完了操作 (キャッシュ内のデータの準備ができているなど) を待つ必要があるか、追加のデータが到着するのを待つ必要があることを示します。
FFmpeg では、通常、AVERROR (EAGAIN) は、デコーダ、エンコーダ、入出力デバイスなどの関連機能の内部バッファ データに有効なデータがない場合の状態を記述するために使用されます。たとえば、 avcodec_receive_frame 関数を使用してデコーダからオーディオ フレームとビデオ フレームを取得する場合、AVERROR(EAGAIN) が返された場合、通常はデコーダ バッファに利用可能なフレームがなく、追加のデータ入力を待つ必要があることを意味します。この時点で、デコーダへのデータの送信を継続し、次のデータ フレームのデコードが完了するまで avcodec_receive_frame 関数を再度呼び出すことができます。
したがって、AVERROR(EAGAIN) の戻り値が発生した場合、プログラムは実際の状況に応じて一定期間待機してから操作を再実行するか、他の手段でデータ入力を増やす必要があります。
-
その他のエラー コード: デコード プロセス中に他のエラーが発生したことを示します。エラー コードは、av_strerror 関数を呼び出すことでエラー メッセージに変換できます。。
avcodec_receive_frame 関数を使用する前に、avcodec_send_packet を呼び出してエンコードされたデータをコーデックに送信する必要があります。コーデックがデコードされると、avcodec_receive_frame 関数はコーデックの出力キューからデコードされた出力フレームを取得します。
avcodec_receive_frame 関数については、次の点に注意する必要があります。
- avcodec_receive_frame 関数を呼び出す前に、コーデックにデコードするパケットがあるかどうかを確認する必要があります。そうでない場合、関数は永遠に待機することになります。
- デコーダ キューに利用可能なフレームがない場合、関数はキューにフレームが利用可能になるまで待機します。
- 関数の戻り値 0 は成功を意味し、-EAGAIN はデコードが完了していないことを意味し、AVERROR (EINVAL) はパラメーターが正しくないことを意味し、その他の戻り値はデコードが失敗したことを意味します。
- AVFrame 構造には、ビデオ ピクセル データやオーディオ サンプル データを含む、デコードされた出力フレームが格納されます。
つまり、avcodec_receive_frame 関数は、エンコーダのデコード後に出力フレームを取得するための重要な関数であり、FFmpeg でのデコード処理を完了するために avcodec_send_packet 関数と併用されることがよくあります。
av_frame_free
av_frame_free() は、AVFrame 構造体のメモリを解放するために FFmpeg で使用される関数です。
以下は av_frame_free() 関数の定義です。
void av_frame_free(AVFrame **frame);
関数パラメータは、AVFrame ポインターへのポインター、つまり、解放する必要がある AVFrame 構造体へのポインターのアドレスです。この関数を呼び出した後、AVFrame 構造体へのポインタは、ダングリング ポインタを避けるために NULL に設定されます。
avcodec_find_decoder
デコーダを見つけるために使用される関数の 1 つは、指定された codec_id に一致するデコーダの AVCodec 構造体ポインタを返します。
AVCodec 構造は、FFmpeg の avcodec.h ヘッダー ファイルで定義されており、デコーダー関連の情報と関数ポインターが含まれています。avcodec_find_decoder 関数を使用して、codec_id に基づいてデコーダを検索します。
次に、avcodec_find_decoder 関数の宣言を示します。
AVCodec *avcodec_find_decoder(enum AVCodecID id);
パラメータ id は、AVCodecID 列挙型で定義される AVCodecID 型のデコーダ ID です。
使用例:
// 查找H.264解码器
AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!codec) {
fprintf(stderr, "未找到解码器\n");
exit(1);
}
// 根据解码器申请AVCodecContext内存
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
上記サンプルコードでは、まず avcodec_find_decoder を使用して H.264 デコーダの AVCodec 構造体ポインタを検索し、見つからない場合はエラー メッセージを出力してプログラムを終了します。デコーダが見つかった場合は、そのデコーダを使用して AVCodecContext メモリを割り当てます。
avcodec_find_decoder 関数は登録されたデコーダのみを検索できるため、この関数を使用する前にすべてのデコーダが av_register_all 関数に登録されていることを確認する必要があることに注意してください。FFmpeg 4.0 より前のバージョンでは、avcodec_register_all 関数を使用してすべてのコーデックをすばやく登録することもできます。
avcodec_send_packet
その役割は、エンコードされたデータ パケットをデコードのためにコーデックに送信することです。
まず、パケット内のデータがバッファに送信され、エンコーダがデータをフェッチするのを待ちます。バッファがいっぱいになっている場合、avcodec_send_packet はバッファにパケットを保存するのに十分なスペースができるまで待機します。
その関数プロトタイプは次のとおりです。
int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
関数パラメータの説明:
- avctx: 開かれた AVCodecContext へのポインタ。
- avpkt: 送信する AVPacket へのポインタ。
このうち、avctx はカメラ、ファイル形式、コーデックなどの情報を含む AVCodecContext 構造体へのポインタ、avpkt はエンコードされたデータを含むパケットである AVPacket 構造体へのポインタです。
関数の戻り値は、送信結果を表す整数です。
- 0: 正常に送信されました。
- AVERROR_EOF: 現在の入力ストリームが終了しました。
- AVERROR(EAGAIN): デコーダは一時的に入力を受け入れることができないため、待機する必要があります。
- AVERROR(EINVAL): 引数が無効です。
avcodec_receive_packet
avcodec_receive_packet 関数は、エンコーダによって出力された圧縮データ パケットを取得するために使用される FFmpeg ライブラリの関数です。この関数は、エンコーダからエンコードされたデータ パケットを読み取り、取得した圧縮データを返します。具体的な使用方法と関連パラメータは次のように分析されます。
関数プロトタイプ:
int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt);
パラメータの説明:
- AVCodecContext *avctx:
エンコーダーのコンテキスト。 - AVPacket *avpkt:
エンコードされたパケット オブジェクトを格納します。
戻り値:
- 0 が返されると、エンコーダによって出力された圧縮データ パケットが正常に取得されたことを意味します。
- AVERROR_EOF が返されると、エンコーダの出力キューが空になったことを示します。
- 他の値が返された場合は、エンコーダーが出力した圧縮データ パッケージの取得に失敗したことを意味します。
関数関数:
avcodec_receive_packet 関数は、エンコーダからエンコードされたデータ パケットを読み取るために使用され、圧縮されたビデオ データ パケットを取得できます。これは、送信のためにファイルやネットワークなどに書き込むことができます。avcodec_send_frame 関数を呼び出した後、この関数を繰り返し呼び出して、データが完全に読み取られるまで出力圧縮データ パケットを読み取ることができます。
使用例:
次の例では、avcodec_receive_packet 関数を使用して、エンコーダから圧縮データのフレームを取得します。
AVCodecContext *codec_ctx; //编码器的上下文环境
AVPacket *avpkt; //存储编码好的数据包对象
//从编码器中获取一帧压缩数据
int ret = avcodec_receive_packet(codec_ctx, avpkt);
if (ret == 0) {
//压缩数据包获取成功
} else if (ret == AVERROR_EOF) {
//编码器输出队列被清空
} else {
//压缩数据包获取失败
}
上の例では、エンコーダから圧縮データ パケットのフレームを取得します。取得が成功すると、データ パケットを処理できます。AVERROR_EOF が返された場合は、エンコーダの出力キューがクリアされていることを意味し、サイクルを再開できます。終了; 他の値が返された場合は、圧縮データ パッケージの取得に失敗したことを意味し、エラー処理が必要です。この関数を使用する前に、エンコーダ コンテキストと圧縮パケット ストレージ オブジェクトを初期化する必要があることに注意してください。
avcodec_open2
Avcodec_open2 は、FFmpeg でデコーダを開くために使用される関数の 1 つで、AVCodecContext をデコーダにバインドし(つまり、AVCodecContext 構造体のデコーダ パラメータをデコーダと結合して、デコーダが解凍方法を認識できるようにします)、 AVCodecContext とデコーダ、デコードの準備としてデコーダを開くプロセス。
以下は avcodec_open2 関数の宣言です。
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
パラメータavctxはデコーダのパラメータ情報を格納するAVCodecContext構造体ポインタ、codecはオープンするデコーダの情報を示すAVCodec構造体ポインタ、optionsはオプションの辞書である。
使用例:
// 查找H.264解码器
AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!codec) {
fprintf(stderr, "未找到解码器\n");
exit(1);
}
// 根据解码器申请AVCodecContext内存
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
// 设置AVCodecContext参数
// ...
// 打开解码器
if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
fprintf(stderr, "无法打开解码器\n");
exit(1);
}
上記のサンプル コードでは、まず avcodec_find_decoder 関数を使用して H.264 デコーダーを検索し、AVCodec 構造体ポインター コーデックを取得します。次に、デコーダに応じて AVCodecContext メモリを適用し、そのパラメータを設定します。最後に、avcodec_open2 関数を使用してデコーダを開き、正常に開かれたかどうかを確認します。この例では、オプションを直接 NULL に設定していることに注意してください。
avcodec_open2 関数はデコーダを 1 回しか開くことができず、同じデコーダを複数回開くとエラーが発生することに注意してください。したがって、個々のケースでは、複数の AVCodecContext を使用して複数のデコーダを開く必要があります。
av_frame_make_writeable
av_frame_make_writable は、AVFrame を確実に書き込めるようにするために FFmpeg で使用される関数です。
AVFrame は通常、初期化時に av_frame_alloc 関数を使用してメモリ空間を割り当てますが、この関数は AVFrame 構造体が占有するメモリ空間のみを割り当て、AVFrame データ バッファ領域 (つまり、データ フィールド) のメモリ空間は割り当てません。AVFrameにデータを書き込む必要がある場合は、av_frame_get_buffer関数を使用して、AVFrameのデータバッファ領域に一定サイズのメモリ空間を割り当てる必要があります。ただし、シナリオによっては、割り当てられたメモリ領域が実際のデータを保存するのに十分ではない場合があり、この場合、 av_frame_make_writable 関数を使用して、AVFrame を確実に書き込むことができるようにする必要があります。
関数のプロトタイプは次のとおりです。
int av_frame_make_writable(AVFrame *frame);
この関数は、AVFrame 構造体を指すポインター フレームを受け取ります。変更に使用される AVFrame データ バッファーは、通常、他のプロセスまたは他のスレッドによって変更されます。このとき、書き込み可能であることを確認するために av_frame_make_writable 関数を呼び出す必要があります。システムのクラッシュやデータの破損を引き起こす可能性があります。
この関数を呼び出すとき、現在の AVFrame がすでに書き込み可能であれば、関数は直接 0 を返します。現在の AVFrame が書き込み可能でない場合、新しいバッファが作成され、AVFrame はそのバッファを指します。新しいキャッシュを作成するときは、キャッシュ領域を再割り当てしてデータのコピーを実行する必要があり、これによりパフォーマンスがある程度低下する可能性があります。メモリ割り当てに失敗した場合、関数は AVERROR を返します。
つまり、av_frame_make_writable の役割は、AVFrame を確実に書き込めるようにすることです。すでに書き込み可能な場合は直接 0 を返し、それ以外の場合は新しいバッファを割り当てます。この関数を呼び出す場合、メモリの割り当てによりパフォーマンスが低下する可能性があることに注意する必要があり、割り当てに失敗した場合は AVERROR が返されます。
この関数の機能により、フレーム内のデータ フィールドのスペースが利用可能であることが保証されます。エンコードするときは、フレームをエンコーダに渡す必要があります。エンコーダはフレームを取得した後、フレーム内のデータをロックし、データをエンコードします。ロックするときに、このフレームを使用したい場合は、フレームを次のアドレスに送信します。エンコーダのフレームデータと競合が発生します。
どうやってするの?
av_frame_make_writeable 関数を呼び出す
この関数は、フレーム内のデータ フィールドを検出して、データ フィールドがロックされているかどうかを確認します。ロックされている場合は、フレーム内のデータ フィールドにバッファを再割り当てします。ロックされていない場合は、データ フィールドがロックされていることを意味します。フィールドは書き込み可能です。このようにして、後でこのデータ フィールドにデータを書き込むことができます。
//9. 生成视频内容 这个循环中,每一次循环,产生一帧数据
for(int i=0; i<25; i++){
ret = av_frame_make_writable(frame);
if(ret < 0) {
break;
}
产生帧数据。。。
}
したがって、ループの最初のラウンドでは問題はありません。getBuffer を通じてフレーム内のデータ フィールドにスペースをすでに割り当てているためです。
2 番目のラウンドでは、データのフレームをエンコーダに送信した人がロックされる可能性があります。そこでこの方法で解決します。
avchannel_layout_copy
avchannel_layout_copy()
は、オーディオ チャネル レイアウト (AV_CH_LAYOUT_XXX) をソースからターゲットにコピーするFFmpeg の関数です。
関数のプロトタイプは次のとおりです。
uint64_t av_channel_layout_copy(uint64_t *dst, const uint64_t *src);
このうち、dst
はターゲット オーディオ チャネル レイアウトのポインタ、src
はソース オーディオ チャネル レイアウトのポインタです。
使用例:
AVCodecContext *ctx;
// 给 ctx 赋值
AVCodecContext temp_ctx;
uint64_t dst_layout = 0;
int ret;
temp_ctx = *ctx;
ret = av_channel_layout_copy(&dst_layout, &temp_ctx.channel_layout);
if (ret < 0) {
fprintf(stderr, "Failed to copy audio channel layout: %s\n", av_err2str(ret));
// 错误处理
}
この関数は、ソース オーディオ チャネル レイアウトの値をターゲット オーディオ チャネル レイアウトにコピーし、コピーされたチャネルの数を返します。コピーが失敗した場合、関数は負の値を返します。関数のエラー メッセージは、 を使用して取得できますav_err2str()
。
avcodec_parameters_to_context
FFmpeg では、AVCodecContext 構造体を使用してコーデック コンテキストを記述します。AVCodecParameters 構造体は、オーディオ ストリームのサンプリング レート、ビデオ ストリームの幅と高さ、その他のパラメータを含むコーデック パラメータを記述するために使用されます。
この関数は、AVFormatContext から取得した AVCodecParameters 構造体のパラメータを AVCodecContext 構造体に割り当てます。
関数のプロトタイプは次のとおりです。
int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par);
このうち、codecは更新対象のAVCodecContext構造体を表し、parはコーデックパラメータを取得するAVCodecParameters構造体を表す。
サンプルコードは次のとおりです。
AVFormatContext *fmt_ctx;
AVCodec *dec;
AVCodecContext *codec_ctx;
AVCodecParameters *codecpar;
int stream_index;
// 打开文件
if (avformat_open_input(&fmt_ctx, "input.mp4", NULL, NULL) < 0) {
return;
}
// 查找音频流
if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
return;
}
stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, &dec, 0);
// 获取AVCodecParameters结构体
codecpar = fmt_ctx->streams[stream_index]->codecpar;
// 分配AVCodecContext结构体
codec_ctx = avcodec_alloc_context3(dec);
// 将参数拷贝到AVCodecContext结构体中
if (avcodec_parameters_to_context(codec_ctx, codecpar) < 0) {
return;
}
// 后续操作...
上の例では、最初に mp4 ファイルが開かれ、その中のオーディオ ストリームが見つかります。オーディオ ストリームに対応する AVCodecParameters 構造体を取得すると、AVCodecContext 構造体を作成し、avcodec_parameters_to_context 関数を使用してパラメーターをそれに割り当てることができます。次に、codec_ctx を使用してオーディオ デコード操作などを実行できます。
sws_getContext
構造体を初期化するために使用されますSwsContext
。これは、画像のスケーリングとフォーマット変換のコンテキストです。
関数の一般的な形式は次のとおりです。
struct SwsContext *sws_getContext(int srcW,
int srcH,
enum AVPixelFormat srcFormat,
int dstW,
int dstH,
enum AVPixelFormat dstFormat,
int flags,
SwsFilter *srcFilter,
SwsFilter *dstFilter,
const double *param);
このうちパラメータリストの意味は以下の通りです。
srcW
およびsrcH
: ソース画像の幅と高さ。srcFormat
: ソース画像のピクセル形式。dstW
およびdstH
: ターゲット画像の幅と高さ。dstFormat
: ターゲット画像のピクセル形式。flags
: オプション フラグ (0 も可);srcFilter
およびdstFilter
: ソース画像と宛先画像のフィルタ。param
: オプションのパラメータ。
関数の戻り値は、画像変換に必要なすべての情報を含む SwsContext 構造体へのポインターです。
コンテキストが初期化されると、それを使用してさまざまなイメージ操作を実行できます。たとえば、関数を使用してsws_scale
、ソース形式からターゲット形式に画像フレームをスケーリングしたり (形式の変換とサイズ変更のため)、sws_getCachedContext
コンテキスト キャッシュからより高速な変換を取得したりできます。
一般に、sws_getContext
この関数は FFmpeg ライブラリの重要な画像処理関数の 1 つであり、さまざまな画像変換のニーズを満たすことができます。
sws_scale
sws_scale
FFmpeg における画像の拡大縮小とフォーマット変換を行う機能です。指定されたパラメータに従って入力画像を拡大縮小およびフォーマットし、新しい画像を出力できます。
関数のシグネチャは次のとおりです。
int sws_scale(SwsContext *c, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH,
uint8_t *const dst[], const int dstStride[]);
このうち、主なパラメータの意味は以下のとおりです。
SwsContext *c
sws_getContext
:関数によって作成されたスケーリングおよび変換コンテキスト。const uint8_t *const srcSlice[]
: 入力イメージ内のすべての行へのポインターの配列。各要素はデータ行へのポインタです。const int srcStride[]
:输入图像中每行数据的字节数,是一个数组,与srcSlice
中的元素一一对应。int srcSliceY
:输入图像的起始行数。int srcSliceH
:输入图像的高度,从起始行开始计算。uint8_t *const dst[]
:输出缩放后图像中所有行的指针的数组,每个元素是指向一行数据的指针。const int dstStride[]
:输出缩放后图像中每行数据的字节数,是一个数组,与dst
中的元素一一对应。
该函数会对输入图像指定的区域进行缩放和色彩空间转换,生成一个新的图像。具体的缩放和转换方式由上下文决定,通常通过设定特定的参数来实现,例如指定目标图像的大小、目标图像的色彩空间等等。
sws_scale
函数的返回值为输出的图像行数,如果发生错误则返回负值。
以下是使用sws_scale
函数进行图像缩放和格式转换的简单示例代码:
#include <libswscale/swscale.h>
int main()
{
// 输入图像的参数
int srcWidth = 1920;
int srcHeight = 1080;
int srcChannels = 3;
uint8_t *srcData = // 输入图像数据
int srcStride[] = {
srcWidth * srcChannels}; // 每行数据的字节数
// 输出图像的参数
int dstWidth = 1280;
int dstHeight = 720;
int dstChannels = 2; // 输出图像的色彩空间为YUV420格式
int dstStride[] = {
dstWidth * dstChannels}; // 每行数据的字节数
uint8_t *dstData = (uint8_t*)malloc(dstStride[0] * dstHeight); // 分配输出图像数据的空间
// 创建sws_scale上下文
SwsContext *swsContext = sws_getContext(srcWidth, srcHeight, AV_PIX_FMT_BGR24,
dstWidth, dstHeight, AV_PIX_FMT_YUV420P,
SWS_BICUBIC, NULL, NULL, NULL);
// 进行缩放和格式转换
sws_scale(swsContext, &srcData, srcStride, 0, srcHeight, &dstData, dstStride);
// 释放空间,并关闭上下文
free(dstData);
sws_freeContext(swsContext);
return 0;
}
上述代码实现了将一张BGR格式的1920x1080的图像缩放为YUV420格式的1280x720的图像。需要注意的是,输入和输出图像的参数需要与创建上下文时设定的参数一致,否则可能无法正常转换并输出图像。另外,如果需要将输出的图像保存为文件,还需要使用特定方式进行编码和写入
swr_alloc
swr_alloc
函数是用于创建 SwrContext
结构体的函数,其定义如下:
SwrContext *swr_alloc(void);
返回值为创建的 SwrContext
结构体的指针,如果创建失败,则返回 NULL
。
调用 swr_alloc
函数可以创建一个 SwrContext
结构体,并为其分配内存空间。需要注意的是,创建该结构体后需要使用 swr_alloc_set_opts
函数来设置音频的输入和输出参数,否则不能进行音频重采样。
使用完 SwrContext
结构体后,需要调用 swr_free
函数来释放内存空间。
swr_init
swr_init
函数是用于初始化 SwrContext
结构体的函数,其定义如下:
int swr_init(SwrContext *s);
このうちパラメータはs
初期化するSwrContext
構造体、戻り値は初期化結果であり、成功した場合は初期化を返し0
、失敗した場合は負の数を返します。
swr_init
関数を呼び出した後、オーディオ サンプリング形式、サンプル レート、チャネル レイアウト、その他のパラメーターを含む、関数を通じて事前に設定された入出力パラメーターに従って、 のSwrContext
さまざまなパラメーターが初期化されます。swr_alloc_set_opts
初期化後、swr_convert
この関数を呼び出してオーディオのリサンプリングを実行できます。
swr_alloc_set_opts2
必要に応じて SwrContext を割り当て、パブリック パラメータを設定/リセットします。
この関数は swr_alloc を使用して割り当てる必要はありません。一方、swr_alloc0 は、swr_alloc_set opts2 を使用して、割り当てられたコンテキストのパラメータを設定できます。
次のように定義されます。
SwrContext *swr_alloc_set_opts2(SwrContext *s,
int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
cint64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate,
int log_offset, void *log_ctx);
この関数のパラメータは次の意味を持ちます。
s
:SwrContext
構造体ポインター。NULL の場合は新しい SwrContext オブジェクトが作成され、それ以外の場合は既存の SwrContext オブジェクトが更新されます。out_ch_layout
: 出力チャンネルのレイアウト;out_sample_fmt
: 出力サンプリング形式;out_sample_rate
: 出力サンプリングレート;in_ch_layout
: 入力チャンネルのレイアウト;in_sample_fmt
: 入力サンプリング形式;in_sample_rate
: 入力サンプリングレート;log_offset
: ログレベル;log_ctx
: AVClass コンテキスト ポインター。
戻り値:
成功の場合は 0、エラーの場合は負の AVERROR コード。エラーが発生すると、Swr コンテキストが解放され、*s が NULL に設定されます。
swr_convert
swr_convert
Function は、オーディオ リサンプリングのSwrContext
構造の中核となる関数です。その関数プロトタイプは次のとおりです。
int swr_convert(SwrContext *s, uint8_t **out, int out_count, const uint8_t **in, int in_count);
このうち、パラメータは次のように説明されます。
s
:オーディオのリサンプリングを実行するためのSwrContext
構造。out
: 出力音声データのバッファアドレス(リサンプリング後のデータ)out_count
: 各チャンネルの出力に利用可能な空き容量 (出力データのチャンネルごとのサンプル数)in
: 入力オーディオデータのバッファアドレス (リサンプリングが必要なデータ)in_count
: チャンネルで利用可能な入力サンプルの数。(入力データのチャンネルごとのサンプル数)
関数の戻り値は各チャンネルが出力したサンプル数であり、戻り値が負の場合は変換に失敗したことを意味します。
swr_convert
この関数はオーディオ データをリサンプリングします。 **入力バッファ内のオーディオ データは、指定された形式の出力バッファに必要なサンプル数にリサンプリングされます。
swr_free
swr_free
SwrContext
この関数は構造体のメモリを解放するために使用され、その定義は次のとおりです。
void swr_free(SwrContext **s);
このうちパラメータは、解放する構造体を示す構造体ポインタs
へのポインタである。SwrContext
この関数には戻り値はありません。解放が成功すると、SwrContext
構造体ポインタは に設定されますNULL
。
av_samples_get_buffer_size
Functionは FFmpeg が提供するオーディオデータバッファのサイズを計算するav_samples_get_buffer_size()
関数であり、その関数プロトタイプは次のとおりです。
int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples,
enum AVSampleFormat sample_fmt, int align);
関数パラメータの説明:
-
linesize: バッファ内のデータの各行のサイズを指します。NULL の場合は計算されません。
-
nb_channels: オーディオチャンネルの数。
-
nb_samples: チャネルごとのサンプル数。
-
AV_SAMPLE_FMT_S16
Sample_fmt:などのサンプリング形式AV_SAMPLE_FMT_FLT
。 -
align: バッファのアラインメント、通常は 0。
-
0 = デフォルト」。冗長サイズを提供するためによく使用されます。この関数の後には、malloc のような関数が続くことがよくあります。
-
1 = アライメントなし」、アライメントなし。実際には、1 バイトずつアライメントされます。つまり、オーディオ データの実際のサイズが求められ、トランスコードされたばかりのデータのサイズを計算するためによく使用されます (以前はこの関数を呼び出す)
-
この関数の機能は、指定されたサンプリング形式、チャネル数、サンプル数、その他のパラメーターの下でオーディオ データ バッファーに必要な合計サイズを計算することです。
of_fast_malloc
av_fast_malloc()
FFmpegが提供するメモリを高速に確保するための関数で、関数プロトタイプは以下のとおりです。
void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size);
関数パラメータの説明:
- ptr: 現在割り当てられているメモリへのポインタ。
- size: インスタンスによって割り当てられたサイズ。
- min_size: 予想される割り当てサイズ。
av_guess_sample_aspect_ratio
av_guess_sample_aspect_ratio は、特定のフレームのサンプル アスペクト比を推測するFFmpeg ライブラリの関数です。
関数のプロトタイプは次のとおりです。
AVRational av_guess_sample_aspect_ratio(AVFormatContext *format_context, AVStream *stream, AVFrame *frame);
パラメータの説明:
format_context
: 入力ファイルのコンテキスト。stream
: フレームが配置されているストリーム。frame
: サンプルのアスペクト比を推測する必要があるフレーム。
戻り値:
- 推定されたサンプルのアスペクト比を返します。
by_guess_frame_rate
ビデオのフレーム レートを推測するために使用されます。その関数プロトタイプは次のとおりです。
AVRational av_guess_frame_rate(AVFormatContext *ctx, AVStream *stream, AVFrame *frame);
関数パラメータは次のように説明されます。
ctx
: 入力 AVFormatContext コンテキスト。このビデオを含むコンテナ形式コンテキストを指します。stream
: ビデオ ストリームを指す入力 AVStream 構造体。frame
:ビデオフレーム(AVFrame構造)。
関数の戻り値は、推測されたフレーム レートを表す AVRational 構造体です。推測できない場合は、デフォルトのフレームレートが返されます。
av_guess_frame_rate は、ストリームのタイムベースとフレームのタイムスタンプに基づいてビデオのフレーム レートを推測します。受信ビデオ ストリームに無効なフレーム レート データが存在する場合、推測は不正確になる可能性があります。
av_guess_frame_rate は単なる推測関数であり、結果の正確性は保証されないことに注意してください。正確なフレーム レート情報が必要な場合は、AVStream 構造体の r_frame_rate フィールドから取得できます。
of_get_bytes_per_sample
av_get_bytes_per_sample は FFmpeg の関数で、指定されたサンプリング形式の各サンプルが占めるバイト数を計算するために使用されます。次のように定義されます。
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt);
この関数のパラメータsample_fmtは列挙型AVSampleFormatであり、サンプリング形式を示します。戻り値は、各サンプルが占めるバイト数を表す整数です。
たとえば、16 ビット符号付き整数型サンプルのサンプルあたりのバイト数を計算したい場合は、次のように av_get_bytes_per_sample 関数を呼び出すことができます。
int bytes_per_sample = av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);
この呼び出しは 2 を返し、各サンプルが 2 バイトを占有することを示します。
by_strdup
av_strdup 関数は、FFmpeg の文字列操作関数であり、文字列を新しいメモリ空間にコピーし、新しい文字列ポインタを返すために使用されます。そのプロトタイプは次のとおりです。
char *av_strdup(const char *s);
パラメータの説明:
- s: コピーする文字列。
戻り値は新しい文字列ポインタ、またはメモリ割り当てが失敗した場合は NULL です。
av_strdup 関数は C 標準ライブラリの strdup 関数に似ていますが、av_strdup 関数は FFmpeg のメモリ割り当て関数 av_malloc および av_free を使用するため、メモリ管理の問題の一部を回避できます。さらに、av_strdup 関数を使用して、FFmpeg 内の AV 文字列 (AVString) タイプの文字列をコピーすることもできます。
AV合理的
AVRational
型の有理数を倍精度浮動小数点数に変換するために使用されます。
AVRational
Type は、FFmpeg ライブラリで分子と分母を含む有理数を表すために使用される構造体です。ビデオのコーディングとデコーディングでは、フレーム レート、ビット レート、その他の情報を表すためにスコアがよく使用されます。
関数のプロトタイプは次のとおりです。
double av_q2d (AVRational a);
引数はtype の有理数a
です。AVRational
a
この関数は、有理数を浮動小数点数に変換した後の値を表す倍精度浮動小数点数を返します。
AVRational
たとえば、型の変数がある場合r
、av_q2d
次のように関数を使用してそれを倍精度浮動小数点数に変換できます。
double d = av_q2d(r);
この関数の具体的な実装は次のとおりです。
static inline double av_q2d(AVRational a)
{
return a.num / (double) a.den;
}
関数内では、まず分子が倍精度浮動小数点数に変換され、次に分母で除算されて有理数の浮動小数点数が取得されます。
一般的なデータ構造
AVフォーマットコンテキスト
これは、オーディオおよびビデオ ファイルの読み取りまたは書き込みに必要なすべての情報 (オーディオおよびビデオ ストリーム、タイムスタンプ、メディア情報など) を含むカプセル化形式コンテキストを表すために使用されます。
AVFormatContext 構造体のメンバー変数は次のとおりです。
- AVInputFormat* iformat: 入力形式。このパラメータはファイルの読み取り時に指定されます。
- AVOutputFormat* offormat: 出力形式。ファイルに書き込まれる場合、このパラメーターが指定されます。
- void* priv_data: FFmpeg モジュールによって内部的に使用されるプライベート データ。
- AVIOContext* pb: ファイルの読み取りまたは書き込みのための IO コンテキスト。
- int nb_streams: ストリームの数。
- AVStream** ストリーム: すべてのオーディオ ストリームとビデオ ストリームを含む、オーディオ ストリームとビデオ ストリームの配列。
- char* ファイル名: ファイル名。
- int64_t start_time: ファイルの開始時刻 (マイクロ秒単位)。
- int64_t 持続時間: ファイルの持続時間 (マイクロ秒単位)。
- int bit_rate: 合計ビットレート。
- AVDictionary* メタデータ: ファイルのさまざまな情報を含むメタデータ。
- int n_programs: プログラムの数。
- AVProgram** プログラム: ストリームのグループを個別に処理するために使用されるプログラム配列。
デコードとエンコードのプロセスでは、AVFormatContext 構造を使用して、さまざまな種類のオーディオ ファイルやビデオ ファイルを読み書きする必要があります。ファイルを読み取る必要がある場合は、avformat_open_input 関数を呼び出して AVFormatContext 構造体を取得した後、av_read_frame 関数を通じて各オーディオおよびビデオ ストリームの AVPacket を読み取る必要があります。
ファイルを書き込む必要がある場合は、avformat_alloc_output_context2 関数を呼び出して AVFormatContext 構造体を初期化し、次に avformat_new_stream 関数を使用してオーディオ ストリームとビデオ ストリームを作成し、av_write_frame を通じて各オーディオ ストリームとビデオ ストリームの AVPacket を書き込む必要があります。関数。
AVストリーム
AVStream 構造は、オーディオおよびビデオ ストリームを表すために使用されます。FFmpeg では、通常、マルチメディア ファイルには複数のオーディオ ストリームとビデオ ストリームが含まれており、各ストリームには対応する AVStream 構造があります。
AVStream 構造体のメンバー変数は非常に豊富で、以下に紹介します。
- Index: ストリームのインデックス。マルチメディア ファイル内のストリームの位置を示します。
- codecpar: ストリームのコーデック パラメータ。AVCodecParameters 構造体を通じてコーデックの特定の情報が含まれます。
- time_base: 単位時間あたりのタイムスタンプの数を示すタイムベース。
- r_frame_rate: フレーム レート。1 秒あたりのフレーム数を示します。
- id: マルチメディア ファイル内で一意のストリームの ID。
- メタデータ: フローのさまざまな関連情報を含む、フローのメタデータ。
- nb_frames: ストリーム内のフレーム数。
- start_time: ストリームの開始時刻。
- 継続時間: ストリームの継続時間。
- disposition: ストリームの位置情報 (プレストリーム、ポストストリームなど)。
- avg_frame_rate: 平均フレーム レート。
- recommend_encoder_configuration: 推奨されるエンコーダー構成情報。
- codec_info_duration: コーデック情報の期間。
AVStream 構造体のメンバー変数は非常に豊富です。これらのメンバー変数は、オーディオとビデオのストリームのさまざまな属性と情報を記述するために使用できます。これは、オーディオとビデオの処理とエンコードに FFmpeg を使用するときにストリームを正しく処理するのに便利です。そしてデコード。
AVパケット
FFmpeg では、AVPacket
この構造は、 FFmpeg でのデータ転送の基本単位である、エンコードされたオーディオおよびビデオ データ フレームを格納するために使用されます。
AVPacket 構造の定義は次のとおりです。
typedef struct AVPacket {
int64_t pts; // 表示该帧的显示时间戳
int64_t dts; // 表示该帧的解码时间戳
uint8_t *data; // 数据指针,指向存储音视频帧数据的缓冲区
int size; // 音视频帧数据的大小
int stream_index; // 音视频流的索引,表示该帧数据属于哪个流
int flags; // 标志位,用于记录该帧数据的一些状态。
struct AVPacket *next; // 下一帧数据指针
int64_t pos; // 数据在输入文件中的位置
int64_t duration; // 帧时长
} AVPacket;
AVPacket 構造には次の重要なフィールドが含まれています。
pts
およびdts
:pts
データ ストリーム全体におけるオーディオおよびビデオ フレームの再生時間を示すために使用される表示タイム スタンプを示します。dts
デコード タイム スタンプを示し、データ ストリーム内のオーディオおよびビデオ フレームのデコード時間を示すために使用されます。データストリーム全体。data
とsize
:data
はオーディオおよびビデオ フレーム データへのポインタであり、size
データ長を示します。stream_index
: 現在のオーディオおよびビデオ フレームが属するストリーム インデックスを示します。flags
: 現在のフレームの特別なプロパティ (キー フレームかどうか、有効なフレームかどうかなど) を示します。pos
: 入力ファイル内のオーディオとビデオのフレームの位置を示します。duration
: フレームの継続時間を示します。ビデオ フレームのシーンなど、一部の場合にのみ意味を持ちます。
AVPacket には複数のデータ フレームが含まれる可能性があるため、単一のデータ フレームを表すだけでなく、複数のデータ フレームで構成されるデータ パケットも表すことに注意してください。AVPacket
マルチフレーム データには、 のsize
およびフィールドを使用してアクセスできdata
、各データ フレームのタイムスタンプと期間にはpts
、dts
およびフィールドを使用してduration
アクセスできます。
AVPacket は、オーディオおよびビデオのエンコードおよびデコードのプロセスにおける中継データ形式として、各ステップで重要な役割を果たします。カプセル化を解除するときは、AVPacket を使用して、コンテナから読み取られた圧縮オーディオおよびビデオ データを保存します。エンコードするときは、AVPacket を使用して、エンコードされた圧縮データを保存します。コーデック操作の間では、AVPacket がデータ送信のキャリアとして使用され、FFmpeg のデータ送信インターフェイスを通じて送信されます。
AVFifo
FIFO (先入れ先出し) データ構造。
struct AVFifo {
uint8_t *buffer;
size_t elem_size, nb_elems;
size_t offset_r, offset_w;
// distinguishes the ambiguous situation offset_r == offset_w
int is_empty;
unsigned int flags;
size_t auto_grow_limit;
};
AVIOコンテキスト
AVIOContext は FFmpeg の構造体であり、出力ファイル コンテキストであり、ファイルにデータを書き込むために使用できます。
AVIOContext にはいくつかの重要なフィールドが含まれています。
- バッファ: メモリ空間を指すキャッシュ ポインタ。
- buffer_size: バイト単位のバッファ サイズ。
- buf_ptr: キャッシュ内のデータの現在の位置を示す現在のポインター。
- eof_reached: 現在のキャッシュが読み取られたかどうかを示すフラグ ビット。1 は読み取りが完了したことを示し、0 は読み取りが完了していないことを示します。
- read_packet: データ パケットを読み取るためのコールバック関数ポインタ。
- write_packet: データ パケットを書き込むためのコールバック関数ポインター。
- Seek: ストリーム シーク関数のコールバック関数ポインタ。
- opaque: コールバック関数でパラメータを渡すために使用される不透明なポインタ。
FFmpeg では、多くのモジュールが AVIOContext を使用してデータの入出力操作を実装します。したがって、FFmpeg の入出力およびデータ処理フローをマスターするには、AVIOContext の使用をマスターすることが非常に重要です。
AV出力フォーマット
AVOutputFormat は、 ffmpeg の出力形式を定義する構造体であり、形式名、ファイル拡張子、オーディオとビデオのコーデック、その他の情報を含むオーディオとビデオの出力形式を表します。各出力フォーマットには、対応する AVOutputFormat 構造があります。
AVOutputFormat 構造体は次のように定義されます。
typedef struct AVOutputFormat {
const char *name; /* 格式名称 */
const char *long_name; /* 格式全名 */
const char *mime_type; /* mime类型 */
const char *extensions; /* 文件扩展名 */
int flags; /* 格式标志 */
const AVCodecTag * const *codec_tag; /* 音视频编码器标记 */
const struct AVOutputFormat *next;
/* ... */
} AVOutputFormat;
- name: 形式名、「mp4」、「mpeg」など、特定の出力形式を識別するために使用される短縮名。
- long_name: 形式の完全名。「MPEG-4 Part 14」など、出力形式の完全名を表示するために使用されます。
- mime_type: 出力フォーマットの MIME タイプ。「video/mp4」など、フォーマットのメディア タイプを表すために使用されます。
- 拡張子: 「mp4 m4v」などの、スペースで区切られた形式でサポートされているファイル拡張子。
- flags: フォーマット フラグ。特定のフォーマットの属性を示すために使用されます。たとえば、「AVFMT_NOFILE」は、そのフォーマットが基礎となるファイル ハンドルを必要としないことを示します。
- codec_tag: オーディオおよびビデオ コーデックのタグ。オーディオおよびビデオ コーデックの識別を指定するために使用されます。このタグは、4 文字のエンコーダ ID と、対応する圧縮エンコーダ ID で構成されます。
- next: 次の AVOutputFormat 構造体へのポインター。出力形式リストの作成に使用されます。
MP4 形式を例に挙げると、対応する AVOutputFormat 構造は次のとおりです。
AVOutputFormat ff_mp4_muxer = {
.name = "mp4",
.long_name = NULL_IF_CONFIG_SMALL("MP4 (MPEG-4 Part 14)"),
.mime_type = "video/mp4",
.extensions = "mp4",
.video_codec = AV_CODEC_ID_MPEG4,
.audio_codec = AV_CODEC_ID_AAC,
/* ... */
.codec_tag = (const struct AVCodecTag *const []) {
ff_mp4_obj_type, 0
},
/* ... */
};
AVCodecパラメータ
AVCodecParameters コーデック形式、幅と高さ、サンプリング レートなど、オーディオおよびビデオ コーデックの関連パラメータを記述するために使用されます。
typedef struct AVStream {
int index; // 媒体流的索引号,表示在文件中的排列顺序
int id; // 媒体流的编号
AVCodecContext *codec; // 指向对应的 AVCodecContext 结构体的指针,表示媒体流的编解码器上下文
void *priv_data; // 指向私有数据的指针,存储一些额外的信息(如元数据、辅助数据等)
AVRational time_base; // 时间基准,表示每个时间单位的长度,例如输入文件中的每个视频帧、音频帧等时间长度
int64_t start_time; // 媒体流的起始时间,以 AV_TIME_BASE 为单位
int64_t duration; // 媒体流的持续时间,以 AV_TIME_BASE 为单位
int64_t nb_frames; // 媒体流中的总帧数
uint32_t disposition; // 媒体流的处理方式,可以是原始数据、附加数据等
enum AVDiscard discard; // 丢帧策略
AVRational sample_aspect_ratio; // 采样长宽比,视频特有
AVDictionary *metadata; // 元数据
AVRational avg_frame_rate; // 帧率
AVPacket attached_pic; // 附图
AVCodecParameters *codecpar; // 媒体流的编解码参数,可以获取媒体流的相关信息,如码率、分辨率、帧率等
struct AVFrac pts; // 表示媒体流中最新的PTS值(presentation timestamp),用于时间基准的缩放计算
AVStreamParseType need_parsing; // 解析媒体流的方式
struct AVCodecParserContext *parser; // 媒体流解析器上下文,用于解析媒体流
int64_t cur_dts; // 媒体流中最新的DTS值(decoding timestamp),表示解码器解码时间,以 AV_TIME_BASE 为单位
int64_t last_IP_pts; // 最新的I帧或P帧的时间戳PTS值,依赖于参考(reference)媒体流
int last_IP_duration; // 最新的I帧或P帧的持续时间,依赖于参考(reference)媒体流
char language[4]; // 媒体流的语言编码,ISO 639-2 3字码
int nb_decoded_frames; // 编解码后的总帧数
int64_t mux_ts_offset; // muxer的时间戳偏移量
AVStreamSideData **side_data; // 指向 Side Data 数据的指针,如添加的 Metadata
int nb_side_data; // Side Data 数据的个数
int event_flags; // 事件标志
} AVStream;
AVCodecParameters 構造体のメンバー変数は次のとおりです。
- enum AVCodecID codec_id: 使用されるコーデックのタイプを示すコーデック ID。
- enum AVMediaType codec_type: ビデオ、オーディオ、字幕などを含むコーデック タイプ。
- int width: ビデオの幅。
- int height: ビデオの高さ。
- AVRationalsample_aspect_ratio: サンプリング レート。
- int bits_per_raw_sample: サンプルあたりのビット数。
- int 形式: ピクセル形式。
- AVRational time_base: 単位時間あたりのタイムスタンプの数を示すタイムベース。
- int Channels: オーディオチャンネルの数。
- int sample_rate: オーディオのサンプル レート。
- uint64_t channel_layout: オーディオ チャネル レイアウト。
- int64_t bit_rate: ビットレート。
- AVDictionary* extradata: コーデックとストリームに関する情報を含む追加データ。
AVCodecParameters 構造体のこれらのメンバー変数は、デコードおよびエンコードのプロセスにとって非常に重要な、コーデックのさまざまなパラメーターとプロパティを記述します。デコード プロセスでは、AVCodecParameters 構造体の情報を使用してデコーダを初期化し、AVPacket から AVFrame をデコードする必要があります。また、エンコード プロセスでは、AVCodecParameters 構造体の情報を使用してエンコーダを初期化する必要があります。そして、AVFrameをAVPacketにエンコードします。
技術的な詳細:
AVCodecParameters 構造は、FFmpeg バージョン 3.0 以降で導入されました。以前のバージョンでは AVCodecContext 構造体が使用されていましたが、この構造体にはコーデック自体に関するより多くの情報が含まれています。AVCodecParameters は、コンテナ形式に関連するコーデック情報を格納するように設計されており、さらに多くのコーデック関連情報が AVCodecContext に格納されます。****
AVCodecParameters と AVCodecContext の違い
- AVCodecContext 構造は、AVCodecParameters 構造のすべての情報を含む重量構造であり、コーデック関連の制御情報など、AVCodecParameters に含まれないいくつかのパラメーターも含まれています。
- AVCodecContext 構造は通常、オーディオとビデオのコーデックを記述するために使用され、デコードやエンコードなどの操作に使用できます。
- デコードするときは、通常、まず AVCodecParameters 構造体から AVCodecContext 構造体を作成し、次にこの構造体をデコードに使用します。
AVCodecParameters と AVCodecContext を使用する場合、それらの間の関係を明確にする必要があります。AVCodecContext 構造体は、 AVCodecParameters 構造体のスーパーセットです。AVCodecParameters 構造体には、AVCodecContext 構造体のほとんどのパラメータが含まれていますが、AVCodecContext 構造体には、AVCodecParameters にはない多くのコーデック関連のパラメータも含まれています。したがって、一部のコーデック関連の操作では AVCodecContext を使用する必要があり、オーディオおよびビデオ ストリームのパラメーター情報のみを取得する場合はAVCodecParameters を使用できます。
AVコーデック
AVCodec 構造体は、 FFmpeg で定義されたエンコーダ構造体です。FFmpeg では、各メディア形式 (MP4、FLV など) が 1 つ以上のコーデックに対応します。ビデオ ファイルをデコードする必要がある場合、FFmpeg はファイル形式に従って対応するコーデックを自動的に選択し、デコードされたデータを AVFrame 構造に保存します。
以下は、AVCodec 構造体のメンバー変数の簡単な分析です。
- name: コーデック名、文字列として保存されます。
- type: オーディオ エンコーダ、ビデオ エンコーダ、オーディオ デコーダ、ビデオ デコーダなどを含むコーデック タイプ。
- id: コーデックの一意の識別子。AVCodecID 列挙型で表されます。
- 機能: コーデックの機能フラグ。AV_CODEC_CAP_* 定数で表され、コーデックがサポートする機能を識別するために使用されます。
- Supported_framerates: サポートされているフレーム レートのリスト。
- pix_fmts: サポートされているピクセル形式のリスト。
- supported_samplerates: サポートされているサンプルレートのリスト。
- Sample_fmts: サポートされているサンプル形式のリスト。
- channel_layouts: サポートされているチャネル レイアウトのリスト。
- profiles:支持的编解码器配置文件列表。
- priv_class:编解码器私有数据的类结构体。
- init_static_data:初始化静态数据的函数指针。
- init:初始化编解码器的函数指针。
- encode2:编码数据的函数指针。
- decode:解码数据的函数指针。
- flush:刷新编解码器缓存的函数指针。
- close:关闭编解码器的函数指针。
在使用AVCodec结构体时,需要根据具体的操作选择适合的函数指针。例如,解码音频数据时,需要用到decode函数,而编码视频数据时,需要用到encode2函数。同时,根据编解码器的支持情况,选择合适的像素格式、采样率、采样格式和声道布局等参数,以便得到更好的编解码效果。
AVCodecContext
AVCodecContext是FFmpeg中用于描述编解码器上下文信息的结构体,它包含了大量的编解码器参数和状态信息,如编解码器类型、帧率、分辨率、编解码器参数、编码质量、音频采样率、通道数、码率等。
下面对AVCodecContext结构体的成员变量做一个简单解析:
-
av_class:用于访问AVCodecContext结构体的类结构体。
-
codec_id:编解码器ID,即AVCodecID枚举类型的值。
-
codec_type:编解码器类型,即AVMediaType枚举类型的值。
-
bit_rate:比特率,以比特每秒(bps)为单位。
-
sample_rate:采样率,以赫兹(Hz)为单位。
-
channels:声道数。
-
channel_layout:声道布局,可通过FFmpeg提供的API获取。
-
time_base:时间基准,指定每个刻度代表的时间长度。
-
ticks_per_frame:每帧所需的刻度数。
-
width:视频帧宽度。
-
height:视频帧高度。
-
pix_fmt:像素格式,即AVPixelFormat枚举类型的值。
-
sample_fmt:采样格式,即AVSampleFormat枚举类型的值。
-
delay:编解码器输出的时延。
-
codec: 使用されるコーデックを示す AVCodec へのポインター。
-
codec_tag: コーデックタグ。
-
priv_data: コーデックのプライベート データ。
-
gop_size: ビデオ フレーム グループ (Group of Pictures、略して GOP) のサイズを示します。
ビデオ ストリームを送信する必要がある場合、gop_size を小さくすると、ネットワークの遅延と帯域幅の消費を削減できます。また、ビデオのクリッピングと編集がローカルで必要な場合、gop_size を大きくするとビデオの品質と編集効率が向上します。
-
flags: コーデックのステータス フラグ。
-
extradata: コーデックの追加データ。
-
extradata_size: 追加データの長さ。
-
qmin、qmax、qcompress、qblur、global_quality: 最小/最大量子化係数、圧縮係数などのビデオ エンコード パラメータ。
-
strict_std_compliance: 標準フラグに従うかどうか。つまり、非標準形式などの重大ではないエラーを無視するかどうかを意味します。
-
レベル、プロファイル: ビデオエンコーディングレベルとプロファイル。
-
keyframe_interval: キーフレーム間隔。
-
pkt_timebase: パケットのタイムベース。
AVフレーム
av_frame は FFmpeg の構造体で、オーディオおよびビデオ フレーム データを保存するために使用されます。これには、フレームのタイムスタンプ、継続時間、サンプル レート、チャネル数、ピクセル形式など、フレーム関連の情報が含まれています。具体的には、av_frame 構造体には次のメンバーが含まれています。
typedef struct AVFrame {
uint8_t *data[AV_NUM_DATA_POINTERS];
int linesize[AV_NUM_DATA_POINTERS];
uint8_t *buf[AV_NUM_DATA_POINTERS];
int64_t pts;
int64_t pkt_dts;
int64_t best_effort_timestamp;
int64_t pkt_pos;
int64_t pkt_duration;
AVRational sample_aspect_ratio;
int format;
int width, height;
int channels;
int channel_layout;
enum AVColorRange color_range;
enum AVColorSpace color_space;
enum AVColorPrimaries color_primaries;
enum AVColorTransferCharacteristic color_trc;
int64_t opaque;
struct AVDictionary *metadata;
int flags;
int64_t pkt_size;
void *hw_frames_ctx;
AVBufferRef *bufs[AV_NUM_DATA_POINTERS];
} AVFrame;
-
data: uint8_t* 型のポインター配列で、オーディオおよびビデオ フレームのデータを格納するために使用されます。
データ配列内のポインタは、オーディオおよびビデオ データのバッファを指します。オーディオおよびビデオ フレームには複数のデータが含まれる場合があるため、たとえば、YUV420P 形式のビデオ フレームには Y、U、V の 3 つのコンポーネントのデータが含まれるため、データ配列はポインターの配列となり、各ポインターはデータを指します。オーディオとビデオのフレーム部分。
データ配列内の要素に対応するデータ ブロックは、ピクセル フォーマットに従って決定されます。たとえば、YUV420P 形式のビデオ フレームの場合、data[0] は Y コンポーネントのデータ ブロックを指し、data[1] は U コンポーネントのデータ ブロックを指し、data[2] は U コンポーネントのデータ ブロックを指します。 V コンポーネント。オーディオ フレームの場合、data[0] はフレームの PCM データ ブロックを指します。
ビデオ フレームの場合、画像のフレームのピクセル データがデータ配列に保存され、オーディオ フレームの場合、フレームのサンプル データがデータ配列に保存されます。
AVFrame 構造体を使用する場合、最初に av_frame_alloc 関数を使用して AVFrame 構造体を初期化し、次に av_frame_get_buffer 関数を使用して AVFrame にデータ バッファーを割り当てる必要があることに注意してください。このステップでバッファを割り当てるプロセスでは、データ配列内のポインタが初期化され、各ポインタはデータ バッファを指すようになります。
サンプルコード:
#include <stdio.h> #include <libavcodec/avcodec.h> int main() { // 初始化AVFrame结构体 AVFrame *frame = av_frame_alloc(); frame->width = 1920; frame->height = 1080; frame->format = AV_PIX_FMT_YUV420P; // 分配缓冲区 int ret = av_frame_get_buffer(frame, 32); if (ret < 0) { printf("Failed to allocate buffer for AVFrame.\n"); return 1; } // 将数据存储到data数组中 uint8_t *y_data = frame->data[0]; // 存储Y分量的数据 uint8_t *u_data = frame->data[1]; // 存储U分量的数据 uint8_t *v_data = frame->data[2]; // 存储V分量的数据 // 接下来可以对y_data、u_data和v_data进行处理 // 释放AVFrame结构体 av_frame_free(&frame); return 0; }
上記のコードでは、av_frame_alloc 関数を使用して AVFrame 構造を初期化し、その幅、高さ、ピクセル形式を設定します。次に、av_frame_get_buffer 関数を使用して AVFrame にデータ バッファーを割り当て、データ配列内のポインターを対応するデータ ブロックにポイントします。最後に、データ配列内のデータを処理し、av_frame_free 関数を使用して AVFrame 構造を解放します。
-
linesize: int 型のポインター配列、メモリ内のピクセル データの各行が占めるバイト数。
AVFrame 構造では、データ配列と同様に、ラインサイズ配列もポインターの配列であり、オーディオおよびビデオ フレーム データを格納するために使用されるライン サイズです。
linesize 配列の要素はデータの各ラインのサイズ (バイト単位) を表し、この値はピクセル形式に関連しているため、ピクセル形式が異なればラインサイズも異なります。AVFrame のデータの各ラインの長さは、実際には、このデータ ラインのピクセル数 * 各ピクセルが占めるバイト数です。
YUV420Pフォーマットのビデオフレームを例にとると、このフォーマットのビデオフレームにはY、U、Vの3つのコンポーネントのデータが含まれており、各コンポーネントのデータはプレーンストレージ形式で格納されます。各コンポーネントのストレージでは、データの各行の長さが画像の幅のサイズになります。したがって、YUV420P 形式のビデオ フレームの場合、その linesize[0]、linesize[1]、および linesize[2] はそれぞれ画像幅、画像幅/2、および画像幅/2 になります。
AVFrame 構造体を使用する場合、最初に av_frame_alloc 関数を使用して AVFrame 構造体を初期化し、次に av_frame_get_buffer 関数を使用して AVFrame にデータ バッファーを割り当てる必要があることに注意してください。このステップでのバッファ割り当てプロセスでは、linesize 配列の要素が初期化され、各要素は対応するデータのラインのサイズを表します。
-
extend_data: 追加データを格納するために使用される uint8_t* タイプの配列ポインター。通常、マルチチャンネルオーディオデータを保存するために使用されます。
-
nb_samples: int 型、各チャンネルのオーディオ サンプルの数。
-
format: int 型。オーディオおよびビデオ フレームのピクセル形式を示します。
-
width: int型でビデオフレームの幅を示します。
-
height: int型でビデオフレームの高さを示します。
-
Sample_rate: オーディオフレームのサンプリングレートを示すint型。
-
channel_layout: オーディオフレームのチャンネルレイアウトを示すuint64_t型。
-
pts: int64_t 型。フレームのタイムスタンプ (プレゼンテーション タイムスタンプ) が時間ベースであることを示します。
-
pkt_pts: int64_t タイプ。フレームが配置されているパケットのタイムスタンプを示します。
-
pkt_dts: int64_t タイプ。フレームが配置されているパケットのデコード タイムスタンプを示します。
-
メタデータ: フレームのメタデータ情報を表す AVDictionary* タイプ。
-
pkt_pos: メディア ファイル内のフレーム データの位置をバイト単位で示します。
一般に、av_frame は、データのみを保存し、データに関連する他の情報は保存しない、オーディオおよびビデオ フレーム データのコンテナーとみなすことができます。これらの情報は通常、対応する AVPacket に保存されるか、別の場所に保存されます。データがデコードされた後、av_frame 内の対応するメンバーにアクセスすることで必要な情報を取得できます。
AV合理的
AVRational は、 FFmpeg で有理数を表す構造体であり、タイムベースやフレーム レートなどの有理数が関与する状況を記述するために使用されます。次のように定義されます。
typedef struct AVRational {
int num; // 分子
int den; // 分母
} AVRational;
このうち、num は有理数の分子を表し、den は有理数の分母を表します。
AVRational 構造は、メディア ファイル内のタイムスタンプやフレーム レートなどの情報を記述するためによく使用されます。たとえば、デコーダでは、ビデオ フレームのタイムスタンプ (PTS) に基づいたタイムベース調整やフレーム レート制御などの操作を実行する必要があります。AVRational 構造を使用すると、タイムスタンプやフレーム レートなどの有理数を含む概念を簡単に表現できます。
FFmpeg では、AVRational 構造の定義と使用が非常に広範囲にわたっています。多くの場所でそれを見ることができます。たとえば、コーデックが初期化されるとき、AVCodecContext の time_base フィールドを設定する必要があります。このフィールドは、タイム ベースを表すために使用される AVRational 構造体タイプです。
AVCodecContext *codec_context = avcodec_alloc_context3(codec);
codec_context->time_base = (AVRational){1, 25}; // 设置时间基为1/25
上記のコード スニペットでは、AVCodecContext の time_base フィールドを設定することで、デコーダーのタイム ベースが 1/25 であることを指定します。もちろん、time_base フィールドはデコーダに使用されるだけでなく、エンコーダのタイムベースを設定するためにも使用される必要があります。
SwsContext
SwsContext
この構造体は FFmpeg ライブラリの重要なタイプであり、画像のスケーリングとフォーマット変換に使用されます。
次のように定義されます。
typedef struct SwsContext SwsContext;
構造SwsContext
体には次の重要なメンバーが含まれています。
swScale
: 入力画像を出力画像に変換するために使用されるスケーリング関数へのポインタ。redBlueTable
: 青と赤のチャンネルを格納するポインター。greenTable
: 緑チャンネルへのポインタ。brightnessTable
:明るさメーターへのポインタ。contrastTable
: コントラストテーブルへのポインタ。swScaleFlags
: スケーリング機能を制御するための特定のフラグ。
上記のメンバ ** の中で最も重要なのはswScale
、入力画像を出力画像に変換するために使用されるスケーリング関数へのポインタであるメンバ ** です。次のように定義されます。
int (*swScale)(struct SwsContext *,
const uint8_t* const srcSlice[],
const int srcStride[],
int srcSliceY, int srcSliceH,
uint8_t* const dst[], const int dstStride[]);
この関数のパラメータ リストには次のものが含まれます。
struct SwsContext *
: コンテキスト構造体へのポインタ。const uint8_t* const srcSlice[]
: ソース画像の行ポインタの配列。const int srcStride[]
: ソース画像の各行のバイト配列。int srcSliceY
: ソース画像のトリミングの開始位置。int srcSliceH
: ソース画像のクリッピングの高さ。uint8_t* const dst[]
: ターゲット画像の行ポインタの配列。const int dstStride[]
: 対象画像の各行のバイト配列。
swScale
Member はSwsContext
、スケーリング関数の基本フレームワークを定義する構造体の最も重要なメンバーの 1 つです。異なるスケーリング関数の実装では、異なるアルゴリズムと最適化手法が使用される場合があります。たとえば、FFmpeg ライブラリには、BICUBIC、BILINEAR、NEAREST などのさまざまなスケーリング関数が提供されています。
ビットマップファイルヘッダーとビットマップインフォヘッダー
BITMAPFILEHEADER
と はBITMAPINFOHEADER
ビットマップ ファイルを記述するために使用される構造です。通常、両方はビットマップ ファイルを完全に記述するために一緒に使用されます。
BITMAPFILEHEADER
ビットマップ ファイルのファイル ヘッダーで、ファイル タイプ、ファイル サイズ、ビットマップ データのオフセットなど、ビットマップ ファイル全体の基本情報が記述されます。これは「シェル」のように機能し、ビットマップ ファイルを解析するための基本情報を提供します。
BITMAPINFOHEADER
これは、ビットマップ ファイルの画像情報ヘッダーであり、幅、高さ、ビット深度、カラー プレーンの数など、ビットマップ ファイル内の画像情報を記述するために使用されます。これは、ビットマップ画像の詳細を提供する「カーネル」のように機能します。
2 つの具体的な違いは、機能の違いです**。BITMAPFILEHEADER
ビットマップファイル全体の基本情報と、BITMAPINFOHEADER
ビットマップ画像**の情報を記述します。BITMAPFILEHEADER
したがって、ビットマップ ファイルを処理する場合は、最初に構造を読み取ってファイルの基本情報を取得し、次にBITMAPINFOHEADER
構造を読み取って画像の詳細情報を取得して後続の処理を行う必要があります。
SwrContext
SwrContext
この構造はオーディオ リサンプリングのコンテキスト構造であり、リサンプリングに必要な状態情報と中間データを保存するために必要なパラメータとバッファが含まれています。次のように定義されます。
typedef struct SwrContext SwrContext;
struct SwrContext {
int swr_flags;
AVSampleFormat in_sample_fmt;
AVSampleFormat out_sample_fmt;
int64_t in_channel_layout;
int64_t out_channel_layout;
int in_sample_rate;
int out_sample_rate;
int nb_samples;
struct ResampleContext *resample;
int async;
int available_samples;
AVAudioResampleContext *avr;
int allocated_samples;
int8_t **midbuf;
int matrix_encoding;
int need_rematrix;
void (*rematrix)(struct SwrContext *s, int32_t **matrix, int stride,
const int32_t *coefs, int channels);
int rematrix_custom;
void *log_ctx;
int log_level_offset;
};
その中で、定義されたメンバー変数には次のものが含まれます。
swr_flags
: 出力のサンプル数の制御など、リサンプリング操作の一部のフラグは、入力のサンプル数に依存します。in_sample_fmt/out_sample_fmt
: 入力および出力オーディオ サンプル形式AV_SAMPLE_FMT_S16
。in_channel_layout/out_channel_layout
: 入力および出力チャンネルのレイアウトAV_CH_LAYOUT_STEREO
。in_sample_rate/out_sample_rate
: 入力および出力のサンプリング レート48000
。nb_samples
:SwrContext
内蔵 FIFO バッファ内のサンプル数。resample
: オーディオのリサンプリングの状態を表す構造体。async/available_samples
: 非同期リサンプリングのフラグとサンプル数。beta1
: オーディオのリサンプリングに必要なステータス情報とバッファ ポインタを保存します。matrix_encoding
: マトリックスエンコーディング。rematrix
:録画機能。rematrix_custom
: カスタム録音機能マーカー。log_ctx/log_level_offset
: ログ出力に使用されるコンテキストとそのオフセット。
SwrContext
の最も重要なメンバーは、resample
実行時のオーディオ リサンプリングの内部動作状態の構造であり、次のように定義されます。
typedef struct ResampleContext ResampleContext;
struct ResampleContext {
double factor; // 采样率转换系数
int phase_shift; // 重采样器移位
int in_incr, out_incr; // 输入输出增量
int32_t ideal_dst_incr; // 目标增量
int dst_incr; // 实际目标增量
int16_t *in_buffer; // 输入缓冲区
int in_buffer_count; // 输入缓冲区大小
int16_t *resample_ptr; // 重采样指针
int in_index, out_index; // 输入输出索引
int frac; // 分数部分
int resample_slice; // 重采样大小
void *filter_bank; // 滤波器状态结构体的指针
void (*resample_one)(ResampleContext *c, int16_t *dst, const int16_t *src, int left, int right); // 单样本重采样函数
};
リサンプリングに関するいくつかのパラメータと、中間データを格納するために使用されるいくつかの変数が で定義されていることがわかりますResampleContext
。たとえば、factor
サンプリング レート変換係数を表す、in_buffer
入力バッファを表す、resample_one
単一サンプル リサンプリング関数を表すなどです。この構造体は、オーディオ リサンプリング操作を反映する状態応答を実装するためにSwrContext
使用されます。resample
他の
1. out_stream -> codecpar -> codec_tag = 0 を理解するにはどうすればよいですか?
機能: マルチメディア ファイルに応じてコーデックを自動的に調整します。
オーディオとビデオをエンコードする場合、入力ストリームのエンコード形式を出力ストリームで指定されたエンコード形式に変換する必要があり、通常は特定のコーデックを使用する必要があります。ただし、コーデックごとに対応するタグ ( ) がcodec_tag
異なるため、出力ストリームのエンコード形式が誤って識別される可能性があります。この問題を解決するには、出力ストリームのエンコード形式のラベルを 0 に設定し、FFmpeg に出力ストリームのエンコード形式を自動的に認識させ、エラーを回避します。
ラベルを 0 に設定しても、すべての出力ストリームに適用されるわけではないことに注意してください。一部のコーデックでは、正しく動作するために正しいタグを指定する必要があります。また、タグを設定する過程では、エンコーダの正常な動作を保証するために、対応する判断とエラー処理が必要です。
2 番目の pkt.pts * av_q2d(in_stream1->time_base)
pkt.pts * av_q2d(in_stream1->time_base)
これは時間単位変換操作であり、pts (プレゼンテーション タイム スタンプ) をストリームのタイム ベース (タイム ベース) から実際の時間単位 (秒単位) に変換します。
ffmpeg では、入力または出力メディア ストリーム内の各オーディオ フレームとビデオ フレームには、pts (表示タイムスタンプ) と dts (デコード タイムスタンプ) が含まれています。
AVPacket 構造体の pts フィールドと dts フィールドにはタイムスタンプが格納されます。実際の時間値を取得するには、対応するタイム ベースに従って変換する必要があります。av_q2d(in_stream1->time_base)
タイムベースを秒に変換します。具体的には、av_q2d
この関数は任意の有理数のタイムベースを秒に変換できます。その関数の定義は次のとおりです。
double av_q2d(AVRational a);
a
: 変換するための合理的な時間ベース。
a
この関数は、秒に変換した後に得られた値を表す浮動小数点数を返します。
したがって、pkt.pts * av_q2d(in_stream1->time_base)
** の意味は、AVPacket に格納されている pts タイムスタンプに入力メディア ストリームのタイムベースを乗算して秒に変換し、実際の時間でのオーディオおよびビデオ フレームの表示時間を取得することです。**