Page 1 of 1

when the server stop the stream transfering?

Posted: Thu Mar 23, 2023 3:30 am
by yangjun1222
HI, I am reading the web cam server example project. I write a simple c program using vs code.

Code: Untitled.c Select all


#include  "camera_index.h"
int main()
{
FILE *file = fopen("index1.bin", "w");
// Check if the file is opened successfully
if (file == NULL)
{
printf("Error opening file\\n");
return 1;
}
// Write each element of the array into the file
for (int i = 0; i < 4408; i++)
{
fputc(index_ov3660_html_gz[i], file);
// Close the file
fclose(file);
return 0;
}
then gzip -d index1.bin -c > index1.html, I get the html file (following ignore the css, html part of the file )

Code: Untitled.js Select all


document.addEventListener('DOMContentLoaded', function (event) {
var baseHost = document.location.origin
var streamUrl = baseHost + ':81'

const hide = el => {
el.classList.add('hidden')
}
const show = el => {
el.classList.remove('hidden')
}

const disable = el => {
el.classList.add('disabled')
el.disabled = true
}

const enable = el => {
el.classList.remove('disabled')
el.disabled = false
}

const updateValue = (el, value, updateRemote) => {
updateRemote = updateRemote == null ? true : updateRemote
let initialValue
if (el.type === 'checkbox') {
initialValue = el.checked
value = !!value
el.checked = value
} else {
initialValue = el.value
el.value = value
}

if (updateRemote && initialValue !== value) {
updateConfig(el);
} else if(!updateRemote){
if(el.id === "aec"){
value ? hide(exposure) : show(exposure)
} else if(el.id === "agc"){
if (value) {
show(gainCeiling)
hide(agcGain)
} else {
hide(gainCeiling)
show(agcGain)
}
} else if(el.id === "awb_gain"){
value ? show(wb) : hide(wb)
} else if(el.id === "face_recognize"){
value ? enable(enrollButton) : disable(enrollButton)
}
}
}

function updateConfig (el) {
let value
switch (el.type) {
case 'checkbox':
value = el.checked ? 1 : 0
break
case 'range':
case 'select-one':
value = el.value
break
case 'button':
case 'submit':
value = '1'
break
default:
return
}

const query = `${baseHost}/control?var=${el.id}&val=${value}`

fetch(query)
.then(response => {
console.log(`request to ${query} finished, status: ${response.status}`)
})
}

document
.querySelectorAll('.close')
.forEach(el => {
el.onclick = () => {
hide(el.parentNode)
}
})

// read initial values
fetch(`${baseHost}/status`)
.then(function (response) {
return response.json()
})
.then(function (state) {
document
.querySelectorAll('.default-action')
.forEach(el => {
updateValue(el, state[el.id], false)
})
})

const view = document.getElementById('stream')
const viewContainer = document.getElementById('stream-container')
const stillButton = document.getElementById('get-still')
const streamButton = document.getElementById('toggle-stream')
const enrollButton = document.getElementById('face_enroll')
const closeButton = document.getElementById('close-stream')

const stopStream = () => {
window.stop();
streamButton.innerHTML = 'Start Stream'
}

const startStream = () => {
view.src = `${streamUrl}/stream`
show(viewContainer)
streamButton.innerHTML = 'Stop Stream'
}

// Attach actions to buttons
stillButton.onclick = () => {
stopStream()
view.src = `${baseHost}/capture?_cb=${Date.now()}`
show(viewContainer)
}

closeButton.onclick = () => {
stopStream()
hide(viewContainer)
}

streamButton.onclick = () => {
const streamEnabled = streamButton.innerHTML === 'Stop Stream'
if (streamEnabled) {
stopStream()
} else {
startStream()
}
}

enrollButton.onclick = () => {
updateConfig(enrollButton)
}

// Attach default on change action
document
.querySelectorAll('.default-action')
.forEach(el => {
el.onchange = () => updateConfig(el)
})

// Custom actions
// Gain
const agc = document.getElementById('agc')
const agcGain = document.getElementById('agc_gain-group')
const gainCeiling = document.getElementById('gainceiling-group')
agc.onchange = () => {
updateConfig(agc)
if (agc.checked) {
show(gainCeiling)
hide(agcGain)
} else {
hide(gainCeiling)
show(agcGain)
}
}

// Exposure
const aec = document.getElementById('aec')
const exposure = document.getElementById('aec_value-group')
aec.onchange = () => {
updateConfig(aec)
aec.checked ? hide(exposure) : show(exposure)
}

// AWB
const awb = document.getElementById('awb_gain')
const wb = document.getElementById('wb_mode-group')
awb.onchange = () => {
updateConfig(awb)
awb.checked ? show(wb) : hide(wb)
}

// Detection and framesize
const detect = document.getElementById('face_detect')
const recognize = document.getElementById('face_recognize')
const framesize = document.getElementById('framesize')

framesize.onchange = () => {
updateConfig(framesize)
if (framesize.value > 5) {
updateValue(detect, false)
updateValue(recognize, false)
}
}

detect.onchange = () => {
if (framesize.value > 5) {
alert("Please select CIF or lower resolution before enabling this feature!");
updateValue(detect, false)
return;
}
updateConfig(detect)
if (!detect.checked) {
disable(enrollButton)
updateValue(recognize, false)
}
}

recognize.onchange = () => {
if (framesize.value > 5) {
alert("Please select CIF or lower resolution before enabling this feature!");
updateValue(recognize, false)
return;
}
updateConfig(recognize)
if (recognize.checked) {
enable(enrollButton)
updateValue(detect, true)
} else {
disable(enrollButton)
}
}
})
then I read the app_httpd.cpp and the index.html I got. I understand how the stream server start, but then it enters a dead loop. the browser stop the stream through : window.stop(), how does the server receive this message?I can not find a break in this dead loop which is caused by a request from browser?

Code: Untitled.c Select all


static esp_err_t stream_handler(httpd_req_t *req)
while(true){.......................}

Re: when the server stop the stream transfering?

Posted: Sat Mar 25, 2023 4:26 pm
by noweare
Good question.

No doubt that the javascript and the camera application is very advanced and not easily understood.
The furthest I could get was "stop stream" button on the browser is pressed which runs the stopStream function which executes window.stop command. window.stop command discontinues loading the stream-container and hides it from view. This causes
stream handler code on the esp32 to return a "send response error" while trying to send a chunk.

I am trying to learn advanced javascript/html/css using this application so I can use it in my own projects. Learning HTML and CSS
is not that difficult but integrating javascript with esp32 code is more of a challenge.

I know this answer is not complete and could be much better answered by an experienced programmer.

Good luck