Attribute VB_Name = "ffmpeg"
Option Explicit

Public Type MediaProp
Formato As String
Duracion As String
Bitrate As String
SampleRate As String
Canales As String
BitrateAudio As String
CodecAudio As String
CodecVideo As String
TamanoCuadro As String
BitrateVideo As String
fps As String
PixelFormat As String
CodecSub As String
Titulo As String
Artista As String
album As String
Genero As String
Track As String
DisplayAspectRatio As String
ContieneVideo As Byte
ContieneAudio As Byte
ContieneSubtitulos As Byte
CodecAudioTag As String
CodecVideoTag As String
End Type

Public Type FFmpegCmdLModif
Contenedor As String
CodecAudio As String
CodecVideo As String
CodecSubtitulo As String
PixelFormat As String
RelAspect As String
Objetivo As String
BitrateAudio As String
BitrateMinAudio As String
BitrateMaxAudio As String
SampleRate As String
Canales As String
AudioCalidad As String
EliminarAudio As String
BitrateVideo As String
BitrateMinVideo As String
BitrateMaxVideo As String
Videofps As String
VideoCalidad As String
VideoCalidadMin As String
VideoCalidadMax As String
TamanoCuadro As String
EliminarVideo As String
FiltroAudio As String
FiltroVideo As String
Filtro As String
Duracion As String
Volumen As String
EliminarSubtitulos As String
SetStart As String
ffplayTamanoCuadro As String
ffplayWidthDisp As String
ffplayHeightDisp As String
Vframes As String
SobreescribirYes As String
ffplayNoDisplay As String
ffplayAutoExit As String
ffplayVerbose As String
Filesizelimit As String
CPase As String
SobreescribirNo As String
CodecVTag As String
CodecATag As String
BufferSize As String
ReadInputAtNFR As String
End Type

Public Type FFmpegCmdLModifLabels
Contenedor As String
CodecAudio As String
CodecVideo As String
CodecSubtitulo As String
PixelFormat As String
RelAspect As String
Objetivo As String
Bitrate As String
BitrateMin As String
BitrateMax As String
SampleRate As String
Canales As String
Calidad As String
fps As String
CalidadMin As String
CalidadMax As String
TamanoCuadro As String
ParametrosAdicionales As String
Extension As String
EliminarA As String
EliminarV As String
EliminarS As String
Multisalida As String
BufferSize As String
ReadInputAtNFR As String
End Type

Public ffplayPath As String
Public ffmpegPath As String
Public ffprobePath As String
Public FFmpegParametros As FFmpegCmdLModif
Public FFmpegParametrosEtiq As FFmpegCmdLModifLabels
Public PlayPipe As Byte

Public Sub PlayFile(FilePath As String, Optional ParCmd As String, Optional ffmpegpipe As Byte)
Dim FormsState() As Boolean, i As Byte, Comandos As String
Dim InSplit() As String, WorkDir As String
Dim Form18IsLoad As Byte
If ComprobarExistenciaFFplay = False Then Exit Sub
If ffmpegpipe = 0 Then
    If FilePath <> "" Then
        InSplit = Split(FilePath, "|")
        If LBound(InSplit) = UBound(InSplit) Or (InSplit(LBound(InSplit)) = "" Or InSplit(UBound(InSplit)) = "") Then
            Comandos = Chr(34) & ScriptObj.Archivo_RutaCorta(Replace(FilePath, "|", "")) & Chr(34)
            Comandos = Chr(34) & ffplayPath & Chr(34) & " " & ParCmd & " -i " & Comandos
            Comandos = "cmd.exe /c " & Chr(34) & Comandos & Chr(34)
            PlayPipe = 0
        Else
            If ComprobarExistenciaFFmpeg = False Then Exit Sub
            Comandos = ScriptObj.NombreBase(ffmpegPath) & "." & ScriptObj.DevolverExtension(ffmpegPath) & " " & ffmpeg.FFmpegParametros.EliminarVideo & " -i " & Chr(34) & ScriptObj.Archivo_RutaCorta(InSplit(LBound(InSplit))) & Chr(34) & " " & ffmpeg.FFmpegParametros.EliminarAudio & " -i " & Chr(34) & ScriptObj.Archivo_RutaCorta(InSplit(UBound(InSplit))) & Chr(34) & " "
            Comandos = Comandos _
            & ffmpeg.FFmpegParametros.Contenedor & " matroska " _
            & ffmpeg.FFmpegParametros.CodecAudio & " pcm_s16le " _
            & ffmpeg.FFmpegParametros.CodecVideo & " rawvideo " _
            & ffmpeg.FFmpegParametros.PixelFormat & " yuv420p"
            WorkDir = ScriptObj.DirectorioPadre(ffmpegPath)
            Comandos = "cmd.exe /C " & Comandos & " pipe:1 | " & Chr(34) & ffplayPath & Chr(34) & " -i pipe:0"
            PlayPipe = 1
        End If
    Else
        Comandos = "cmd.exe /c " & Chr(34) & Chr(34) & ffplayPath & Chr(34) & " " & ParCmd & Chr(34)
        PlayPipe = 0
    End If
