Чтение jpeg из потока, предоставленного libcurl - PullRequest
0 голосов
/ 10 января 2012

У меня есть 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), и мне нужно вызвать curl_easy_setopt () с параметром CURLOPT_WRITEDATA и передать ему поток.

Теперь это тот случай, когда я не уверен, как это сделать. Если я просто передам ему обычный файловый поток и запишу весь материал в файл (как будто это был просто текст), он не будет работать, так как обычный файловый поток не понимает 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));
}

Это не работает ....?

С наилучшими пожеланиями

Tobias

Ответы [ 3 ]

1 голос
/ 11 января 2012

Хорошо, я выяснил, в чем проблема:

В целях отладки моя функция 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 байтами. Так как я получаю 2 Кбайт каждый раз, когда вызывается функция write_test, я думаю, это как-то повредило память.

1 голос
/ 10 января 2012

Вы хотите, чтобы он был выгружен в файл на диске, или вы хотите получить его в буфер памяти (или базу данных, или что-то еще)? В любом случае CURL может помочь вам. Если вы хотите, чтобы это было в файле, вы можете использовать CURLOPT_WRITEDATA, как вы сказали, без установки CURLOPT_WRITEFUNCTION. Если вы хотите получить его в буфере памяти, вам нужно будет указать и CURLOPT_WRITEDATA, и CURLOPT_WRITEFUNCTION, причем последний является указателем на написанную вами функцию, которая принимает данные, поступающие с удаленного сервера, и сохраняет их где-то.

Что вы хотите сделать с JPEG после его получения? Кажется, это выходит за рамки вашего вопроса, если я правильно понимаю, и это не имеет никакого отношения к cURL. "libjpeg" действительно может вам помочь.

0 голосов
/ 07 ноября 2013

Это решение размещено на сайте 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

...