As currently configured, the video should be 1280x720 progressive pixels. It has been tested with videos in the YUV color space with 4:2:0 pixels, which most videos are. The program converts YUV to RGB using BT.709 coefficients. You may be able to change this by altering the argument passed to ffmpeg in pipeIn$ and the constats #Kr, #Kg and #Kb.
The program sets up an input pipe from ffmpeg. It was (fairly) easy to do in PureBasic. I hate to think what it's like in other languages.
ffmpeg.exe needs to be available to your program. It could be in the same folder as your program file. ffmpeg executables can be obtained here: https://ffmpeg.zeranoe.com/builds/
Comments welcome.
Code: Select all
; PROGRAM TO READ ONE FRAME OF VIDEO BY chris319
; updated 3/3/2020
#H = 720: #W = 1280
;BT.709 COEFFICIENTS
#Kr = 0.2126: #Kg = 0.7152: #Kb = 0.0722
Global Dim frame.a(#H*#W*3) ;Allocate a buffer To store one frame
Global numpixels = #H * #W
OpenWindow(1,0,0,#W,#H,"")
Procedure RedrawImage()
StartDrawing(WindowOutput(1))
DrawImage(ImageID(1),0,0,#W, #H)
StopDrawing()
EndProcedure
CreateImage(1, #W, #H , 24)
Global filename$ = OpenFileRequester("Select a file","Videos", "Media files (*.avi, *.wmv, *.mp4, *.mp2)"+Chr(0)+"*.avi; *.wmv; *.mp4; *.mp2", 3)
If filename$ = ""
FreeArray(frame())
CloseWindow(1):End
EndIf
filename$ = Chr(34) + filename$ + Chr(34); ENCLOSE FILE NAME IN QUOTATION MARKS
pipeIn$ = "-i " + filename$ + " -f image2pipe -s 1280x720 -pix_fmt yuv420p -r 59.94 -vf scale=in_range=limited:out_range=limited,scale=in_color_matrix=bt709,scale=out_color_matrix=bt709 -vcodec rawvideo -"
readFrame = RunProgram("ffmpeg.exe", pipeIn$, "", #PB_Program_Open | #PB_Program_Read)
ReadProgramData(readFrame, @frame(0), #H * #W * 3)
CloseProgram(readFrame)
StartDrawing(ImageOutput(1))
*pntr = @frame.a(0)
For ycoord = 0 To #H - 1
For x = 0 To #W - 1
y.a = PeekA(*pntr)
u.a = frame((yCoord / 2) * (#W / 2) + (x / 2) + numpixels)
v.a = frame((yCoord / 2) * (#W / 2) + (x / 2) + numpixels + (numpixels / 4))
yf.f = y
uf.f = u
vf.f = v
rf.d = (255/219)*yf + (255/112)*vf*(1-#Kr) - (255*16/219 + 255*128/112*(1-#Kr))
gf.d = (255/219)*yf - (255/112)*uf*(1-#Kb)*#Kb/#Kg - (255/112)*vf*(1-#Kr)*#Kr/#Kg - (255*16/219 - 255/112*128*(1-#Kb)*#Kb/#Kg - 255/112*128*(1-#Kr)*#Kr/#Kg)
bf.d = (255/219)*yf + (255/112)*uf*(1-#Kb) - (255*16/219 + 255*128/112*(1-#Kb))
If rf.d > 255: rf = 255: ElseIf rf < 0: rf = 0:EndIf
If gf.d > 255: gf = 255: ElseIf gf < 0: gf = 0:EndIf
If bf.d > 255: bf = 255: ElseIf bf < 0: bf = 0:EndIf
rd.a = rf
gd.a = gf
bd.a = bf
Plot (x, ycoord, RGB(Rd,Gd,Bd)); DRAW COLOR MONITOR
*pntr + 1
Next
Next
StopDrawing()
Repeat:
event = WaitWindowEvent()
If Event = #PB_Event_Repaint:ReDrawImage():EndIf
Until event = #PB_Event_CloseWindow
FreeArray(frame())
CloseWindow(1):End