Bug #16 0
This commit is contained in:
695
src/buffer.go
695
src/buffer.go
@@ -205,7 +205,7 @@ func bufferingStream(playlistID, streamingURL, channelName string, w http.Respon
|
|||||||
playlist.Streams[streamID] = stream
|
playlist.Streams[streamID] = stream
|
||||||
BufferInformation.Store(playlistID, playlist)
|
BufferInformation.Store(playlistID, playlist)
|
||||||
|
|
||||||
go connectToStreamingServer(streamID, playlist)
|
go connectToStreamingServer(streamID, playlistID)
|
||||||
|
|
||||||
showInfo(fmt.Sprintf("Streaming Status:Playlist: %s - Tuner: %d / %d", playlist.PlaylistName, len(playlist.Streams), playlist.Tuner))
|
showInfo(fmt.Sprintf("Streaming Status:Playlist: %s - Tuner: %d / %d", playlist.PlaylistName, len(playlist.Streams), playlist.Tuner))
|
||||||
|
|
||||||
@@ -507,176 +507,191 @@ func clientConnection(stream ThisStream) (status bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func connectToStreamingServer(streamID int, playlist Playlist) {
|
func connectToStreamingServer(streamID int, playlistID string) {
|
||||||
|
|
||||||
var timeOut = 0
|
if p, ok := BufferInformation.Load(playlistID); ok {
|
||||||
var debug string
|
|
||||||
var tmpSegment = 1
|
|
||||||
var tmpFolder = playlist.Streams[streamID].Folder
|
|
||||||
var m3u8Segments []string
|
|
||||||
var bandwidth BandwidthCalculation
|
|
||||||
var networkBandwidth = Settings.M3U8AdaptiveBandwidthMBPS * 1e+6
|
|
||||||
|
|
||||||
var defaultSegment = func() {
|
var playlist = p.(Playlist)
|
||||||
|
|
||||||
var segment Segment
|
var timeOut = 0
|
||||||
|
var debug string
|
||||||
|
var tmpSegment = 1
|
||||||
|
var tmpFolder = playlist.Streams[streamID].Folder
|
||||||
|
var m3u8Segments []string
|
||||||
|
var bandwidth BandwidthCalculation
|
||||||
|
var networkBandwidth = Settings.M3U8AdaptiveBandwidthMBPS * 1e+6
|
||||||
|
|
||||||
if len(playlist.Streams[streamID].Location) > 0 {
|
var defaultSegment = func() {
|
||||||
segment.URL = playlist.Streams[streamID].Location
|
|
||||||
} else {
|
|
||||||
segment.URL = playlist.Streams[streamID].URL
|
|
||||||
}
|
|
||||||
|
|
||||||
segment.Duration = 0
|
var segment Segment
|
||||||
|
|
||||||
var stream = playlist.Streams[streamID]
|
if len(playlist.Streams[streamID].Location) > 0 {
|
||||||
stream.Segment = []Segment{}
|
segment.URL = playlist.Streams[streamID].Location
|
||||||
stream.Segment = append(stream.Segment, segment)
|
} else {
|
||||||
|
segment.URL = playlist.Streams[streamID].URL
|
||||||
|
}
|
||||||
|
|
||||||
stream.HLS = false
|
segment.Duration = 0
|
||||||
stream.Sequence = 0
|
|
||||||
stream.Wait = 0
|
|
||||||
stream.NetworkBandwidth = networkBandwidth
|
|
||||||
|
|
||||||
playlist.Streams[streamID] = stream
|
var stream = playlist.Streams[streamID]
|
||||||
|
stream.Segment = []Segment{}
|
||||||
|
stream.Segment = append(stream.Segment, segment)
|
||||||
|
|
||||||
timeOut++
|
stream.HLS = false
|
||||||
|
stream.Sequence = 0
|
||||||
|
stream.Wait = 0
|
||||||
|
stream.NetworkBandwidth = networkBandwidth
|
||||||
|
|
||||||
}
|
playlist.Streams[streamID] = stream
|
||||||
|
|
||||||
var addErrorToStream = func(err error) {
|
timeOut++
|
||||||
|
|
||||||
var stream = playlist.Streams[streamID]
|
|
||||||
|
|
||||||
if c, ok := BufferClients.Load(stream.PlaylistID + stream.MD5); ok {
|
|
||||||
|
|
||||||
var clients = c.(ClientConnection)
|
|
||||||
clients.Error = err
|
|
||||||
BufferClients.Store(stream.PlaylistID+stream.MD5, clients)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
var addErrorToStream = func(err error) {
|
||||||
|
|
||||||
os.RemoveAll(getPlatformPath(tmpFolder))
|
var stream = playlist.Streams[streamID]
|
||||||
|
|
||||||
err := checkFolder(tmpFolder)
|
if c, ok := BufferClients.Load(playlistID + stream.MD5); ok {
|
||||||
if err != nil {
|
|
||||||
ShowError(err, 0)
|
|
||||||
addErrorToStream(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// M3U8 Segmente
|
var clients = c.(ClientConnection)
|
||||||
InitBuffer:
|
clients.Error = err
|
||||||
defaultSegment()
|
BufferClients.Store(playlistID+stream.MD5, clients)
|
||||||
|
|
||||||
if len(m3u8Segments) > 30 {
|
}
|
||||||
m3u8Segments = m3u8Segments[15:]
|
|
||||||
}
|
|
||||||
if timeOut >= 10 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var stream ThisStream = playlist.Streams[streamID]
|
|
||||||
|
|
||||||
if stream.Status == false {
|
|
||||||
|
|
||||||
if strings.Index(stream.URL, ".m3u8") != -1 {
|
|
||||||
showInfo("Streaming Type:" + "[HLS / M3U8]")
|
|
||||||
} else {
|
|
||||||
showInfo("Streaming Type:" + "[TS]")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
showInfo("Streaming URL:" + stream.URL)
|
os.RemoveAll(getPlatformPath(tmpFolder))
|
||||||
|
|
||||||
}
|
err := checkFolder(tmpFolder)
|
||||||
|
if err != nil {
|
||||||
var s = 0
|
ShowError(err, 0)
|
||||||
|
addErrorToStream(err)
|
||||||
stream.TimeStart = time.Now()
|
|
||||||
bandwidth.Start = stream.TimeStart
|
|
||||||
bandwidth.Size = 0
|
|
||||||
|
|
||||||
for {
|
|
||||||
|
|
||||||
if clientConnection(stream) == false {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(stream.Segment) == 0 || len(stream.URL) == 0 {
|
// M3U8 Segmente
|
||||||
goto InitBuffer
|
InitBuffer:
|
||||||
|
defaultSegment()
|
||||||
|
|
||||||
|
if len(m3u8Segments) > 30 {
|
||||||
|
m3u8Segments = m3u8Segments[15:]
|
||||||
|
}
|
||||||
|
if timeOut >= 10 {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var segment = stream.Segment[0]
|
var stream ThisStream = playlist.Streams[streamID]
|
||||||
|
|
||||||
var currentURL = strings.Trim(segment.URL, "\r\n")
|
if stream.Status == false {
|
||||||
|
|
||||||
|
if strings.Index(stream.URL, ".m3u8") != -1 {
|
||||||
|
showInfo("Streaming Type:" + "[HLS / M3U8]")
|
||||||
|
} else {
|
||||||
|
showInfo("Streaming Type:" + "[TS]")
|
||||||
|
}
|
||||||
|
|
||||||
|
showInfo("Streaming URL:" + stream.URL)
|
||||||
|
|
||||||
if len(currentURL) == 0 {
|
|
||||||
goto InitBuffer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
debug = fmt.Sprintf("Connection to:%s", currentURL)
|
var s = 0
|
||||||
showDebug(debug, 2)
|
|
||||||
|
|
||||||
// Sprung für Redirect (301 <---> 308)
|
stream.TimeStart = time.Now()
|
||||||
Redirect:
|
bandwidth.Start = stream.TimeStart
|
||||||
|
bandwidth.Size = 0
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", currentURL, nil)
|
for {
|
||||||
req.Header.Set("User-Agent", Settings.UserAgent)
|
|
||||||
req.Header.Set("Connection", "close")
|
|
||||||
//req.Header.Set("Range", "bytes=0-")
|
|
||||||
req.Header.Set("Accept", "*/*")
|
|
||||||
debugRequest(req)
|
|
||||||
|
|
||||||
client := &http.Client{}
|
|
||||||
client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
|
||||||
return errors.New("Redirect")
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
|
|
||||||
if resp != nil && err != nil {
|
|
||||||
debugResponse(resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
|
|
||||||
if resp == nil {
|
|
||||||
|
|
||||||
err = errors.New("No response from streaming server")
|
|
||||||
fmt.Println("Current URL:", currentURL)
|
|
||||||
ShowError(err, 0)
|
|
||||||
|
|
||||||
addErrorToStream(err)
|
|
||||||
|
|
||||||
killClientConnection(streamID, stream.PlaylistID, true)
|
|
||||||
clientConnection(stream)
|
|
||||||
|
|
||||||
|
if clientConnection(stream) == false {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect
|
if len(stream.Segment) == 0 || len(stream.URL) == 0 {
|
||||||
if resp.StatusCode >= 301 && resp.StatusCode <= 308 {
|
goto InitBuffer
|
||||||
|
}
|
||||||
|
|
||||||
debug = fmt.Sprintf("Streaming Status:HTTP response status [%d] %s", resp.StatusCode, http.StatusText(resp.StatusCode))
|
var segment = stream.Segment[0]
|
||||||
showDebug(debug, 2)
|
|
||||||
|
|
||||||
currentURL = strings.Trim(resp.Header.Get("Location"), "\r\n")
|
var currentURL = strings.Trim(segment.URL, "\r\n")
|
||||||
|
|
||||||
stream.Location = currentURL
|
if len(currentURL) == 0 {
|
||||||
|
goto InitBuffer
|
||||||
|
}
|
||||||
|
|
||||||
if len(currentURL) > 0 {
|
debug = fmt.Sprintf("Connection to:%s", currentURL)
|
||||||
|
showDebug(debug, 2)
|
||||||
|
|
||||||
debug = fmt.Sprintf("HTTP Redirect:%s", stream.Location)
|
// Sprung für Redirect (301 <---> 308)
|
||||||
|
Redirect:
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", currentURL, nil)
|
||||||
|
req.Header.Set("User-Agent", Settings.UserAgent)
|
||||||
|
req.Header.Set("Connection", "close")
|
||||||
|
//req.Header.Set("Range", "bytes=0-")
|
||||||
|
req.Header.Set("Accept", "*/*")
|
||||||
|
debugRequest(req)
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
||||||
|
return errors.New("Redirect")
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
|
||||||
|
if resp != nil && err != nil {
|
||||||
|
debugResponse(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
if resp == nil {
|
||||||
|
|
||||||
|
err = errors.New("No response from streaming server")
|
||||||
|
fmt.Println("Current URL:", currentURL)
|
||||||
|
ShowError(err, 0)
|
||||||
|
|
||||||
|
addErrorToStream(err)
|
||||||
|
|
||||||
|
killClientConnection(streamID, playlistID, true)
|
||||||
|
clientConnection(stream)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect
|
||||||
|
if resp.StatusCode >= 301 && resp.StatusCode <= 308 {
|
||||||
|
|
||||||
|
debug = fmt.Sprintf("Streaming Status:HTTP response status [%d] %s", resp.StatusCode, http.StatusText(resp.StatusCode))
|
||||||
showDebug(debug, 2)
|
showDebug(debug, 2)
|
||||||
defer resp.Body.Close()
|
|
||||||
goto Redirect
|
currentURL = strings.Trim(resp.Header.Get("Location"), "\r\n")
|
||||||
|
|
||||||
|
stream.Location = currentURL
|
||||||
|
|
||||||
|
if len(currentURL) > 0 {
|
||||||
|
|
||||||
|
debug = fmt.Sprintf("HTTP Redirect:%s", stream.Location)
|
||||||
|
showDebug(debug, 2)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
goto Redirect
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
err = errors.New("Streaming server")
|
||||||
|
ShowError(err, 4002)
|
||||||
|
addErrorToStream(err)
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
err = errors.New("Streaming server")
|
ShowError(err, 0)
|
||||||
ShowError(err, 4002)
|
|
||||||
addErrorToStream(err)
|
addErrorToStream(err)
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
@@ -685,293 +700,232 @@ InitBuffer:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
ShowError(err, 0)
|
|
||||||
addErrorToStream(err)
|
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
}
|
// HTTP Status überprüfen, bei Fehlern wird der Stream beendet
|
||||||
|
var contentType = resp.Header.Get("Content-Type")
|
||||||
|
var httpStatusCode = resp.StatusCode
|
||||||
|
var httpStatusInfo = fmt.Sprintf("HTTP Response Status [%d] %s", httpStatusCode, http.StatusText(resp.StatusCode))
|
||||||
|
|
||||||
defer resp.Body.Close()
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
|
||||||
// HTTP Status überprüfen, bei Fehlern wird der Stream beendet
|
showInfo("Content Type:" + contentType)
|
||||||
var contentType = resp.Header.Get("Content-Type")
|
showInfo("Streaming Status:" + httpStatusInfo)
|
||||||
var httpStatusCode = resp.StatusCode
|
showInfo("Error with this URL:" + currentURL)
|
||||||
var httpStatusInfo = fmt.Sprintf("HTTP Response Status [%d] %s", httpStatusCode, http.StatusText(resp.StatusCode))
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
var err = errors.New(http.StatusText(resp.StatusCode))
|
||||||
|
ShowError(err, 4004)
|
||||||
|
|
||||||
showInfo("Content Type:" + contentType)
|
debug = fmt.Sprintf("Streaming Status:Playlist: %s - Tuner: %d / %d", playlist.PlaylistName, len(playlist.Streams), playlist.Tuner)
|
||||||
showInfo("Streaming Status:" + httpStatusInfo)
|
showDebug(debug, 1)
|
||||||
showInfo("Error with this URL:" + currentURL)
|
|
||||||
|
|
||||||
var err = errors.New(http.StatusText(resp.StatusCode))
|
BufferInformation.Store(playlist.PlaylistID, playlist)
|
||||||
ShowError(err, 4004)
|
|
||||||
|
|
||||||
debug = fmt.Sprintf("Streaming Status:Playlist: %s - Tuner: %d / %d", playlist.PlaylistName, len(playlist.Streams), playlist.Tuner)
|
|
||||||
showDebug(debug, 1)
|
|
||||||
|
|
||||||
BufferInformation.Store(playlist.PlaylistID, playlist)
|
|
||||||
addErrorToStream(err)
|
|
||||||
|
|
||||||
killClientConnection(streamID, stream.PlaylistID, true)
|
|
||||||
clientConnection(stream)
|
|
||||||
resp.Body.Close()
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Informationen über den Streamingserver auslesen
|
|
||||||
if stream.Status == false {
|
|
||||||
|
|
||||||
if len(stream.URLStreamingServer) == 0 {
|
|
||||||
|
|
||||||
u, _ := url.Parse(currentURL)
|
|
||||||
p, _ := url.Parse(currentURL)
|
|
||||||
|
|
||||||
stream.URLScheme = u.Scheme
|
|
||||||
stream.URLHost = req.Host
|
|
||||||
stream.URLPath = p.Path
|
|
||||||
stream.URLFile = path.Base(p.Path)
|
|
||||||
|
|
||||||
stream.URLRedirect = fmt.Sprintf("%s://%s%s", stream.URLScheme, stream.URLHost, stream.URLPath)
|
|
||||||
stream.URLStreamingServer = fmt.Sprintf("%s://%s", stream.URLScheme, stream.URLHost)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
debug = fmt.Sprintf("Server URL:%s", stream.URLStreamingServer)
|
|
||||||
showDebug(debug, 1)
|
|
||||||
|
|
||||||
debug = fmt.Sprintf("Temp Folder:%s", tmpFolder)
|
|
||||||
showDebug(debug, 1)
|
|
||||||
|
|
||||||
showInfo("Streaming Status:" + "HTTP Response Status [" + strconv.Itoa(resp.StatusCode) + "] " + http.StatusText(resp.StatusCode))
|
|
||||||
showInfo("Content Type:" + contentType)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
debug = fmt.Sprintf("Content Type:%s", contentType)
|
|
||||||
showDebug(debug, 2)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Content Type bereinigen
|
|
||||||
if len(contentType) > 0 {
|
|
||||||
var ct = strings.SplitN(contentType, ";", 2)
|
|
||||||
contentType = strings.ToLower(ct[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
switch contentType {
|
|
||||||
|
|
||||||
// M3U8 Playlist
|
|
||||||
case "application/x-mpegurl", "application/vnd.apple.mpegurl", "audio/mpegurl":
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
ShowError(err, 0)
|
|
||||||
addErrorToStream(err)
|
addErrorToStream(err)
|
||||||
}
|
|
||||||
|
|
||||||
stream.Body = string(body)
|
killClientConnection(streamID, playlistID, true)
|
||||||
stream.HLS = true
|
clientConnection(stream)
|
||||||
stream.M3U8URL = currentURL
|
|
||||||
|
|
||||||
err = parseM3U8(&stream)
|
|
||||||
if err != nil {
|
|
||||||
ShowError(err, 4050)
|
|
||||||
addErrorToStream(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Video Stream (TS)
|
|
||||||
case "video/mpeg", "video/mp4", "video/mp2t", "video/m2ts", "application/octet-stream", "binary/octet-stream", "application/mp2t":
|
|
||||||
|
|
||||||
var fileSize int
|
|
||||||
|
|
||||||
// Größe des Buffers
|
|
||||||
buffer := make([]byte, 1024*Settings.BufferSize*2)
|
|
||||||
var tmpFileSize = 1024 * Settings.BufferSize * 1
|
|
||||||
|
|
||||||
debug = fmt.Sprintf("Buffer Size:%d KB [SERVER CONNECTION]", len(buffer)/1024)
|
|
||||||
showDebug(debug, 3)
|
|
||||||
|
|
||||||
debug = fmt.Sprintf("Buffer Size:%d KB [CLIENT CONNECTION]", tmpFileSize/1024)
|
|
||||||
showDebug(debug, 3)
|
|
||||||
|
|
||||||
var tmpFile = fmt.Sprintf("%s%d.ts", tmpFolder, tmpSegment)
|
|
||||||
|
|
||||||
if clientConnection(stream) == false {
|
|
||||||
resp.Body.Close()
|
resp.Body.Close()
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferFile, err := os.Create(tmpFile)
|
// Informationen über den Streamingserver auslesen
|
||||||
if err != nil {
|
if stream.Status == false {
|
||||||
|
|
||||||
addErrorToStream(err)
|
if len(stream.URLStreamingServer) == 0 {
|
||||||
bufferFile.Close()
|
|
||||||
resp.Body.Close()
|
u, _ := url.Parse(currentURL)
|
||||||
return
|
p, _ := url.Parse(currentURL)
|
||||||
|
|
||||||
|
stream.URLScheme = u.Scheme
|
||||||
|
stream.URLHost = req.Host
|
||||||
|
stream.URLPath = p.Path
|
||||||
|
stream.URLFile = path.Base(p.Path)
|
||||||
|
|
||||||
|
stream.URLRedirect = fmt.Sprintf("%s://%s%s", stream.URLScheme, stream.URLHost, stream.URLPath)
|
||||||
|
stream.URLStreamingServer = fmt.Sprintf("%s://%s", stream.URLScheme, stream.URLHost)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
debug = fmt.Sprintf("Server URL:%s", stream.URLStreamingServer)
|
||||||
|
showDebug(debug, 1)
|
||||||
|
|
||||||
|
debug = fmt.Sprintf("Temp Folder:%s", tmpFolder)
|
||||||
|
showDebug(debug, 1)
|
||||||
|
|
||||||
|
showInfo("Streaming Status:" + "HTTP Response Status [" + strconv.Itoa(resp.StatusCode) + "] " + http.StatusText(resp.StatusCode))
|
||||||
|
showInfo("Content Type:" + contentType)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
debug = fmt.Sprintf("Content Type:%s", contentType)
|
||||||
|
showDebug(debug, 2)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
// Content Type bereinigen
|
||||||
|
if len(contentType) > 0 {
|
||||||
|
var ct = strings.SplitN(contentType, ";", 2)
|
||||||
|
contentType = strings.ToLower(ct[0])
|
||||||
|
}
|
||||||
|
|
||||||
if fileSize == 0 {
|
switch contentType {
|
||||||
|
|
||||||
debug = fmt.Sprintf("Buffer Status:Buffering (%s)", tmpFile)
|
|
||||||
showDebug(debug, 2)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
timeOut = 0
|
|
||||||
// Buffer mit Daten vom Server füllen
|
|
||||||
n, err := resp.Body.Read(buffer)
|
|
||||||
|
|
||||||
if err != nil && err != io.EOF {
|
|
||||||
|
|
||||||
|
// M3U8 Playlist
|
||||||
|
case "application/x-mpegurl", "application/vnd.apple.mpegurl", "audio/mpegurl":
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
ShowError(err, 0)
|
ShowError(err, 0)
|
||||||
addErrorToStream(err)
|
addErrorToStream(err)
|
||||||
resp.Body.Close()
|
|
||||||
return
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close()
|
stream.Body = string(body)
|
||||||
|
stream.HLS = true
|
||||||
|
stream.M3U8URL = currentURL
|
||||||
|
|
||||||
if _, err := bufferFile.Write(buffer[:n]); err != nil {
|
err = parseM3U8(&stream)
|
||||||
|
if err != nil {
|
||||||
ShowError(err, 0)
|
ShowError(err, 4050)
|
||||||
addErrorToStream(err)
|
addErrorToStream(err)
|
||||||
resp.Body.Close()
|
|
||||||
return
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defer bufferFile.Close()
|
// Video Stream (TS)
|
||||||
|
case "video/mpeg", "video/mp4", "video/mp2t", "video/m2ts", "application/octet-stream", "binary/octet-stream", "application/mp2t":
|
||||||
|
|
||||||
fileSize = fileSize + n
|
var fileSize int
|
||||||
|
|
||||||
|
// Größe des Buffers
|
||||||
|
buffer := make([]byte, 1024*Settings.BufferSize*2)
|
||||||
|
var tmpFileSize = 1024 * Settings.BufferSize * 1
|
||||||
|
|
||||||
|
debug = fmt.Sprintf("Buffer Size:%d KB [SERVER CONNECTION]", len(buffer)/1024)
|
||||||
|
showDebug(debug, 3)
|
||||||
|
|
||||||
|
debug = fmt.Sprintf("Buffer Size:%d KB [CLIENT CONNECTION]", tmpFileSize/1024)
|
||||||
|
showDebug(debug, 3)
|
||||||
|
|
||||||
|
var tmpFile = fmt.Sprintf("%s%d.ts", tmpFolder, tmpSegment)
|
||||||
|
|
||||||
if clientConnection(stream) == false {
|
if clientConnection(stream) == false {
|
||||||
|
|
||||||
resp.Body.Close()
|
resp.Body.Close()
|
||||||
bufferFile.Close()
|
return
|
||||||
|
}
|
||||||
|
|
||||||
err = os.RemoveAll(stream.Folder)
|
bufferFile, err := os.Create(tmpFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ShowError(err, 4005)
|
|
||||||
}
|
addErrorToStream(err)
|
||||||
|
bufferFile.Close()
|
||||||
|
resp.Body.Close()
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Buffer auf die Festplatte speichern
|
for {
|
||||||
if fileSize >= tmpFileSize || n == 0 {
|
|
||||||
|
|
||||||
bandwidth.Stop = time.Now()
|
if fileSize == 0 {
|
||||||
bandwidth.Size += fileSize
|
|
||||||
|
|
||||||
bandwidth.TimeDiff = bandwidth.Stop.Sub(bandwidth.Start).Seconds()
|
debug = fmt.Sprintf("Buffer Status:Buffering (%s)", tmpFile)
|
||||||
|
showDebug(debug, 2)
|
||||||
|
|
||||||
networkBandwidth = int(float64(bandwidth.Size) / bandwidth.TimeDiff * 1000)
|
|
||||||
|
|
||||||
stream.NetworkBandwidth = networkBandwidth
|
|
||||||
bandwidth.NetworkBandwidth = stream.NetworkBandwidth
|
|
||||||
|
|
||||||
debug = fmt.Sprintf("Buffer Status:Done (%s)", tmpFile)
|
|
||||||
showDebug(debug, 2)
|
|
||||||
|
|
||||||
bufferFile.Close()
|
|
||||||
|
|
||||||
if stream.Status == false {
|
|
||||||
stream.Status = true
|
|
||||||
playlist.Streams[streamID] = stream
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpSegment++
|
timeOut = 0
|
||||||
|
// Buffer mit Daten vom Server füllen
|
||||||
|
n, err := resp.Body.Read(buffer)
|
||||||
|
|
||||||
tmpFile = fmt.Sprintf("%s%d.ts", tmpFolder, tmpSegment)
|
if err != nil && err != io.EOF {
|
||||||
|
|
||||||
|
ShowError(err, 0)
|
||||||
|
addErrorToStream(err)
|
||||||
|
resp.Body.Close()
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if _, err := bufferFile.Write(buffer[:n]); err != nil {
|
||||||
|
|
||||||
|
ShowError(err, 0)
|
||||||
|
addErrorToStream(err)
|
||||||
|
resp.Body.Close()
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
defer bufferFile.Close()
|
||||||
|
|
||||||
|
fileSize = fileSize + n
|
||||||
|
|
||||||
if clientConnection(stream) == false {
|
if clientConnection(stream) == false {
|
||||||
|
|
||||||
bufferFile.Close()
|
|
||||||
resp.Body.Close()
|
resp.Body.Close()
|
||||||
|
bufferFile.Close()
|
||||||
|
|
||||||
err = os.RemoveAll(stream.Folder)
|
err = os.RemoveAll(stream.Folder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ShowError(err, 4005)
|
ShowError(err, 4005)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferFile, err = os.Create(tmpFile)
|
// Buffer auf die Festplatte speichern
|
||||||
if err != nil {
|
if fileSize >= tmpFileSize || n == 0 {
|
||||||
addErrorToStream(err)
|
|
||||||
resp.Body.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fileSize = 0
|
bandwidth.Stop = time.Now()
|
||||||
|
bandwidth.Size += fileSize
|
||||||
|
|
||||||
|
bandwidth.TimeDiff = bandwidth.Stop.Sub(bandwidth.Start).Seconds()
|
||||||
|
|
||||||
|
networkBandwidth = int(float64(bandwidth.Size) / bandwidth.TimeDiff * 1000)
|
||||||
|
|
||||||
|
stream.NetworkBandwidth = networkBandwidth
|
||||||
|
bandwidth.NetworkBandwidth = stream.NetworkBandwidth
|
||||||
|
|
||||||
|
debug = fmt.Sprintf("Buffer Status:Done (%s)", tmpFile)
|
||||||
|
showDebug(debug, 2)
|
||||||
|
|
||||||
if n == 0 {
|
|
||||||
bufferFile.Close()
|
bufferFile.Close()
|
||||||
resp.Body.Close()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
stream.Status = true
|
||||||
|
playlist.Streams[streamID] = stream
|
||||||
|
BufferInformation.Store(playlistID, playlist)
|
||||||
|
|
||||||
}
|
tmpSegment++
|
||||||
|
|
||||||
//--
|
tmpFile = fmt.Sprintf("%s%d.ts", tmpFolder, tmpSegment)
|
||||||
|
|
||||||
// Umbekanntes Format
|
if clientConnection(stream) == false {
|
||||||
default:
|
|
||||||
showInfo("Content Type:" + resp.Header.Get("Content-Type"))
|
|
||||||
err = errors.New("Streaming error")
|
|
||||||
ShowError(err, 4003)
|
|
||||||
|
|
||||||
addErrorToStream(err)
|
bufferFile.Close()
|
||||||
resp.Body.Close()
|
resp.Body.Close()
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
s++
|
err = os.RemoveAll(stream.Folder)
|
||||||
|
if err != nil {
|
||||||
|
ShowError(err, 4005)
|
||||||
|
}
|
||||||
|
|
||||||
// Wartezeit für den Download das nächste Segments berechnen
|
return
|
||||||
if stream.HLS == true {
|
}
|
||||||
|
|
||||||
var sleep float64
|
bufferFile, err = os.Create(tmpFile)
|
||||||
|
if err != nil {
|
||||||
|
addErrorToStream(err)
|
||||||
|
resp.Body.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if segment.Duration > 0 {
|
fileSize = 0
|
||||||
|
|
||||||
stream.TimeEnd = time.Now()
|
if n == 0 {
|
||||||
stream.TimeDiff = stream.TimeEnd.Sub(stream.TimeStart).Seconds()
|
bufferFile.Close()
|
||||||
|
resp.Body.Close()
|
||||||
sleep = (segment.Duration - stream.TimeDiff) - (segment.Duration * 0.25)
|
|
||||||
|
|
||||||
if sleep < 0 {
|
|
||||||
sleep = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
debug = fmt.Sprintf("HLS Status:Download time: %f s | Segment duration: %f s | Sleep: %f s Sequence: %d", stream.TimeDiff, segment.Duration, sleep, segment.Sequence)
|
|
||||||
showDebug(debug, 1)
|
|
||||||
|
|
||||||
if sleep > 0 {
|
|
||||||
|
|
||||||
for i := 0.0; i < sleep*1000; i = i + 100 {
|
|
||||||
|
|
||||||
_ = i
|
|
||||||
time.Sleep(time.Duration(100) * time.Millisecond)
|
|
||||||
|
|
||||||
if _, err := os.Stat(stream.Folder); os.IsNotExist(err) {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -979,15 +933,66 @@ InitBuffer:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--
|
||||||
|
|
||||||
|
// Umbekanntes Format
|
||||||
|
default:
|
||||||
|
showInfo("Content Type:" + resp.Header.Get("Content-Type"))
|
||||||
|
err = errors.New("Streaming error")
|
||||||
|
ShowError(err, 4003)
|
||||||
|
|
||||||
|
addErrorToStream(err)
|
||||||
|
resp.Body.Close()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
s++
|
||||||
|
|
||||||
stream.Segment = stream.Segment[1:len(stream.Segment)]
|
// Wartezeit für den Download das nächste Segments berechnen
|
||||||
|
if stream.HLS == true {
|
||||||
|
|
||||||
resp.Body.Close()
|
var sleep float64
|
||||||
|
|
||||||
} // Ende for loop
|
if segment.Duration > 0 {
|
||||||
|
|
||||||
|
stream.TimeEnd = time.Now()
|
||||||
|
stream.TimeDiff = stream.TimeEnd.Sub(stream.TimeStart).Seconds()
|
||||||
|
|
||||||
|
sleep = (segment.Duration - stream.TimeDiff) - (segment.Duration * 0.25)
|
||||||
|
|
||||||
|
if sleep < 0 {
|
||||||
|
sleep = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
debug = fmt.Sprintf("HLS Status:Download time: %f s | Segment duration: %f s | Sleep: %f s Sequence: %d", stream.TimeDiff, segment.Duration, sleep, segment.Sequence)
|
||||||
|
showDebug(debug, 1)
|
||||||
|
|
||||||
|
if sleep > 0 {
|
||||||
|
|
||||||
|
for i := 0.0; i < sleep*1000; i = i + 100 {
|
||||||
|
|
||||||
|
_ = i
|
||||||
|
time.Sleep(time.Duration(100) * time.Millisecond)
|
||||||
|
|
||||||
|
if _, err := os.Stat(stream.Folder); os.IsNotExist(err) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.Segment = stream.Segment[1:len(stream.Segment)]
|
||||||
|
|
||||||
|
resp.Body.Close()
|
||||||
|
|
||||||
|
} // Ende for loop
|
||||||
|
|
||||||
|
} // Ende BufferInformation
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -620,6 +620,7 @@ func saveWizard(request RequestStruct) (nextStep int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buildXEPG(false)
|
buildXEPG(false)
|
||||||
|
System.ScanInProgress = 0
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
xteve.go
2
xteve.go
@@ -39,7 +39,7 @@ var GitHub = GitHubStruct{Branch: "master", User: "xteve-project", Repo: "xTeVe-
|
|||||||
const Name = "xTeVe"
|
const Name = "xTeVe"
|
||||||
|
|
||||||
// Version : Version, die Build Nummer wird in der main func geparst.
|
// Version : Version, die Build Nummer wird in der main func geparst.
|
||||||
const Version = "2.0.2.0020"
|
const Version = "2.0.2.0023"
|
||||||
|
|
||||||
// DBVersion : Datanbank Version
|
// DBVersion : Datanbank Version
|
||||||
const DBVersion = "2.0.0"
|
const DBVersion = "2.0.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user