densen2014 / ZXingBlazor

Using ZXing Scan barcode/QR code in blazor
Apache License 2.0
102 stars 41 forks source link

Possible memory leak? #32

Closed horrorhound closed 10 months ago

horrorhound commented 11 months ago

Using ZXingBlazor (All versions I've tried) in a Blazor Server application; after every scan the Visual Studio Output console shows an additional "Trying to play video that is already playing." after every scan. About every 3-4 scans the memory usage increases by around 1mb.

Example of output after about 10 scans.

i {text: '00020051135962EO935R', rawBytes: Uint8Array(19), numBits: 152, resultPoints: Array(3), format: 11, …}
autostop
Started decodeOnce decode from camera with id 644de2807523e8eae3603f8c916ba3f6322f17c7cf76e44e2d3dc47e1584fca7
0acf76c7-437e-466b-a15c-c689026b896d start
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.

Simple Code Example.

@page "/BoxOffice/ScannerTest"
@using ZXingBlazor

@* TOP BOX *@
@* ******* *@
<div class="d-flex flex-grow-1 gap-0 mb-8">
  <MudPaper Class="py-4" Elevation="0">
    <MudText Typo="Typo.h6" Class="ml-2">ZXing Scanner Test</MudText>
  </MudPaper>
  <MudPaper Class="flex-grow-1 py-4" Elevation="0" />
  <MudPaper Class="pa-4" Elevation="0">
    <MudButtonGroup Color="Color.Primary" Variant="Variant.Outlined">
      <MudToggleIconButton Icon="@Icons.Material.Filled.ScreenSearchDesktop" Color="@Color.Success"
                           ToggledIcon="@Icons.Material.Filled.ScreenSearchDesktop" ToggledColor="@Color.Error"
                           Toggled="@_toggleContinuousScan" ToggledChanged="ToggleContinuousScan" />
      <MudToggleIconButton Icon="@Icons.Material.Filled.PlayArrow" Color="@Color.Success"
                           ToggledIcon="@Icons.Material.Filled.Stop" ToggledColor="@Color.Error"
                           Toggled="@_toggleScanner" ToggledChanged="ToggleStartStop" />
      <MudIconButton Icon="@Icons.Material.Filled.Refresh" aria-label="Refresh" OnClick="@(async () => await OnRefresh())"></MudIconButton>
    </MudButtonGroup>
  </MudPaper>
</div>
@* ******* *@

      <BarcodeReader @ref="_scanner"
                     ScanResult="OnBarcodeScan"
                     Close="(()=>_toggleScanner=!_toggleScanner)"
                     ScanBtnTitle="Scan"
                     ResetBtnTitle="Reset"
                     CloseBtnTitle="Close"
                     Pdf417Only="Pdf417"
                     Decodeonce="_toggleContinuousScan"
                     DecodeAllFormats="_toggleDecodeAllFormats"
                     UseBuiltinDiv="false"
                     Options="_zxingOptions"
                     SaveDeviceID="true"
                     SelectDeviceBtnTitle="Select Device" />

      <div @ref="_scanner.Element">
        <div style="max-width: 100%">
          <button class="btn btn-outline-success p-2 m-1 w-25" data-action="startButton">Scan</button>
          <button class="btn btn-outline-success p-2 m-1 w-25" data-action="resetButton">Reset</button>
          <button type="button" class="btn btn-outline-success p-2 m-1 w-25" data-action="closeButton">Close</button>

          <div data-action="sourceSelectPanel" style="display:none">
            <label for="sourceSelect">SelectDevice:</label><span class="text-dark" data-action="result"></span>
            <select data-action="sourceSelect" style="max-width:100%" class="form-control">
            </select>
          </div>
          <div style="display: flex; justify-content: center; position: relative;">
            @*<video disabled="@_toggleScanner" id="video" playsinline autoplay></video>*@
            <video id="video" playsinline autoplay></video>
            @*<div class="reticle"></div>*@
            <div style="position: absolute; top: 20%; left: 40%; width: 2px; height: 20px; background-color: red; transform: skewX(-45deg);"></div>
            <div style="position: absolute; top: 20%; right: 40%; width: 2px; height: 20px; background-color: red; transform: skewX(45deg);"></div>
            <div style="position: absolute; bottom: 20%; right: 40%; width: 2px; height: 20px; background-color: red; transform: skewX(-45deg);"></div>
            <div style="position: absolute; bottom: 20%; left: 40%; width: 2px; height: 20px; background-color: red; transform: skewX(45deg);"></div>
          </div>
        </div>
      </div>

<MudText Typo="Typo.caption">@_statusMessage</MudText>

@code {

  // Page data variables
  // *******************
  private BarcodeReader _scanner;
  private bool _toggleScanner = false;
  private bool _toggleContinuousScan { get; set; } = false;
  private bool Pdf417 { get; set; }
  private bool _toggleDecodeAllFormats { get; set; } = false;
  private ZXingOptions _zxingOptions;

  private String _statusMessage = String.Empty;
  private String _barcode = String.Empty;

  protected override async Task OnInitializedAsync()
  {
    // Initialize ZXingOptions with your desired settings
    _zxingOptions = new ZXingOptions
      {
        formats = new List<BarcodeFormat> { BarcodeFormat.QR_CODE }, // Specify the barcode format you want to scan
        TimeBetweenDecodingAttempts = 5000 // Delay time between decode attempts made by the scanner.  - In milli seconds.
      };
  }

  protected async override Task OnAfterRenderAsync(bool firstRender)
  {

  }

  private void ToggleContinuousScan(bool toggled)
  {
    _toggleContinuousScan = toggled;

    if (_toggleContinuousScan)
    {
      _toggleContinuousScan = true;
    }
    else
    {
      _toggleContinuousScan = false;
    }
  }

  private void ToggleStartStop(bool toggled)
  {
    if (_scanner != null)
    {
      _toggleScanner = toggled;

      if (_toggleScanner)
      {
        _scanner.Start();
      }
      else
      {
        _scanner.Stop();
      }
    }
  }

  private async Task OnRefresh()
  {
    if (_scanner != null)
      await _scanner.Reload();
    else
      ToggleStartStop(true);
  }

  private async void OnBarcodeScan(string e)
  {

    try
    {
      _barcode = e;
      _statusMessage = $"{_barcode}"; // retain the last status message.

      await _scanner.Start();
      _toggleScanner = true;
      //await InvokeAsync(StateHasChanged);
      StateHasChanged();
    }
    catch (Exception ex)
    {
      _statusMessage = ex.Message;
    }
    finally
    {
    }
  }
}
densen2014 commented 11 months ago

Which version is it? Can you go back to the first two versions and give it a try?

horrorhound commented 11 months ago

Originally noticed in v1.0.3 and also still present in 1.0.6. Below You see I've tested earlier versions also.

Sample code for these test... New BlazorServer app and then updated the Index.razor page with the following code:

@page "/"

@using ZXingBlazor

<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

<ZXingBlazor.Components.BarcodeReader ScanResult="ScanResult"></ZXingBlazor.Components.BarcodeReader>

@code{

    /// <summary>
    /// BarCode
    /// </summary>
    public string? BarCode { get; set; }

    private void ScanResult(string e)
    {
        BarCode = e;
    }
}

With Version 0.27 (Note the additional "Trying to play video that is already playing." lines on each start of the camera after each scan)

ZXing code reader initialized
videoInputDevices:2
Started decodeOnce decode from camera with id c0c704f8c376d13341c888e5164b57011289ba196a0f59b7814c044139b26a84
Started decodeOnce decode from camera with id c0c704f8c376d13341c888e5164b57011289ba196a0f59b7814c044139b26a84
Trying to play video that is already playing.
Trying to play video that is already playing.
Started decodeOnce decode from camera with id c0c704f8c376d13341c888e5164b57011289ba196a0f59b7814c044139b26a84
Started decodeOnce decode from camera with id 305602e1870d552dece46ca009ea13697a6d5b93952c01bed33f321a46b72cfe
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
F {text: '00020051135962EO935R', rawBytes: Uint8Array(19), numBits: 152, resultPoints: Array(3), format: 11, …}
autostop
Started decodeOnce decode from camera with id 305602e1870d552dece46ca009ea13697a6d5b93952c01bed33f321a46b72cfe
The thread 0x10da4 has exited with code 0 (0x0).
The thread 0x10e28 has exited with code 0 (0x0).
The thread 0x10dcc has exited with code 0 (0x0).
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
The thread 0x10d38 has exited with code 0 (0x0).
The thread 0x81ec has exited with code 0 (0x0).
F {text: '00020051135962EO935R', rawBytes: Uint8Array(19), numBits: 152, resultPoints: Array(3), format: 11, …}
autostop
Started decodeOnce decode from camera with id 305602e1870d552dece46ca009ea13697a6d5b93952c01bed33f321a46b72cfe
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
F {text: '00020051135962EO935R', rawBytes: Uint8Array(19), numBits: 152, resultPoints: Array(3), format: 11, …}
autostop
Started decodeOnce decode from camera with id 305602e1870d552dece46ca009ea13697a6d5b93952c01bed33f321a46b72cfe
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
The thread 0x10e0c has exited with code 0 (0x0).
Started decodeOnce decode from camera with id 305602e1870d552dece46ca009ea13697a6d5b93952c01bed33f321a46b72cfe
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
F {text: '00020051135962EO935R', rawBytes: Uint8Array(19), numBits: 152, resultPoints: Array(3), format: 11, …}
autostop
Started decodeOnce decode from camera with id 305602e1870d552dece46ca009ea13697a6d5b93952c01bed33f321a46b72cfe
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.

With Version 2.0

Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
i {text: '00020051135962EO935R', rawBytes: Uint8Array(19), numBits: 152, resultPoints: Array(3), format: 11, …}
None-stop
Started continous decode from camera with id 305602e1870d552dece46ca009ea13697a6d5b93952c01bed33f321a46b72cfe
The thread 0x1e78 has exited with code 0 (0x0).
The thread 0xd09c has exited with code 0 (0x0).
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
i {text: '00020051135962EO935R', rawBytes: Uint8Array(19), numBits: 152, resultPoints: Array(3), format: 11, …}
None-stop
Started continous decode from camera with id 305602e1870d552dece46ca009ea13697a6d5b93952c01bed33f321a46b72cfe
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
i {text: '00020051135962EO935R', rawBytes: Uint8Array(19), numBits: 152, resultPoints: Array(3), format: 11, …}
None-stop
Started continous decode from camera with id 305602e1870d552dece46ca009ea13697a6d5b93952c01bed33f321a46b72cfe
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
i {text: '00020051135962EO935R', rawBytes: Uint8Array(19), numBits: 152, resultPoints: Array(3), format: 11, …}
None-stop
The thread 0xeb2c has exited with code 0 (0x0).
The thread 0xe53c has exited with code 0 (0x0).
Started continous decode from camera with id 305602e1870d552dece46ca009ea13697a6d5b93952c01bed33f321a46b72cfe
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.
Trying to play video that is already playing.

Anything before v.02 I couldn't get to work and didn't spend anytime trying to fix the code.

densen2014 commented 11 months ago

Which version are using? we have not ver2.0 totaly. maybe you can follow this link, because all new version is in nuget.org

https://www.nuget.org/packages/ZXingBlazor#versions-body-tab

image

horrorhound commented 11 months ago

Sorry, when I wrote v2 I meant 0.2. I couldn't get any of the v0.1 versions to work which doesn't matter. But all versions of v0.2 and above I see the issue with.

densen2014 commented 11 months ago

ok i see, Trying to play video that is already playing you want to hide it right?

because in ios , first render we can not list all cameras, so we do something hack and work for that, so zxing.js show this error

densen2014 commented 11 months ago

Fixed! try ZXingBlazor 1.0.8

horrorhound commented 11 months ago

This version seems much better thanks. I'm going to continue testing.

EmilAlipiev commented 10 months ago

One quick question here. Is this library threadsafe using on Blazor server? I read on other library on blazor server if multiple devices read qr code, it is displayed on all other devices.

horrorhound commented 10 months ago

So far yes, I've been testing with 2 different devices.

I do see slowness in trying to scan the QR Codes at times; if it's this library, the underlying ZXing library or if my QR codes need to be generated "better".

densen2014 commented 10 months ago

can you please test the last veision?

horrorhound commented 10 months ago

Yes, I'll be working on my app this weekend and will respond with any issues.