summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Reufer <thomas@reufer.ch>2015-08-14 14:19:33 +0200
committerThomas Reufer <thomas@reufer.ch>2015-08-14 14:19:33 +0200
commit6192a97d75f9a5049774f4ee024d09a7dfb45fce (patch)
tree4eb7d8efe2affaa394a6896831f8560c35c3f40a
parentdf3e781fa0365e0359d04111502473d861f80b8c (diff)
downloadvdr-plugin-rpihddevice-6192a97d75f9a5049774f4ee024d09a7dfb45fce.tar.gz
vdr-plugin-rpihddevice-6192a97d75f9a5049774f4ee024d09a7dfb45fce.tar.bz2
reworked video frame format handling
-rw-r--r--display.c35
-rw-r--r--display.h18
-rw-r--r--omx.c65
-rw-r--r--omx.h16
-rw-r--r--omxdevice.c27
-rw-r--r--tools.h38
6 files changed, 111 insertions, 88 deletions
diff --git a/display.c b/display.c
index b15e259..d44837e 100644
--- a/display.c
+++ b/display.c
@@ -55,7 +55,7 @@ cRpiDisplay* cRpiDisplay::GetInstance(void)
void cRpiDisplay::DropInstance(void)
{
- SetSyncField(0);
+ SetHvsSyncUpdate(cScanMode::eProgressive);
delete s_instance;
s_instance = 0;
}
@@ -99,20 +99,21 @@ int cRpiDisplay::GetSize(int &width, int &height, double &aspect)
return -1;
}
-int cRpiDisplay::SetVideoFormat(int width, int height, int frameRate,
- bool interlaced)
+int cRpiDisplay::SetVideoFormat(const cVideoFrameFormat *frameFormat)
{
cRpiDisplay* instance = GetInstance();
if (instance)
- return instance->Update(width, height, frameRate, interlaced);
+ return instance->Update(frameFormat);
return -1;
}
-int cRpiDisplay::SetSyncField(int field)
+int cRpiDisplay::SetHvsSyncUpdate(cScanMode::eMode scanMode)
{
char response[64];
- return vc_gencmd(response, sizeof(response), "hvs_update_fields %d", field);
+ return vc_gencmd(response, sizeof(response), "hvs_update_fields %d",
+ scanMode == cScanMode::eTopFieldFirst ? 1 :
+ scanMode == cScanMode::eBottomFieldFirst ? 2 : 0);
}
cRpiVideoPort::ePort cRpiDisplay::GetVideoPort(void)
@@ -161,7 +162,7 @@ int cRpiDisplay::Snapshot(unsigned char* frame, int width, int height)
return -1;
}
-int cRpiDisplay::Update(int width, int height, int frameRate, bool interlaced)
+int cRpiDisplay::Update(const cVideoFrameFormat *frameFormat)
{
if (cRpiSetup::GetVideoResolution() == cVideoResolution::eDontChange &&
cRpiSetup::GetVideoFrameRate() == cVideoFrameRate::eDontChange)
@@ -180,10 +181,10 @@ int cRpiDisplay::Update(int width, int height, int frameRate, bool interlaced)
case cVideoResolution::e1080: newWidth = 1920; newHeight = 1080; break;
case cVideoResolution::eFollowVideo:
- if (width && height)
+ if (frameFormat->width && frameFormat->height)
{
- newWidth = width;
- newHeight = height;
+ newWidth = frameFormat->width;
+ newHeight = frameFormat->height;
}
break;
@@ -203,10 +204,10 @@ int cRpiDisplay::Update(int width, int height, int frameRate, bool interlaced)
case cVideoFrameRate::e60p: newFrameRate = 60; newInterlaced = false; break;
case cVideoFrameRate::eFollowVideo:
- if (frameRate)
+ if (frameFormat->frameRate)
{
- newFrameRate = frameRate;
- newInterlaced = interlaced;
+ newFrameRate = frameFormat->frameRate;
+ newInterlaced = frameFormat->Interlaced();
}
break;
@@ -218,7 +219,8 @@ int cRpiDisplay::Update(int width, int height, int frameRate, bool interlaced)
// set new mode only if necessary
if (newWidth != m_width || newHeight != m_height ||
newFrameRate != m_frameRate || newInterlaced != m_interlaced)
- return SetMode(newWidth, newHeight, newFrameRate, newInterlaced);
+ return SetMode(newWidth, newHeight, newFrameRate,
+ newInterlaced ? frameFormat->scanMode : cScanMode::eProgressive);
return 0;
}
@@ -308,8 +310,11 @@ cRpiHDMIDisplay::~cRpiHDMIDisplay()
}
int cRpiHDMIDisplay::SetMode(int width, int height, int frameRate,
- bool interlaced)
+ cScanMode::eMode scanMode)
{
+ SetHvsSyncUpdate(scanMode);
+ bool interlaced = cScanMode::Interlaced(scanMode);
+
for (int i = 0; i < m_modes->nModes; i++)
{
if (m_modes->modes[i].width == width &&
diff --git a/display.h b/display.h
index 4388d13..5af4e02 100644
--- a/display.h
+++ b/display.h
@@ -25,10 +25,7 @@ public:
static int Snapshot(unsigned char* frame, int width, int height);
- static int SetVideoFormat(int width, int height, int frameRate,
- bool interlaced);
-
- static int SetSyncField(int field);
+ static int SetVideoFormat(const cVideoFrameFormat *frameFormat);
protected:
@@ -36,12 +33,15 @@ protected:
cRpiVideoPort::ePort port);
virtual ~cRpiDisplay();
- int Update(int width, int height, int frameRate, bool interlaced);
+ int Update(const cVideoFrameFormat *videoFormat);
- virtual int SetMode(int width, int height, int frameRate, bool interlaced) {
+ virtual int SetMode(int width, int height, int frameRate,
+ cScanMode::eMode scanMode) {
return -1;
}
+ static int SetHvsSyncUpdate(cScanMode::eMode scanMode);
+
int m_width;
int m_height;
int m_frameRate;
@@ -67,7 +67,8 @@ public:
private:
- virtual int SetMode(int width, int height, int frameRate, bool interlaced);
+ virtual int SetMode(int width, int height, int frameRate,
+ cScanMode::eMode scanMode);
int SetMode(int group, int mode);
static void TvServiceCallback(void *data, unsigned int reason,
@@ -93,7 +94,8 @@ public:
private:
- virtual int SetMode(int width, int height, int frameRate, bool interlaced) {
+ virtual int SetMode(int width, int height, int frameRate,
+ cScanMode::eMode scanMode) {
return 0;
}
};
diff --git a/omx.c b/omx.c
index 02a9142..1b18f23 100644
--- a/omx.c
+++ b/omx.c
@@ -297,28 +297,34 @@ void cOmx::HandlePortSettingsChanged(unsigned int portId)
&interlace) != OMX_ErrorNone)
ELOG("failed to get video decoder interlace config!");
- m_videoFormat.width = portdef.format.video.nFrameWidth;
- m_videoFormat.height = portdef.format.video.nFrameHeight;
- m_videoFormat.interlaced = interlace.eMode != OMX_InterlaceProgressive;
+ m_videoFrameFormat.width = portdef.format.video.nFrameWidth;
+ m_videoFrameFormat.height = portdef.format.video.nFrameHeight;
+ m_videoFrameFormat.scanMode =
+ interlace.eMode == OMX_InterlaceProgressive ? cScanMode::eProgressive :
+ interlace.eMode == OMX_InterlaceFieldSingleUpperFirst ? cScanMode::eTopFieldFirst :
+ interlace.eMode == OMX_InterlaceFieldSingleLowerFirst ? cScanMode::eBottomFieldFirst :
+ interlace.eMode == OMX_InterlaceFieldsInterleavedUpperFirst ? cScanMode::eTopFieldFirst :
+ interlace.eMode == OMX_InterlaceFieldsInterleavedLowerFirst ? cScanMode::eBottomFieldFirst :
+ cScanMode::eProgressive;
// discard 4 least significant bits, since there might be some deviation
// due to jitter in time stamps
- m_videoFormat.frameRate = ALIGN_UP(
+ m_videoFrameFormat.frameRate = ALIGN_UP(
portdef.format.video.xFramerate & 0xfffffff0, 1 << 16) >> 16;
// workaround for progressive streams detected as interlaced video by
// the decoder due to missing SEI parsing
// see: https://github.com/raspberrypi/firmware/issues/283
// update: with FW from 2015/01/18 this is not necessary anymore
- if (m_videoFormat.interlaced && m_videoFormat.frameRate >= 50)
+ if (m_videoFrameFormat.Interlaced() && m_videoFrameFormat.frameRate >= 50)
{
DLOG("%di looks implausible, you should use a recent firmware...",
- m_videoFormat.frameRate * 2);
+ m_videoFrameFormat.frameRate * 2);
//m_videoFormat.interlaced = false;
}
- if (m_videoFormat.interlaced)
- m_videoFormat.frameRate = m_videoFormat.frameRate * 2;
+ if (m_videoFrameFormat.Interlaced())
+ m_videoFrameFormat.frameRate = m_videoFrameFormat.frameRate * 2;
if (m_onStreamStart)
m_onStreamStart(m_onStreamStartData);
@@ -332,7 +338,7 @@ void cOmx::HandlePortSettingsChanged(unsigned int portId)
OMX_INIT_STRUCT(extraBuffers);
extraBuffers.nPortIndex = 130;
- if (cRpiDisplay::IsProgressive() && m_videoFormat.interlaced)
+ if (cRpiDisplay::IsProgressive() && m_videoFrameFormat.Interlaced())
{
bool fastDeinterlace = portdef.format.video.nFrameWidth *
portdef.format.video.nFrameHeight > 576 * 720;
@@ -437,10 +443,10 @@ cOmx::cOmx() :
memset(m_tun, 0, sizeof(m_tun));
memset(m_comp, 0, sizeof(m_comp));
- m_videoFormat.width = 0;
- m_videoFormat.height = 0;
- m_videoFormat.frameRate = 0;
- m_videoFormat.interlaced = false;
+ m_videoFrameFormat.width = 0;
+ m_videoFrameFormat.height = 0;
+ m_videoFrameFormat.frameRate = 0;
+ m_videoFrameFormat.scanMode = cScanMode::eProgressive;
}
cOmx::~cOmx()
@@ -859,6 +865,18 @@ void cOmx::StopVideo(void)
{
Lock();
+ // disable port buffers and allow video decoder to reconfig
+ ilclient_disable_port_buffers(m_comp[eVideoDecoder], 130,
+ m_spareVideoBuffers, NULL, NULL);
+
+ m_spareVideoBuffers = 0;
+ m_handlePortEvents = false;
+
+ m_videoFrameFormat.width = 0;
+ m_videoFrameFormat.height = 0;
+ m_videoFrameFormat.frameRate = 0;
+ m_videoFrameFormat.scanMode = cScanMode::eProgressive;
+
// put video decoder into idle
ilclient_change_component_state(m_comp[eVideoDecoder], OMX_StateIdle);
@@ -879,18 +897,6 @@ void cOmx::StopVideo(void)
ilclient_disable_tunnel(&m_tun[eVideoSchedulerToVideoRender]);
ilclient_change_component_state(m_comp[eVideoRender], OMX_StateIdle);
- // disable port buffers and allow video decoder to reconfig
- ilclient_disable_port_buffers(m_comp[eVideoDecoder], 130,
- m_spareVideoBuffers, NULL, NULL);
-
- m_spareVideoBuffers = 0;
-
- m_videoFormat.width = 0;
- m_videoFormat.height = 0;
- m_videoFormat.frameRate = 0;
- m_videoFormat.interlaced = false;
-
- m_handlePortEvents = false;
Unlock();
}
@@ -1173,15 +1179,6 @@ int cOmx::SetupAudioRender(cAudioCodec::eCodec outputFormat, int channels,
return 0;
}
-void cOmx::GetVideoFormat(int &width, int &height, int &frameRate,
- bool &interlaced)
-{
- width = m_videoFormat.width;
- height = m_videoFormat.height;
- frameRate = m_videoFormat.frameRate;
- interlaced = m_videoFormat.interlaced;
-}
-
void cOmx::SetDisplayMode(bool fill, bool noaspect)
{
OMX_CONFIG_DISPLAYREGIONTYPE region;
diff --git a/omx.h b/omx.h
index 98ece21..17591ea 100644
--- a/omx.h
+++ b/omx.h
@@ -80,8 +80,10 @@ public:
int SetupAudioRender(cAudioCodec::eCodec outputFormat,
int channels, cRpiAudioPort::ePort audioPort,
int samplingRate = 0, int frameSize = 0);
- void GetVideoFormat(int &width, int &height, int &frameRate,
- bool &interlaced);
+
+ const cVideoFrameFormat *GetVideoFrameFormat(void) {
+ return &m_videoFrameFormat;
+ }
void SetDisplayMode(bool letterbox, bool noaspect);
void SetDisplayRegion(int x, int y, int width, int height);
@@ -130,15 +132,7 @@ private:
COMPONENT_T *m_comp[cOmx::eNumComponents + 1];
TUNNEL_T m_tun[cOmx::eNumTunnels + 1];
- struct VideoFormat
- {
- int width;
- int height;
- int frameRate;
- bool interlaced;
- };
-
- VideoFormat m_videoFormat;
+ cVideoFrameFormat m_videoFrameFormat;
bool m_setAudioStartTime;
bool m_setVideoStartTime;
diff --git a/omxdevice.c b/omxdevice.c
index e42dd7f..34b9588 100644
--- a/omxdevice.c
+++ b/omxdevice.c
@@ -120,10 +120,8 @@ void cOmxDevice::GetOsdSize(int &Width, int &Height, double &PixelAspect)
void cOmxDevice::GetVideoSize(int &Width, int &Height, double &VideoAspect)
{
- bool interlaced;
- int frameRate;
-
- m_omx->GetVideoFormat(Width, Height, frameRate, interlaced);
+ Height = m_omx->GetVideoFrameFormat()->height;
+ Width = m_omx->GetVideoFrameFormat()->width;
if (Height)
VideoAspect = (double)Width / Height;
@@ -165,7 +163,6 @@ bool cOmxDevice::SetPlayMode(ePlayMode PlayMode)
m_hasVideo = false;
m_videoCodec = cVideoCodec::eInvalid;
m_playMode = pmNone;
- cRpiDisplay::SetSyncField(0);
break;
case pmAudioVideo:
@@ -672,17 +669,11 @@ void cOmxDevice::HandleStreamStart()
{
DBG("HandleStreamStart()");
- int width, height, frameRate;
- bool interlaced;
-
- m_omx->GetVideoFormat(width, height, frameRate, interlaced);
+ const cVideoFrameFormat *format = m_omx->GetVideoFrameFormat();
+ DLOG("video stream started %dx%d@%d%s", format->width, format->height,
+ format->frameRate, format->Interlaced() ? "i" : "p");
- DLOG("video stream started %dx%d@%d%s",
- width, height, frameRate, interlaced ? "i" : "p");
-
- cRpiDisplay::SetVideoFormat(width, height, frameRate, interlaced);
- if (!cRpiDisplay::IsProgressive() && interlaced)
- cRpiDisplay::SetSyncField(1);
+ cRpiDisplay::SetVideoFormat(format);
}
void cOmxDevice::HandleVideoSetupChanged()
@@ -705,11 +696,7 @@ void cOmxDevice::HandleVideoSetupChanged()
break;
}
- int width, height, frameRate;
- bool interlaced;
-
- m_omx->GetVideoFormat(width, height, frameRate, interlaced);
- cRpiDisplay::SetVideoFormat(width, height, frameRate, interlaced);
+ cRpiDisplay::SetVideoFormat(m_omx->GetVideoFrameFormat());
}
void cOmxDevice::FlushStreams(bool flushVideoRender)
diff --git a/tools.h b/tools.h
index 2589e56..f218a99 100644
--- a/tools.h
+++ b/tools.h
@@ -175,4 +175,42 @@ public:
}
};
+class cScanMode
+{
+public:
+
+ enum eMode {
+ eProgressive,
+ eTopFieldFirst,
+ eBottomFieldFirst
+ };
+
+ static const char* Str(eMode mode) {
+ return (mode == eProgressive) ? "progressive" :
+ (mode == eTopFieldFirst) ? "interlaced (tff)" :
+ (mode == eBottomFieldFirst) ? "interlaced (bff)" : "unknown";
+ }
+
+ static const bool Interlaced(eMode mode) {
+ return mode != eProgressive;
+ }
+};
+
+class cVideoFrameFormat
+{
+public:
+
+ cVideoFrameFormat() : width(0), height(0), frameRate(0),
+ scanMode(cScanMode::eProgressive) { };
+
+ int width;
+ int height;
+ int frameRate;
+ cScanMode::eMode scanMode;
+
+ bool Interlaced(void) const {
+ return cScanMode::Interlaced(scanMode);
+ }
+};
+
#endif