CRI Sofdec  Last Updated: 2024-01-10 18:57 p
メモリ管理

Sofdec でムービー再生を行う場合のメモリ管理について説明します。
アプリケーション自前のメモリ管理システムを使うことも可能です。その方法についても紹介します。

Sofdec のメモリ管理(概要)

Sofdec ライブラリが必要とするワークバッファーは、全てアプリケーションから指定します。
ライブラリが内部で勝手にシステム関数を利用してメモリ確保することはありません。

Sofdec ライブラリに渡すワークバッファーは、大きくわけて次の4種類があります。

Sofdec ランタイムに必要なワークバッファーの種類
ワークバッファー種別 説明
(a) ライブラリ共通 ライブラリ初期化時に渡します。ライブラリ全体で1つです。
(b) ハンドル基本 再生ハンドル作成時に渡します。ハンドルごとに1つ必要です。
(c) 再生用ワーク ムービーデータのスペックや再生方法にあわせてサイズが決まります。
再生開始後、ヘッダー解析が終わった時点で渡します。
(d) メタデータ用 シーク情報やキューポイント情報を格納するためのバッファーです。
ヘッダー解析中に渡します。

(a)(b)(c)は、ワークサイズ計算関数またはワークサイズ取得関数を使用して、アプリケーションが必要なワークバッファーを確保して渡します。
(d)だけはワークの確保方法が違います。(d)は、アプリケーションがメタデータ用メモリ関数を登録し、ライブラリがその関数を呼び出します。


ライブラリ共通ワークバッファーについて

ライブラリ初期化時に、ライブラリ共通で使用するワークバッファーを指定する必要があります。
構造体 CriManaLibConfig をゼロクリア後、必要なパラメーターを指定してから criMana_CalculateLibWorkSize() でワークサイズが取得できます。
確保したワークバッファーは、初期化関数 criMana_Initialize() の引数として指定します。

CriManaLibConfig lib_config;
/* ライブラリ初期化パラメーターの指定 */
memset(&lib_config, 0, sizeof(lib_config));
lib_config.max_decoder_handles = 1;
/* Manaライブラリ初期化 */
lib_work_size = criMana_CalculateLibWorkSize(&lib_config);
lib_work = malloc(lib_work_size);
criMana_Initialize(&lib_config, lib_work, lib_work_size);
void criMana_Initialize(const CriManaLibConfig *config, void *work, CriSint32 work_size)
ライブラリの初期化
CriSint32 criMana_CalculateLibWorkSize(const CriManaLibConfig *config)
ライブラリ初期化用ワーク領域サイズの計算
@ CRIMANA_THREAD_MODEL_SINGLE
Definition: cri_mana.h:346
Manaライブラリ初期化パラメーター
Definition: cri_mana.h:642
CriUint32 max_decoder_handles
Definition: cri_mana.h:645
CriManaThreadModel thread_model
Definition: cri_mana.h:649

ハンドル基本ワークバッファーについて

再生ハンドル CriManaPlayerHn 作成時には、ハンドル基本ワークバッファーを指定する必要があります。
ハンドル基本ワークバッファーは、再生ハンドルの管理領域やヘッダー解析用のバッファーを含んでいます。
ハンドル作成と、再生するムービーのスペック指定を分離することで、一度作った再生ハンドルの再利用をメモリの無駄なく実行することができます。

ハンドル基本ワークバッファーのサイズは、 criManaPlayer_CalculateHanldeWorkSize() で取得できます。引数はありません。
確保したワークバッファーは、ハンドル作成関数 criManaPlayer_Create() の引数として指定します。

/* Manaハンドルの作成 */
hn_work_size = criManaPlayer_CalculateHanldeWorkSize();
hn_work = malloc(hn_work_size);
mana = criManaPlayer_Create(hn_work, hn_work_size);
CriManaPlayerHn criManaPlayer_Create(void *work, CriSint32 work_size)
Manaプレーヤーの作成(コンフィグ指定なし)
CriManaPlayerObj * CriManaPlayerHn
プレーヤーハンドル
Definition: cri_mana.h:802

再生用ワークバッファーについて

再生ハンドルを使用してムービーファイルのヘッダー解析が終わったあと、実際に再生を開始するためには再生用ワークバッファーを指定する必要があります。
再生用ワークバッファーを計算するための情報は、基本構造体と応用構造体の2種類に分かれています。

