-
-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Performance of JPEG decode/re-encode #6
Comments
How about to add DecodeRaw ? |
Could you please try this patch? diff --git a/_example/mjpegproxy.go b/_example/mjpegproxy.go
index 4186dff..65db818 100644
--- a/_example/mjpegproxy.go
+++ b/_example/mjpegproxy.go
@@ -1,12 +1,11 @@
+//go:build ignore
// +build ignore
package main
import (
- "bytes"
"context"
"flag"
- "image/jpeg"
"log"
"net/http"
"os"
@@ -31,18 +30,12 @@ func proxy(wg *sync.WaitGroup, stream *mjpeg.Stream) {
log.Fatal(err)
}
- var buf bytes.Buffer
for {
- img, err := dec.Decode()
+ b, err := dec.DecodeRaw()
if err != nil {
break
}
- buf.Reset()
- err = jpeg.Encode(&buf, img, nil)
- if err != nil {
- break
- }
- err = stream.Update(buf.Bytes())
+ err = stream.Update(b)
if err != nil {
break
}
diff --git a/mjpeg.go b/mjpeg.go
index b9b2c93..c60509f 100644
--- a/mjpeg.go
+++ b/mjpeg.go
@@ -1,6 +1,7 @@
package mjpeg
import (
+ "bytes"
"errors"
"fmt"
"image"
@@ -59,6 +60,20 @@ func (d *Decoder) Decode() (image.Image, error) {
return jpeg.Decode(p)
}
+// DecodeRaw do decoding raw bytes
+func (d *Decoder) DecodeRaw() ([]byte, error) {
+ p, err := d.r.NextPart()
+ if err != nil {
+ return nil, err
+ }
+ var buf bytes.Buffer
+ _, err = io.Copy(&buf, p)
+ if err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
type Stream struct {
m sync.Mutex
s map[chan []byte]struct{} |
Or one another patch. diff --git a/_example/mjpegproxy.go b/_example/mjpegproxy.go
index 4186dff..7f7824b 100644
--- a/_example/mjpegproxy.go
+++ b/_example/mjpegproxy.go
@@ -1,12 +1,12 @@
+//go:build ignore
// +build ignore
package main
import (
- "bytes"
"context"
"flag"
- "image/jpeg"
+ "io"
"log"
"net/http"
"os"
@@ -31,22 +31,7 @@ func proxy(wg *sync.WaitGroup, stream *mjpeg.Stream) {
log.Fatal(err)
}
- var buf bytes.Buffer
- for {
- img, err := dec.Decode()
- if err != nil {
- break
- }
- buf.Reset()
- err = jpeg.Encode(&buf, img, nil)
- if err != nil {
- break
- }
- err = stream.Update(buf.Bytes())
- if err != nil {
- break
- }
- }
+ io.Copy(stream, dec)
}
func main() {
diff --git a/mjpeg.go b/mjpeg.go
index b9b2c93..57dbdff 100644
--- a/mjpeg.go
+++ b/mjpeg.go
@@ -1,6 +1,7 @@
package mjpeg
import (
+ "bytes"
"errors"
"fmt"
"image"
@@ -59,6 +60,20 @@ func (d *Decoder) Decode() (image.Image, error) {
return jpeg.Decode(p)
}
+// DecodeRaw do decoding raw bytes
+func (d *Decoder) DecodeRaw() ([]byte, error) {
+ p, err := d.r.NextPart()
+ if err != nil {
+ return nil, err
+ }
+ var buf bytes.Buffer
+ _, err = io.Copy(&buf, p)
+ if err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
type Stream struct {
m sync.Mutex
s map[chan []byte]struct{}
@@ -95,6 +110,10 @@ func (s *Stream) Close() error {
return nil
}
+func (s *Stream) Write(b []byte) (int, error) {
+ return len(b), s.Update(b)
+}
+
func (s *Stream) Update(b []byte) error {
s.m.Lock()
defer s.m.Unlock() This should be good than previous. |
Added DecodeRaw. Thank you. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm having a little trouble with the performance of the library - my use-case is more-or-less exactly as [_example/mjpegproxy.go] - I'm reading several MJPEG streams and re-serving them. Looking at the code I notice that it effectively reads the JPEG bytes from each part, decodes that into an image.Image, then turns that image.Image back into bytes, which seems very inefficient?
I've tried skipping the JPEG decode -> encode and just writing the bytes from the part straight to the stream, but the output comes out very broken. I'd love to find a way to achieve this without needing the decode/encode step as I'm finding that's putting a lot of pressure on the CPU with multiple streams - I'm seeing it take on average between 50ms and 80ms per part, which isn't great for a 25fps stream.
I'll open a PR if I figure out a way to handle this, but otherwise I'd love to know what the decode->encode is doing under the hood, because it's clearly necessary!
The text was updated successfully, but these errors were encountered: