2012-01-10 63 views
0

我有一台IP摄像机,从中可以得到一些图片。首先我只想读一个jpeg。由于所有通信都是通过http完成的,因此我使用libcurl。所以我的代码看起来很简单,像这样:从libcurl提供的流中读取jpeg

// Initialize some stuff 
CURL * curl; 
curl = curl_easy_init(); 
curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.0.147/cgi-bin/mjpeg?mode=single"); curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION, write_test); 

现在我很清楚我需要两件事。我需要声明和定义回调函数(write_test),我需要使用参数CURLOPT_WRITEDATA调用curl_easy_setopt()并为他提供一个流。

现在,我不知道如何做到这一点。如果我只是给他一个普通的文件流,并将所有的东西写入文件(比如它只是一些文本),它将无法正常工作,因为普通的文件流不理解jpeg。

我该怎么做?我是否需要像“libjpeg”这样的附加库?我将如何与流合作?

//编辑:

好吧提到我可以只转储一个单独的JPEG流为FILESTREAM。现在,这实际工作:

FILE* pFile = fopen("/home/username/test.jpeg","w"); 
curl = curl_easy_init(); 
curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.0.147/cgi-bin/mjpeg?mode=single"); 
//curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION, write_test); 
curl_easy_setopt(curl,CURLOPT_WRITEDATA, pFile); 
curl_easy_perform(curl); 

如果我不声明一个回调函数它工作正常 - 但如果我不注释掉CURLOP_WRITEFUNCTION,并通过自己申报的回调我没有得到任何好的结果。

- >

size_t write_test(void *ptr, size_t size, size_t nmeb, void *stream) 
{ 
    return fwrite(ptr,size,nmeb,static_cast<FILE*>(stream)); 
} 

这不工作....?

问候

托比亚斯

+1

“它不起作用,因为普通文件流不能理解jpeg。”它需要了解什么?如果你用二进制模式写入文件扩展名为.jpg不起作用?或者,您是否在没有JFIF标题的情况下获取数据?或希望首先以某种方式处理文件?还是它给你一个连续的流,你需要切成个人的图像或其他东西? – Rup 2012-01-10 10:20:02

+0

哦,有时候,我觉得我不应该在清晨早些时候工作 - 我可以(当我只是得到一张照片时)将所有流转储到文件中。但是我没有注意到其他东西(只是要在上面的问题中指定它) – Toby 2012-01-10 10:28:13

+0

您的write_test回调函数对我来说看起来不错,因为除了通过调用'fwrite'完全相同的参数。难道是因为'write_test'是一个C++函数,你需要以某种方式将它声明为一个C函数(即在'extern“C”{}'块中)?我不知道C++。 – Celada 2012-01-10 10:38:06

回答

1

好吧,我发现了问题所在:

为了调试的目的我实施了这样的我“write_test”功能:

size_t write_test(void *ptr, size_t size, size_t nmeb, void *stream) 
{ 
    memcpy(buffer,ptr,size*nmeb); 
    size_t no; 

    no = fwrite(ptr,size,nmeb,static_cast<FILE*>(stream)); 
    printf("no: %d\tsize: %d\tnmeb: %d\n",no,size,nmeb); 
    return no; 
} 

现在,不幸的是我没有给你用的memcpy的部分(你是我的错......)。现在,如果我评论它的程序工作。现在我没有搜索那里的问题,因为memcpy不应该影响我的数据与ptr。我想它没有我只分配了50字节的缓冲区。由于每次调用write_test函数时我都会得到2kByte,所以我猜它有点损坏了内存。

1

你想它转储到磁盘上的文件,或者你想它接收到内存缓冲区(或数据库,或其他任何东西)?无论哪种方式cURL可以帮助你。如果你想在一个文件中,那么你可以使用CURLOPT_WRITEDATA,正如你所说的没有设置任何CURLOPT_WRITEFUNCTION。如果你需要一个内存缓冲区,那么你将不得不提供CURLOPT_WRITEDATACURLOPT_WRITEFUNCTION,后者是一个指向你写的函数的指针,它接受来自远程服务器的数据并将其存储在某个地方。

你想要什么与JPEG一旦你得到它?这似乎超出了你的问题的范围,如果我理解正确的话,它与cURL无关。 “libjpeg”确实可以帮助你。

0

这是在libcurl的网站上发布的解决方案。这个功能对我来说完全适合你,和你一样的目标!

struct MemoryStruct { 
    char *memory; 
    size_t size; 
}; 


size_t MailServer::WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) 
{ 
    size_t realsize = size * nmemb; 
    struct MemoryStruct *mem = (struct MemoryStruct *)userp; 

    mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1); 
    if(mem->memory == NULL) { 
     /* out of memory! */ 
     printf("not enough memory (realloc returned NULL)\n"); 
     return 0; 
    } 

    memcpy(&(mem->memory[mem->size]), contents, realsize); 
    mem->size += realsize; 
    mem->memory[mem->size] = 0; 

    return realsize; 
} 

我希望它有帮助! :D