Welcome to mirror list, hosted at ThFree Co, Russian Federation.

webcamd « bin « root « home « filesystem « octopi « modules « src - github.com/guysoft/OctoPi.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: effdfbe20b64f772a92aa37b13aa5a3135b33fcc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
#!/bin/bash

########################################################################
### DO NOT EDIT THIS FILE TO CHANGE THE CONFIG!!!                    ###
### ---------------------------------------------------------------- ###
### There is no need to edit this file for changing resolution,      ###
### frame rates or any other mjpg-streamer parameters. Please edit   ###
### /boot/octopi.txt instead - that's what it's there for! You can   ###
### even do this with your Pi powered down by directly accessing the ###
### file when using the SD card as thumb drive in your regular       ###
### computer.                                                        ###
########################################################################

MJPGSTREAMER_HOME=/home/pi/mjpg-streamer
MJPGSTREAMER_INPUT_USB="input_uvc.so"
MJPGSTREAMER_INPUT_RASPICAM="input_raspicam.so"

brokenfps_usb_devices=("046d:082b" "1908:2310" "0458:708c" "0458:6006" "1e4e:0102" "0471:0311" "038f:6001" "046d:0804" "046d:0825" "046d:0994" "0ac8:3450")

config_dir="/boot/octopi.conf.d"

echo "Starting up webcamDaemon..."
echo ""

cfg_files=()
cfg_files+=/boot/octopi.txt
if [[ -d ${config_dir} ]]; then
  cfg_files+=( `ls ${config_dir}/*.txt` )
fi

array_camera_config=()
array_camera=()
array_camera_usb_options=()
array_camera_usb_device=()
array_camera_raspi_options=()
array_camera_http_webroot=()
array_camera_http_options=()
array_additional_brokenfps_usb_devices=()
array_camera_device=()
array_assigned_device=()

echo "--- Configuration: ----------------------------"
for cfg_file in ${cfg_files[@]}; do
  # init configuration - DO NOT EDIT, USE /boot/octopi.conf.d/*.txt INSTEAD!
  camera="auto"
  camera_usb_options="-r 640x480 -f 10"
  camera_raspi_options="-fps 10"
  camera_http_webroot="./www-octopi"
  camera_http_options="-n --listen 127.0.0.1"
  additional_brokenfps_usb_devices=()

  if [[ -e ${cfg_file} ]]; then
      source "$cfg_file"
  fi
  usb_options="$camera_usb_options"

  # if webcam device is explicitly given in /boot/octopi.txt, save the path of the device
  # to a variable and remove its parameter from usb_options
  extracted_device=`echo $usb_options | sed 's@.*-d \(/dev/\(video[0-9]\+\|v4l/[^ ]*\)\).*@\1@'`
  if [ "$extracted_device" != "$usb_options" ]
  then
    # the camera options refer to a device, save it in a variable
    # replace video device parameter with empty string and strip extra whitespace
    usb_options=`echo $usb_options | sed 's/\-d \/dev\/\(video[0-9]\+\|v4l\/[^ ]*\)//g' | awk '$1=$1'`
  else
    extracted_device=""
  fi

  # echo configuration
  echo "cfg_file:      $cfg_file"
  echo "camera:        $camera"
  echo "usb options:   $camera_usb_options"
  echo "raspi options: $camera_raspi_options"
  echo "http options:  -w $camera_http_webroot $camera_http_options"
  echo ""
  echo "Explicitly USB device: $extracted_device"
  echo "-----------------------------------------------"
  echo ""

  array_camera_config+=( $cfg_file )
  array_camera+=( $camera )
  array_camera_usb_options+=("$usb_options")
  array_camera_usb_device+=("$extracted_device")
  array_camera_raspi_options+=("$camera_raspi_options")
  array_camera_http_webroot+=("$camera_http_webroot")
  array_camera_http_options+=("$camera_http_options")
  array_camera_brokenfps_usb_devices+=("${brokenfps_usb_devices[*]} ${additional_brokenfps_usb_devices[*]}")
  array_camera_device+=("")
done

# check if array contains a string
function containsString() {
  local e match="$1"
  shift
  for e; do [[ "$e" == "$match" ]] && return 0; done
  return 1
}

