Hi all,

I am trying to implement MJPEG streaming server using MHD. I have attached my test code.

Basically I am looping through a directory with JPEG files to create each frame. And I am able to start the process without any error.

But fetching the URL using wget gets stuck . Vlc player shows the first frame only.

I suspect there is some issue with buffer handling in the callback function. Please take a look and let me know if you find any issues in my code(Please note that this is just POC code). Also If there is a publicly available implementation of MJPEG server using MHD please let me know.

Thanks for your time.

Regards,
Kiran G




/*
 * Copyright (C) 2011-2013 Red Hat, Inc.
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA
 *
 * Author: Gris Ge <fge <at> redhat.com>
 */

#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
#include <microhttpd.h>
#include <json/json.h>
#include <uriparser/Uri.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/param.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define PAGE "<html><head><title>File not found</title></head><body>File not found</body></html>"
#define PORT 8888
#define TMO 60000
#define LSM_SOCK_BUFF_LEN 250 // No idea why 4096 fail.
#define LSM_DEFAULT_ID 100
#define JSON_MIME "application/json"
#define LSM_HEADER_LEN 10
#define LSM_API_VER_LEN 4

// gcc lsm_rest.c -lmicrohttpd -ljson-c -luriparser -o lsm_restd

static ssize_t
callback (void *cls, uint64_t pos, char *buf, size_t max)
{


    int ret;
    char fullFileName[100];
    char *header="--MyBoundary\r\nContent-Type: image/jpeg\r\n\r\n";
    int headersize=strlen(header);
    FILE *file;
    char **filelist = (char *[]) {
        "/home/kiran/mjpg-streamer-read-only/mjpg-streamer-1.6.3/plugins/input_testpicture/pictures/320x240_2.jpg","/home/kiran/mjpg-streamer-read-only/mjpg-streamer-1.6.3/plugins/input_testpicture/pictures/960x720_1.jpg","/home/kiran/mjpg-streamer-read-only/mjpg-streamer-1.6.3/plugins/input_testpicture/pictures/960x720_2.jpg","/home/kiran/mjpg-streamer-read-only/mjpg-streamer-1.6.3/plugins/input_testpicture/pictures/640x480_2.jpg","/home/kiran/mjpg-streamer-read-only/mjpg-streamer-1.6.3/plugins/input_testpicture/pictures/320x240_1.jpg","/home/kiran/mjpg-streamer-read-only/mjpg-streamer-1.6.3/plugins/input_testpicture/pictures/160x120_1.jpg","/home/kiran/mjpg-streamer-read-only/mjpg-streamer-1.6.3/plugins/input_testpicture/pictures/640x480_1.jpg","/home/kiran/mjpg-streamer-read-only/mjpg-streamer-1.6.3/plugins/input_testpicture/pictures/160x120_2.jpg"
    };
    static int file_num=0;
    printf("callback 1 %d \n",file_num);
    sleep(5);
    struct stat buf1;
    printf("callback 2 file %s \n",filelist[file_num]);

    printf("callback 3 \n");
    if (0 == stat (filelist[file_num], &buf1))
    {
        printf("STAT ok\n");
        file = fopen (filelist[file_num], "rb");
        perror ("The following error occurred");
    }
    else

    {
        printf("STAT error\n");
        file = NULL;
        return 0;
    }
    if (file == NULL)
    {
        printf("callback NULL \n");
    }
    else
    {
        printf("callback 4 \n");
        file_num++;
        if(file_num >7)
        {
            file_num=0;
        }
        printf("callback 5 \n");
        (void)  fseek (file, pos, SEEK_SET);
        strcpy(buf,header);
        ret=fread (buf+headersize, 1, max, file);
        fclose(file);
        if(ret==0)
            buf[0]='\0';
        printf("Returning %d \n",ret);
        return ret+headersize;
    }


    printf("HERE5\n");









}

static void
free_callback (void *cls)
{

}



int file_handler(void *cls, struct MHD_Connection *connection,
                 const char *url,
                 const char *method, const char *version,
                 const char *upload_data,
                 size_t *upload_data_size, void **con_cls)
{
    const char *arg = MHD_lookup_connection_value (connection,MHD_GET_ARGUMENT_KIND, "test");
    printf ("file_handler New %s request, URL: %s ARG: %s\n", method, url,arg); // code_debug
}

int view_handler(void *cls, struct MHD_Connection *connection,
                 const char *url,
                 const char *method, const char *version,
                 const char *upload_data,
                 size_t *upload_data_size, void **con_cls)
{
    struct MHD_Response *response;
    int ret;

    printf("Before MHD_create_response_from_callback\n");
    response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN, 32 * 1024,     /* 32k page size */
               &callback,
               0,
               &free_callback);
    printf("After MHD_create_response_from_callback\n");
    if (response == NULL)
    {

        return MHD_NO;
    }

    MHD_add_response_header(response, "Content-Type", "multipart/x-mixed-replace;boundary=MyBoundary");
    MHD_add_response_header(response, "Cache-Control", "no-cache");
    MHD_add_response_header(response, "Expires", "Thu, 01 Dec 1994 16:00:00 GMT");
    MHD_add_response_header(response, "Connection", "close");
    printf("Before MHD_queue_response\n");
    ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
    printf("After MHD_queue_response\n");
    MHD_destroy_response (response);
    const char *arg = MHD_lookup_connection_value (connection,
                      MHD_GET_ARGUMENT_KIND, "test");
    printf ("view_handler New %s request, URL: %s ARG: %s\n", method, url,arg); // code_debug

}
int answer_to_connection(void *cls, struct MHD_Connection *connection,
                         const char *url,
                         const char *method, const char *version,
                         const char *upload_data,
                         size_t *upload_data_size, void **con_cls)
{

    char *url_copy;
    url_copy=strdup(url);
    struct MHD_Response *response;
    printf("HERE\n");
    if (0 != strcmp (method, "GET")) {
        return MHD_NO;
    }

    if (strlen(url) == 1) {
        return MHD_NO;
    }
    printf("HERE\n");

    //char command[10];
    char *url_without_arguments = strtok(url_copy, "?");
    printf("URL without arguments : %s\n",url_without_arguments);
    char *command = strtok(url_without_arguments, "/");
    printf("Command : %s\n",command);
    //Removing arguments (?test)

    if(0==strcmp(command,"file"))
    {
        file_handler(cls, connection,url,method, version,upload_data,upload_data_size, con_cls);
    }
    else  if(0==strcmp(command,"view"))
    {
        view_handler(cls, connection,url,method, version,upload_data,upload_data_size, con_cls);
    }

    //MHD_destroy_response(response);

}

int main (int argc, char *argv[])
{
    struct MHD_Daemon *daemon;
    daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
                              &answer_to_connection, NULL, MHD_OPTION_END);
    if (NULL == daemon) return 1;
    getchar();
    MHD_stop_daemon(daemon);
    return 0;
}

Reply via email to