カスタム動画のレンダリング(iOS)
概要
このチュートリアルでは、OTPublisher オブジェクトで使用されるビデオレンダラーに軽微な変更を加える手順について解説します。同様の手法を用いて、OTSubscriber オブジェクトで使用されるビデオレンダラーを変更することも可能です(ただし、この例ではパブリッシャー用のカスタムレンダラーについてのみ説明しています)。
プロジェクトの設定
このセクションのコードは 基本的なビデオ・レンダラー のプロジェクトである。 opentok-ios-sdk-samples リポジトリもしまだなら、レポをローカル・ディレクトリにクローンする必要がある。 これはコマンドラインを使って実行できる:
git clone https://github.com/opentok/opentok-ios-sdk-samples.git
ディレクトリをBasic Video Rendererプロジェクトに変更します:
cd opentok-ios-sdk-samples/Basic-Video-Renderer
次に、OpenTokの依存関係をインストールします:
pod install
Xcodeでプロジェクトを開き、その通りに進めてください。
コードを詳しく見ていく
この例では、アプリはカスタムビデオレンダラを使用して、OTPublisherオブジェクトのビデオの白黒バージョンを表示しています。
メインのViewControllerでは、OTPublisherオブジェクトを初期化した後に videoRender プロパティは、OTKBasicVideoRenderのインスタンスに設定されます:
_publisher = [[OTPublisher alloc] initWithDelegate:self settings:settings];
_renderer = [[OTKBasicVideoRender alloc] init];
_publisher.videoRender = _renderer;
OTKBasicVideoRender は、OTVideoRender プロトコル(OpenTok iOS SDK で定義されている)を実装するカスタムクラスです。このプロトコルを使用すると、OpenTok のパブリッシャーまたはサブスクライバーが使用するカスタムビデオレンダラーを定義することができます。
について [OTKBasicVideoRender init:] メソッドは _renderView プロパティを UIView オブジェクトに追加します。これは、(パブリッシャーまたはサブスクライバーによって)レンダリングされるビューを含む UIView オブジェクトです。このサンプルでは、UIView オブジェクトは UIView を継承した OTKCustomRenderView クラスで定義されています:
- (id)init
{
self = [super init];
if (self) {
_renderView = [[OTKCustomRenderView alloc] initWithFrame:CGRectZero];
}
return self;
}
OTKCustomRenderViewクラスには、ビデオフレームを白黒表現に変換するメソッド(後述)があります。
[OTVideoRender renderVideoFrame:] メソッドは、パブリッシャー(またはサブスクライバー)がビデオフレームをビデオレンダラーにレンダリングする際に呼び出されます。このフレームは OTVideoFrame オブジェクト(OpenTok iOS SDK で定義)です。 OTKCustomRenderView におけるこのメソッドの実装では、単にフレームを受け取り、それを [renderVideoFrame] メソッドを呼び出します:
- (void)renderVideoFrame:(OTVideoFrame*) frame
{
[(OTKCustomRenderView*)self.renderView renderVideoFrame:frame];
}
について [OTKCustomRenderView renderVideoFrame] メソッドは、プレーン内のピクセルを繰り返し処理し、各ピクセルを白黒の値に調整し、その値をバッファに追加します。そして、バッファをビューの画像を表すCGImageRefに書き出し、次のように呼び出します。 [self setNeedsDisplay] で画像ビューをレンダリングする:
- (void)renderVideoFrame:(OTVideoFrame *)frame
{
__block OTVideoFrame *frameToRender = frame;
dispatch_sync(self.renderQueue, ^{
if (_img != NULL) {
CGImageRelease(_img);
_img = NULL;
}
size_t bufferSize = frameToRender.format.imageHeight
* frameToRender.format.imageWidth * 3;
uint8_t *buffer = malloc(bufferSize);
uint8_t *yplane = [frameToRender.planes pointerAtIndex:0];
for (int i = 0; i < frameToRender.format.imageHeight; i++) {
for (int j = 0; j < frameToRender.format.imageWidth; j++) {
int starting = (i * frameToRender.format.imageWidth * 3) + (j * 3);
uint8_t yvalue = yplane[(i * frameToRender.format.imageWidth) + j];
// If in a RGB image we copy the same Y value for R, G and B
// we will obtain a Black & White image
buffer[starting] = yvalue;
buffer[starting+1] = yvalue;
buffer[starting+2] = yvalue;
}
}
CGDataProviderRef imgProvider = CGDataProviderCreateWithData(NULL,
buffer,
bufferSize,
release_frame);
_img = CGImageCreate(frameToRender.format.imageWidth,
frameToRender.format.imageHeight,
8,
24,
3 * frameToRender.format.imageWidth,
CGColorSpaceCreateDeviceRGB(),
kCGBitmapByteOrder32Big | kCGImageAlphaNone,
imgProvider,
NULL,
false,
kCGRenderingIntentDefault);
CGDataProviderRelease(imgProvider);
dispatch_async(dispatch_get_main_queue(), ^{
[self setNeedsDisplay];
});
});
}
おめでとうございます!iOS向け「カスタム動画レンダリング」チュートリアルを完了しました。
ここで作成したコードをさらに試したり調整したりすることもできますし、あるいは 次のステップ の下にある。
次のステップ
ここでの作業が終わったら、以下の役立つリソースを活用して、OpenTokアプリケーションの構築と機能強化を続けてください: