Skip to content
This repository
Browse code

[bluray] Initial support for menu's, no BD-J supported

Code will fall back to longest item if there is not first play
hdmv item. However it will still try menu's if there is only
some unnsupported BD-J titles. This could possible fail to
play if it switches into BD-J mode later in menu's.

Starting index.bdmv will still only play longest title,
to attempt playback with menu's, start the MovieObject.bdmv
  • Loading branch information...
commit 226c8504e78ff56e98318f9beb475d66a94bea95 1 parent 9b1dd39
Joakim Plate authored October 08, 2011
32  lib/DllLibbluray.h
@@ -30,6 +30,8 @@ extern "C"
30 30
 #include <libbluray/bluray.h>
31 31
 #include <libbluray/filesystem.h>
32 32
 #include <libbluray/log_control.h>
  33
+#include <libbluray/keys.h>
  34
+#include <libbluray/overlay.h>
33 35
 }
34 36
 
35 37
 class DllLibblurayInterface
@@ -65,6 +67,16 @@ class DllLibblurayInterface
65 67
   virtual void     bd_set_debug_mask(uint32_t mask)=0;
66 68
   virtual uint32_t bd_get_debug_mask(void)=0;
67 69
   virtual const BLURAY_DISC_INFO *bd_get_disc_info(BLURAY *bd)=0;
  70
+
  71
+  virtual int      bd_get_event                 (BLURAY *bd, BD_EVENT *event)=0;
  72
+  virtual int      bd_play                      (BLURAY *bd)=0;
  73
+  virtual int      bd_read_ext                  (BLURAY *bd, unsigned char *buf, int len, BD_EVENT *event)=0;
  74
+  virtual int      bd_read_skip_still           (BLURAY *bd)=0;
  75
+  virtual int      bd_user_input                (BLURAY *bd, int64_t pts, uint32_t key)=0;
  76
+  virtual int      bd_set_player_setting        (BLURAY *bd, uint32_t idx, uint32_t value)=0;
  77
+  virtual int      bd_set_player_setting_str    (BLURAY *bd, uint32_t idx, const char *s)=0;
  78
+  virtual void     bd_register_overlay_proc     (BLURAY *bd, void *handle, bd_overlay_proc_f func)=0;
  79
+  virtual int      bd_menu_call                 (BLURAY *bd, int64_t pts)=0;
68 80
 };
69 81
 
70 82
 class DllLibbluray : public DllDynamic, DllLibblurayInterface
@@ -100,6 +112,16 @@ class DllLibbluray : public DllDynamic, DllLibblurayInterface
100 112
   DEFINE_METHOD0(uint32_t,            bd_get_debug_mask)
101 113
   DEFINE_METHOD1(const BLURAY_DISC_INFO*, bd_get_disc_info,      (BLURAY *p1))
102 114
 
  115
+  DEFINE_METHOD2(int,                 bd_get_event,              (BLURAY *p1, BD_EVENT *p2))
  116
+  DEFINE_METHOD1(int,                 bd_play,                   (BLURAY *p1))
  117
+  DEFINE_METHOD4(int,                 bd_read_ext,               (BLURAY *p1, unsigned char *p2, int p3, BD_EVENT *p4))
  118
+  DEFINE_METHOD1(int,                 bd_read_skip_still,        (BLURAY *p1))
  119
+  DEFINE_METHOD3(int,                 bd_user_input,             (BLURAY *p1, int64_t p2, uint32_t p3))
  120
+  DEFINE_METHOD3(int,                 bd_set_player_setting,     (BLURAY *p1, uint32_t p2, uint32_t p3))
  121
+  DEFINE_METHOD3(int,                 bd_set_player_setting_str, (BLURAY *p1, uint32_t p2, const char *p3))
  122
+  DEFINE_METHOD3(void,                bd_register_overlay_proc,  (BLURAY *p1, void *p2, bd_overlay_proc_f p3))
  123
+  DEFINE_METHOD2(int,                 bd_menu_call,              (BLURAY *p1, int64_t p2))
  124
+
103 125
   BEGIN_METHOD_RESOLVE()
104 126
     RESOLVE_METHOD(bd_get_titles)
105 127
     RESOLVE_METHOD(bd_get_title_info)
@@ -129,6 +151,16 @@ class DllLibbluray : public DllDynamic, DllLibblurayInterface
129 151
     RESOLVE_METHOD(bd_set_debug_mask)
130 152
     RESOLVE_METHOD(bd_get_debug_mask)
131 153
     RESOLVE_METHOD(bd_get_disc_info)
  154
+
  155
+    RESOLVE_METHOD(bd_get_event)
  156
+    RESOLVE_METHOD(bd_play)
  157
+    RESOLVE_METHOD(bd_read_ext)
  158
