in idb_companion/Server/FBIDBServiceHandler.mm [1257:1311]
Status FBIDBServiceHandler::video_stream(ServerContext* context, grpc::ServerReaderWriter<idb::VideoStreamResponse, idb::VideoStreamRequest>* stream)
{@autoreleasepool{
NSError *error = nil;
idb::VideoStreamRequest request;
FBMutableFuture<NSNull *> *done = FBMutableFuture.future;
id<FBDataConsumer> consumer = consumer_from_request(stream, request, done, &error);
if (!consumer) {
return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String);
}
idb::VideoStreamRequest_Start start = request.start();
NSNumber *framesPerSecond = start.fps() > 0 ? @(start.fps()) : nil;
FBVideoStreamEncoding encoding = @"";
switch (start.format()) {
case idb::VideoStreamRequest_Format_RBGA:
encoding = FBVideoStreamEncodingBGRA;
break;
case idb::VideoStreamRequest_Format_H264:
encoding = FBVideoStreamEncodingH264;
break;
case idb::VideoStreamRequest_Format_MJPEG:
encoding = FBVideoStreamEncodingMJPEG;
break;
case idb::VideoStreamRequest_Format_MINICAP:
encoding = FBVideoStreamEncodingMinicap;
break;
default:
return Status(grpc::StatusCode::INTERNAL, "Invalid Video format provided");
}
NSNumber *compressionQuality = @(start.compression_quality());
NSNumber *scaleFactor = @(start.scale_factor());
NSNumber *avgBitrate = start.avg_bitrate() > 0 ? @(start.avg_bitrate()) : nil;
FBVideoStreamConfiguration *configuration = [[FBVideoStreamConfiguration alloc] initWithEncoding:encoding framesPerSecond:framesPerSecond compressionQuality:compressionQuality scaleFactor:scaleFactor avgBitrate:avgBitrate];
id<FBVideoStream> videoStream = [[_target createStreamWithConfiguration:configuration] block:&error];
if (!stream) {
return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String);
}
BOOL success = [[videoStream startStreaming:consumer] block:&error] != nil;
if (success == NO) {
return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String);
}
// Wait for the client to hangup or stream to stop
FBFuture<NSNull *> *clientStopped = resolve_next_read(stream);
[[FBFuture race:@[clientStopped, videoStream.completed]] block:nil];
// Signal that we're done so we don't write to a dangling pointer.
[done resolveWithResult:NSNull.null];
// Stop the streaming for real. It may have stopped already in which case this returns instantly.
success = [[videoStream stopStreaming] block:&error] != nil;
[_target.logger logFormat:@"The video stream is terminated"];
if (success == NO) {
return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String);
}
return Status::OK;
}}