CRI Sofdec  Last Updated: 2024-01-10 18:57 p
サンプル:単純再生

このサンプルプログラムでは実装を単純にするために、次の方法で再生しています。

  • メモリ関数を登録(個別のワークバッファー渡しは無し)
  • メタデータ用メモリ関数なし(シーク再生/キューポイント取得は不可)
  • 事前ヘッダー解析なし(ムービーの解像度やアルファ有無は固定)

サンプルコードから重要な部分を抜粋して、いくつかのステップに分けて紹介します。

1.初期化、ハンドル作成
/* Sofdec にメモリアロケーターを登録 */
criMana_SetUserAllocator(user_alloc, user_free, NULL);
/* CRI AtomExライブラリの初期化 (必ずManaの初期化の前に行ってください) */
criAtomEx_Initialize(NULL, NULL, 0);
/* CRI Manaライブラリの初期化(デフォルトでマルチスレッドモデル) */
criMana_Initialize(NULL, NULL, 0);
/* プレーヤーの作成 */
app_obj->player = criManaPlayer_Create(NULL, 0);
void criMana_Initialize(const CriManaLibConfig *config, void *work, CriSint32 work_size)
ライブラリの初期化
void criMana_SetUserAllocator(CriManaMallocFunc malloc_func, CriManaFreeFunc free_func, void *obj)
ユーザーアロケーターの登録
CriManaPlayerHn criManaPlayer_Create(void *work, CriSint32 work_size)
Manaプレーヤーの作成(コンフィグ指定なし)
criMana_SetUserAllocator 関数でメモリアロケーターを登録しておくことで、 ワーク領域が必要なモジュールの初期化やハンドル作成処理において、ワーク領域の指定を省略できます。 なお、Sofdec単体で使用する場合でも、::criAtomEx_Initialize 関数 の呼び出しは必ず行ってください。



2.再生開始
/* ムービーファイルの指定 */
criManaPlayer_SetFile(app_obj->player, NULL, USM_FILE);
/* 再生の開始 */
criManaPlayer_Start(app_obj->player);
void criManaPlayer_Start(CriManaPlayerHn player)
再生開始
void criManaPlayer_SetFile(CriManaPlayerHn player, CriFsBinderHn bndrhn, const CriChar8 *path)
ムービーファイルの設定
メモリアロケーターを登録した場合は、::criManaPlayer_SetPlaybackWork 関数による再生用ワークバッファーの設定を 省略していきなり再生を開始することができます。



3.定常処理
/* [定期処理] Atom側のサーバー処理を実行 */
criAtomEx_ExecuteMain();
/* [定期処理] ムービー時刻の同期 */
/* [定期処理] サーバー処理の実行 */
void criMana_SyncMasterTimer(void)
マスタータイマーへの同期
void criMana_ExecuteMain(void)
サーバー処理の実行
上記3つの関数をアプリケーションループ内で毎V呼び出してください。これらの呼び出しが1vsync以上 滞ってしまうと、ムービー再生がガタついてしまう可能性がありますので注意してください。



4.ビデオフレームの取得
/* フレームプールにデコード済みのフレームがあるか? */
if (criManaPlayer_ReferFrame(app_obj->player, &frame_info) == CRI_TRUE) {
/* フレームが表示時刻になっているか? */
if (criManaPlayer_IsFrameOnTime(app_obj->player, &frame_info) == CRI_TRUE) {
/* シェーダー用にフレームバッファーのコピー */
smpvideo_texture_lock_buffer(app_obj->svt, &yuvbufs);
criManaPlayer_CopyFrameToBuffersYUV(app_obj->player, &frame_info, &yuvbufs);
smpvideo_texture_unlock_buffer(app_obj->svt);
/* 描画し終わったのでフレームを破棄 */
criManaPlayer_DiscardFrame(app_obj->player, &frame_info);
}
}
CriBool criManaPlayer_IsFrameOnTime(CriManaPlayerHn player, const CriManaFrameInfo *frame_info)
フレームの時刻判定
void criManaPlayer_CopyFrameToBuffersYUV(CriManaPlayerHn player, const CriManaFrameInfo *frame_info, CriManaTextureBuffersYUV *frame_buf)
デコード結果の取得 (YUV個別バッファー方式)
void criManaPlayer_DiscardFrame(CriManaPlayerHn player, const CriManaFrameInfo *frame_info)
フレームの解放
CriBool criManaPlayer_ReferFrame(CriManaPlayerHn player, CriManaFrameInfo *frame_info)
デコード済みのフレーム情報の参照
YUVテクスチャバッファー構造体
Definition: cri_mana.h:1451
ライブラリ側では描画処理を行いませんので、アプリケーション側でムービーを描画するテクスチャをあらかじめ 確保してください。そして、適切なフレーム形式を選択してテクスチャバッファーにデータをコピーします。


criManaPlayer_ReferFrame 関数で参照したフレームは、アプリケーション側にフレームデータをコピーした後、 criManaPlayer_DiscardFrame 関数を呼び出さないと次のフレームを参照できませんので注意してください。 詳しいビデオフレーム取得に関する情報は ビデオフレームの取得と表示について を参照ください。



5.再生終了待ちと再生停止状態チェック
/* Manaプレーヤーのステータス取得 */
app_obj->player_status = criManaPlayer_GetStatus(app_obj->player);
/* 再生終了 or 停止状態ならアプリ終了を要求 */
if (app_obj->player_status == CRIMANAPLAYER_STATUS_PLAYEND ||
app_obj->player_status == CRIMANAPLAYER_STATUS_STOP) {
return CRI_FALSE;
}
CriManaPlayerStatus criManaPlayer_GetStatus(CriManaPlayerHn player)
Manaプレーヤーの状態取得
@ CRIMANAPLAYER_STATUS_STOP
Definition: cri_mana.h:244
@ CRIMANAPLAYER_STATUS_PLAYEND
Definition: cri_mana.h:268
criManaPlayer_GetStatus 関数でプレーヤーの状態を取得し、終了状態( CRIMANAPLAYER_STATUS_PLAYEND ) が取得できたら再生終了です。また、 criManaPlayer_Stop 関数で再生を停止した場合は再生停止状態( CRIMANAPLAYER_STATUS_STOP )になります。この状態になるまでプレーヤーハンドルを壊さないように注意してください。



6.終了処理
/* プレーヤーハンドルの破棄 */
criManaPlayer_Destroy(app_obj->player);
/* Manaライブラリの終了 */
/* AtomExライブラリの終了 */
criAtomEx_Finalize();
void criMana_Finalize(void)
ライブラリの終了処理
void criManaPlayer_Destroy(CriManaPlayerHn player)
Manaプレーヤーの破棄
ムービー再生の終了時には、各ハンドルを対応する関数で破棄します。登録したメモリアロケーター関数を呼び出してライブラリ が確保したワーク領域は、それぞれの対応した破棄関数・終了関数で同じく登録アロケーターを呼び出して解放されます。