+    RESOLVE_METHOD(bd_read_skip_still)
  159
+    RESOLVE_METHOD(bd_user_input)
  160
+    RESOLVE_METHOD(bd_set_player_setting)
  161
+    RESOLVE_METHOD(bd_set_player_setting_str)
  162
+    RESOLVE_METHOD(bd_register_overlay_proc)
  163
+    RESOLVE_METHOD(bd_menu_call)
132 164
   END_METHOD_RESOLVE()
133 165
 
134 166
 public:
2  xbmc/cores/dvdplayer/DVDInputStreams/DVDFactoryInputStream.cpp
@@ -54,7 +54,7 @@ CDVDInputStream* CDVDFactoryInputStream::CreateInputStream(IDVDPlayer* pPlayer,
54 54
   }
55 55
 #ifdef HAVE_LIBBLURAY
56 56
   else if (item.IsType(".bdmv") || item.IsType(".mpls") || content == "bluray/iso")
57  
-    return new CDVDInputStreamBluray();
  57
+    return new CDVDInputStreamBluray(pPlayer);
58 58
 #endif
59 59
   else if(file.substr(0, 6) == "rtp://"
60 60
        || file.substr(0, 7) == "rtsp://"
475  xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp
@@ -22,6 +22,11 @@
22 22
 #ifdef HAVE_LIBBLURAY
23 23
 
24 24
 #include "DVDInputStreamBluray.h"
  25
+#include "IDVDPlayer.h"
  26
+#include "DVDCodecs/Overlay/DVDOverlay.h"
  27
+#include "DVDCodecs/Overlay/DVDOverlayImage.h"
  28
+#include "settings/GUISettings.h"
  29
+#include "LangInfo.h"
25 30
 #include "utils/log.h"
26 31
 #include "utils/URIUtils.h"
27 32
 #include "filesystem/File.h"
@@ -195,10 +200,17 @@ void DllLibbluray::bluray_logger(const char* msg)
195 200
   CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Logger - %s", msg);
196 201
 }
197 202
 
198  
-CDVDInputStreamBluray::CDVDInputStreamBluray() :
  203
+
  204
+static void bluray_overlay_cb(void *this_gen, const BD_OVERLAY * ov)
  205
+{
  206
+  static_cast<CDVDInputStreamBluray*>(this_gen)->OverlayCallback(ov);
  207
+}
  208
+
  209
+CDVDInputStreamBluray::CDVDInputStreamBluray(IDVDPlayer* player) :
199 210
   CDVDInputStream(DVDSTREAM_TYPE_BLURAY)
200 211
 {
201 212
   m_title = NULL;
  213
+  m_clip  = 0;
202 214
   m_bd    = NULL;
203 215
   m_dll = new DllLibbluray;
204 216
   if (!m_dll->Load())
@@ -206,6 +218,8 @@ CDVDInputStreamBluray::CDVDInputStreamBluray() :
206 218
     delete m_dll;
207 219
     m_dll = NULL;
208 220
   }
  221
+  m_content = "video/x-mpegts";
  222
+  m_player  = player;
209 223
 }
210 224
 
211 225
 CDVDInputStreamBluray::~CDVDInputStreamBluray()
@@ -250,33 +264,15 @@ BLURAY_TITLE_INFO* CDVDInputStreamBluray::GetTitleFile(const std::string& filena
250 264
     return NULL;
251 265
   }
252 266
 
253  
-  int titles = m_dll->bd_get_titles(m_bd, TITLES_ALL, 0);
254  
-  if(titles < 0)
255  
-  {
256  
-    CLog::Log(LOGERROR, "get_playlist_title - unable to get list of titles");
257  
-    return NULL;
258  
-  }
259  
-
260  
-  BLURAY_TITLE_INFO *t;
261  
-  for(int i=0; i < titles; i++)
262  
-  {
263  
-    t = m_dll->bd_get_title_info(m_bd, i, 0);
264  
-    if(!t)
265  
-    {
266  
-      CLog::Log(LOGDEBUG, "get_playlist_title - unable to get title %d", i);
267  
-      continue;
268  
-    }
269  
-    if(t->playlist == playlist)
270  
-      return t;
271  
-    m_dll->bd_free_title_info(t);
272  
-  }
273  
-
274  
-  return NULL;
  267
+  return m_dll->bd_get_playlist_info(m_bd, playlist, 0);
275 268
 }
276 269
 
277 270
 
278 271
 bool CDVDInputStreamBluray::Open(const char* strFile, const std::string& content)
