summaryrefslogtreecommitdiff
path: root/display.c
diff options
context:
space:
mode:
Diffstat (limited to 'display.c')
-rw-r--r--display.c210
1 files changed, 167 insertions, 43 deletions
diff --git a/display.c b/display.c
index f4f5273..7add79c 100644
--- a/display.c
+++ b/display.c
@@ -55,6 +55,7 @@ cRpiDisplay* cRpiDisplay::GetInstance(void)
tvstate.display.hdmi.width,
tvstate.display.hdmi.height,
tvstate.display.hdmi.frame_rate,
+ tvstate.display.hdmi.aspect_ratio,
tvstate.display.hdmi.scan_mode != 0,
tvstate.display.hdmi.group,
tvstate.display.hdmi.mode);
@@ -70,7 +71,7 @@ cRpiDisplay* cRpiDisplay::GetInstance(void)
DISPMANX_MODEINFO_T mode;
if (vc_dispmanx_display_get_info(display, &mode) >= 0)
s_instance = new cRpiDefaultDisplay(id,
- mode.width, mode.height);
+ mode.width, mode.height, SDTV_ASPECT_4_3);
vc_dispmanx_display_close(display);
}
@@ -78,7 +79,7 @@ cRpiDisplay* cRpiDisplay::GetInstance(void)
if (!s_instance)
{
ELOG("failed to get display information!");
- s_instance = new cRpiDefaultDisplay(id, 720, 576);
+ s_instance = new cRpiDefaultDisplay(id, 720, 576, SDTV_ASPECT_4_3);
}
}
@@ -93,11 +94,12 @@ void cRpiDisplay::DropInstance(void)
}
cRpiDisplay::cRpiDisplay(int id, int width, int height, int frameRate,
- bool interlaced, bool fixedMode) :
+ int aspectRatio, bool interlaced, bool fixedMode) :
m_id(id),
m_width(width),
m_height(height),
m_frameRate(frameRate),
+ m_aspectRatio(aspectRatio),
m_interlaced(interlaced),
m_fixedMode(fixedMode)
{
@@ -126,7 +128,19 @@ int cRpiDisplay::GetSize(int &width, int &height, double &aspect)
{
width = instance->m_width;
height = instance->m_height;
- aspect = (double)width / height;
+ switch (instance->m_aspectRatio)
+ {
+ case HDMI_ASPECT_4_3:
+ aspect = 4.0 / 3.0;
+ break;
+ case HDMI_ASPECT_16_9:
+ aspect = 16.0 / 9.0;
+ break;
+ default:
+ aspect = (double)width / height;
+ break;
+ }
+ aspect /= (double)width / height;
return 0;
}
return -1;
@@ -205,6 +219,62 @@ int cRpiDisplay::Snapshot(unsigned char* frame, int width, int height)
return -1;
}
+void cRpiDisplay::GetModeFormat(const cVideoFrameFormat *format,
+ int &modeX, int &modeY, int &aspectRatio)
+{
+ /* | Format | PAR | Mode | DAR |
+ * -------------------------------------------------------
+ * NTSC SD MPEG-2 | 720x480 | 8:9 | 720x480 | 4:3 |
+ * NTSC SD MPEG-4 | 720x480 | 10:11 | 720x480 | 4:3 |
+ * NTSC SD MPEG-2 | 720x480 | 32:27 | 720x480 | 16:9 |
+ * NTSC SD MPEG-4 | 720x480 | 40:33 | 720x480 | 16:9 |
+ * PAL SD MPEG-2 | 720x576 | 16:15 | 720x576 | 4:3 |
+ * PAL SD MPEG-4 | 720x576 | 12:11 | 720x576 | 4:3 |
+ * PAL SD MPEG-2 | 720x576 | 64:45 | 720x576 | 16:9 |
+ * PAL SD MPEG-4 | 720x576 | 16:11 | 720x576 | 16:9 |
+ * HD | 1280x720 | 1:1 | 1280x720 | 16:9 |
+ * HD | 1280x1080 | 3:2 | 1920x1080 | 16:9 |
+ * HD | 1920x1080 | 1:1 | 1920x1080 | 16:9 |
+ */
+
+ aspectRatio = HDMI_ASPECT_UNKNOWN;
+ modeY = format->height;
+
+ switch (modeY)
+ {
+ case 480:
+ if ((format->pixelWidth == 8 && format->pixelHeight == 9) ||
+ (format->pixelWidth == 10 && format->pixelHeight == 11))
+ aspectRatio = HDMI_ASPECT_4_3;
+ else if ((format->pixelWidth == 32 && format->pixelHeight == 27) ||
+ (format->pixelWidth == 40 && format->pixelHeight == 33))
+ aspectRatio = HDMI_ASPECT_16_9;
+ modeX = format->width;
+ break;
+
+ case 576:
+ if ((format->pixelWidth == 16 && format->pixelHeight == 15) ||
+ (format->pixelWidth == 12 && format->pixelHeight == 11))
+ aspectRatio = HDMI_ASPECT_4_3;
+ else if ((format->pixelWidth == 64 && format->pixelHeight == 45) ||
+ (format->pixelWidth == 16 && format->pixelHeight == 11))
+ aspectRatio = HDMI_ASPECT_16_9;
+ modeX = format->width;
+ break;
+
+ default:
+ ILOG("unknown video frame format: %dx%d@%d%s PAR(%d:%d)",
+ format->width, format->height, format->frameRate,
+ format->Interlaced() ? "i" : "p",
+ format->pixelWidth, format->pixelHeight);
+ case 720:
+ case 1080:
+ aspectRatio = HDMI_ASPECT_16_9;
+ modeX = format->width * format->pixelWidth / format->pixelHeight;
+ break;
+ }
+}
+
int cRpiDisplay::Update(const cVideoFrameFormat *frameFormat)
{
if (m_fixedMode || (
@@ -215,21 +285,49 @@ int cRpiDisplay::Update(const cVideoFrameFormat *frameFormat)
int newWidth = m_width;
int newHeight = m_height;
int newFrameRate = m_frameRate;
+ int newAspectRatio = m_aspectRatio;
bool newInterlaced = m_interlaced;
switch (cRpiSetup::GetVideoResolution())
{
- case cVideoResolution::e480: newWidth = 720; newHeight = 480; break;
- case cVideoResolution::e576: newWidth = 720; newHeight = 576; break;
- case cVideoResolution::e720: newWidth = 1280; newHeight = 720; break;
- case cVideoResolution::e1080: newWidth = 1920; newHeight = 1080; break;
+ case cVideoResolution::e480:
+ newWidth = 720;
+ newHeight = 480;
+ newAspectRatio = HDMI_ASPECT_4_3;
+ break;
+
+ case cVideoResolution::e480w:
+ newWidth = 720;
+ newHeight = 480;
+ newAspectRatio = HDMI_ASPECT_16_9;
+ break;
+
+ case cVideoResolution::e576:
+ newWidth = 720;
+ newHeight = 576;
+ newAspectRatio = HDMI_ASPECT_4_3;
+ break;
+
+ case cVideoResolution::e576w:
+ newWidth = 720;
+ newHeight = 576;
+ newAspectRatio = HDMI_ASPECT_16_9;
+ break;
+
+ case cVideoResolution::e720:
+ newWidth = 1280;
+ newHeight = 720;
+ newAspectRatio = HDMI_ASPECT_16_9;
+ break;
+
+ case cVideoResolution::e1080:
+ newWidth = 1920;
+ newHeight = 1080;
+ newAspectRatio = HDMI_ASPECT_16_9;
+ break;
case cVideoResolution::eFollowVideo:
- if (frameFormat->width && frameFormat->height)
- {
- newWidth = frameFormat->width;
- newHeight = frameFormat->height;
- }
+ GetModeFormat(frameFormat, newWidth, newHeight, newAspectRatio);
break;
default:
@@ -262,13 +360,26 @@ int cRpiDisplay::Update(const cVideoFrameFormat *frameFormat)
// set new mode only if necessary
if (newWidth != m_width || newHeight != m_height ||
- newFrameRate != m_frameRate || newInterlaced != m_interlaced)
- return SetMode(newWidth, newHeight, newFrameRate,
+ newFrameRate != m_frameRate || newInterlaced != m_interlaced ||
+ newAspectRatio != m_aspectRatio)
+ return SetMode(newWidth, newHeight, newFrameRate, newAspectRatio,
newInterlaced ? frameFormat->scanMode : cScanMode::eProgressive);
return 0;
}
+const char* cRpiDisplay::AspectRatioStr(int aspectRatio)
+{
+ return aspectRatio == HDMI_ASPECT_4_3 ? "4:3" :
+ aspectRatio == HDMI_ASPECT_14_9 ? "14:9" :
+ aspectRatio == HDMI_ASPECT_16_9 ? "16:9" :
+ aspectRatio == HDMI_ASPECT_5_4 ? "5:4" :
+ aspectRatio == HDMI_ASPECT_16_10 ? "16:10" :
+ aspectRatio == HDMI_ASPECT_15_9 ? "15:9" :
+ aspectRatio == HDMI_ASPECT_64_27 ? "64:27" :
+ aspectRatio == HDMI_ASPECT_21_9 ? "21:9" : "unknown";
+}
+
/* ------------------------------------------------------------------------- */
#define HDMI_MAX_MODES 64
@@ -281,8 +392,8 @@ public:
};
cRpiHDMIDisplay::cRpiHDMIDisplay(int id, int width, int height, int frameRate,
- bool interlaced, int group, int mode) :
- cRpiDisplay(id, width, height, frameRate, interlaced, false),
+ int aspectRatio, bool interlaced, int group, int mode) :
+ cRpiDisplay(id, width, height, frameRate, aspectRatio, interlaced, false),
m_modes(new cRpiHDMIDisplay::ModeList()),
m_group(group),
m_mode(mode),
@@ -304,7 +415,7 @@ cRpiHDMIDisplay::cRpiHDMIDisplay(int id, int width, int height, int frameRate,
DLOG("supported HDMI modes:");
for (int i = 0; i < m_modes->nModes; i++)
{
- DLOG("%s[%02d]: %4dx%4d@%2d%s | %s | %3d.%03dMHz%s%s",
+ DLOG("%s[%02d]: %4dx%4d@%2d%s | %*s | %3d.%03dMHz%s%s",
m_modes->modes[i].group == HDMI_RES_GROUP_CEA ? "CEA" :
m_modes->modes[i].group == HDMI_RES_GROUP_DMT ? "DMT" : "---",
m_modes->modes[i].code,
@@ -312,14 +423,7 @@ cRpiHDMIDisplay::cRpiHDMIDisplay(int id, int width, int height, int frameRate,
m_modes->modes[i].height,
m_modes->modes[i].frame_rate,
m_modes->modes[i].scan_mode ? "i" : "p",
- m_modes->modes[i].aspect_ratio == HDMI_ASPECT_4_3 ? " 4:3 " :
- m_modes->modes[i].aspect_ratio == HDMI_ASPECT_14_9 ? "14:9 " :
- m_modes->modes[i].aspect_ratio == HDMI_ASPECT_16_9 ? "16:9 " :
- m_modes->modes[i].aspect_ratio == HDMI_ASPECT_5_4 ? " 5:4 " :
- m_modes->modes[i].aspect_ratio == HDMI_ASPECT_16_10 ? "16:10" :
- m_modes->modes[i].aspect_ratio == HDMI_ASPECT_15_9 ? "15:9 " :
- m_modes->modes[i].aspect_ratio == HDMI_ASPECT_21_9 ? "21:9 " :
- "unknown aspect ratio",
+ 5, AspectRatioStr(m_modes->modes[i].aspect_ratio),
m_modes->modes[i].pixel_freq / 1000000,
m_modes->modes[i].pixel_freq % 1000000 / 1000,
m_modes->modes[i].native ? " (native)" : "",
@@ -354,31 +458,50 @@ cRpiHDMIDisplay::~cRpiHDMIDisplay()
}
int cRpiHDMIDisplay::SetMode(int width, int height, int frameRate,
- cScanMode::eMode scanMode)
+ int aspectRatio, cScanMode::eMode scanMode)
{
SetHvsSyncUpdate(scanMode);
- bool interlaced = cScanMode::Interlaced(scanMode);
+ int interlaced = cScanMode::Interlaced(scanMode) ? 1 : 0;
+ int mode = -1, altMode = -1;
- for (int i = 0; i < m_modes->nModes; i++)
+ for (int i = 0; i < m_modes->nModes && mode == -1; i++)
{
if (m_modes->modes[i].width == width &&
m_modes->modes[i].height == height &&
m_modes->modes[i].frame_rate == frameRate &&
+ m_modes->modes[i].aspect_ratio == aspectRatio &&
m_modes->modes[i].scan_mode == interlaced)
- {
- DLOG("setting HDMI mode to %dx%d@%2d%s", width, height,
- frameRate, interlaced ? "i" : "p");
-
- m_width = width;
- m_height = height;
- m_frameRate = frameRate;
- m_interlaced = interlaced;
- return SetMode(m_modes->modes[i].group, m_modes->modes[i].code);
- }
+ mode = i;
+
+ else if (m_modes->modes[i].height == height &&
+ m_modes->modes[i].frame_rate == frameRate &&
+ m_modes->modes[i].aspect_ratio == aspectRatio &&
+ m_modes->modes[i].scan_mode == interlaced)
+ altMode = i;
+ }
+
+ if (mode == -1 && altMode != -1)
+ mode = altMode;
+
+ if (mode != -1)
+ {
+ m_width = m_modes->modes[mode].width;
+ m_height = m_modes->modes[mode].height;
+ m_frameRate = m_modes->modes[mode].frame_rate;
+ m_aspectRatio = m_modes->modes[mode].aspect_ratio;
+ m_interlaced = m_modes->modes[mode].scan_mode;
+
+ DLOG("setting HDMI mode to %dx%d@%2d%s (%s)", m_width, m_height,
+ m_frameRate, m_interlaced ? "i" : "p",
+ AspectRatioStr(m_aspectRatio));
+
+ return SetMode(m_modes->modes[mode].group, m_modes->modes[mode].code);
}
- DLOG("failed to set HDMI mode to %dx%d@%2d%s",
- width, height, frameRate, interlaced ? "i" : "p");
+ DLOG("failed to set HDMI mode to %dx%d@%2d%s (%s)",
+ width, height, frameRate, interlaced ? "i" : "p",
+ AspectRatioStr(aspectRatio));
+
return -1;
}
@@ -414,7 +537,8 @@ void cRpiHDMIDisplay::TvServiceCallback(void *data, unsigned int reason,
/* ------------------------------------------------------------------------- */
-cRpiDefaultDisplay::cRpiDefaultDisplay(int id, int width, int height) :
- cRpiDisplay(id, width, height, 50, false, true)
+cRpiDefaultDisplay::cRpiDefaultDisplay(int id, int width, int height,
+ int aspectRatio) :
+ cRpiDisplay(id, width, height, 50, aspectRatio, false, true)
{
}