# cleans up when the script receives a SIGINT or SIGTERM
function cleanup() {
    # make sure that all child processed die when we die
    local pids=$(jobs -pr)
    [ -n "$pids" ] && kill $pids
    exit 0
}

# says goodbye when the script shuts down
function goodbye() {
    # say goodbye
    echo ""
    echo "Goodbye..."
    echo ""
}

# runs MJPG Streamer, using the provided input plugin + configuration
function runMjpgStreamer {
    input=$1

    # There are problems with 0x000137ab firmware on VL805 (Raspberry Pi 4}).
    # Try to autodetect offending firmware and temporarily fix the issue
    # by changing power management mode
    echo "Checking for VL805 (Raspberry Pi 4)..."
    if [[ -f /usr/bin/vl805 ]]; then
        VL805_VERSION=$(/usr/bin/vl805)
        VL805_VERSION=${VL805_VERSION#*: }
        echo " - version 0x${VL805_VERSION} detected"
        case "$VL805_VERSION" in
            00013701)
                echo "    - nothing to be done. It shouldn't cause USB problems."
                ;;
            000137ab)
                echo -e "    - \e[31mThis version is known to cause problems with USB cameras.\e[39m"
                echo -e "      You may want to downgrade to 0x0013701."
                echo -e "    - [FIXING] Trying the setpci -s 01:00.0 0xD4.B=0x41 hack to mitigate the"
                echo -e "      issue. It disables ASPM L1 on the VL805. Your board may (or may not) get"
                echo -e "      slightly hotter. For details see:"
                echo -e "      https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=244421"
                setpci -s 01:00.0 0xD4.B=0x41
                ;;
            *)
                echo "   - unknown firmware version. Doing nothing."
                ;;
        esac
    else
        echo "  - It seems that you don't have VL805 (Raspberry Pi 4)."
        echo "    There should be no problems with USB (a.k.a. select() timeout)"
    fi

    pushd $MJPGSTREAMER_HOME > /dev/null 2>&1
        echo Running ./mjpg_streamer -o "output_http.so -w $camera_http_webroot $camera_http_options" -i "$input"
        LD_LIBRARY_PATH=. ./mjpg_streamer -o "output_http.so -w $camera_http_webroot $camera_http_options" -i "$input" &
        sleep 1 &
        sleep_pid=$!
        wait ${sleep_pid}
    popd > /dev/null 2>&1
}

# starts up the RasPiCam
function startRaspi {
    logger -s "Starting Raspberry Pi camera"
    runMjpgStreamer "$MJPGSTREAMER_INPUT_RASPICAM $camera_raspi_options"
}

# starts up the USB webcam
function startUsb {
    options="$usb_options"
    device="video0"

    # check for parameter and set the device if it is given as a parameter
    input=$1
    if [[ -n $input ]]; then
        device=`basename "$input"`
    fi

    # add video device into options
    options="$options -d /dev/$device"

    uevent_file="/sys/class/video4linux/$device/device/uevent"
    if [ -e $uevent_file ]; then
        # let's see what kind of webcam we have here, fetch vid and pid...
        product=`cat $uevent_file | grep PRODUCT | cut -d"=" -f2`
        vid=`echo $product | cut -d"/" -f1`
        pid=`echo $product | cut -d"/" -f2`
        vidpid=`printf "%04x:%04x" "0x$vid" "0x$pid"`

        # ... then look if it is in our list of known broken-fps-devices and if so remove
        # the -f parameter from the options (if it's in there, else that's just a no-op)
        for identifier in ${brokenfps_usb_devices[@]};
        do
            if [ "$vidpid" = "$identifier" ]; then
                echo
                echo "Camera model $vidpid is known to not work with -f parameter, stripping it out"
                echo
                options=`echo $options | sed -e "s/\(\s\+\|^\)-f\s\+[0-9]\+//g"`
            fi
        done
    fi

    logger -s "Starting USB webcam"
    runMjpgStreamer "$MJPGSTREAMER_INPUT_USB $options"
}

# make sure our cleanup function gets called when we receive SIGINT, SIGTERM
trap "cleanup" SIGINT SIGTERM
# say goodbye when we EXIT
trap "goodbye" EXIT

