github.com/aamcrae/webcam@v0.0.0-20210915060337-934acc13bdc3/examples/imageserver/server.go (about)

     1  // Copyright 2019 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     https://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Program that serves images taken from a webcam.
    16  package main
    17  
    18  import (
    19  	"flag"
    20  	"fmt"
    21  	"image/gif"
    22  	"image/jpeg"
    23  	"image/png"
    24  	"log"
    25  	"net/http"
    26  	"strconv"
    27  	"strings"
    28  	"time"
    29  
    30  	"github.com/aamcrae/webcam"
    31  	"github.com/aamcrae/webcam/frame"
    32  	"github.com/aamcrae/webcam/snapshot"
    33  )
    34  
    35  var port = flag.Int("port", 8080, "Web server port number")
    36  var path = flag.String("path", "image", "Image base filename")
    37  var device = flag.String("input", "/dev/video0", "Input video device")
    38  var resolution = flag.String("resolution", "800x600", "Camera resolution")
    39  var format = flag.String("format", "YUYV", "Pixel format of camera")
    40  var controls = flag.String("controls", "",
    41  	"Control parameters for camera (use --controls=list to list controls)")
    42  var startDelay = flag.Int("delay", 2, "Delay at start (seconds)")
    43  var verbose = flag.Bool("v", false, "Log more information")
    44  
    45  var cnames map[string]webcam.ControlID = map[string]webcam.ControlID{
    46  	"focus":                0x009a090a,
    47  	"power_line_frequency": 0x00980918,
    48  	"brightness":           0x00980900,
    49  	"contrast":             0x00980901,
    50  	"autoiso":              0x009a0918,
    51  	"autoexp":              0x009a0901,
    52  	"saturation":           0x00980902,
    53  	"sharpness":            0x0098091b,
    54  	"rotate":               0x00980922,
    55  	"stabilization":        0x009a0916,
    56  }
    57  
    58  func main() {
    59  	flag.Parse()
    60  	s := strings.Split(*resolution, "x")
    61  	if len(s) != 2 {
    62  		log.Fatalf("%s: Illegal resolution", *resolution)
    63  	}
    64  	x, err := strconv.Atoi(s[0])
    65  	if err != nil {
    66  		log.Fatalf("%s: illegal width: %v", s[0], err)
    67  	}
    68  	y, err := strconv.Atoi(s[1])
    69  	if err != nil {
    70  		log.Fatalf("%s: illegal height: %v", s[1], err)
    71  	}
    72  	if *controls == "list" {
    73  		fmt.Printf("Control list (not all cameras may support all options):\n")
    74  		for c, _ := range cnames {
    75  			fmt.Printf("    %s\n", c)
    76  		}
    77  		return
    78  	}
    79  	if *startDelay != 0 {
    80  		time.Sleep(time.Duration(*startDelay) * time.Second)
    81  	}
    82  	cm := snapshot.NewSnapper()
    83  	if err := cm.Open(*device, frame.FourCC(*format), x, y); err != nil {
    84  		log.Fatalf("%s: %v", *device, err)
    85  	}
    86  	if *startDelay != 0 {
    87  		time.Sleep(time.Duration(*startDelay) * time.Second)
    88  	}
    89  	defer cm.Close()
    90  	// Set camera controls.
    91  	if len(*controls) != 0 {
    92  		for _, control := range strings.Split(*controls, ",") {
    93  			s := strings.Split(control, "=")
    94  			if len(s) != 2 {
    95  				log.Fatalf("Bad control option: %s", control)
    96  			}
    97  			id, ok := cnames[s[0]]
    98  			if !ok {
    99  				log.Fatalf("%s: Unknown control", s[0])
   100  			}
   101  			val, err := strconv.Atoi(s[1])
   102  			if err != nil {
   103  				log.Fatalf("Bad control value: %s (%v)", control, err)
   104  			}
   105  			if *verbose {
   106  				fmt.Printf("Setting control '%s' to %d\n", s[0], val)
   107  			}
   108  			if err = cm.SetControl(id, int32(val)); err != nil {
   109  				log.Fatalf("SetControl error: %s (%v)", control, err)
   110  			}
   111  		}
   112  	}
   113  	encodeJpeg := func(w http.ResponseWriter, f frame.Frame) error {
   114  		w.Header().Set("Content-Type", "image/jpeg")
   115  		return jpeg.Encode(w, f, nil)
   116  	}
   117  	encodePNG := func(w http.ResponseWriter, f frame.Frame) error {
   118  		w.Header().Set("Content-Type", "image/png")
   119  		return png.Encode(w, f)
   120  	}
   121  	encodeGIF := func(w http.ResponseWriter, f frame.Frame) error {
   122  		w.Header().Set("Content-Type", "image/gif")
   123  		return gif.Encode(w, f, nil)
   124  	}
   125  	http.Handle(fmt.Sprintf("/%s.jpg", *path), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   126  		publishImage(cm, w, r, encodeJpeg)
   127  	}))
   128  	http.Handle(fmt.Sprintf("/%s.jpeg", *path), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   129  		publishImage(cm, w, r, encodeJpeg)
   130  	}))
   131  	http.Handle(fmt.Sprintf("/%s.png", *path), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   132  		publishImage(cm, w, r, encodePNG)
   133  	}))
   134  	http.Handle(fmt.Sprintf("/%s.gif", *path), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   135  		publishImage(cm, w, r, encodeGIF)
   136  	}))
   137  	url := fmt.Sprintf(":%d", *port)
   138  	if *verbose {
   139  		log.Printf("Starting server on %s", url)
   140  	}
   141  	server := &http.Server{Addr: url}
   142  	log.Fatal(server.ListenAndServe())
   143  }
   144  
   145  func publishImage(cm *snapshot.Snapper, w http.ResponseWriter, r *http.Request, encode func(http.ResponseWriter, frame.Frame) error) {
   146  	if *verbose {
   147  		log.Printf("URL request: %v", r.URL)
   148  	}
   149  	f, err := cm.Snap()
   150  	if err != nil {
   151  		log.Printf("Getframe: %v", err)
   152  		w.WriteHeader(http.StatusInternalServerError)
   153  		return
   154  	}
   155  	defer f.Release()
   156  	if err := encode(w, f); err != nil {
   157  		log.Printf("Error writing image: %v\n", err)
   158  		w.WriteHeader(http.StatusInternalServerError)
   159  	} else if *verbose {
   160  		log.Printf("Wrote image successfully\n")
   161  	}
   162  }