The Media Kit Table of Contents | The Media Kit Index |
Derived from: virtual BMediaNode
Declared in: be/media/BufferProducer.h
Library: libmedia.so
Allocation: Constructor only
BBufferProducerは、他のnode(特にBBufferConsumer)によって受け取られ、処理される可能性のあるメディアデータを内包するバッファを発行するBMediaNodeです。もしnodeがバッファを発行したければ、そのnodeはBBufferProducerから派生しなければならず、またBBufferProducerのプロトコルを実装するためにフック関数をオーバーライドしなければなりません。
このクラスにはB_CLIP_SHORT_RUNSとBRegionとを変換する関数がありますが、現在のところ、Media KitにサポートされているビデオクリップのフォーマットはB_CLIP_SHORT_RUNSのみです。
このフォーマットは、二つのint16値から構成されるヘッダで始まります。
offsetX | 以下の全ての座標に対するX座標のオフセット。 |
offsetY | 以下の全ての座標に対するY座標のオフセット |
これらの値は、残りのクリッピングデータを通してのX軸とY軸の座標に対するオフセットを示します。
クリッピングデータの残りは、下記のようにビデオデータの行を表すentryで構成されています :
numShorts | coordListの値の数。常に偶数。もし負の数であれば、前回のentryを |numShorts| 回繰り返す。 |
coordList... | 座標のリスト。偶数のentryは左端のX座標、奇数のentryは右端のX座標である。 |
クリッピングデータは、クリッピング情報が変化するたびに、これらのentryのうち一つを含みます。
例えば、もしクリッピングが、左辺が100、上辺が50、右辺が300、底辺が200の矩形であれば、640x480のディスプレイに対するクリッピングデータはこのようになるでしょう :
header
|
entry 1
|
entry 2
|
entry 3
|
entry 4
|
ヘッダは、50行目から始まるクリッピングデータを表します。
最初のentryは、クリッピングがクリッピングの最初の行(50行目)の100列目から300列目の長さであることを示します。二つ目のentryは、これが150回繰り返されることを示します。
Entry 3 は、その点から始まるクリッピングが0列目から639列目まで(ディスプレイの全幅)であることを示しています。Entry 4 では、これをディスプレイの底まで280回繰り返します。
外部のカプセル化されたレイヤーに於いてタイミング情報を提供しないメディアフォーマットをサポートするために、あるいはキーフレームをサポートしたメディアフォーマットに対するseek性能を向上させるために、Media Kitはseekタグの概念をサポートします。自分のデータがタイミング情報を持たないと分かっているか、あるいは特殊なタグを使用してseek性能の向上を提供できるproducerは、自身の送るバッファのヘッダuser_dataフィールドにタグを置きます。このタグは、producerが必要とする任意のデータを内包できます。
それらをデコードした後にそのパケットから優良なタイミング情報を得ることができるconsumerは、後に適切なseek pointを選択し、そのseek pointに到達した最初のバッファのperformance timeとタグの値をキャッシュします。
デコーダの助けなしにはseekできないproducerは、その後FindSeekTag()を呼び出すことでconsumerを探すことができるようになります。これはconsumerのSeekTagRequested()関数が呼び出される原因となります。この関数は、要求された時間にもっとも近いseekタグと時間を返します。producerは、メディアデータ中の適切なポイントをの場所を示すこの情報を使用できます。
これを用いる最も簡単な方法は、タグのデータとしてファイルのオフセットを使用することですが、consumerはデータの複製を保存だけして内容を見ずに返却するので、producerにとって意味のある任意の値が使用できます。
Time Seek Tag |
0.0 seconds 0 |
0.1 seconds <none> |
0.2 seconds 2 |
0.3 seconds <none> |
この単純な例では、4つのバッファがあり、2つのseekタグが(0.0秒と0.3秒に)記録されています。もしproducerが0.2秒をseekするならば、FindSeekTag()をこの様に呼び出すでしょう :
media_seek_tag tag; bigtime_t time; FindSeekTag(&destination, 0.2*1000000, &tag, &time); /* now we can use the tag to seek */
もしタグがファイルのオフセットを含んでいれば、単純にファイル中のオフセットをseekすることができ、準備が整います。
この例では、要求された時間に正確に位置するseekタグがあるため、返されるタグは"2"であり、時間は0.2秒です。しかしながら、もし0.1秒のseekタグを探したなら、それが要求された時間と最も近くに一致するタグであることから、"0"のタグと0.0秒の時間が返されます。
protected:
|
BBufferProducerオブジェクトをコンストラクトします。producerTypeには、そのnodeによって出力されるメディアデータの型が指定されます。
もしnodeが一つ以上のデータ型を産生するならば、BBufferProducerのサブクラスは種類(kind)をデフォルト(ワイルドカード値)に設定します。
もしnodeに開始時点で追加すべきlatencyがあるなら、この情報を記録するためにSetInitialLatency()を呼び出して下さい。これは、nodeが産生するバッファが、テレビ信号の様にあまり頻繁にリフレッシュされない入力信号によって生成される場合です。
|
|
consumerがBBufferConsumer::RequestAdditionalBuffer()を呼び出した時、結果としてこの関数が呼び出されます。この関数の仕事は、直ちに次のバッファをconsumerに送るためにSendBuffer()を呼び出すことです。
引数previousBufferID、previousTime及びpreviousTagは、consumerが受け取った最後のバッファを識別します。nodeは、次のバッファを記述されたものの後に送信することで対応します。
|
もし全てがうまくいけば、B_OKを返して下さい。そうでなければ、適切なエラーコードを返して下さい。
|
sourceとdestinationとの間を流れるデータが、直ちにnewFormatによって指定されるフォーマットに変更されるよう、destinationに通知します。
|
RETURN CODES
B_OK. フォーマット変更要求はエラーなしに送信された。
|
与えられたクリッピングデータ clipDatain (指定されたformat)のうちbyteCountバイトで、指定されたregionをクリッピング領域に一致させます。
指定したregionは、すでに存在してなければなりません。
現在サポートされているフォーマットは、B_CLIP_SHORT_RUNSだけです。
RETURN CODES
B_OK. クリップデータはエラーなしに変換された。
こちらもご覧下さい: BBufferConsumer::RegionToClipData()
|
このフック関数は、sourceとdestinationの間の接続を確立するために実装されます。フォーマットの交渉は、すでにConnect()が呼び出されるまでに完了しているため、nodeは指定されたformatを受け入れなければなりません。
引数statusは、接続が実際に行われているかどうかを示します。これはBBufferConsumer::Connected()関数によって返される結果コードか、または接続の他の準備を行っている間に生じたエラーを示します。
もしstatusがB_OKでなければ、この接続のためにPrepareToConnect()によって予約されたmedia_sourceを開放して下さい。そうすることで、それを他の接続のために利用できるようになります。
この関数が呼び出されたとき、ioNameはconsumerによって指定された接続名を含んでいます(これはBBufferProducer::PrepareToConnect() によって指定された名前とは異っているでしょう)。戻る際には、ioNameが接続に対する名前を指しているでしょう。もし名前が現実に問題となるなら、ioNameに書き戻すために、名前を複製しておいて下さい。そうでなければ、放っておくことができます。
|
Disconnect()は、指定されたsourceとdestinationを終了させるために実装されます。一度この関数が戻ったら、もはや接続にはいかなるバッファも送ってはいけません。
もしBBufferGroupが(SetBufferGroup()経由で)producerのために指定されていたなら、この関数でそれを削除して下さい。
|
クライアントがGetNextOutput()呼び出しを経由して出力を通る繰り返し動作を完了したら、最後の値をcookieとしてこの関数を呼び出すでしょう。これによって、繰り返し処理のために確保したメモリの破棄を行う機会が得られます。
もしcookieが無事に破棄されたら(またはなにもする必要がなければ)、B_OKを返して下さい。そうでなければ、適切なエラーコードを返して下さい。
|
このフック関数は、consumerのSetOutputEnabled()関数が呼ばれた時に呼び出されます。これはwhichOutputによって指定された出力に、バッファを送る必要があるかどうか示します。バッファを必要としない出力にバッファを送らないように、この関数を実装しなければなりません。引数_depreciated_は、もう使用されていません。
デフォルトでは、出力はenabledです。
|
GetLatencyFor()は、destination forDestinationに送られるデータによって持ち込まれたlatencyを返します。関数が戻る際は、latencyはoutLatencyに保存され、forDestinationによって使用されるtime sourceがoutTimeSourceで使用できるようになります(エラーが返された場合は除きます。この場合、これらの値は不定となります)。
あるtime sourceから他のtime sourceにバッファを送る際のlatencyは、二つの異ったtime sourceの時間の経過の間にはなんの関係もないと思われるため、常にゼロであると仮定されます。
RETURN CODES
B_OK. latencyはエラーなしに返された。
|
seek機能を改善するために、Media Kitはseekタグの概念を提供します。これは(Cinepakビデオのキーフレームといった)メディアデータ中の位置を容易に識別するための特別なタグです。FindSeekTag()関数は、forDestinationで指定されるconsumerに対して、inTargetTimeによって指定される時間に最も近いseekタグを要求し、outTagにタグを、outTaggedTimeにはそのタグに対応する時間を返します。関数が返る際には、(もしそのポインタがNULLでなければ)outFlagsは与えられたタグに関する詳細を内包しています。
現在のところ、inFlagsまたはoutFlagsに対して定義された値はありません。
RETURN CODES
B_OK. エラーなし。
|
与えられたsourceから指定されたdestinationに流れるメディアデータのフォーマットを、指定されたioFormatに変更するために、FormatChangeRequested()を実装して下さい。もしioFormatにワイルドカードが指定されるなら、この関数が戻る前に、優先されるフォーマットに一致するフォーマットをそれに収めて下さい。引数_depreciated_は無視して下さい。それはもう使用されていません。
|
もし変更の要求が問題なく処理されれば、B_OKを返して下さい。そうでなければ、適切なエラーコードを返して下さい。
こちらもご覧下さい: FormatSuggestionRequested(), FormatProposal()
|
BBufferProducerは、指定されたoutputに対して提案されたmedia_formatが適切であることを証明するために、この関数を実装します。もしformatの任意のフィールドがワイルドカードであり、尚且つ特定の要求があれば、関数が戻る前に、その要求に合うようにそれらのフィールドを適合させて下さい。
もし提案されたformatが受け入れられるものであれば、B_OKを返して下さい。一度これを行うと、Media Kitは任意の接続要求が(なにか変更が行われた後であっても)指定されたフォーマットでoutputに生成できると仮定します。
もしoutputが使用できなければ、B_BAD_SOURCEを返して下さい。
もしformatが条件に合わなければ、B_BAD_MEDIA_FORMATを返して下さい。
|
producerが、要求されたtype及びquality要求を満足するように発行できるformatによって指し示されるバッファを満たして返すように、FormatSuggestionRequested()を実装しなければなりません。
もしproducerが、扱えるフォーマットの中で範囲をもって作業できるなら、引数qualityがなにを選択するかの指針になります。例えば、プレビューには10fpsを使用し、インターレース方式で640x480の大きさの最高画質のビデオには60fpsを使用することができるでしょう。
もしtypeが、producerが一緒に働きたくないメディアクラスであれば、B_BAD_MEDIA_FORMATを返して下さい。もしある特定のフィールドについて広い範囲の値を受け入れるよう準備するなら、そのフィールドにワイルドカード値を設定して下さい(詳細は、media_audio_format::wildcard()及びmedia_video_format::wildcard()をご覧下さい)。
もしformatが問題なく返れば、B_OKを返して下さい。
|
データのバッファが最終的なdestinationに到達するまで、BBufferProducerがそれを受け取ることによって生じるlatencyの総量をoutLatencyに保存するために、このフック関数を実装します。
データの転送されている出力がなんであれ、FindLatencyFor()を呼び出し、これらの値のうち最大のものにそれ自身のlatencyを追加し、そしてその値を返して下さい。
GetLatency()は、デフォルトで現在繰り返し作業に使用可能な出力のうち最大のlatencyを探すように実装されています。そのため、単純にこの関数を実装するには、この関数の派生バージョンをまず呼び出す必要があり、その後に自分自身の処理のlatencyを戻り値に追加して下さい。
RETURN CODES
B_OK. latencyは無事に返された。
|
この関数は、使用可能な出力に関する情報を返すために実装して下さい。新しい繰り返しループのために初めて呼び出された時、cookieによって指し示される値は0になります。GetNextOutput()が呼び出されるたびに、繰り返し処理の中でクライアントがどこにいるか持続的に追跡する事のできる意味のある値をcookieに設定しなければなりません。しかし、それには決して0を設定してはいけません。
初回を含めたGetNextOutput()の各々の呼び出しについて、outOutput内で繰り返しループを行っている間に、クライアントが見たことのない出力のうちの一つを返して下さい。
一度全ての出力を報告し終わったら、B_ERRORを返して下さい。
|
BBufferProducerから派生したnodeがその制御ポートにメッセージを受け取った時、扱う方法を知っているか、あるいは各々の先祖のクラスをHandleMessage()の実装の一つがB_OKを返すまで(BBufferProducer::HandleMessage()から開始して)順番にディスパッチして、自分自身でそれを扱って下さい。もしこの関数から派生して実装された関数が一つもB_OKを返さなければ、それを扱うためにBMediaNode::HandleBadMessage()にそのメッセージを渡して下さい。
ポートを監視するスレッドは、受け取ったメッセージをディスパッチするためにHandleMessage()を呼び出して下さい。
こちらもご覧下さい: BMediaNode::HandleMessage(), "About Multiple Virtual Inheritance" 21ページ目
|
このフック関数は、あなたからデータを受け取るBBufferConsumerが、自分のlatencyが変化したと判断したときに呼び出されます。
引数sourceは接続に関わる出力を示し、destinationは接続がリンクされているconsumerの入力を指定します。newLatencyは、consumerの新しいlatencyです。flagsは、現在のところ使用されていません。
データがスムーズに流れる状態を保つために、あなたがあなた自身のlatencyの計算を適合させる必要があるならば、その機能を実装するためにこの関数をオーバーライドします。
|
このフック関数は、データを受け取るBBufferConsumerがデータが遅れて到着すると判断した時(BBufferConsumer::NotifyLateProducer()が呼び出された時)に呼び出されます。バッファ遅延の正確な時間は、引数howLateによって指定されます。現在の実行モードに合わせて、上流のnodeに対してバッファを早めに配送するように依頼したり、バッファを脱落させたり、またはその他の適切な動作によって問題の修正が必要なステップをすべて行うように、この関数を実装して下さい。
引数performanceTimeは、通知が送られたperformance timeを指定します。
こちらもご覧下さい: BMediaNode::RunMode()
|
PrepareToConnect()フック関数は、formatに残された任意のワイルドカードを特殊化する最後のチャンスをproducerに与えるために、source whichSourceとdestination whichDestinationの間の新しい接続が確立される前に呼び出されます(この点に於てなすべきことがなくても、とにかくチェックは行って下さい)。
加えて、outSourceには接続のために使用されるsourceを返し、outNameバッファには接続に与えられる名前を収めて下さい。consumerはこれを、BBufferConsumer::Connected()で指定される引数outInput->nameに見ることになります。もしnodeが名前が何であるか問題にしない場合、outNameは放置しておいて構いません。
|
もし接続処理が続行するならB_OKを、もしなにか問題があれば適切なエラーコードを返して下さい。
もしB_OKが返されたら、新しい接続が確立していることを知らせるために、consumerのConnected()関数が呼ばれるでしょう。最後に、producerのConnect()関数が交換を完了させるために呼び出されます。
こちらもご覧下さい: BBufferConsumer::Connected(), Connect()
|
nodeによって産生されるメディアデータのmedia_typeを返します。
|
destination forDestinationが、指定されたformatのバッファを受け取るよう準備されているかどうか判断するために、この関数を呼び出して下さい。この関数は、要求するフォーマットがワイルドカードを含む接続要求の中で、最もよく適合するフォーマットを選択するために多数のフォーマットをテストしたい場合、特に便利です。
RETURN CODES
B_OK. 提案されたフォーマットはdestinationに受け入れられた。
|
指定されたdestinationに対してメディアデータのbufferを送るために、この関数を呼び出して下さい。destinationは、あなたの出力のうち一つとすでに接続されていなければなりません。これは、BBufferProducerオブジェクトが下流の接続ずみのBBufferConsumerにデータを送信する方法です。
SendBuffer()が自動的に下記のヘッダフィールドに書込んでくれますが、しかしあなたには、バッファのヘッダとバッファ自身に収められたデータが適正であることを保証する責任があります。
特に、ビデオバッファを出力している場合には必ず、ビデオを適切に記述するためにmedia_video_bufferを設定して下さい。
自分自身のBBufferConsumerにあるBBufferConsumer::RequestBuffer()を呼び出すことで、内容を埋め、送信するためのバッファを得ることができます(また、指定されたdestinationに向かうバッファを使用しても大丈夫です)。
RETURN CODES
B_OK. バッファはエラーなしに送られた。
|
producer nodeから産生される使用可能なデータがあるかどうかを指定されたdestinationに通知するには、この関数を呼び出して下さい。
statusに使用できる値は、下記の通りです :
Constant | Description |
---|---|
B_DATA_NOT_AVAILABLE | destinationに送る準備のできたバッファはない。 |
B_DATA_AVAILABLE | destinationに送る準備のできたバッファがある。 |
B_PRODUCER_STOPPED | producerは停止している。 |
RETURN CODES
B_OK. 状態の更新は、エラーなく送信された。
|
クライアントが与えられた出力forSourceに対して使用する特定のBBufferGroupが必要になったとき、クライアントはこの関数を呼び出します。groupを思い出し、バッファを出力forSourceに送るための全ての要求に対し、これを使用して下さい(他の出力sourceに対し、SetBufferGroup()呼び出しによってクライアントが明示的にそうするよう要求しなければ、他の出力には行いません)。
もしBBufferProducerが消えるか、あるいは接続が破綻したら、BBufferGroupオブジェクトを削除して下さい。
もしgroupがNULLであれば、それまでのgroupを破棄した後に、使用したいBBufferGroupをなんでも使用して下さい。
もしBBufferProducerが処理中のループで受け取ったバッファを手渡すだけであっても、BBufferProducerから他の上流のnodeにgroupを受け渡して大丈夫です。この場合、BMediaRoster::SetOutputBuffers()呼び出しにてwillReclaimにtrueを渡さないかぎり、あなたはBBufferGroupの実際の所有者ではありません。
もしバッファグループが問題なく設定されれば、B_OKを返して下さい。そうでなければ、適切なエラーコードを返して下さい。
|
もしバッファを構築するための信号によってnodeの起動時にlatencyを追加する必要が出てきた場合は、この遅れによって追加されうる最大のlatencyを特定するためにSetInitialLatency()を呼び出して下さい。initialLatencyはマイクロ秒単位であり、生じうる最大のlatencyです。
これが生じる一つの状況としては、TVキャプチャカードのnodeがあります。NTSCテレビ信号は、約16分の1秒に一回、新しいフィールドを送信します。これは、もしnodeが受け取っている一つのフィールドを部分的に処理し始めたら、最初の完全なフレームが到着するまでに16分の1秒の間待たなければならないということです。この状況における最大のlatencyは、16分の1秒となります。
初期のlatencyを正確に設定することで、あなたのnodeとconsumerとの同期に問題が発生するのを防ぐことができ、演奏を改善できます。
現在、flagsは0です。値はまだ全く定義されていません。
|
この関数は、指定された要因によってデータレートを再サンプリングするようproducerに命じるために呼び出されます。値に1を指定する(つまりnumerator/denominator = 1 とする)ことは、データがnodeにやって来たのと同じ再生レートで出力することを示します。データのフォーマットは変更されません。
例えば、あなたが48kHzで音声を再生しており、2 のnumeratorと 1 のdemoninator(2倍速)でSetPlayRate()呼び出しを受け取ったとすると、出力レートを一定に保ちつつsourceのデータを2倍の速度にするために再サンプリングして下さい。これは、強引に24kHzに再サンプリングするか(これはデータレートが2倍になります)、あるいは時間の短縮をすること(これは音程を保持します)で行います。
もう一つの例としては、もし毎秒30フレームでビデオを再生しており、SetPlayRate()が1:2(1/2倍速)の比を指定された上で呼び出されたとすると、毎秒30フレームで送信を続けながら、半分の速度に見えるように演奏をアレンジする必要があります。これを行う妥当な方法は、各々のフレームを(必要なら再度タイムスタンプを行い、内部的にバッファを生成して)2回送信することです。これは、見掛け上、求められた1/2倍速となります。
もしサンプリングレートが変更されたら、B_OKを返して下さい。そうでなければエラーを返して下さい。もしnodeがサンプリングレートの変更に対応していなければ、エラーを返しても構いません—Media Kitは、あなたに反抗してそれを保持したりはしません。
|
このフック関数は、クライアントがBBufferProducerに対して特定の領域にクリップされたビデオデータを出力させたい場合に呼び出されます。producerはこのクリッピング領域を記憶し、source forSourceを通して送られる任意のバッファの領域の外部には1バイトの変更も加えずに、それをproducerが産生する全てのビデオデータに適用しなければなりません。
あなたの実装したVideoClippingChanged()が戻る前に、outFromChangeTagによって指し示される値を、クリッピングが有効になる場所で変更タグの値に設定しなければなりません。クライアントはどんなバッファが要求されたクリッピングを持っていると予測できるか知ることになります。これは、下記の行をあなたのコードに追加するだけで簡単に実現できます。
*outFromChangeTag = UpdateChangeTag();
もしそれが作業するのにより良いフォーマットであれば、あなたは、実際のBRegionにclipDataのデータを変換して入れるために、ClipDataToRegion()関数を使うことができます。もしそうするなら、ClipDataToRegion()が配列のデータのbytesの数を要求するにも関わらず、numShortsがclipDataによって指定されるint16の値が実際の数であるということに留意して下さい。必ずsizeof(int16)でnumShortsの数を増やしておいて下さい。
ディスプレイによって参照されるmedia_video_display_info構造体は、ビデオが表示されているビデオディスプレイのフォーマットを示します。これはどんな色空間(color space)、スクリーンのサイズ等がビデオディスプレイで使用されていることを知らせてくれるため、producerは正しく描画できるのです。VideoClippingChanged()は、クリッピングが変更されたときだけでなく、ディスプレイの設定が変更されたときも同様に呼び出されます。producerは、指定された変更カウントにこれが開始されるまで、じっと我慢しなければなりません。
クリップデータのフォーマットに関する情報は、"Video Clipping"の85ページ目をご覧下さい。
こちらもご覧下さい: ClipDataToRegion(), BBufferConsumer::RegionToClipData()
Declared in: <be/media/BufferProducer.h>
Constant | Description |
---|---|
B_CLIP_SHORT_RUNS | クリッピングはshortのrunを使用してエンコードされている |
この値は現在BBufferProducerにサポートされているクリッピングフォーマットのみを定義しています。この定数はBBufferProducerクラスのメンバであることから、もし他のクラスからそれにアクセスする必要のある場合はBBufferProducer::B_CLIP_SHORT_RUNSのようにコードを書かなければなりません。このフォーマットに関しては"Video Clipping"の85ページ目をご覧下さい。
(訳注 : この部分はもとのテキストが壊れています。)
Declared in: be/media/BufferProducer.h
Constant | Meaning |
---|---|
B_ANY_QUALITY | 任意の品質 |
B_LOW_QUALITY | 低い品質レベル (10) |
B_MEDIUM_QUALITY | 中程度の品質レベル (50) |
B_HIGH_QUALITY | 高い品質レベル (100) |
使用できる品質(quality)の値は、あなたが自分でそれを用意したくない時に使用できます。
The Media Kit Table of Contents | The Media Kit Index |
Copyright © 2000 Be, Inc. All rights reserved..