Esempio n. 1
0
/******************************************************************************
Description.: this function is called first, in order to initialize
              this plugin and pass a parameter string
Input Value.: parameters
Return Value: 0 if everything is OK, non-zero otherwise
******************************************************************************/
int output_init(output_parameter *param, int id)
{
	int i;
    delay = 0;
    pglobal = param->global;
    pglobal->out[id].name = (char *) malloc((1+strlen(OUTPUT_PLUGIN_NAME))*sizeof(char));
    sprintf(pglobal->out[id].name, "%s", OUTPUT_PLUGIN_NAME);
    DBG("OUT plugin %d name: %s\n", id, pglobal->out[id].name);

    param->argv[0] = OUTPUT_PLUGIN_NAME;

    /* show all parameters for DBG purposes */
    for(i = 0; i < param->argc; i++) {
        DBG("argv[%d]=%s\n", i, param->argv[i]);
    }

    reset_getopt();
    while(1) {
        int option_index = 0, c = 0;
        static struct option long_options[] = {
            {"h", no_argument, 0, 0
            },
            {"help", no_argument, 0, 0},
            {0, 0, 0, 0}
        };

        c = getopt_long_only(param->argc, param->argv, "", long_options, &option_index);

        /* no more options to parse */
        if(c == -1) break;

        /* unrecognized option */
        if(c == '?') {
            help();
            return 1;
        }

        switch(option_index) {
            /* h, help */
        case 0:
        case 1:
            DBG("case 0,1\n");
            help();
            return 1;
            break;
        }
    }

    if(!(input_number < pglobal->incnt)) {
        OPRINT("ERROR: the %d input_plugin number is too much only %d plugins loaded\n", input_number, param->global->incnt);
        return 1;
    }

    OPRINT("Starting OpenCV.....\n");
    OPRINT("input plugin.....: %d: %s\n", input_number, pglobal->in[input_number].plugin);

    param->global->out[id].parametercount = 0;
    return 0;
}
/******************************************************************************
Description.: clean up allocated ressources
Input Value.: unused argument
Return Value: -
******************************************************************************/
void worker_cleanup(void *arg)
{
    static unsigned char first_run = 1;

    if(!first_run) {
        DBG("already cleaned up ressources\n");
        return;
    }

    first_run = 0;
    OPRINT("cleaning up ressources allocated by worker thread\n");
}
/******************************************************************************
Description.: clean up allocated ressources
Input Value.: unused argument
Return Value: -
******************************************************************************/
void worker_cleanup(void *arg)
{
    static unsigned char first_run = 1;

    if(!first_run) {
        DBG("already cleaned up ressources\n");
        return;
    }

    first_run = 0;
    OPRINT("cleaning up ressources allocated by worker thread\n");

    if(frame != NULL) {
        free(frame);
    }

    //close tcp socket
    client_tcp_destory();

}
Esempio n. 4
0
/******************************************************************************
Description.: clean up allocated resources
Input Value.: unused argument
Return Value: -
******************************************************************************/
void worker_cleanup(void *arg)
{
    static unsigned char first_run = 1;

    if (mjpgFileName != NULL) {
        close(fd);
    }

    if(!first_run) {
        DBG("already cleaned up resources\n");
        return;
    }

    first_run = 0;
    OPRINT("cleaning up resources allocated by worker thread\n");

    if(frame != NULL) {
        free(frame);
    }
    close(fd);
}
/******************************************************************************
Description.: clean up allocated ressources
Input Value.: unused argument
Return Value: -
******************************************************************************/
void worker_cleanup(void *arg)
{
    static unsigned char first_run = 1;
    int i;

    if (mjpgFileName != NULL) {
        close(fd);
    }

    if(!first_run) {
        DBG("already cleaned up ressources\n");
        return;
    }

    first_run = 0;
    OPRINT("cleaning up ressources allocated by worker thread\n");

    if(frame != NULL) {
        free(frame);
    }
    close(fd);

    // cleanup zmq
    zmq_close (publisher);
    zmq_ctx_destroy (context);

    // Free the allocated serialized buffer
    free(buf);

    // Free protobuf message
    for (i = 0; i < pbPackage.n_frame; ++i)
    {
        free(pbPackage.frame[i]);
    }
    free(pbPackage.frame);
}
int output_cmd(int plugin_id, unsigned int control_id, unsigned int group, int value, char *valueStr)
{
    int i = 0;
    DBG("command (%d, value: %d) for group %d triggered for plugin instance #%02d\n", control_id, value, group, plugin_id);
    switch(group) {
		case IN_CMD_GENERIC:
			for(i = 0; i < pglobal->out[plugin_id].parametercount; i++) {
				if((pglobal->out[plugin_id].out_parameters[i].ctrl.id == control_id) && (pglobal->out[plugin_id].out_parameters[i].group == IN_CMD_GENERIC)) {
					DBG("Generic control found (id: %d): %s\n", control_id, pglobal->out[plugin_id].out_parameters[i].ctrl.name);
					switch(control_id) {
                            case OUT_FILE_CMD_TAKE: {
                                if (valueStr != NULL) {
                                    int frame_size = 0;
                                    unsigned char *tmp_framebuffer = NULL;

                                    if(pthread_mutex_lock(&pglobal->in[input_number].db)) {
                                        DBG("Unable to lock mutex\n");
                                        return -1;
                                    }
                                    /* read buffer */
                                    frame_size = pglobal->in[input_number].size;

                                    /* check if buffer for frame is large enough, increase it if necessary */
                                    if(frame_size > max_frame_size) {
                                        DBG("increasing buffer size to %d\n", frame_size);

                                        max_frame_size = frame_size + (1 << 16);
                                        if((tmp_framebuffer = realloc(frame, max_frame_size)) == NULL) {
                                            pthread_mutex_unlock(&pglobal->in[input_number].db);
                                            LOG("not enough memory\n");
                                            return -1;
                                        }

                                        frame = tmp_framebuffer;
                                    }

                                    /* copy frame to our local buffer now */
                                    memcpy(frame, pglobal->in[input_number].buf, frame_size);

                                    /* allow others to access the global buffer again */
                                    pthread_mutex_unlock(&pglobal->in[input_number].db);

                                    DBG("writing file: %s\n", valueStr);

                                    int fd;
                                    /* open file for write */
                                    if((fd = open(valueStr, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
                                        OPRINT("could not open the file %s\n", valueStr);
                                        return -1;
                                    }

                                    /* save picture to file */
                                    //if(write(fileno(stdout), frame, frame_size) < 0) {
                                    if(fwrite(frame, sizeof(unsigned char), frame_size, stdout) < 0) {
                                        OPRINT("could not write to file %s\n", valueStr);
                                        perror("fwrite()");
                                        close(fd);
                                        return -1;
                                    }

                                    close(fd);
                                } else {
                                    DBG("No filename specified\n");
                                    return -1;
                                }
                            } break;
                            case OUT_FILE_CMD_FILENAME: {
                                DBG("Not yet implemented\n");
                                return -1;
                            } break;
                            default: {
                                DBG("Unknown command\n");
                                return -1;
                            } break;
					}
					DBG("Ctrl %s new value: %d\n", pglobal->out[plugin_id].out_parameters[i].ctrl.name, value);
					return 0;
				}
			}
			DBG("Requested generic control (%d) did not found\n", control_id);
			return -1;
			break;
	}
    return 0;
}
/******************************************************************************
Description.: this function is called first, in order to initialize
              this plugin and pass a parameter string
Input Value.: parameters
Return Value: 0 if everything is OK, non-zero otherwise
******************************************************************************/
int output_init(output_parameter *param, int id)
{
	int i;
    pglobal = param->global;
    pglobal->out[id].name = malloc((1+strlen(OUTPUT_PLUGIN_NAME))*sizeof(char));
    sprintf(pglobal->out[id].name, "%s", OUTPUT_PLUGIN_NAME);
    DBG("OUT plugin %d name: %s\n", id, pglobal->out[id].name);

    param->argv[0] = OUTPUT_PLUGIN_NAME;

    /* show all parameters for DBG purposes */
    for(i = 0; i < param->argc; i++) {
        DBG("argv[%d]=%s\n", i, param->argv[i]);
    }

    reset_getopt();
    while(1) {
        int option_index = 0, c = 0;
        static struct option long_options[] = {
            {"h", no_argument, 0, 0
            },
            {"help", no_argument, 0, 0},
            {"f", required_argument, 0, 0},
            {"folder", required_argument, 0, 0},
            {"s", required_argument, 0, 0},
            {"size", required_argument, 0, 0},
            {"e", required_argument, 0, 0},
            {"exceed", required_argument, 0, 0},
            {"i", required_argument, 0, 0},
            {"input", required_argument, 0, 0},
            {"m", required_argument, 0, 0},
            {"mjpeg", required_argument, 0, 0},
            {"a", required_argument, 0, 0},
            {"address", required_argument, 0, 0},
            {"b", required_argument, 0, 0},
            {"buffer_size", required_argument, 0, 0},
            {0, 0, 0, 0}
        };

        c = getopt_long_only(param->argc, param->argv, "", long_options, &option_index);

        /* no more options to parse */
        if(c == -1) break;

        /* unrecognized option */
        if(c == '?') {
            help();
            return 1;
        }

        switch(option_index) {
            /* h, help */
        case 0:
        case 1:
            DBG("case 0,1\n");
            help();
            return 1;
            break;

            /* f, folder */
        case 2:
        case 3:
            DBG("case 2,3\n");
            folder = malloc(strlen(optarg) + 1);
            strcpy(folder, optarg);
            if(folder[strlen(folder)-1] == '/')
                folder[strlen(folder)-1] = '\0';
            break;

            /* s, size */
        case 4:
        case 5:
            DBG("case 4,5\n");
            ringbuffer_size = atoi(optarg);
            break;

            /* e, exceed */
        case 6:
        case 7:
            DBG("case 6,7\n");
            ringbuffer_exceed = atoi(optarg);
            break;
            /* i, input*/
        case 8:
        case 9:
            DBG("case 8,9\n");
            input_number = atoi(optarg);
            break;
            /* m mjpeg */
        case 10:
        case 11:
            DBG("case 10,11\n");
            mjpgFileName = strdup(optarg);
            break;
            /* a address */
        case 12:
        case 13:
            DBG("case 12,13\n");
            zmqAddress = strdup(optarg);
            break;
            /* buffer_size */
        case 14:
        case 15:
            DBG("case 14,15\n");
            zmqBufferSize = atoi(optarg);
            break;
        }
    }

    if(!(input_number < pglobal->incnt)) {
        OPRINT("ERROR: the %d input_plugin number is too much only %d plugins loaded\n", input_number, param->global->incnt);
        return 1;
    }

    OPRINT("output folder.....: %s\n", folder);
    OPRINT("input plugin.....: %d: %s\n", input_number, pglobal->in[input_number].plugin);
    if  (mjpgFileName == NULL) {
        if(ringbuffer_size > 0) {
            OPRINT("ringbuffer size...: %d to %d\n", ringbuffer_size, ringbuffer_size + ringbuffer_exceed);
        } else {
            OPRINT("ringbuffer size...: %s\n", "no ringbuffer");
        }
    } else {
        char *fnBuffer = malloc(strlen(mjpgFileName) + strlen(folder) + 3);
        sprintf(fnBuffer, "%s/%s", folder, mjpgFileName);

        OPRINT("output file.......: %s\n", fnBuffer);
        if((fd = open(fnBuffer, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
            OPRINT("could not open the file %s\n", fnBuffer);
            free(fnBuffer);
            return 1;
        }
        free(fnBuffer);
    }

    param->global->out[id].parametercount = 2;

    param->global->out[id].out_parameters = (control*) calloc(2, sizeof(control));

    control take_ctrl;
	take_ctrl.group = IN_CMD_GENERIC;
	take_ctrl.menuitems = NULL;
	take_ctrl.value = 1;
	take_ctrl.class_id = 0;

	take_ctrl.ctrl.id = OUT_FILE_CMD_TAKE;
	take_ctrl.ctrl.type = V4L2_CTRL_TYPE_BUTTON;
	strcpy((char*) take_ctrl.ctrl.name, "Take snapshot");
	take_ctrl.ctrl.minimum = 0;
	take_ctrl.ctrl.maximum = 1;
	take_ctrl.ctrl.step = 1;
	take_ctrl.ctrl.default_value = 0;

	param->global->out[id].out_parameters[0] = take_ctrl;

    control filename_ctrl;
	filename_ctrl.group = IN_CMD_GENERIC;
	filename_ctrl.menuitems = NULL;
	filename_ctrl.value = 1;
	filename_ctrl.class_id = 0;

	filename_ctrl.ctrl.id = OUT_FILE_CMD_FILENAME;
	filename_ctrl.ctrl.type = V4L2_CTRL_TYPE_STRING;
	strcpy((char*) filename_ctrl.ctrl.name, "Filename");
	filename_ctrl.ctrl.minimum = 0;
	filename_ctrl.ctrl.maximum = 32;
	filename_ctrl.ctrl.step = 1;
	filename_ctrl.ctrl.default_value = 0;

	param->global->out[id].out_parameters[1] = filename_ctrl;


    return 0;
}
/******************************************************************************
Description.: this is the main worker thread
              it loops forever, grabs a fresh frame and stores it to file
Input Value.:
Return Value:
******************************************************************************/
void *worker_thread(void *arg)
{
    int ok = 1, frame_size = 0, rc = 0;
    char buffer1[1024] = {0}, buffer2[1024] = {0};
    unsigned long long counter = 0;
    unsigned char *tmp_framebuffer = NULL;

    //  Prepare our context and publisher
    //char zmqAddress[20];
    if (zmqAddress == NULL) {
        LOG("No ZMQ address specified");
    }

    context = zmq_ctx_new ();
    publisher = zmq_socket (context, ZMQ_PUB);
    //snprintf(zmqAddress, 20u, "epgm://eth0;239.1.1.1:%i", zmqPort);

    if (zmq_bind (publisher, zmqAddress) == -1) {
        LOG("Couldn't create zmq socket.\n");
    }

    unsigned len;                      // Length of serialized data
    char topic[] = "frames";
    struct timeval timestamp;
    int i;

    buf = NULL;
    for (i = 0; i < MAX_ZMQ_BUFFER_SIZE; ++i)
    {
        frames[i] = NULL;
    }

    pbPackage.n_frame = zmqBufferSize;
    if ((pbPackage.frame = malloc(sizeof(Pb__Package__Frame*) * pbPackage.n_frame)) == NULL) {
        LOG("not enough memory\n");
    }
    for (i = 0; i < pbPackage.n_frame; ++i)
    {
        if ((pbPackage.frame[i] = malloc(sizeof(Pb__Package__Frame))) == NULL) {
            LOG("not enough memory\n");
        }
        pb__package__frame__init(pbPackage.frame[i]);
    }
    /* set cleanup handler to cleanup allocated ressources */
    pthread_cleanup_push(worker_cleanup, NULL);

    while(ok >= 0 && !pglobal->stop) {
        DBG("waiting for fresh frame\n");

        pthread_mutex_lock(&pglobal->in[input_number].db);
        pthread_cond_wait(&pglobal->in[input_number].db_update, &pglobal->in[input_number].db);

        /* read buffer */
        frame_size = pglobal->in[input_number].size;

        /* set the right frame to store the data */
        frame = frames[zmqBufferPos];

        /* check if buffer for frame is large enough, increase it if necessary */
        if((frame_size > max_frame_size) || (frame == NULL)) {
            DBG("increasing buffer size to %d\n", frame_size);

            if (frame_size > max_frame_size) {
                max_frame_size = frame_size + (1 << 16);
            }
            if((tmp_framebuffer = realloc(frame, max_frame_size)) == NULL) {
                pthread_mutex_unlock(&pglobal->in[input_number].db);
                LOG("not enough memory\n");
                return NULL;
            }

            if ((setvbuf(stdout, NULL, _IOFBF, max_frame_size)) != 0) {
                DBG("setvbuf failed.\n");
            }

            frame = tmp_framebuffer;
        }

        /* copy v4l2_buffer timeval to user space */
        timestamp = pglobal->in[input_number].timestamp;

        /* copy frame to our local buffer now */
        memcpy(frame, pglobal->in[input_number].buf, frame_size);

        /* resync again with the frame buffer */
        frames[zmqBufferPos] = frame;

        /* allow others to access the global buffer again */
        pthread_mutex_unlock(&pglobal->in[input_number].db);

        if (mjpgFileName == NULL) { // single files with ringbuffer mode
            DBG("Packaging data: %lld\n", counter);
            counter++;

            begin = clock();

            /* allocate enough memory to store a serialized string */
            if ((buf == NULL) || (bufferSize < (max_frame_size * zmqBufferSize + 20)))
            {
                bufferSize = (max_frame_size * zmqBufferSize + 20);
                buf = realloc(buf, bufferSize);
                if (buf == NULL) {
                    LOG("Not enough memory");
                }
            }

            /* fill protobuf data */
            pbPackage.frame[zmqBufferPos]->timestamp_unix = (u_int32_t)time(NULL);
            pbPackage.frame[zmqBufferPos]->timestamp_s = (u_int32_t)timestamp.tv_sec;
            pbPackage.frame[zmqBufferPos]->timestamp_us = (u_int32_t)timestamp.tv_usec;
            pbPackage.frame[zmqBufferPos]->blob.data = frame;
            pbPackage.frame[zmqBufferPos]->blob.len = frame_size;

            zmqBufferPos++;

            if (zmqBufferPos == zmqBufferSize)
            {
                DBG("transmitting ZMQ: %lld\n", counter);
                /* pack protobuf data */
                len = pb__package__get_packed_size(&pbPackage);
                DBG("packing data: %i %i", max_frame_size, len);
                pb__package__pack(&pbPackage, buf);

                DBG("sending data");
                // send data using zmq
                if ((zmq_send(publisher, topic, strlen(topic), ZMQ_SNDMORE) == -1) || (zmq_send(publisher, buf, len, 0) == -1)) {
                    DBG("ZMQ Transmission failure");
                }

                zmqBufferPos = 0;
            }

            end = clock();
            DBG("Time1: %f\n", (double)(end-begin) / CLOCKS_PER_SEC);
            begin = clock();

            /* call the command if user specified one, pass current filename as argument */
            if(command != NULL) {
                memset(buffer1, 0, sizeof(buffer1));

                /* buffer2 still contains the filename, pass it to the command as parameter */
                snprintf(buffer1, sizeof(buffer1), "%s \"%s\"", command, buffer2);
                DBG("calling command %s", buffer1);

                /* in addition provide the filename as environment variable */
                if((rc = setenv("MJPG_FILE", buffer2, 1)) != 0) {
                    LOG("setenv failed (return value %d)\n", rc);
                }

                /* execute the command now */
                if((rc = system(buffer1)) != 0) {
                    LOG("command failed (return value %d)\n", rc);
                }
            }

            end = clock();
            DBG("Time2: %f\n", (double)(end-begin) / CLOCKS_PER_SEC);
            begin = clock();

            /*
             * maintain ringbuffer
             * do not maintain ringbuffer for each picture, this saves ressources since
             * each run of the maintainance function involves sorting/malloc/free operations
             */
            if(ringbuffer_exceed <= 0) {
                /* keep ringbuffer excactly at specified siOUTPUT_PLUGIN_NAMEze */
                maintain_ringbuffer(ringbuffer_size);
            } else if(counter == 1 || counter % (ringbuffer_exceed + 1) == 0) {
                DBG("counter: %llu, will clean-up now\n", counter);
                maintain_ringbuffer(ringbuffer_size);
            }

            end = clock();
            DBG("Time3: %f\n", (double)(end-begin) / CLOCKS_PER_SEC);

        } else { // recording to MJPG file
            DBG("Entered else branch!\n");
            /* save picture to file */
            //if(write(fileno(stdout), frame, frame_size) < 0) {
            if(fwrite(frame, sizeof(unsigned char), frame_size, stdout) < 0) {
                OPRINT("could not write to file %s\n", buffer2);
                perror("fwrite()");
                close(fd);
                return NULL;
            }
        }
    }

    /* cleanup now */
    pthread_cleanup_pop(1);

    return NULL;
}
Esempio n. 9
0
/******************************************************************************
Description.: this function is called first, in order to initialise
              this plugin and pass a parameter string
Input Value.: parameters
Return Value: 0 if everything is ok, non-zero otherwise
******************************************************************************/
int output_init(output_parameter *param)
{
    int i;

    param->argv[0] = OUTPUT_PLUGIN_NAME;

    /* show all parameters for DBG purposes */
    for(i = 0; i < param->argc; i++) {
        DBG("argv[%d]=%s\n", i, param->argv[i]);
    }

    reset_getopt();
    while(1) {
        int option_index = 0, c = 0;
        static struct option long_options[] = {
            {"h", no_argument, 0, 0
            },
            {"help", no_argument, 0, 0},
            {"p", required_argument, 0, 0},
            {"port", required_argument, 0, 0},
            {"i", required_argument, 0, 0},
            {"input", required_argument, 0, 0},
            {0, 0, 0, 0}
        };

        c = getopt_long_only(param->argc, param->argv, "", long_options, &option_index);

        /* no more options to parse */
        if(c == -1) break;

        /* unrecognized option */
        if(c == '?') {
            help();
            return 1;
        }

        switch(option_index) {
            /* h, help */
        case 0:
        case 1:
            DBG("case 0,1\n");
            help();
            return 1;
            break;
        case 2:
        case 3:
            DBG("case 2,3\n");
            port = atoi(optarg);
            break;
            /* i, input */
        case 4:
        case 5:
            DBG("case 4,5\n");
            input_number = atoi(optarg);
            break;
        }
    }

    pglobal = param->global;
    if(!(input_number < pglobal->incnt)) {
        OPRINT("ERROR: the %d input_plugin number is too much only %d plugins loaded\n", input_number, pglobal->incnt);
        return 1;
    }

    OPRINT("input plugin.....: %d: %s\n", input_number, pglobal->in[input_number].plugin);
    OPRINT("UDP port..........: %s\n", "disabled");
    return 0;
}
/******************************************************************************
Description.: this is the main worker thread
              it loops forever, grabs a fresh frame and stores it to file
Input Value.:
Return Value:
******************************************************************************/
void *worker_thread(void *arg)
{
    int ok = 1;
    int frame_size = 0;
    unsigned char *tmp_framebuffer = NULL;

    struct sockaddr_in addr;
    int sd;

    bzero(&addr, sizeof(addr));


    /* set cleanup handler to cleanup allocated ressources */
    pthread_cleanup_push(worker_cleanup, NULL);

    // set TCP server data structures ---------------------------
    if(port <= 0) {
        OPRINT("a valid TCP port must be provided\n");
        return NULL;
    }

    addr.sin_addr.s_addr = inet_addr(server);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    // -----------------------------------------------------------

    struct timeval imageProcessingStart;
    struct timeval imageProcessingStop;

    struct timeval socketStart;
    struct timeval socketStop;

    while (ok >= 0 && !pglobal->stop) {
        //DBG("waiting for fresh frame\n");

        gettimeofday(&imageProcessingStart, NULL);

        pthread_mutex_lock(&pglobal->in[input_number].db);
        pthread_cond_wait(&pglobal->in[input_number].db_update, &pglobal->in[input_number].db);


        /* read buffer */
        frame_size = pglobal->in[input_number].size;

        /* check if buffer for frame is large enough, increase it if necessary */
        if(frame_size > max_frame_size) {
            DBG("increasing buffer size to %d\n", frame_size);

            max_frame_size = frame_size + (1 << 16);
            if((tmp_framebuffer = realloc(frame, max_frame_size)) == NULL) {
                pthread_mutex_unlock(&pglobal->in[input_number].db);
                LOG("not enough memory\n");
                return NULL;
            }

            frame = tmp_framebuffer;
        }

        /* copy frame to our local buffer now */
        memcpy(frame, pglobal->in[input_number].buf, frame_size);

        /* allow others to access the global buffer again */
        pthread_mutex_unlock(&pglobal->in[input_number].db);

        gettimeofday(&imageProcessingStop, NULL);

        printDuration(&imageProcessingStart, &imageProcessingStop, "Image");

        /* Send image */
        gettimeofday(&socketStart, NULL);

        DBG("Create connection to %s:%d\n", server, port);
        sd = socket(AF_INET, SOCK_STREAM, 0);

        // Test
        usleep(200 * 1000);

        if (connect(sd , (struct sockaddr*) &addr , sizeof(addr)) == 0) {
            DBG("Connection to %s:%d established\n", server, port);

            if (!send(sd, frame, frame_size, 0)) {
                perror("Image was not send");
            }

            DBG("Closing connection to %s:%d\n", server, port);
            close(sd);
        } else {
            perror("connect");
        }

        gettimeofday(&socketStop, NULL);

        printDuration(&socketStart, &socketStop, "Socket");
    }

    DBG("Ending TCP worker thread\n");

    /* cleanup now */
    pthread_cleanup_pop(1);

    return NULL;
}
Esempio n. 11
0
/******************************************************************************
Description.: this is the main worker thread
              it loops forever, grabs a fresh frame and stores it to file
Input Value.:
Return Value:
******************************************************************************/
void *worker_thread(void *arg)
{
    int ok = 1, frame_size = 0, rc = 0;
    char buffer1[1024] = {0};
    unsigned char *tmp_framebuffer = NULL;

    /* set cleanup handler to cleanup allocated ressources */
    pthread_cleanup_push(worker_cleanup, NULL);

    // set UDP server data structures ---------------------------
    if(port <= 0) {
        OPRINT("a valid UDP port must be provided\n");
        return NULL;
    }
    struct sockaddr_in addr;
    int sd;
    int bytes;
    unsigned int addr_len = sizeof(addr);
    char udpbuffer[1024] = {0};
    sd = socket(PF_INET, SOCK_DGRAM, 0);
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(port);
    if(bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0)
        perror("bind");
    // -----------------------------------------------------------

    while(ok >= 0 && !pglobal->stop) {
        DBG("waiting for a UDP message\n");

        // UDP receive ---------------------------------------------
        memset(udpbuffer, 0, sizeof(udpbuffer));
        bytes = recvfrom(sd, udpbuffer, sizeof(udpbuffer), 0, (struct sockaddr*)&addr, &addr_len);
        // ---------------------------------------------------------



        DBG("waiting for fresh frame\n");
        pthread_mutex_lock(&pglobal->in[input_number].db);
        pthread_cond_wait(&pglobal->in[input_number].db_update, &pglobal->in[input_number].db);

        /* read buffer */
        frame_size = pglobal->in[input_number].size;

        /* check if buffer for frame is large enough, increase it if necessary */
        if(frame_size > max_frame_size) {
            DBG("increasing buffer size to %d\n", frame_size);

            max_frame_size = frame_size + (1 << 16);
            if((tmp_framebuffer = realloc(frame, max_frame_size)) == NULL) {
                pthread_mutex_unlock(&pglobal->in[input_number].db);
                LOG("not enough memory\n");
                return NULL;
            }

            frame = tmp_framebuffer;
        }

        /* copy frame to our local buffer now */
        memcpy(frame, pglobal->in[input_number].buf, frame_size);

        /* allow others to access the global buffer again */
        pthread_mutex_unlock(&pglobal->in[input_number].db);

        /* only save a file if a name came in with the UDP message */
        if(strlen(udpbuffer) > 0) {
            DBG("writing file: %s\n", udpbuffer);

            /* open file for write. Path must pre-exist */
            if((fd = open(udpbuffer, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
                OPRINT("could not open the file %s\n", udpbuffer);
                return NULL;
            }

            /* save picture to file */
            if(write(fd, frame, frame_size) < 0) {
                OPRINT("could not write to file %s\n", udpbuffer);
                perror("write()");
                close(fd);
                return NULL;
            }

            close(fd);
        }

        // send back client's message that came in udpbuffer
        sendto(sd, udpbuffer, bytes, 0, (struct sockaddr*)&addr, sizeof(addr));

        /* call the command if user specified one, pass current filename as argument */
        if(command != NULL) {
            memset(buffer1, 0, sizeof(buffer1));

            /* udpbuffer still contains the filename, pass it to the command as parameter */
            snprintf(buffer1, sizeof(buffer1), "%s \"%s\"", command, udpbuffer);
            DBG("calling command %s", buffer1);

            /* in addition provide the filename as environment variable */
            if((rc = setenv("MJPG_FILE", udpbuffer, 1)) != 0) {
                LOG("setenv failed (return value %d)\n", rc);
            }

            /* execute the command now */
            if((rc = system(buffer1)) != 0) {
                LOG("command failed (return value %d)\n", rc);
            }
        }
    }

    // close UDP port
    if(port > 0)
        close(sd);

    /* cleanup now */
    pthread_cleanup_pop(1);

    return NULL;
}
Esempio n. 12
0
/******************************************************************************
Description.: Initialize this plugin.
              parse configuration parameters,
              store the parsed values in global variables
Input Value.: All parameters to work with.
              Among many other variables the "param->id" is quite important -
              it is used to distinguish between several server instances
Return Value: 0 if everything is OK, other values signal an error
******************************************************************************/
int output_init(output_parameter *param, int id)
{
    int i;
    int  port;
    char *credentials, *www_folder;
    char nocommands;

    DBG("output #%02d\n", param->id);

    port = htons(8080);
    credentials = NULL;
    www_folder = NULL;
    nocommands = 0;

    param->argv[0] = OUTPUT_PLUGIN_NAME;

    /* show all parameters for DBG purposes */
    for(i = 0; i < param->argc; i++) {
        DBG("argv[%d]=%s\n", i, param->argv[i]);
    }

    reset_getopt();
    while(1) {
        int option_index = 0, c = 0;
        static struct option long_options[] = {
            {"h", no_argument, 0, 0
            },
            {"help", no_argument, 0, 0},
            {"p", required_argument, 0, 0},
            {"port", required_argument, 0, 0},
            {"c", required_argument, 0, 0},
            {"credentials", required_argument, 0, 0},
            {"w", required_argument, 0, 0},
            {"www", required_argument, 0, 0},
            {"n", no_argument, 0, 0},
            {"nocommands", no_argument, 0, 0},
            {0, 0, 0, 0}
        };

        c = getopt_long_only(param->argc, param->argv, "", long_options, &option_index);

        /* no more options to parse */
        if(c == -1) break;

        /* unrecognized option */
        if(c == '?') {
            help();
            return 1;
        }

        switch(option_index) {
            /* h, help */
        case 0:
        case 1:
            DBG("case 0,1\n");
            help();
            return 1;
            break;

            /* p, port */
        case 2:
        case 3:
            DBG("case 2,3\n");
            port = htons(atoi(optarg));
            break;

            /* c, credentials */
        case 4:
        case 5:
            DBG("case 4,5\n");
            credentials = strdup(optarg);
            break;

            /* w, www */
        case 6:
        case 7:
            DBG("case 6,7\n");
            www_folder = malloc(strlen(optarg) + 2);
            strcpy(www_folder, optarg);
            if(optarg[strlen(optarg)-1] != '/')
                strcat(www_folder, "/");
            break;

            /* n, nocommands */
        case 8:
        case 9:
            DBG("case 8,9\n");
            nocommands = 1;
            break;
        }
    }

    servers[param->id].id = param->id;
    servers[param->id].pglobal = param->global;
    servers[param->id].conf.port = port;
    servers[param->id].conf.credentials = credentials;
    servers[param->id].conf.www_folder = www_folder;
    servers[param->id].conf.nocommands = nocommands;

    OPRINT("www-folder-path...: %s\n", (www_folder == NULL) ? "disabled" : www_folder);
    OPRINT("HTTP TCP port.....: %d\n", ntohs(port));
    OPRINT("username:password.: %s\n", (credentials == NULL) ? "disabled" : credentials);
    OPRINT("commands..........: %s\n", (nocommands) ? "disabled" : "enabled");
    return 0;
}
/******************************************************************************
Description.: this function is called first, in order to initialise
              this plugin and pass a parameter string
Input Value.: parameters
Return Value: 0 if everything is ok, non-zero otherwise
******************************************************************************/
int output_init(output_parameter *param) {
  char *argv[MAX_ARGUMENTS]={NULL};
  int argc=1, i;

  delay = 10000;

  /* convert the single parameter-string to an array of strings */
  argv[0] = OUTPUT_PLUGIN_NAME;
  if ( param->parameter_string != NULL && strlen(param->parameter_string) != 0 ) {
    char *arg=NULL, *saveptr=NULL, *token=NULL;

    arg=(char *)strdup(param->parameter_string);

    if ( strchr(arg, ' ') != NULL ) {
      token=strtok_r(arg, " ", &saveptr);
      if ( token != NULL ) {
        argv[argc] = strdup(token);
        argc++;
        while ( (token=strtok_r(NULL, " ", &saveptr)) != NULL ) {
          argv[argc] = strdup(token);
          argc++;
          if (argc >= MAX_ARGUMENTS) {
            OPRINT("ERROR: too many arguments to output plugin\n");
            return 1;
          }
        }
      }
    }
  }

  /* show all parameters for DBG purposes */
  for (i=0; i<argc; i++) {
    DBG("argv[%d]=%s\n", i, argv[i]);
  }

  reset_getopt();
  while(1) {
    int option_index = 0, c=0;
    static struct option long_options[] = \
    {
      {"h", no_argument, 0, 0},
      {"help", no_argument, 0, 0},
      {"d", required_argument, 0, 0},
      {"delay", required_argument, 0, 0},
      {0, 0, 0, 0}
    };

    c = getopt_long_only(argc, argv, "", long_options, &option_index);

    /* no more options to parse */
    if (c == -1) break;

    /* unrecognized option */
    if (c == '?'){
      help();
      return 1;
    }

    switch (option_index) {
      /* h, help */
      case 0:
      case 1:
        DBG("case 0,1\n");
        help();
        return 1;
        break;

      /* d, delay */
      case 2:
      case 3:
        DBG("case 2,3\n");
        delay = atoi(optarg);
        break;
    }
  }

  pglobal = param->global;

  OPRINT("delay.............: %d\n", delay);
  return 0;
}
Esempio n. 14
0
/******************************************************************************
Description.: this is the main worker thread
              it loops forever, grabs a fresh frame, decompressed the JPEG
              and displays the decoded data using SDL
Input Value.:
Return Value:
******************************************************************************/
void *worker_thread(void *arg)
{
    int frame_size = 0, firstrun = 1;

    SDL_Surface *screen = NULL, *image = NULL;
    decompressed_image rgbimage;

    /* initialze the buffer for the decompressed image */
    rgbimage.buffersize = 0;
    rgbimage.buffer = NULL;

    /* initialze the SDL video subsystem */
    if(SDL_Init(SDL_INIT_VIDEO) < 0) {
        fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
        exit(EXIT_FAILURE);
    }

    /* just allocate a large buffer for the JPEGs */
    if((frame = malloc(4096 * 1024)) == NULL) {
        OPRINT("not enough memory for worker thread\n");
        exit(EXIT_FAILURE);
    }

    /* set cleanup handler to cleanup allocated ressources */
    pthread_cleanup_push(worker_cleanup, NULL);

    while(!pglobal->stop) {
        DBG("waiting for fresh frame\n");
        pthread_mutex_lock(&pglobal->in[input_number].db);
        pthread_cond_wait(&pglobal->in[plugin_number].db_update, &pglobal->in[plugin_number].db);

        /* read buffer */
        frame_size = pglobal->in[plugin_number].size;
        memcpy(frame, pglobal->in[plugin_number].buf, frame_size);

        pthread_mutex_unlock(&pglobal->in[plugin_number].db);

        /* decompress the JPEG and store results in memory */
        if(decompress_jpeg(frame, frame_size, &rgbimage)) {
            DBG("could not properly decompress JPEG data\n");
            continue;
        }

        if(firstrun) {
            /* create the primary surface (the visible window) */
            screen = SDL_SetVideoMode(rgbimage.width, rgbimage.height, 0, SDL_ANYFORMAT | SDL_HWSURFACE);
            SDL_WM_SetCaption("MJPG-Streamer Viewer", NULL);

            /* create a SDL surface to display the data */
            image = SDL_AllocSurface(SDL_SWSURFACE, rgbimage.width, rgbimage.height, 24,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
                                     0x0000FF, 0x00FF00, 0xFF0000,
#else
                                     0xFF0000, 0x00FF00, 0x0000FF,
#endif
                                     0);

            /* copy the decoded data across */
            memcpy(image->pixels, rgbimage.buffer, rgbimage.width * rgbimage.height * 3);
            free(rgbimage.buffer);

            /* now, that we know the dimensions, we can directly copy to the right surface */
            rgbimage.buffer = image->pixels;
            rgbimage.buffersize = rgbimage.width * rgbimage.height * 3;

            firstrun = 0;
        }

        /* copy the image to the primary surface */
        SDL_BlitSurface(image, NULL, screen, NULL);

        /* redraw the whole surface */
        SDL_Flip(screen);
    }

    pthread_cleanup_pop(1);

    /* get rid of the image */
    SDL_FreeSurface(image);

    return NULL;
}
void printDuration(struct timeval *start, struct timeval *end, char * text) {
    #ifdef PRINT_TIMESTAMPS
    OPRINT("%s: Start: %d:%d, End: %d:%d, Duration: %d:%d\n", text, start->tv_sec, start->tv_usec, end->tv_sec, end->tv_usec, end->tv_sec - start->tv_sec, end->tv_usec - start->tv_usec);
    #endif
}
Esempio n. 16
0
/******************************************************************************
Description.: this function is called first, in order to initialise
              this plugin and pass a parameter string
Input Value.: parameters
Return Value: 0 if everything is ok, non-zero otherwise
******************************************************************************/
int output_init(output_parameter *param)
{
    int i;

    delay = 0;

    param->argv[0] = OUTPUT_PLUGIN_NAME;

    /* show all parameters for DBG purposes */
    for(i = 0; i < param->argc; i++) {
        DBG("argv[%d]=%s\n", i, param->argv[i]);
    }

    reset_getopt();
    while(1) {
        int option_index = 0, c = 0;
        static struct option long_options[] = {
            {"h", no_argument, 0, 0
            },
            {"help", no_argument, 0, 0},
            {"f", required_argument, 0, 0},
            {"folder", required_argument, 0, 0},
            {"d", required_argument, 0, 0},
            {"delay", required_argument, 0, 0},
            {"c", required_argument, 0, 0},
            {"command", required_argument, 0, 0},
            {"p", required_argument, 0, 0},
            {"port", required_argument, 0, 0},
            {"i", required_argument, 0, 0},
            {"input", required_argument, 0, 0},
            {0, 0, 0, 0}
        };

        c = getopt_long_only(param->argc, param->argv, "", long_options, &option_index);

        /* no more options to parse */
        if(c == -1) break;

        /* unrecognized option */
        if(c == '?') {
            help();
            return 1;
        }

        switch(option_index) {
            /* h, help */
        case 0:
        case 1:
            DBG("case 0,1\n");
            help();
            return 1;
            break;

            /* f, folder */
        case 2:
        case 3:
            DBG("case 2,3\n");
            folder = malloc(strlen(optarg) + 1);
            strcpy(folder, optarg);
            if(folder[strlen(folder)-1] == '/')
                folder[strlen(folder)-1] = '\0';
            break;

            /* d, delay */
        case 4:
        case 5:
            DBG("case 4,5\n");
            delay = atoi(optarg);
            break;

            /* c, command */
        case 6:
        case 7:
            DBG("case 6,7\n");
            command = strdup(optarg);
            break;
            /* p, port */
        case 8:
        case 9:
            DBG("case 8,9\n");
            port = atoi(optarg);
            break;
            /* i, input */
        case 10:
        case 11:
            DBG("case 10,11\n");
            input_number = atoi(optarg);
            break;
        }
    }

    pglobal = param->global;
    if(!(input_number < pglobal->incnt)) {
        OPRINT("ERROR: the %d input_plugin number is too much only %d plugins loaded\n", input_number, pglobal->incnt);
        return 1;
    }
    OPRINT("input plugin.....: %d: %s\n", input_number, pglobal->in[input_number].plugin);
    OPRINT("output folder.....: %s\n", folder);
    OPRINT("delay after save..: %d\n", delay);
    OPRINT("command...........: %s\n", (command == NULL) ? "disabled" : command);
    if(port > 0) {
        OPRINT("UDP port..........: %d\n", port);
    } else {
        OPRINT("UDP port..........: %s\n", "disabled");
    }
    return 0;
}
/******************************************************************************
Description.: this function is called first, in order to initialise
              this plugin and pass a parameter string
Input Value.: parameters
Return Value: 0 if everything is ok, non-zero otherwise
******************************************************************************/
int output_init(output_parameter *param)
{
    int i;

    delay = 10000;

    param->argv[0] = OUTPUT_PLUGIN_NAME;

    /* show all parameters for DBG purposes */
    for(i = 0; i < param->argc; i++) {
        DBG("argv[%d]=%s\n", i, param->argv[i]);
    }

    reset_getopt();
    while(1) {
        int option_index = 0, c = 0;
        static struct option long_options[] = {
            {"h", no_argument, 0, 0
            },
            {"help", no_argument, 0, 0},
            {"d", required_argument, 0, 0},
            {"delay", required_argument, 0, 0},
            {"i", required_argument, 0, 0},
            {"input", required_argument, 0, 0},
            {0, 0, 0, 0}
        };

        c = getopt_long_only(param->argc, param->argv, "", long_options, &option_index);

        /* no more options to parse */
        if(c == -1) break;

        /* unrecognized option */
        if(c == '?') {
            help();
            return 1;
        }

        switch(option_index) {
            /* h, help */
        case 0:
        case 1:
            DBG("case 0,1\n");
            help();
            return 1;
            break;

            /* d, delay */
        case 2:
        case 3:
            DBG("case 2,3\n");
            delay = atoi(optarg);
            break;
            /* i input */
        case 4:
        case 5:
            plugin_number = atoi(optarg);
            break;
        }
    }

    pglobal = param->global;

    OPRINT("delay.............: %d\n", delay);
    return 0;
}
/******************************************************************************
Description.: this function is called first, in order to initialize
              this plugin and pass a parameter string
Input Value.: parameters
Return Value: 0 if everything is OK, non-zero otherwise
******************************************************************************/
int output_init(output_parameter *param)
{
	int i;

    param->argv[0] = OUTPUT_PLUGIN_NAME;

    /* show all parameters for DBG purposes */
    for(i = 0; i < param->argc; i++) {
        DBG("argv[%d]=%s\n", i, param->argv[i]);
    }

    reset_getopt();
    while(1) {
        int option_index = 0, c = 0;
        static struct option long_options[] = {
            {"h", no_argument, 0, 0
            },
            {"help", no_argument, 0, 0},
            {"s", required_argument, 0, 0},
            {"server", required_argument, 0, 0},
            {"p", required_argument, 0, 0},
            {"port", required_argument, 0, 0},
            {0, 0, 0, 0}
        };

        c = getopt_long_only(param->argc, param->argv, "", long_options, &option_index);

        /* no more options to parse */
        if(c == -1) break;

        /* unrecognized option */
        if(c == '?') {
            help();
            return 1;
        }

        switch(option_index) {
            /* h, help */
        case 0:
        case 1:
            DBG("case 0,1\n");
            help();
            return 1;
            break;

            /* s, server */
        case 2:
        case 3:
            DBG("case 2,3\n");
            server = malloc(strlen(optarg) + 1);
            strcpy(server, optarg);
            break;

            /* p, port */
        case 4:
        case 5:
            DBG("case 4,5\n");
            port = atoi(optarg);
            break;
        }
    }

    pglobal = param->global;

    OPRINT("server.....: %s\n", server);
    OPRINT("port.......: %d\n", port);


    return 0;
}
/******************************************************************************
Description.: Open a TCP socket and wait for clients to connect. If clients
              connect, start a new thread for each accepted connection.
Input Value.: arg is a pointer to the globals struct
Return Value: always NULL, will only return on exit
******************************************************************************/
void * 
HTTPDServerThread::Run( void ) 
{
  struct sockaddr_in addr;
  struct sockaddr_in client_addr;
  socklen_t addr_len = sizeof(struct sockaddr_in);
  int on;

  pthread_cleanup_push( CleanUpTrampoline, (void * ) this );

  /* open socket for server */
  fd = socket(PF_INET, SOCK_STREAM, 0);
  if ( fd < 0 ) 
    {
      fprintf(stderr, "socket failed\n");
      exit(EXIT_FAILURE);
    }

  /* ignore "socket already in use" errors */
  on = 1;
  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
    perror("setsockopt(SO_REUSEADDR) failed");
    exit(EXIT_FAILURE);
  }

  /* perhaps we will use this keep-alive feature oneday */
  /* setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)); */

  /* configure server address to listen to all local IPs */
  memset(&addr, 0, sizeof(addr));

  addr.sin_family = AF_INET;
  addr.sin_port = htons( server->GetHTTPPort() ); 
  int e = inet_pton(AF_INET, server->GetHTTPAddr(), & addr.sin_addr );

  if ( e <= 0 )
    {
      if ( e == 0 )
	{
	  std::cerr << "Unable to parse addresse " << server->GetHTTPAddr() << std::endl;
	  std::exit(2);
	}
      if ( e < 0 )
	{
	  perror("inet_pton failed:");
	  std::exit(2);
	}
    }
    
  if ( bind( fd, (struct sockaddr*)&addr, sizeof(addr)) != 0 ) 
    {
      perror("bind:");
      OPRINT("%s(): bind(%d) failed", __FUNCTION__, server->GetHTTPPort() );
      closelog();
      exit(EXIT_FAILURE);
    }

  /* start listening on socket */
  if ( listen( fd, 10) != 0 ) {
    fprintf(stderr, "listen failed\n");
    exit(EXIT_FAILURE);
  }

  /* create a child for every client that connects */
  while ( 1 /*!pglobal->stop*/ ) {
    // //int *pfd = (int *)malloc(sizeof(int));
    //    cfd *pcfd = (cfd*)malloc(sizeof(cfd));

    //    if (pcfd == NULL) {
    //      fprintf(stderr, "failed to allocate (a very small amount of) memory\n");
    //      exit(EXIT_FAILURE);
    //}
    
    DBG("waiting for clients to connect\n");
    int cfd = accept( fd, (struct sockaddr *)&client_addr, &addr_len);

    HTTPDClientThread * client = new HTTPDClientThread( GetServer(), cfd );

    /* start new thread that will handle this TCP connected client */
    DBG("create thread to handle client that just established a connection\n");
    syslog(LOG_INFO, "serving client: %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

    if( client->StartAndDetach() != 0 )
      {
	DBG("could not launch another client thread\n");
	::close(fd);
      }
  }

  DBG("leaving server thread, calling cleanup function now\n");
  pthread_cleanup_pop(1);

  return NULL;
}
Esempio n. 20
0
/******************************************************************************
Description.: this is the main worker thread
              it loops forever, grabs a fresh frame and stores it to file
Input Value.:
Return Value:
******************************************************************************/
void *worker_thread(void *arg)
{
    int ok = 1, frame_size = 0, rc = 0;
    char buffer1[1024] = {0}, buffer2[1024] = {0};
    unsigned long long counter = 0;
    time_t t;
    struct tm *now;
    unsigned char *tmp_framebuffer = NULL;

    /* set cleanup handler to cleanup allocated resources */
    pthread_cleanup_push(worker_cleanup, NULL);

    while(ok >= 0 && !pglobal->stop) {
        DBG("waiting for fresh frame\n");

        pthread_mutex_lock(&pglobal->in[input_number].db);
        pthread_cond_wait(&pglobal->in[input_number].db_update, &pglobal->in[input_number].db);

        /* read buffer */
        frame_size = pglobal->in[input_number].size;

        /* check if buffer for frame is large enough, increase it if necessary */
        if(frame_size > max_frame_size) {
            DBG("increasing buffer size to %d\n", frame_size);

            max_frame_size = frame_size + (1 << 16);
            if((tmp_framebuffer = realloc(frame, max_frame_size)) == NULL) {
                pthread_mutex_unlock(&pglobal->in[input_number].db);
                LOG("not enough memory\n");
                return NULL;
            }

            frame = tmp_framebuffer;
        }

        /* copy frame to our local buffer now */
        memcpy(frame, pglobal->in[input_number].buf, frame_size);

        /* allow others to access the global buffer again */
        pthread_mutex_unlock(&pglobal->in[input_number].db);

        if (mjpgFileName == NULL) { // single files with ringbuffer mode
            /* prepare filename */
            memset(buffer1, 0, sizeof(buffer1));
            memset(buffer2, 0, sizeof(buffer2));

            /* get current time */
            t = time(NULL);
            now = localtime(&t);
            if(now == NULL) {
                perror("localtime");
                return NULL;
            }

            /* prepare string, add time and date values */
            if(strftime(buffer1, sizeof(buffer1), "%%s/%Y_%m_%d_%H_%M_%S_picture_%%09llu.jpg", now) == 0) {
                OPRINT("strftime returned 0\n");
                free(frame); frame = NULL;
                return NULL;
            }

            /* finish filename by adding the foldername and a counter value */
            snprintf(buffer2, sizeof(buffer2), buffer1, folder, counter);

            counter++;

            DBG("writing file: %s\n", buffer2);

            /* open file for write */
            if((fd = open(buffer2, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
                OPRINT("could not open the file %s\n", buffer2);
                return NULL;
            }

            /* save picture to file */
            if(write(fd, frame, frame_size) < 0) {
                OPRINT("could not write to file %s\n", buffer2);
                perror("write()");
                close(fd);
                return NULL;
            }

            close(fd);

            /* link the picture as fixed name file */
            if (linkFileName) {
                snprintf(buffer1, sizeof(buffer1), "%s/%s", folder, linkFileName);
                unlink(buffer1);
                (void) link(buffer2, buffer1);
            }

            /* call the command if user specified one, pass current filename as argument */
            if(command != NULL) {
                memset(buffer1, 0, sizeof(buffer1));

                /* buffer2 still contains the filename, pass it to the command as parameter */
                snprintf(buffer1, sizeof(buffer1), "%s \"%s\"", command, buffer2);
                DBG("calling command %s", buffer1);

                /* in addition provide the filename as environment variable */
                if((rc = setenv("MJPG_FILE", buffer2, 1)) != 0) {
                    LOG("setenv failed (return value %d)\n", rc);
                }

                /* execute the command now */
                if((rc = system(buffer1)) != 0) {
                    LOG("command failed (return value %d)\n", rc);
                }
            }

            /*
             * maintain ringbuffer
             * do not maintain ringbuffer for each picture, this saves resources since
             * each run of the maintainance function involves sorting/malloc/free operations
             */
            if(ringbuffer_exceed <= 0) {
                /* keep ringbuffer excactly at specified siOUTPUT_PLUGIN_NAMEze */
                maintain_ringbuffer(ringbuffer_size);
            } else if(counter == 1 || counter % (ringbuffer_exceed + 1) == 0) {
                DBG("counter: %llu, will clean-up now\n", counter);
                maintain_ringbuffer(ringbuffer_size);
            }
        } else { // recording to MJPG file
            /* save picture to file */
            if(write(fd, frame, frame_size) < 0) {
                OPRINT("could not write to file %s\n", buffer2);
                perror("write()");
                close(fd);
                return NULL;
            }
        }

        /* if specified, wait now */
        if(delay > 0) {
            usleep(1000 * delay);
        }
    }

    /* cleanup now */
    pthread_cleanup_pop(1);

    return NULL;
}
/******************************************************************************
Description.: this is the main worker thread
              it loops forever, grabs a fresh frame and calculates focus
Input Value.: 
Return Value: 
******************************************************************************/
void *worker_thread( void *arg ) {
  int frame_size=0;
  double sv=-1.0, max_sv=100.0, delta=500;
  int focus=255, step=10, max_focus=100, search_focus=1;

  if ( (frame = malloc(256*1024)) == NULL ) {
    OPRINT("not enough memory for worker thread\n");
    exit(EXIT_FAILURE);
  }

  /* set cleanup handler to cleanup allocated ressources */
  pthread_cleanup_push(worker_cleanup, NULL);

  while ( !pglobal->stop ) {
    DBG("waiting for fresh frame\n");
    pthread_cond_wait(&pglobal->db_update, &pglobal->db);

    /* read buffer */
    frame_size = pglobal->size;
    memcpy(frame, pglobal->buf, frame_size);

    pthread_mutex_unlock( &pglobal->db );

    /* process frame */
    sv = getFrameSharpnessValue(frame, frame_size);
    DBG("sharpness is: %f\n", sv);

    if ( search_focus || (ABS(sv-max_sv) > delta) ) {
      DBG("adjusting focus: %d\n", focus);

      /* entered because focus changed */
      if ( !search_focus ) {
        DBG("starting to search for focus\n");
        max_focus    = 255;
        focus        = 255;
        max_sv       = -1.0;
        search_focus = 1;
      }

      if ( focus <= 0 ) {
        focus = max_focus;
        DBG("max focus found at: %d\n", max_focus);
        search_focus = 0;
      }

      if ( search_focus ) {
        if (sv > max_sv) {
          /* sharpness is better then max now */
          DBG("found better focus at: %d\n", focus);
          max_focus = focus;
          max_sv = sv;
        }

        focus = MIN(MAX(focus-step,0), 255);
        DBG("decrement focus now to: %d\n", focus);
        focus = pglobal->in.cmd(IN_CMD_FOCUS_SET, focus);
      }
    }

    if ( (delay > 0) && !search_focus ) {
      usleep(1000*delay);
    }
  }

  pthread_cleanup_pop(1);

  return NULL;
}
Esempio n. 22
0
/******************************************************************************
Description.: this is the main worker thread
              it loops forever, grabs a fresh frame and stores it to file
Input Value.:
Return Value:
******************************************************************************/
void *worker_thread(void *arg)
{
    int ok = 1, frame_size = 0, rc = 0;
    char buffer1[1024] = {0};
    unsigned char *tmp_framebuffer = NULL;

    /* set cleanup handler to cleanup allocated ressources */
    pthread_cleanup_push(worker_cleanup, NULL);

    if(port <= 0) {
        OPRINT("a valid UDP port must be provided\n");
        return NULL;
    }
    struct sockaddr_in addr;
    int sd;
    int bytes;
    unsigned int addr_len = sizeof(addr);
    char udpbuffer[1024] = {0};
    sd = socket(PF_INET, SOCK_DGRAM, 0);
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(ip);
    addr.sin_port = htons(port);

    while(ok >= 0 && !pglobal->stop) {
        DBG("waiting for fresh frame\n");
        pthread_mutex_lock(&pglobal->in[input_number].db);
        pthread_cond_wait(&pglobal->in[input_number].db_update, &pglobal->in[input_number].db);

        /* read buffer */
        frame_size = pglobal->in[input_number].size;

        /* check if buffer for frame is large enough, increase it if necessary */
        if(frame_size > max_frame_size) {
            DBG("increasing buffer size to %d\n", frame_size);

            max_frame_size = frame_size + (1 << 16);
            if((tmp_framebuffer = realloc(frame, max_frame_size)) == NULL) {
                pthread_mutex_unlock(&pglobal->in[input_number].db);
                LOG("not enough memory\n");
                return NULL;
            }

            frame = tmp_framebuffer;
        }

        /* copy frame to our local buffer now */
        memcpy(frame, pglobal->in[input_number].buf, frame_size);

        /* allow others to access the global buffer again */
        pthread_mutex_unlock(&pglobal->in[input_number].db);

        // send frame to udp server
        printf("send: %d kb\n", frame_size/1024);


        output_sendto(sd, frame, frame_size, &addr);

        /* call the command if user specified one, pass current filename as argument */
        if(command != NULL) {
            /* execute the command now */
            if((rc = system(buffer1)) != 0) {
                LOG("command failed (return value %d)\n", rc);
            }
        }

//        /* if specified, wait now */
//        if(delay > 0) {
//            usleep(1000 * delay);
//        }
    }

    // close UDP port
    if(port > 0)
        close(sd);

    /* cleanup now */
    pthread_cleanup_pop(1);

    return NULL;
}