2012-01-10 62 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