再生用ワークバッファーのパラメーター
パラメーター種別 説明
再生ワーク用パラメーター構造体 (基本)
CriManaPlaybackBasicWorkConfig
ビデオの解像度、再生するオーディオトラック番号、読み込みバッファー情報、字幕情報のパラメーターです。
再生ワーク用パラメーター構造体 (応用)
CriManaPlaybackExWorkConfig
アルファムービー、追加ボイストラックのパラメーターです。省略可能です。

ヘッダー解析が終わった後であれば、 criManaPlayer_GetPlaybackWorkParam() を使用して、再生用ワークバッファーのパラメーターを取得することが出来ます。
アプリケーションは取得したパラメーターで、変更したいパラメーターだけを調整して再生用ワークバッファー計算関数 criManaPlayer_CalculatePlaybackWorkSize() の引数として使用することができます。

解像度やオーディオのスペックが事前にわかっている場合は、ヘッダー解析を行わずに再生用ワークバッファーのパラメーターをアプリケーションが直接作成することも可能です。

事前のヘッダー解析をせず、アプリケーションが手動で再生用ワークバッファーパラメーターを作成するサンプルコードです。

/* 再生用ワークの手動パラメーター設定 */
memset(&config_b, 0, sizeof(config_b));
config_b.common_params.readbuf_size_byte = 4*1000*1000/8; /* ビットレートから計算 */
config_b.video_params.video_flag = CRI_TRUE;
config_b.video_params.max_width = 320;
config_b.video_params.max_height = 240;
config_b.main_audio_params.audio_flag = CRI_TRUE;
config_b.main_audio_params.sampling_rate = 480000;
/* 再生用ワークの計算と確保 */
ply_work_size = criManaPlayer_CalculatePlaybackWorkSize(mana, &config_b, NULL);
ply_work = malloc(ply_work_size);
criManaPlayer_SetPlaybackWork(mana, &config_b, NULL, ply_work, ply_work_size);
CriSint32 criManaPlayer_CalculatePlaybackWorkSize(CriManaPlayerHn player, const CriManaPlaybackBasicWorkConfig *config_basic, const CriManaPlaybackExWorkConfig *config_ex)
再生用ワーク領域のサイズ計算
void criManaPlayer_SetPlaybackWork(CriManaPlayerHn player, const CriManaPlaybackBasicWorkConfig *config_basic, const CriManaPlaybackExWorkConfig *config_ex, void *work, CriSint32 work_size)
再生ワーク領域の設定
CriSint32 output_buffer_samples
Definition: cri_mana.h:902
CriUint32 num_channels
Definition: cri_mana.h:898
CriUint32 sampling_rate
Definition: cri_mana.h:894
CriBool audio_flag
Definition: cri_mana.h:890
再生ワーク用パラメーター構造体 (基本)
Definition: cri_mana.h:980
CriManaPlaybackCommonParams common_params
Definition: cri_mana.h:983
CriManaPlaybackAudioParams main_audio_params
Definition: cri_mana.h:991
CriManaPlaybackVideoParams video_params
Definition: cri_mana.h:987
CriSint32 readbuf_size_byte
Definition: cri_mana.h:820
CriBool video_flag
Definition: cri_mana.h:842
CriSint32 max_width
Definition: cri_mana.h:846
CriSint32 max_height
Definition: cri_mana.h:850
CriSint32 num_frame_pools
Definition: cri_mana.h:854

ヘッダー解析後に再生用ワークバッファーパラメーターを取得して指定するサンプルコードです。

