HLS & ffmpeg trouble again ? Cannot pass cookies to ffmpeg
#1
Hi all,

I've been working to fix an add-on working against a content provider that serves video content via HLS. This specific provider requires the correct cookies
to be sent with the HTTP requests for all segments of the m3u8 file.

I know ffmpeg was recently bumped to v1.2 and that it supports HLS much better now. I also know that XBMC now supports passing protocol options to ffmpeg but
I can't get it to work and I think there's a bug (consulting before opening a bug..)

Side note: Some of these HLS content providers are quite picky and will not like HTTP HEAD methods. Specifically, when XBMC attempts to find the mime type
(CCurlFile::GetMimeType). The only workaround is to set the mime-type for the listItem yourself. (could have enjoyed a way to change the method to GET).

Anyway, the current code in CDVDDemuxFFmpeg::GetFFMpegOptionsFromURL will parse the options passed and will set them into ffmpeg's dictionary.
The problem is - it does so for very selected options (like user-agent). All other options are handled as HTTP headers, which seems not to be enough.

for(std::map<CStdString, CStdString>::const_iterator it = protocolOptions.begin(); it != protocolOptions.end(); ++it)
{
const CStdString &name = it->first;
const CStdString &value = it->second;

if (name.Equals("seekable"))
m_dllAvUtil.av_dict_set(&options, "seekable", value.c_str(), 0);
else if (name.Equals("User-Agent"))
{
m_dllAvUtil.av_dict_set(&options, "user-agent", value.c_str(), 0);
hasUserAgent = true;
}
else if (!name.Equals("auth") && !name.Equals("Encoding"))
// all other protocol options can be added as http header.
headers.append(name).append(": ").append(value).append("\r\n");
}
if (!hasUserAgent)
// set default xbmc user-agent.
m_dllAvUtil.av_dict_set(&options, "user-agent", g_advancedSettings.m_userAgent.c_str(), 0);

if (!headers.empty())
m_dllAvUtil.av_dict_set(&options, "headers", headers.c_str(), 0);


The URL I'm passing to play the video looks like the following:
http://<some_host>/segments.m3u8|User-Agent=<some_good_user_agent>&Cookie=<cookies_that_are_valid>

This is enough for XBMC to obtain the playlist (with all the TS segments) but later when ffmpeg tries to access each file it receives a 403 Forbidden since it didn't
pass those cookies. Note: I know ffmpeg will save cookies and keep them for later requests (see hls.c in ffmpeg's lib avformat).

I couldn't find anywhere, in ffmpeg's code, where headers from outside get turned into cookies. I saw where it parses cookies returning from the server,
I saw that when it builds the HTTP request it will add cookies if they exist within the HTTPContext, but I guess they're not there (http.c -> http_connect function).

The request for the first TS segment looks like this:
GET /<host>/segment-0.ts HTTP/1.1
User-Agent: stagefright/1.2 (Linux; Android 4.2.2)
Accept: */*
Connection: close
Host:<host>

As you can see, it will preserve the user agent as it was specifically set as an option.


Am I doing something wrong or is there really some kind of bug ?

I think we should add the following block of code to GetFFMpegOptionsFromURL:

else if (name.Equals("Cookie"))
{
m_dllAvUtil.av_dict_set(&options, "cookies", value.c_str(), 0);
}

Since ffmpeg has a specific protocol option for passing in cookie data. Side note - ffmpeg is extremely picky with cookies. It requires the path, domain and cookie data to be present in order to use the cookie later.


I'm currently trying to build XBMC but ffmpeg keeps failing to compile. I'll update if I have more luck.

Any help is very much appreciated!
Reply
#2
Bingo. I'm having a similar problem.

This url
http://46.165.210.22/hqstream/eurospirt1...1375113106
generates a playlist containing "chunklist.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INFTongueROGRAM-ID=1,BANDWIDTH=427055,CODECS="avc1.66.31, mp4a.40.34",RESOLUTION=600x364
chunklist.m3u8

If it is accessed with
curl -X GET "http://46.165.210.22/hqstream/eurospirt1/chunklist.m3u8" -v > D:\chunk.txt
the response is "Not allowed URL"

If it is accessed with
curl -X GET "http://46.165.210.22/hqstream/eurospirt1/chunklist.m3u8" -H "Cookie: eurospirt1keys=goXwiG_clitxCyNihl0ErA; eurospirt1keyt=1375113106" -v > D:\chunk.txt
the response is
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-ALLOW-CACHE:NO
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:22917
#EXTINF:2.48,
media_22917.ts
#EXTINF:5.0,
media_22918.ts

So this confirms the need for cookies

if I issue
ffplay -I "http://46.165.210.22/hqstream/eurospirt1/playlist.m3u8?keys=goXwiG_clitxCyNihl0ErA&keyt=1375113106"
it fails

if I issue
ffplay -i "http://46.165.210.22/hqstream/eurospirt1/playlist.m3u8?keys=goXwiG_clitxCyNihl0ErA&keyt=1375113106" -header "Cookie: eurospirt1keys=goXwiG_clitxCyNihl0ErA; eurospirt1keyt=1375113106"
it returns "[http @ 0213c6a0] No trailing CRLF found in HTTP header."
and if I add \r\n it is simply deleted by the command processor and I get the same message.

So at this point I am unable to invoke ffmpeg with a cookies header. Even if I could, based on your experience, it would fail to access the .ts files.

Have you reported this to the ffmpeg team?
Reply
#3
How to fix this problem on xbmc 13 on windows and little black box(lunix)? i got some akamai AES HLS m3u8 that xbmc cant play them ! hope you be able to help me .
Reply

Logout Mark Read Team Forum Stats Members Help
HLS & ffmpeg trouble again ? Cannot pass cookies to ffmpeg0