VideoHelp Forum
+ Reply to Thread
Results 1 to 18 of 18
Thread
  1. Member vhelp's Avatar
    Join Date
    Mar 2001
    Location
    New York
    Search Comp PM
    [RESOLVED] -- memory leak now fixed

    Good day everyone

    I need Help because this is driving me nuts and don't know whereelse to turn. Not sure if anyone knows, being that this is a programing related question to AVIsynth and plugin development and i've never seen any plugin developers on this board so i'm doubtful that i'll get any response but i have to at least try.

    I am doing work on a filter that I coded in delphi some years ago. It was part of a GUI I made for image processing. Now, I would like to port it into an avisynth plugin to take advantage of its unlimited potentials. Breaking the bridge between C and Delphi has not been an easy task for me let alone the avisynth and _C parts, all of which are complicated areas to overcome. So i'm making small steps, finally.

    1. While working on one of my plugins I noticed that i run out of ram/system resources. There seems to be a leak somewhere source code and I just can't seem to find it.

    2. Also, while using the plugin and writing out a new avi file inside virtualdub, avisynth crashes out with a "GDI or Insuficient memory" error message and the timeline window looses connection to avisynth. It usually happens betwee 700 and 900 frames have been read.

    The above two are abviously related.

    So, my question is, is there a common aspect about avisynth that usually causes these leaks or crashes?

    However, when I close down virtualdub, all memory and resources are restored, but that's the least of my problem It must be something I changed in the code because i had to use a technique to obtain the frames data through copying pointer references, but i'm not sure. AVIsynth and _C are difficult to understand let alone program in another language. Thank you for any leads.

    I'll try to elaborate with more details if needed, thank you.

    EDIT 1: I got an idea, don't know why I didn't think of it, maybe too burnt out. Anyway. I'm gonna try reming out some code in my filter function where most of the heavy algo is and work (remark) backward until the code works without crashes or leaks.

    EDIT 2: finally, some answers. Too tired to go further. It 12:40am here, and its bedtime for me.

    -vhelp 5409
    Last edited by vhelp; 17th Jul 2011 at 19:27.
    Quote Quote  
  2. Member
    Join Date
    Jul 2009
    Location
    Spain
    Search Comp PM
    Originally Posted by vhelp View Post
    Not sure if anyone knows, being that this is a programing related question to AVIsynth and plugin development and i've never seen any plugin developers on this board so i'm doubtful that i'll get any response but i have to at least try.
    You would find a wider audience for this topic on the Avisynth Development forum:
    http://forum.doom9.org/forumdisplay.php?f=69
    it also looks like avisynth has a slight leak depending on what (internal) functions you use and how you use them. The leak is small and increases gradually over time, then settles at a peak w/out change through rest of video.
    Avisynth saves rendered video frames in a cache to avoid regenerating them if needed again. So as frames are generated, memory use gradually increases until the cache memory is full.

    The size of the cache is controlled by the SetMemoryMax() function, which you can use in your script. By setting a smaller value, more memory is made available to other components, including your plugin.

    Are you using the C plugin interface or the C++ one?
    Memory management is simpler in C++ than in C.
    Quote Quote  
  3. Member vhelp's Avatar
    Join Date
    Mar 2001
    Location
    New York
    Search Comp PM
    Gavino, thanks for your interest and suggestions

    Are you using the C plugin interface or the C++ one?
    Memory management is simpler in C++ than in C.
    Yes, I am using the C plugin interface.

    I googled the error (above post) and came up with some discussion on this issue--where you were part of the discussion--and took your advise on the SetMemoryCach(192) but i used (64) and it solve the cache memory hit issue when (my) code is correct or single frame access--read on to indepth explanation after link.

    --> http://forum.doom9.org/archive/index.php/t-150875.html

    I am not too worried about the gradual cache memory loss. That is a normal function of avisynth, now that I understand it. But i'm mostly worried about my part in all this with my "wrapper" code, using the _C plugin interface. I think the error is in my implementation of calling three frames, and the way I am going about it basically is copying from lines (5 through 6d) from this link below. Since it is more in your c/c++ area of expert I am using that to illustrate where my error could be, maybe you can spot it.

    --> How do I open a script with the AviSynth C API, and is this a typo?

    1. AVS_ScriptEnvironment *env = avs_create_script_environment(2);
    2. AVS_Value Args=avs_new_value_string("C:\script.avs");
    3. AVS_Value val=avs_invoke(env, "Import", Args, 0);
    4. AVS_Clip *clip=avs_take_clip(val, env);
    5. AVS_VideoFrame *frame=avs_get_frame(clip, n);
    6a. const BYTE *data=avs_get_read_ptr(frame);
    6b. int rowsize=avs_get_row_size(frame);
    6c. int pitch=avs_get_pitch(frame);
    6d. int height=avs_get_height(frame);
    7. do something with data
    8. avs_release_frame(frame);
    9. avs_release_clip(clip);
    10. avs_delete_script_environment(env);


    (since i haven't seen any example code for temporal type frame access, i have to conjure up a crude method of my own and things sure enough got messy -- see crude pseudo code below. My actual code is a lot messy slightly different than the one below but it does work, just the cache problem is the issue)

    From above, I setup for line 1 through 10 and all work as it should.

    But, to create the prev/curr/next frames, I am copying lines 5 thru 6d, like this:

    Previous frame:
    P5. AVS_VideoFrame *frame=avs_get_frame(clip, n-1); // PREVF
    P6a. const BYTE *data=avs_get_read_ptr(frame);
    P6b. int rowsize=avs_get_row_size(frame);
    P6c. int pitch=avs_get_pitch(frame);
    P6d. int height=avs_get_height(frame);


    Current frame:
    C5. AVS_VideoFrame *frame=avs_get_frame(clip, n); // CURRF
    C6a. const BYTE *data=avs_get_read_ptr(frame);
    C6b. int rowsize=avs_get_row_size(frame);
    C6c. int pitch=avs_get_pitch(frame);
    C6d. int height=avs_get_height(frame);


    Next frame:
    N5. AVS_VideoFrame *frame=avs_get_frame(clip, n+1); // NEXTF
    N6a. const BYTE *data=avs_get_read_ptr(frame);
    N6b. int rowsize=avs_get_row_size(frame);
    N6c. int pitch=avs_get_pitch(frame);
    N6d. int height=avs_get_height(frame);



    Gavino, thank you again for any guidance or suggestions you may find.

    -vhelp 5410
    Quote Quote  
  4. Member
    Join Date
    Jul 2009
    Location
    Spain
    Search Comp PM
    The code you have shown looks basically correct, although I'm not clear if you have different variables for previous, next and current frames, or simply re-use the same ones (if you only need one at a time).

    Either way, be sure to call avs_release_frame() (step 8) for each frame you get, otherwise you will get a memory leak.
    Quote Quote  
  5. Member vhelp's Avatar
    Join Date
    Mar 2001
    Location
    New York
    Search Comp PM
    Thanks Gavino. The release frame is in another function and that may be the cause of the confusion.

    Would you mind having a look at my code--i can send to you in pm--and see if there is anything you might spot that could be the cause of the memory leak ? There is no rush, i can come back next week.

    There are two functions that I am currently stripping it out of main project and am commenting it to make it as easy to follow (a baby could figure it out) and I should be done with it in a little while. I think that once you see it, it won't be difficult to spot the problem, i hope.

    EDIT: please disregard my request. Having thought about it some, I realize now that I shouldn't be imposing on your free time. I'll try and figure this out on my own. If I figure it out i'll add "resolved" to the subject title. Thank you for your interest and help so far, Gavino!

    -vhelp 5411
    Last edited by vhelp; 8th Aug 2010 at 15:43.
    Quote Quote  
  6. Member
    Join Date
    Jul 2009
    Location
    Spain
    Search Comp PM
    I don't mind having a quick look at something (either posted here or by PM).
    If the problem is obvious, I can let you know quickly, otherwise it might have to wait a few days.

    And often, just explaining your code to someone else can make you realise what's wrong with it, so you might not need my help after all.
    Quote Quote  
  7. Member vhelp's Avatar
    Join Date
    Mar 2001
    Location
    New York
    Search Comp PM
    Gavino, thanks again.

    I think i found the problem. It is definately this line: AVS_VideoFrame *frame=avs_get_frame(clip, n). The call to free frame is in another function, it is called, indrectly so to speak inside this function when calling the *frame= function. I would have to re-write these two parts somehow.

    When used only once (as in current frame) it is problem free, no memory leak.

    But, when I use it more than once, (like below) then it looks like two frame or instances (whatever the programming lingo is for this) are not freed. So, think of it like this, C5 and N5 (curr and next) are not freed, so the memory increments at every frame scrub in the timeline.

    P5. AVS_VideoFrame *frame=avs_get_frame(clip, n-1); // PREVF
    C5. AVS_VideoFrame *frame=avs_get_frame(clip, n); // CURRF
    N5. AVS_VideoFrame *frame=avs_get_frame(clip, n+1); // NEXTF


    I'm afraid that the (original Myrsloik project) (see the invert.dpr demo for how frames are called and released, then you'll understand my problem and temporal-less access) is past my tallents to figure out unfortunately. And it seems that the dev'er abandond it, is more consentrating on the more popular ffmpegsource / ffm2s project. The way he wrote the orig source, it is intended for single frame access.

    For your reference, you can see the original project here, (above link) in case you are curious how he accomplished this for delphi (plugin) programming. Temporal plugin development doesn't seem possible, not without the huge memory leak associated, the routine (or part of it) will have to be re-written in order to accomedate.

    If I resolve these issues i'll mark subj title [RESOLVED] and move on, until then..it looks like I am left with the task of re-writing code if I want to do temporal type frame processing

    EDIT: ok, i might have something crude..note, no error checkig done--assume script is correct b4 filter.

    Code:
    var
      clip: PAVS_Clip;
    ..
    ..
    function GetPCNFrame(bm: TBitmap; FrameNo: integer): TBitmap;
    var
      frame : PAVS_VideoFrame;
    begin
      // assume already in rgb color space else include colortorgb24() b4 filter in script
      frame := avs_get_frame(clip, FrameNo); 
      ConvertFrameToBMP(frame, bm);
      result := bm;
      avs_release_video_frame(frame);
    end;
    call in the following way:

    GetPCNFrame(prevBM, FrameNo-1)
    GetPCNFrame(currBM, FrameNo )
    GetPCNFrame(nextBM, FrameNo+1)


    ..and then, where to put the code.

    thats it for now..too burnt out.

    -vhelp 5413
    Last edited by vhelp; 11th Aug 2010 at 00:11.
    Quote Quote  
  8. Member
    Join Date
    Jul 2009
    Location
    Spain
    Search Comp PM
    Yes, for each call to avs_get_frame there must be a corresponding call to avs_release_video_frame.

    The download link to Myrsloik's code seems to be dead, so I can't see how it was originally done.
    But your strategy of "get frame, copy data, release frame" should solve the memory leak problem.
    Quote Quote  
  9. The download link to Myrsloik's code seems to be dead, so I can't see how it was originally done.
    I added a working link to that post
    Quote Quote  
  10. Member vhelp's Avatar
    Join Date
    Mar 2001
    Location
    New York
    Search Comp PM
    [RESOLVED] -- 7/17/2011 Sun

    just wanted to update/close this issue.

    after a year i finally solved the memory leak problem when reading more than one frame or three frames for temporal filter work. the idea i present earlier in these posts did not work. i mostly re-wrote the code.

    of course, now i have another problem, when i open a script in vdub and then edit the script and open again in vdub, it will crash with a "colors_rgb.avsi, line 17, column 0" error. i have no idea where that is since i'm not using any avsi scripts. but i can live with that since i can just close vdub first then re-open with the edited script..i mainly drag my scripts anyway.
    Quote Quote  
  11. DECEASED
    Join Date
    Jun 2009
    Location
    Heaven
    Search Comp PM
    Originally Posted by vhelp View Post
    ...
    when i open a script in vdub and then edit the script and open again in vdub, it will crash with a "colors_rgb.avsi, line 17, column 0" error. i have no idea where that is since i'm not using any avsi scripts.
    Take a look at Avisynth's default plugins folder.
    Quote Quote  
  12. Member
    Join Date
    Jul 2009
    Location
    Spain
    Search Comp PM
    I have never seen this problem before. Does it happen for all scripts after editing, or is there something particular about your script?

    colors_rgb.avsi (which defines a list of global color names) is loaded on Avisynth startup.
    There is nothing special about line 17, so this leads me to suspect some sort of memory corruption is happening.
    Do you have any 'unusual' dlls or .avsi files in the plugins folder?
    Quote Quote  
  13. Member vhelp's Avatar
    Join Date
    Mar 2001
    Location
    New York
    Search Comp PM
    I have never seen this problem before. Does it happen for all scripts after editing, or is there something particular about your script?
    no. i believe it has to do with the DLL I created. After countless debugging and what-if scenarios of all the coding I added/deleted to get it finally work, theres bound to be a repacusion down the round yet to find and correct.

    but the odd thing is, I have another plugin I coded, (the one with the memory leak) and that does not give me this problem. I can make as many edits to the script and drag and drop many times and it will not produce that error.

    here is the exact error. sorry for the way the image is posted in that annoying box--some people don't get it though i do. anyway. thanks to looking into this guys. (please excuse my rush to leave for work, am late this morning.)
    Image Attached Images  
    Quote Quote  
  14. Member
    Join Date
    Jul 2009
    Location
    Spain
    Search Comp PM
    Hmm, definitely sounds like some sort of memory corruption.

    So the problem occurs with any script that calls a particular dll (written by you), but not with any other dll?
    That strongly suggests that there is something wrong with that plugin - probably the changes you made to 'fix' the memory leak just moved the problem to another part of the code.
    Quote Quote  
  15. Member vhelp's Avatar
    Join Date
    Mar 2001
    Location
    New York
    Search Comp PM
    (i took off from work..too hot)

    I agree..with your comments..i'm in middle of posting more details..
    Quote Quote  
  16. Member vhelp's Avatar
    Join Date
    Mar 2001
    Location
    New York
    Search Comp PM
    my sources are captures, huffy yuy2 avi's.

    its definately the dll i made. i'm investigating it now. but not an easy process to resolve since i added and deleted stuff since last year. i'm trying to back-track original sources from the demo files from (original Myrsloik project) but so far not easy. wilbert updated the links in case you want to have a look. if you look at the invert (simiplest one and one i used as a bases in my plugin development) i think it has to do with the code in this function below.

    i removed a lot of (new) code i wrote that you don't need--less confusion. but in the invert demo, there are a few lines of code that query for correct color space, i think though i'm not sure. but there could be color space checks that need to be in this section of code for yuy2, yv12, rgb24 etc that i'm not using because they were never included in the demos and/or i don't know how they are called in c/c++ / avisynth syntax language that i might be able to translate into the delphi pascal code.

    --my code--

    Code:
    function create_NR(env: PAVS_ScriptEnvironment; args: MSVC_AVS_Value; use_inplace: Pointer): MSVC_AVS_Value; stdcall;
    begin;
      //typecast the args to something usable
      avsargs := AVS_Value(args);
    
      new_clip := avs_new_c_filter(env, fi, avs_array_elt(avsargs, 0), true);
    
      fi^.get_frame := @GetFrameBM; // our curr frame
    
      // procedure to run when the filter is destroyed (optional)
      fi^.free_filter := @destroy_NR;
    
      //make an avs_value out of the new clip
      v := avs_new_value_clip(new_clip);
    
      //free the clip as it's no longer needed, the avs_value v also points to it
      //unless an error happened
      avs_release_clip(new_clip);
    
      //typecast v to return it
      Result := MSVC_AVS_Value(v);
    
    end;
    --code snip from invert demo--

    Code:
    function create_invert(env: PAVS_ScriptEnvironment; args: MSVC_AVS_Value; use_inplace: Pointer): MSVC_AVS_Value; stdcall;
    var
      v: AVS_Value;
      fi: PAVS_FilterInfo;
      new_clip: PAVS_Clip;
    begin;
      new_clip := avs_new_c_filter(env, fi, avs_array_elt(AVS_Value(args), 0), true);
      if (avs_is_planar(@fi^.vi)) then
        v := avs_new_value_error('Video must be on a single plane')
      else
      begin
        if use_inplace = nil then
          fi^.get_frame := @invert_get_frame
        else
          fi^.get_frame := @invert_inplace_get_frame;
    
        v := avs_new_value_clip(new_clip);
      end;
      avs_release_clip(new_clip);
      Result := MSVC_AVS_Value(v);
    end;
    in the mean time, i will continue researching the problem and report back if resolved. thank you again.
    Quote Quote  
  17. Member vhelp's Avatar
    Join Date
    Mar 2001
    Location
    New York
    Search Comp PM
    ahha! i think i might know what the problem is. at the root of my filter work, i am working in RGB color space. but how i access and return it is the key here, i think.

    so it might have to do with the way i define the pf24bit bitmap array. there are several ways to work with 24bit RGB bitmaps via pointers and arrays defination types in code.

    in the invert demo code below, it uses this method:

    --invert demo--
    Code:
    type
      PByteArray = ^TByteArray;
      TByteArray = array[0..32767] of Byte;
    while in my code i chose to use the method you see because i like to access the r.g.b more plainly than having to resort to multiplying byte arrays etc to deal with each color component.

    --my code--
    Code:
    CONST
      PixelCountMax = 2880; //32768;
    TYPE
      pRGBTripleArray = ^TRGBTripleArray;
      TRGBTriple = packed record
                     r : byte;
                     g : byte;
                     b : byte;
                   end;
      TRGBTripleArray = ARRAY[0..PixelCountMax-1] OF TRGBTriple;
    i can't change my code to the invert's method because of the complexty and amount of work envolved. but i can prob do it to the invert demo, change it to my method and then test it to see if i get the same error.
    Quote Quote  
  18. Member
    Join Date
    Jul 2009
    Location
    Spain
    Search Comp PM
    Before you get involved with a lot of extra work, there is one possibly suspicious thing you can check.

    I see in your create_NR function, you are setting fi^.free_filter:=@destroyNR.
    What does you destroyNR function do?
    In the extended invert demo code, the corresponding destroy_invert function frees the memory used for settings in fi^.user_data.
    However, I do not see fi^.user_data being initialised in your code.

    If you don't have any user_data, you don't need a free_filter function.
    As this function is called when a script is unloaded, erroneous use could lead to the symptoms you are seeing.
    Quote Quote  



Similar Threads

Visit our sponsor! Try DVDFab and backup Blu-rays!