SHARE
TWEET

Untitled

a guest Jan 6th, 2019 66 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. diff --git a/mythtv/libs/libmythtv/videoout_opengl.h b/mythtv/libs/libmythtv/videoout_opengl.h
  2. index 412024cc09..14e8892e65 100644
  3. --- a/mythtv/libs/libmythtv/videoout_opengl.h
  4. +++ b/mythtv/libs/libmythtv/videoout_opengl.h
  5. @@ -27,7 +27,7 @@ class VideoOutputOpenGL : public VideoOutput
  6.                        FilterChain *filterList,
  7.                        const PIPMap &pipPlayers,
  8.                        FrameScanType scan) override; // VideoOutput
  9. -    void Show(FrameScanType ) override; // VideoOutput
  10. +    virtual void Show(FrameScanType ) override; // VideoOutput
  11.      bool InputChanged(const QSize &video_dim_buf,
  12.                        const QSize &video_dim_disp,
  13.                        float aspect,
  14. diff --git a/mythtv/libs/libmythtv/videoout_openglvaapi.cpp b/mythtv/libs/libmythtv/videoout_openglvaapi.cpp
  15. index 8fd4565ab7..1f75796225 100644
  16. --- a/mythtv/libs/libmythtv/videoout_openglvaapi.cpp
  17. +++ b/mythtv/libs/libmythtv/videoout_openglvaapi.cpp
  18. @@ -34,13 +34,24 @@ void VideoOutputOpenGLVAAPI::GetRenderOptions(render_opts &opts)
  19.  }
  20.  
  21.  VideoOutputOpenGLVAAPI::VideoOutputOpenGLVAAPI()
  22. -  : VideoOutputOpenGL(), m_ctx(nullptr), m_pauseBuffer(nullptr)
  23. +  : VideoOutputOpenGL(),
  24. +    m_ctx(nullptr),
  25. +    m_pauseBuffer(nullptr),
  26. +    m_videoChangedLock(QMutex::NonRecursive),
  27. +    m_videoChangedWait(),
  28. +    m_videoChanged(0),
  29. +    m_videoChangedOK(true),
  30. +    m_newVideoBufferSize(),
  31. +    m_newVideoDisplaySize(),
  32. +    m_newVideoAspect(1.0),
  33. +    m_newVideoCodec(kCodec_NONE)
  34.  {
  35.  }
  36.  
  37.  VideoOutputOpenGLVAAPI::~VideoOutputOpenGLVAAPI()
  38.  {
  39.      TearDown();
  40. +    m_videoChangedWait.wakeAll();
  41.  }
  42.  
  43.  void VideoOutputOpenGLVAAPI::TearDown(void)
  44. @@ -48,23 +59,93 @@ void VideoOutputOpenGLVAAPI::TearDown(void)
  45.      DeleteVAAPIContext();
  46.  }
  47.  
  48. +bool VideoOutputOpenGLVAAPI::InputChangedIsThreadSafe()
  49. +{
  50. +    return gCoreContext->IsUIThread();
  51. +}
  52. +
  53.  bool VideoOutputOpenGLVAAPI::InputChanged(const QSize &video_dim_buf,
  54.                                            const QSize &video_dim_disp,
  55.                                            float aspect,
  56.                                MythCodecID  av_codec_id, void *codec_private,
  57.                                bool &aspect_only)
  58.  {
  59. -    LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("InputChanged(%1,%2,%3) %4->%5")
  60. -            .arg(video_dim_disp.width()).arg(video_dim_disp.height())
  61. -            .arg(aspect)
  62. -            .arg(toString(video_codec_id)).arg(toString(av_codec_id)));
  63. +    (void)codec_private;
  64. +
  65. +    QSize currentbuf = window.GetVideoDim();
  66. +    QSize currentres = window.GetActualVideoDim();
  67. +    float currentasp = window.GetVideoAspect();
  68. +
  69. +    LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Video changed: %1x%2 (%3x%4) '%5' (Aspect %6)"
  70. +                                             "-> %7x%8 (%9x%10) '%11' (Aspect %12)")
  71. +        .arg(currentres.width()).arg(currentres.height())
  72. +        .arg(currentbuf.width()).arg(currentbuf.height())
  73. +        .arg(toString(video_codec_id)).arg(currentasp)
  74. +        .arg(video_dim_disp.width()).arg(video_dim_disp.height())
  75. +        .arg(video_dim_buf.width()).arg(video_dim_buf.height())
  76. +        .arg(toString(av_codec_id)).arg(aspect));
  77. +
  78. +    // aspect ratio changes are a no-op as changes are handled at display time
  79. +    if ((video_codec_id == av_codec_id) && (currentres == video_dim_disp))
  80. +    {
  81. +        aspect_only = true;
  82. +        return true;
  83. +    }
  84.  
  85. -    if (!codec_is_vaapi(av_codec_id))
  86. -        return VideoOutputOpenGL::InputChanged(video_dim_buf, video_dim_disp,
  87. -                                               aspect, av_codec_id,
  88. -                                               codec_private, aspect_only);
  89. +    // if this has been called from the decoder thread and either the old or new
  90. +    // codec is VAAPI, then store the new video metadata and wait until video has
  91. +    // been re-initialised. This ensures thread safe VAAPI calls and allows the
  92. +    // video buffers to play out before re-creating
  93. +    if (!(codec_sw_copy(video_codec_id) && codec_sw_copy(av_codec_id)) && !gCoreContext->IsUIThread())
  94. +    {
  95. +        LOG(VB_PLAYBACK, LOG_INFO, "Video change signalled from decoder thread");
  96. +        m_videoChangedLock.lock();
  97. +        m_videoChanged        = 1;
  98. +        m_newVideoCodec       = av_codec_id;
  99. +        m_newVideoAspect      = aspect;
  100. +        m_newVideoBufferSize  = video_dim_buf;
  101. +        m_newVideoDisplaySize = video_dim_disp;
  102. +        m_videoChangedWait.wait(&m_videoChangedLock);
  103. +        bool result = m_videoChangedOK;
  104. +        m_videoChangedOK = true;
  105. +        m_videoChangedLock.unlock();
  106. +        LOG(VB_PLAYBACK, LOG_INFO, "Video change complete");
  107. +        return result;
  108. +    }
  109.  
  110. -    QMutexLocker locker(&gl_context_lock);
  111. +    return InputChangedPriv(video_dim_buf, video_dim_disp, aspect, av_codec_id);
  112. +}
  113. +
  114. +void VideoOutputOpenGLVAAPI::Show(FrameScanType Scan)
  115. +{
  116. +    VideoOutputOpenGL::Show(Scan);
  117. +    InputChangedCheck();
  118. +}
  119. +
  120. +void VideoOutputOpenGLVAAPI::InputChangedCheck()
  121. +{
  122. +    if (m_videoChanged.testAndSetAcquire(1, 0))
  123. +    {
  124. +        LOG(VB_PLAYBACK, LOG_INFO, "Recreating video resources in UI thread");
  125. +        m_videoChangedOK = InputChangedPriv(m_newVideoBufferSize, m_newVideoDisplaySize,
  126. +                                            m_newVideoAspect, m_newVideoCodec);
  127. +        m_videoChangedWait.wakeAll();
  128. +    }
  129. +}
  130. +
  131. +bool VideoOutputOpenGLVAAPI::InputChangedPriv(const QSize &VideoBufferSize,
  132. +                                              const QSize &VideoDisplaySize,
  133. +                                              float        VideoAspect,
  134. +                                              MythCodecID  MythAVCodecID)
  135. +{
  136. +    if (!gCoreContext->IsUIThread())
  137. +    {
  138. +        LOG(VB_GENERAL, LOG_ERR, "Cannot change video codec from this thread");
  139. +        return false;
  140. +    }
  141. +
  142. +    QMutexLocker lock1(&gl_context_lock);
  143. +    OpenGLLocker lock2(gl_context);
  144.  
  145.      bool wasembedding = window.IsEmbedding();
  146.      QRect oldrect;
  147. @@ -74,42 +155,23 @@ bool VideoOutputOpenGLVAAPI::InputChanged(const QSize &video_dim_buf,
  148.          StopEmbedding();
  149.      }
  150.  
  151. -    bool cid_changed = (video_codec_id != av_codec_id);
  152. -    bool res_changed = video_dim_disp != window.GetActualVideoDim();
  153. -    bool asp_changed = aspect      != window.GetVideoAspect();
  154.  
  155. -    if (!res_changed && !cid_changed)
  156. -    {
  157. -        if (asp_changed)
  158. -        {
  159. -            aspect_only = true;
  160. -            VideoAspectRatioChanged(aspect);
  161. -            MoveResize();
  162. -            if (wasembedding)
  163. -                EmbedInWidget(oldrect);
  164. -        }
  165. -        return true;
  166. -    }
  167. -
  168. -    if (gCoreContext->IsUIThread())
  169. -        TearDown();
  170. -    else
  171. -        DestroyCPUResources();
  172. +    TearDown();
  173. +    DestroyCPUResources();
  174. +    DestroyVideoResources();
  175. +    DestroyGPUResources();
  176.  
  177. -    QRect disp = window.GetDisplayVisibleRect();
  178. -    if (Init(video_dim_buf, video_dim_disp,
  179. -             aspect, gl_parent_win, disp, av_codec_id))
  180. +    QRect display = window.GetDisplayVisibleRect();
  181. +    if (Init(VideoBufferSize, VideoDisplaySize, VideoAspect, gl_parent_win, display, MythAVCodecID))
  182.      {
  183.          if (wasembedding)
  184.              EmbedInWidget(oldrect);
  185. -        if (gCoreContext->IsUIThread())
  186. -            BestDeint();
  187. +        BestDeint();
  188.          return true;
  189.      }
  190.  
  191.      LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to re-initialise video output.");
  192.      errorState = kError_Unknown;
  193. -
  194.      return false;
  195.  }
  196.  
  197. @@ -129,16 +191,6 @@ bool VideoOutputOpenGLVAAPI::Init(const QSize &video_dim_buf,
  198.  
  199.  bool VideoOutputOpenGLVAAPI::CreateVAAPIContext(QSize size)
  200.  {
  201. -    // FIXME During a video stream change this is called from the decoder
  202. -    // thread - which breaks all other efforts to remove non-UI thread
  203. -    // access to the OpenGL context. There is no obvious fix however - if we
  204. -    // don't delete and re-create the VAAPI decoder context immediately then
  205. -    // the decoder fails and playback exits.
  206. -
  207. -    // lvr 27-oct-13
  208. -    // in 0.27 if m_ctx->CreateDisplay is called outside of the UI thread then
  209. -    // it fails, which then causes subsequent unbalanced calls to doneCurrent
  210. -    // which results in Qt aborting.  So just fail if non-UI.
  211.      if (!gCoreContext->IsUIThread())
  212.      {
  213.          LOG(VB_GENERAL, LOG_ERR, LOC +
  214. @@ -284,10 +336,15 @@ void VideoOutputOpenGLVAAPI::PrepareFrame(VideoFrame *frame, FrameScanType scan,
  215.          QMutexLocker locker(&gl_context_lock);
  216.          if (codec_is_vaapi(video_codec_id) && m_ctx && gl_videochain)
  217.          {
  218. +            FrameScanType newscan = kScan_Progressive;
  219. +            if (frame && (scan == kScan_Interlaced))
  220. +                newscan = frame->top_field_first ? kScan_Intr2ndField : kScan_Interlaced;
  221. +            else if (frame && (scan == kScan_Intr2ndField))
  222. +                newscan = frame->top_field_first ? kScan_Interlaced : kScan_Intr2ndField;
  223.              gl_context->makeCurrent();
  224.              m_ctx->CopySurfaceToTexture(frame ? frame->buf : m_pauseBuffer,
  225.                                          gl_videochain->GetInputTexture(),
  226. -                                        gl_videochain->GetTextureType(), scan);
  227. +                                        gl_videochain->GetTextureType(), newscan);
  228.              gl_videochain->SetInputUpdated();
  229.              gl_context->doneCurrent();
  230.          }
  231. diff --git a/mythtv/libs/libmythtv/videoout_openglvaapi.h b/mythtv/libs/libmythtv/videoout_openglvaapi.h
  232. index f0ccea1217..47e153cd50 100644
  233. --- a/mythtv/libs/libmythtv/videoout_openglvaapi.h
  234. +++ b/mythtv/libs/libmythtv/videoout_openglvaapi.h
  235. @@ -30,8 +30,10 @@ class VideoOutputOpenGLVAAPI : public VideoOutputOpenGL
  236.                         float aspect,
  237.                         MythCodecID  av_codec_id, void *codec_private,
  238.                         bool &aspect_only) override; // VideoOutputOpenGL
  239. +    bool  InputChangedIsThreadSafe() override;
  240.      void  UpdatePauseFrame(int64_t &disp_timecode) override; // VideoOutputOpenGL
  241.      void  PrepareFrame(VideoFrame *frame, FrameScanType scan, OSD *osd) override; // VideoOutputOpenGL
  242. +    void  Show(FrameScanType) override; // VideoOutputOpenGL
  243.      bool  ApproveDeintFilter(const QString& filtername) const override; // VideoOutputOpenGL
  244.      bool  SetDeinterlacingEnabled(bool enable) override; // VideoOutputOpenGL
  245.      bool  SetupDeinterlace(bool interlaced, const QString& overridefilter="") override; // VideoOutputOpenGL
  246. @@ -47,8 +49,25 @@ class VideoOutputOpenGLVAAPI : public VideoOutputOpenGL
  247.                                               AVPixelFormat &pix_fmt);
  248.  
  249.    private:
  250. -    VAAPIContext *m_ctx;
  251. -    void         *m_pauseBuffer;
  252. +    bool  InputChangedPriv(const QSize &VideoBufferSize,
  253. +                           const QSize &VideoDisplaySize,
  254. +                           float        VideoAspect,
  255. +                           MythCodecID  MythAVCodecID);
  256. +    void  InputChangedCheck();
  257. +
  258. +  private:
  259. +    VAAPIContext  *m_ctx;
  260. +    void          *m_pauseBuffer;
  261. +
  262. +    // Video codec changes
  263. +    QMutex         m_videoChangedLock;
  264. +    QWaitCondition m_videoChangedWait;
  265. +    QAtomicInt     m_videoChanged;
  266. +    bool           m_videoChangedOK;
  267. +    QSize          m_newVideoBufferSize;
  268. +    QSize          m_newVideoDisplaySize;
  269. +    float          m_newVideoAspect;
  270. +    MythCodecID    m_newVideoCodec;
  271.  };
  272.  #endif // VIDEOOUTPUTOPENGLVAAPI_H
  273.  
  274. diff --git a/mythtv/libs/libmythtv/videooutbase.h b/mythtv/libs/libmythtv/videooutbase.h
  275. index 0d1bca5b49..37b51ca60f 100644
  276. --- a/mythtv/libs/libmythtv/videooutbase.h
  277. +++ b/mythtv/libs/libmythtv/videooutbase.h
  278. @@ -99,6 +99,7 @@ class VideoOutput
  279.                                MythCodecID  myth_codec_id,
  280.                                void        *codec_private,
  281.                                bool        &aspect_changed);
  282. +    virtual bool InputChangedIsThreadSafe() { return true; }
  283.  
  284.      virtual void VideoAspectRatioChanged(float aspect);
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top