/* ファイル名を指定してヘッダー解析開始 */
criManaPlayer_SetFile(mana, NULL, FILE_PATH);
.....
/* ハンドル状態が CRIMANAPLAYER_STATUS_WAIT_PREP になった後…… */
/* 再生用ワークバッファーパラメーターを取得 */
criManaPlayer_GetPlaybackWorkParam(mana, &config_b, &config_ex);
/* 再生用ワークバッファーサイズの計算と確保 */
ply_work_size = criManaPlayer_CalculatePlaybackWorkSize(mana, &config_b, &config_ex);
ply_work = malloc(ply_work_size);
criManaPlayer_SetPlaybackWork(mana, &config_b, &config_ex, ply_work, ply_work_size);
void criManaPlayer_DecodeHeader(CriManaPlayerHn player)
ヘッダーのデコード要求
void criManaPlayer_SetFile(CriManaPlayerHn player, CriFsBinderHn bndrhn, const CriChar8 *path)
ムービーファイルの設定
再生ワーク用パラメーター構造体(拡張)
Definition: cri_mana.h:1011
再生ワークメモリの解放について
再生終了後も再生ワークメモリは利用される可能性があるため、再生ワークメモリは再生終了しても直接破棄しないでください。 再生終了/停止後のプレーヤーハンドル再利用時にメモリだけは一時的に解放をしておきたい場合、必ずcriManaPlayer_FreePlaybackWork 関数を呼び出してからメモリの解放を行ってください。 なお、ハンドルの破棄を行った後であれば無条件に再生ワークメモリを解放して構いません。
[備考] ユーザーアロケーター登録時について
ユーザーアロケーター登録時(ユーザーアロケーターについては下記参照)は、criManaPlayer_SetPlaybackWork 関数を呼び出す必要はありません。ユーザーアロケーターを経由して必要なタイミングで再生ワークメモリを確保します。

メタデータ用ワークバッファーについて

メタデータ用ワークバッファーだけは、他のワークバッファーと違いメモリ関数が必要です。
メタデータ用メモリ関数の登録は criManaPlayer_SetMetaDataWorkAllocator() を使用します。
メモリ確保関数、メモリ解放関数、ユーザーオブジェクトポインタ、メタデータ使用フラグを引数で指定します。 (現在、メタデータ使用フラグの指定には対応していません。)

現在、メタデータにはシーク情報とキューポイント情報が含まれています。シーク再生もキューポイントも使用しない場合は、 メモリ関数を登録しないことでメモリ確保自体を行わなくなります。
登録したメモリ関数はヘッダー解析処理中に呼び出されます。マルチスレッドデコードを使用している場合は、メモリ関数がデコードスレッド側から発生します。 使用するメモリ確保関数がスレッドセーフではない場合は、アプリ側で排他制御を行ってください。

/* ハンドルの作成 */
mana = criManaPlayer_Create(hn_work, hn_work_size);
/* メタデータ用メモリ関数の登録 */
criManaPlayer_SetMetaDataWorkAllocator(mana, meta_alloc, meta_free, NULL, 0);
/* ヘッダー解析開始 */
criManaPlayer_SetFile(mana, NULL, FILE_PATH);
void criManaPlayer_SetMetaDataWorkAllocator(CriManaPlayerHn player, CriManaMetaMallocFunc allocfunc, CriManaMetaFreeFunc freefunc, void *obj, CriManaMetaFlag meta_flag)
メタデータ用アロケーターの登録

アプリケーション独自のメモリ管理の使用 (ユーザーアロケーター登録機能)

Sofdec用のメモリ確保/解放関数をアプリケーション側で定義してライブラリに登録することが出来ます。
メモリ確保/解放関数を登録した場合、アプリケーションはワークバッファーサイズの計算やバッファー登録をする必要がなくなります。
メモリ関数を登録した上で、各ワークバッファー設定関数のバッファーアドレスにはNULLを指定してください。
必要なメモリはSofdecライブラリが随時、登録された関数を呼び出して確保/解放します。
なお、関数登録を利用した場合、ワークバッファーは関数で個別に指定する時よりも細かな単位で分割して確保される場合があります。

/* メモリ確保 */
void *user_alloc(void *obj, CriUint32 size)
{
void *ptr;
ptr = malloc(size);
return ptr;
}
/* メモリ解放 */
void tutil_free(void *obj, void *ptr)
{
free(ptr);
}
....
/* メモリ関数の登録 */
criMana_SetUserAllocator(user_alloc, user_free, NULL);
....
/* Sofdecライブラリの初期化 */
criMana_Initialize(&lib_config, NULL, 0);
/* 再生ハンドルの作成 */
mana = criManaPlayer_Create(NULL, 0);
....
/* 再生用ワークの設定は不要 */
//criManaPlayer_SetPlaybackWork(mana, &config_b, NULL, ply_work, ply_work_size);
void criMana_SetUserAllocator(CriManaMallocFunc malloc_func, CriManaFreeFunc free_func, void *obj)
ユーザーアロケーターの登録