問題背景:
有些服務器,播放HLS時,m3u8文件經過gzip壓縮,需要進行解壓操作,否則無法播放。
方法1、使用curl下載
使用curl的話則十分簡單,可以在下載之前設置參數,curl會自己進行解壓。參考源文檔的解釋,參數enc可以設置“gzip”或者“”即可(“”則支持更多的壓縮方式)。
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ACCEPT_ENCODING, char *enc);
例子:
CURL *curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
/* enable all supported built-in compressions */
curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "");
/* Perform the request */
curl_easy_perform(curl);
}
Three encodings are supported: identity, meaning non-compressed, deflate which requests the server to compress its response using the zlib algorithm, and gzip which requests the gzip algorithm.
If a zero-length string is set like “”, then an Accept-Encoding: header containing all built-in supported encodings is sent.
參考:
https://curl.haxx.se/libcurl/c/CURLOPT_ACCEPT_ENCODING.html
方法2、下載後使用zlib庫解壓
需要注意的點:
1、gzip格式使用inflate函數進行解壓,而不是uncompress函數(uncompress是給zlib格式使用的)。
2、初始化函數必須使用inflateInit2(stream,47);
例子(截取一些調用代碼):
(1)初始化:
/* 15 is the max windowBits, +32 to enable optional gzip decoding */
if(inflateInit2(&s->b_inflate.stream, 32+15 ) != Z_OK ) {
av_log(h, AV_LOG_ERROR, "Error during zlib initialisation: %s\n", s->b_inflate.stream.msg);
}
if(zlibCompileFlags() & (1<<17)) {
av_log(h, AV_LOG_ERROR, "zlib was compiled without gzip support!\n");
}
(2)解壓:
int ret;
if(!s->b_inflate.p_buffer) {
s->b_inflate.p_buffer = av_malloc(256*1024);
}
if(s->b_inflate.stream.avail_in == 0) {
int i_read = http_read(h, s->b_inflate.p_buffer, 256*1024);
if(i_read <= 0)
return i_read;
s->b_inflate.stream.next_in = s->b_inflate.p_buffer;
s->b_inflate.stream.avail_in = i_read;
}
s->b_inflate.stream.avail_out = size;
s->b_inflate.stream.next_out = buf;
ret = inflate(&s->b_inflate.stream, Z_SYNC_FLUSH);
(3)結束:
inflateEnd(&s->b_inflate.stream);
av_free(s->b_inflate.p_buffer);
參考:
gzip格式rfc 1952 http://www.ietf.org/rfc/rfc1952.txt
deflate格式rfc 1951 http://www.ietf.org/rfc/rfc1951.txt
zlib開發庫 http://www.zlib.net/manual.html