Page 3 of 4

AVBin Example code..

Posted: Sat Nov 22, 2008 11:59 pm
by Philippe-felixer76-2
Paul wrote:ok, I've looked a little more into it so I have this now...

Code: Select all

Enumeration  
  #AVBIN_RESULT_ERROR        =-1
  #AVBIN_RESULT_OK           = 0
EndEnumeration

Enumeration 
  #AVBIN_STREAM_TYPE_UNKNOWN = 0
  #AVBIN_STREAM_TYPE_VIDEO   = 1
  #AVBIN_STREAM_TYPE_AUDIO   = 2
EndEnumeration

Enumeration  
  #AVBIN_SAMPLE_FORMAT_U8    = 0
  #AVBIN_SAMPLE_FORMAT_S16   = 1
  #AVBIN_SAMPLE_FORMAT_S24   = 2
  #AVBIN_SAMPLE_FORMAT_S32   = 3
  #AVBIN_SAMPLE_FORMAT_FLOAT = 4
EndEnumeration

Enumeration 
  #AVBIN_LOG_QUIET           =-8
  #AVBIN_LOG_PANIC           = 0
  #AVBIN_LOG_FATAL           = 8
  #AVBIN_LOG_ERROR           = 16
  #AVBIN_LOG_WARNING         = 24
  #AVBIN_LOG_INFO            = 32
  #AVBIN_LOG_VERBOSE         = 40
  #AVBIN_LOG_DEBUG           = 48
EndEnumeration

Structure AVbinFileInfo
  structure_size.l
  n_streams.l
  start_time.q
  duration.q
  title.s{512}
  author.s{512}
  copyright.s{512}
  comment.s{512}
  album.s{512}
  year.l
  track.l
  genre.s{32}
EndStructure

Structure AVbinStreamInfo
  structure_size.l
  type.l
  StructureUnion
    width.l
    sample_format.l
  EndStructureUnion 
  StructureUnion
    height.l
    sample_rate.l
  EndStructureUnion 
  StructureUnion
    sample_aspect_num.l
    sample_bits.l
  EndStructureUnion 
  StructureUnion
    sample_aspect_den.l
    channels.l
  EndStructureUnion 
EndStructure

Structure AVbinPacket
  structure_size.l
  timestamp.q
  stream_index.l
  *data.q
  size.l
EndStructure


#MicroSecond=1000000



Prototype.l Proto_avbin_init()
Prototype.l Proto_avbin_open_filename(filename.s)
Prototype   Proto_avbin_close_file(avFile.l)
Prototype.l Proto_avbin_file_info(avFile.l,fiStructure.l)
Prototype.l Proto_avbin_stream_info(avFile.l,avStream.l,siStructure.l)
Prototype.l Proto_avbin_open_stream(avFile.l,avStream.l)
Prototype.l Proto_avbin_close_stream(avStream.l)
Prototype.l Proto_avbin_read(avFile.l,pStructure.l)






