Videoframes auslesen

Für allgemeine Fragen zur Programmierung mit PureBasic.
gem
Beiträge: 14
Registriert: 24.08.2014 18:04

Videoframes auslesen

Beitrag von gem »

Guten Abend

Ich möchte aus einer Videodatei (Beliebiger Codec und Format) alle Frames einzeln dekodieren und mit einem eigenen Algorithmus verarbeiten.
Bis jetzt habe ich noch keine brauchbare Lösung gefunden.
Bei ffmpeg schaffe ich es nur die Frames vorher als Bilddatei abzuspeichern und anschließen wieder zu öffnen, was sehr Zeitaufwendig ist.
Die Extrahierung mit der avifil32.dll konnte ich in PureBasic nicht implementieren. Ich habe bereits alte Foreneinträge gelesen, leider funktionieren diese Skripte nicht mehr.
Eine weiteres Problem der avifil32.dll trat bereits auf als ich diese mit AutoIt verwendet habe, so konnten einige Codecs und Formate nicht gelesen werden.
Im Internet habe ich noch etwas zu libavcodec libavformat gefunden ,leider konnte ich diese nicht in PureBasic implementieren.

Ich benötige die Frames als raw format. Speichergröße eines Frames (breite * höhe * tiefe), tiefe = 3 (RGB), So das ich die Werte jedes Pixel auslesen kann.

Ich würde mich sehr freuen wenn mir jemand zum Thema ein Beispiel, Informationen oder einfach eine gute Hilfe geben kann.

Vielen Dank und Schöne Grüße
Gabriel
gem
Beiträge: 14
Registriert: 24.08.2014 18:04

Re: Videoframes auslesen

Beitrag von gem »

Habe nochmal das Internet durchforstet und bin dabei auf einen alten Forenbeitrag gestoßen.
Dieser beschäftigte sich mit der avifil32
http://www.purebasic.fr/english/viewtop ... =12&t=7648

Ich habe das Beispiel noch für meine Bedürfnisse angepasst.
Hier mein Ergebnis

Code: Alles auswählen

#streamtypeVIDEO = $73646976
#AVIGETFRAMEF_BESTDISPLAYFMT = 1
#AVI_ERR_OK = 0

Structure AVIFILEINFO
    dwMaxBytesPerSec.l
    dwFlags.l
    dwCaps.l
    dwStreams.l
    dwSuggestedBufferSize.l
    dwWidth.l
    dwHeight.l
    dwScale.l
    dwRate.l
    dwLength.l
    dwEditCount.l
    szFileType.b[64]     
EndStructure

Structure Video
	width.i
	height.i
	framerate.i
	frames.i
	file.i
	stream.i
	obj.i
	first.i
EndStructure

Declare.i InitVideo()
Declare.i CloseVideo()
Declare.i LoadVideo(filename.s)
Declare.i FreeVideo(*video.Video)
Declare.i GetVideoWidth(*video.Video)
Declare.i GetVideoHeight(*video.Video)
Declare.i GetVideoFramerate(*video.Video)
Declare.i GetVideoFrames(*video.Video)
Declare.i VideoFrameToImage(*video.Video, img.i, frame.i)
Declare.i CreateImageFromVideoFrame(*video.Video)

Global avifil32.i

Procedure.i InitVideo()
	If Not IsLibrary(avifil32)
		avifil32 = OpenLibrary(#PB_Any ,"AVIFIL32.DLL")
		CallFunction(avifil32,"AVIFileInit" )
		ProcedureReturn 1
	EndIf
EndProcedure	

Procedure.i CloseVideo()
	If IsLibrary(avifil32)
		CallFunction(avifil32, "AVIFileExit" )
		CloseLibrary(avifil32)
		ProcedureReturn 1
	EndIf
EndProcedure	

Procedure.i LoadVideo(filename.s)
	If IsLibrary(avifil32)
		Define file.i
		Define stream.i
		Define res.i
		res = CallFunction( avifil32, "AVIFileOpen", @file, @filename.s, #OF_SHARE_DENY_WRITE, 0 )
		If res = #AVI_ERR_OK	
			res = CallFunction( avifil32, "AVIFileGetStream", file, @stream, #streamtypeVIDEO, 0 )
    	If res = #AVI_ERR_OK		
    		Define fileinfo.AVIFILEINFO 	
    		CallFunction( avifil32, "AVIFileInfo", file , @fileinfo ,SizeOf(AVIFILEINFO)) 		
    		Define *video.Video
    		*video = AllocateStructure(Video)
				*video\file = file
				*video\stream = stream
				*video\obj = CallFunction( avifil32, "AVIStreamGetFrameOpen", stream, #AVIGETFRAMEF_BESTDISPLAYFMT )
				*video\first = CallFunction( avifil32, "AVIStreamStart", stream )				
				*video\width = fileinfo\dwWidth
				*video\height = fileinfo\dwHeight
				*video\framerate = fileinfo\dwRate / fileinfo\dwScale
				*video\frames = CallFunction( avifil32, "AVIStreamLength", stream ) - *video\first			
				ProcedureReturn *video
			Else		
				CallFunction( avifil32, "AVIFileRelease", file )			
			EndIf
		EndIf
	EndIf
EndProcedure	

Procedure FreeVideo(*video.Video)
	If *video <> 0
		CallFunction( avifil32, "AVIStreamGetFrameClose", *video\obj )
		CallFunction( avifil32, "AVIFileRelease", *video\file )
		ProcedureReturn 1
	EndIf
EndProcedure	

Procedure.i GetVideoWidth(*video.Video)
	If *video <> 0
		ProcedureReturn *video\width
	EndIf
EndProcedure	

Procedure.i GetVideoHeight(*video.Video)
	If *video <> 0
		ProcedureReturn *video\height
	EndIf
EndProcedure	

Procedure.i GetVideoFramerate(*video.Video)
	If *video <> 0
		ProcedureReturn *video\framerate
	EndIf
EndProcedure	

Procedure.i GetVideoFrames(*video.Video)
	If *video <> 0
		ProcedureReturn *video\frames
	EndIf
EndProcedure	

Procedure .i VideoFrameToImage(*video.Video, img.i, frame.i)
	If *video <> 0
			Define *header.BITMAPINFOHEADER
			*header = CallFunction(avifil32, "AVIStreamGetFrame", *video\obj, frame - *video\first)
			If *header
			 Define dc   = GetDC_(#Null)
			 Define cdc  = CreateCompatibleDC_(dc)
			  If cdc
			    SelectObject_( cdc, img )
			    SetDIBits_( cdc, img, 0, *header\biHeight, *header + SizeOf(BITMAPINFOHEADER), *header, #DIB_RGB_COLORS)
			    DeleteDC_(cdc)
			  EndIf
			  ReleaseDC_(#Null, dc)
			  ProcedureReturn 1
			EndIf
	EndIf
EndProcedure

Procedure .i CreateImageFromVideoFrame(*video.Video)
	If *video <> 0
		ProcedureReturn CreateImage(#PB_Any,*video\width,*video\height)
	EndIf
EndProcedure
__________________________________________________
Domain-Link angepasst
21.04.2015
RSBasic
Antworten