2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #if (defined HAVE_CONFIG_H) && (!defined WIN32)
25 #include "system.h" // just for HAS_LIBRTMP
29 #include "settings/AdvancedSettings.h"
30 #include "DVDInputStreamRTMP.h"
31 #include "threads/SingleLock.h"
32 #include "utils/log.h"
33 #include "utils/Variant.h"
37 using namespace XFILE;
40 static int RTMP_level=0;
43 static void CDVDInputStreamRTMP_Log(int level, const char *fmt, va_list args)
47 if (level > RTMP_level)
53 case RTMP_LOGCRIT: level = LOGFATAL; break;
54 case RTMP_LOGERROR: level = LOGERROR; break;
55 case RTMP_LOGWARNING: level = LOGWARNING; break;
56 case RTMP_LOGINFO: level = LOGNOTICE; break;
57 case RTMP_LOGDEBUG: level = LOGINFO; break;
58 case RTMP_LOGDEBUG2: level = LOGDEBUG; break;
61 vsnprintf(buf, sizeof(buf), fmt, args);
62 CLog::Log(level, "%s", buf);
66 CDVDInputStreamRTMP::CDVDInputStreamRTMP() : CDVDInputStream(DVDSTREAM_TYPE_RTMP)
70 CLog::Log(LOGINFO,"%s: Using external libRTMP",__FUNCTION__);
73 m_libRTMP.LogSetCallback(CDVDInputStreamRTMP_Log);
74 switch (g_advancedSettings.m_logLevel)
76 case LOG_LEVEL_DEBUG_SAMBA: level = RTMP_LOGDEBUG2; break;
77 case LOG_LEVEL_DEBUG_FREEMEM:
78 case LOG_LEVEL_DEBUG: level = RTMP_LOGDEBUG; break;
79 case LOG_LEVEL_NORMAL: level = RTMP_LOGINFO; break;
80 default: level = RTMP_LOGCRIT; break;
82 m_libRTMP.LogSetLevel(level);
85 m_rtmp = m_libRTMP.Alloc();
86 m_libRTMP.Init(m_rtmp);
95 m_sStreamPlaying = NULL;
98 CDVDInputStreamRTMP::~CDVDInputStreamRTMP()
100 free(m_sStreamPlaying);
101 m_sStreamPlaying = NULL;
104 m_libRTMP.Free(m_rtmp);
109 bool CDVDInputStreamRTMP::IsEOF()
114 #define SetAVal(av, cstr) av.av_val = (char *)cstr.c_str(); av.av_len = cstr.length()
116 #define AVC(str) {(char *)str,sizeof(str)-1}
118 /* librtmp option names are slightly different */
119 static const struct {
123 { "SWFPlayer", AVC("swfUrl") },
124 { "PageURL", AVC("pageUrl") },
125 { "PlayPath", AVC("playpath") },
126 { "TcUrl", AVC("tcUrl") },
127 { "IsLive", AVC("live") },
131 bool CDVDInputStreamRTMP::Open(const char* strFile, const std::string& content)
133 if (m_sStreamPlaying)
135 free(m_sStreamPlaying);
136 m_sStreamPlaying = NULL;
139 if (!CDVDInputStream::Open(strFile, "video/x-flv"))
142 CSingleLock lock(m_RTMPSection);
144 // libRTMP can and will alter strFile, so take a copy of it
145 m_sStreamPlaying = (char*)calloc(strlen(strFile)+1,sizeof(char));
146 strcpy(m_sStreamPlaying,strFile);
148 if (!m_libRTMP.SetupURL(m_rtmp, m_sStreamPlaying))
151 // SetOpt and SetAVal copy pointers to the value. librtmp doesn't use the values until the Connect() call,
152 // so value objects must stay allocated until then. To be extra safe, keep the values around until Close(),
153 // in case librtmp needs them again.
154 m_optionvalues.clear();
155 for (int i=0; options[i].name; i++)
157 CStdString tmp = m_item.GetProperty(options[i].name).asString();
160 m_optionvalues.push_back(tmp);
162 SetAVal(av_tmp, m_optionvalues.back());
163 m_libRTMP.SetOpt(m_rtmp, &options[i].key, &av_tmp);
167 if (!m_libRTMP.Connect(m_rtmp, NULL) || !m_libRTMP.ConnectStream(m_rtmp, 0))
175 // close file and reset everything
176 void CDVDInputStreamRTMP::Close()
178 CSingleLock lock(m_RTMPSection);
179 CDVDInputStream::Close();
181 m_libRTMP.Close(m_rtmp);
183 m_optionvalues.clear();
188 int CDVDInputStreamRTMP::Read(BYTE* buf, int buf_size)
190 int i = m_libRTMP.Read(m_rtmp, (char *)buf, buf_size);
197 int64_t CDVDInputStreamRTMP::Seek(int64_t offset, int whence)
199 if (whence == SEEK_POSSIBLE)
205 bool CDVDInputStreamRTMP::SeekTime(int iTimeInMsec)
207 CLog::Log(LOGNOTICE, "RTMP Seek to %i requested", iTimeInMsec);
208 CSingleLock lock(m_RTMPSection);
210 if (m_libRTMP.SendSeek(m_rtmp, iTimeInMsec))
216 int64_t CDVDInputStreamRTMP::GetLength()
221 bool CDVDInputStreamRTMP::Pause(double dTime)
223 CSingleLock lock(m_RTMPSection);
225 m_bPaused = !m_bPaused;
226 m_libRTMP.Pause(m_rtmp, m_bPaused);