Else
    If ComprobarExistenciaFFmpeg = False Then Exit Sub
    Comandos = ScriptObj.NombreBase(ffmpegPath) & "." & ScriptObj.DevolverExtension(ffmpegPath) & " -i " & Chr(34) & FilePath & Chr(34) & " "
    Comandos = Comandos _
            & ffmpeg.FFmpegParametros.Contenedor & " matroska " _
            & ffmpeg.FFmpegParametros.CodecAudio & " pcm_s16le " _
            & ffmpeg.FFmpegParametros.CodecVideo & " rawvideo " _
            & ffmpeg.FFmpegParametros.PixelFormat & " yuv420p"
            WorkDir = ScriptObj.DirectorioPadre(ffmpegPath)
    Comandos = Comandos & " " & ParCmd
    Comandos = "cmd.exe /C " & Comandos & " pipe:1 | " & Chr(34) & ffplayPath & Chr(34) & " -i pipe:0"
    PlayPipe = 1
End If
ReDim FormsState(0 To Forms.Count - 1)
For i = 0 To Forms.Count - 1
FormsState(i) = Forms(i).Visible
Forms(i).Visible = False
Next
Load Form18
Form18.Show
Call CaptureConsole.ExecAndCapture(Comandos, WorkDir, , 1, Form18.Text1, , 3, , 0)
Form18.Command1.Enabled = False
Form18.Command2.Enabled = False
Form18IsLoad = 1
While Form18IsLoad = 1
DoEvents
Form18IsLoad = 0
For i = 0 To Forms.Count - 1
If Forms(i) Is Form18 Then
Form18IsLoad = 1
Exit For
End If
Next
Wend
For i = 0 To Forms.Count - 1
Forms(i).Visible = FormsState(i)
Next
End Sub

Public Function FileProperties(FilePath As String) As MediaProp
Dim Comandos As String, ConsoleRet As String, Ret As MediaProp
Dim Posicion1 As Long, Posicion2 As Long, IndexStreamAudio As Integer, IndexStreamVideo As Integer
Dim IndexStreamSub As Integer, StreamSplit() As String, i As Integer
If ComprobarExistenciaFFprobe = False Then Exit Function

Comandos = Chr(34) & ffprobePath & Chr(34) & " -show_streams -i " & Chr(34) & ScriptObj.Archivo_RutaCorta(FilePath) & Chr(34)
If CaptureConsole.ExecAndCapture(Comandos, , , , , , , ConsoleRet) = False Then Exit Function

'Obtener datos
'Formato
Posicion1 = InStr(1, ConsoleRet, vbCrLf & "Input #0,")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 11
Posicion2 = InStr(Posicion1, ConsoleRet, ",")
If Posicion2 > 0 Then Ret.Formato = Mid(ConsoleRet, Posicion1, Posicion2 - Posicion1)
End If

'Duracion
Posicion1 = InStr(1, ConsoleRet, "duration=")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 9
Posicion2 = InStr(Posicion1, ConsoleRet, vbCrLf)
If Posicion2 > 0 Then Ret.Duracion = Mid(ConsoleRet, Posicion1, Posicion2 - Posicion1)
End If

'Bitrate
Posicion1 = InStr(1, ConsoleRet, " bitrate:")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 9
Posicion2 = InStr(Posicion1, ConsoleRet, vbCrLf)
If Posicion2 > 0 Then Ret.Bitrate = Mid(ConsoleRet, Posicion1, Posicion2 - Posicion1)
End If

'Titulo
Posicion1 = InStr(1, ConsoleRet, vbCrLf & "    title           : ")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 24
Posicion2 = InStr(Posicion1, ConsoleRet, vbCrLf)
If Posicion2 > 0 Then Ret.Titulo = Mid(ConsoleRet, Posicion1, Posicion2 - Posicion1)
End If

'Artista
Posicion1 = InStr(1, ConsoleRet, vbCrLf & "    artist          : ")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 24
Posicion2 = InStr(Posicion1, ConsoleRet, vbCrLf)
If Posicion2 > 0 Then Ret.Artista = Mid(ConsoleRet, Posicion1, Posicion2 - Posicion1)
End If

