PageRenderTime 75ms CodeModel.GetById 13ms app.highlight 58ms RepoModel.GetById 1ms app.codeStats 0ms

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

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