October 29, 2020, 02:07:22 AM

Author Topic: [bb] FrameGrabber using AVIFil32.dll by jfk EO-11110 [ 1+ years ago ]  (Read 1430 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
Title : FrameGrabber using AVIFil32.dll
Author : jfk EO-11110
Posted : 1+ years ago

Description : Since a long time I am searching and asking for a fast and reliable way to access frames of an avi. I tried a lot of things and was pretty frustrated in the end. However, wrapping Avifil32.dll for frameaccess only turned out to be less painfull than I thought in the first place.

So here's my version of using Avifil32.dll to access Avi frames.

There are still some Problems with some codecs, especially with the VP6 codec. Any help is welcome to fix this issue.


Code :
Code: BlitzBasic
  1. ; Approach: Fast and reliable direct Avi Frame access (for Video FX Processing etc.)
  2. ; AVIFIL32.DLL is used to read-access certain Frames of an Avi.
  3.  
  4. ; A decls file named Avifil32.decls is required, containing:
  5.  
  6. ;.lib "avifil32.dll"
  7. ;AVIFileInit%()
  8. ;AVIFileOpen%(ppfile*,szFile$,uMode%,lpHandler%)
  9. ;AVIFileRelease%(pfile%)
  10. ;AVIFileInfo%(pfile%,pfi*,lSize%)
  11. ;AVIFileGetStream%(pfile%,ppavi*,fccType%,lParam%)
  12. ;AVIFileExit%()
  13. ;AVIStreamStart%(pavi%)
  14. ;AVIStreamRelease%(pavi%)
  15. ;AVIStreamLength%(pavi%)
  16. ;AVIStreamGetFrameOpen%(pavi%,lpbiWanted%)
  17. ;AVIStreamGetFrame%(pFrame%,index%)
  18. ;AVIStreamGetFrameClose%(pFrame%)
  19.  
  20. ;Additionally in "kernel32.decls" the following lines are required:
  21.  
  22. ;.lib "kernel32.dll"
  23. ;RtlMoveMemory2%(Destination*,Source,Length) : "RtlMoveMemory"
  24.  
  25. ;Of course, everything without semicolon.
  26.  
  27. Graphics 800,600,32,2
  28. SetBuffer BackBuffer()
  29.  
  30.  
  31. Const OF_READ=$0
  32.  
  33. ; The following Avi codecs were tested and seem to work without problems:
  34. ; HuffYuf
  35. ; Indeo 5
  36. ; Cinepak Radius
  37. ; MPG4 V2
  38.  
  39.  
  40. ; Some Avi codecs that made troubles:
  41. ; DV-Avi: will be detected as not accessible
  42. ; VP6n (VP61, VP62 etc.) This one can be accessed, but when the stream and avi is closed,
  43. ;      it will produce a Windows Error message that cannot be clicked away until the machine
  44. ;      will be rebootet (at least on Win98). Unfortunately it's not possible to detect
  45. ;      this problem since Accessing the Frames works, only closing the handles forces the error.
  46. ;      I am desperatly seeking for a solution for this issue since it forces the user to
  47. ;      manually check the Avi codec before loading to make sure it's not vp6.
  48. ;      Any help is welcome!
  49.  
  50.  
  51.  
  52. testfile$="D:videosmoke.AVI"
  53.  
  54.  
  55.  
  56.  
  57. ; **** demo ****
  58.  
  59. AVIFileInit(); this needs to be called before any other Avifil32.dll function call
  60.  
  61. ; multiple movies may now be opened simultanously, each one gets a bank handle:
  62. avi_struct = bbOpenAvi(testfile$) ; this bank contains useful info. See function bbOpenAvi
  63. ; if it's zero then our app failed to open the avi sor some reason:
  64. If avi_struct=0 Then
  65.  AVIFileExit()
  66.  RuntimeError "error opening avi "+testfile$
  67. Endif
  68.  
  69. FirstFrame1=PeekInt(avi_struct,136)
  70. NumFrames1 =PeekInt(avi_struct,140)
  71.  
  72. index1=FirstFrame1
  73.  
  74. ClsColor 50,50,50
  75. While KeyDown(1)=0
  76.   img=bbAviGetFrame(avi_struct,index1)
  77.   Cls
  78.   DrawBlock img,10,10
  79.   FreeImage img
  80.   Text 100,100,"Frame: "+index1+"  "
  81.   Flip
  82.   index1=index1+1
  83.   If index1>=NumFrames1 Then index1=FirstFrame1
  84. Wend
  85.  
  86. If avi_struct <> 0 Then
  87.  bbCloseAvi(avi_struct) ; don't forget this!
  88. EndIf
  89.  
  90. AVIFileExit()          ; this needs to be called  here to release the avifil32.dll initialisation !
  91. End
  92.  
  93.  
  94.  
  95.  
  96.  
  97.  
  98.  
  99. ; **********************************************************************************************
  100. Function bbOpenAvi(file$)
  101.  ; After opening the avi file we will need to retrieve some info from the avi handler.
  102.  ; the following structure will be used:
  103.  ; AVIFILEINFO structure:
  104.  ;    0 dwMaxBytesPerSec;
  105.  ;    4 dwFlags;
  106.  ;    8 dwCaps;
  107.  ;   12 dwStreams;
  108.  ;   16 dwSuggestedBufferSize;
  109.  ;   20 dwWidth;
  110.  ;   24 dwHeight;
  111.  ;   28 dwScale;
  112.  ;   32 dwRate;
  113.  ;   36 dwLength;
  114.  ;   40 dwEditCount;
  115.  ;   44 string  szFileType 64 bytes;
  116.  ; (11*4)+64 =108
  117.  ; size of AVIFILEINFO structure: 108 bytes
  118.  s=108
  119.  ; create a bank that A) stores the AVIFILEINFO that is given by Avifil32.dll, and B) store
  120.  ; some bank handles, avifile handles, stream handles, frame handles that will be used
  121.  ; in other functions as well. In case of B) the Data is stored at offset 128 and higher.
  122.  AviFileInfoBank=CreateBank(512)
  123.  For i=0 To 508 Step 4
  124.   PokeInt AviFileInfoBank,i,0
  125.  Next
  126.  
  127.  ret=CreateBank(8) ; will hold the avifileopen handle
  128.  res=AVIFileOpen(ret,file$,OF_READ,0)
  129.  avi_handle=PeekInt(ret,0)
  130.  If res<>0 Then ; error opening!
  131.   If avi_handle<>0
  132.    AVIFileRelease(avi_handle)
  133.   EndIf
  134.   FreeBank ret
  135.   FreeBank AviFileInfoBank
  136.   Return 0
  137.  EndIf
  138.  ;Print "opened file" ; used for debugging purposes
  139.  
  140.  ;*** GET AVI INFO ***
  141.  res=AVIFileInfo(avi_handle,AviFileInfoBank,108)
  142.  ; string "szFileType", 64 bytes, contains some info about the Avi handler (well not used here, but, anyway)
  143.  szFileType$=""
  144.  For i=44 To 108
  145.   If PeekByte(AviFileInfoBank,i)=0 Then Exit
  146.   szFileType$=szFileType$+Chr$(PeekByte(AviFileInfoBank,i))
  147.  Next
  148.  ;Print "got info" ; used for debugging purposes
  149.  ;Print szFileType$
  150.  
  151.  PokeInt AviFileInfoBank,128,avi_handle ; store avi_handle for future usage
  152.  
  153.  
  154.  ;*** Open AVI STREAM ***
  155.  ; fccType is a 32Bit long string that may be:
  156.  ; "vids","auds","mids" or "txts" (of course we only use "vids")
  157.  ; sent as 32 bit unsigned long:
  158.  ; 1935960438 vids
  159.  ; 1935963489 auds
  160.  ; 1935960429 mids
  161.  ; 1937012852 txts
  162.  fccType=1935960438
  163.  res=AVIFileGetStream(avi_handle,ret,fccType,0)
  164.  stream_handle=PeekInt(ret,0)
  165.  
  166.  If res<>0 Then ; error getting stream!
  167.   If stream_handle<>0
  168.    AVIStreamRelease(stream_handle)
  169.   EndIf
  170.   If avi_handle<>0
  171.    AVIFileRelease(avi_handle)
  172.   EndIf
  173.   FreeBank ret
  174.   FreeBank AviFileInfoBank
  175.   Return 0
  176.  EndIf
  177.  ;Print "got stream" ; used for debugging purposes
  178.  
  179.  PokeInt AviFileInfoBank,132,stream_Handle ; store stream_handle for future usage
  180.  
  181.  FirstFrame=AVIStreamStart(stream_handle)
  182.  If firstframe<0 Then ; signs of incorrect avi data (no frames)
  183.   If stream_handle<>0
  184.    AVIStreamRelease(stream_handle)
  185.   EndIf
  186.   If avi_handle<>0
  187.    AVIFileRelease(avi_handle)
  188.   EndIf
  189.   FreeBank ret
  190.   FreeBank AviFileInfoBank
  191.   Return 0
  192.  EndIf
  193.  ;Print "firstframe >-1" ; used for debugging purposes
  194.  
  195.  NumFrames=AVIStreamLength(stream_handle)
  196.  If numframes<=0 Then ; no frames in avi
  197.   If stream_handle<>0
  198.    AVIStreamRelease(stream_handle)
  199.   EndIf
  200.   If avi_handle<>0
  201.    AVIFileRelease(avi_handle)
  202.   EndIf
  203.   FreeBank ret
  204.   FreeBank AviFileInfoBank
  205.   Return 0
  206.  EndIf
  207.  ;Print "numframes > 0" ; used for debugging purposes
  208.  
  209.  PokeInt AviFileInfoBank,136,FirstFrame ; store FirstFrame for future usage
  210.  PokeInt AviFileInfoBank,140,NumFrames ; store NumFrames for future usage
  211.  
  212.  
  213.  
  214.  frame_handle=AVIStreamGetFrameOpen(stream_handle,0) ; 0= default, 1=bestdisplay
  215.  If frame_handle=0 ; failed to create a frame access handle
  216.   If stream_handle<>0
  217.    AVIStreamRelease(stream_handle)
  218.   EndIf
  219.   If avi_handle<>0
  220.    AVIFileRelease(avi_handle)
  221.   EndIf
  222.   FreeBank ret
  223.   FreeBank AviFileInfoBank
  224.   Return 0
  225.  EndIf
  226.  PokeInt AviFileInfoBank,144,frame_handle ; store frame_handle for future usage
  227.  ;Print "frame handle <> 0" ; used for debugging purposes
  228.  
  229.  ; create a bank that will be used to store the DIB bitmaps delivered by "AviStreamGetFrame".
  230.  ; (currently only 24 bit DIB mode is supported)
  231.  FrameBank=CreateBank((PeekInt(AviFileInfoBank,20)*PeekInt(AviFileInfoBank,24)*3)+40+1000)
  232.  PokeInt AviFileInfoBank,148,FrameBank ; store FrameBank for future usage
  233.  FreeBank ret
  234.  Return AviFileInfoBank
  235. End Function
  236.  
  237.  
  238.  
  239.  
  240.  
  241.  
  242.  
  243.  
  244. Function bbAviGetFrame(AviFileInfoBank,index) ;request a certain frame and move the DIB image to a bank
  245.  frame_adress=AVIStreamGetFrame(PeekInt(AviFileInfoBank,144),index)
  246.  RtlMoveMemory2(PeekInt(AviFileInfoBank,148),frame_adress,40+(PeekInt(AviFileInfoBank,20)*PeekInt(AviFileInfoBank,24)*3))
  247.  img=decodeDIB(PeekInt(AviFileInfoBank,148),PeekInt(AviFileInfoBank,20),PeekInt(AviFileInfoBank,24))
  248.  Return img
  249. End Function
  250.  
  251.  
  252.  
  253. Function bbCloseAvi(AviFileInfoBank) ; close frame, stream, avi, release used banks
  254.  AVIStreamGetFrameClose(PeekInt(AviFileInfoBank,132))
  255.  AVIStreamRelease(PeekInt(AviFileInfoBank,132))
  256.  AVIFileRelease(PeekInt(AviFileInfoBank,128))
  257.  FreeBank PeekInt(AviFileInfoBank,148)
  258.  FreeBank AviFileInfoBank
  259. End Function
  260.  
  261.  
  262.  
  263.  
  264. Function decodeDIB(bank,w,h) ; create an image from a 24bit DIB image stored in a bank
  265.  img=CreateImage(w,h)
  266.  SetBuffer ImageBuffer(img)
  267.  LockBuffer ImageBuffer(img)
  268.  z=40
  269.  For y=0 To h-1
  270.   For x=0 To w-1
  271.    rgb=PeekInt(bank,z) And $FFFFFF
  272.    WritePixelFast x,(h-1)-y,rgb
  273.    z=z+3
  274.   Next
  275.  Next
  276.  UnlockBuffer ImageBuffer(img)
  277.  SetBuffer BackBuffer()
  278.  Return img
  279. End Function


Comments :


Litobyte(Posted 1+ years ago)

 Would be hard to the same for videocap ?One of the greatest lack of blitz3D is the ability to grab from a directshow device.All what I have seen working, was dead slow, it will be sweet to be able to process images for analysis coming from a camera.This will open blitz3D to a lot of gaming ( playing in front of a cam ) and tools possibilities.


ZJP(Posted 1+ years ago)

 Hi,This does not work with the Xvid codec.JP


 

SimplePortal 2.3.6 © 2008-2014, SimplePortal