Status FBIDBServiceHandler::video_stream()

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;
}}