279 272
 {
  273
+  if(m_player == NULL)
  274
+    return false;
  275
+
280 276
   CStdString strPath;
281 277
   URIUtils::GetDirectory(strFile,strPath);
282 278
   URIUtils::RemoveSlashAtEnd(strPath);
@@ -299,7 +295,7 @@ bool CDVDInputStreamBluray::Open(const char* strFile, const std::string& content
299 295
   m_dll->bd_register_dir(DllLibbluray::dir_open);
300 296
   m_dll->bd_register_file(DllLibbluray::file_open);
301 297
   m_dll->bd_set_debug_handler(DllLibbluray::bluray_logger);
302  
-  m_dll->bd_set_debug_mask(DBG_CRIT);
  298
+  m_dll->bd_set_debug_mask(DBG_CRIT | DBG_BLURAY | DBG_NAV);
303 299
 
304 300
   CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - opening %s", strPath.c_str());
305 301
   m_bd = m_dll->bd_open(strPath.c_str(), NULL);
@@ -353,28 +349,76 @@ bool CDVDInputStreamBluray::Open(const char* strFile, const std::string& content
353 349
   CStdString filename = URIUtils::GetFileName(strFile);
354 350
   if(filename.Equals("index.bdmv"))
355 351
   {
  352
+    m_navmode = false;
356 353
     m_title = GetTitleLongest();
357 354
   }
358 355
   else if(URIUtils::GetExtension(filename).Equals(".mpls"))
359 356
   {
  357
+    m_navmode = false;
360 358
     m_title = GetTitleFile(filename);
361 359
   }
  360
+  else if(filename.Equals("MovieObject.bdmv"))
  361
+  {
  362
+    m_navmode = true;
  363
+    if (m_navmode && !disc_info->first_play_supported) {
  364
+      CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - Can't play disc in HDMV navigation mode - First Play title not supported");
  365
+      m_navmode = false;
  366
+    }
  367
+
  368
+    if (m_navmode && disc_info->num_unsupported_titles > 0) {
  369
+      CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - Unsupported titles found - Some titles can't be played in navigation mode");
  370
+    }
  371
+
  372
+    if(!m_navmode)
  373
+      m_title = GetTitleLongest();
  374
+  }
362 375
   else
363 376
   {
364 377
     CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - unsupported bluray file selected %s", strPath.c_str());
365 378
     return false;
366 379
   }
367 380
 
368  
-  if(!m_title)
  381
+  if(m_navmode)
369 382
   {
370  
-    CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - failed to get title info");
371  
-    return false;
372  
-  }
  383
+    int region = g_guiSettings.GetInt("dvds.playerregion");
  384
+    if(region == 0)
  385
+    {
  386
+      CLog::Log(LOGWARNING, "CDVDInputStreamBluray::Open - region dvd must be set in setting, assuming region 1");
  387
+      region = 1;
  388
+    }
  389
+    m_dll->bd_set_player_setting    (m_bd, BLURAY_PLAYER_SETTING_REGION_CODE,  region);
  390
+    m_dll->bd_set_player_setting    (m_bd, BLURAY_PLAYER_SETTING_PARENTAL,     0);
  391
+    m_dll->bd_set_player_setting    (m_bd, BLURAY_PLAYER_SETTING_PLAYER_PROFILE, 0);
  392
+    m_dll->bd_set_player_setting_str(m_bd, BLURAY_PLAYER_SETTING_AUDIO_LANG,   g_langInfo.GetDVDAudioLanguage().c_str());
  393
+    m_dll->bd_set_player_setting_str(m_bd, BLURAY_PLAYER_SETTING_PG_LANG,      g_langInfo.GetDVDSubtitleLanguage().c_str());
  394
+    m_dll->bd_set_player_setting_str(m_bd, BLURAY_PLAYER_SETTING_MENU_LANG,    g_langInfo.GetDVDMenuLanguage().c_str());
  395
+    m_dll->bd_set_player_setting_str(m_bd, BLURAY_PLAYER_SETTING_COUNTRY_CODE, "us");
  396
+    m_dll->bd_register_overlay_proc (m_bd, this, bluray_overlay_cb);
  397
+
  398
+    m_dll->bd_get_event(m_bd, NULL);
  399
+
373 400
 
374  
-  if(m_dll->bd_select_title(m_bd, m_title->idx) == 0 )
  401
+    if(m_dll->bd_play(m_bd) <= 0)
  402
+    {
  403
+      CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - failed play disk %s", strPath.c_str());
  404
+      return false;
  405
+    }
  406
+    m_hold = HOLD_DATA;
  407
+    m_title_playing = false;
  408
+  }
  409
+  else
375 410
   {
376  
-    CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - failed to select title %d", m_title->idx);
377  
-    return false;
  411
+    if(!m_title)
  412
+    {
  413
+      CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - failed to get title info");
  414
+      return false;
  415
+    }
  416
+
  417
+    if(m_dll->bd_select_playlist(m_bd, m_title->playlist) == 0 )
  418
+    {
  419
+      CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - failed to select title %d", m_title->idx);
  420
+      return false;
  421
+    }
378 422
   }
379 423
 
380 424
   return true;
@@ -385,17 +429,324 @@ void CDVDInputStreamBluray::Close()
385 429
 {
386 430
   if (!m_dll)
387 431
     return;
  432
+  if(m_title)
  433
+    m_dll->bd_free_title_info(m_title);
388 434
   if(m_bd)
  435
+  {
  436
+    m_dll->bd_register_overlay_proc(m_bd, NULL, NULL);
389 437
     m_dll->bd_close(m_bd);
  438
+  }
390 439
   m_bd = NULL;
391  
-  if(m_title)
392  
-    m_dll->bd_free_title_info(m_title);
393 440
   m_title = NULL;
394 441
 }
395 442
 
396 443
 int CDVDInputStreamBluray::Read(BYTE* buf, int buf_size)
397 444
 {
398  
-  return m_dll->bd_read(m_bd, buf, buf_size);
  445
+  if(m_navmode)
  446
+  {
  447
+    int result = 0;
  448
+    do {
  449
+
  450
+      if(m_hold == HOLD_HELD)
  451
+        return 0;
  452
+
  453
+      if(m_hold == HOLD_SKIP)
  454
+      {
  455
+        /* m_event already holds data */
  456
+        m_hold = HOLD_DATA;
  457
+        result = 0;
  458
+      }
  459
+      else
  460
+      {
  461
+        result = m_dll->bd_read_ext (m_bd, buf, buf_size, &m_event);
  462
+
  463
+        if(m_hold == HOLD_NONE)
  464
+        {
  465
+          /* Check for holding events */
  466
+          switch(m_event.event) {
  467
+            case BD_EVENT_SEEK:
  468
+            case BD_EVENT_TITLE:
  469
+              if(m_title_playing)
  470
+                m_player->OnDVDNavResult(NULL, 1);
  471
+              m_hold = HOLD_HELD;
  472
+              return result;
  473
+
  474
+            case BD_EVENT_PLAYLIST:
  475
+            case BD_EVENT_PLAYITEM:
  476
+              m_hold = HOLD_HELD;
  477
+              return result;
  478
+            default:
  479
+              break;
  480
+          }
  481
+        }
  482
+        if(result > 0)
  483
+          m_hold = HOLD_NONE;
  484
+      }
  485
+      int pid = -1;
  486
+      switch (m_event.event) {
  487
+
  488
+        case BD_EVENT_ERROR:
  489
+          CLog::Log(LOGERROR, "CDVDInputStreamBluray - BD_EVENT_ERROR");
  490
+          return -1;
  491
+
  492
+        case BD_EVENT_ENCRYPTED:
  493
+          CLog::Log(LOGERROR, "CDVDInputStreamBluray - BD_EVENT_ENCRYPTED");
  494
+          return -1;
  495
+
  496
+        /* playback control */
  497
+
  498
+        case BD_EVENT_SEEK:
  499
+          CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_SEEK");
  500
+          break;
  501
+
  502
+        case BD_EVENT_STILL_TIME:
  503
+          CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_STILL_TIME %d", m_event.param);
  504
+          return 0;
  505
+
  506
+        case BD_EVENT_STILL:
  507
+          CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_STILL %d", m_event.param);
  508
+          break;
  509
+
  510
+        /* playback position */
  511
+
  512
+        case BD_EVENT_ANGLE:
  513
+          CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_ANGLE %d", m_event.param);
  514
+          break;
  515
+
  516
+        case BD_EVENT_END_OF_TITLE:
  517
+          CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_END_OF_TITLE %d", m_event.param);
  518
+          m_title_playing = false;
  519
+          break;
  520
+
  521
+        case BD_EVENT_TITLE:
  522
+          CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_TITLE %d", m_event.param);
  523
+          if(m_title)
  524
+            m_dll->bd_free_title_info(m_title);
  525
+          m_title = m_dll->bd_get_title_info(m_bd, m_event.param, 0);
  526
+          m_title_playing = true;
  527
+          break;
  528
+
  529
+        case BD_EVENT_PLAYLIST:
  530
+          CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_PLAYLIST %d", m_event.param);
  531
+          if(m_title)
  532
+            m_dll->bd_free_title_info(m_title);
  533
+          m_title = m_dll->bd_get_playlist_info(m_bd, m_event.param, 0);
  534
+          break;
  535
+
  536
+        case BD_EVENT_PLAYITEM:
  537
+          CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_PLAYITEM %d", m_event.param);
  538
+          m_clip = m_event.param;
  539
+          break;
  540
+
  541
+        case BD_EVENT_CHAPTER:
  542
+          CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_CHAPTER %d", m_event.param);
  543
+          break;
  544
+
  545
+        /* stream selection */
  546
+
  547
+        case BD_EVENT_AUDIO_STREAM:
  548
+          pid = -1;
  549
+          if(m_title
  550
+          && m_title->clip_count > m_clip
  551
+          && m_title->clips[m_clip].audio_stream_count > (uint8_t)(m_event.param - 1))
  552
+            pid = m_title->clips[m_clip].audio_streams[m_event.param-1].pid;
  553
+          CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_AUDIO_STREAM %d %d", m_event.param, pid);
  554
+          m_player->OnDVDNavResult((void*)&pid, 2);
  555
+          break;
  556
+
  557
+        case BD_EVENT_PG_TEXTST:
  558
+          CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_PG_TEXTST %d", m_event.param);
  559
+          pid = m_event.param;
  560
+          m_player->OnDVDNavResult((void*)&pid, 4);
  561
+          break;
  562
+
  563
+        case BD_EVENT_PG_TEXTST_STREAM:
  564
+          pid = -1;
  565
+          if(m_title
  566
+          && m_title->clip_count > m_clip
  567
+          && m_title->clips[m_clip].pg_stream_count > (uint8_t)(m_event.param - 1))
  568
+            pid = m_title->clips[m_clip].pg_streams[m_event.param-1].pid;
  569
+          CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_PG_TEXTST_STREAM %d, %d", m_event.param, pid);
  570
+          m_player->OnDVDNavResult((void*)&pid, 3);
  571
+          break;
  572
+
  573
+        case BD_EVENT_IG_STREAM:
  574
+        case BD_EVENT_SECONDARY_AUDIO:
  575
+        case BD_EVENT_SECONDARY_AUDIO_STREAM:
  576
+        case BD_EVENT_SECONDARY_VIDEO:
  577
+        case BD_EVENT_SECONDARY_VIDEO_SIZE:
  578
+        case BD_EVENT_SECONDARY_VIDEO_STREAM:
  579
+
  580
+        case BD_EVENT_NONE:
  581
+          break;
  582
+
  583
+        default:
  584
+          CLog::Log(LOGWARNING, "CDVDInputStreamBluray - unhandled libbluray event %d [param %d]", m_event.event, m_event.param);
  585
+          break;
  586
+      }
  587
+
  588
+    } while(result == 0);
  589
+
  590
+    return result;
  591
+  }
  592
+  else
  593
+    return m_dll->bd_read(m_bd, buf, buf_size);
  594
+}
  595
+
  596
+static uint8_t  clamp(double v)
  597
+{
  598
+  return (v) > 255.0 ? 255 : ((v) < 0.0 ? 0 : (uint8_t)(v+0.5f));
  599
+}
  600
+
  601
+static uint32_t build_rgba(const BD_PG_PALETTE_ENTRY &e)
  602
+{
  603
+  double r = 1.164 * (e.Y - 16)                        + 1.596 * (e.Cr - 128);
  604
+  double g = 1.164 * (e.Y - 16) - 0.391 * (e.Cb - 128) - 0.813 * (e.Cr - 128);
  605
+  double b = 1.164 * (e.Y - 16) + 2.018 * (e.Cb - 128);
  606
+  return (uint32_t)e.T      << PIXEL_ASHIFT
  607
+       | (uint32_t)clamp(r) << PIXEL_RSHIFT
  608
+       | (uint32_t)clamp(g) << PIXEL_GSHIFT
  609
+       | (uint32_t)clamp(b) << PIXEL_BSHIFT;
  610
+}
  611
+
  612
+void CDVDInputStreamBluray::OverlayCallback(const BD_OVERLAY * const ov)
  613
+{
  614
+
  615
+  CDVDOverlayGroup* group   = new CDVDOverlayGroup();
  616
+  group->bForced = true;
  617
+
  618
+  if(ov == NULL)
  619
+  {
  620
+    for(unsigned i = 0; i < 2; ++i)
  621
+    {
  622
+      for(std::vector<CDVDOverlayImage*>::iterator it = m_overlays[i].begin(); it != m_overlays[i].end(); ++it)
  623
+        (*it)->Release();
  624
+      m_overlays[i].clear();
  625
+    }
  626
+
  627
+    m_player->OnDVDNavResult(group, 0);
  628
+    return;
  629
+  }
  630
+
  631
+  group->iPTSStartTime = ov->pts;
  632
+  group->iPTSStopTime  = 0;
  633
+
  634
+  if (ov->plane > 1)
  635
+  {
  636
+    CLog::Log(LOGWARNING, "CDVDInputStreamBluray - Ignoring overlay with multiple planes");
  637
+    group->Release();
  638
+    return;
  639
+  }
  640
+
  641
+  std::vector<CDVDOverlayImage*>& plane(m_overlays[ov->plane]);
  642
+
  643
+  /* fixup existing overlays */
  644
+  for(std::vector<CDVDOverlayImage*>::iterator it = plane.begin(); it != plane.end();)
  645
+  {
  646
+    /* if it's fully outside we are done */
  647
+    if(ov->x + ov->w <= (*it)->x
  648
+    || ov->x         >= (*it)->x + (*it)->width
  649
+    || ov->y + ov->h <= (*it)->y
  650
+    || ov->y         >= (*it)->y + (*it)->height)
  651
+    {
  652
+      ++it;
  653
+      continue;
  654
+    }
  655
+
  656
+    int y1 = std::max<int>((*it)->y                , ov->y);
  657
+    int y2 = std::min<int>((*it)->y + (*it)->height, ov->y + ov->h);
  658
+    int x1 = std::max<int>((*it)->x                , ov->x);
  659
+    int x2 = std::min<int>((*it)->x + (*it)->width , ov->x + ov->w);
  660
+
  661
+    /* if all should be cleared, delete */
  662
+    if(x1 == (*it)->x
  663
+    && x2 == (*it)->x + (*it)->width
  664
+    && y1 == (*it)->y
  665
+    && y2 == (*it)->y + (*it)->height)
  666
+    {
  667
+      CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - Delete(%d) %d-%dx%d-%d", ov->plane, x1, x2, y1, y2);
  668
+      it = plane.erase(it);
  669
+      continue;
  670
+    }
  671
+#if(1)
  672
+    CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - Clearing(%d) %d-%dx%d-%d", ov->plane, x1, x2, y1, y2);
  673
+
  674
+    /* replace overlay with a new copy*/
  675
+    CDVDOverlayImage* overlay = new CDVDOverlayImage(*(*it));
  676
+    (*it)->Release();
  677
+    (*it) = overlay;
  678
+
  679
+    /* any old hw overlay must be released */
  680
+    SAFE_RELEASE(overlay->m_overlay);
  681
+
  682
+    /* clear out overlap */
  683
+    y1 -= overlay->y;
  684
+    y2 -= overlay->y;
  685
+    x1 -= overlay->x;
  686
+    x2 -= overlay->x;
  687
+
  688
+    /* find fully transparent */
  689
+    int transp = 0;
  690
+    for(; transp < overlay->palette_colors; ++transp)
  691
+    {
  692
+      if(((overlay->palette[transp] >> PIXEL_ASHIFT) & 0xff) == 0)
  693
+        break;
  694
+    }
  695
+
  696
+    if(transp == overlay->palette_colors)
  697
+    {
  698
+      CLog::Log(LOGERROR, "CDVDInputStreamBluray - failed to find transparent color");
  699
+      continue;
  700
+    }
  701
+
  702
+    for(int y = y1; y < y2; ++y)
  703
+    {
  704
+      BYTE* line = overlay->data + y * overlay->linesize;
  705
+      for(int x = x1; x < x2; ++x)
  706
+        line[x] = transp;
  707
+    }
  708
+    ++it;
  709
+#endif
  710
+  }
  711
+
  712
+
  713
+  /* uncompress and draw bitmap */
  714
+  if (ov->img)
  715
+  {
  716
+    CDVDOverlayImage* overlay = new CDVDOverlayImage();
  717
+
  718
+    if (ov->palette)
  719
+    {
  720
+      overlay->palette_colors = 256;
  721
+      overlay->palette        = (uint32_t*)calloc(overlay->palette_colors, 4);
  722
+
  723
+      for(unsigned i = 0; i < 256; i++)
  724
+        overlay->palette[i] = build_rgba(ov->palette[i]);
  725
+    }
  726
+
  727
+    const BD_PG_RLE_ELEM *rlep = ov->img;
  728
+    uint8_t *img = (uint8_t*) malloc(ov->w * ov->h);
  729
+    unsigned pixels = ov->w * ov->h;
  730
+
  731
+    for (unsigned i = 0; i < pixels; i += rlep->len, rlep++) {
  732
+      memset(img + i, rlep->color, rlep->len);
  733
+    }
  734
+
  735
+    overlay->data     = img;
  736
+    overlay->linesize = ov->w;
  737
+    overlay->x        = ov->x;
  738
+    overlay->y        = ov->y;
  739
+    overlay->height   = ov->h;
  740
+    overlay->width    = ov->w;
  741
+    plane.push_back(overlay);
  742
+  }
  743
+
  744
+  for(unsigned i = 0; i < 2; ++i)
  745
+  {
  746
+    for(std::vector<CDVDOverlayImage*>::iterator it = m_overlays[i].begin(); it != m_overlays[i].end(); ++it)
  747
+      group->m_overlays.push_back((*it)->Acquire());
  748
+  }
  749
+  m_player->OnDVDNavResult(group, 0);
399 750
 }
400 751
 
401 752
 int CDVDInputStreamBluray::GetTotalTime()
@@ -499,10 +850,10 @@ static bool find_stream(int pid, BLURAY_STREAM_INFO *info, int count, char* lang
499 850
 
500 851
 void CDVDInputStreamBluray::GetStreamInfo(int pid, char* language)
501 852
 {
502  
-  if(m_title->clip_count == 0)
  853
+  if(!m_title || m_clip >= m_title->clip_count)
503 854
     return;
504 855
 
505  
-  BLURAY_CLIP_INFO *clip = m_title->clips;
  856
+  BLURAY_CLIP_INFO *clip = m_title->clips+m_clip;
506 857
 
507 858
   if(find_stream(pid, clip->audio_streams, clip->audio_stream_count, language))
508 859
     return;
@@ -514,4 +865,56 @@ void CDVDInputStreamBluray::GetStreamInfo(int pid, char* language)
514 865
     return;
515 866
 }
516 867
 
  868
+CDVDInputStream::ENextStream CDVDInputStreamBluray::NextStream()
  869
+{
  870
+  if(!m_navmode)
  871
+    return NEXTSTREAM_NONE;
  872
+
  873
+  if(m_hold == HOLD_HELD)
  874
+  {
  875
+    m_hold = HOLD_SKIP;
  876
+    return NEXTSTREAM_OPEN;
  877
+  }
  878
+  if(m_hold == HOLD_NONE)
  879
+  {
  880
+    m_hold = HOLD_DATA;
  881
+    m_dll->bd_read_skip_still(m_bd);
  882
+  }
  883
+  return NEXTSTREAM_RETRY;
  884
+}
  885
+
  886
+void CDVDInputStreamBluray::UserInput(bd_vk_key_e vk)
  887
+{
  888
+  if(m_bd == NULL || !m_navmode)
  889
+    return;
  890
+  m_dll->bd_user_input(m_bd, -1, vk);
  891
+}
  892
+
  893
+void CDVDInputStreamBluray::OnMenu()
  894
+{
  895
+  if(m_bd == NULL || !m_navmode)
  896
+    return;
  897
+
  898
+  if(m_dll->bd_user_input(m_bd, -1, BD_VK_POPUP) >= 0)
  899
+    return;
  900
+  CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::OnMenu - popup failed, trying root");
  901
+
  902
+  if(m_dll->bd_user_input(m_bd, -1, BD_VK_ROOT_MENU) >= 0)
  903
+    return;
  904
+
  905
+  CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::OnMenu - root failed, trying explicit");
  906
+  if(m_dll->bd_menu_call(m_bd, -1) >= 0)
  907
+    return;
  908
+  CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::OnMenu - root failed");
  909
+}
  910
+
  911
+bool CDVDInputStreamBluray::IsInMenu()
  912
+{
  913
+  if(m_bd == NULL || !m_navmode)
  914
+    return false;
  915
+  if(m_overlays[BD_OVERLAY_IG].size() > 0)
  916
+    return true;
  917
+  return false;
  918
+}
  919
+
517 920
 #endif
59  xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.h
@@ -23,18 +23,27 @@
23 23
 
24 24
 #include "DVDInputStream.h"
25 25
 
  26
+
  27
+extern "C"
  28
+{
  29
+#include <libbluray/bluray.h>
  30
+#include <libbluray/keys.h>
  31
+#include <libbluray/overlay.h>
  32
+}
  33
+
  34
+class CDVDOverlayImage;
26 35
 class DllLibbluray;
27  
-typedef struct bluray BLURAY;
28  
-typedef struct bd_title_info BLURAY_TITLE_INFO;
  36
+class IDVDPlayer;
29 37
 
30 38
 class CDVDInputStreamBluray 
31 39
   : public CDVDInputStream
32 40
   , public CDVDInputStream::IDisplayTime
33 41
   , public CDVDInputStream::IChapter
34 42
   , public CDVDInputStream::ISeekTime
  43
+  , public CDVDInputStream::IMenus
35 44
 {
36 45
 public:
37  
-  CDVDInputStreamBluray();
  46
+  CDVDInputStreamBluray(IDVDPlayer* player);
38 47
   virtual ~CDVDInputStreamBluray();
39 48
   virtual bool Open(const char* strFile, const std::string &content);
40 49
   virtual void Close();
@@ -44,6 +53,36 @@ class CDVDInputStreamBluray
44 53
   virtual bool IsEOF();
45 54
   virtual __int64 GetLength();
46 55
   virtual int GetBlockSize() { return 6144; }
  56
+  virtual ENextStream NextStream();
  57
+
  58
+
  59
+  /* IMenus */
  60
+  virtual void ActivateButton()          { UserInput(BD_VK_ENTER); }
  61
+  virtual void SelectButton(int iButton)
  62
+  {
  63
+    if(iButton < 10)
  64
+      UserInput((bd_vk_key_e)(BD_VK_0 + iButton));
  65
+  }
  66
+  virtual int  GetCurrentButton()        { return 0; }
  67
+  virtual int  GetTotalButtons()         { return 0; }
  68
+  virtual void OnUp()                    { UserInput(BD_VK_UP); }
  69
+  virtual void OnDown()                  { UserInput(BD_VK_DOWN); }
  70
+  virtual void OnLeft()                  { UserInput(BD_VK_LEFT); }
  71
+  virtual void OnRight()                 { UserInput(BD_VK_RIGHT); }
  72
+  virtual void OnMenu();
  73
+  virtual void OnBack()
  74
+  {
  75
+    if(IsInMenu())
  76
+      OnMenu();
  77
+  }
  78
+  virtual void OnNext()                  {}
  79
+  virtual void OnPrevious()              {}
  80
+  virtual bool IsInMenu();
  81
+  virtual bool OnMouseMove(const CPoint &point)  { return false; }
  82
+  virtual bool OnMouseClick(const CPoint &point) { return false; }
  83
+  virtual double GetTimeStampCorrection()        { return 0.0; }
  84
+
  85
+  void UserInput(bd_vk_key_e vk);
47 86
 
48 87
   int GetChapter();
49 88
   int GetChapterCount();
@@ -56,11 +95,25 @@ class CDVDInputStreamBluray
56 95
 
57 96
   void GetStreamInfo(int pid, char* language);
58 97
 
  98
+  void OverlayCallback(const BD_OVERLAY * const);
  99
+
59 100
   BLURAY_TITLE_INFO* GetTitleLongest();
60 101
   BLURAY_TITLE_INFO* GetTitleFile(const std::string& name);
61 102
 
62 103
 protected:
  104
+  IDVDPlayer*   m_player;
63 105
   DllLibbluray *m_dll;
64 106
   BLURAY* m_bd;
65 107
   BLURAY_TITLE_INFO* m_title;
  108
+  bool               m_title_playing;
  109
+  uint32_t           m_clip;
  110
+  bool m_navmode;
  111
+  std::vector<CDVDOverlayImage*> m_overlays[2];
  112
+  enum EHoldState {
  113
+    HOLD_NONE = 0,
  114
+    HOLD_HELD,
  115
+    HOLD_SKIP,
  116
+    HOLD_DATA,
  117
+  } m_hold;
  118
+  BD_EVENT m_event;
66 119
 };
19  xbmc/cores/dvdplayer/DVDPlayer.cpp
@@ -855,7 +855,8 @@ bool CDVDPlayer::IsBetterStream(CCurrentStream& current, CDemuxStream* stream)
855 855
   if(m_PlayerOptions.video_only && current.type != STREAM_VIDEO)
856 856
     return false;
857 857
 
858  
-  if (m_pInputStream && m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD))
  858
+  if (m_pInputStream && ( m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD)
  859
+                       || m_pInputStream->IsStreamType(DVDSTREAM_TYPE_BLURAY) ) )
859 860
   {
860 861
     int source_type;
861 862
 
@@ -3064,6 +3065,22 @@ void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate)
3064 3065
 // since we call ffmpeg functions to decode, this is being called in the same thread as ::Process() is
3065 3066
 int CDVDPlayer::OnDVDNavResult(void* pData, int iMessage)
3066 3067
 {
  3068
+  if (m_pInputStream->IsStreamType(DVDSTREAM_TYPE_BLURAY))
  3069
+  {
  3070
+    if(iMessage == 0)
  3071
+      m_overlayContainer.Add((CDVDOverlay*)pData);
  3072
+    else if(iMessage == 1)
  3073
+      m_messenger.Put(new CDVDMsg(CDVDMsg::GENERAL_FLUSH));
  3074
+    else if(iMessage == 2)
  3075
+      m_dvd.iSelectedAudioStream = *(int*)pData;
  3076
+    else if(iMessage == 3)
  3077
+      m_dvd.iSelectedSPUStream   = *(int*)pData;
  3078
+    else if(iMessage == 4)
  3079
+      m_dvdPlayerVideo.EnableSubtitle(*(int*)pData ? true: false);
  3080
+
  3081
+    return 0;
  3082
+  }
  3083
+
3067 3084
   if (m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD))
3068 3085
   {
3069 3086
     CDVDInputStreamNavigator* pStream = (CDVDInputStreamNavigator*)m_pInputStream;

3 notes on commit 226c850

arnova
Collaborator

This fails to compile on Linux systems which don't have libbluray installed

Joakim Plate
Collaborator
arnova
Collaborator

Fixed compile error in 8d0d0b3

Please sign in to comment.
Something went wrong with that request. Please try again.