# we need this to prevent the later calls to vcgencmd from blocking
# I have no idea why, but that's how it is...
vcgencmd version > /dev/null 2>&1

# keep mjpg streamer running if some camera is attached
while true; do

  # get list of usb video devices into an array
  video_devices=($(find /dev -regextype sed -regex '\/dev/video[0-9]\+' | sort 2> /dev/null))

  # add list of raspi camera into an array
  if [ "`vcgencmd get_camera`" = "supported=1 detected=1" ]; then
    video_devices+=( "raspi" )
  fi

  echo "Found video devices:"
  printf '%s\n' "${video_devices[@]}"

  for scan_mode in "usb" "usb-auto" "raspi" "auto"; do
    camera=$scan_mode
    if [[ "usb-auto" == "$scan_mode" ]]; then
      camera="usb"
    fi
    for ((i=0;i<${#array_camera[@]};i++));  do
      if [[ -z ${array_camera_device[${i}]} ]] && [[ $camera == ${array_camera[${i}]} ]]; then
        camera_config="${array_camera_config[${i}]}"
        usb_options="${array_camera_usb_options[${i}]}"
        camera_usb_device="${array_camera_usb_device[${i}]}"
        camera_raspi_options="${array_camera_raspi_options[${i}]}"
        camera_http_webroot="${array_camera_http_webroot[${i}]}"
        camera_http_options="${array_camera_http_options[${i}]}"
        brokenfps_usb_devices="${array_camera_brokenfps_usb_devices[${i}]}"
        if [[ ${camera_usb_device} ]] && { [[ "usb" == ${scan_mode} ]] || [[ "auto" == ${scan_mode} ]]; }; then
           # usb device is explicitly set in options
          usb_device_path=`readlink -f ${camera_usb_device}`
          if containsString "$usb_device_path" "${array_camera_device[@]}"; then
            if [[ "auto" != ${scan_mode} ]]; then
              array_camera_device[${i}]="alredy_in_use"
              echo "config file='$camera_config':Video device already in use."
              continue
            fi
          elif containsString "$usb_device_path" "${video_devices[@]}"; then
            array_camera_device[${i}]="$usb_device_path"
            # explicitly set usb device was found in video_devices array, start usb with the found device
            echo "config file='$camera_config':USB device was set in options and found in devices, start MJPG-streamer with the configured USB video device: $usb_device_path"
            startUsb "$usb_device_path"
            continue
          fi
        elif [[ -z ${camera_usb_device} ]] && { [[ "usb-auto" == ${scan_mode} ]] || [[ "auto" == ${scan_mode} ]]; }; then
          for video_device in "${video_devices[@]}"; do
            if [[ "raspi" != "$video_device" ]]; then
              if containsString "$video_device" "${array_camera_device[@]}"; then
                : #already in use
              else
                array_camera_device[${i}]="$video_device"
                # device is not set explicitly in options, start usb with first found usb camera as the device
                echo "config file='$camera_config':USB device was not set in options, start MJPG-streamer with the first found video device: ${video_device}"
                startUsb "${video_device}"
                break
              fi
            fi
          done
          if [[ -n ${array_camera_device[${i}]} ]]; then
            continue
          fi
        fi
        if [[ "raspi" == ${scan_mode} ]] || [[ "auto" == ${scan_mode} ]]; then
          video_device="raspi"
          if containsString "$video_device" "${array_camera_device[@]}"; then
            if [[ "auto" != ${scan_mode} ]]; then
              array_camera_device[${i}]="alredy_in_use"
              echo "config file='$camera_config':RasPiCam device already in use."
            fi
          elif containsString "$video_device" "${video_devices[@]}"; then
            array_camera_device[${i}]="$video_device"
            echo "config file='$camera_config':Start MJPG-streamer with video device: ${video_device}"
            startRaspi
            sleep 30 &
            sleep_pid=$!
            wait ${sleep_pid}
          fi
        fi
      fi
    done
  done
  array_assigned_device=( ${array_camera_device[*]} )
  if [[ ${#array_camera[@]} -eq ${#array_assigned_device[@]} ]]; then
    echo "Done bring up all configured video device"
    exit 0
  else
    echo "Scan again in two minutes"
    sleep 120 &
    sleep_pid=$!
    wait ${sleep_pid}
  fi
done