diff --git a/lib/DllLibbluray.h b/lib/DllLibbluray.h index 30307ca60d915..5111c53bf307b 100644 --- a/lib/DllLibbluray.h +++ b/lib/DllLibbluray.h @@ -30,6 +30,8 @@ extern "C" #include #include #include +#include +#include } class DllLibblurayInterface @@ -65,6 +67,16 @@ class DllLibblurayInterface virtual void bd_set_debug_mask(uint32_t mask)=0; virtual uint32_t bd_get_debug_mask(void)=0; virtual const BLURAY_DISC_INFO *bd_get_disc_info(BLURAY *bd)=0; + + virtual int bd_get_event (BLURAY *bd, BD_EVENT *event)=0; + virtual int bd_play (BLURAY *bd)=0; + virtual int bd_read_ext (BLURAY *bd, unsigned char *buf, int len, BD_EVENT *event)=0; + virtual int bd_read_skip_still (BLURAY *bd)=0; + virtual int bd_user_input (BLURAY *bd, int64_t pts, uint32_t key)=0; + virtual int bd_set_player_setting (BLURAY *bd, uint32_t idx, uint32_t value)=0; + virtual int bd_set_player_setting_str (BLURAY *bd, uint32_t idx, const char *s)=0; + virtual void bd_register_overlay_proc (BLURAY *bd, void *handle, bd_overlay_proc_f func)=0; + virtual int bd_menu_call (BLURAY *bd, int64_t pts)=0; }; class DllLibbluray : public DllDynamic, DllLibblurayInterface @@ -100,6 +112,16 @@ class DllLibbluray : public DllDynamic, DllLibblurayInterface DEFINE_METHOD0(uint32_t, bd_get_debug_mask) DEFINE_METHOD1(const BLURAY_DISC_INFO*, bd_get_disc_info, (BLURAY *p1)) + DEFINE_METHOD2(int, bd_get_event, (BLURAY *p1, BD_EVENT *p2)) + DEFINE_METHOD1(int, bd_play, (BLURAY *p1)) + DEFINE_METHOD4(int, bd_read_ext, (BLURAY *p1, unsigned char *p2, int p3, BD_EVENT *p4)) + DEFINE_METHOD1(int, bd_read_skip_still, (BLURAY *p1)) + DEFINE_METHOD3(int, bd_user_input, (BLURAY *p1, int64_t p2, uint32_t p3)) + DEFINE_METHOD3(int, bd_set_player_setting, (BLURAY *p1, uint32_t p2, uint32_t p3)) + DEFINE_METHOD3(int, bd_set_player_setting_str, (BLURAY *p1, uint32_t p2, const char *p3)) + DEFINE_METHOD3(void, bd_register_overlay_proc, (BLURAY *p1, void *p2, bd_overlay_proc_f p3)) + DEFINE_METHOD2(int, bd_menu_call, (BLURAY *p1, int64_t p2)) + BEGIN_METHOD_RESOLVE() RESOLVE_METHOD(bd_get_titles) RESOLVE_METHOD(bd_get_title_info) @@ -129,6 +151,16 @@ class DllLibbluray : public DllDynamic, DllLibblurayInterface RESOLVE_METHOD(bd_set_debug_mask) RESOLVE_METHOD(bd_get_debug_mask) RESOLVE_METHOD(bd_get_disc_info) + + RESOLVE_METHOD(bd_get_event) + RESOLVE_METHOD(bd_play) + RESOLVE_METHOD(bd_read_ext) + RESOLVE_METHOD(bd_read_skip_still) + RESOLVE_METHOD(bd_user_input) + RESOLVE_METHOD(bd_set_player_setting) + RESOLVE_METHOD(bd_set_player_setting_str) + RESOLVE_METHOD(bd_register_overlay_proc) + RESOLVE_METHOD(bd_menu_call) END_METHOD_RESOLVE() public: diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDFactoryInputStream.cpp b/xbmc/cores/dvdplayer/DVDInputStreams/DVDFactoryInputStream.cpp index e4e7065b71a53..1fe8ae19f3069 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDFactoryInputStream.cpp +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDFactoryInputStream.cpp @@ -54,7 +54,7 @@ CDVDInputStream* CDVDFactoryInputStream::CreateInputStream(IDVDPlayer* pPlayer, } #ifdef HAVE_LIBBLURAY else if (item.IsType(".bdmv") || item.IsType(".mpls") || content == "bluray/iso") - return new CDVDInputStreamBluray(); + return new CDVDInputStreamBluray(pPlayer); #endif else if(file.substr(0, 6) == "rtp://" || file.substr(0, 7) == "rtsp://" diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp index 41e78182874bd..ce871e41b3195 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp @@ -22,6 +22,11 @@ #ifdef HAVE_LIBBLURAY #include "DVDInputStreamBluray.h" +#include "IDVDPlayer.h" +#include "DVDCodecs/Overlay/DVDOverlay.h" +#include "DVDCodecs/Overlay/DVDOverlayImage.h" +#include "settings/GUISettings.h" +#include "LangInfo.h" #include "utils/log.h" #include "utils/URIUtils.h" #include "filesystem/File.h" @@ -195,10 +200,17 @@ void DllLibbluray::bluray_logger(const char* msg) CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Logger - %s", msg); } -CDVDInputStreamBluray::CDVDInputStreamBluray() : + +static void bluray_overlay_cb(void *this_gen, const BD_OVERLAY * ov) +{ + static_cast(this_gen)->OverlayCallback(ov); +} + +CDVDInputStreamBluray::CDVDInputStreamBluray(IDVDPlayer* player) : CDVDInputStream(DVDSTREAM_TYPE_BLURAY) { m_title = NULL; + m_clip = 0; m_bd = NULL; m_dll = new DllLibbluray; if (!m_dll->Load()) @@ -206,6 +218,8 @@ CDVDInputStreamBluray::CDVDInputStreamBluray() : delete m_dll; m_dll = NULL; } + m_content = "video/x-mpegts"; + m_player = player; } CDVDInputStreamBluray::~CDVDInputStreamBluray() @@ -250,33 +264,15 @@ BLURAY_TITLE_INFO* CDVDInputStreamBluray::GetTitleFile(const std::string& filena return NULL; } - int titles = m_dll->bd_get_titles(m_bd, TITLES_ALL, 0); - if(titles < 0) - { - CLog::Log(LOGERROR, "get_playlist_title - unable to get list of titles"); - return NULL; - } - - BLURAY_TITLE_INFO *t; - for(int i=0; i < titles; i++) - { - t = m_dll->bd_get_title_info(m_bd, i, 0); - if(!t) - { - CLog::Log(LOGDEBUG, "get_playlist_title - unable to get title %d", i); - continue; - } - if(t->playlist == playlist) - return t; - m_dll->bd_free_title_info(t); - } - - return NULL; + return m_dll->bd_get_playlist_info(m_bd, playlist, 0); } bool CDVDInputStreamBluray::Open(const char* strFile, const std::string& content) { + if(m_player == NULL) + return false; + CStdString strPath; URIUtils::GetDirectory(strFile,strPath); URIUtils::RemoveSlashAtEnd(strPath); @@ -299,7 +295,7 @@ bool CDVDInputStreamBluray::Open(const char* strFile, const std::string& content m_dll->bd_register_dir(DllLibbluray::dir_open); m_dll->bd_register_file(DllLibbluray::file_open); m_dll->bd_set_debug_handler(DllLibbluray::bluray_logger); - m_dll->bd_set_debug_mask(DBG_CRIT); + m_dll->bd_set_debug_mask(DBG_CRIT | DBG_BLURAY | DBG_NAV); CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - opening %s", strPath.c_str()); m_bd = m_dll->bd_open(strPath.c_str(), NULL); @@ -353,28 +349,76 @@ bool CDVDInputStreamBluray::Open(const char* strFile, const std::string& content CStdString filename = URIUtils::GetFileName(strFile); if(filename.Equals("index.bdmv")) { + m_navmode = false; m_title = GetTitleLongest(); } else if(URIUtils::GetExtension(filename).Equals(".mpls")) { + m_navmode = false; m_title = GetTitleFile(filename); } + else if(filename.Equals("MovieObject.bdmv")) + { + m_navmode = true; + if (m_navmode && !disc_info->first_play_supported) { + CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - Can't play disc in HDMV navigation mode - First Play title not supported"); + m_navmode = false; + } + + if (m_navmode && disc_info->num_unsupported_titles > 0) { + CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - Unsupported titles found - Some titles can't be played in navigation mode"); + } + + if(!m_navmode) + m_title = GetTitleLongest(); + } else { CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - unsupported bluray file selected %s", strPath.c_str()); return false; } - if(!m_title) + if(m_navmode) { - CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - failed to get title info"); - return false; - } + int region = g_guiSettings.GetInt("dvds.playerregion"); + if(region == 0) + { + CLog::Log(LOGWARNING, "CDVDInputStreamBluray::Open - region dvd must be set in setting, assuming region 1"); + region = 1; + } + m_dll->bd_set_player_setting (m_bd, BLURAY_PLAYER_SETTING_REGION_CODE, region); + m_dll->bd_set_player_setting (m_bd, BLURAY_PLAYER_SETTING_PARENTAL, 0); + m_dll->bd_set_player_setting (m_bd, BLURAY_PLAYER_SETTING_PLAYER_PROFILE, 0); + m_dll->bd_set_player_setting_str(m_bd, BLURAY_PLAYER_SETTING_AUDIO_LANG, g_langInfo.GetDVDAudioLanguage().c_str()); + m_dll->bd_set_player_setting_str(m_bd, BLURAY_PLAYER_SETTING_PG_LANG, g_langInfo.GetDVDSubtitleLanguage().c_str()); + m_dll->bd_set_player_setting_str(m_bd, BLURAY_PLAYER_SETTING_MENU_LANG, g_langInfo.GetDVDMenuLanguage().c_str()); + m_dll->bd_set_player_setting_str(m_bd, BLURAY_PLAYER_SETTING_COUNTRY_CODE, "us"); + m_dll->bd_register_overlay_proc (m_bd, this, bluray_overlay_cb); + + m_dll->bd_get_event(m_bd, NULL); + - if(m_dll->bd_select_title(m_bd, m_title->idx) == 0 ) + if(m_dll->bd_play(m_bd) <= 0) + { + CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - failed play disk %s", strPath.c_str()); + return false; + } + m_hold = HOLD_DATA; + m_title_playing = false; + } + else { - CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - failed to select title %d", m_title->idx); - return false; + if(!m_title) + { + CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - failed to get title info"); + return false; + } + + if(m_dll->bd_select_playlist(m_bd, m_title->playlist) == 0 ) + { + CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - failed to select title %d", m_title->idx); + return false; + } } return true; @@ -385,17 +429,324 @@ void CDVDInputStreamBluray::Close() { if (!m_dll) return; + if(m_title) + m_dll->bd_free_title_info(m_title); if(m_bd) + { + m_dll->bd_register_overlay_proc(m_bd, NULL, NULL); m_dll->bd_close(m_bd); + } m_bd = NULL; - if(m_title) - m_dll->bd_free_title_info(m_title); m_title = NULL; } int CDVDInputStreamBluray::Read(BYTE* buf, int buf_size) { - return m_dll->bd_read(m_bd, buf, buf_size); + if(m_navmode) + { + int result = 0; + do { + + if(m_hold == HOLD_HELD) + return 0; + + if(m_hold == HOLD_SKIP) + { + /* m_event already holds data */ + m_hold = HOLD_DATA; + result = 0; + } + else + { + result = m_dll->bd_read_ext (m_bd, buf, buf_size, &m_event); + + if(m_hold == HOLD_NONE) + { + /* Check for holding events */ + switch(m_event.event) { + case BD_EVENT_SEEK: + case BD_EVENT_TITLE: + if(m_title_playing) + m_player->OnDVDNavResult(NULL, 1); + m_hold = HOLD_HELD; + return result; + + case BD_EVENT_PLAYLIST: + case BD_EVENT_PLAYITEM: + m_hold = HOLD_HELD; + return result; + default: + break; + } + } + if(result > 0) + m_hold = HOLD_NONE; + } + int pid = -1; + switch (m_event.event) { + + case BD_EVENT_ERROR: + CLog::Log(LOGERROR, "CDVDInputStreamBluray - BD_EVENT_ERROR"); + return -1; + + case BD_EVENT_ENCRYPTED: + CLog::Log(LOGERROR, "CDVDInputStreamBluray - BD_EVENT_ENCRYPTED"); + return -1; + + /* playback control */ + + case BD_EVENT_SEEK: + CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_SEEK"); + break; + + case BD_EVENT_STILL_TIME: + CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_STILL_TIME %d", m_event.param); + return 0; + + case BD_EVENT_STILL: + CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_STILL %d", m_event.param); + break; + + /* playback position */ + + case BD_EVENT_ANGLE: + CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_ANGLE %d", m_event.param); + break; + + case BD_EVENT_END_OF_TITLE: + CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_END_OF_TITLE %d", m_event.param); + m_title_playing = false; + break; + + case BD_EVENT_TITLE: + CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_TITLE %d", m_event.param); + if(m_title) + m_dll->bd_free_title_info(m_title); + m_title = m_dll->bd_get_title_info(m_bd, m_event.param, 0); + m_title_playing = true; + break; + + case BD_EVENT_PLAYLIST: + CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_PLAYLIST %d", m_event.param); + if(m_title) + m_dll->bd_free_title_info(m_title); + m_title = m_dll->bd_get_playlist_info(m_bd, m_event.param, 0); + break; + + case BD_EVENT_PLAYITEM: + CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_PLAYITEM %d", m_event.param); + m_clip = m_event.param; + break; + + case BD_EVENT_CHAPTER: + CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_CHAPTER %d", m_event.param); + break; + + /* stream selection */ + + case BD_EVENT_AUDIO_STREAM: + pid = -1; + if(m_title + && m_title->clip_count > m_clip + && m_title->clips[m_clip].audio_stream_count > (uint8_t)(m_event.param - 1)) + pid = m_title->clips[m_clip].audio_streams[m_event.param-1].pid; + CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_AUDIO_STREAM %d %d", m_event.param, pid); + m_player->OnDVDNavResult((void*)&pid, 2); + break; + + case BD_EVENT_PG_TEXTST: + CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_PG_TEXTST %d", m_event.param); + pid = m_event.param; + m_player->OnDVDNavResult((void*)&pid, 4); + break; + + case BD_EVENT_PG_TEXTST_STREAM: + pid = -1; + if(m_title + && m_title->clip_count > m_clip + && m_title->clips[m_clip].pg_stream_count > (uint8_t)(m_event.param - 1)) + pid = m_title->clips[m_clip].pg_streams[m_event.param-1].pid; + CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_PG_TEXTST_STREAM %d, %d", m_event.param, pid); + m_player->OnDVDNavResult((void*)&pid, 3); + break; + + case BD_EVENT_IG_STREAM: + case BD_EVENT_SECONDARY_AUDIO: + case BD_EVENT_SECONDARY_AUDIO_STREAM: + case BD_EVENT_SECONDARY_VIDEO: + case BD_EVENT_SECONDARY_VIDEO_SIZE: + case BD_EVENT_SECONDARY_VIDEO_STREAM: + + case BD_EVENT_NONE: + break; + + default: + CLog::Log(LOGWARNING, "CDVDInputStreamBluray - unhandled libbluray event %d [param %d]", m_event.event, m_event.param); + break; + } + + } while(result == 0); + + return result; + } + else + return m_dll->bd_read(m_bd, buf, buf_size); +} + +static uint8_t clamp(double v) +{ + return (v) > 255.0 ? 255 : ((v) < 0.0 ? 0 : (uint8_t)(v+0.5f)); +} + +static uint32_t build_rgba(const BD_PG_PALETTE_ENTRY &e) +{ + double r = 1.164 * (e.Y - 16) + 1.596 * (e.Cr - 128); + double g = 1.164 * (e.Y - 16) - 0.391 * (e.Cb - 128) - 0.813 * (e.Cr - 128); + double b = 1.164 * (e.Y - 16) + 2.018 * (e.Cb - 128); + return (uint32_t)e.T << PIXEL_ASHIFT + | (uint32_t)clamp(r) << PIXEL_RSHIFT + | (uint32_t)clamp(g) << PIXEL_GSHIFT + | (uint32_t)clamp(b) << PIXEL_BSHIFT; +} + +void CDVDInputStreamBluray::OverlayCallback(const BD_OVERLAY * const ov) +{ + + CDVDOverlayGroup* group = new CDVDOverlayGroup(); + group->bForced = true; + + if(ov == NULL) + { + for(unsigned i = 0; i < 2; ++i) + { + for(std::vector::iterator it = m_overlays[i].begin(); it != m_overlays[i].end(); ++it) + (*it)->Release(); + m_overlays[i].clear(); + } + + m_player->OnDVDNavResult(group, 0); + return; + } + + group->iPTSStartTime = ov->pts; + group->iPTSStopTime = 0; + + if (ov->plane > 1) + { + CLog::Log(LOGWARNING, "CDVDInputStreamBluray - Ignoring overlay with multiple planes"); + group->Release(); + return; + } + + std::vector& plane(m_overlays[ov->plane]); + + /* fixup existing overlays */ + for(std::vector::iterator it = plane.begin(); it != plane.end();) + { + /* if it's fully outside we are done */ + if(ov->x + ov->w <= (*it)->x + || ov->x >= (*it)->x + (*it)->width + || ov->y + ov->h <= (*it)->y + || ov->y >= (*it)->y + (*it)->height) + { + ++it; + continue; + } + + int y1 = std::max((*it)->y , ov->y); + int y2 = std::min((*it)->y + (*it)->height, ov->y + ov->h); + int x1 = std::max((*it)->x , ov->x); + int x2 = std::min((*it)->x + (*it)->width , ov->x + ov->w); + + /* if all should be cleared, delete */ + if(x1 == (*it)->x + && x2 == (*it)->x + (*it)->width + && y1 == (*it)->y + && y2 == (*it)->y + (*it)->height) + { + CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - Delete(%d) %d-%dx%d-%d", ov->plane, x1, x2, y1, y2); + it = plane.erase(it); + continue; + } +#if(1) + CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - Clearing(%d) %d-%dx%d-%d", ov->plane, x1, x2, y1, y2); + + /* replace overlay with a new copy*/ + CDVDOverlayImage* overlay = new CDVDOverlayImage(*(*it)); + (*it)->Release(); + (*it) = overlay; + + /* any old hw overlay must be released */ + SAFE_RELEASE(overlay->m_overlay); + + /* clear out overlap */ + y1 -= overlay->y; + y2 -= overlay->y; + x1 -= overlay->x; + x2 -= overlay->x; + + /* find fully transparent */ + int transp = 0; + for(; transp < overlay->palette_colors; ++transp) + { + if(((overlay->palette[transp] >> PIXEL_ASHIFT) & 0xff) == 0) + break; + } + + if(transp == overlay->palette_colors) + { + CLog::Log(LOGERROR, "CDVDInputStreamBluray - failed to find transparent color"); + continue; + } + + for(int y = y1; y < y2; ++y) + { + BYTE* line = overlay->data + y * overlay->linesize; + for(int x = x1; x < x2; ++x) + line[x] = transp; + } + ++it; +#endif + } + + + /* uncompress and draw bitmap */ + if (ov->img) + { + CDVDOverlayImage* overlay = new CDVDOverlayImage(); + + if (ov->palette) + { + overlay->palette_colors = 256; + overlay->palette = (uint32_t*)calloc(overlay->palette_colors, 4); + + for(unsigned i = 0; i < 256; i++) + overlay->palette[i] = build_rgba(ov->palette[i]); + } + + const BD_PG_RLE_ELEM *rlep = ov->img; + uint8_t *img = (uint8_t*) malloc(ov->w * ov->h); + unsigned pixels = ov->w * ov->h; + + for (unsigned i = 0; i < pixels; i += rlep->len, rlep++) { + memset(img + i, rlep->color, rlep->len); + } + + overlay->data = img; + overlay->linesize = ov->w; + overlay->x = ov->x; + overlay->y = ov->y; + overlay->height = ov->h; + overlay->width = ov->w; + plane.push_back(overlay); + } + + for(unsigned i = 0; i < 2; ++i) + { + for(std::vector::iterator it = m_overlays[i].begin(); it != m_overlays[i].end(); ++it) + group->m_overlays.push_back((*it)->Acquire()); + } + m_player->OnDVDNavResult(group, 0); } int CDVDInputStreamBluray::GetTotalTime() @@ -499,10 +850,10 @@ static bool find_stream(int pid, BLURAY_STREAM_INFO *info, int count, char* lang void CDVDInputStreamBluray::GetStreamInfo(int pid, char* language) { - if(m_title->clip_count == 0) + if(!m_title || m_clip >= m_title->clip_count) return; - BLURAY_CLIP_INFO *clip = m_title->clips; + BLURAY_CLIP_INFO *clip = m_title->clips+m_clip; if(find_stream(pid, clip->audio_streams, clip->audio_stream_count, language)) return; @@ -514,4 +865,56 @@ void CDVDInputStreamBluray::GetStreamInfo(int pid, char* language) return; } +CDVDInputStream::ENextStream CDVDInputStreamBluray::NextStream() +{ + if(!m_navmode) + return NEXTSTREAM_NONE; + + if(m_hold == HOLD_HELD) + { + m_hold = HOLD_SKIP; + return NEXTSTREAM_OPEN; + } + if(m_hold == HOLD_NONE) + { + m_hold = HOLD_DATA; + m_dll->bd_read_skip_still(m_bd); + } + return NEXTSTREAM_RETRY; +} + +void CDVDInputStreamBluray::UserInput(bd_vk_key_e vk) +{ + if(m_bd == NULL || !m_navmode) + return; + m_dll->bd_user_input(m_bd, -1, vk); +} + +void CDVDInputStreamBluray::OnMenu() +{ + if(m_bd == NULL || !m_navmode) + return; + + if(m_dll->bd_user_input(m_bd, -1, BD_VK_POPUP) >= 0) + return; + CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::OnMenu - popup failed, trying root"); + + if(m_dll->bd_user_input(m_bd, -1, BD_VK_ROOT_MENU) >= 0) + return; + + CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::OnMenu - root failed, trying explicit"); + if(m_dll->bd_menu_call(m_bd, -1) >= 0) + return; + CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::OnMenu - root failed"); +} + +bool CDVDInputStreamBluray::IsInMenu() +{ + if(m_bd == NULL || !m_navmode) + return false; + if(m_overlays[BD_OVERLAY_IG].size() > 0) + return true; + return false; +} + #endif diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.h b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.h index 1d11ea2f830a1..dc0ffa9fbb908 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.h +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.h @@ -23,18 +23,27 @@ #include "DVDInputStream.h" + +extern "C" +{ +#include +#include +#include +} + +class CDVDOverlayImage; class DllLibbluray; -typedef struct bluray BLURAY; -typedef struct bd_title_info BLURAY_TITLE_INFO; +class IDVDPlayer; class CDVDInputStreamBluray : public CDVDInputStream , public CDVDInputStream::IDisplayTime , public CDVDInputStream::IChapter , public CDVDInputStream::ISeekTime + , public CDVDInputStream::IMenus { public: - CDVDInputStreamBluray(); + CDVDInputStreamBluray(IDVDPlayer* player); virtual ~CDVDInputStreamBluray(); virtual bool Open(const char* strFile, const std::string &content); virtual void Close(); @@ -44,6 +53,36 @@ class CDVDInputStreamBluray virtual bool IsEOF(); virtual __int64 GetLength(); virtual int GetBlockSize() { return 6144; } + virtual ENextStream NextStream(); + + + /* IMenus */ + virtual void ActivateButton() { UserInput(BD_VK_ENTER); } + virtual void SelectButton(int iButton) + { + if(iButton < 10) + UserInput((bd_vk_key_e)(BD_VK_0 + iButton)); + } + virtual int GetCurrentButton() { return 0; } + virtual int GetTotalButtons() { return 0; } + virtual void OnUp() { UserInput(BD_VK_UP); } + virtual void OnDown() { UserInput(BD_VK_DOWN); } + virtual void OnLeft() { UserInput(BD_VK_LEFT); } + virtual void OnRight() { UserInput(BD_VK_RIGHT); } + virtual void OnMenu(); + virtual void OnBack() + { + if(IsInMenu()) + OnMenu(); + } + virtual void OnNext() {} + virtual void OnPrevious() {} + virtual bool IsInMenu(); + virtual bool OnMouseMove(const CPoint &point) { return false; } + virtual bool OnMouseClick(const CPoint &point) { return false; } + virtual double GetTimeStampCorrection() { return 0.0; } + + void UserInput(bd_vk_key_e vk); int GetChapter(); int GetChapterCount(); @@ -56,11 +95,25 @@ class CDVDInputStreamBluray void GetStreamInfo(int pid, char* language); + void OverlayCallback(const BD_OVERLAY * const); + BLURAY_TITLE_INFO* GetTitleLongest(); BLURAY_TITLE_INFO* GetTitleFile(const std::string& name); protected: + IDVDPlayer* m_player; DllLibbluray *m_dll; BLURAY* m_bd; BLURAY_TITLE_INFO* m_title; + bool m_title_playing; + uint32_t m_clip; + bool m_navmode; + std::vector m_overlays[2]; + enum EHoldState { + HOLD_NONE = 0, + HOLD_HELD, + HOLD_SKIP, + HOLD_DATA, + } m_hold; + BD_EVENT m_event; }; diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp index 19beafad3555d..9c9fbace45b73 100644 --- a/xbmc/cores/dvdplayer/DVDPlayer.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp @@ -855,7 +855,8 @@ bool CDVDPlayer::IsBetterStream(CCurrentStream& current, CDemuxStream* stream) if(m_PlayerOptions.video_only && current.type != STREAM_VIDEO) return false; - if (m_pInputStream && m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD)) + if (m_pInputStream && ( m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD) + || m_pInputStream->IsStreamType(DVDSTREAM_TYPE_BLURAY) ) ) { int source_type; @@ -3064,6 +3065,22 @@ void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate) // since we call ffmpeg functions to decode, this is being called in the same thread as ::Process() is int CDVDPlayer::OnDVDNavResult(void* pData, int iMessage) { + if (m_pInputStream->IsStreamType(DVDSTREAM_TYPE_BLURAY)) + { + if(iMessage == 0) + m_overlayContainer.Add((CDVDOverlay*)pData); + else if(iMessage == 1) + m_messenger.Put(new CDVDMsg(CDVDMsg::GENERAL_FLUSH)); + else if(iMessage == 2) + m_dvd.iSelectedAudioStream = *(int*)pData; + else if(iMessage == 3) + m_dvd.iSelectedSPUStream = *(int*)pData; + else if(iMessage == 4) + m_dvdPlayerVideo.EnableSubtitle(*(int*)pData ? true: false); + + return 0; + } + if (m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD)) { CDVDInputStreamNavigator* pStream = (CDVDInputStreamNavigator*)m_pInputStream;