从libcurl提供的流中读取jpeg

时间:2012-01-10 10:10:42

标签: c++ http jpeg libcurl

我有一台IP摄像机(哦,很惊讶)我想要一些照片。首先,我只想阅读一个jpeg。由于所有通信都通过http完成,我使用libcurl。所以我的代码看起来非常简单:

// 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的流转储到文件流中。现在这实际上有效:

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));
}

这不起作用....?

最好的问候

托拜厄斯

3 个答案:

答案 0 :(得分:1)

您是希望将其转储到磁盘上的文件中,还是要将其接收到内存缓冲区(或数据库或其他任何内容)?无论哪种方式,cURL都可以帮到你。如果您希望将其存储在文件中,则可以使用CURLOPT_WRITEDATA,而无需设置任何CURLOPT_WRITEFUNCTION。如果你想要它在内存缓冲区中,那么你必须提供CURLOPT_WRITEDATACURLOPT_WRITEFUNCTION,后者是指向你编写的函数的指针,该函数接受来自远程服务器的数据并存储它某处。

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

答案 1 :(得分: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,我猜它有点破坏了内存。

答案 2 :(得分: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