mirror of
https://github.com/Motion-Project/motion.git
synced 2025-12-23 23:18:21 -05:00
12
conf.c
12
conf.c
@@ -80,6 +80,7 @@ struct config conf_template = {
|
||||
.ffmpeg_video_codec = DEF_FFMPEG_CODEC,
|
||||
.ipv6_enabled = 0,
|
||||
.stream_port = 0,
|
||||
.substream_port = 0,
|
||||
.stream_quality = 50,
|
||||
.stream_motion = 0,
|
||||
.stream_maxrate = 1,
|
||||
@@ -1054,6 +1055,17 @@ config_param config_params[] = {
|
||||
print_int
|
||||
},
|
||||
{
|
||||
"substream_port",
|
||||
"\n############################################################\n"
|
||||
"# Live Substream Server\n"
|
||||
"############################################################\n\n"
|
||||
"# The mini-http server listens to this port for requests (default: 0 = disabled)",
|
||||
0,
|
||||
CONF_OFFSET(substream_port),
|
||||
copy_int,
|
||||
print_int
|
||||
},
|
||||
{
|
||||
"stream_quality",
|
||||
"# Quality of the jpeg (in percent) images produced (default: 50)",
|
||||
0,
|
||||
|
||||
1
conf.h
1
conf.h
@@ -70,6 +70,7 @@ struct config {
|
||||
const char *ffmpeg_video_codec;
|
||||
int ipv6_enabled;
|
||||
int stream_port;
|
||||
int substream_port;
|
||||
int stream_quality;
|
||||
int stream_motion;
|
||||
int stream_maxrate;
|
||||
|
||||
10
event.c
10
event.c
@@ -334,7 +334,10 @@ static void event_stop_stream(struct context *cnt,
|
||||
struct timeval *tv1 ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if ((cnt->conf.stream_port) && (cnt->stream.socket != -1))
|
||||
stream_stop(cnt);
|
||||
stream_stop(&cnt->stream);
|
||||
|
||||
if ((cnt->conf.substream_port) && (cnt->substream.socket != -1))
|
||||
stream_stop(&cnt->substream);
|
||||
}
|
||||
|
||||
static void event_stream_put(struct context *cnt,
|
||||
@@ -343,7 +346,10 @@ static void event_stream_put(struct context *cnt,
|
||||
void *dummy2 ATTRIBUTE_UNUSED, struct timeval *tv1 ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (cnt->conf.stream_port)
|
||||
stream_put(cnt, img);
|
||||
stream_put(cnt, &cnt->stream, &cnt->stream_count, img, 0);
|
||||
|
||||
if (cnt->conf.substream_port)
|
||||
stream_put(cnt, &cnt->substream, &cnt->substream_count, img, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -466,6 +466,9 @@ ipv6_enabled off
|
||||
# The mini-http server listens to this port for requests (default: 0 = disabled)
|
||||
stream_port 8081
|
||||
|
||||
# 50% scaled down substream (default: 0 = disabled)
|
||||
# substream_port 8082
|
||||
|
||||
# Quality of the jpeg (in percent) images produced (default: 50)
|
||||
stream_quality 50
|
||||
|
||||
@@ -495,6 +498,7 @@ stream_auth_method 0
|
||||
; stream_authentication username:password
|
||||
|
||||
# Percentage to scale the stream image for preview
|
||||
# This is scaled on the browser side, motion will keep sending full frames
|
||||
# Default: 25
|
||||
; stream_preview_scale 25
|
||||
|
||||
|
||||
27
motion.c
27
motion.c
@@ -1131,7 +1131,8 @@ static int motion_init(struct context *cnt)
|
||||
|
||||
/* Initialize stream server if stream port is specified to not 0 */
|
||||
if (cnt->conf.stream_port) {
|
||||
if (stream_init(cnt) == -1) {
|
||||
if (stream_init (&(cnt->stream), cnt->conf.stream_port, cnt->conf.stream_localhost,
|
||||
cnt->conf.ipv6_enabled) == -1) {
|
||||
MOTION_LOG(ERR, TYPE_ALL, SHOW_ERRNO, "Problem enabling motion-stream server in port %d",
|
||||
cnt->conf.stream_port);
|
||||
cnt->conf.stream_port = 0;
|
||||
@@ -1142,6 +1143,30 @@ static int motion_init(struct context *cnt)
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize 50% scaled substream server if substream port is specified to not 0
|
||||
But only if dimensions are 8-modulo after scaling. Otherwise disable substream */
|
||||
if (cnt->conf.substream_port){
|
||||
if ((cnt->conf.width / 2) % 8 == 0 && (cnt->conf.height / 2) % 8 == 0
|
||||
&& cnt->imgs.type == VIDEO_PALETTE_YUV420P){
|
||||
if (stream_init (&(cnt->substream), cnt->conf.substream_port, cnt->conf.stream_localhost,
|
||||
cnt->conf.ipv6_enabled) == -1) {
|
||||
MOTION_LOG(ERR, TYPE_ALL, SHOW_ERRNO, "Problem enabling motion-substream server in port %d",
|
||||
cnt->conf.substream_port);
|
||||
cnt->conf.substream_port = 0;
|
||||
cnt->finish = 1;
|
||||
} else {
|
||||
MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO, "Started motion-substream server on port %d (auth %s)",
|
||||
cnt->conf.substream_port, cnt->conf.stream_auth_method ? "Enabled":"Disabled");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO support GRAY scale */
|
||||
MOTION_LOG(WRN, TYPE_ALL, NO_ERRNO, "Subtream does not support GRAY, and original resolution must be modulo of 16");
|
||||
cnt->conf.substream_port = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Prevent first few frames from triggering motion... */
|
||||
cnt->moved = 8;
|
||||
/* Initialize the double sized characters if needed. */
|
||||
|
||||
4
motion.h
4
motion.h
@@ -448,6 +448,10 @@ struct context {
|
||||
struct stream stream;
|
||||
int stream_count;
|
||||
|
||||
struct stream substream;
|
||||
int substream_count;
|
||||
|
||||
|
||||
#if defined(HAVE_MYSQL) || defined(HAVE_PGSQL) || defined(HAVE_SQLITE3)
|
||||
int sql_mask;
|
||||
#endif
|
||||
|
||||
@@ -1660,6 +1660,11 @@ Some configuration options are only used if Motion is built on a system that has
|
||||
<td align="left">stream_port</td>
|
||||
<td align="left"><a href="#stream_port" >stream_port</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td height="17" align="left"> </td>
|
||||
<td align="left"> </td>
|
||||
<td align="left"><a href="#substream_port" >substream_port</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td height="17" align="left"><br></td>
|
||||
<td align="left">stream_preview_newline</td>
|
||||
@@ -2231,22 +2236,23 @@ Some configuration options are only used if Motion is built on a system that has
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" ><a href="#ipv6_enabled" >ipv6_enabled</a> </td>
|
||||
<td bgcolor="#edf4f9" ><a href="#stream_port" >stream_port</a> </td>
|
||||
<td bgcolor="#edf4f9" ><a href="#substream_port" >substream_port</a> </td>
|
||||
<td bgcolor="#edf4f9" ><a href="#stream_quality" >stream_quality</a> </td>
|
||||
<td bgcolor="#edf4f9" ><a href="#stream_motion" >stream_motion</a> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" ><a href="#stream_maxrate" >stream_maxrate</a> </td>
|
||||
<td bgcolor="#edf4f9" ><a href="#stream_motion" >stream_motion</a> </td>
|
||||
<td bgcolor="#edf4f9" ><a href="#stream_maxrate" >stream_maxrate</a> </td>
|
||||
<td bgcolor="#edf4f9" ><a href="#stream_localhost" >stream_localhost</a> </td>
|
||||
<td bgcolor="#edf4f9" ><a href="#stream_limit" >stream_limit</a> </td>
|
||||
<td bgcolor="#edf4f9" ><a href="#stream_auth_method" >stream_auth_method</a> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" ><a href="#stream_auth_method" >stream_auth_method</a> </td>
|
||||
<td bgcolor="#edf4f9" ><a href="#stream_authentication" >stream_authentication</a> </td>
|
||||
<td bgcolor="#edf4f9" ><a href="#stream_preview_scale" >stream_preview_scale</a> </td>
|
||||
<td bgcolor="#edf4f9" ><a href="#stream_preview_newline" >stream_preview_newline</a> </td>
|
||||
<td bgcolor="#edf4f9" ><a href="#webcontrol_port" >webcontrol_port</a> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" ><a href="#webcontrol_port" >webcontrol_port</a> </td>
|
||||
<td bgcolor="#edf4f9" ><a href="#webcontrol_localhost" >webcontrol_localhost</a> </td>
|
||||
<td bgcolor="#edf4f9" ><a href="#webcontrol_html_output" >webcontrol_html_output</a> </td>
|
||||
<td bgcolor="#edf4f9" ><a href="#webcontrol_authentication" >webcontrol_authentication</a> </td>
|
||||
@@ -4825,6 +4831,23 @@ one camera, in which case it can be placed in motion.conf).
|
||||
|
||||
<p></p>
|
||||
|
||||
<h3><a name="substream_port"></a> substream_port </h3>
|
||||
<p></p>
|
||||
<ul>
|
||||
<li> Type: Integer</li>
|
||||
<li> Range / Valid values: 0 - 65535</li>
|
||||
<li> Default: 0 (disabled)</li>
|
||||
</ul>
|
||||
<p></p>
|
||||
# 50% scaled down substream (default: 0 = disabled)
|
||||
TCP port on which motion will listen for incoming connections to substream.
|
||||
Substream shares same settings as mini-http streaming server
|
||||
Image is scaled down by 50% including timestamp
|
||||
Substream can save bandwidth when viewing over mobile internet or poor wireless
|
||||
|
||||
<p></p>
|
||||
|
||||
|
||||
<h3><a name="stream_quality"></a> stream_quality </h3>
|
||||
<p></p>
|
||||
<ul>
|
||||
@@ -4934,6 +4957,7 @@ If the webcontrol page has HTML enabled, Motion displays all of the streams on t
|
||||
format so that all the images can be viewed by standard browsers.
|
||||
<p></p>
|
||||
This parameter indicates the percentage to scale the stream image when it is placed on the page.
|
||||
Note that this is scaled on the browser side, motion will keep sending full frame
|
||||
Numbers greater than 100 are permitted.
|
||||
<p></p>
|
||||
<p></p>
|
||||
|
||||
40
picture.c
40
picture.c
@@ -970,19 +970,17 @@ void overlay_largest_label(struct context *cnt, unsigned char *out)
|
||||
*
|
||||
* Returns the dest_image_size if successful. Otherwise 0.
|
||||
*/
|
||||
int put_picture_memory(struct context *cnt, unsigned char* dest_image, int image_size,
|
||||
unsigned char *image, int quality)
|
||||
int put_picture_memory(struct context *cnt, unsigned char* dest_image, int image_size, unsigned char *image,
|
||||
int quality, int width, int height)
|
||||
{
|
||||
switch (cnt->imgs.type) {
|
||||
case VIDEO_PALETTE_YUV420P:
|
||||
return put_jpeg_yuv420p_memory(dest_image, image_size, image,
|
||||
cnt->imgs.width, cnt->imgs.height, quality, cnt, &(cnt->current_image->timestamp_tv), &(cnt->current_image->location));
|
||||
width, height, quality, cnt, &(cnt->current_image->timestamp_tv), &(cnt->current_image->location));
|
||||
case VIDEO_PALETTE_GREY:
|
||||
return put_jpeg_grey_memory(dest_image, image_size, image,
|
||||
cnt->imgs.width, cnt->imgs.height, quality);
|
||||
return put_jpeg_grey_memory(dest_image, image_size, image, width, height, quality);
|
||||
default:
|
||||
MOTION_LOG(WRN, TYPE_ALL, NO_ERRNO, "Unknown image type %d",
|
||||
cnt->imgs.type);
|
||||
MOTION_LOG(WRN, TYPE_ALL, NO_ERRNO, "Unknown image type %d", cnt->imgs.type);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1232,3 +1230,31 @@ void preview_save(struct context *cnt)
|
||||
cnt->current_image = saved_current_image;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* scale_half_yuv420p
|
||||
* scale down by half yuv420p
|
||||
*
|
||||
* Returns pointer to scaled image
|
||||
*/
|
||||
|
||||
unsigned char *scale_half_yuv420p(int origwidth, int origheight, unsigned char *img)
|
||||
{
|
||||
/* allocate buffer for resized image */
|
||||
unsigned char *scaled_img = mymalloc ((origwidth/2 * origheight/2) * 3 / 2);
|
||||
|
||||
int i = 0, x, y;
|
||||
for (y = 0; y < origheight; y+=2)
|
||||
for (x = 0; x < origwidth; x+=2)
|
||||
scaled_img[i++] = img[y * origwidth + x];
|
||||
|
||||
for (y = 0; y < origheight / 2; y+=2)
|
||||
for (x = 0; x < origwidth; x += 4)
|
||||
{
|
||||
scaled_img[i++] = img[(origwidth * origheight) + (y * origwidth) + x];
|
||||
scaled_img[i++] = img[(origwidth * origheight) + (y * origwidth) + (x + 1)];
|
||||
}
|
||||
|
||||
return scaled_img;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,9 +17,10 @@ void overlay_fixed_mask(struct context *, unsigned char *);
|
||||
void put_fixed_mask(struct context *, const char *);
|
||||
void overlay_largest_label(struct context *, unsigned char *);
|
||||
void put_picture_fd(struct context *, FILE *, unsigned char *, int);
|
||||
int put_picture_memory(struct context *, unsigned char*, int, unsigned char *, int);
|
||||
int put_picture_memory(struct context *, unsigned char*, int, unsigned char *, int, int, int);
|
||||
void put_picture(struct context *, char *, unsigned char *, int);
|
||||
unsigned char *get_pgm(FILE *, int, int);
|
||||
void preview_save(struct context *);
|
||||
unsigned char *scale_half_yuv420p(int, int, unsigned char*);
|
||||
|
||||
#endif /* _INCLUDE_PICTURE_H_ */
|
||||
|
||||
93
stream.c
93
stream.c
@@ -33,6 +33,8 @@
|
||||
typedef void* (*auth_handler)(void*);
|
||||
struct auth_param {
|
||||
struct context *cnt;
|
||||
struct stream *stm;
|
||||
int *stream_count;
|
||||
int sock;
|
||||
int sock_flags;
|
||||
int* thread_count;
|
||||
@@ -233,8 +235,8 @@ static void* handle_basic_auth(void* param)
|
||||
/* Lock the mutex */
|
||||
pthread_mutex_lock(&stream_auth_mutex);
|
||||
|
||||
stream_add_client(&p->cnt->stream, p->sock);
|
||||
p->cnt->stream_count++;
|
||||
stream_add_client(p->stm, p->sock);
|
||||
(*p->stream_count)++;
|
||||
p->thread_count--;
|
||||
|
||||
/* Unlock the mutex */
|
||||
@@ -596,8 +598,8 @@ Error:
|
||||
/* Lock the mutex */
|
||||
pthread_mutex_lock(&stream_auth_mutex);
|
||||
|
||||
stream_add_client(&p->cnt->stream, p->sock);
|
||||
p->cnt->stream_count++;
|
||||
stream_add_client(p->stm, p->sock);
|
||||
(*p->stream_count)++;
|
||||
|
||||
p->thread_count--;
|
||||
/* Unlock the mutex */
|
||||
@@ -629,7 +631,7 @@ Invalid_Request:
|
||||
*
|
||||
*
|
||||
*/
|
||||
static void do_client_auth(struct context *cnt, int sc)
|
||||
static void do_client_auth(struct context *cnt, struct stream *stm, int *stream_count, int sc)
|
||||
{
|
||||
pthread_t thread_id;
|
||||
pthread_attr_t attr;
|
||||
@@ -661,6 +663,8 @@ static void do_client_auth(struct context *cnt, int sc)
|
||||
|
||||
handle_param = mymalloc(sizeof(struct auth_param));
|
||||
handle_param->cnt = cnt;
|
||||
handle_param->stm = stm;
|
||||
handle_param->stream_count = stream_count;
|
||||
handle_param->sock = sc;
|
||||
handle_param->conf = &cnt->conf;
|
||||
handle_param->thread_count = &thread_count;
|
||||
@@ -1032,13 +1036,13 @@ static int stream_check_write(struct stream *list)
|
||||
*
|
||||
* Returns: stream socket descriptor.
|
||||
*/
|
||||
int stream_init(struct context *cnt)
|
||||
int stream_init(struct stream *stm, int stream_port, int stream_localhost, int ipv6_enabled)
|
||||
{
|
||||
cnt->stream.socket = http_bindsock(cnt->conf.stream_port, cnt->conf.stream_localhost,
|
||||
cnt->conf.ipv6_enabled);
|
||||
cnt->stream.next = NULL;
|
||||
cnt->stream.prev = NULL;
|
||||
return cnt->stream.socket;
|
||||
stm->socket = http_bindsock(stream_port, stream_localhost, ipv6_enabled);
|
||||
stm->next = NULL;
|
||||
stm->prev = NULL;
|
||||
|
||||
return stm->socket;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1046,16 +1050,17 @@ int stream_init(struct context *cnt)
|
||||
* This function is called from the motion_loop when it ends
|
||||
* and motion is terminated or restarted.
|
||||
*/
|
||||
void stream_stop(struct context *cnt)
|
||||
void stream_stop(struct stream *stm)
|
||||
{
|
||||
struct stream *list;
|
||||
struct stream *next = cnt->stream.next;
|
||||
struct stream *next = stm->next;
|
||||
|
||||
/* TODO friendly info which socket is closing */
|
||||
MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO, "Closing motion-stream listen socket"
|
||||
" & active motion-stream sockets");
|
||||
|
||||
close(cnt->stream.socket);
|
||||
cnt->stream.socket = -1;
|
||||
close(stm->socket);
|
||||
stm->socket = -1;
|
||||
|
||||
while (next) {
|
||||
list = next;
|
||||
@@ -1090,12 +1095,13 @@ void stream_stop(struct context *cnt)
|
||||
* Note: Clients that have disconnected are handled in the stream_flush()
|
||||
* function.
|
||||
*/
|
||||
void stream_put(struct context *cnt, unsigned char *image)
|
||||
void stream_put(struct context *cnt, struct stream *stm, int *stream_count, unsigned char *image,
|
||||
int do_scale_down)
|
||||
{
|
||||
struct timeval timeout;
|
||||
struct stream_buffer *tmpbuffer;
|
||||
fd_set fdread;
|
||||
int sl = cnt->stream.socket;
|
||||
int sl = stm->socket;
|
||||
int sc;
|
||||
/* Tthe following string has an extra 16 chars at end for length. */
|
||||
const char jpeghead[] = "--BoundaryString\r\n"
|
||||
@@ -1104,6 +1110,10 @@ void stream_put(struct context *cnt, unsigned char *image)
|
||||
int headlength = sizeof(jpeghead) - 1; /* Don't include terminator. */
|
||||
char len[20]; /* Will be used for sprintf, must be >= 16 */
|
||||
|
||||
/* will point either to the original image or a scaled down */
|
||||
unsigned char *img = image;
|
||||
int image_width = cnt->imgs.width, image_height = cnt->imgs.height, image_size = cnt->imgs.size;
|
||||
|
||||
/*
|
||||
* Timeout struct used to timeout the time we wait for a client
|
||||
* and we do not wait at all.
|
||||
@@ -1111,7 +1121,7 @@ void stream_put(struct context *cnt, unsigned char *image)
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
FD_ZERO(&fdread);
|
||||
FD_SET(cnt->stream.socket, &fdread);
|
||||
FD_SET(stm->socket, &fdread);
|
||||
|
||||
/*
|
||||
* If we have not reached the max number of allowed clients per
|
||||
@@ -1120,27 +1130,48 @@ void stream_put(struct context *cnt, unsigned char *image)
|
||||
* add this to the end of the chain of stream structs that are linked
|
||||
* to each other.
|
||||
*/
|
||||
if ((cnt->stream_count < DEF_MAXSTREAMS) &&
|
||||
if ((*stream_count < DEF_MAXSTREAMS) &&
|
||||
(select(sl + 1, &fdread, NULL, NULL, &timeout) > 0)) {
|
||||
sc = http_acceptsock(sl);
|
||||
if (cnt->conf.stream_auth_method == 0) {
|
||||
stream_add_client(&cnt->stream, sc);
|
||||
cnt->stream_count++;
|
||||
stream_add_client(stm, sc);
|
||||
(*stream_count)++;
|
||||
} else {
|
||||
do_client_auth(cnt, sc);
|
||||
do_client_auth(cnt, stm, stream_count, sc);
|
||||
}
|
||||
}
|
||||
|
||||
/* if there is no connected clients - nothing to do, return */
|
||||
if (*stream_count <= 0)
|
||||
return;
|
||||
|
||||
/* substream put - scale image down and update pointer to the scaled buffer */
|
||||
if (do_scale_down)
|
||||
{
|
||||
/* TODO for now just scale 50%, better resize image to a config predefined size */
|
||||
|
||||
int origwidth = cnt->imgs.width, origheight = cnt->imgs.height;
|
||||
int subwidth = origwidth/2, subheight = origheight/2;
|
||||
int subsize = subwidth * subheight * 3 / 2;
|
||||
|
||||
/* allocate new buffer and scale image */
|
||||
img = scale_half_yuv420p (origwidth, origheight, img);
|
||||
|
||||
image_width = subwidth;
|
||||
image_height = subheight;
|
||||
image_size = subsize;
|
||||
}
|
||||
|
||||
/* Lock the mutex */
|
||||
if (cnt->conf.stream_auth_method != 0)
|
||||
pthread_mutex_lock(&stream_auth_mutex);
|
||||
|
||||
|
||||
/* Call flush to send any previous partial-sends which are waiting. */
|
||||
stream_flush(&cnt->stream, &cnt->stream_count, cnt->conf.stream_limit);
|
||||
stream_flush(stm, stream_count, cnt->conf.stream_limit);
|
||||
|
||||
/* Check if any clients have available buffers. */
|
||||
if (stream_check_write(&cnt->stream)) {
|
||||
if (stream_check_write(stm)) {
|
||||
/*
|
||||
* Yes - create a new tmpbuffer for current image.
|
||||
* Note that this should create a buffer which is *much* larger
|
||||
@@ -1172,8 +1203,8 @@ void stream_put(struct context *cnt, unsigned char *image)
|
||||
wptr += headlength;
|
||||
|
||||
/* Create a jpeg image and place into tmpbuffer. */
|
||||
tmpbuffer->size = put_picture_memory(cnt, wptr, cnt->imgs.size, image,
|
||||
cnt->conf.stream_quality);
|
||||
tmpbuffer->size = put_picture_memory(cnt, wptr, image_size, img,
|
||||
cnt->conf.stream_quality, image_width, image_height);
|
||||
|
||||
/* Fill in the image length into the header. */
|
||||
imgsize = sprintf(len, "%9ld\r\n\r\n", tmpbuffer->size);
|
||||
@@ -1193,7 +1224,7 @@ void stream_put(struct context *cnt, unsigned char *image)
|
||||
* And finally put this buffer to all clients with
|
||||
* no outstanding data from previous frames.
|
||||
*/
|
||||
stream_add_write(&cnt->stream, tmpbuffer, cnt->conf.stream_maxrate);
|
||||
stream_add_write(stm, tmpbuffer, cnt->conf.stream_maxrate);
|
||||
} else {
|
||||
MOTION_LOG(ERR, TYPE_STREAM, SHOW_ERRNO, "Error creating tmpbuffer");
|
||||
}
|
||||
@@ -1203,11 +1234,17 @@ void stream_put(struct context *cnt, unsigned char *image)
|
||||
* Now we call flush again. This time (assuming some clients were
|
||||
* ready for the new frame) the new data will be written out.
|
||||
*/
|
||||
stream_flush(&cnt->stream, &cnt->stream_count, cnt->conf.stream_limit);
|
||||
stream_flush(stm, stream_count, cnt->conf.stream_limit);
|
||||
|
||||
/* Unlock the mutex */
|
||||
if (cnt->conf.stream_auth_method != 0)
|
||||
pthread_mutex_unlock(&stream_auth_mutex);
|
||||
|
||||
/* free resized image buffer */
|
||||
if (do_scale_down)
|
||||
{
|
||||
free (img);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
6
stream.h
6
stream.h
@@ -38,8 +38,8 @@ struct stream {
|
||||
struct stream *next;
|
||||
};
|
||||
|
||||
int stream_init(struct context *);
|
||||
void stream_put(struct context *, unsigned char *);
|
||||
void stream_stop(struct context *);
|
||||
int stream_init(struct stream *, int, int, int);
|
||||
void stream_put(struct context *, struct stream *, int *, unsigned char *, int);
|
||||
void stream_stop(struct stream *);
|
||||
|
||||
#endif /* _INCLUDE_STREAM_H_ */
|
||||
|
||||
@@ -2118,7 +2118,7 @@ static unsigned int handle_get(int client_socket, const char *url, void *userdat
|
||||
sprintf(res, "<a href=http://%s:%d> "
|
||||
"<img src=http://%s:%d/ border=0 width=%d%%></a>\n"
|
||||
,httphostname,cnt[y]->conf.stream_port
|
||||
,httphostname,cnt[y]->conf.stream_port
|
||||
,httphostname,(cnt[y]->conf.substream_port)?cnt[y]->conf.substream_port:cnt[y]->conf.stream_port
|
||||
,cnt[y]->conf.stream_preview_scale);
|
||||
send_template(client_socket, res);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user