3

AVSampleBufferDisplayLayer を使用して、h.264 形式でネットワーク接続を介して送信される CMSampleBuffers を表示しています。ビデオの再生はスムーズで正しく機能していますが、フレーム レートを制御できないようです。具体的には、AVSampleBufferDisplayLayer で毎秒 60 フレームをキューに入れると、ビデオが 30 FPS で記録されていても、60 フレームが表示されます。

サンプル バッファーを作成する場合、タイミング情報の配列を CMSampleBufferCreate に渡すことで、プレゼンテーションのタイム スタンプを設定できます (タイミング情報は h.264 ストリームには存在しませんが、コンテナー形式で計算または渡すことができます)。設定したプレゼンテーション タイム スタンプは約 0.033 秒間隔で、持続時間は 0.033 ですが、ディスプレイ レイヤーは 1 秒あたりのフレーム数を可能な限り表示します。

AVSampleBufferDisplayLayer でバッファーをキューに入れる方法は 2 つあります。バッファーの準備ができたら常に -[AVSampleBufferDisplayLayer enqueueSampleBuffer:] を呼び出して「制約」するか、-[AVSampleBufferDisplayLayer requestMediaDataWhenReadyOnQueue:usingBlock:] を呼び出してそのブロックのバッファーをキューに入れることで「制約なし」です。私は両方を試しましたが、2 番目の方法でもできるだけ早くバッファを表示します。バッファーはキューに入れられ、すべてが非常に短い時間で表示されます。

この動作は、kCMSampleAttachmentKey_DisplayImmediately 添付ファイルが CMSampleBuffer に設定されている場合に予想されるものと似ていますが、これは現在設定されていません (デフォルトは false です)。

レイヤーのcontrolTimeBaseを設定してみましたが、効果がないようでした。他に試してみるべきことがなく、オンラインで例を見つけることができませんでした。AVSampleBufferDisplayLayer がフレームを表示するフレームレートを制御する方法を知っている人はいますか?

4

3 に答える 3

2

タイムベースは、デコードする最初のフレームのプレゼンテーション タイム スタンプ (pts) に設定する必要があります。後続のすべてのポイントから最初のポイントを減算し、タイムベースを 0 に設定することで、最初のフレームのポイントを 0 にインデックス付けしていました。何らかの理由で、それは機能しませんでした。

次のようなものが必要です ( decode の呼び出しの前に呼び出されます):

CMTimebaseRef controlTimebase;
CMTimebaseCreateWithMasterClock( CFAllocatorGetDefault(), CMClockGetHostTimeClock(), &controlTimebase );

displayLayer.controlTimebase = controlTimebase;

// Set the timebase to the initial pts here
CMTimebaseSetTime(displayLayer.controlTimebase, CMTimeMake(ptsInitial, 1));
CMTimebaseSetRate(displayLayer.controlTimebase, 1.0);

CMSampleBuffer の PTS を設定します...

CMSampleBufferSetOutputPresentationTimeStamp(sampleBuffer, presentationTimeStamp);

そしておそらく、表示がすぐに設定されていないことを確認してください....

CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanFalse);

これは、WWDC 2014 セッション 513 で非常に簡単に説明されています。

于 2016-01-14T22:01:45.567 に答える