Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add bluray OSD menu support (HDMV only).

There are a number of outstanding issues:-

- the RLE decoding of certain images is still not quite correct, so
there are a few image errors.
- certain OSD optimisations are disabled for the menus due to the way we
receive the images (individually rather than as a set).
- there is currently no mechanism for removing duplicate images. So
until a reset is triggered by the bd object, some menus are continually
overpainted with the same, duplicated image.
  • Loading branch information...
commit 5479b3af7afa85b23ac41ab4c986e75919c9b220 1 parent 3526655
Mark Kendall authored
View
135 mythtv/libs/libmythtv/bdringbuffer.cpp
@@ -24,66 +24,14 @@ static void HandleOverlayCallback(
void *data, const bd_overlay_s * const overlay)
{
BDRingBuffer *bdrb = (BDRingBuffer*) data;
-
- if (!bdrb)
- return;
-
- if (!overlay || overlay->plane == 1)
- bdrb->m_inMenu = false;
-
- if (!overlay || !overlay->img)
- return;
-
- bdrb->m_inMenu = true;
-
- const BD_PG_RLE_ELEM *rlep = overlay->img;
-
- uint8_t *yuvimg = (uint8_t*)malloc(overlay->w * overlay->h);
- unsigned pixels = overlay->w * overlay->h;
-
- for (unsigned i = 0; i < pixels; i += rlep->len, rlep++)
- {
- memset(yuvimg + i, rlep->color, rlep->len);
- }
-
- QImage qoverlay(yuvimg, overlay->w, overlay->h, QImage::Format_Indexed8);
-
- uint32_t *origpalette = (uint32_t *)(overlay->palette);
- QVector<unsigned int> palette;
- for (int i = 0; i < 256; i++)
- {
- int y = (origpalette[i] >> 0) & 0xff;
- int cr = (origpalette[i] >> 8) & 0xff;
- int cb = (origpalette[i] >> 16) & 0xff;
- int a = (origpalette[i] >> 24) & 0xff;
- int r = int(y + 1.4022 * (cr - 128));
- int b = int(y + 1.7710 * (cb - 128));
- int g = int(1.7047 * y - (0.1952 * b) - (0.5647 * r));
- if (r < 0) r = 0;
- if (g < 0) g = 0;
- if (b < 0) b = 0;
- if (r > 0xff) r = 0xff;
- if (g > 0xff) g = 0xff;
- if (b > 0xff) b = 0xff;
- palette.push_back((a << 24) | (r << 16) | (g << 8) | b);
- }
-
- qoverlay.setColorTable(palette);
- qoverlay.save(QString("%1/bluray.menuimg.%2.%3.jpg").arg(QDir::home().path()).arg(overlay->w).arg(overlay->h));
-
- VERBOSE(VB_PLAYBACK|VB_EXTRA, QString("In Menu Callback, ready to draw "
- "an overlay of %1x%2 at %3,%4 (%5 pixels).")
- .arg(overlay->w).arg(overlay->h).arg(overlay->x)
- .arg(overlay->y).arg(pixels));
-
- if (overlay->plane == 1)
- bdrb->m_inMenu = true;
+ if (bdrb)
+ bdrb->SubmitOverlay(overlay);
}
BDRingBuffer::BDRingBuffer(const QString &lfilename)
: bdnav(NULL), m_is_hdmv_navigation(false),
m_numTitles(0), m_titleChanged(false), m_playerWait(false),
- m_ignorePlayerWait(true)
+ m_ignorePlayerWait(true), m_overlayCleared(false)
{
OpenFile(lfilename);
}
@@ -102,6 +50,8 @@ void BDRingBuffer::close(void)
bd_close(bdnav);
bdnav = NULL;
}
+
+ ClearOverlays();
}
long long BDRingBuffer::Seek(long long pos, int whence, bool has_lock)
@@ -839,3 +789,78 @@ bool BDRingBuffer::StartFromBeginning(void)
return true;
}
+void BDRingBuffer::ClearOverlays(void)
+{
+ QMutexLocker lock(&m_overlayLock);
+
+ while (!m_overlayImages.isEmpty())
+ {
+ BDOverlay *img = m_overlayImages.takeFirst();
+ delete img->m_data;
+ delete img->m_palette;
+ delete img;
+ }
+ OverlayCleared(false);
+}
+
+BDOverlay* BDRingBuffer::GetOverlay(void)
+{
+ QMutexLocker lock(&m_overlayLock);
+ if (!m_overlayImages.isEmpty())
+ return m_overlayImages.takeFirst();
+ return NULL;
+}
+
+void BDRingBuffer::SubmitOverlay(const bd_overlay_s * const overlay)
+{
+ QMutexLocker lock(&m_overlayLock);
+
+ if (!overlay || overlay->plane == 1)
+ m_inMenu = false;
+
+ if (!overlay || !overlay->img)
+ {
+ VERBOSE(VB_PLAYBACK, LOC + "Null overlay submitted.");
+ OverlayCleared(true);
+ return;
+ }
+
+ VERBOSE(VB_PLAYBACK, LOC + QString("New overlay image %1x%2 %3+%4")
+ .arg(overlay->w).arg(overlay->h)
+ .arg(overlay->x).arg(overlay->y));
+ m_inMenu = true;
+
+ const BD_PG_RLE_ELEM *rlep = overlay->img;
+ static const unsigned palettesize = 256 * 4;
+ unsigned width = (overlay->w + 0x3) & (~0x3);
+ unsigned pixels = width * overlay->h;
+ unsigned actual = overlay->w * overlay->h;
+ uint8_t *data = (uint8_t*)malloc(pixels);
+ uint8_t *palette = (uint8_t*)malloc(palettesize);
+ memset(data, 0, pixels);
+
+ int line = 0;
+ int this_line = 0;
+ for (unsigned i = 0; i < actual; i += rlep->len, rlep++)
+ {
+ if ((rlep->color == 0 && rlep->len == 0) || this_line >= overlay->w)
+ {
+ this_line = 0;
+ line++;
+ i = (line * width) + 1;
+ }
+ else
+ {
+ this_line += rlep->len;
+ memset(data + i, rlep->color, rlep->len);
+ }
+ }
+
+ memcpy(palette, overlay->palette, palettesize);
+
+ QRect pos(overlay->x, overlay->y, width, overlay->h);
+ m_overlayImages.append(new BDOverlay(data, palette, pos));
+
+ if (overlay->plane == 1)
+ m_inMenu = true;
+}
View
23 mythtv/libs/libmythtv/bdringbuffer.h
@@ -4,6 +4,7 @@
#define BD_BLOCK_SIZE 6144LL
#include <QString>
+#include <QRect>
#include "libmythbluray/bluray.h"
#include "libmythbluray/keys.h"
@@ -17,6 +18,17 @@
* A class to allow a RingBuffer to read from BDs.
*/
+class BDOverlay
+{
+ public:
+ BDOverlay(uint8_t *data, uint8_t *palette, QRect position)
+ : m_data(data), m_palette(palette), m_position(position) { }
+
+ uint8_t *m_data;
+ uint8_t *m_palette;
+ QRect m_position;
+};
+
class MPUBLIC BDRingBuffer : public RingBuffer
{
public:
@@ -29,6 +41,13 @@ class MPUBLIC BDRingBuffer : public RingBuffer
void IgnoreWaitStates(bool ignore) { m_ignorePlayerWait = ignore; }
bool StartFromBeginning(void);
+ void ClearOverlays(void);
+ BDOverlay* GetOverlay(void);
+ void SubmitOverlay(const bd_overlay_s * const overlay);
+ bool OverlayCleared(void) { return m_overlayCleared; }
+ void OverlayCleared(bool cleared) { m_overlayCleared = cleared; }
+
+
uint32_t GetNumTitles(void) const { return m_numTitles; }
int GetCurrentTitle(void) const;
uint64_t GetCurrentAngle(void) const { return m_currentAngle; }
@@ -116,6 +135,10 @@ class MPUBLIC BDRingBuffer : public RingBuffer
bool m_playerWait;
bool m_ignorePlayerWait;
+ QMutex m_overlayLock;
+ QList<BDOverlay*> m_overlayImages;
+ bool m_overlayCleared;
+
public:
uint8_t m_still;
volatile bool m_inMenu;
View
38 mythtv/libs/libmythtv/mythbdplayer.cpp
@@ -4,10 +4,46 @@
#define LOC QString("BDPlayer: ")
#define LOC_ERR QString("BDPlayer error: ")
-MythBDPlayer::MythBDPlayer(bool muted) : MythPlayer(muted)
+MythBDPlayer::MythBDPlayer(bool muted) : MythPlayer(muted), m_inMenu(false)
{
}
+void MythBDPlayer::PreProcessNormalFrame(void)
+{
+ DisplayMenu();
+}
+
+void MythBDPlayer::DisplayMenu(void)
+{
+ if (!player_ctx->buffer->IsBD())
+ return;
+
+ if (!player_ctx->buffer->BD()->IsInMenu())
+ {
+ if (m_inMenu)
+ {
+ m_inMenu = false;
+ player_ctx->buffer->BD()->ClearOverlays();
+ SetCaptionsEnabled(false, false);
+ osd->ClearSubtitles();
+ }
+ return;
+ }
+
+ if (player_ctx->buffer->BD()->OverlayCleared())
+ {
+ osd->ClearSubtitles();
+ player_ctx->buffer->BD()->OverlayCleared(false);
+ }
+
+ BDOverlay *overlay = NULL;
+ while (NULL != (overlay = player_ctx->buffer->BD()->GetOverlay()))
+ {
+ m_inMenu = true;
+ osd->DisplayBDOverlay(overlay);
+ }
+}
+
bool MythBDPlayer::VideoLoop(void)
{
if (!player_ctx->buffer->IsBD())
View
6 mythtv/libs/libmythtv/mythbdplayer.h
@@ -29,6 +29,12 @@ class MythBDPlayer : public MythPlayer
protected:
// Playback
virtual bool VideoLoop(void);
+ virtual void PreProcessNormalFrame(void);
+
+ private:
+ void DisplayMenu(void);
+
+ bool m_inMenu;
};
#endif // MYTHBDPLAYER_H
View
1  mythtv/libs/libmythtv/mythplayer.cpp
@@ -1275,6 +1275,7 @@ void MythPlayer::ResetCaptions(void)
(textDisplayMode & kDisplayTextSubtitle) ||
(textDisplayMode & kDisplayRawTextSubtitle) ||
(textDisplayMode & kDisplayDVDButton) ||
+ (textDisplayMode & kDisplayBDOverlay) ||
(textDisplayMode & kDisplayCC608) ||
(textDisplayMode & kDisplayCC708)))
{
View
5 mythtv/libs/libmythtv/mythplayer.h
@@ -76,8 +76,9 @@ enum
kDisplayTextSubtitle = 0x020,
kDisplayDVDButton = 0x040,
kDisplayRawTextSubtitle = 0x080,
- kDisplayAllCaptions = 0x0ff,
- kDisplayTeletextMenu = 0x100,
+ kDisplayBDOverlay = 0x0ff,
+ kDisplayAllCaptions = 0x100,
+ kDisplayTeletextMenu = 0x200,
};
class DecoderThread : public QThread
View
13 mythtv/libs/libmythtv/osd.cpp
@@ -17,6 +17,7 @@
#include "mythuistatetype.h"
// libmythtv
+#include "bdringbuffer.h"
#include "channelutil.h"
#include "teletextscreen.h"
#include "subtitlescreen.h"
@@ -1147,3 +1148,15 @@ void OSD::DisplayDVDButton(AVSubtitle* dvdButton, QRect &pos)
sub->DisplayDVDButton(dvdButton, pos);
}
}
+
+void OSD::DisplayBDOverlay(BDOverlay* overlay)
+{
+ SubtitleScreen* sub = InitSubtitles();
+ if (sub && overlay)
+ {
+ // this ensures we don't delete existing items
+ if (sub->EnabledSubtitleType() != kDisplayBDOverlay)
+ EnableSubtitles(kDisplayBDOverlay);
+ sub->DisplayBDOverlay(overlay);
+ }
+}
View
2  mythtv/libs/libmythtv/osd.h
@@ -27,6 +27,7 @@ class MythPlayer;
class TeletextScreen;
class SubtitleScreen;
struct AVSubtitle;
+class BDOverlay;
enum OSDFunctionalType
{
@@ -173,6 +174,7 @@ class OSD
void EnableSubtitles(int type);
void ClearSubtitles(void);
void DisplayDVDButton(AVSubtitle* dvdButton, QRect &pos);
+ void DisplayBDOverlay(BDOverlay *overlay);
private:
void TearDown(void);
View
54 mythtv/libs/libmythtv/subtitlescreen.cpp
@@ -7,6 +7,7 @@
#include "mythuiimage.h"
#include "mythpainter.h"
#include "subtitlescreen.h"
+#include "bdringbuffer.h"
#define LOC QString("Subtitles: ")
#define LOC_WARN QString("Subtitles Warning: ")
@@ -550,6 +551,59 @@ void SubtitleScreen::DisplayDVDButton(AVSubtitle* dvdButton, QRect &buttonPos)
AddScaledImage(fg_image, button);
}
+void SubtitleScreen::DisplayBDOverlay(BDOverlay *overlay)
+{
+ if (!overlay || !m_player)
+ return;
+
+ VideoOutput *vo = m_player->getVideoOutput();
+ if (!vo)
+ return;
+
+ // set the screen area
+ float tmp = 0.0;
+ QRect dummy;
+ vo->GetOSDBounds(dummy, m_safeArea, tmp, tmp, tmp);
+
+ // convert the palette to ARGB
+ uint32_t *origpalette = (uint32_t *)(overlay->m_palette);
+ QVector<unsigned int> palette;
+ for (int i = 0; i < 256; i++)
+ {
+ int y = (origpalette[i] >> 0) & 0xff;
+ int cr = (origpalette[i] >> 8) & 0xff;
+ int cb = (origpalette[i] >> 16) & 0xff;
+ int a = (origpalette[i] >> 24) & 0xff;
+ int r = int(y + 1.4022 * (cr - 128));
+ int b = int(y + 1.7710 * (cb - 128));
+ int g = int(1.7047 * y - (0.1952 * b) - (0.5647 * r));
+ if (r < 0) r = 0;
+ if (g < 0) g = 0;
+ if (b < 0) b = 0;
+ if (r > 0xff) r = 0xff;
+ if (g > 0xff) g = 0xff;
+ if (b > 0xff) b = 0xff;
+ palette.push_back((a << 24) | (r << 16) | (g << 8) | b);
+ }
+
+ // convert the image to QImage
+ QImage img(overlay->m_position.size(), QImage::Format_Indexed8);
+ memcpy(img.bits(), overlay->m_data,
+ overlay->m_position.width() * overlay->m_position.height());
+ img.setColorTable(palette);
+ QImage converted = img.convertToFormat(QImage::Format_ARGB32);
+
+ // add to screen
+ AddScaledImage(converted, overlay->m_position);
+ SetRedraw();
+ m_refreshArea = false; // N.B. this disables some optimisations
+
+ // release the overlay
+ delete overlay->m_data;
+ delete overlay->m_palette;
+ delete overlay;
+}
+
void SubtitleScreen::DisplayCC608Subtitles(void)
{
static const QColor clr[8] =
View
4 mythtv/libs/libmythtv/subtitlescreen.h
@@ -17,12 +17,14 @@ class SubtitleScreen : public MythScreenType
virtual ~SubtitleScreen();
void EnableSubtitles(int type);
+ int EnabledSubtitleType(void) { return m_subtitleType; }
void ClearAllSubtitles(void);
void ClearNonDisplayedSubtitles(void);
void ClearDisplayedSubtitles(void);
void ExpireSubtitles(void);
void DisplayDVDButton(AVSubtitle* dvdButton, QRect &buttonPos);
+ void DisplayBDOverlay(BDOverlay* overlay);
// MythScreenType methods
virtual bool Create(void);
@@ -44,7 +46,7 @@ class SubtitleScreen : public MythScreenType
float aspect, vector<CC708String*> &list);
MythFontProperties* Get708Font(CC708CharacterAttribute attr);
- MythPlayer *m_player;
+ MythPlayer *m_player;
SubtitleReader *m_subreader;
CC608Reader *m_608reader;
CC708Reader *m_708reader;
Please sign in to comment.
Something went wrong with that request. Please try again.