Hi to all.

I'm using libcurl as a receiver for MP3 radio streams.
When using custom headers in conjunction with header and body data callbacks, some data is missing in the data callbacks. This is also reproducable when using the following command line:

curl --header "Icy-MetaData: 1" -sD - -o ./ndr1.mp3 http://ndr-edge-2061.dus-lg.cdn.addradio.net/ndr/ndr1niedersachsen/hannover/mp3/128/stream.mp3

If you play the resulting MP3 file with some kind of media player you can hear dropdowns caused by missing data. If you remove the custom header, then the stream is OK. Also this behaviour is independant of the header value, so any header string will cause the problem.

You can also see the problem in the CURLOPT_WRITEFUNCTION callback.
Usually MP3 streams send around 1400 bytes per callback. When header(s) are set, the byte count is smaller from time to time. But that is not because the data is fragmented in more than one call, some data is simply missing.

The following code is an excerpt of the cURL setup part of the C++ class I'm using.
I hope this information helps...

Kind regards,
Dirk.

    // Set URL to download from
    errval = curl_easy_setopt(curl(), CURLOPT_URL, url.c_str());
    if (!success()) {
        throw util::app_error_fmt("TWebClient::execute() Setting URL failed for $ [%]", url, errmsg());
    }

//    // Set custom headers (commented for now!)
//    if (!txHeaders.empty() && !util::assigned(headerList)) {
//        bool first = true;
//        headerList = nil;
//        for (size_t i=0; i<txHeaders.size(); ++i) {
//            const std::string& s = txHeaders.at(i);
//            struct curl_slist * sl = nil;
//            if (!s.empty()) {
//                if (first) {
//                    sl = headerList = curl_slist_append(NULL, s.c_str());
//                    first = false;
//                } else {
//                    sl = curl_slist_append(headerList, s.c_str());
//                }
//                if (!util::assigned(sl)) {
//                    throw util::app_error_fmt("TWebClient::execute() Setting custom header failed for $ <%;> [%]", url, s, errmsg());
//                }
//            }
//        }
//        if (util::assigned(headerList)) {
//            errval = curl_easy_setopt(curl(), CURLOPT_HTTPHEADER, headerList);
//            if (!success()) {
//                throw util::app_error_fmt("TWebClient::execute() Setting custom headers failed for $ [%]", url, errmsg());
//            }
//        }
//    }

    // Setup transfer data callback
    if (nil != callback) {
        errval = curl_easy_setopt(curl(), CURLOPT_WRITEFUNCTION, callback);
        if (!success()) {
            throw util::app_error_fmt("TWebClient::execute() Setting callback method failed for $ [%]", url, errmsg());
        }
    }
    errval = curl_easy_setopt(curl(), CURLOPT_WRITEDATA, this);
    if (!success()) {
        throw util::app_error_fmt("TWebClient::execute() Setting CURLOPT_WRITEDATA option failed for $ [%]", url, errmsg());
    }

    // Setup header data callback
    if (requestHeaders && nil != onHeaderDataMethod) {
        errval = curl_easy_setopt(curl(), CURLOPT_HEADERFUNCTION, writeHeaderDispatcher);
        if (!success()) {
            throw util::app_error_fmt("TWebClient::execute() Setting header callback method failed for $ [%]", url, errmsg());
        }
        errval = curl_easy_setopt(curl(), CURLOPT_HEADERDATA, this);
        if (!success()) {
            throw util::app_error_fmt("TWebClient::execute() Setting CURLOPT_HEADERDATA option failed for $ [%]", url, errmsg());
        }
    }

    // Enable all supported built-in compressions
    errval = curl_easy_setopt(curl(), CURLOPT_ACCEPT_ENCODING, "");
    if (!success()) {
        throw util::app_error_fmt("TWebClient::execute() Setting CURLOPT_ACCEPT_ENCODING option failed for $ [%]", url, errmsg());
    }

    // Disable signal handlers
    errval = curl_easy_setopt(curl(), CURLOPT_NOSIGNAL, 1L);
    if (!success()) { // && CURLE_UNKNOWN_OPTION != errval) {
        throw util::app_error_fmt("TWebClient::execute() Setting CURLOPT_NOSIGNAL option failed for $ [%]", url, errmsg());
    }

    // Set application user agent name
    errval = curl_easy_setopt(curl(), CURLOPT_USERAGENT, agent.c_str());
    if (!success()) {
        throw util::app_error_fmt("TWebClient::execute() Setting CURLOPT_USERAGENT option failed for $", agent, errmsg());
    }

    // Be verbose?
    if (debug) {
        errval = curl_easy_setopt(curl(), CURLOPT_VERBOSE, 1L);
        if (!success()) {
            throw util::app_error_fmt("TWebClient::execute() Setting CURLOPT_VERBOSE option failed for $", agent, errmsg());
        }
    }

    // Execute prepared CURL action...
    errval = curl_easy_perform(curl());
    return success();

-------------------------------------------------------------------
Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library
Etiquette:   https://curl.haxx.se/mail/etiquette.html

Reply via email to