问题背景:
有些服务器,播放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