'Album
Posicion1 = InStr(1, ConsoleRet, vbCrLf & "    album           : ")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 24
Posicion2 = InStr(Posicion1, ConsoleRet, vbCrLf)
If Posicion2 > 0 Then Ret.album = Mid(ConsoleRet, Posicion1, Posicion2 - Posicion1)
End If

'Genero
Posicion1 = InStr(1, ConsoleRet, vbCrLf & "    genre           : ")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 24
Posicion2 = InStr(Posicion1, ConsoleRet, vbCrLf)
If Posicion2 > 0 Then Ret.Genero = Mid(ConsoleRet, Posicion1, Posicion2 - Posicion1)
End If

'Track
Posicion1 = InStr(1, ConsoleRet, vbCrLf & "    track           : ")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 24
Posicion2 = InStr(Posicion1, ConsoleRet, vbCrLf)
If Posicion2 > 0 Then Ret.Track = Mid(ConsoleRet, Posicion1, Posicion2 - Posicion1)
End If

'Streams
IndexStreamAudio = -1
IndexStreamVideo = -1
IndexStreamSub = -1
Ret.ContieneAudio = 0
Ret.ContieneSubtitulos = 0
Ret.ContieneVideo = 0
StreamSplit = Split(ConsoleRet, "[/STREAM]" & vbCrLf)
ConsoleRet = ""
i = LBound(StreamSplit)
While i <= UBound(StreamSplit)
If InStr(1, StreamSplit(i), "codec_type=audio" & vbCrLf) > 0 And IndexStreamAudio = -1 Then
IndexStreamAudio = i
Else
If InStr(1, StreamSplit(i), "codec_type=video" & vbCrLf) > 0 And IndexStreamVideo = -1 Then
IndexStreamVideo = i
Else
If InStr(1, StreamSplit(i), "codec_type=subtitle" & vbCrLf) > 0 And IndexStreamSub = -1 Then IndexStreamSub = i
End If
End If
If IndexStreamAudio > -1 And IndexStreamVideo > -1 And IndexStreamSub > -1 Then i = UBound(StreamSplit)
i = i + 1
Wend

'Audio
If IndexStreamAudio <> -1 Then
Ret.ContieneAudio = 1

    'Canales
Posicion1 = InStr(1, StreamSplit(IndexStreamAudio), "channels=")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 9
Posicion2 = InStr(Posicion1, StreamSplit(IndexStreamAudio), vbCrLf)
If Posicion2 > 0 Then Ret.Canales = Mid(StreamSplit(IndexStreamAudio), Posicion1, Posicion2 - Posicion1)
End If

    'Bitrate
Posicion1 = InStr(1, StreamSplit(IndexStreamAudio), "bit_rate=")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 9
Posicion2 = InStr(Posicion1, StreamSplit(IndexStreamAudio), vbCrLf)
If Posicion2 > 0 Then Ret.BitrateAudio = Mid(StreamSplit(IndexStreamAudio), Posicion1, Posicion2 - Posicion1)
End If

    'Codec
Posicion1 = InStr(1, StreamSplit(IndexStreamAudio), "codec_name=")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 11
Posicion2 = InStr(Posicion1, StreamSplit(IndexStreamAudio), vbCrLf)
If Posicion2 > 0 Then Ret.CodecAudio = Mid(StreamSplit(IndexStreamAudio), Posicion1, Posicion2 - Posicion1)
End If

    'SampleRate
Posicion1 = InStr(1, StreamSplit(IndexStreamAudio), "sample_rate=")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 12
Posicion2 = InStr(Posicion1, StreamSplit(IndexStreamAudio), vbCrLf)
If Posicion2 > 0 Then Ret.SampleRate = Mid(StreamSplit(IndexStreamAudio), Posicion1, Posicion2 - Posicion1)
End If

Posicion1 = InStr(1, StreamSplit(IndexStreamAudio), "codec_tag_string=")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 17
Posicion2 = InStr(Posicion1, StreamSplit(IndexStreamAudio), vbCrLf)
If Posicion2 > 0 Then Ret.CodecAudioTag = Mid(StreamSplit(IndexStreamAudio), Posicion1, Posicion2 - Posicion1)
If InStr(1, Ret.CodecAudioTag, "[0]") > 0 Then Ret.CodecAudioTag = ""
End If

End If

'Video
If IndexStreamVideo <> -1 Then
Ret.ContieneVideo = 1
    'Codec
