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/>.
23 #include "DVDInputStreamBluray.h"
24 #include "IDVDPlayer.h"
25 #include "DVDCodecs/Overlay/DVDOverlay.h"
26 #include "DVDCodecs/Overlay/DVDOverlayImage.h"
27 #include "settings/Settings.h"
29 #include "utils/log.h"
30 #include "utils/StringUtils.h"
31 #include "utils/URIUtils.h"
32 #include "filesystem/File.h"
33 #include "filesystem/Directory.h"
34 #include "DllLibbluray.h"
36 #include "guilib/Geometry.h"
37 #include "utils/StringUtils.h"
39 #define LIBBLURAY_BYTESEEK 0
42 using namespace XFILE;
44 void DllLibbluray::file_close(BD_FILE_H *file)
48 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - Closed file (%p)\n", file);
50 delete static_cast<CFile*>(file->internal);
55 int64_t DllLibbluray::file_seek(BD_FILE_H *file, int64_t offset, int32_t origin)
57 return static_cast<CFile*>(file->internal)->Seek(offset, origin);
60 int64_t DllLibbluray::file_tell(BD_FILE_H *file)
62 return static_cast<CFile*>(file->internal)->GetPosition();
65 int DllLibbluray::file_eof(BD_FILE_H *file)
67 if(static_cast<CFile*>(file->internal)->GetPosition() == static_cast<CFile*>(file->internal)->GetLength())
73 int64_t DllLibbluray::file_read(BD_FILE_H *file, uint8_t *buf, int64_t size)
75 return static_cast<CFile*>(file->internal)->Read(buf, size);
78 int64_t DllLibbluray::file_write(BD_FILE_H *file, const uint8_t *buf, int64_t size)
83 BD_FILE_H * DllLibbluray::file_open(const char* filename, const char *mode)
85 BD_FILE_H *file = new BD_FILE_H;
87 file->close = file_close;
88 file->seek = file_seek;
89 file->read = file_read;
90 file->write = file_write;
91 file->tell = file_tell;
94 CFile* fp = new CFile();
95 if(fp->Open(filename))
97 file->internal = (void*)fp;
101 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - Error opening file! (%p)", file);
119 void DllLibbluray::dir_close(BD_DIR_H *dir)
123 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - Closed dir (%p)\n", dir);
124 delete static_cast<SDirState*>(dir->internal);
130 int DllLibbluray::dir_read(BD_DIR_H *dir, BD_DIRENT *entry)
132 SDirState* state = static_cast<SDirState*>(dir->internal);
134 if(state->curr >= state->list.Size())
137 strncpy(entry->d_name, state->list[state->curr]->GetLabel(), sizeof(entry->d_name));
138 entry->d_name[sizeof(entry->d_name)-1] = 0;
144 BD_DIR_H *DllLibbluray::dir_open(const char* dirname)
146 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - Opening dir %s\n", dirname);
147 SDirState *st = new SDirState();
149 CStdString strDirname(dirname);
151 if(!CDirectory::GetDirectory(strDirname, st->list))
153 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - Error opening dir! (%s)\n", dirname);
158 BD_DIR_H *dir = new BD_DIR_H;
159 dir->close = dir_close;
160 dir->read = dir_read;
161 dir->internal = (void*)st;
166 void DllLibbluray::bluray_logger(const char* msg)
168 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Logger - %s", msg);
172 static void bluray_overlay_cb(void *this_gen, const BD_OVERLAY * ov)
174 static_cast<CDVDInputStreamBluray*>(this_gen)->OverlayCallback(ov);
177 #ifdef HAVE_LIBBLURAY_BDJ
178 void bluray_overlay_argb_cb(void *this_gen, const struct bd_argb_overlay_s * const ov)
180 static_cast<CDVDInputStreamBluray*>(this_gen)->OverlayCallbackARGB(ov);
184 CDVDInputStreamBluray::CDVDInputStreamBluray(IDVDPlayer* player) :
185 CDVDInputStream(DVDSTREAM_TYPE_BLURAY)
188 m_clip = (uint32_t)-1;
189 m_playlist = (uint32_t)-1;
192 m_dll = new DllLibbluray;
198 m_content = "video/x-mpegts";
202 memset(&m_event, 0, sizeof(m_event));
205 CDVDInputStreamBluray::~CDVDInputStreamBluray()
211 bool CDVDInputStreamBluray::IsEOF()
216 BLURAY_TITLE_INFO* CDVDInputStreamBluray::GetTitleLongest()
218 int titles = m_dll->bd_get_titles(m_bd, TITLES_RELEVANT, 0);
220 BLURAY_TITLE_INFO *s = NULL;
221 for(int i=0; i < titles; i++)
223 BLURAY_TITLE_INFO *t = m_dll->bd_get_title_info(m_bd, i, 0);
226 CLog::Log(LOGDEBUG, "get_main_title - unable to get title %d", i);
229 if(!s || s->duration < t->duration)
233 m_dll->bd_free_title_info(t);
238 BLURAY_TITLE_INFO* CDVDInputStreamBluray::GetTitleFile(const std::string& filename)
240 unsigned int playlist;
241 if(sscanf(filename.c_str(), "%05d.mpls", &playlist) != 1)
243 CLog::Log(LOGERROR, "get_playlist_title - unsupported playlist file selected %s", filename.c_str());
247 return m_dll->bd_get_playlist_info(m_bd, playlist, 0);
251 bool CDVDInputStreamBluray::Open(const char* strFile, const std::string& content)
256 CStdString strPath(strFile);
260 if(StringUtils::StartsWithNoCase(strPath, "bluray:"))
263 root = url.GetHostName();
264 filename = URIUtils::GetFileName(url.GetFileName());
266 else if(URIUtils::HasExtension(strPath, ".iso|.img"))
269 url.SetHostName(strPath);
271 filename = "index.bdmv";
275 strPath = URIUtils::GetDirectory(strPath);
276 URIUtils::RemoveSlashAtEnd(strPath);
278 if(URIUtils::GetFileName(strPath) == "PLAYLIST")
280 strPath = URIUtils::GetDirectory(strPath);
281 URIUtils::RemoveSlashAtEnd(strPath);
284 if(URIUtils::GetFileName(strPath) == "BDMV")
286 strPath = URIUtils::GetDirectory(strPath);
287 URIUtils::RemoveSlashAtEnd(strPath);
290 filename = URIUtils::GetFileName(strFile);
293 // root should not have trailing slash
294 URIUtils::RemoveSlashAtEnd(root);
299 m_dll->bd_register_dir(DllLibbluray::dir_open);
300 m_dll->bd_register_file(DllLibbluray::file_open);
301 m_dll->bd_set_debug_handler(DllLibbluray::bluray_logger);
302 m_dll->bd_set_debug_mask(DBG_CRIT | DBG_BLURAY | DBG_NAV);
304 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - opening %s", root.c_str());
305 m_bd = m_dll->bd_open(root.c_str(), NULL);
309 CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - failed to open %s", root.c_str());
313 const BLURAY_DISC_INFO *disc_info;
315 disc_info = m_dll->bd_get_disc_info(m_bd);
319 CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - bd_get_disc_info() failed");
323 if (disc_info->bluray_detected)
325 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - First Play supported: %d", disc_info->first_play_supported);
326 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - Top menu supported : %d", disc_info->top_menu_supported);
327 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - HDMV titles : %d", disc_info->num_hdmv_titles);
328 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - BD-J titles : %d", disc_info->num_bdj_titles);
329 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - UNSUPPORTED titles : %d", disc_info->num_unsupported_titles);
330 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - AACS detected : %d", disc_info->aacs_detected);
331 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - libaacs detected : %d", disc_info->libaacs_detected);
332 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - AACS handled : %d", disc_info->aacs_handled);
333 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - BD+ detected : %d", disc_info->bdplus_detected);
334 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - libbdplus detected : %d", disc_info->libbdplus_detected);
335 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::Open - BD+ handled : %d", disc_info->bdplus_handled);
338 CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - BluRay not detected");
340 if (disc_info->aacs_detected && !disc_info->aacs_handled)
342 CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - Media stream scrambled/encrypted with AACS");
346 if (disc_info->bdplus_detected && !disc_info->bdplus_handled)
348 CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - Media stream scrambled/encrypted with BD+");
352 if(filename.Equals("index.bdmv"))
355 m_title = GetTitleLongest();
357 else if(URIUtils::HasExtension(filename, ".mpls"))
360 m_title = GetTitleFile(filename);
362 else if(filename.Equals("MovieObject.bdmv"))
365 if (m_navmode && !disc_info->first_play_supported) {
366 CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - Can't play disc in HDMV navigation mode - First Play title not supported");
370 if (m_navmode && disc_info->num_unsupported_titles > 0) {
371 CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - Unsupported titles found - Some titles can't be played in navigation mode");
375 m_title = GetTitleLongest();
379 CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - unsupported bluray file selected %s", strPath.c_str());
385 int region = CSettings::Get().GetInt("dvds.playerregion");
388 CLog::Log(LOGWARNING, "CDVDInputStreamBluray::Open - region dvd must be set in setting, assuming region 1");
391 m_dll->bd_set_player_setting (m_bd, BLURAY_PLAYER_SETTING_REGION_CODE, region);
392 m_dll->bd_set_player_setting (m_bd, BLURAY_PLAYER_SETTING_PARENTAL, 0);
393 m_dll->bd_set_player_setting (m_bd, BLURAY_PLAYER_SETTING_PLAYER_PROFILE, 0);
394 m_dll->bd_set_player_setting_str(m_bd, BLURAY_PLAYER_SETTING_AUDIO_LANG, g_langInfo.GetDVDAudioLanguage().c_str());
395 m_dll->bd_set_player_setting_str(m_bd, BLURAY_PLAYER_SETTING_PG_LANG, g_langInfo.GetDVDSubtitleLanguage().c_str());
396 m_dll->bd_set_player_setting_str(m_bd, BLURAY_PLAYER_SETTING_MENU_LANG, g_langInfo.GetDVDMenuLanguage().c_str());
397 m_dll->bd_set_player_setting_str(m_bd, BLURAY_PLAYER_SETTING_COUNTRY_CODE, "us");
398 m_dll->bd_register_overlay_proc (m_bd, this, bluray_overlay_cb);
399 #ifdef HAVE_LIBBLURAY_BDJ
400 m_dll->bd_register_argb_overlay_proc (m_bd, this, bluray_overlay_argb_cb, NULL);
403 m_dll->bd_get_event(m_bd, NULL);
406 if(m_dll->bd_play(m_bd) <= 0)
408 CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - failed play disk %s", strPath.c_str());
417 CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - failed to get title info");
421 if(m_dll->bd_select_playlist(m_bd, m_title->playlist) == 0 )
423 CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - failed to select title %d", m_title->idx);
432 // close file and reset everyting
433 void CDVDInputStreamBluray::Close()
438 m_dll->bd_free_title_info(m_title);
441 m_dll->bd_register_overlay_proc(m_bd, NULL, NULL);
442 m_dll->bd_close(m_bd);
448 void CDVDInputStreamBluray::ProcessEvent() {
451 switch (m_event.event) {
454 CLog::Log(LOGERROR, "CDVDInputStreamBluray - BD_EVENT_ERROR");
457 case BD_EVENT_ENCRYPTED:
458 CLog::Log(LOGERROR, "CDVDInputStreamBluray - BD_EVENT_ENCRYPTED");
461 /* playback control */
464 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_SEEK");
465 //m_player->OnDVDNavResult(NULL, 1);
466 //m_dll->bd_read_skip_still(m_bd);
467 //m_hold = HOLD_HELD;
470 case BD_EVENT_STILL_TIME:
471 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_STILL_TIME %d", m_event.param);
473 m_player->OnDVDNavResult((void*) &pid, 5);
478 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_STILL %d",
482 /* playback position */
485 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_ANGLE %d",
487 m_angle = m_event.param;
489 m_dll->bd_free_title_info(m_title);
490 m_title = m_dll->bd_get_playlist_info(m_bd, m_playlist, m_angle);
493 case BD_EVENT_END_OF_TITLE:
494 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_END_OF_TITLE %d",
496 /* when a title ends, playlist WILL eventually change */
498 m_dll->bd_free_title_info(m_title);
503 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_TITLE %d",
507 case BD_EVENT_PLAYLIST:
508 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_PLAYLIST %d",
510 m_playlist = m_event.param;
512 m_dll->bd_free_title_info(m_title);
513 m_title = m_dll->bd_get_playlist_info(m_bd, m_playlist, m_angle);
516 case BD_EVENT_PLAYITEM:
517 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_PLAYITEM %d",
519 m_clip = m_event.param;
522 case BD_EVENT_CHAPTER:
523 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_CHAPTER %d",
527 /* stream selection */
529 case BD_EVENT_AUDIO_STREAM:
531 if (m_title && m_title->clip_count > m_clip
532 && m_title->clips[m_clip].audio_stream_count
533 > (uint8_t) (m_event.param - 1))
534 pid = m_title->clips[m_clip].audio_streams[m_event.param - 1].pid;
535 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_AUDIO_STREAM %d %d",
537 m_player->OnDVDNavResult((void*) &pid, 2);
540 case BD_EVENT_PG_TEXTST:
541 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_PG_TEXTST %d",
544 m_player->OnDVDNavResult((void*) &pid, 4);
547 case BD_EVENT_PG_TEXTST_STREAM:
549 if (m_title && m_title->clip_count > m_clip
550 && m_title->clips[m_clip].pg_stream_count
551 > (uint8_t) (m_event.param - 1))
552 pid = m_title->clips[m_clip].pg_streams[m_event.param - 1].pid;
554 "CDVDInputStreamBluray - BD_EVENT_PG_TEXTST_STREAM %d, %d",
556 m_player->OnDVDNavResult((void*) &pid, 3);
559 #ifdef HAVE_LIBBLURAY_BDJ
561 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray - BD_EVENT_PG_TEXTST %d",
563 m_menu = !!m_event.param;
571 case BD_EVENT_IG_STREAM:
572 case BD_EVENT_SECONDARY_AUDIO:
573 case BD_EVENT_SECONDARY_AUDIO_STREAM:
574 case BD_EVENT_SECONDARY_VIDEO:
575 case BD_EVENT_SECONDARY_VIDEO_SIZE:
576 case BD_EVENT_SECONDARY_VIDEO_STREAM:
582 CLog::Log(LOGWARNING,
583 "CDVDInputStreamBluray - unhandled libbluray event %d [param %d]",
584 m_event.event, m_event.param);
588 /* event has been consumed */
589 m_event.event = BD_EVENT_NONE;
592 int CDVDInputStreamBluray::Read(uint8_t* buf, int buf_size)
599 if(m_hold == HOLD_HELD)
602 result = m_dll->bd_read_ext (m_bd, buf, buf_size, &m_event);
604 /* Check for holding events */
605 switch(m_event.event) {
609 case BD_EVENT_PLAYLIST:
610 case BD_EVENT_PLAYITEM:
611 if(m_hold != HOLD_DATA)
618 case BD_EVENT_STILL_TIME:
619 if(m_hold == HOLD_STILL)
620 m_event.event = 0; /* Consume duplicate still event */
634 } while(result == 0);
639 return m_dll->bd_read(m_bd, buf, buf_size);
642 static uint8_t clamp(double v)
644 return (v) > 255.0 ? 255 : ((v) < 0.0 ? 0 : (uint8_t)(v+0.5f));
647 static uint32_t build_rgba(const BD_PG_PALETTE_ENTRY &e)
649 double r = 1.164 * (e.Y - 16) + 1.596 * (e.Cr - 128);
650 double g = 1.164 * (e.Y - 16) - 0.391 * (e.Cb - 128) - 0.813 * (e.Cr - 128);
651 double b = 1.164 * (e.Y - 16) + 2.018 * (e.Cb - 128);
652 return (uint32_t)e.T << PIXEL_ASHIFT
653 | (uint32_t)clamp(r) << PIXEL_RSHIFT
654 | (uint32_t)clamp(g) << PIXEL_GSHIFT
655 | (uint32_t)clamp(b) << PIXEL_BSHIFT;
658 void CDVDInputStreamBluray::OverlayClose()
660 #if(BD_OVERLAY_INTERFACE_VERSION >= 2)
661 for(unsigned i = 0; i < 2; ++i)
662 m_planes[i].o.clear();
663 CDVDOverlayGroup* group = new CDVDOverlayGroup();
664 group->bForced = true;
665 m_player->OnDVDNavResult(group, 0);
669 void CDVDInputStreamBluray::OverlayInit(SPlane& plane, int w, int h)
671 #if(BD_OVERLAY_INTERFACE_VERSION >= 2)
678 void CDVDInputStreamBluray::OverlayClear(SPlane& plane, int x, int y, int w, int h)
680 #if(BD_OVERLAY_INTERFACE_VERSION >= 2)
686 /* fixup existing overlays */
687 for(SOverlays::iterator it = plane.o.begin(); it != plane.o.end();)
691 , (*it)->x + (*it)->width
692 , (*it)->y + (*it)->height);
694 vector<CRect> rem = old.SubtractRect(ovr);
696 /* if no overlap we are done */
697 if(rem.size() == 1 && !(rem[0] != old))
704 for(vector<CRect>::iterator itr = rem.begin(); itr != rem.end(); ++itr)
706 SOverlay overlay(new CDVDOverlayImage(*(*it)
711 , std::ptr_fun(CDVDOverlay::Release));
712 add.push_back(overlay);
715 it = plane.o.erase(it);
716 plane.o.insert(it, add.begin(), add.end());
721 void CDVDInputStreamBluray::OverlayFlush(int64_t pts)
723 #if(BD_OVERLAY_INTERFACE_VERSION >= 2)
724 CDVDOverlayGroup* group = new CDVDOverlayGroup();
725 group->bForced = true;
726 group->iPTSStartTime = (double) pts;
727 group->iPTSStopTime = 0;
729 for(unsigned i = 0; i < 2; ++i)
731 for(SOverlays::iterator it = m_planes[i].o.begin(); it != m_planes[i].o.end(); ++it)
732 group->m_overlays.push_back((*it)->Acquire());
735 m_player->OnDVDNavResult(group, 0);
739 void CDVDInputStreamBluray::OverlayCallback(const BD_OVERLAY * const ov)
741 #if(BD_OVERLAY_INTERFACE_VERSION >= 2)
742 if(ov == NULL || ov->cmd == BD_OVERLAY_CLOSE)
750 CLog::Log(LOGWARNING, "CDVDInputStreamBluray - Ignoring overlay with multiple planes");
754 SPlane& plane(m_planes[ov->plane]);
756 if (ov->cmd == BD_OVERLAY_CLEAR)
762 if (ov->cmd == BD_OVERLAY_INIT)
764 OverlayInit(plane, ov->w, ov->h);
768 if (ov->cmd == BD_OVERLAY_DRAW
769 || ov->cmd == BD_OVERLAY_WIPE)
770 OverlayClear(plane, ov->x, ov->y, ov->w, ov->h);
773 /* uncompress and draw bitmap */
774 if (ov->img && ov->cmd == BD_OVERLAY_DRAW)
776 SOverlay overlay(new CDVDOverlayImage(), std::ptr_fun(CDVDOverlay::Release));
780 overlay->palette_colors = 256;
781 overlay->palette = (uint32_t*)calloc(overlay->palette_colors, 4);
783 for(unsigned i = 0; i < 256; i++)
784 overlay->palette[i] = build_rgba(ov->palette[i]);
787 const BD_PG_RLE_ELEM *rlep = ov->img;
788 uint8_t *img = (uint8_t*) malloc(ov->w * ov->h);
789 unsigned pixels = ov->w * ov->h;
791 for (unsigned i = 0; i < pixels; i += rlep->len, rlep++) {
792 memset(img + i, rlep->color, rlep->len);
796 overlay->linesize = ov->w;
799 overlay->height = ov->h;
800 overlay->width = ov->w;
801 overlay->source_height = plane.h;
802 overlay->source_width = plane.w;
803 plane.o.push_back(overlay);
806 if(ov->cmd == BD_OVERLAY_FLUSH)
807 OverlayFlush(ov->pts);
811 #ifdef HAVE_LIBBLURAY_BDJ
812 void CDVDInputStreamBluray::OverlayCallbackARGB(const struct bd_argb_overlay_s * const ov)
814 if(ov == NULL || ov->cmd == BD_ARGB_OVERLAY_CLOSE)
822 CLog::Log(LOGWARNING, "CDVDInputStreamBluray - Ignoring overlay with multiple planes");
826 SPlane& plane(m_planes[ov->plane]);
828 if (ov->cmd == BD_ARGB_OVERLAY_INIT)
830 OverlayInit(plane, ov->w, ov->h);
834 if (ov->cmd == BD_ARGB_OVERLAY_DRAW)
835 OverlayClear(plane, ov->x, ov->y, ov->w, ov->h);
837 /* uncompress and draw bitmap */
838 if (ov->argb && ov->cmd == BD_ARGB_OVERLAY_DRAW)
840 SOverlay overlay(new CDVDOverlayImage(), std::ptr_fun(CDVDOverlay::Release));
842 overlay->palette_colors = 0;
843 overlay->palette = NULL;
845 unsigned bytes = ov->stride * ov->h * 4;
846 uint8_t *img = (uint8_t*) malloc(bytes);
847 memcpy(img, ov->argb, bytes);
850 overlay->linesize = ov->stride * 4;
853 overlay->height = ov->h;
854 overlay->width = ov->w;
855 overlay->source_height = plane.h;
856 overlay->source_width = plane.w;
857 plane.o.push_back(overlay);
860 if(ov->cmd == BD_ARGB_OVERLAY_FLUSH)
861 OverlayFlush(ov->pts);
866 int CDVDInputStreamBluray::GetTotalTime()
869 return (int)(m_title->duration / 90);
874 int CDVDInputStreamBluray::GetTime()
876 return (int)(m_dll->bd_tell_time(m_bd) / 90);
879 bool CDVDInputStreamBluray::SeekTime(int ms)
881 if(m_dll->bd_seek_time(m_bd, ms * 90) < 0)
887 int CDVDInputStreamBluray::GetChapterCount()
890 return m_title->chapter_count;
895 int CDVDInputStreamBluray::GetChapter()
898 return m_dll->bd_get_current_chapter(m_bd) + 1;
903 bool CDVDInputStreamBluray::SeekChapter(int ch)
905 if(m_title && m_dll->bd_seek_chapter(m_bd, ch-1) < 0)
911 int64_t CDVDInputStreamBluray::Seek(int64_t offset, int whence)
913 #if LIBBLURAY_BYTESEEK
914 if(whence == SEEK_POSSIBLE)
916 else if(whence == SEEK_CUR)
919 return m_dll->bd_tell(m_bd);
921 offset += bd_tell(m_bd);
923 else if(whence == SEEK_END)
924 offset += m_dll->bd_get_title_size(m_bd);
925 else if(whence != SEEK_SET)
928 int64_t pos = m_dll->bd_seek(m_bd, offset);
931 CLog::Log(LOGERROR, "CDVDInputStreamBluray::Seek - seek to %"PRId64", failed with %"PRId64, offset, pos);
936 CLog::Log(LOGWARNING, "CDVDInputStreamBluray::Seek - seek to %"PRId64", ended at %"PRId64, offset, pos);
940 if(whence == SEEK_POSSIBLE)
946 int64_t CDVDInputStreamBluray::GetLength()
948 return m_dll->bd_get_title_size(m_bd);
951 static bool find_stream(int pid, BLURAY_STREAM_INFO *info, int count, char* language)
954 for(;i<count;i++,info++)
961 memcpy(language, info->lang, 4);
965 void CDVDInputStreamBluray::GetStreamInfo(int pid, char* language)
967 if(!m_title || m_clip >= m_title->clip_count)
970 BLURAY_CLIP_INFO *clip = m_title->clips+m_clip;
972 if(find_stream(pid, clip->audio_streams, clip->audio_stream_count, language))
974 if(find_stream(pid, clip->video_streams, clip->video_stream_count, language))
976 if(find_stream(pid, clip->pg_streams, clip->pg_stream_count, language))
978 if(find_stream(pid, clip->ig_streams, clip->ig_stream_count, language))
982 CDVDInputStream::ENextStream CDVDInputStreamBluray::NextStream()
985 return NEXTSTREAM_NONE;
987 /* process any current event */
990 /* process all queued up events */
991 while(m_dll->bd_get_event(m_bd, &m_event))
994 if(m_hold == HOLD_STILL)
995 return NEXTSTREAM_RETRY;
998 return NEXTSTREAM_OPEN;
1001 void CDVDInputStreamBluray::UserInput(bd_vk_key_e vk)
1003 if(m_bd == NULL || !m_navmode)
1005 m_dll->bd_user_input(m_bd, -1, vk);
1008 void CDVDInputStreamBluray::OnMenu()
1010 if(m_bd == NULL || !m_navmode)
1013 if(m_dll->bd_user_input(m_bd, -1, BD_VK_POPUP) >= 0)
1015 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::OnMenu - popup failed, trying root");
1017 if(m_dll->bd_user_input(m_bd, -1, BD_VK_ROOT_MENU) >= 0)
1020 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::OnMenu - root failed, trying explicit");
1021 if(m_dll->bd_menu_call(m_bd, -1) >= 0)
1023 CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::OnMenu - root failed");
1026 bool CDVDInputStreamBluray::IsInMenu()
1028 if(m_bd == NULL || !m_navmode)
1030 if(m_menu || m_planes[BD_OVERLAY_IG].o.size() > 0)
1035 void CDVDInputStreamBluray::SkipStill()
1037 if(m_bd == NULL || !m_navmode)
1040 if(m_hold == HOLD_STILL)
1043 m_dll->bd_read_skip_still(m_bd);