...
To analyze the code, let's take TwoWayStreaming example version with hash 62b3aca, which can be downloaded with corresponding build 2.5.2.0.
View class for the main view of the application: ViewController (header file ViewController.h; implementation file ViewController.m).
1. Import of API. ViewController.m, line 11 code
Code Block | ||||
---|---|---|---|---|
| ||||
#import <FPWCSApi2/FPWCSApi2.h> |
2. Connection Session creation and connection to server.
ViewController method connect is called when Connect button is tapped. ViewController.m, line 253
Code Block | ||||
---|---|---|---|---|
| ||||
[self connect]; |
In the method,
- object with options for connection session is created (ViewController.m, line 29)
...
language | js |
---|---|
theme | RDark |
The options include FPWCSApi2 createSession, FPWCSApi2Session connect code
The options include:
- URL of WCS server
...
- appKey of internal server-side application
...
- (defaultApp)
Code Block | ||||
---|---|---|---|---|
| ||||
- (FPWCSApi2Session *)connect { FPWCSApi2SessionOptions *options = [[FPWCSApi2SessionOptions alloc] init]; options.urlServer = _connectUrl.text; options.appKey = @"defaultApp"; |
- callback functions for processing session statuses are added (ViewController.m, line 52)
Code Block | ||||
---|---|---|---|---|
| ||||
[session on:kFPWCSSessionStatusEstablished callback:^(FPWCSApi2Session *rSession){ [self changeConnectionStatus:[rSession getStatus]]NSError *error; [self onConnected:rSession]; }]; [session on:kFPWCSSessionStatusDisconnected callback:^(FPWCSApi2Session *rSession){ session = [selfFPWCSApi2 changeConnectionStatuscreateSession:[rSession getStatus]]options error:&error]; [self onDisconnected]; }]; [session on:kFPWCSSessionStatusFailed callback:^(FPWCSApi2Session *rSession){ [self changeConnectionStatus:[rSession getStatus]]... [session connect]; [selfreturn onDisconnected]session; }]; |
Depending on the session status, corresponding ViewController methods will be called to make appropriate changes in controls of the interface
- if connection is successfully established: onConnected
- in case of disconnection, or connection failure: onDisconnected
- FPWCSApi2Session method connect is called to establish connection to server (ViewController.m, line 66)
Code Block | ||||
---|---|---|---|---|
| ||||
[session connect]; |
3. Stream publishing.
When connection to the server is established, stream publication can be started by tapping Publish button.
ViewController method publishStream is called when the button is tapped. ViewController.m, line 282
Code Block | ||||
---|---|---|---|---|
| ||||
[self publishStream]; |
In the method,
- object with stream publish options is created (ViewController.m, line 72)
Code Block | ||||
---|---|---|---|---|
| ||||
3. Stream publishing.
FPWCSApi2Session createStream, FPWCSApi2Stream publish code
Object with next stream options is passed to createStream method:
- stream name
- view to display video
- 'true' for parameter 'record' to enable stream recording
- video constraints for iPad
Code Block | ||||
---|---|---|---|---|
| ||||
- (FPWCSApi2Stream *)publishStream { FPWCSApi2Session *session = [FPWCSApi2 getSessions][0]; FPWCSApi2StreamOptions *options = [[FPWCSApi2StreamOptions alloc] init]; options.name = _localStreamName.text; options.display = _localDisplay; |
The required options are stream name and view for displaying video.
Also, video constraints can be specified. E.g., in the example, video constraints are added in case the iOS device is iPad:
Code Block | ||||
---|---|---|---|---|
| ||||
if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) { options.constraints = [[FPWCSApi2MediaConstraints alloc] initWithAudio:YES videoWidth:640 videoHeight:480 videoFps:15]; } |
- new stream is created with FPWCSApi2Session method createStream (ViewController.m, line 79)
Code Block | ||||
---|---|---|---|---|
| ||||
}
NSError *error;
FPWCSApi2Stream *stream = [session createStream:options error:&error]; |
- callback functions for processing stream statuses are added (ViewController.m, line 97)
Code Block | ||||
---|---|---|---|---|
| ||||
[stream on:kFPWCSStreamStatusPublishing callback:^(FPWCSApi2Stream *rStream){ [self changeStreamStatus:rStream]; [self onPublishing:rStream]; }]; [stream on:kFPWCSStreamStatusUnpublished callback:^(FPWCSApi2Stream *rStream){ [self changeStreamStatus:rStream]; ... if(![stream publish:&error]) { UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"Failed to publish" message:error.localizedDescription preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction* okButton = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { [self onUnpublished]; }]; [stream on:kFPWCSStreamStatusFailed callback:^(FPWCSApi2Stream *rStream){ [selfalert changeStreamStatusaddAction:rStreamokButton]; [self onUnpublished presentViewController:alert animated:YES completion:nil]; }]; |
Depending on the stream status, corresponding ViewController methods will be called to make appropriate changes in controls of the interface
- if stream is successfully published: onPublishing
- in case of failure, or when stream is unpublished: onUnpublished
...
}
return stream;
} |
4. Switching camera while publishing stream
FPWCSApi2Stream switchCamera code
Code Block | ||||
---|---|---|---|---|
| ||||
[stream publish:&error] |
...
FPWCSApi2Stream method stop is called to stop streaming when Unpublish button is tapped.
Code Block | ||||
---|---|---|---|---|
| ||||
[stream stop:&error];- (void)switchCameraButton:(UIButton *)button { if ([FPWCSApi2 getSessions].count) { FPWCSApi2Session *session = [FPWCSApi2 getSessions][0]; NSArray *streams = [session getStreams]; for (FPWCSApi2Stream *stream in streams ) { if ([stream isPublished]) { NSLog(@"Found published stream, switching camera"); [stream switchCamera]; } } } else { NSLog(@"No active sessions found"); } } |
5. Stream playback.When connection to the server is established, playback of a stream can be started by tapping Play button.
ViewController method playStream is called when the button is tapped. ViewController.m, line 315
FPWCSApi2Session createStream, FPWCSApi2Stream play code
Object with next stream options is passed to createStream method:
- stream name
- view to display video
Code Block | ||||
---|---|---|---|---|
| ||||
[self playStream]; |
In the method,
- object with stream playback options is created (ViewController.m, line 132)
Code Block | ||||
---|---|---|---|---|
| ||||
- (FPWCSApi2Stream *)playStream { FPWCSApi2Session *session = [FPWCSApi2 getSessions][0]; FPWCSApi2StreamOptions *options = [[FPWCSApi2StreamOptions alloc] init]; options.name = _remoteStreamName.text; options.display = _remoteDisplay; |
The options include stream name and view for displaying video.
- new stream is created with FPWCSApi2Session method createStream (ViewController.m, line 136)
Code Block | ||||
---|---|---|---|---|
| ||||
NSError *error; FPWCSApi2Stream *stream = [session createStream:options error:nil]; ... if(![stream play:&error]) { UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"Failed to play" message:error.localizedDescription preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction* okButton = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { }]; [alert addAction:okButton]; [self presentViewController:alert animated:YES completion:nil]; |
...
}
return stream;
} |
6. Stop of stream playback.
FPWCSApi2Stream stop code
Code Block | ||||
---|---|---|---|---|
| ||||
[stream on:kFPWCSStreamStatusPlaying callback:^(FPWCSApi2Stream *rStream)- (void)playButton:(UIButton *)button { [self changeViewState:button changeStreamStatusenabled:rStreamNO]; [self onPlaying:rStream]; }]; [stream on:kFPWCSStreamStatusStopped callback:^(FPWCSApi2Stream *rStream){ [self changeStreamStatus:rStream]; [self onStopped]; }]; [stream on:kFPWCSStreamStatusFailed callback:^(FPWCSApi2Stream *rStream){ [self changeStreamStatus:rStream]; if ([button.titleLabel.text isEqualToString:@"STOP"]) { if ([FPWCSApi2 getSessions].count) { FPWCSApi2Stream *stream; for (FPWCSApi2Stream *s in [[FPWCSApi2 getSessions][0] getStreams]) { if ([[s getName] isEqualToString:_remoteStreamName.text]) { stream = s; break; } } if (!stream) { NSLog(@"Stop playing, nothing to stop"); [self onStopped]; return; } NSError *error; [stream stop:&error]; } else { NSLog(@"Stop playing, no session"); [self onStopped]; }]; |
Depending on the stream status, corresponding ViewController methods will be called to make appropriate changes in controls of the interface
- if playback is successfully started: onPlaying
- in case of failure, or when playback is stopped: onStopped
...
}
...
}
} |
7. Stop of stream publishing.
FPWCSApi2Stream stop code
Code Block | ||||
---|---|---|---|---|
| ||||
[stream play:&error] |
6. Stop of stream playback. ViewController.m, line 307
FPWCSApi2Stream method stop is called to stop stream playback when Stop button is tapped.
Code Block | ||||
---|---|---|---|---|
| ||||
[stream stop:&error]; |
7. Disconnection. ViewController.m, line 245
FPWCSApi2Session method disconnect is called to close connection to the server.
Code Block | ||||
---|---|---|---|---|
| ||||
[session disconnect];- (void)publishButton:(UIButton *)button { [self changeViewState:button enabled:NO]; if ([button.titleLabel.text isEqualToString:@"STOP"]) { if ([FPWCSApi2 getSessions].count) { FPWCSApi2Stream *stream; for (FPWCSApi2Stream *s in [[FPWCSApi2 getSessions][0] getStreams]) { if ([[s getName] isEqualToString:_localStreamName.text]) { stream = s; break; } } if (!stream) { NSLog(@"Stop publishing, nothing to stop"); [self onUnpublished]; return; } NSError *error; [stream stop:&error]; } else { NSLog(@"Stop publishing, no session"); [self onUnpublished]; } ... } } |
8. Disconnection.
FPWCSApi2Session disconnect code
Code Block | ||||
---|---|---|---|---|
| ||||
- (void)connectButton:(UIButton *)button {
[self changeViewState:button enabled:NO];
if ([button.titleLabel.text isEqualToString:@"DISCONNECT"]) {
if ([FPWCSApi2 getSessions].count) {
FPWCSApi2Session *session = [FPWCSApi2 getSessions][0];
NSLog(@"Disconnect session with server %@", [session getServerUrl]);
[session disconnect];
} else {
NSLog(@"Nothing to disconnect");
[self onDisconnected];
}
...
}
} |