Posicion1 = InStr(1, StreamSplit(IndexStreamVideo), "codec_name=")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 11
Posicion2 = InStr(Posicion1, StreamSplit(IndexStreamVideo), vbCrLf)
If Posicion2 > 0 Then Ret.CodecVideo = Mid(StreamSplit(IndexStreamVideo), Posicion1, Posicion2 - Posicion1)
End If
    
    'Tamaņo cuadro
Posicion1 = InStr(1, StreamSplit(IndexStreamVideo), "width=")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 6
Posicion2 = InStr(Posicion1, StreamSplit(IndexStreamVideo), vbCrLf)
If Posicion2 > 0 Then Ret.TamanoCuadro = Mid(StreamSplit(IndexStreamVideo), Posicion1, Posicion2 - Posicion1)
End If

Posicion1 = InStr(1, StreamSplit(IndexStreamVideo), "height=")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 7
Posicion2 = InStr(Posicion1, StreamSplit(IndexStreamVideo), vbCrLf)
If Posicion2 > 0 Then Ret.TamanoCuadro = Ret.TamanoCuadro & "x" & Mid(StreamSplit(IndexStreamVideo), Posicion1, Posicion2 - Posicion1)
End If

    'Bitrate Video
Posicion1 = InStr(1, StreamSplit(IndexStreamVideo), "bit_rate=")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 9
Posicion2 = InStr(Posicion1, StreamSplit(IndexStreamVideo), vbCrLf)
If Posicion2 > 0 Then Ret.BitrateVideo = Mid(StreamSplit(IndexStreamVideo), Posicion1, Posicion2 - Posicion1)
End If

    'fps
Posicion1 = InStr(1, StreamSplit(IndexStreamVideo), "r_frame_rate=")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 13
Posicion2 = InStr(Posicion1, StreamSplit(IndexStreamVideo), vbCrLf)
If Posicion2 > 0 Then Ret.fps = Mid(StreamSplit(IndexStreamVideo), Posicion1, Posicion2 - Posicion1)
End If

    'Formato de pixel
'pix_fmt
Posicion1 = InStr(1, StreamSplit(IndexStreamVideo), "pix_fmt=")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 8
Posicion2 = InStr(Posicion1, StreamSplit(IndexStreamVideo), vbCrLf)
If Posicion2 > 0 Then Ret.PixelFormat = Mid(StreamSplit(IndexStreamVideo), Posicion1, Posicion2 - Posicion1)
End If

    'display_aspect_ratio
Posicion1 = InStr(1, StreamSplit(IndexStreamVideo), "display_aspect_ratio=")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 21
Posicion2 = InStr(Posicion1, StreamSplit(IndexStreamVideo), vbCrLf)
If Posicion2 > 0 Then Ret.DisplayAspectRatio = Mid(StreamSplit(IndexStreamVideo), Posicion1, Posicion2 - Posicion1)
End If

Posicion1 = InStr(1, StreamSplit(IndexStreamVideo), "codec_tag_string=")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 17
Posicion2 = InStr(Posicion1, StreamSplit(IndexStreamVideo), vbCrLf)
If Posicion2 > 0 Then Ret.CodecVideoTag = Mid(StreamSplit(IndexStreamVideo), Posicion1, Posicion2 - Posicion1)
If InStr(1, Ret.CodecVideoTag, "[0]") > 0 Then Ret.CodecVideoTag = ""
End If

End If

'Subtitulos

If IndexStreamSub <> -1 Then
Ret.ContieneSubtitulos = 1
    'Codec
Posicion1 = InStr(1, StreamSplit(IndexStreamSub), "codec_name=")
If Posicion1 > 0 Then
Posicion1 = Posicion1 + 11
Posicion2 = InStr(Posicion1, StreamSplit(IndexStreamSub), vbCrLf)
If Posicion2 > 0 Then Ret.CodecSub = Mid(StreamSplit(IndexStreamSub), Posicion1, Posicion2 - Posicion1)
End If
End If

FileProperties = Ret
End Function