hLib=OpenLibrary(#PB_Any,"avbin.dll")
If hLib
  avbin_init.Proto_avbin_init=GetFunction(hLib,"avbin_init")
  avbin_open_filename.Proto_avbin_open_filename=GetFunction(hLib,"avbin_open_filename")
  avbin_close_file.Proto_avbin_close_file=GetFunction(hLib,"avbin_close_file")
  avbin_file_info.Proto_avbin_file_info=GetFunction(hLib,"avbin_file_info")
  avbin_stream_info.Proto_avbin_stream_info=GetFunction(hLib,"avbin_stream_info")
  avbin_open_stream.Proto_avbin_open_stream=GetFunction(hLib,"avbin_open_stream")
  avbin_close_stream.Proto_avbin_close_stream=GetFunction(hLib,"avbin_close_stream")
  avbin_read.Proto_avbin_read=GetFunction(hLib,"avbin_read")
 
 
  ;file$=GetCurrentDirectory()+"days.mp3"
  ;file$=GetCurrentDirectory()+"test.mpg"
  file$=GetCurrentDirectory()+"flake.mpg"
 
 
 
  avbin_init()
  avFile=avbin_open_filename(file$)
 
  finfo.AVbinFileInfo\structure_size=SizeOf(AVbinFileInfo)
  avbin_file_info(avFile,finfo)
;{ 
  streams=finfo\n_streams
  Debug streams
  Debug finfo\start_time
  dur=AddDate(Date(2000,1,1,0,0,0),#PB_Date_Second,finfo\duration / #MicroSecond)
  Debug FormatDate("%ii:%ss",dur)
  
  Debug "----------" 
  Debug finfo\title
  Debug finfo\author
  Debug finfo\copyright 
  Debug finfo\comment
  Debug finfo\album
  Debug finfo\year
  Debug finfo\track 
  Debug finfo\genre
  Debug "----------" 
;}  
  
  
  For idx=0 To streams-1
    sinfo.AVbinStreamInfo\structure_size=SizeOf(AVbinStreamInfo)  
    avbin_stream_info(avFile,idx,sinfo)

    Select sinfo\type
      Case #AVBIN_STREAM_TYPE_VIDEO
        aspect.f=sinfo\sample_aspect_num/sinfo\sample_aspect_den
        Debug aspect
        Debug sinfo\width
        Debug sinfo\height
      Case #AVBIN_STREAM_TYPE_AUDIO
        Debug sinfo\sample_format
        Debug sinfo\sample_rate
        Debug sinfo\sample_bits
        Debug sinfo\channels
    EndSelect 

    Debug "----------"  
  Next
   
   
  hStream=avbin_open_stream(avFile,StreamIndex) 
  pinfo.AVbinPacket\structure_size=SizeOf(AVbinPacket)
  pinfo\timestamp=0
  pinfo\stream_index=hStream
  Debug avbin_read(avFile,pinfo)
  
  avbin_close_stream(hStream)
 
 
 
 
  avbin_close_file(avFile) 

  CloseLibrary(hLib)
EndIf
End 
I think I am not yet understanding how to use avbin_read since it returns -1 (error). What do you have for this so far?

Also I am not getting meta data from the files so there is most likely a mistake there also ;)
Hi Paul,

It's better to share all our knowledge in stead of PM's..

Here's my current example code, NO audio, i have
problems with audio packets and it has a very poor
simplistic cpu eating video display method at this
moment, sowwy..

Get the library here:
http://avbin.googlecode.com/files/avbin-win32-5.zip

I left out debugging the title, author, etc data in this example.

Code: Select all

; AVBin For PureBasic (attempt)
; -------------------
; v 181108 decoding frames from video streams
; v 181108 Display video frames in 24 bit RGB format
; v 211108 Simple video timing
; - 211108 Audio testing, having real problems here

; structures
Structure _AVbinFileInfo
   size_t.l
   n_streams.l
   starttime.q
   duration.q
   title.c[512]
   author.c[512]
   copyright.c[512]
   comment.c[512]
   album.c[512]
   year.l
   track.l
   genre.c[32]
EndStructure
Structure _AVbinStreamInfo
   structuresize.l     ; size
   AVBinStreamType.l   ; 0 (unknown),1 (video) of 2 (audio)
   ; BELOW SHOULD BE STRUCTUREUNION FOR AUDIO AND VIDEO
   ; --------------------------------------------------
   width.l             ; or avbinsampleformat
   height.l            ; or samplerate 
   sample_aspect_num.l ; or sample_bits
   sample_aspect_den.l ; or channels
EndStructure
Structure _AVbinPacket
   structure_size.q    ; why quad?
   timestamp.q         ; timestamp uint64_t
   streamindex.l       ; int 
   *dat.l              ; long 
   size.q              ; why quad?
EndStructure
; test
Structure _AVbinFile 
    *context           ;AVFormatContext *context;
    *packet            ;AVPacket *packet;
EndStructure
Structure _AVBinStream
    type.l             ;int type;
    *format_context    ;AVFormatContext *format_context;
    *codec_context     ;AVCodecContext *codec_context;
    *frame             ;AVFrame *frame;   
EndStructure

; procedures
Procedure ReverseMemoryB(*memory.Byte,length.l)
 Protected *memend.Byte
 If length>SizeOf(Byte)
  *memend=(*memory+length)-SizeOf(Byte)
  length>>1
  While length>0
   Swap *memory\b,*memend\b
   *memory+SizeOf(Byte)
   *memend-SizeOf(Byte)
   length-SizeOf(Byte)
  Wend
 EndIf
EndProcedure 
Procedure ImageFlipH(img_id) ; Flip an image on it's Horizontal axis
    msImageFlipH=ElapsedMilliseconds()
    result = #False
    If IsImage(img_id)
      hOldImage.l = ImageID(img_id)
      img_w = ImageWidth(img_id)
      img_h = ImageHeight(img_id)
      Dim Points.Point(2)
      Points(0)\x = img_w
      Points(0)\y = 0
      Points(1)\x = 0
      Points(1)\y = 0 
      Points(2)\x = img_w 
      Points(2)\y = img_h
      main_dc = GetDC_(WindowID(0))
      source_dc = CreateCompatibleDC_(main_dc)
      SelectObject_(source_dc,hOldImage)
      dest_dc = main_dc
      SelectObject_(dest_dc,hNewImage)
      result = PlgBlt_(dest_dc,@Points(), source_dc, 0, 0, img_w, img_h, 0, 0, 0) 
      DeleteDC_(source_dc)
      DeleteDC_(dest_dc)
    EndIf
    ProcedureReturn result
EndProcedure

; test video file, please adjust to your needs...
; ---------------------------------------------------
testfile.s = "F:\bb.20080116.asf"
; window
OpenWindow(0,0,0,10,10 ,"AVBIN - (FFMPEG) Libavcodec/Libavformat WRAPPER",#WS_SYSMENU|1)

; open avbin and video file
If OpenLibrary(0, "avbin.dll") And (FileSize(testfile.s)>0)
   
   ; get all needed functions
   *avbin_init           = GetFunction(0, "avbin_init")
   *avbin_open_filename  = GetFunction(0, "avbin_open_filename")
   *avbin_file_info      = GetFunction(0, "avbin_file_info")
   *avbin_stream_info    = GetFunction(0, "avbin_stream_info")
   *avbin_open_stream    = GetFunction(0, "avbin_open_stream")
   *avbin_read           = GetFunction(0, "avbin_read")
   *avbin_decode_audio   = GetFunction(0, "avbin_decode_audio")
   *avbin_decode_video   = GetFunction(0, "avbin_decode_video")
   *avbin_close_stream   = GetFunction(0, "avbin_close_stream")
   *avbin_close_file     = GetFunction(0, "avbin_close_file")
   
   ; check if everything is ok..
   If *avbin_init And *avbin_open_filename  And *avbin_file_info  And *avbin_stream_info And *avbin_open_stream 
      If *avbin_read  And *avbin_decode_audio And *avbin_decode_video
         If *avbin_close_stream And *avbin_close_file
            
            ; init avbin
            *avbinresult = CallFunctionFast(*avbin_init)
            
            ; avbin open file and info
            *avbinfile._AVBinFile         = CallFunctionFast(*avbin_open_filename, testfile.s)
            *AVBinFileInfo._AVbinFileInfo = AllocateMemory(SizeOf(_AVbinFileInfo))
            *AVBinFileInfo\size_t         = SizeOf(_AVbinFileInfo)
            CallFunctionFast(*avbin_file_info, *AVBinFile, *AVBinFileInfo)            
            
            ; checkout if stream(s) available
            If *AVBinFileInfo\n_streams>0               
               
               ; check starttime, duration and totaltime..
               st.d  = *AVBinFileInfo\starttime
               dr.d  = *AVBinFileInfo\duration 
               tot.d = st+dr
               st.d  = 0            
               tk.d  = GetTickCount_()
               
               ; allocate memory avbin structures
               If *AVBinPacket._AVBinPacket   = 0
                  *AVBinPacket._AVBinPacket   = AllocateMemory(SizeOf(_AVbinPacket))
                  *AVBinPacket\structure_size = SizeOf(_AVbinPacket)
               EndIf
               If *AVBinStreamInfo._AVBinStreamInfo = 0
                  *AVBinStreamInfo._AVBinStreamInfo = AllocateMemory(SizeOf(_AVbinStreamInfo))
                  *AVBinStreamInfo\structuresize    = SizeOf(_AVbinStreamInfo)
               EndIf
               
               ; examine available streams
               For a = 0 To *AVBinFileInfo\n_streams-1
                  
                  ; get stream info
                  CallFunctionFast(*avbin_stream_info, *AVBinFile, a, *AVBinStreamInfo)
                  
                  ; video stream
                  If *AVBinStreamInfo\AVBinStreamType = 1
                     If IsImage(0)=0
                        CreateImage(0,*AVBinStreamInfo\width,*AVBinStreamInfo\height, 32)                                   
                        ResizeWindow(0, WindowX(0)-(*AVBinStreamInfo\width/2), WindowY(0)-(*AVBinStreamInfo\height/2), *AVBinStreamInfo\width, *AVBinStreamInfo\height)
                        *image = AllocateMemory((*AVBinStreamInfo\width * *AVBinStreamInfo\height) * 3)
                     EndIf
                     If *AVBinStream._AVBinStream = 0
                        *AVbinStream._AVBinStream = CallFunctionFast(*avbin_open_stream, *avbinfile, a)
                        video = a
                     EndIf
                  EndIf
                  
                  ; audio stream
                  If *AVBinStreamInfo\AVBinStreamType = 2
                     If *AVBinStream1._AVBinStream    = 0
                        *AVbinStream1._AVBinStream    = CallFunctionFast(*avbin_open_stream, *avbinfile, a)
                        audio=a
                        If *audio = 0
                           *audio = AllocateMemory(CallFunction(0, "avbin_get_audio_buffer_size"))
                           *size  = AllocateMemory(4)
                        EndIf
                     EndIf                                                       	
                  EndIf
               Next
               
               ; program loop..
               ; --------------
               While st<tot And wevent<>#PB_Event_CloseWindow 
                  
                  ; windowevents
                  wevent=WindowEvent()         
                  
                  ; it might be showtime
                  If st.d >= ts.d And wevent<>#PB_Event_CloseWindow
                     
                     ; read a packet
                     CallFunctionFast(*avbin_read, *avbinfile, *AVBinPacket)
                     
                     ; video packet
                     If *avbinpacket\size And *avbinpacket\streamindex=video 
                        ts.d = *AVBinPacket\timestamp
                        bytesused.l = CallFunctionFast(*avbin_decode_video, *AVbinStream, *AVBinPacket\dat, *avbinpacket\size, *image)                             
                        If bytesused
                           If st.d = 0 
                              st.d = *AVBinPacket\timestamp+10
                           EndIf
                           
                           ; reverse memory, needed to correct image but VERY SLOW!!!!!!! comment to disable
                           ReverseMemoryB(*image, (*AVBinStreamInfo\width * *AVBinStreamInfo\height) * 3)                                                        
                           
                           IW = *AVBinStreamInfo\width
                           IH = *AVBinStreamInfo\height
                           bmi.BITMAPINFO
                           bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
                           bmi\bmiHeader\biWidth = IW
                           bmi\bmiHeader\biHeight = IH
                           bmi\bmiHeader\biPlanes = 1
                           bmi\bmiHeader\biBitCount = 24
                           bmi\bmiHeader\biCompression = #BI_RGB                                  
                           hdc = StartDrawing(ImageOutput(0))
                              SetDIBits_(hdc,ImageID(0),0,IH,*image,bmi,#DIB_RGB_COLORS) 
                           StopDrawing()
                           ; flip image and blit (draw to window)  
                           ImageFlipH(0) 
                        EndIf
                     EndIf  
                     
                     ; audio packet
                     If *avbinpacket\size And *avbinpacket\streamindex=audio
                        ;bytesused1.l = CallFunction(0, "avcodec_decode_audio2", *AVBinStream1\codec_context, *AVBinPacket\dat, Str(*AVBinPacket\size), *audio, *size)
                        ;bytesused1.l = CallFunctionFast(*avbin_decode_audio, *AVBinStream1, *AVBinPacket\dat, *avbinpacket\size, *audio, *size)                             
                        ;Debug bytesused1
                        ;If bytesused1
                        ;   If st.d = 0 
                        ;      st.d = *AVBinPacket\timestamp+10
                        ;   EndIf
                        ;   Debug bytesused1                               
                        ;EndIf
                     EndIf  
                  EndIf
                  
                  ; delay
                  Delay(1)
                  
                  ; timing..
                  tk1.d =GetTickCount_() 
                  If tk1.d-tk.d>=102.4
                     If st.d>0
                        st.d + (tk1.d-tk.d)*1024
                     EndIf
                     tk.d=tk1.d
                  EndIf

               Wend
               
               ; free
               If *AVBinStreamInfo
                  FreeMemory(*AVBinStreamInfo)
               EndIf
               If *AVBinPacket
                  FreeMemory(*AVBinPacket)
               EndIf
               If IsImage(0)>0
                  FreeImage(0)
                  FreeMemory(*image)
                  CloseWindow(0)
               EndIf
               If *avbinstream
                  CallFunctionFast(*avbin_close_stream, *avbinstream)
               EndIf
               If *AVBinStream1
                  CallFunctionFast(*avbin_close_stream, *avbinstream1)
               EndIf
            EndIf               
            CallFunctionFast(*avbin_close_file, *avbinfile)        
         Else
            Debug "AVBIN: Closing functions fail.."
         EndIf
      Else
         Debug "AVBIN: Decode and reading functions fail.."
      EndIf
   Else
      Debug "AVBIN: Init and opening functions fail.."
   EndIf
   CloseLibrary(0)
EndIf
End

Posted: Sun Nov 23, 2008 3:37 pm
by inc.
Best Y Axis flipping is done via GetDIBits using a BitmapInfo Structure including biHeight set as negative:

bmi\bmiHeader\biHeight = -IH

So dont flip the image itself, but only the rgb resulting imagedata out of the libav function and copy it directly into the PB-Image using the (negative-height)-method as mentioned above.

As u're using GDI for displaying graphics, you should try using Directdraw, because you can handle a YV12 resulting image out of Libavcodec! Means: native Pixelformat, less size and fast image display using a direct YV12 Overlay!
http://www.purebasic.fr/english/viewtop ... 898#202898

Posted: Sun Nov 23, 2008 4:43 pm
by Philippe-felixer76-2
inc. wrote:Best Y Axis flipping is done via GetDIBits using a BitmapInfo Structure including biHeight set as negative:

bmi\bmiHeader\biHeight = -IH

So dont flip the image itself, but only the rgb resulting imagedata out of the libav function and copy it directly into the PB-Image using the (negative-height)-method as mentioned above.

As u're using GDI for displaying graphics, you should try using Directdraw, because you can handle a YV12 resulting image out of Libavcodec! Means: native Pixelformat, less size and fast image display using a direct YV12 Overlay!
http://www.purebasic.fr/english/viewtop ... 898#202898
Tnx for the input inc. The RGB seems to be BGR also..

I already checked out using GDI, but i'm not used to it, i totally
understand what you mean. You are totally right. I won't know
how to copy image data directly, but ill investigate..

I just updated the display method to use screenoutput and
using -IH in de bitmapheader:

Code: Select all


; Add InitSprite() in beginning..

; Add this procedure:

Procedure GetRenderTargetDDS();returns the DirectDrawSurface of the target buffer set with UseBuffer()
!extrn _PB_Sprite_CurrentBitmap
!MOV Eax,[_PB_Sprite_CurrentBitmap]
ProcedureReturn
EndProcedure

; Change display code with this:

                  ; video stream
                  If *AVBinStreamInfo\AVBinStreamType = 1
                     If IsImage(0)=0
                        CreateImage(0,*AVBinStreamInfo\width,*AVBinStreamInfo\height, 32)                                   
                        ResizeWindow(0, WindowX(0)-(*AVBinStreamInfo\width/2), WindowY(0)-(*AVBinStreamInfo\height/2), *AVBinStreamInfo\width, *AVBinStreamInfo\height)

                        OpenWindowedScreen(WindowID(0), 0, 0, *AVBinStreamInfo\width,*AVBinStreamInfo\height, 0, 0, 0)
                        *RenderTargetDDS.IDirectDrawSurface7=GetRenderTargetDDS()
                        
                        *image = AllocateMemory((*AVBinStreamInfo\width * *AVBinStreamInfo\height) * 3)
                     EndIf
                     If *AVBinStream._AVBinStream = 0
                        *AVbinStream._AVBinStream = CallFunctionFast(*avbin_open_stream, *avbinfile, a)
                        video = a
                     EndIf
                  EndIf


                     ; video packet
                     If *avbinpacket\size And *avbinpacket\streamindex=video 
                        ts.d = *AVBinPacket\timestamp
                        bytesused.l = CallFunctionFast(*avbin_decode_video, *AVbinStream, *AVBinPacket\dat, *avbinpacket\size, *image)                             
                        If bytesused
                           If st.d = 0 
                              st.d = *AVBinPacket\timestamp+10
                           EndIf
                           
                           ;; reversememory, needed to correct image but VERY SLOW!!!!!!! comment to disable
                           ;ReverseMemoryB(*image, (*AVBinStreamInfo\width * *AVBinStreamInfo\height) * 3)                                                        
                           
                           IW = *AVBinStreamInfo\width
                           IH = *AVBinStreamInfo\height
                           bmi.BITMAPINFO
                           bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
                           bmi\bmiHeader\biWidth = IW
                           bmi\bmiHeader\biHeight = -IH
                           bmi\bmiHeader\biPlanes = 1
                           bmi\bmiHeader\biBitCount = 24
                           bmi\bmiHeader\biCompression = #BI_RGB                                  
                           
                           ClearScreen(RGB(0,0,0))
                           *RenderTargetDDS\GetDC(@TargetDC)
                           SrcDC=StartDrawing(ImageOutput(0))
                              SetDIBits_(SrcDC,ImageID(0),0,IH,*image,bmi,#DIB_RGB_COLORS)
                              ; uncomment when reversememoryB is not used                              
                              BitBlt_(TargetDC, 0, 0, IW, IH, SrcDC, 0, 0, #SRCCOPY) ;;blt_()
                              ; uncomment when reversememoryB is used
                              ;StretchBlt_(TargetDC, 0, 0, IW, IH, SrcDC, IW, IH, -IW, -IH, #SRCCOPY)
                           StopDrawing()
                           *RenderTargetDDS\ReleaseDC(TargetDC);                          
                           FlipBuffers()
                        EndIf
                     EndIf  

It's quit a bit faster then before already.
But the audio stream packets are still a problem..

Gr,
Phil.

Posted: Sun Nov 23, 2008 6:28 pm
by inc.
The RGB seems to be BGR also..
Thats the Type of the alignment and not an axis thing.

Also ... if you can choose ... always do choose RGB32 as outputformat if rgb is choosen for later screen display. Many graphic cards do not support 24bit that easy and 32bit is handled perfectly by any hardware.

Posted: Sun Nov 23, 2008 7:27 pm
by Philippe-felixer76-2
inc. wrote:
The RGB seems to be BGR also..
Thats the Type of the alignment and not an axis thing.

Also ... if you can choose ... always do choose RGB32 as outputformat if rgb is choosen for later screen display. Many graphic cards do not support 24bit that easy and 32bit is handled perfectly by any hardware.
Tnx inc..

I guess i need to open directdraw with

ddsd\ddpfPixelFormat\dwFlags=#DDPF_RGB
ddsd\ddpfPixelFormat\dwRGBBitCount = 32
ddsd\ddpfPixelFormat\dwRBitMask = $000000FF
ddsd\ddpfPixelFormat\dwGBitMask = $0000FF00
ddsd\ddpfPixelFormat\dwBBitMask = $00FF0000

And find some way to copy/blit image data directly.

But i'm not experienced with it.. :(

Gr,
Phil.

Posted: Sun Nov 23, 2008 8:06 pm
by inc.
Just have a look at my Image data writing part of the given example further above of the code in the link.

The logic is, to get the directdraw surface pointer where you have to copy the image data to.
But as said: If you choose DirectDraw, best choice is to let your libav procedures output a YV12 picture as its also the native image format of 99% of the resulting formats out of libavcodec, means xvid, h264, divx, etc etc etc., so no colorspace conversion, therefore no imagequality loss and accelerated by the users graphics hardware! :)

Posted: Sun Nov 23, 2008 9:10 pm
by Philippe-felixer76-2
inc. wrote:Just have a look at my Image data writing part of the given example further above of the code in the link.

The logic is, to get the directdraw surface pointer where you have to copy the image data to.
But as said: If you choose DirectDraw, best choice is to let your libav procedures output a YV12 picture as its also the native image format of 99% of the resulting formats out of libavcodec, means xvid, h264, divx, etc etc etc., so no colorspace conversion, therefore no imagequality loss and accelerated by the users graphics hardware! :)
You mean like:

CallFunctionFast(*avbin_decode_video, *AVbinStream, *AVBinPacket\dat, *avbinpacket\size, ddsd\lpSurface)

Update:
I already tried some stuff, and it seems to work, but i
can't get ddsd\ddpfPixelFormat\dwFlags=#DDPF_RGB
to work.. i get a Failed: YUV Surface..

Gr,
Phil.

Posted: Sun Nov 23, 2008 9:50 pm
by Philippe-felixer76-2
Philippe-felixer76-2 wrote:
inc. wrote:Just have a look at my Image data writing part of the given example further above of the code in the link.

The logic is, to get the directdraw surface pointer where you have to copy the image data to.
But as said: If you choose DirectDraw, best choice is to let your libav procedures output a YV12 picture as its also the native image format of 99% of the resulting formats out of libavcodec, means xvid, h264, divx, etc etc etc., so no colorspace conversion, therefore no imagequality loss and accelerated by the users graphics hardware! :)
You mean like:

CallFunctionFast(*avbin_decode_video, *AVbinStream, *AVBinPacket\dat, *avbinpacket\size, ddsd\lpSurface)

Update:
I already tried some stuff, and it seems to work, but i
can't get ddsd\ddpfPixelFormat\dwFlags=#DDPF_RGB
to work.. i get a Failed: YUV Surface.. I like to use
YV12 but AVBin just gives me this 24 BGR data.

Gr,
Phil.

DVBin update

Posted: Mon Nov 24, 2008 12:26 pm
by Philippe-felixer76-2
Here's my latest attempt, i used libavformat commands
to decode and convert the image to usable colorspace,
it's very fast now on my setup.

Im also working on a DVBin/DirectDraw experiment, using
YUV native output, and i already have accelerated video
output, but it looks like crap at the moment ;-)

Code: Select all

; AVBin For PureBasic (attempt)
; -------------------
; v 181108 decoding frames from video streams
; v 181108 Display video frames in 24 bit RGB format
; v 211108 Simple video timing
; v 221108 Faster video display using screenoutput
; v 231108 Faster video converting colorspace with libav commands
; - 211108 Audio testing, having real problems here

; structures
Structure _AVbinFileInfo
   size_t.l
   n_streams.l
   starttime.q
   duration.q
   title.c[512]
   author.c[512]
   copyright.c[512]
   comment.c[512]
   album.c[512]
   year.l
   track.l
   genre.c[32]
EndStructure
Structure _AVbinStreamInfo
   structuresize.l     ; size
   AVBinStreamType.l   ; 0 (unknown),1 (video) of 2 (audio)
   width.l             ; or avbinsampleformat
   height.l            ; or samplerate 
   sample_aspect_num.l ; or sample_bits
   sample_aspect_den.l ; or channels
EndStructure
Structure _AVbinPacket
   structure_size.q    ; why quad?
   timestamp.q         ; timestamp uint64_t
   streamindex.l       ; int 
   *dat.l              ; long 
   size.q              ; why quad?
EndStructure
; test
Structure _AVbinFile 
    *context           ;AVFormatContext *context;
    *packet            ;AVPacket *packet;
EndStructure
Structure _AVBinStream
    type.l             ;int type;
    *format_context    ;AVFormatContext *format_context;
    *codec_context     ;AVCodecContext *codec_context;
    *frame             ;AVFrame *frame;   
EndStructure

; procedures
Procedure GetRenderTargetDDS();returns the DirectDrawSurface of the target buffer set with UseBuffer()
!extrn _PB_Sprite_CurrentBitmap
!MOV Eax,[_PB_Sprite_CurrentBitmap]
ProcedureReturn
EndProcedure

; test video file, please adjust to your needs...
testfile.s = "F:\bb.20080116.asf"

; window
InitSprite()
OpenWindow(0,0,0,10,10 ,"AVBIN - (FFMPEG) Libavcodec/Libavformat WRAPPER",#WS_SYSMENU|1)

; open avbin and video file
If OpenLibrary(0, "avbin.dll") And (FileSize(testfile.s)>0)
   
   ; get all needed functions
   *avbin_init           = GetFunction(0, "avbin_init")
   *avbin_open_filename  = GetFunction(0, "avbin_open_filename")
   *avbin_file_info      = GetFunction(0, "avbin_file_info")
   *avbin_stream_info    = GetFunction(0, "avbin_stream_info")
   *avbin_open_stream    = GetFunction(0, "avbin_open_stream")
   *avbin_read           = GetFunction(0, "avbin_read")
   *avbin_decode_audio   = GetFunction(0, "avbin_decode_audio")
   *avbin_decode_video   = GetFunction(0, "avbin_decode_video")
   *avbin_close_stream   = GetFunction(0, "avbin_close_stream")
   *avbin_close_file     = GetFunction(0, "avbin_close_file")
   ; get libavcodec funtions..
   *avcodec_decode_video = GetFunction(0, "avcodec_decode_video")
   *avpicture_fill       = GetFunction(0, "avpicture_fill")
   *img_convert          = GetFunction(0, "img_convert")
        
   ; check if everything is ok..
   If *avbin_init And *avbin_open_filename  And *avbin_file_info  And *avbin_stream_info And *avbin_open_stream 
      If *avbin_read  And *avbin_decode_audio And *avbin_decode_video
         If *avbin_close_stream And *avbin_close_file
            
            ; init avbin
            *avbinresult = CallFunctionFast(*avbin_init)
            
            ; avbin open file and info
            *avbinfile._AVBinFile         = CallFunctionFast(*avbin_open_filename, testfile.s)
            *AVBinFileInfo._AVbinFileInfo = AllocateMemory(SizeOf(_AVbinFileInfo))
            *AVBinFileInfo\size_t         = SizeOf(_AVbinFileInfo)
            CallFunctionFast(*avbin_file_info, *AVBinFile, *AVBinFileInfo)            
            
            ; checkout if stream(s) available
            If *AVBinFileInfo\n_streams>0               
               
               ; check starttime, duration and totaltime..
               st.d  = *AVBinFileInfo\starttime
               dr.d  = *AVBinFileInfo\duration 
               tot.d = st+dr
               st.d  = 0            
               tk.d  = GetTickCount_()
               
               ; allocate memory avbin structures
               If *AVBinPacket._AVBinPacket   = 0
                  *AVBinPacket._AVBinPacket   = AllocateMemory(SizeOf(_AVbinPacket))
                  *AVBinPacket\structure_size = SizeOf(_AVbinPacket)
               EndIf
               If *AVBinStreamInfo._AVBinStreamInfo = 0
                  *AVBinStreamInfo._AVBinStreamInfo = AllocateMemory(SizeOf(_AVbinStreamInfo))
                  *AVBinStreamInfo\structuresize    = SizeOf(_AVbinStreamInfo)
               EndIf
               
               ; examine available streams
               For a = 0 To *AVBinFileInfo\n_streams-1
                  
                  ; get stream info
                  CallFunctionFast(*avbin_stream_info, *AVBinFile, a, *AVBinStreamInfo)
                  
                  ; video stream
                  If *AVBinStreamInfo\AVBinStreamType = 1
                     If IsImage(0)=0
                        CreateImage(0,*AVBinStreamInfo\width,*AVBinStreamInfo\height, 32)                                   
                        ResizeWindow(0, WindowX(0)-(*AVBinStreamInfo\width/2), WindowY(0)-(*AVBinStreamInfo\height/2), *AVBinStreamInfo\width, *AVBinStreamInfo\height)
                        OpenWindowedScreen(WindowID(0), 0, 0, *AVBinStreamInfo\width,*AVBinStreamInfo\height, 0, 0, 0)
                        *RenderTargetDDS.IDirectDrawSurface7=GetRenderTargetDDS()                       
                        *image = AllocateMemory((*AVBinStreamInfo\width * *AVBinStreamInfo\height) * 3)
                     EndIf
                     If *AVBinStream._AVBinStream = 0
                        *AVBinStream._AVBinStream = AllocateMemory(SizeOf(_AVBinStream))
                        *AVbinStream._AVBinStream = CallFunctionFast(*avbin_open_stream, *avbinfile, a)
                        video = a
                     EndIf
                  EndIf
                  
                  ; audio stream
                  If *AVBinStreamInfo\AVBinStreamType = 2
                     If *AVBinStream1._AVBinStream    = 0
                        *AVbinStream1._AVBinStream    = CallFunctionFast(*avbin_open_stream, *avbinfile, a)
                        audio=a
                        Structure align
                           i.l
                           i1.l
                        EndStructure
                        If *audio.align = 0
                           *audio.align = AllocateMemory(CallFunction(0, "avbin_get_audio_buffer_size"))
                           *size  = AllocateMemory(4)
                           s.l = CallFunction(0, "avbin_get_audio_buffer_size") ;MemorySize(*audio)
                        EndIf
                     EndIf                                                       	
                  EndIf
               Next
               
               ; program loop..
               ; --------------
               While st<tot And wevent<>#PB_Event_CloseWindow 
                  
                  ; windowevents
                  wevent=WindowEvent()         
                  
                  ; it might be showtime
                  If st.d >= ts.d And wevent<>#PB_Event_CloseWindow
                     
                     ; read a packet
                     CallFunctionFast(*avbin_read, *avbinfile, *AVBinPacket)

                     ; video packet
                     If *avbinpacket\size And *avbinpacket\streamindex=video ;becomes 0???!!!! 
                        ts.d = *AVBinPacket\timestamp
                        bytesused.l = CallFunctionFast(*avcodec_decode_video, *AVbinStream\codec_context, *AVbinStream\frame, @pic.l, *AVBinPacket\dat, *avbinpacket\size)                         
                        If bytesused
                           If st.d = 0 
                              st.d = *AVBinPacket\timestamp+10
                           EndIf
                           ; do the picture fill 
                           CallFunctionFast(*avpicture_fill, @p,  *image, 3, *AVBinStreamInfo\width, *AVBinStreamInfo\height)                          
                           ; convert YU12 to BGR (Wich is RGB..)
                           CallFunctionFast(*img_convert, @p, 3,*AVBinStream\frame, 0, *AVBinStreamInfo\width, *AVBinStreamInfo\height)
                           video=1 ; strange video is set to 0 after avpicture_fill
                           IW = *AVBinStreamInfo\width
                           IH = *AVBinStreamInfo\height
                           bmi.BITMAPINFO
                           bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
                           bmi\bmiHeader\biWidth = IW
                           bmi\bmiHeader\biHeight = -IH ; Flip image
                           bmi\bmiHeader\biPlanes = 1
                           bmi\bmiHeader\biBitCount = 24
                           bmi\bmiHeader\biCompression = #BI_RGB  
                           ; Draw the frame                                
                           *RenderTargetDDS\GetDC(@TargetDC)
                           SrcDC=StartDrawing(ImageOutput(0))
                              SetDIBits_(SrcDC,ImageID(0),0,IH,*image,bmi,#DIB_RGB_COLORS)
                              BitBlt_(TargetDC, 0, 0, IW, IH, SrcDC, 0, 0, #SRCCOPY) 
                           StopDrawing()
                           *RenderTargetDDS\ReleaseDC(TargetDC);                          
                           FlipBuffers()
                        EndIf
                     EndIf  
                     
                     ; audio packet
                     If *avbinpacket\size And *avbinpacket\streamindex=audio
                        ;bytesused1.l = CallFunction(0, "avcodec_decode_audio2", *AVBinStream1\codec_context,  *audio, @si.l, *AVBinPacket\dat, *AVBinPacket\size)
                        ;bytesused1.l = CallFunctionFast(*avbin_decode_audio, *AVBinStream1, *AVBinPacket\dat, *avbinpacket\size, *audio, *size)                             
                        ;Debug bytesused1
                        ;If bytesused1
                        ;   If st.d = 0 
                        ;      st.d = *AVBinPacket\timestamp+10
                        ;   EndIf
                        ;   Debug bytesused1                               
                        ;EndIf
                     EndIf  
                  EndIf
                  
                  ; delay
                  Delay(1)
                  
                  ; timing..
                  tk1.d =GetTickCount_() 
                  If tk1.d-tk.d>=102.4
                     If st.d>0
                        st.d + (tk1.d-tk.d)*1024
                     EndIf
                     tk.d=tk1.d
                  EndIf

               Wend
               
               ; free
               If *AVBinStreamInfo
                  FreeMemory(*AVBinStreamInfo)
               EndIf
               If *AVBinPacket
                  FreeMemory(*AVBinPacket)
               EndIf
               If IsImage(0)>0
                  FreeImage(0)
                  FreeMemory(*image)
                  CloseWindow(0)
               EndIf
               If *avbinstream
                  CallFunctionFast(*avbin_close_stream, *avbinstream)
               EndIf
               If *AVBinStream1
                  CallFunctionFast(*avbin_close_stream, *avbinstream1)
               EndIf
            EndIf               
            CallFunctionFast(*avbin_close_file, *avbinfile)        
         Else
            Debug "AVBIN: Closing functions fail.."
         EndIf
      Else
         Debug "AVBIN: Decode and reading functions fail.."
      EndIf
   Else
      Debug "AVBIN: Init and opening functions fail.."
   EndIf
   CloseLibrary(0)
EndIf
End


Posted: Mon Nov 24, 2008 12:27 pm
by inc.
Philippe-felixer76-2 wrote: I already tried some stuff, and it seems to work, but i
can't get ddsd\ddpfPixelFormat\dwFlags=#DDPF_RGB
to work.. i get a Failed: YUV Surface.
Does the example of my DirectDraw include work on your system?

Posted: Mon Nov 24, 2008 12:59 pm
by Philippe-felixer76-2
inc. wrote:
Philippe-felixer76-2 wrote: I already tried some stuff, and it seems to work, but i
can't get ddsd\ddpfPixelFormat\dwFlags=#DDPF_RGB
to work.. i get a Failed: YUV Surface.
Does the example of my DirectDraw include work on your system?
It works in YV12 mode.. It doesn't work when i set #YV12 to false.

Gr,
Phil.

Posted: Mon Nov 24, 2008 10:49 pm
by inc.
Maybe you're feeding the RGB32 Surface using a RGB24 Picture out of AVCodec?

Posted: Mon Nov 24, 2008 11:13 pm
by Philippe-felixer76-2
inc. wrote:Maybe you're feeding the RGB32 Surface using a RGB24 Picture out of AVCodec?
Talking about your plain example, It works only in YV12 mode on
my setup.

I currently working on experiment to display frames in
YV12 mode, it does show output, but is very strange,
mabe you could help?


And i'm not feeding a rgb32 surface in this experiment..

Gr,
Phil.

AVBin

Posted: Sun Nov 30, 2008 5:41 pm
by Philippe-felixer76-2
I recompiled and changed the AVBin dll (win32 only) for better use with PureBasic.

These functions changed:

from:

int avbin_decode_video(AVbinStream *stream,
uint8_t *data_in, size_t size_in,
uint8_t *data_out);

to:

int avbin_decode_video(AVbinStream *stream,
AVbinFile *file,
uint8_t *data_out,
int RGB)

from:

int avbin_decode_audio(AVbinStream *stream,
uint8_t *data_in, size_t size_in,
uint8_t *data_out, int *size_out);

to:

int avbin_decode_audio(AVbinStream *stream,
AVbinFile *file,
uint8_t *data_out, int *size_out);

Using this version of AVBin with PB gives positive results in
decoding audio packets.

RGB option in the video decode function is added, with this
option you can decode a frame to specified RGB output.

RGB enum:

PIX_FMT_NONE = -1, PIX_FMT_YUV420P, PIX_FMT_YUYV422, PIX_FMT_RGB24,
PIX_FMT_BGR24, PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_RGB32,
PIX_FMT_YUV410P, PIX_FMT_YUV411P, PIX_FMT_RGB565, PIX_FMT_RGB555,
PIX_FMT_GRAY8, PIX_FMT_MONOWHITE, PIX_FMT_MONOBLACK, PIX_FMT_PAL8,
PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ444P, PIX_FMT_XVMC_MPEG2_MC,
PIX_FMT_XVMC_MPEG2_IDCT, PIX_FMT_UYVY422, PIX_FMT_UYYVYY411, PIX_FMT_BGR32,
PIX_FMT_BGR565, PIX_FMT_BGR555, PIX_FMT_BGR8, PIX_FMT_BGR4,
PIX_FMT_BGR4_BYTE, PIX_FMT_RGB8, PIX_FMT_RGB4, PIX_FMT_RGB4_BYTE,
PIX_FMT_NV12, PIX_FMT_NV21, PIX_FMT_RGB32_1, PIX_FMT_BGR32_1,
PIX_FMT_GRAY16BE, PIX_FMT_GRAY16LE, PIX_FMT_NB

Dll: http://members.chello.nl/p.calsteren/avbin.zip

Basic example:

Code: Select all

; AVBin For PureBasic (attempt)
; -------------------
; v 181108 decoding frames from video streams
; v 181108 Display video frames in 24 bit RGB format
; v 211108 Simple video timing
; v 221108 Faster video display using screenoutput
; v 201108 Recompiled and changed AVBin library

; structures
Structure _AVbinFileInfo
   size_t.l
   n_streams.l
   starttime.q
   duration.q
   title.c[512]
   author.c[512]
   copyright.c[512]
   comment.c[512]
   album.c[512]
   year.l
   track.l
   genre.c[32]
EndStructure
Structure _AVbinStreamInfo
   structuresize.l     ; size
   AVBinStreamType.l   ; 0 (unknown),1 (video) of 2 (audio)
   width.l             ; or avbinsampleformat
   height.l            ; or samplerate 
   sample_aspect_num.l ; or sample_bits
   sample_aspect_den.l ; or channels
EndStructure
Structure _AVbinPacket
   structure_size.q    ; why quad?
   timestamp.q         ; timestamp uint64_t
   streamindex.l       ; int 
   *dat.l              ; long 
   size.q              ; why quad?
EndStructure
Structure _AVbinFile 
    *context           ;AVFormatContext *context;
    *packet            ;AVPacket *packet;
EndStructure
Structure _AVBinStream
    type.l             ;int type;
    *format_context    ;AVFormatContext *format_context;
    *codec_context     ;AVCodecContext *codec_context;
    *frame             ;AVFrame *frame;   
EndStructure

; procedures
Procedure GetRenderTargetDDS();returns the DirectDrawSurface of the target buffer set with UseBuffer()
!extrn _PB_Sprite_CurrentBitmap
!MOV Eax,[_PB_Sprite_CurrentBitmap]
ProcedureReturn
EndProcedure

; test video file, please adjust to your needs...
testfile.s = "F:\bb.20080116.asf"

InitSprite()
OpenWindow(0,0,0,10,10 ,"AVBIN - (FFMPEG) Libavcodec/Libavformat WRAPPER",#WS_SYSMENU|1)

; open avbin and video file
If OpenLibrary(0, "avbin.dll") And (FileSize(testfile.s)>0)
   
   ; get all needed functions
   *avbin_init           = GetFunction(0, "avbin_init")
   *avbin_open_filename  = GetFunction(0, "avbin_open_filename")
   *avbin_file_info      = GetFunction(0, "avbin_file_info")
   *avbin_stream_info    = GetFunction(0, "avbin_stream_info")
   *avbin_open_stream    = GetFunction(0, "avbin_open_stream")
   *avbin_read           = GetFunction(0, "avbin_read")
   *avbin_decode_audio   = GetFunction(0, "avbin_decode_audio")
   *avbin_decode_video   = GetFunction(0, "avbin_decode_video")
   *avbin_close_stream   = GetFunction(0, "avbin_close_stream")
   *avbin_close_file     = GetFunction(0, "avbin_close_file")
        
   ; check if everything is ok..
   If *avbin_init And *avbin_open_filename  And *avbin_file_info  And *avbin_stream_info And *avbin_open_stream 
      If *avbin_read  And *avbin_decode_audio And *avbin_decode_video
         If *avbin_close_stream And *avbin_close_file
            
            ; init avbin
            *avbinresult = CallFunctionFast(*avbin_init)
            
            ; avbin open file and info
            *avbinfile._AVBinFile         = CallFunctionFast(*avbin_open_filename, testfile.s)
            *AVBinFileInfo._AVbinFileInfo = AllocateMemory(SizeOf(_AVbinFileInfo))
            *AVBinFileInfo\size_t         = SizeOf(_AVbinFileInfo)
            CallFunctionFast(*avbin_file_info, *AVBinFile, *AVBinFileInfo)            
            
            ; checkout if stream(s) available
            If *AVBinFileInfo\n_streams>0               
               
               ; check starttime, duration and totaltime..
               st.d  = *AVBinFileInfo\starttime
               dr.d  = *AVBinFileInfo\duration 
               tot.d = st+dr
               st.d  = 0            
               tk.d  = GetTickCount_()
               
               ; allocate memory avbin structures
               If *AVBinPacket._AVBinPacket   = 0
                  *AVBinPacket._AVBinPacket   = AllocateMemory(SizeOf(_AVbinPacket))
                  *AVBinPacket\structure_size = SizeOf(_AVbinPacket)
               EndIf
               If *AVBinStreamInfo._AVBinStreamInfo = 0
                  *AVBinStreamInfo._AVBinStreamInfo = AllocateMemory(SizeOf(_AVbinStreamInfo))
                  *AVBinStreamInfo\structuresize    = SizeOf(_AVbinStreamInfo)
               EndIf
               
               ; examine available streams
               For a = 0 To *AVBinFileInfo\n_streams-1
                  
                  ; get stream info
                  CallFunctionFast(*avbin_stream_info, *AVBinFile, a, *AVBinStreamInfo)
                  
                  ; video stream
                  If *AVBinStreamInfo\AVBinStreamType = 1
                     If IsImage(0)=0
                        CreateImage(0,*AVBinStreamInfo\width,*AVBinStreamInfo\height, 32)                                   
                        ResizeWindow(0, WindowX(0)-(*AVBinStreamInfo\width/2), WindowY(0)-(*AVBinStreamInfo\height/2), *AVBinStreamInfo\width, *AVBinStreamInfo\height)
                        OpenWindowedScreen(WindowID(0), 0, 0, *AVBinStreamInfo\width,*AVBinStreamInfo\height, 0, 0, 0)
                        *RenderTargetDDS.IDirectDrawSurface7=GetRenderTargetDDS()                       
                        *image = AllocateMemory((*AVBinStreamInfo\width * *AVBinStreamInfo\height) * 3)
                     EndIf
                     If *AVBinStream._AVBinStream = 0
                        *AVbinStream._AVBinStream = CallFunctionFast(*avbin_open_stream, *avbinfile, a)
                        video = a
                     EndIf
                  EndIf
                  
                  ; audio stream
                  If *AVBinStreamInfo\AVBinStreamType = 2
                     If *AVBinStream1._AVBinStream    = 0
                        *AVbinStream1._AVBinStream    = CallFunctionFast(*avbin_open_stream, *avbinfile, a)
                        audio=a
                        #AVCODEC_MAX_AUDIO_FRAME_SIZE = 131072
                        s.l = CallFunction(0, "avbin_get_audio_buffer_size")*2
                        *audio = AllocateMemory(s) 
                     EndIf                                                       	
                  EndIf
                  
               Next
               
               ; program loop..
               ; --------------
               While st<tot And wevent<>#PB_Event_CloseWindow 
                  
                  ; windowevents
                  wevent=WindowEvent()         
                                   
                  ; it might be showtime
                  If st.d >= ts.d And wevent<>#PB_Event_CloseWindow
                     
                     ; read a packet
                     CallFunctionFast(*avbin_read, *avbinfile, *AVBinPacket)

                     ; video packet
                     If *avbinpacket\size And *avbinpacket\streamindex=video ;becomes 0???!!!! 
                        ts.d = *AVBinPacket\timestamp
                        bytesused.l = CallFunctionFast(*avbin_decode_video, *AVbinStream, *avbinfile, *image, 3)                                                    
                        If bytesused
                           If st.d = 0 
                              st.d = *AVBinPacket\timestamp+10
                           EndIf
                           IW = *AVBinStreamInfo\width
                           IH = *AVBinStreamInfo\height
                           bmi.BITMAPINFO
                           bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
                           bmi\bmiHeader\biWidth = IW
                           bmi\bmiHeader\biHeight = -IH ; Flip image
                           bmi\bmiHeader\biPlanes = 1
                           bmi\bmiHeader\biBitCount = 24
                           bmi\bmiHeader\biCompression = #BI_RGB          
                           *RenderTargetDDS\GetDC(@TargetDC)
                           SrcDC=StartDrawing(ImageOutput(0))
                              SetDIBits_(SrcDC,ImageID(0),0,IH,*image,bmi,#DIB_RGB_COLORS)
                              BitBlt_(TargetDC, 0, 0, IW, IH, SrcDC, 0, 0, #SRCCOPY) 
                           StopDrawing()
                           *RenderTargetDDS\ReleaseDC(TargetDC);                          
                           FlipBuffers()
                        EndIf
                     EndIf  
                     
                     ; audio packet
                     If *avbinpacket\size And *avbinpacket\streamindex=audio
                        s1.l = s.l
                        bytesused1.l = CallFunctionFast(*avbin_decode_audio, *AVBinStream1, *avbinfile, *audio, @s1.l)                             
                        Debug bytesused1
                     EndIf  
                  EndIf
                  
                  ; delay
                  Delay(1)
                  
                  ; timing..
                  tk1.d =GetTickCount_() 
                  If tk1.d-tk.d>=102.4
                     If st.d>0
                        st.d + (tk1.d-tk.d)*1024
                     EndIf
                     tk.d=tk1.d
                  EndIf

               Wend
               
               ; free
               If *AVBinStreamInfo
                  FreeMemory(*AVBinStreamInfo)
               EndIf
               If *AVBinPacket
                  FreeMemory(*AVBinPacket)
               EndIf
               If IsImage(0)>0
                  FreeImage(0)
                  FreeMemory(*image)
                  CloseWindow(0)
               EndIf
               If *avbinstream
                  CallFunctionFast(*avbin_close_stream, *avbinstream)
               EndIf
               If *AVBinStream1
                  CallFunctionFast(*avbin_close_stream, *avbinstream1)
               EndIf
            EndIf               
            CallFunctionFast(*avbin_close_file, *avbinfile)        
         Else
            Debug "AVBIN: Closing functions fail.."
         EndIf
      Else
         Debug "AVBIN: Decode and reading functions fail.."
      EndIf
   Else
      Debug "AVBIN: Init and opening functions fail.."
   EndIf
   CloseLibrary(0)
EndIf
End


AVBin example

Posted: Tue Dec 02, 2008 10:03 pm
by Philippe-felixer76-2
I have got so many positive responses from PB users wanting to
get the LibAVCodec/LibAVFormat, known as the not needing any
microsoft software way of using video on any OS, usable in PB.

Thank you all of those people. Most of you prommised to
send some fee to me and most already did, i now have a
brandnew car.

I have managed to blown our (LibAVMinded) vision
a bit further, this example, using the AVBIn http://members.chello.nl/p.calsteren/avbin.zip dll
i recompiled, will actualy load and decode audio and video,
and also buffer it in linked lists, and also try's to show it in
realtime. I must admit audio is single buffered, and
sounds like crap but timing seems to be very accurate.

Not all video files work, but some do..

Code: Select all

; AVBin For PureBasic (attempt)
; -------------------
; v 181108 decoding frames from video streams
; v 181108 Display video frames in 24 bit RGB format
; v 211108 Simple video timing
; v 221108 Faster video display using screenoutput
; v 281108 Audio buffering
; v 011208 Better timing.. 
; v 011208 Video buffer, linked list..
; v 011208 Audio buffer, linked list..
; v 011208 Fix bug crashed with memory problems..
; v 021208 Primitive sound output..

#buffer     = 100
#maxpackets = 1

; structures
; Timing
Structure timing
   *buffer  ; video picture if type is video or audio packet if is audio
   type.b   ; audio/video
   time.q   ; frametime, use formatdate( mask, time,q>>8 ) get some info 
   length.l ; datalength 
   done.b
EndStructure
Global NewList timing.timing()
   
; DIRECTSOUND 
#Duration   = 1 ;sek
#DSBCAPS_LOCSOFTWARE   = $8
#DSBCAPS_CTRLFREQUENCY = $20
#DSBCAPS_CTRLVOLUME    = $80
#DSBCAPS_CTRLPAN       = $40
#DSBCAPS_CTRLPOSITIONNOTIFY = $00000100
#DSBCAPS_GETCURRENTPOSITION2 =$00010000
#DSBCAPS_GLOBALFOCUS = $00008000
#DSSCL_EXCLUSIVE = 3 
#DSSCL_NORMAL = 1     
#DSSCL_PRIORITY = 2   
#DSSCL_WRITEPRIMARY = 4
#DD_OK = 0
#DS_OK = 0
#DSBPLAY_LOOPING         = $1
#DSBLOCK_FROMWRITECURSOR = $1
#DSBLOCK_ENTIREBUFFER    = $2
Structure DSBUFFERDESC
  dwSize.l           
  dwFlags.l           
  dwBufferBytes.l     
  dwReserved.l       
  *lpwfxFormat       
EndStructure
Structure DSBPOSITIONNOTIFY
  dwOffset.l;
  hEventNotify.l;
EndStructure
Structure DIRECTSOUND
  RA_DirectSound.l
  Sound.l
  Notify.l
  secBuflen.l
  nChannels.l
EndStructure
Global DX8Sound.DIRECTSOUND
; AVBin
Structure _AVbinFileInfo
   size_t.l
   n_streams.l
   starttime.q
   duration.q
   title.c[512]
   author.c[512]
   copyright.c[512]
   comment.c[512]
   album.c[512]
   year.l
   track.l
   genre.c[32]
EndStructure
Structure _AVbinStreamInfo
   structuresize.l     ; size
   AVBinStreamType.l   ; 0 (unknown),1 (video) of 2 (audio)
   width.l             ; or avbinsampleformat
   height.l            ; or samplerate 
   sample_aspect_num.l ; or sample_bits
   sample_aspect_den.l ; or channels
EndStructure
Structure _AVbinPacket
   structure_size.q    ; why quad?
   timestamp.q         ; timestamp uint64_t
   streamindex.l       ; int 
   *dat.l              ; long 
   size.q              ; why quad?
EndStructure
Structure _AVbinFile 
    *context           ;AVFormatContext *context;
    *packet            ;AVPacket *packet;
EndStructure
Structure _AVBinStream
    type.l             ;int type;
    *format_context    ;AVFormatContext *format_context;
    *codec_context     ;AVCodecContext *codec_context;
    *frame             ;AVFrame *frame;   
EndStructure

; procedures
Procedure Delete(*obj.IUnknown)
  ProcedureReturn *Obj\Release()
EndProcedure
Procedure PrepareDX8Sound (*AVBinStreamInfo._AVBinStreamInfo)
  If OpenLibrary(1,"DSOUND.DLL")
     result.l = CallFunction(1,"DirectSoundCreate8",0,@*RA_DirectSound.IDirectSound8,0)
  EndIf
  If result = #Null
     result = *RA_DirectSound\SetCooperativeLevel(WindowID(0),#DSSCL_NORMAL) ; hwnd is the WindowID
     If result.l <> #DD_OK
         Delete(*RA_DirectSound)
     Else
       dsbd.DSBUFFERDESC                       
       dsbd\dwSize        = SizeOf(DSBUFFERDESC)  
       dsbd\dwFlags       = 1              
       dsbd\dwBufferBytes = 0             
       dsbd\lpwfxFormat   = 0       
       Result.l = *RA_DirectSound\CreateSoundBuffer(@dsbd,@*pDSBPrimary.IDirectSoundBuffer,0) 
       If Result.l <> #DD_OK 
          End
       EndIf 
       wfx.WAVEFORMATEX             
       RtlZeroMemory_(@wfx,SizeOf(WAVEFORMATEX)); 
       wfx\wFormatTag      = #WAVE_FORMAT_PCM; 
       wfx\nChannels       = *AVBinStreamInfo\sample_aspect_den  
       wfx\nSamplesPerSec  = *AVBinStreamInfo\height 
       wfx\wBitsPerSample  = *AVBinStreamInfo\sample_aspect_num 
       wfx\nBlockAlign     = (wfx\wBitsPerSample / 8 * wfx\nChannels) 
       wfx\nAvgBytesPerSec = (wfx\nSamplesPerSec * wfx\nBlockAlign) 
       dsbd\dwFlags       = #DSBCAPS_LOCSOFTWARE|#DSBCAPS_CTRLVOLUME|#DSBCAPS_CTRLFREQUENCY|#DSBCAPS_CTRLPAN 
       dsbd\dwBufferBytes = 10 * wfx\nAvgBytesPerSec 
       dsbd\lpwfxFormat   = @wfx 
       result.l = *RA_DirectSound\CreateSoundBuffer(@dsbd,@*pDSB.IDirectSoundBuffer,0)
       If result.l <> #DD_OK
          Delete(*RA_DirectSound)
          Fresult = #Null
       Else
          *DSB8.IDirectSoundBuffer8 = 0
          *pDSB\QueryInterface(?IID_DirectSoundBuffer8,@*DSB8) 
          *DSN8.IDirectSoundNotify = 0
          *pDSB\QueryInterface(?IID_DirectSoundNotify8,@*DSN8)     
          Delete(*pDSB)   
          If *DSB8 = 0
             Delete(*RA_DirectSound)
          Else         
             DX8Sound\secBuflen   = #Duration * *AVBinStreamInfo\height
             DX8Sound\Sound       = *DSB8
             DX8Sound\Notify      = *DSN8
             DX8Sound\RA_DirectSound = *RA_DirectSound
             DX8Sound\nChannels = *AVBinStreamInfo\sample_aspect_den 
             FResult = *DSB8
          EndIf
       EndIf
    EndIf
 Else
    MessageRequester("Error","Please install DirectX v.8 or above",0): End
 EndIf
  If IsLibrary(1)
    CloseLibrary(1)
  EndIf
 ProcedureReturn FResult
EndProcedure
Procedure GetRenderTargetDDS();returns the DirectDrawSurface of the target buffer set with UseBuffer()
!extrn _PB_Sprite_CurrentBitmap
!MOV Eax,[_PB_Sprite_CurrentBitmap]
ProcedureReturn
EndProcedure

; test video file, please adjust to your needs...
testfile.s = OpenFileRequester("Select video", "", "*.*", 0)

; window
InitSprite()
OpenWindow(0,0,0,10,10 ,"AVBIN - (FFMPEG) Libavcodec/Libavformat WRAPPER",#WS_SYSMENU|1)

; open avbin and video file
If OpenLibrary(0, "avbin.dll") And (FileSize(testfile.s)>0)
     
   ; get all needed functions
   *avbin_init           = GetFunction(0, "avbin_init")
   *avbin_open_filename  = GetFunction(0, "avbin_open_filename")
   *avbin_file_info      = GetFunction(0, "avbin_file_info")
   *avbin_stream_info    = GetFunction(0, "avbin_stream_info")
   *avbin_open_stream    = GetFunction(0, "avbin_open_stream")
   *avbin_read           = GetFunction(0, "avbin_read")
   *avbin_decode_audio   = GetFunction(0, "avbin_decode_audio")
   *avbin_decode_video   = GetFunction(0, "avbin_decode_video")
   *avbin_close_stream   = GetFunction(0, "avbin_close_stream")
   *avbin_close_file     = GetFunction(0, "avbin_close_file")
        
   ; check if everything is ok..
   If *avbin_init And *avbin_open_filename  And *avbin_file_info  And *avbin_stream_info And *avbin_open_stream 
      If *avbin_read  And *avbin_decode_audio And *avbin_decode_video
         If *avbin_close_stream And *avbin_close_file
            
            ; init avbin
            *avbinresult = CallFunctionFast(*avbin_init)
            
            ; avbin open file and info
            *avbinfile._AVBinFile         = CallFunctionFast(*avbin_open_filename, testfile.s)
            *AVBinFileInfo._AVbinFileInfo = AllocateMemory(SizeOf(_AVbinFileInfo))
            *AVBinFileInfo\size_t         = SizeOf(_AVbinFileInfo)
            CallFunctionFast(*avbin_file_info, *AVBinFile, *AVBinFileInfo)            
            
            ; checkout if stream(s) available
            If *AVBinFileInfo\n_streams>0               
               
               ; allocate memory avbin structures
               If *AVBinPacket._AVBinPacket   = 0
                  *AVBinPacket._AVBinPacket   = AllocateMemory(SizeOf(_AVbinPacket))
                  *AVBinPacket\structure_size = SizeOf(_AVbinPacket)
               EndIf
               If *AVBinStreamInfo._AVBinStreamInfo = 0
                  *AVBinStreamInfo._AVBinStreamInfo = AllocateMemory(SizeOf(_AVbinStreamInfo))
                  *AVBinStreamInfo\structuresize    = SizeOf(_AVbinStreamInfo)
               EndIf
               
               ; examine available streams
               For a = 0 To *AVBinFileInfo\n_streams-1
                  
                  ; get stream info
                  CallFunctionFast(*avbin_stream_info, *AVBinFile, a, *AVBinStreamInfo)
                  
                  ; video stream
                  If *AVBinStreamInfo\AVBinStreamType = 1
                     If *AVBinStream._AVBinStream = 0
                        *AVbinStream._AVBinStream = CallFunctionFast(*avbin_open_stream, *avbinfile, a)
                        video = a
                        CreateImage(0,*AVBinStreamInfo\width,*AVBinStreamInfo\height, 32)                                   
                        ResizeWindow(0, WindowX(0)-(*AVBinStreamInfo\width/2), WindowY(0)-(*AVBinStreamInfo\height/2), *AVBinStreamInfo\width, *AVBinStreamInfo\height+20)
                        OpenWindowedScreen(WindowID(0), 0, 0, *AVBinStreamInfo\width,*AVBinStreamInfo\height, 0, 0, 0)
                        *RenderTargetDDS.IDirectDrawSurface7=GetRenderTargetDDS()                       
                        *image = AllocateMemory((*AVBinStreamInfo\width * *AVBinStreamInfo\height) * 3)
                        IW = *AVBinStreamInfo\width
                        IH = *AVBinStreamInfo\height
                        bmi.BITMAPINFO
                        bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
                        bmi\bmiHeader\biWidth = IW
                        bmi\bmiHeader\biHeight = -IH 
                        bmi\bmiHeader\biPlanes = 1
                        bmi\bmiHeader\biBitCount = 24
                        bmi\bmiHeader\biCompression = #BI_RGB   
                        If *AVBinFileInfo\starttime+*AVBinFileInfo\duration>*AVBinFileInfo\starttime ;>0
                           If CreateGadgetList(WindowID(0))
                              ScrollBarGadget(0, 0, *AVBinStreamInfo\height, *AVBinStreamInfo\width, 20, 0, *AVBinFileInfo\duration/1000000, 1) ;-*AVBinFileInfo\starttime,1 ) ; [, Flags]) 
                              DisableGadget(0, 1)
                           EndIf
                        Else
                           ResizeWindow(0, WindowX(0)-(*AVBinStreamInfo\width/2), WindowY(0)-(*AVBinStreamInfo\height/2), *AVBinStreamInfo\width, *AVBinStreamInfo\height)                        
                        EndIf
                     EndIf
                  EndIf
                  
                  ; audio stream
                  If *AVBinStreamInfo\AVBinStreamType = 2
                     If *AVBinStream1._AVBinStream    = 0
                        *AVbinStream1._AVBinStream    = CallFunctionFast(*avbin_open_stream, *avbinfile, a)
                        audio=a
                        s.l = CallFunction(0, "avbin_get_audio_buffer_size")*2
                        *DX8Sound = PrepareDX8Sound(*AVBinStreamInfo)
                        *Sound.IDirectSoundBuffer8 = *DX8Sound ;\Sound 
                        *Sound\SetCurrentPosition(0)
                        *Sound\Play(0,0,#DSBPLAY_LOOPING)    
                     EndIf                                                       	
                  EndIf
                  
               Next
               
               ; program loop..
               ; --------------
               While wevent<>#PB_Event_CloseWindow 
                  
                  ; windowevents
                  wevent=WindowEvent()         
                                   
                  ; Read a few packets .. 
                  For d = 1 To #maxpackets
                  
                      ; it might be showtime
                      If wevent<>#PB_Event_CloseWindow
                         
                         ; read a packet
                         check = CallFunctionFast(*avbin_read, *avbinfile, *AVBinPacket)
                         If check=0
                         
                             ; video packet
                             If *avbinpacket\size And *avbinpacket\streamindex=video  And *AVBinFileInfo\n_streams-1>0                  
                                bytesused.l = CallFunctionFast(*avbin_decode_video, *AVbinStream, *avbinfile, *image, 3)                                                    
                                If bytesused
                                   If videostart.q=0
                                      videostart.q=*AVBinPacket\timestamp
                                   EndIf
                                   ; add to timing buffer
                                   LastElement(timing())
                                   AddElement(timing())
                                   timing()\type = video
                                   timing()\time = *AVBinPacket\timestamp 
                                   timing()\buffer = AllocateMemory((*AVBinStreamInfo\width * *AVBinStreamInfo\height) * 3)
                                   If timing()\buffer
                                      CopyMemory(*image, timing()\buffer, (*AVBinStreamInfo\width * *AVBinStreamInfo\height) * 3)
                                   EndIf
                                Else
                                   FreeMemory(timing()\buffer)
                                   DeleteElement(timing())                            
                                EndIf
                             EndIf  
                             
                             ; audio packet
                             If *avbinpacket\size And *avbinpacket\streamindex=audio
                                s1.l = s.l       
                                total.l=0                 
                                ; add to timing buffer
                                LastElement(timing())
                                AddElement(timing())
                                timing()\buffer = AllocateMemory(s1)
                                If *AVBinFile\packet And timing()\buffer 
                                   bytesused1.l = CallFunctionFast(*avbin_decode_audio, *AVBinStream1, *avbinfile, timing()\buffer, @s1.l)                             
                                EndIf
                                If bytesused1     
                                   If audiostart.q=0
                                      audiostart.q =  *AVBinPacket\timestamp
                                   EndIf  
                                   If s1<>s                                   
                                      ReAllocateMemory(timing()\buffer, s1)
                                   EndIf
                                   timing()\type   = audio
                                   timing()\time   = *AVBinPacket\timestamp
                                   timing()\length = s1  
                                Else
                                   FreeMemory(timing()\buffer)
                                   DeleteElement(timing())
                                EndIf                                            
                             EndIf  
                             
                         Else
                             If streamstart.q>=*AVBinFileInfo\duration+*AVBinFileInfo\starttime
                                wevent=#PB_Event_CloseWindow
                             EndIf
                         EndIf
                      EndIf
                  Next
                  
                  ; delay
                  Delay(2)
                  
                  ; timing, display video or play sound..
                  If audiostart.q And videostart.q And CountList(timing())>#buffer 
                     
                     ; is streamstart set?
                     If streamstart.q=0
                        If audiostart.q < videostart.q
                           streamstart.q = audiostart.q
                        Else
                           streamstart.q = videostart.q 
                        EndIf
                        tickcount0.d = GetTickCount_()
                        tickcount1.d = tickcount0.d
                     EndIf
                     
                     ; find a frame..
                     ResetList(timing()): gevonden=-1
                     While NextElement(timing())
                        If timing()\time <= streamstart And timing()\done=0
                           gevonden=ListIndex(timing())
                           timing()\done=1
                           LastElement(timing())
                        EndIf
                     Wend
                     
                     ; timing ..
                     tickcount0.d = GetTickCount_()
                     If tickcount0>tickcount1
                        streamstart + (tickcount0.d-tickcount1.d)*1000
                        tickcount1.d = tickcount0.d
                     EndIf
                  
                     ; Have a frame?
                     If gevonden>-1
                        If IsGadget(0)
                           If (streamstart-*AVBinFileInfo\starttime)/1000000
                              If (streamstart-*AVBinFileInfo\starttime)/1000000<>oval.q
                                 oval.q = (streamstart-*AVBinFileInfo\starttime)/1000000
                                 SetGadgetState(0, (streamstart-*AVBinFileInfo\starttime)/1000000)
                              EndIf
                           EndIf
                        EndIf
                        SelectElement(timing(), gevonden)
                        
                        ; PLAY AUDIO                      
                        If timing()\type=audio
                           dwLength = timing()\Length
                           If *Sound\Lock(0,dwLength,@lpvWrite,@L1,@lpvWrite1,@L2, #DSBLOCK_FROMWRITECURSOR) = #DS_OK                              
                              dwLength = L1
                              If timing()\length>dwLength ; sometime can happen .. 
                                 over.l = timing()\length-dwLength
                                 If over>L2
                                    over=L2
                                 EndIf
                                 If L2 And over
                                    CopyMemory_(lpvWrite,timing()\buffer,dwLength) 
                                    ReAllocateMemory(timing()\buffer, over)
                                    copymemory_(lpvWrite1, timing()\buffer, over)
                                 Else
                                    CopyMemory_(lpvWrite,timing()\buffer,dwLength) 
                                 EndIf
                              Else
                                 If timing()\buffer
                                    CopyMemory_(lpvWrite,timing()\buffer,timing()\Length) 
                                 EndIf
                              EndIf
                              *Sound\UnLock(lpvWrite,dwLength,0,0) 
                              FreeMemory(timing()\buffer)
                           EndIf
                        EndIf
                        
                        ; PLAY VIDEO                        
                        If timing()\type=video
                           *RenderTargetDDS\GetDC(@TargetDC)
                           SrcDC=StartDrawing(ImageOutput(0))
                              SetDIBits_(SrcDC,ImageID(0),0,IH,timing()\buffer,bmi,#DIB_RGB_COLORS)
                              BitBlt_(TargetDC, 0, 0, IW, IH, SrcDC, 0, 0, #SRCCOPY) 
                           StopDrawing()
                           *RenderTargetDDS\ReleaseDC(TargetDC);                          
                           FlipBuffers()
                           If timing()\buffer
                              FreeMemory(timing()\buffer)
                           EndIf
                        EndIf
                        
                        ; Delete element.. 
                        DeleteElement(timing())
                        
                     EndIf
                  EndIf
                  
               Wend
              
               ; free              
               If *AVBinStreamInfo
                  FreeMemory(*AVBinStreamInfo)
               EndIf
               If *AVBinPacket
                  FreeMemory(*AVBinPacket)
               EndIf
               If IsImage(0)>0
                  FreeImage(0)
                  FreeMemory(*image)
                  CloseWindow(0)
               EndIf
               If *avbinstream
                  CallFunctionFast(*avbin_close_stream, *avbinstream)
               EndIf
               If *AVBinStream1
                  CallFunctionFast(*avbin_close_stream, *avbinstream1)
               EndIf
            EndIf               
            CallFunctionFast(*avbin_close_file, *avbinfile)        
         Else
            Debug "AVBIN: Closing functions fail.."
         EndIf
      Else
         Debug "AVBIN: Decode and reading functions fail.."
      EndIf
   Else
      Debug "AVBIN: Init and opening functions fail.."
   EndIf
   CloseLibrary(0)
EndIf
End

DataSection
  IID_DirectSoundBuffer8: 
    Data.l $6825A449
    Data.w $7524,$4D82
    Data.b $92,$0F,$50,$E3,$6A,$B3,$AB,$1E
 
  IID_DirectSoundNotify8:
    Data.l $b0210783
    Data.w $89cd, $11d0
    Data.b $af,$08,$00,$a0,$c9,$25,$cd,$16
EndDataSection