diff options
| author | Thomas Reufer <thomas@reufer.ch> | 2015-08-14 14:19:33 +0200 |
|---|---|---|
| committer | Thomas Reufer <thomas@reufer.ch> | 2015-08-14 14:19:33 +0200 |
| commit | 6192a97d75f9a5049774f4ee024d09a7dfb45fce (patch) | |
| tree | 4eb7d8efe2affaa394a6896831f8560c35c3f40a | |
| parent | df3e781fa0365e0359d04111502473d861f80b8c (diff) | |
| download | vdr-plugin-rpihddevice-6192a97d75f9a5049774f4ee024d09a7dfb45fce.tar.gz vdr-plugin-rpihddevice-6192a97d75f9a5049774f4ee024d09a7dfb45fce.tar.bz2 | |
reworked video frame format handling
| -rw-r--r-- | display.c | 35 | ||||
| -rw-r--r-- | display.h | 18 | ||||
| -rw-r--r-- | omx.c | 65 | ||||
| -rw-r--r-- | omx.h | 16 | ||||
| -rw-r--r-- | omxdevice.c | 27 | ||||
| -rw-r--r-- | tools.h | 38 |
6 files changed, 111 insertions, 88 deletions
@@ -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 && @@ -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; } }; @@ -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; @@ -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) @@ -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 |
