VHS(またはVHS-C)からBD(またはDVD)作成【4】〜タイトルメニュー(PowerProducer編)

今回は、タイトルメニューについて紹介します。
タイトルメニューとは、

※サンプル映像にNHKクリエイティブ・ライブラリーを利用しています。
このようなものです。

PowerProducerPowerDirector
作成するBD(あるいはDVD)にタイトルメニューを設置することができ、
コンテンツへのアクセスが行いやすくなります。

タイトルメニューはテンプレートから作成します。
テンプレートは、

  • PowerProducerにプレインストール済みのテンプレート
  • CyberLinkのDirector Zoneというテンプレートダウンロードサイト
  • PowerDirectorによるテンプレート作成

などにより、入手できます。
プレインストール済みではあまりに選択肢がなさすぎるので、Director Zoneを覗いてみるべきだと思います。
それでもやはり納得するテンプレートがない場合は、PowerDirectorで作成することをおすすめします。

では、一通りの説明ができるように、

  • Director Zoneからテンプレートをダウンロードして、PowerProducerで利用する方法
  • PowerDirectorでテンプレートを作成して、利用する方法

この二つのストーリーを紹介します。

まず、Director Zoneからテンプレートをダウンロードして、PowerProducerで利用する方法です。

  1. 以前の投稿で紹介した動画取り込みを実施
  2. 「ディスク」画面にて「編集」の「メニュー」を選択する。
    メニュー設定へ
  3. 「メニューの設定」画面へ遷移するので、「追加テンプレートのダウンロード」を選択する。
    追加テンプレートのダウンロード
  4. Director Zoneがブラウザで起動するので(サインインして、)ログインし、所望のテンプレートを探してダウンロードする。(ダウンロードしたものはdzmという拡張子で保存されます。)
    Director Zonedzmアイコン
  5. ダウンロードしたものを実行する。
  6. 「メニューの設定」画面で「テンプレート」とを選択する。
    テンプレートへ
  7. ダウンロードしたテンプレートを選択する。(なければ、1度PowerProducerを再起動してみて下さい。)
    テンプレートを選択

テンプレートを決めた後は、BGMや文字列の内容や位置、色、フォント、また、サムネイルの位置変更が可能です。

メニューは階層になっていますので、階層を遷移しながら、各画面に設定を行う必要があります。
トップ画面からサムネイルの画面へ遷移するには「シーン」を選んで、「決定」をクリックします。
サムネイルの画面からは、「次のページ」「前のページ」「メインへ戻る」を使って、各画面へ遷移します。
メニュー間移動

最後に「OK」で完了です。

次回は、PowerDirectorでテンプレートを作成して、利用する方法を紹介します。

vectorに詰め込んだオブジェクト解放するための便利関数

久しぶりにテンプレート関数を使おうとしたときのいくつかの間違いを覚書として書いておきます。

Utilityクラスなるものを用意し、次のような静的メソッドを宣言、定義しました。

Utility.h

template<typename T>
static void Utility::releaser(std::vector<T*>& v);

Utility.cpp

template<typename T>
void Utility::releaser(std::vector<T*>& v)
{
  std::vector<T*>::iterator it;
  it = v.begin();
  while(it != v.end()){
    delete (*it);
    it = v.erase(it);
  }
}

これをコンパイルすると、

.cpp: 静的メンバ関数 ‘static void Utility::releaser(std::vector<T*>&)’ 内:
.cpp:???:???: エラー: need ‘typename’ before ‘std::vector<T*>::iterator’ because ‘std::vector<T*>’ is a dependent scope
.cpp:???:???: エラー: expected ‘;’ before ‘it’
.cpp:???:???: エラー: ‘it’ was not declared in this scope

といったエラーがでます。

because ‘std::vector’ is a dependent scope
はstd::vectorという部分がTに依存するため、型なのか変数名なのか、何なのか分からない、ということ言っています。
(VC++の場合は、問題なくコンパイルが通るらしいです。)

need ‘typename’ before ‘std::vector::iterator’
型だと分かるように「typename」をつけてください、と言っています。
この時点でこのコンパイラ自身は型だとわかっているようですが、どんなコンパイラでも通るように厳しく戒めてくれている、という理解です。

Utility.cpp

template<typename T>
void Utility::releaser(std::vector<T*>& v)
{
  typename std::vector<T*>::iterator it;

  it = v.begin();
  while(it != v.end()){
    delete (*it);
    it = v.erase(it);
  }
}

言われた通りにつけてみましたが、今度は、

Hoge.o: In function `hogehoge(void)':
Hoge.cpp:???: undefined reference to `void Utility::releaser<Hoge>(std::vector<Hoge*, std::allocator<Hoge*> >&)'

と怒られてしまいました。
これは実際にHoge.cppでUtility::releaserを使用している個所でその実体が何か分からない、ということを言っています。
Utility.cppにおいて、クラスHogeを考慮したテンプレート関数の実体化を行っていない、かつ、Hoge.cppでも実体化を行っていないためです。
そこで、Hoge.cppで実体化が行われるように、Utility.h、つまりヘッダにテンプレートの実装を書きます。
Utility.cppの実装は消去し、

Utility.h

template<typename T>
static void Utility::releaser(std::vector<T*>& v)
{
  typename std::vector<T*>::iterator it;

  it = v.begin();
  while(it != v.end()){
    delete (*it);
    it = v.erase(it);
  }
};

これで、テンプレート関数が使えます。

どうしても定義と実装を分けたい場合は、
明示的実装というものがあり、分けることもできるそうです。
予めテンプレートの使用パターンを宣言しておくというやり方です。
また、exportという記述子があり、定義と実装を分け、予めのパターン列挙も必要ないそうです。
ただし、こちらは対応コンパイラが少ないそうです。

このあたりのお話は、こちらが参考になりました。
http://d.hatena.ne.jp/pknight/20090826/1251303641
http://d.hatena.ne.jp/pknight/20090826/1251307608