mirror of
https://github.com/Luzifer/cam2mjpeg.git
synced 2024-09-18 23:02:58 +00:00
Replace mjpeg reader to fix broken frames
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
ce8b98b9cb
commit
e0d5f6a195
44
main.go
44
main.go
@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@ -96,27 +95,46 @@ func main() {
|
|||||||
|
|
||||||
log.Debug("ffmpeg spawned")
|
log.Debug("ffmpeg spawned")
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
var (
|
||||||
|
br, bw int
|
||||||
|
buf = make([]byte, 10*1024*1024) // 10MB (jpg should be smaller)
|
||||||
|
)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if _, err := io.CopyN(buf, out, 1024); err != nil {
|
// If buffer was read, slide the remains to the beginning
|
||||||
log.WithError(err).Error("Failed to read ffmpeg output")
|
if br > 0 {
|
||||||
break
|
copy(buf, buf[br:bw])
|
||||||
|
bw -= br
|
||||||
|
br = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
eoj := bytes.Index(buf.Bytes(), endOfJPEG)
|
// Fill buffer
|
||||||
if eoj == -1 {
|
n, err := out.Read(buf[bw:])
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Fatal("Unable to read from output")
|
||||||
|
}
|
||||||
|
bw += n
|
||||||
|
|
||||||
|
if n == 0 {
|
||||||
|
// Nothing read, try again
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
img := buf.Next(eoj + len(endOfJPEG))
|
// Extract as many images as possible before next read
|
||||||
|
for eoj := bytes.Index(buf[br:bw], endOfJPEG); eoj >= 0; eoj = bytes.Index(buf[br:bw], endOfJPEG) {
|
||||||
|
eoj += len(endOfJPEG)
|
||||||
|
img := make([]byte, eoj-br)
|
||||||
|
copy(img, buf[br:br+eoj])
|
||||||
|
|
||||||
if !bytes.HasPrefix(img, beginOfJPEG) || !bytes.HasSuffix(img, endOfJPEG) {
|
br += eoj
|
||||||
log.Warn("Found invalid JPEG, skipping")
|
|
||||||
continue
|
if !bytes.HasPrefix(img, beginOfJPEG) || !bytes.HasSuffix(img, endOfJPEG) {
|
||||||
|
log.Warn("Found invalid JPEG, skipping")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
go sendImage(img)
|
||||||
}
|
}
|
||||||
|
|
||||||
go sendImage(img)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
mjpeg.go
2
mjpeg.go
@ -5,6 +5,7 @@ import (
|
|||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/textproto"
|
"net/textproto"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@ -38,6 +39,7 @@ func handleMJPEG(res http.ResponseWriter, r *http.Request, imgs chan []byte, uid
|
|||||||
err := func() error {
|
err := func() error {
|
||||||
partHeader := make(textproto.MIMEHeader)
|
partHeader := make(textproto.MIMEHeader)
|
||||||
partHeader.Add("Content-Type", "image/jpeg")
|
partHeader.Add("Content-Type", "image/jpeg")
|
||||||
|
partHeader.Add("Content-Length", strconv.Itoa(len(img)))
|
||||||
|
|
||||||
partWriter, err := mimeWriter.CreatePart(partHeader)
|
partWriter, err := mimeWriter.CreatePart(partHeader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user