aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Morten Kvarving <spiff@xbmc.org>2012-11-13 01:06:08 -0800
committerArne Morten Kvarving <spiff@xbmc.org>2012-11-13 01:06:08 -0800
commit26b23a33cf884a68061c686a0d8c50da0ea2edfd (patch)
treeb675074e6cced783263f9dc3e1b9fc4159b1250d
parenta09559ecc0dcb3bd576fe006d874be3e1b15560a (diff)
parentc5645ec27dd96531a659fd050efd33c9f6c50b25 (diff)
Merge pull request #1769 from elupus/blumenu
dvdplayer: fixed several issues with overlay handling on bluray
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlay.h8
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayImage.h36
-rw-r--r--xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp159
-rw-r--r--xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.h21
4 files changed, 137 insertions, 87 deletions
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlay.h b/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlay.h
index 66def5df40..cb4d5ca17e 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlay.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlay.h
@@ -93,6 +93,14 @@ public:
return count;
}
+ /**
+ * static release function for use with boost shared ptr for example
+ */
+ static void Release(CDVDOverlay* ov)
+ {
+ ov->Release();
+ }
+
bool IsOverlayType(DVDOverlayType type) { return (m_type == type); }
double iPTSStartTime;
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayImage.h b/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayImage.h
index 2f3553eef3..d205c8a778 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayImage.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayImage.h
@@ -61,12 +61,48 @@ public:
}
+ CDVDOverlayImage(const CDVDOverlayImage& src, int sub_x, int sub_y, int sub_w, int sub_h)
+ : CDVDOverlay(src)
+ {
+ palette = (uint32_t*)malloc(src.palette_colors * 4);
+ memcpy(palette, src.palette, src.palette_colors * 4);
+
+ palette_colors = src.palette_colors;
+ linesize = sub_w;
+ x = sub_x;
+ y = sub_y;
+ width = sub_w;
+ height = sub_h;
+ source_width = src.source_width;
+ source_height = src.source_height;
+
+ data = (BYTE*)malloc(height*linesize);
+
+ BYTE* s = src.data_at(sub_x, sub_y);
+ BYTE* t = data;
+
+ for(int row = 0;row < sub_h; ++row)
+ {
+ memcpy(t, s, width);
+ s += src.linesize;
+ t += linesize;
+ }
+
+ SAFE_RELEASE(m_overlay);
+ }
+
~CDVDOverlayImage()
{
if(data) free(data);
if(palette) free(palette);
}
+ BYTE* data_at(int sub_x, int sub_y) const
+ {
+ return &data[(sub_y - y)*linesize +
+ (sub_x - x)];
+ }
+
BYTE* data;
int linesize;
diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp
index f745fa7a08..ddf213579a 100644
--- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp
+++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp
@@ -32,6 +32,7 @@
#include "filesystem/Directory.h"
#include "DllLibbluray.h"
#include "URL.h"
+#include "Geometry.h"
#define LIBBLURAY_BYTESEEK 0
@@ -627,109 +628,85 @@ static uint32_t build_rgba(const BD_PG_PALETTE_ENTRY &e)
void CDVDInputStreamBluray::OverlayCallback(const BD_OVERLAY * const ov)
{
-
- CDVDOverlayGroup* group = new CDVDOverlayGroup();
- group->bForced = true;
-
- if(ov == NULL)
+#if(BD_OVERLAY_INTERFACE_VERSION >= 2)
+ if(ov == NULL || ov->cmd == BD_OVERLAY_CLOSE)
{
for(unsigned i = 0; i < 2; ++i)
- {
- for(std::vector<CDVDOverlayImage*>::iterator it = m_overlays[i].begin(); it != m_overlays[i].end(); ++it)
- (*it)->Release();
- m_overlays[i].clear();
- }
-
+ m_planes[i].o.clear();
+ CDVDOverlayGroup* group = new CDVDOverlayGroup();
+ group->bForced = true;
m_player->OnDVDNavResult(group, 0);
return;
}
- group->iPTSStartTime = (double) ov->pts;
- group->iPTSStopTime = 0;
-
if (ov->plane > 1)
{
CLog::Log(LOGWARNING, "CDVDInputStreamBluray - Ignoring overlay with multiple planes");
- group->Release();
return;
}
- std::vector<CDVDOverlayImage*>& plane(m_overlays[ov->plane]);
+ SPlane& plane(m_planes[ov->plane]);
- /* fixup existing overlays */
- for(std::vector<CDVDOverlayImage*>::iterator it = plane.begin(); it != plane.end();)
+ if (ov->cmd == BD_OVERLAY_CLEAR)
{
- /* 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;
- }
+ plane.o.clear();
+ return;
+ }
- int y1 = std::max<int>((*it)->y , ov->y);
- int y2 = std::min<int>((*it)->y + (*it)->height, ov->y + ov->h);
- int x1 = std::max<int>((*it)->x , ov->x);
- int x2 = std::min<int>((*it)->x + (*it)->width , ov->x + ov->w);
+ if (ov->cmd == BD_OVERLAY_INIT)
+ {
+ plane.o.clear();
+ plane.w = ov->w;
+ plane.h = ov->h;
+ return;
+ }
- /* 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 (ov->cmd == BD_OVERLAY_DRAW
+ || ov->cmd == BD_OVERLAY_WIPE)
+ {
+ CRect ovr(ov->x
+ , ov->y
+ , ov->x + ov->w
+ , ov->y + ov->h);
- if(transp == overlay->palette_colors)
+ /* fixup existing overlays */
+ for(SOverlays::iterator it = plane.o.begin(); it != plane.o.end();)
{
- CLog::Log(LOGERROR, "CDVDInputStreamBluray - failed to find transparent color");
- continue;
- }
+ CRect old((*it)->x
+ , (*it)->y
+ , (*it)->x + (*it)->width
+ , (*it)->y + (*it)->height);
- for(int y = y1; y < y2; ++y)
- {
- BYTE* line = overlay->data + y * overlay->linesize;
- for(int x = x1; x < x2; ++x)
- line[x] = transp;
+ vector<CRect> rem = old.SubtractRect(ovr);
+
+ /* if no overlap we are done */
+ if(rem.size() == 1 && !(rem[0] != old))
+ {
+ it++;
+ continue;
+ }
+
+ SOverlays add;
+ for(vector<CRect>::iterator itr = rem.begin(); itr != rem.end(); ++itr)
+ {
+ SOverlay overlay(new CDVDOverlayImage(*(*it)
+ , itr->x1
+ , itr->y1
+ , itr->Width()
+ , itr->Height())
+ , std::ptr_fun(CDVDOverlay::Release));
+ add.push_back(overlay);
+ }
+
+ it = plane.o.erase(it);
+ plane.o.insert(it, add.begin(), add.end());
}
- ++it;
-#endif
}
-
/* uncompress and draw bitmap */
- if (ov->img)
+ if (ov->img && ov->cmd == BD_OVERLAY_DRAW)
{
- CDVDOverlayImage* overlay = new CDVDOverlayImage();
+ SOverlay overlay(new CDVDOverlayImage(), std::ptr_fun(CDVDOverlay::Release));
if (ov->palette)
{
@@ -754,15 +731,27 @@ void CDVDInputStreamBluray::OverlayCallback(const BD_OVERLAY * const ov)
overlay->y = ov->y;
overlay->height = ov->h;
overlay->width = ov->w;
- plane.push_back(overlay);
+ overlay->source_height = plane.h;
+ overlay->source_width = plane.w;
+ plane.o.push_back(overlay);
}
- for(unsigned i = 0; i < 2; ++i)
+ if(ov->cmd == BD_OVERLAY_FLUSH)
{
- for(std::vector<CDVDOverlayImage*>::iterator it = m_overlays[i].begin(); it != m_overlays[i].end(); ++it)
- group->m_overlays.push_back((*it)->Acquire());
+ CDVDOverlayGroup* group = new CDVDOverlayGroup();
+ group->bForced = true;
+ group->iPTSStartTime = (double) ov->pts;
+ group->iPTSStopTime = 0;
+
+ for(unsigned i = 0; i < 2; ++i)
+ {
+ for(SOverlays::iterator it = m_planes[i].o.begin(); it != m_planes[i].o.end(); ++it)
+ group->m_overlays.push_back((*it)->Acquire());
+ }
+
+ m_player->OnDVDNavResult(group, 0);
}
- m_player->OnDVDNavResult(group, 0);
+#endif
}
int CDVDInputStreamBluray::GetTotalTime()
@@ -928,7 +917,7 @@ bool CDVDInputStreamBluray::IsInMenu()
{
if(m_bd == NULL || !m_navmode)
return false;
- if(m_overlays[BD_OVERLAY_IG].size() > 0)
+ if(m_planes[BD_OVERLAY_IG].o.size() > 0)
return true;
return false;
}
diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.h b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.h
index a6dbf19f58..6897d0f459 100644
--- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.h
+++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.h
@@ -21,7 +21,8 @@
*/
#include "DVDInputStream.h"
-
+#include <list>
+#include <boost/shared_ptr.hpp>
extern "C"
{
@@ -107,7 +108,23 @@ protected:
bool m_title_playing;
uint32_t m_clip;
bool m_navmode;
- std::vector<CDVDOverlayImage*> m_overlays[2];
+
+ typedef boost::shared_ptr<CDVDOverlayImage> SOverlay;
+ typedef std::list<SOverlay> SOverlays;
+
+ struct SPlane
+ {
+ SOverlays o;
+ int w;
+ int h;
+
+ SPlane()
+ : w(0)
+ , h(0)
+ {}
+ };
+
+ SPlane m_planes[2];
enum EHoldState {
HOLD_NONE = 0,
HOLD_HELD,