Public Sub FFCmdLParInicializar()
With FFmpegParametros
.AudioCalidad = "-aq"
.BitrateAudio = "-b:a"
.BitrateMaxAudio = "-maxrate:a"
.BitrateMaxVideo = "-maxrate:v"
.BitrateMinAudio = "-minrate:a"
.BitrateMinVideo = "-minrate:v"
.BitrateVideo = "-b:v"
.Canales = "-ac"
.CodecAudio = "-c:a"
.CodecSubtitulo = "-c:s"
.CodecVideo = "-c:v"
.Contenedor = "-f"
.EliminarAudio = "-an"
.EliminarVideo = "-vn"
.FiltroAudio = "-af"
.FiltroVideo = "-vf"
.Filtro = "-filter_complex"
.Objetivo = "-target"
.PixelFormat = "-pix_fmt"
.RelAspect = "-aspect"
.SampleRate = "-ar"
.TamanoCuadro = "-s"
.VideoCalidad = "-q:v"
.VideoCalidadMax = "-qmax:v"
.VideoCalidadMin = "-qmin:v"
.Videofps = "-r"
.Duracion = "-t"
.Volumen = "-af volume=volume="
.SetStart = "-ss"
.ffplayTamanoCuadro = "-video_size"
.ffplayHeightDisp = "-y"
.ffplayWidthDisp = "-x"
.Vframes = "-vframes"
.SobreescribirYes = "-y"
.ffplayNoDisplay = "-nodisp"
.ffplayAutoExit = "-autoexit"
.ffplayVerbose = "-loglevel"
.Filesizelimit = "-fs"
.CPase = "-pass"
.SobreescribirNo = "-n"
.EliminarSubtitulos = "-sn"
.CodecATag = "-atag"
.CodecVTag = "-vtag"
.BufferSize = "-bufsize"
.ReadInputAtNFR = "-re"
End With
End Sub

Public Sub FFCmdLParEtiqInicializar()
FFmpegParametrosEtiq = Lang.FFParLabels
End Sub

Public Function FFConvertirCronometroASegungos(Cronometro As String) As String
Dim CronSplit() As String, Ret As Single, EsValido As Byte, i As Integer
Dim multiplo As Long
On Error GoTo ErrH
If Cronometro = "" Then Exit Function
CronSplit = Split(Cronometro, ":")
If UBound(CronSplit) - LBound(CronSplit) + 1 > 3 Then Exit Function
EsValido = 1
For i = LBound(CronSplit) To UBound(CronSplit)
If IsNumeric(CronSplit(i)) = False Then
EsValido = 0
Exit For
End If
Next
If EsValido = 0 Then Exit Function
multiplo = 1
For i = UBound(CronSplit) To LBound(CronSplit) Step -1
Ret = Ret + CSng(CronSplit(i)) * multiplo
multiplo = multiplo * 60
Next
If Ret < 0 Then Exit Function
FFConvertirCronometroASegungos = Trim(CStr(Ret))
Exit Function
ErrH:
MsgBox "Error " & Err.Number & vbCrLf & Err.Description, vbCritical, Form1.Caption
End Function

Public Function ComprobarExistenciaFFmpeg() As Boolean
If ScriptObj.ExisteArchivo(ffmpegPath) = False Then
Lang.FF_ffmpegNotFound
ComprobarExistenciaFFmpeg = False
Else
ComprobarExistenciaFFmpeg = True
End If
End Function

Public Function ComprobarExistenciaFFplay() As Boolean
If ScriptObj.ExisteArchivo(ffplayPath) = False Then
Lang.FF_ffplayNotFound
ComprobarExistenciaFFplay = False
Else
ComprobarExistenciaFFplay = True
End If
End Function

Public Function ComprobarExistenciaFFprobe() As Boolean
If ScriptObj.ExisteArchivo(ffprobePath) = False Then
Lang.FF_ffprobeNotFound
ComprobarExistenciaFFprobe = False
Else
ComprobarExistenciaFFprobe = True
End If
End Function

Public Function TerminarFFPlay() As Boolean
Dim Terminados As Integer, Activos As Integer
Dim Ret As Boolean
Ret = APIS.MatarProcesoPorRuta(ffplayPath, Activos, Terminados)
Ret = Ret And (Activos = 0) And (Terminados > 0)
TerminarFFPlay = Ret
End Function

Public Sub DetenerReproduccion()
Dim Procesos() As Long, NumProcesos As Integer, ProcConsola As Long
Dim i As Integer, ProcesoPadre As Long, Finalizado As Byte
NumProcesos = APIS.BuscarProcesosAsociadosARuta(ffplayPath, Procesos)
If NumProcesos = 0 Then Exit Sub
ProcConsola = CaptureConsole.IDProcesoPrincipal
For i = 1 To NumProcesos
    If Procesos(i) = ProcConsola Then
        Call CaptureConsole.StopProcess
        Exit For
    Else
        ProcesoPadre = Procesos(i)
        While ProcesoPadre <> 0
            DoEvents
            ProcesoPadre = APIS.GetParentProcessID(ProcesoPadre)
            If ProcesoPadre = ProcConsola And ProcesoPadre <> 0 Then
                Call APIS.MatarProcesoPorID(Procesos(i))
                ProcesoPadre = 0
                Finalizado = 1
            End If
        Wend
        If Finalizado = 1 Then Exit For
    End If
Next
End Sub

