MJPEG streaming with libcurl - c

I want to receive JPEG images from an IP-camera over HTTP. I am using LIBCURL for this purpose in my C program. The camera returns a single image with the following URL:
"http://143.205.116.14?image&res=full&x0=0&y0=0&x1=2944&y1=1920"
Using LIBCURL, I can receive a single image and write it to a .jpg file in the callback function. However, for continuous streaming, the camera accepts a GET request as follows:
"GET /mjpeg&res=full&x0=0&y0=0&x1=2944&y1=1920 HTTP/1.1\r\n HOST:143.205.16.14\r\n\r\n"
I was wondering how do I specify this GET request in libcurl. Is it possible to use in curl_easy_setopt()?
At present I use the following code to get a single image and save in the write_data callback function:
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
size_t written;
written = fwrite(ptr, size, nmemb, stream);
return written;
}
int main()
{
curl = curl_easy_init();
if(curl) {
fp = fopen("C:\\trans.txt","wb");
curl_easy_setopt(curl, CURLOPT_URL, "http://143.205.116.14?image&res=full&x0=0&y0=0&x1=2944&y1=1920");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
fclose(fp);
}
How do I use the GET method so that the images are received continuously and saved by the callback function?

I'm not totally sure about this, but I think you must open the connection with CURL specify that the connection will be kept alive and then start downloading data.
With some type of while() you should download data and get each JPEG that the camera sent.
You must read about MJPEG codec, which has a structure where each JPEG is delimited by a header.

Have you tried using the full URL?
http://143.205.116.14/mjpeg&res=full&x0=0&y0=0&x1=2944&y1=1920
libcurl parses this and creates the GET request. GET is the default for HTTP, you have to add some code to get HEAD or POST (so you probably don't want to do that).

Related

How do I use libcurl to printf a remote FTP directory listing?

I think I'm supposed to use CURLOPT_DIRLISTONLY but I'm not really sure how to proceed.
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DIRLISTONLY, long listonly);
I'm not sure how to make the call to actually print the list.
Enabling the CURLOPT_DIRLISTONLY option for FTP has the effect of retrieving only file names instead of file details (e.g. file size, date, etc.) basically as the difference between using a plain ls (only names) or a ls -l (listing with details) on UNIX. At the FTP protocol level, enabling CURLOPT_DIRLISTONLY will make libcurl issue a NLST command rather than a LIST. Then to get the directory listing you do the same as a file transfer, with the difference that your ftp:// URL will point to a directory (and not to a file). The contents of that transfer will be your directory listing.
To display the directory listing, rather than saving it to a file, you can use the CURLOPT_WRITEFUNCTION option to have libcurl call a callback function you supply for every block of data. That function only needs to fwrite the data to stdout to display it. It should look something like this:
void write_callback(void* data, size_t size, size_t nmemb, void* ptr)
{
fwrite(data, size, nmemb, stdout);
}
int main()
{
// ...
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_callback);
// ...
ret = curl_easy_perform(handle);
}

How can I use libcurl to get a page with a specific server IP

I am crawling a page by libcurl. I need to use specific IP to get page. this ip has been made by the DNS resolver. So I can skip the getaddrinfo in libcurl and cost less time.
I have asked a question How can I use libcurl function "curl_easy_setopt(CURL *handle, CURLOPT_DNS_LOCAL_IP4, char *address);" but I found this is not what I want.
You can "pre-populate" libcurl's DNS cache with CURLOPT_RESOLVE, and then you can keep using the host name in the URL just like normal.
Here's a little sample telling curl example.com is at 127.0.0.1
CURL *curl;
struct curl_slist *host = NULL;
host = curl_slist_append(NULL, "example.com:80:127.0.0.1");
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
curl_slist_free_all(host);
Another option is to use the correct IP in the URL and send a custom Host: header that includes the correct host name.
(CURLOPT_DNS_LOCAL_IP4 sets "the local IPv4 address that the resolver should bind to" and is thus a completely different functionality)

Cannot download more than one file with sockets in C

When i try to download a set of files using stream sockets over an HTTP protocol, it only gets data from the first file i try to download.
Assume a loop like the following...
char* file = (char*) malloc(enough_space);
char page[] = {"www.foobar.com"};
for(int n=0 ; n<10 ; n++)
{
sprintf(file, "file%i.html", n);
fopen(file, "wb");
sprintf(request, "GET %s HTTP/1.1\nHost: %s\n\n", file, page);
write( socket, request, strlen(request) );
read_file(output_file);
fclose(output_file);
}
Where a connection has been established first.
This code would give me file1.html, including its header from the server.. But only the first file, and this puzzles me.. What will i have to do in order to get them all?
Thanks up front.
HTTP was designed so that just a single file can be downloaded over a TCP connection. To download multiple files over one TCP connection, you could use HTTP Pipelining. You can read more here: HTTP pipelining request text example
Or you could just use one of the many libraries that will handle this, and many other caveats of HTTP for you: libcurl, libsoup...

libcurl clean CURLOPT_POSTFIELDS?

Hello what I am trying to do is send post method twice, however when I send it a second time the information from the first time is also being included and I do not want that.
To illustrate what I mean, this is the code that sends using post method. (the handle curl was already created)
void process(char* transferBuffer) {
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost/cpp.php");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, transferBuffer);
res = curl_easy_perform(curl);
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
If I do something like:
process("name=John"); - webserver receives name=John
process("name=El"); - webserver receives name=John AND name=El
What I want to do is somehow clean previously used data;
the curl handle was already created ... What I want to do is somehow clean previously used data
All I can say is that if you want to reuse your curl handle - which is a best practice, you should reset it with curl_easy_reset before re-setting your options and re-performing the transfer.
Note that without the complete sample code (including the creation of your curl handle, etc) it is quite hard to provide a detailed answer.

Twitter Stream API through C and curl [duplicate]

This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
Trying to Access Twitter Streaming API with C
Could anyone help me how do I code in C of getting a stream of tweets? I already have read how to output results through C libcurl get output into a string.
I also know how to get a stream of tweets just through 'curl' in the command terminal. Thanks!
If I understand you're asking for the basic pattern of a CURL request, which I personally thought was not that well written in the tutorial. It seemed like a dozen lines of code should provide the basic pattern for how to use CURL, but I didn't see it written like that in a tutorial. Hope this helps:
CURL *handle;
char PostFields[512];
/* initialise curl */
curl_global_init( CURL_GLOBAL_ALL )
handle = curl_easy_init();
/* set options to post */
curl_easy_setopt( handle, CURLOPT_URL, TwitterUrl );
curl_easy_setopt( handle, CURLOPT_POST, 1 );
sprintf( PostFields, "user_id=%s?screen_name=%s", TwitterId, TwitterName );
curl_easy_setopt( handle, CURLOPT_POSTFIELDS, (void*)PostFields );
curl_easy_setopt( handle, CURLOPT_POSTFIELDSSIZE, strlen( PostFields ) );
/* set options to handle response */
curl_easy_setopt( handle, CURLOPT_HEADERFUNCTION, HandleTwitterHeader );
curl_easy_setopt( handle, CURLOPT_WRITEFUNCTION, HandleTwitterResponse );
/* do the request */
curl_easy_perform( handle );
curl_easy_cleanup( handle );
I'm not sure to understand your question, and I am not sure you are understanding it well.
Perhaps your issue is related to JSON in C. There are several C (& C++) libraries for JSON. You could use jansson

Resources