public override void RenderOutput(WebCamScreenController screenController, PixelData pixelData) {
    var texture = screenController.GetScreen();

    if (!outputStreamPoller.Next(outputPacket)) {
      Debug.LogWarning("Failed to fetch an output packet, rendering the input image");
      texture.SetPixels32(pixelData.Colors);
      texture.Apply();
      return;
    }

    ImageFrame outputFrame = null;

    var status = gpuHelper.RunInGlContext(() => {
      var gpuFrame = outputPacket.GetValue();
      var gpuFrameFormat = gpuFrame.Format();
      var sourceTexture = gpuHelper.CreateSourceTexture(gpuFrame);

      outputFrame = new ImageFrame(
        gpuFrameFormat.ImageFormatFor(), gpuFrame.Width(), gpuFrame.Height(), ImageFrame.kGlDefaultAlignmentBoundary);

      gpuHelper.BindFramebuffer(sourceTexture);
      var info = gpuFrameFormat.GlTextureInfoFor(0);

      GL.ReadPixels(0, 0, sourceTexture.Width(), sourceTexture.Height(), info.glFormat, info.glType, outputFrame.PixelDataPtr());
      GL.Flush();

      sourceTexture.Release();

      return Status.Ok(false);
    });

    if (status.IsOk()) {
      texture.SetPixels32(outputFrame.GetColor32s());
    } else {
      Debug.LogError(status.ToString());
      texture.SetPixels32(pixelData.Colors);
    }

    texture.Apply();
  }
    private ImageFrame FetchNextHairMask()
    {
        if (!hairMaskStreamPoller.Next(hairMaskPacket))
        {
            Debug.LogWarning($"Failed to fetch next packet from {hairMaskStream}");
            return(null);
        }

        ImageFrame outputFrame = null;

        var status = gpuHelper.RunInGlContext(() => {
            var gpuFrame       = hairMaskPacket.GetValue();
            var gpuFrameFormat = gpuFrame.Format();
            var sourceTexture  = gpuHelper.CreateSourceTexture(gpuFrame);

            outputFrame = new ImageFrame(
                gpuFrameFormat.ImageFormatFor(), gpuFrame.Width(), gpuFrame.Height(), ImageFrame.kGlDefaultAlignmentBoundary);

            gpuHelper.BindFramebuffer(sourceTexture);
            var info = gpuFrameFormat.GlTextureInfoFor(0);

            GL.ReadPixels(0, 0, sourceTexture.Width(), sourceTexture.Height(), info.glFormat, info.glType, outputFrame.PixelDataPtr());
            GL.Flush();

            sourceTexture.Release();

            return(Status.Ok(false));
        });

        if (!status.IsOk())
        {
            Debug.LogError(status.ToString());
        }

        return(outputFrame);
    }