/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxHTSP.cpp

http://github.com/xbmc/xbmc · C++ · 392 lines · 317 code · 56 blank · 19 comment · 77 complexity · 6ee6f2aa719432dee230f5d23b9a0744 MD5 · raw file

  1. /*
  2. * Copyright (C) 2005-2013 Team XBMC
  3. * http://xbmc.org
  4. *
  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)
  8. * any later version.
  9. *
  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.
  14. *
  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/>.
  18. *
  19. */
  20. #include "DVDCodecs/DVDCodecs.h"
  21. #include "DVDInputStreams/DVDInputStream.h"
  22. #include "DVDInputStreams/DVDInputStreamHTSP.h"
  23. #include "DVDDemuxHTSP.h"
  24. #include "DVDDemuxUtils.h"
  25. #include "DVDClock.h"
  26. #include "dialogs/GUIDialogKaiToast.h"
  27. #include "utils/log.h"
  28. #include <arpa/inet.h>
  29. extern "C" {
  30. #include "lib/libhts/net.h"
  31. #include "lib/libhts/htsmsg.h"
  32. #include "lib/libhts/htsmsg_binary.h"
  33. }
  34. using namespace std;
  35. using namespace HTSP;
  36. class CDemuxStreamVideoHTSP
  37. : public CDemuxStreamVideo
  38. {
  39. CDVDDemuxHTSP *m_parent;
  40. string m_codec;
  41. public:
  42. CDemuxStreamVideoHTSP(CDVDDemuxHTSP *parent, const string& codec)
  43. : m_parent(parent)
  44. , m_codec(codec)
  45. {}
  46. void GetStreamInfo(std::string& strInfo)
  47. {
  48. CStdString info;
  49. info.Format("%s, delay: %u, drops: %ub %up %ui"
  50. , m_codec.c_str()
  51. , m_parent->m_QueueStatus.delay
  52. , m_parent->m_QueueStatus.bdrops
  53. , m_parent->m_QueueStatus.pdrops
  54. , m_parent->m_QueueStatus.idrops);
  55. strInfo = info;
  56. }
  57. };
  58. class CDemuxStreamAudioHTSP
  59. : public CDemuxStreamAudio
  60. {
  61. CDVDDemuxHTSP *m_parent;
  62. string m_codec;
  63. public:
  64. CDemuxStreamAudioHTSP(CDVDDemuxHTSP *parent, const string& codec)
  65. : m_parent(parent)
  66. , m_codec(codec)
  67. {}
  68. void GetStreamInfo(string& strInfo)
  69. {
  70. CStdString info;
  71. info.Format("%s", m_codec.c_str());
  72. strInfo = info;
  73. }
  74. };
  75. CDVDDemuxHTSP::CDVDDemuxHTSP()
  76. : CDVDDemux()
  77. , m_Input(NULL)
  78. , m_StatusCount(0)
  79. {
  80. }
  81. CDVDDemuxHTSP::~CDVDDemuxHTSP()
  82. {
  83. Dispose();
  84. }
  85. bool CDVDDemuxHTSP::Open(CDVDInputStream* input)
  86. {
  87. Dispose();
  88. if(!input->IsStreamType(DVDSTREAM_TYPE_HTSP))
  89. return false;
  90. m_Input = (CDVDInputStreamHTSP*)input;
  91. m_StatusCount = 0;
  92. while(m_Streams.empty() && m_StatusCount == 0)
  93. {
  94. DemuxPacket* pkg = Read();
  95. if(!pkg)
  96. return false;
  97. CDVDDemuxUtils::FreeDemuxPacket(pkg);
  98. }
  99. return true;
  100. }
  101. void CDVDDemuxHTSP::Dispose()
  102. {
  103. }
  104. void CDVDDemuxHTSP::Reset()
  105. {
  106. }
  107. void CDVDDemuxHTSP::Flush()
  108. {
  109. }
  110. bool CDVDDemuxHTSP::ReadStream(uint8_t* buf, int len)
  111. {
  112. while(len > 0)
  113. {
  114. int ret = m_Input->Read(buf, len);
  115. if(ret <= 0)
  116. return false;
  117. len -= ret;
  118. buf += ret;
  119. }
  120. return true;
  121. }
  122. htsmsg_t* CDVDDemuxHTSP::ReadStream()
  123. {
  124. if(m_Input->IsStreamType(DVDSTREAM_TYPE_HTSP))
  125. return ((CDVDInputStreamHTSP*)m_Input)->ReadStream();
  126. uint32_t l;
  127. if(!ReadStream((uint8_t*)&l, 4))
  128. return NULL;
  129. l = ntohl(l);
  130. if(l == 0)
  131. return htsmsg_create_map();
  132. uint8_t* buf = (uint8_t*)malloc(l);
  133. if(!buf)
  134. return NULL;
  135. if(!ReadStream(buf, l))
  136. return NULL;
  137. return htsmsg_binary_deserialize(buf, l, buf); /* consumes 'buf' */
  138. }
  139. DemuxPacket* CDVDDemuxHTSP::Read()
  140. {
  141. htsmsg_t * msg;
  142. while((msg = ReadStream()))
  143. {
  144. const char* method = htsmsg_get_str(msg, "method");
  145. if(method == NULL)
  146. break;
  147. if (strcmp("subscriptionStart", method) == 0)
  148. SubscriptionStart(msg);
  149. else if(strcmp("subscriptionStop", method) == 0)
  150. SubscriptionStop (msg);
  151. else if(strcmp("subscriptionStatus", method) == 0)
  152. SubscriptionStatus(msg);
  153. else if(strcmp("queueStatus" , method) == 0)
  154. CHTSPSession::ParseQueueStatus(msg, m_QueueStatus);
  155. else if(strcmp("muxpkt" , method) == 0)
  156. {
  157. uint32_t index, duration;
  158. const void* bin;
  159. size_t binlen;
  160. int64_t ts;
  161. if(htsmsg_get_u32(msg, "stream" , &index) ||
  162. htsmsg_get_bin(msg, "payload", &bin, &binlen))
  163. break;
  164. DemuxPacket* pkt = CDVDDemuxUtils::AllocateDemuxPacket(binlen);
  165. memcpy(pkt->pData, bin, binlen);
  166. pkt->iSize = binlen;
  167. if(!htsmsg_get_u32(msg, "duration", &duration))
  168. pkt->duration = (double)duration * DVD_TIME_BASE / 1000000;
  169. if(!htsmsg_get_s64(msg, "dts", &ts))
  170. pkt->dts = (double)ts * DVD_TIME_BASE / 1000000;
  171. else
  172. pkt->dts = DVD_NOPTS_VALUE;
  173. if(!htsmsg_get_s64(msg, "pts", &ts))
  174. pkt->pts = (double)ts * DVD_TIME_BASE / 1000000;
  175. else
  176. pkt->pts = DVD_NOPTS_VALUE;
  177. pkt->iStreamId = -1;
  178. for(int i = 0; i < (int)m_Streams.size(); i++)
  179. {
  180. if(m_Streams[i]->iPhysicalId == (int)index)
  181. {
  182. pkt->iStreamId = i;
  183. break;
  184. }
  185. }
  186. htsmsg_destroy(msg);
  187. return pkt;
  188. }
  189. break;
  190. }
  191. if(msg)
  192. {
  193. htsmsg_destroy(msg);
  194. return CDVDDemuxUtils::AllocateDemuxPacket(0);
  195. }
  196. return NULL;
  197. }
  198. void CDVDDemuxHTSP::SubscriptionStart (htsmsg_t *m)
  199. {
  200. htsmsg_t *streams;
  201. htsmsg_t *info;
  202. htsmsg_field_t *f;
  203. if((info = htsmsg_get_map(m, "sourceinfo")))
  204. {
  205. HTSMSG_FOREACH(f, info)
  206. {
  207. if(f->hmf_type != HMF_STR)
  208. continue;
  209. CLog::Log(LOGDEBUG, "CDVDDemuxHTSP::SubscriptionStart - %s: %s", f->hmf_name, htsmsg_field_get_string(f));
  210. }
  211. }
  212. if((streams = htsmsg_get_list(m, "streams")) == NULL)
  213. {
  214. CLog::Log(LOGERROR, "CDVDDemuxHTSP::SubscriptionStart - malformed message");
  215. return;
  216. }
  217. for(int i = 0; i < (int)m_Streams.size(); i++)
  218. delete m_Streams[i];
  219. m_Streams.clear();
  220. HTSMSG_FOREACH(f, streams)
  221. {
  222. uint32_t index;
  223. const char* type;
  224. const char* lang;
  225. htsmsg_t* sub;
  226. if(f->hmf_type != HMF_MAP)
  227. continue;
  228. sub = &f->hmf_msg;
  229. if((type = htsmsg_get_str(sub, "type")) == NULL)
  230. continue;
  231. if(htsmsg_get_u32(sub, "index", &index))
  232. continue;
  233. union {
  234. CDemuxStream* g;
  235. CDemuxStreamAudio* a;
  236. CDemuxStreamVideo* v;
  237. CDemuxStreamSubtitle* s;
  238. CDemuxStreamTeletext* t;
  239. } st;
  240. CLog::Log(LOGDEBUG, "CDVDDemuxHTSP::SubscriptionStart - id: %d, type: %s", index, type);
  241. if(!strcmp(type, "AC3")) {
  242. st.a = new CDemuxStreamAudioHTSP(this, type);
  243. st.a->codec = AV_CODEC_ID_AC3;
  244. } else if(!strcmp(type, "EAC3")) {
  245. st.a = new CDemuxStreamAudioHTSP(this, type);
  246. st.a->codec = AV_CODEC_ID_EAC3;
  247. } else if(!strcmp(type, "MPEG2AUDIO")) {
  248. st.a = new CDemuxStreamAudioHTSP(this, type);
  249. st.a->codec = AV_CODEC_ID_MP2;
  250. } else if(!strcmp(type, "AAC")) {
  251. st.a = new CDemuxStreamAudioHTSP(this, type);
  252. st.a->codec = AV_CODEC_ID_AAC;
  253. } else if(!strcmp(type, "MPEG2VIDEO")) {
  254. st.v = new CDemuxStreamVideoHTSP(this, type);
  255. st.v->codec = AV_CODEC_ID_MPEG2VIDEO;
  256. st.v->iWidth = htsmsg_get_u32_or_default(sub, "width" , 0);
  257. st.v->iHeight = htsmsg_get_u32_or_default(sub, "height", 0);
  258. } else if(!strcmp(type, "H264")) {
  259. st.v = new CDemuxStreamVideoHTSP(this, type);
  260. st.v->codec = AV_CODEC_ID_H264;
  261. st.v->iWidth = htsmsg_get_u32_or_default(sub, "width" , 0);
  262. st.v->iHeight = htsmsg_get_u32_or_default(sub, "height", 0);
  263. } else if(!strcmp(type, "DVBSUB")) {
  264. st.s = new CDemuxStreamSubtitle();
  265. st.s->codec = AV_CODEC_ID_DVB_SUBTITLE;
  266. uint32_t composition_id = 0, ancillary_id = 0;
  267. htsmsg_get_u32(sub, "composition_id", &composition_id);
  268. htsmsg_get_u32(sub, "ancillary_id" , &ancillary_id);
  269. if(composition_id || ancillary_id)
  270. {
  271. st.s->ExtraData = new uint8_t[4];
  272. st.s->ExtraSize = 4;
  273. ((uint16_t*)st.s->ExtraData)[0] = composition_id;
  274. ((uint16_t*)st.s->ExtraData)[1] = ancillary_id;
  275. }
  276. } else if(!strcmp(type, "TEXTSUB")) {
  277. st.s = new CDemuxStreamSubtitle();
  278. st.s->codec = AV_CODEC_ID_TEXT;
  279. } else if(!strcmp(type, "TELETEXT")) {
  280. st.t = new CDemuxStreamTeletext();
  281. st.t->codec = AV_CODEC_ID_DVB_TELETEXT;
  282. } else {
  283. continue;
  284. }
  285. if((lang = htsmsg_get_str(sub, "language")))
  286. {
  287. strncpy(st.g->language, lang, sizeof(st.g->language));
  288. st.g->language[sizeof(st.g->language) - 1] = '\0';
  289. }
  290. st.g->iId = m_Streams.size();
  291. st.g->iPhysicalId = index;
  292. m_Streams.push_back(st.g);
  293. }
  294. }
  295. void CDVDDemuxHTSP::SubscriptionStop (htsmsg_t *m)
  296. {
  297. for(int i = 0; i < (int)m_Streams.size(); i++)
  298. delete m_Streams[i];
  299. m_Streams.clear();
  300. }
  301. void CDVDDemuxHTSP::SubscriptionStatus(htsmsg_t *m)
  302. {
  303. const char* status;
  304. status = htsmsg_get_str(m, "status");
  305. if(status == NULL)
  306. m_Status = "";
  307. else
  308. {
  309. m_StatusCount++;
  310. m_Status = status;
  311. CLog::Log(LOGDEBUG, "CDVDDemuxHTSP::SubscriptionStatus - %s", status);
  312. CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, "TVHeadend Status", status, TOAST_DISPLAY_TIME, false);
  313. }
  314. }
  315. CDemuxStream* CDVDDemuxHTSP::GetStream(int iStreamId)
  316. {
  317. if(iStreamId >= 0 && iStreamId < (int)m_Streams.size())
  318. return m_Streams[iStreamId];
  319. return NULL;
  320. }
  321. int CDVDDemuxHTSP::GetNrOfStreams()
  322. {
  323. return m_Streams.size();
  324. }
  325. std::string CDVDDemuxHTSP::GetFileName()
  326. {
  327. if(m_Input)
  328. return m_Input->GetFileName();
  329. else
  330. return "";
  331. }
  332. void CDVDDemuxHTSP::Abort()
  333. {
  334. if(m_Input)
  335. return m_Input->Abort();
  336. }