MythTV  0.26-pre
videoout_vdpau.cpp
Go to the documentation of this file.
00001 #include "mythcontext.h"
00002 #include "mythplayer.h"
00003 #include "videooutbase.h"
00004 #include "videoout_vdpau.h"
00005 #include "videodisplayprofile.h"
00006 #include "osd.h"
00007 #include "mythxdisplay.h"
00008 #include "mythmainwindow.h"
00009 #include "mythuihelper.h"
00010 #include "mythpainter_vdpau.h"
00011 
00012 #define LOC      QString("VidOutVDPAU: ")
00013 
00014 #define MIN_REFERENCE_FRAMES 2
00015 #define MAX_REFERENCE_FRAMES 16
00016 #define MIN_PROCESS_BUFFER   6
00017 #define MAX_PROCESS_BUFFER   50
00018 #define DEF_PROCESS_BUFFER   12
00019 
00020 #define CHECK_ERROR(Loc) \
00021   if (m_render && m_render->IsErrored()) \
00022       errorState = kError_Unknown; \
00023   if (IsErrored()) \
00024   { \
00025       LOG(VB_GENERAL, LOG_ERR, LOC + QString("IsErrored() in %1").arg(Loc)); \
00026       return; \
00027   } while(0)
00028 
00029 void VideoOutputVDPAU::GetRenderOptions(render_opts &opts)
00030 {
00031     opts.renderers->append("vdpau");
00032     (*opts.osds)["vdpau"].append("vdpau");
00033     if (opts.decoders->contains("vdpau"))
00034         (*opts.safe_renderers)["vdpau"].append("vdpau");
00035     if (opts.decoders->contains("ffmpeg"))
00036         (*opts.safe_renderers)["ffmpeg"].append("vdpau");
00037     if (opts.decoders->contains("crystalhd"))
00038         (*opts.safe_renderers)["crystalhd"].append("vdpau");
00039     (*opts.safe_renderers)["dummy"].append("vdpau");
00040     (*opts.safe_renderers)["nuppel"].append("vdpau");
00041 
00042     opts.priorities->insert("vdpau", 120);
00043     QStringList deints;
00044     deints += "none";
00045     deints += "vdpauonefield";
00046     deints += "vdpaubobdeint";
00047     deints += "vdpaubasic";
00048     deints += "vdpauadvanced";
00049     deints += "vdpaubasicdoublerate";
00050     deints += "vdpauadvanceddoublerate";
00051     opts.deints->insert("vdpau", deints);
00052 }
00053 
00054 VideoOutputVDPAU::VideoOutputVDPAU()
00055   : m_win(0),                m_render(NULL),
00056     m_decoder_buffer_size(MAX_REFERENCE_FRAMES),
00057     m_process_buffer_size(DEF_PROCESS_BUFFER), m_pause_surface(0),
00058     m_need_deintrefs(false), m_video_mixer(0), m_mixer_features(kVDPFeatNone),
00059     m_checked_surface_ownership(false),
00060     m_checked_output_surfaces(false),
00061     m_decoder(0),            m_pix_fmt(-1),
00062     m_lock(QMutex::Recursive), m_pip_layer(0), m_pip_surface(0),
00063     m_pip_ready(false),      m_osd_painter(NULL),
00064     m_skip_chroma(false),    m_denoise(0.0f),
00065     m_sharpen(0.0f),
00066     m_colorspace(VDP_COLOR_STANDARD_ITUR_BT_601)
00067 {
00068     if (gCoreContext->GetNumSetting("UseVideoModes", 0))
00069         display_res = DisplayRes::GetDisplayRes(true);
00070 }
00071 
00072 VideoOutputVDPAU::~VideoOutputVDPAU()
00073 {
00074     QMutexLocker locker(&m_lock);
00075     TearDown();
00076 }
00077 
00078 void VideoOutputVDPAU::TearDown(void)
00079 {
00080     QMutexLocker locker(&m_lock);
00081     DeinitPIPS();
00082     DeinitPIPLayer();
00083     DeleteBuffers();
00084     RestoreDisplay();
00085     DeleteRender();
00086 }
00087 
00088 bool VideoOutputVDPAU::Init(int width, int height, float aspect,
00089                             WId winid, const QRect &win_rect,
00090                             MythCodecID codec_id)
00091 {
00092     // Attempt to free up as much video memory as possible
00093     // only works when using the VDPAU painter for the UI
00094     MythPainter *painter = GetMythPainter();
00095     if (painter)
00096         painter->FreeResources();
00097 
00098     m_win = winid;
00099     QMutexLocker locker(&m_lock);
00100     window.SetNeedRepaint(true);
00101     bool ok = VideoOutput::Init(width, height, aspect, winid, win_rect,codec_id);
00102     if (db_vdisp_profile)
00103         db_vdisp_profile->SetVideoRenderer("vdpau");
00104 
00105     InitDisplayMeasurements(width, height, true);
00106     ParseOptions();
00107     if (ok) ok = InitRender();
00108     if (ok) ok = InitBuffers();
00109     if (!ok)
00110     {
00111         TearDown();
00112         return ok;
00113     }
00114 
00115     InitPictureAttributes();
00116     MoveResize();
00117     LOG(VB_PLAYBACK, LOG_INFO, LOC +
00118         QString("Created VDPAU context (%1 decode)")
00119             .arg(codec_is_std(video_codec_id) ? "software" : "GPU"));
00120 
00121     return ok;
00122 }
00123 
00124 bool VideoOutputVDPAU::InitRender(void)
00125 {
00126     QMutexLocker locker(&m_lock);
00127 
00128     const QSize size = window.GetDisplayVisibleRect().size();
00129     const QRect rect = QRect(QPoint(0,0), size);
00130     m_render = new MythRenderVDPAU();
00131 
00132     if (m_render && m_render->Create(size, m_win))
00133     {
00134         m_osd_painter = new MythVDPAUPainter(m_render);
00135         if (m_osd_painter)
00136         {
00137             m_osd_painter->SetSwapControl(false);
00138             LOG(VB_PLAYBACK, LOG_INFO, LOC +
00139                 QString("Created VDPAU osd (%1x%2)")
00140                     .arg(size.width()).arg(size.height()));
00141         }
00142         else
00143             LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create VDPAU osd.");
00144         return true;
00145     }
00146 
00147     LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to initialise VDPAU");
00148 
00149     return false;
00150 }
00151 
00152 void VideoOutputVDPAU::DeleteRender(void)
00153 {
00154     QMutexLocker locker(&m_lock);
00155 
00156     if (m_osd_painter)
00157         delete m_osd_painter;
00158 
00159     if (m_render)
00160     {
00161         if (m_decoder)
00162             m_render->DestroyDecoder(m_decoder);
00163 
00164         delete m_render;
00165     }
00166 
00167     m_checked_output_surfaces = false;
00168     m_osd_painter = NULL;
00169     m_decoder = 0;
00170     m_render = NULL;
00171     m_pix_fmt = -1;
00172 }
00173 
00174 bool VideoOutputVDPAU::InitBuffers(void)
00175 {
00176     QMutexLocker locker(&m_lock);
00177     if (!m_render)
00178         return false;
00179 
00180     uint buffer_size = m_decoder_buffer_size + m_process_buffer_size;
00181     const QSize video_dim = codec_is_std(video_codec_id) ?
00182                             window.GetVideoDim() : window.GetActualVideoDim();
00183 
00184     vbuffers.Init(buffer_size, false, 2, 1, 4, 1);
00185 
00186     bool ok = false;
00187     if (codec_is_vdpau(video_codec_id))
00188     {
00189         ok = CreateVideoSurfaces(buffer_size);
00190         if (ok)
00191         {
00192             for (int i = 0; i < m_video_surfaces.size(); i++)
00193                 ok &= vbuffers.CreateBuffer(video_dim.width(),
00194                                     video_dim.height(), i,
00195                                     m_render->GetRender(m_video_surfaces[i]),
00196                                     FMT_VDPAU);
00197         }
00198     }
00199     else if (codec_is_std(video_codec_id))
00200     {
00201         ok = CreateVideoSurfaces(NUM_REFERENCE_FRAMES);
00202         if (ok)
00203             ok = vbuffers.CreateBuffers(FMT_YV12,
00204                                         video_dim.width(), video_dim.height());
00205     }
00206 
00207     if (!ok)
00208     {
00209         LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to create VDPAU buffers");
00210     }
00211     else
00212     {
00213         m_video_mixer = m_render->CreateVideoMixer(video_dim, 2,
00214                                                    m_mixer_features);
00215         ok = m_video_mixer;
00216         m_pause_surface = m_video_surfaces[0];
00217 
00218         if (ok && (m_mixer_features & kVDPFeatSharpness))
00219             m_render->SetMixerAttribute(m_video_mixer,
00220                                         kVDPAttribSharpness,
00221                                         m_sharpen);
00222         if (ok && (m_mixer_features & kVDPFeatDenoise))
00223             m_render->SetMixerAttribute(m_video_mixer,
00224                                         kVDPAttribNoiseReduction,
00225                                         m_denoise);
00226         if (ok && m_skip_chroma)
00227             m_render->SetMixerAttribute(m_video_mixer,
00228                                         kVDPAttribSkipChroma, 1);
00229 
00230         if (ok && (db_letterbox_colour == kLetterBoxColour_Gray25))
00231             m_render->SetMixerAttribute(m_video_mixer,
00232                                         kVDPAttribBackground, 0x7F7F7FFF);
00233     }
00234 
00235     if (!ok)
00236     {
00237         LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to create VDPAU mixer");
00238         DeleteBuffers();
00239     }
00240 
00241     return ok;
00242 }
00243 
00244 bool VideoOutputVDPAU::CreateVideoSurfaces(uint num)
00245 {
00246     if (!m_render || num < 1)
00247         return false;
00248 
00249     bool ret = true;
00250     const QSize size = codec_is_std(video_codec_id) ?
00251                        window.GetVideoDim() : window.GetActualVideoDim();
00252     for (uint i = 0; i < num; i++)
00253     {
00254         uint tmp = m_render->CreateVideoSurface(size);
00255         if (tmp)
00256         {
00257             m_video_surfaces.push_back(tmp);
00258             m_render->ClearVideoSurface(tmp);
00259         }
00260         else
00261         {
00262             ret = false;
00263             break;
00264         }
00265     }
00266     return ret;
00267 }
00268 
00269 void VideoOutputVDPAU::DeleteVideoSurfaces(void)
00270 {
00271     if (!m_render || !m_video_surfaces.size())
00272         return;
00273 
00274     for (int i = 0; i < m_video_surfaces.size(); i++)
00275         m_render->DestroyVideoSurface(m_video_surfaces[i]);
00276     m_video_surfaces.clear();
00277 }
00278 
00279 void VideoOutputVDPAU::DeleteBuffers(void)
00280 {
00281     QMutexLocker locker(&m_lock);
00282     if (m_render && m_video_mixer)
00283         m_render->DestroyVideoMixer(m_video_mixer);
00284     m_video_mixer = 0;
00285     m_checked_surface_ownership = false;
00286     DiscardFrames(true);
00287     DeleteVideoSurfaces();
00288     vbuffers.Reset();
00289     vbuffers.DeleteBuffers();
00290 }
00291 
00292 void VideoOutputVDPAU::RestoreDisplay(void)
00293 {
00294     QMutexLocker locker(&m_lock);
00295 
00296     const QRect tmp_display_visible_rect =
00297         window.GetTmpDisplayVisibleRect();
00298     if (window.GetPIPState() == kPIPStandAlone &&
00299         !tmp_display_visible_rect.isEmpty())
00300     {
00301         window.SetDisplayVisibleRect(tmp_display_visible_rect);
00302     }
00303     const QRect display_visible_rect = window.GetDisplayVisibleRect();
00304 
00305     if (m_render)
00306         m_render->DrawDisplayRect(display_visible_rect);
00307 }
00308 
00309 bool VideoOutputVDPAU::SetDeinterlacingEnabled(bool interlaced)
00310 {
00311     if ((interlaced && m_deinterlacing) ||
00312        (!interlaced && !m_deinterlacing))
00313         return m_deinterlacing;
00314 
00315     return SetupDeinterlace(interlaced);
00316 }
00317 
00318 bool VideoOutputVDPAU::SetupDeinterlace(bool interlaced,
00319                                         const QString &override)
00320 {
00321     m_lock.lock();
00322     if (!m_render)
00323         return false;
00324 
00325     bool enable = interlaced;
00326     if (enable)
00327     {
00328         m_deintfiltername = db_vdisp_profile->GetFilteredDeint(override);
00329         if (m_deintfiltername.contains("vdpau"))
00330         {
00331             uint features = kVDPFeatNone;
00332             bool spatial  = m_deintfiltername.contains("advanced");
00333             bool temporal = m_deintfiltername.contains("basic") || spatial;
00334             m_need_deintrefs = spatial || temporal;
00335 
00336             if (temporal)
00337                 features += kVDPFeatTemporal;
00338 
00339             if (spatial)
00340                 features += kVDPFeatSpatial;
00341 
00342             enable = m_render->SetDeinterlacing(m_video_mixer, features);
00343             if (enable)
00344             {
00345                 m_deinterlacing = true;
00346                 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Enabled deinterlacing.");
00347             }
00348             else
00349             {
00350                 enable = false;
00351                 LOG(VB_PLAYBACK, LOG_INFO, LOC +
00352                     "Failed to enable deinterlacing.");
00353             }
00354         }
00355         else
00356         {
00357             enable = false;
00358         }
00359     }
00360 
00361     if (!enable)
00362     {
00363         ClearReferenceFrames();
00364         m_render->SetDeinterlacing(m_video_mixer);
00365         m_deintfiltername = QString();
00366         m_deinterlacing   = false;
00367         m_need_deintrefs  = false;
00368     }
00369     m_lock.unlock();
00370     return enable;
00371 }
00372 
00373 bool VideoOutputVDPAU::ApproveDeintFilter(const QString &filtername) const
00374 {
00375     return filtername.contains("vdpau");
00376 }
00377 
00378 void VideoOutputVDPAU::ProcessFrame(VideoFrame *frame, OSD *osd,
00379                                     FilterChain *filterList,
00380                                     const PIPMap &pipPlayers,
00381                                     FrameScanType scan)
00382 {
00383     QMutexLocker locker(&m_lock);
00384     CHECK_ERROR("ProcessFrame");
00385 
00386     if (!m_checked_surface_ownership && codec_is_std(video_codec_id))
00387         ClaimVideoSurfaces();
00388 
00389     m_pip_ready = false;
00390     ShowPIPs(frame, pipPlayers);
00391 }
00392 
00393 void VideoOutputVDPAU::ClearDummyFrame(VideoFrame *frame)
00394 {
00395     if (frame && m_render && !codec_is_std(video_codec_id))
00396     {
00397         struct vdpau_render_state *render =
00398             (struct vdpau_render_state *)frame->buf;
00399         if (render)
00400             m_render->ClearVideoSurface(render->surface);
00401     }
00402     VideoOutput::ClearDummyFrame(frame);
00403 }
00404 
00405 void VideoOutputVDPAU::PrepareFrame(VideoFrame *frame, FrameScanType scan,
00406                                     OSD *osd)
00407 {
00408     QMutexLocker locker(&m_lock);
00409     (void)osd;
00410     CHECK_ERROR("PrepareFrame");
00411 
00412     if (!m_render)
00413         return;
00414 
00415     if (!m_checked_output_surfaces &&
00416         !(!codec_is_std(video_codec_id) && !m_decoder))
00417     {
00418         m_render->CheckOutputSurfaces();
00419         m_checked_output_surfaces = true;
00420     }
00421 
00422     bool new_frame = false;
00423     bool dummy     = false;
00424     if (frame)
00425     {
00426         // FIXME for 0.23. This should be triggered from AFD by a seek
00427         if ((abs(frame->frameNumber - framesPlayed) > 8))
00428             ClearReferenceFrames();
00429         new_frame = (framesPlayed != frame->frameNumber + 1);
00430         framesPlayed = frame->frameNumber + 1;
00431         dummy = frame->dummy;
00432     }
00433 
00434     uint video_surface = m_video_surfaces[0];
00435     bool deint = (m_deinterlacing && m_need_deintrefs &&
00436                   frame && !dummy);
00437 
00438     if (deint)
00439     {
00440         if (new_frame)
00441             UpdateReferenceFrames(frame);
00442         if (m_reference_frames.size() != NUM_REFERENCE_FRAMES)
00443             deint = false;
00444     }
00445 
00446     if (!codec_is_std(video_codec_id) && frame)
00447     {
00448         struct vdpau_render_state *render =
00449             (struct vdpau_render_state *)frame->buf;
00450         if (!render)
00451             return;
00452         video_surface = m_render->GetSurfaceOwner(render->surface);
00453     }
00454     else if (new_frame && frame && !dummy)
00455     {
00456         // FIXME - reference frames for software decode
00457         if (deint)
00458             video_surface = m_video_surfaces[(framesPlayed + 1) %
00459                             NUM_REFERENCE_FRAMES];
00460 
00461         uint32_t pitches[3] = {
00462             frame->pitches[0],
00463             frame->pitches[2],
00464             frame->pitches[1]
00465         };
00466         void* const planes[3] = {
00467             frame->buf,
00468             frame->buf + frame->offsets[2],
00469             frame->buf + frame->offsets[1]
00470         };
00471 
00472         if (!m_render->UploadYUVFrame(video_surface, planes, pitches))
00473             return;
00474     }
00475     else if (!frame)
00476     {
00477         deint = false;
00478         video_surface = m_pause_surface;
00479     }
00480 
00481     VdpVideoMixerPictureStructure field =
00482         VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
00483 
00484     if (scan == kScan_Interlaced && m_deinterlacing && frame)
00485     {
00486         field = frame->top_field_first ?
00487                 VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD :
00488                 VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
00489     }
00490     else if (scan == kScan_Intr2ndField && m_deinterlacing && frame)
00491     {
00492         field = frame->top_field_first ?
00493                 VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD :
00494                 VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
00495     }
00496     else if (!frame && m_deinterlacing)
00497     {
00498         field = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
00499     }
00500 
00501     m_render->WaitForFlip();
00502 
00503     QSize size = window.GetDisplayVisibleRect().size();
00504     if (size != m_render->GetSize())
00505         LOG(VB_GENERAL, LOG_ERR, LOC + "Unexpected display size.");
00506 
00507     if (dummy)
00508     {
00509         m_render->DrawBitmap(0, 0, NULL, NULL, kVDPBlendNormal, 255);
00510     }
00511     else
00512     {
00513         if (!m_render->MixAndRend(m_video_mixer, field, video_surface, 0,
00514                                   deint ? &m_reference_frames : NULL,
00515                                   scan == kScan_Interlaced,
00516                                   window.GetVideoRect(),
00517                                   QRect(QPoint(0,0), size),
00518                                   vsz_enabled ? vsz_desired_display_rect :
00519                                                 window.GetDisplayVideoRect(),
00520                                   0, 0))
00521         {
00522             LOG(VB_PLAYBACK, LOG_ERR, LOC + "Prepare frame failed.");
00523         }
00524     }
00525 
00526     if (m_pip_ready)
00527         m_render->DrawLayer(m_pip_layer, 0);
00528     if (m_visual)
00529         m_visual->Draw(GetTotalOSDBounds(), m_osd_painter, NULL);
00530 
00531     if (osd && m_osd_painter && !window.IsEmbedding())
00532         osd->DrawDirect(m_osd_painter, GetTotalOSDBounds().size(), true);
00533 
00534     if (!frame)
00535     {
00536         VideoFrame *buf = GetLastShownFrame();
00537         if (buf)
00538             buf->timecode = 0;
00539     }
00540 }
00541 
00542 void VideoOutputVDPAU::ClaimVideoSurfaces(void)
00543 {
00544     if (!m_render)
00545         return;
00546 
00547     QVector<uint>::iterator it;
00548     for (it = m_video_surfaces.begin(); it != m_video_surfaces.end(); ++it)
00549         m_render->ChangeVideoSurfaceOwner(*it);
00550     m_checked_surface_ownership = true;
00551 }
00552 
00553 void VideoOutputVDPAU::DrawSlice(VideoFrame *frame, int x, int y, int w, int h)
00554 {
00555     (void)x;
00556     (void)y;
00557     (void)w;
00558     (void)h;
00559 
00560     CHECK_ERROR("DrawSlice");
00561 
00562     if (codec_is_std(video_codec_id) || !m_render)
00563         return;
00564 
00565     if (!m_checked_surface_ownership)
00566         ClaimVideoSurfaces();
00567 
00568     struct vdpau_render_state *render = (struct vdpau_render_state *)frame->buf;
00569     if (!render)
00570     {
00571         LOG(VB_GENERAL, LOG_ERR, LOC + "No video surface to decode to.");
00572         errorState = kError_Unknown;
00573         return;
00574     }
00575 
00576     if (frame->pix_fmt != m_pix_fmt)
00577     {
00578         if (m_decoder)
00579         {
00580             LOG(VB_GENERAL, LOG_ERR, LOC + "Picture format has changed.");
00581             errorState = kError_Unknown;
00582             return;
00583         }
00584 
00585         uint max_refs = MIN_REFERENCE_FRAMES;
00586         if (frame->pix_fmt == PIX_FMT_VDPAU_H264)
00587         {
00588             max_refs = render->info.h264.num_ref_frames;
00589             if (max_refs < 1 || max_refs > MAX_REFERENCE_FRAMES)
00590             {
00591                 uint32_t round_width  = (frame->width + 15) & ~15;
00592                 uint32_t round_height = (frame->height + 15) & ~15;
00593                 uint32_t surf_size    = (round_width * round_height * 3) / 2;
00594                 max_refs = (12 * 1024 * 1024) / surf_size;
00595             }
00596             if (max_refs > MAX_REFERENCE_FRAMES)
00597                 max_refs = MAX_REFERENCE_FRAMES;
00598 
00599             // Add extra buffers as necessary
00600             int needed = max_refs - m_decoder_buffer_size;
00601             if (needed > 0)
00602             {
00603                 QMutexLocker locker(&m_lock);
00604                 const QSize size = window.GetActualVideoDim();
00605                 uint created = 0;
00606                 for (int i = 0; i < needed; i++)
00607                 {
00608                     uint tmp = m_render->CreateVideoSurface(size);
00609                     if (tmp)
00610                     {
00611                         m_video_surfaces.push_back(tmp);
00612                         m_render->ClearVideoSurface(tmp);
00613                         if (vbuffers.AddBuffer(size.width(), size.height(),
00614                                                m_render->GetRender(tmp),
00615                                                FMT_VDPAU))
00616                         {
00617                             created++;
00618                         }
00619                     }
00620                 }
00621                 m_decoder_buffer_size += created;
00622                 LOG(VB_GENERAL, LOG_INFO, LOC +
00623                     QString("Added %1 new buffers. New buffer size %2 "
00624                             "(%3 decode and %4 process)")
00625                                 .arg(created).arg(vbuffers.Size())
00626                                 .arg(m_decoder_buffer_size)
00627                                 .arg(m_process_buffer_size));
00628             }
00629         }
00630 
00631         VdpDecoderProfile vdp_decoder_profile;
00632         switch (frame->pix_fmt)
00633         {
00634             case PIX_FMT_VDPAU_MPEG1:
00635                 vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG1;
00636                 break;
00637             case PIX_FMT_VDPAU_MPEG2:
00638                 vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG2_MAIN;
00639                 break;
00640             case PIX_FMT_VDPAU_MPEG4:
00641                 vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG4_PART2_ASP;
00642                 break;
00643             case PIX_FMT_VDPAU_H264:
00644                 vdp_decoder_profile = VDP_DECODER_PROFILE_H264_HIGH;
00645                 break;
00646             case PIX_FMT_VDPAU_WMV3:
00647                 vdp_decoder_profile = VDP_DECODER_PROFILE_VC1_MAIN;
00648                 break;
00649             case PIX_FMT_VDPAU_VC1:
00650                 vdp_decoder_profile = VDP_DECODER_PROFILE_VC1_ADVANCED;
00651                 break;
00652             default:
00653                 LOG(VB_GENERAL, LOG_ERR, LOC +
00654                     "Picture format is not supported.");
00655                 errorState = kError_Unknown;
00656                 return;
00657         }
00658 
00659         m_decoder = m_render->CreateDecoder(window.GetActualVideoDim(),
00660                                             vdp_decoder_profile, max_refs);
00661         if (m_decoder)
00662         {
00663             m_pix_fmt = frame->pix_fmt;
00664             LOG(VB_PLAYBACK, LOG_INFO, LOC +
00665                 QString("Created VDPAU decoder (%1 ref frames)")
00666                     .arg(max_refs));
00667         }
00668         else
00669         {
00670             LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create decoder.");
00671             errorState = kError_Unknown;
00672             return;
00673         }
00674     }
00675     else if (!m_decoder)
00676     {
00677         LOG(VB_GENERAL, LOG_ERR, LOC +
00678             "Pix format already set but no VDPAU decoder.");
00679         errorState = kError_Unknown;
00680         return;
00681     }
00682 
00683     m_render->Decode(m_decoder, render);
00684 }
00685 
00686 void VideoOutputVDPAU::Show(FrameScanType scan)
00687 {
00688     QMutexLocker locker(&m_lock);
00689     CHECK_ERROR("Show");
00690 
00691     if (window.IsRepaintNeeded())
00692         DrawUnusedRects(false);
00693 
00694     if (m_render)
00695         m_render->Flip();
00696     CheckFrameStates();
00697 }
00698 
00699 void VideoOutputVDPAU::ClearAfterSeek(void)
00700 {
00701     m_lock.lock();
00702     LOG(VB_PLAYBACK, LOG_INFO, LOC + "ClearAfterSeek()");
00703     DiscardFrames(false);
00704     m_lock.unlock();
00705 }
00706 
00707 bool VideoOutputVDPAU::InputChanged(const QSize &input_size,
00708                                     float        aspect,
00709                                     MythCodecID  av_codec_id,
00710                                     void        *codec_private,
00711                                     bool        &aspect_only)
00712 {
00713     LOG(VB_PLAYBACK, LOG_INFO, LOC +
00714         QString("InputChanged(%1,%2,%3) '%4'->'%5'")
00715             .arg(input_size.width()).arg(input_size.height()).arg(aspect)
00716             .arg(toString(video_codec_id)).arg(toString(av_codec_id)));
00717 
00718     QMutexLocker locker(&m_lock);
00719 
00720     // Ensure we don't lose embedding through program changes. This duplicates
00721     // code in VideoOutput::Init but we need start here otherwise the embedding
00722     // is lost during window re-initialistion.
00723     bool wasembedding = window.IsEmbedding();
00724     QRect oldrect;
00725     if (wasembedding)
00726     {
00727         oldrect = window.GetEmbeddingRect();
00728         StopEmbedding();
00729     }
00730 
00731     bool cid_changed = (video_codec_id != av_codec_id);
00732     bool res_changed = input_size  != window.GetActualVideoDim();
00733     bool asp_changed = aspect      != window.GetVideoAspect();
00734 
00735     if (!res_changed && !cid_changed)
00736     {
00737         aspect_only = true;
00738         if (asp_changed)
00739         {
00740             VideoAspectRatioChanged(aspect);
00741             MoveResize();
00742         }
00743         if (wasembedding)
00744             EmbedInWidget(oldrect);
00745         return true;
00746     }
00747 
00748     TearDown();
00749     QRect disp = window.GetDisplayVisibleRect();
00750     if (Init(input_size.width(), input_size.height(),
00751              aspect, m_win, disp, av_codec_id))
00752     {
00753         if (wasembedding)
00754             EmbedInWidget(oldrect);
00755         BestDeint();
00756         return true;
00757     }
00758 
00759     LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to re-initialise video output.");
00760     errorState = kError_Unknown;
00761 
00762     return false;
00763 }
00764 
00765 void VideoOutputVDPAU::Zoom(ZoomDirection direction)
00766 {
00767     QMutexLocker locker(&m_lock);
00768     VideoOutput::Zoom(direction);
00769     MoveResize();
00770 }
00771 
00772 void VideoOutputVDPAU::VideoAspectRatioChanged(float aspect)
00773 {
00774     QMutexLocker locker(&m_lock);
00775     VideoOutput::VideoAspectRatioChanged(aspect);
00776 }
00777 
00778 void VideoOutputVDPAU::EmbedInWidget(const QRect &rect)
00779 {
00780     QMutexLocker locker(&m_lock);
00781     if (!window.IsEmbedding())
00782     {
00783         VideoOutput::EmbedInWidget(rect);
00784         MoveResize();
00785         window.SetDisplayVisibleRect(window.GetTmpDisplayVisibleRect());
00786     }
00787 }
00788 
00789 void VideoOutputVDPAU::StopEmbedding(void)
00790 {
00791     if (!window.IsEmbedding())
00792         return;
00793     QMutexLocker locker(&m_lock);
00794     VideoOutput::StopEmbedding();
00795     MoveResize();
00796 }
00797 
00798 void VideoOutputVDPAU::MoveResizeWindow(QRect new_rect)
00799 {
00800     m_lock.lock();
00801     if (m_render)
00802         m_render->MoveResizeWin(new_rect);
00803     m_lock.unlock();
00804 }
00805 
00806 void VideoOutputVDPAU::DrawUnusedRects(bool sync)
00807 {
00808     m_lock.lock();
00809     if (window.IsRepaintNeeded() && m_render)
00810     {
00811         const QRect dvr = window.GetDisplayVisibleRect();
00812         m_render->DrawDisplayRect(dvr, true);
00813         window.SetNeedRepaint(false);
00814         if (sync)
00815             m_render->SyncDisplay();
00816     }
00817     m_lock.unlock();
00818 }
00819 
00820 void VideoOutputVDPAU::UpdatePauseFrame(int64_t &disp_timecode)
00821 {
00822     QMutexLocker locker(&m_lock);
00823 
00824     LOG(VB_PLAYBACK, LOG_INFO, LOC + "UpdatePauseFrame() " +
00825             vbuffers.GetStatus());
00826 
00827     vbuffers.begin_lock(kVideoBuffer_used);
00828 
00829     if (vbuffers.size(kVideoBuffer_used) && m_render)
00830     {
00831         VideoFrame *frame = vbuffers.head(kVideoBuffer_used);
00832         disp_timecode = frame->disp_timecode;
00833         if (codec_is_std(video_codec_id))
00834         {
00835             m_pause_surface = m_video_surfaces[0];
00836             uint32_t pitches[3] = { frame->pitches[0],
00837                                     frame->pitches[2],
00838                                     frame->pitches[1] };
00839             void* const planes[3] = { frame->buf,
00840                                       frame->buf + frame->offsets[2],
00841                                       frame->buf + frame->offsets[1] };
00842             m_render->UploadYUVFrame(m_video_surfaces[0], planes, pitches);
00843         }
00844         else
00845         {
00846             struct vdpau_render_state *render =
00847                     (struct vdpau_render_state *)frame->buf;
00848             if (render)
00849                 m_pause_surface = m_render->GetSurfaceOwner(render->surface);
00850         }
00851     }
00852     else
00853         LOG(VB_PLAYBACK, LOG_WARNING, LOC +
00854             "Could not update pause frame - no used frames.");
00855 
00856     vbuffers.end_lock();
00857 }
00858 
00859 void VideoOutputVDPAU::InitPictureAttributes(void)
00860 {
00861     videoColourSpace.SetSupportedAttributes((PictureAttributeSupported)
00862                                      (kPictureAttributeSupported_Brightness |
00863                                       kPictureAttributeSupported_Contrast |
00864                                       kPictureAttributeSupported_Colour |
00865                                       kPictureAttributeSupported_Hue |
00866                                       kPictureAttributeSupported_StudioLevels));
00867 
00868     m_lock.lock();
00869     if (m_render && m_video_mixer)
00870     {
00871         if (m_colorspace < 0)
00872         {
00873             QSize size = window.GetVideoDim();
00874             m_colorspace = (size.width() > 720 || size.height() > 576) ?
00875                             VDP_COLOR_STANDARD_ITUR_BT_709 :
00876                             VDP_COLOR_STANDARD_ITUR_BT_601;
00877             LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Using ITU %1 colorspace")
00878                         .arg((m_colorspace == VDP_COLOR_STANDARD_ITUR_BT_601) ?
00879                         "BT.601" : "BT.709"));
00880         }
00881 
00882         if (m_colorspace != VDP_COLOR_STANDARD_ITUR_BT_601)
00883         {
00884             videoColourSpace.SetColourSpace((m_colorspace == VDP_COLOR_STANDARD_ITUR_BT_601)
00885                          ? kCSTD_ITUR_BT_601 : kCSTD_ITUR_BT_709);
00886         }
00887         m_render->SetCSCMatrix(m_video_mixer, videoColourSpace.GetMatrix());
00888     }
00889     m_lock.unlock();
00890 }
00891 
00892 int VideoOutputVDPAU::SetPictureAttribute(PictureAttribute attribute,
00893                                           int newValue)
00894 {
00895     if (!m_render || !m_video_mixer)
00896         return -1;
00897 
00898     m_lock.lock();
00899     newValue = videoColourSpace.SetPictureAttribute(attribute, newValue);
00900     if (newValue >= 0)
00901         m_render->SetCSCMatrix(m_video_mixer, videoColourSpace.GetMatrix());
00902     m_lock.unlock();
00903     return newValue;
00904 }
00905 
00906 QStringList VideoOutputVDPAU::GetAllowedRenderers(
00907     MythCodecID myth_codec_id, const QSize &video_dim)
00908 {
00909     (void) video_dim;
00910     QStringList list;
00911     if ((codec_is_std(myth_codec_id) || codec_is_vdpau_hw(myth_codec_id)) &&
00912          !getenv("NO_VDPAU"))
00913     {
00914         list += "vdpau";
00915     }
00916 
00917     return list;
00918 }
00919 
00920 MythCodecID VideoOutputVDPAU::GetBestSupportedCodec(
00921     uint width, uint height, const QString &decoder,
00922     uint stream_type, bool no_acceleration)
00923 {
00924     bool use_cpu = no_acceleration;
00925 
00926     MythCodecID test_cid = (MythCodecID)(kCodec_MPEG1_VDPAU + (stream_type-1));
00927     use_cpu |= !codec_is_vdpau_hw(test_cid);
00928     if (test_cid == kCodec_MPEG4_VDPAU)
00929         use_cpu |= !MythRenderVDPAU::IsMPEG4Available();
00930     if (test_cid == kCodec_H264_VDPAU)
00931         use_cpu |= !MythRenderVDPAU::H264DecoderSizeSupported(width, height);
00932     if ((decoder != "vdpau") || getenv("NO_VDPAU") || use_cpu)
00933         return (MythCodecID)(kCodec_MPEG1 + (stream_type-1));
00934 
00935     return test_cid;
00936 }
00937 
00938 void VideoOutputVDPAU::UpdateReferenceFrames(VideoFrame *frame)
00939 {
00940     while (m_reference_frames.size() > (NUM_REFERENCE_FRAMES - 1))
00941         m_reference_frames.pop_front();
00942 
00943     uint ref = m_video_surfaces[(framesPlayed +1)  % NUM_REFERENCE_FRAMES];
00944     if (!codec_is_std(video_codec_id))
00945     {
00946         struct vdpau_render_state *render =
00947             (struct vdpau_render_state *)frame->buf;
00948         if (render)
00949             ref = m_render->GetSurfaceOwner(render->surface);
00950     }
00951 
00952     m_reference_frames.push_back(ref);
00953 }
00954 
00955 bool VideoOutputVDPAU::FrameIsInUse(VideoFrame *frame)
00956 {
00957     if (!frame || codec_is_std(video_codec_id))
00958         return false;
00959 
00960     uint ref = 0;
00961     struct vdpau_render_state *render = (struct vdpau_render_state *)frame->buf;
00962     if (render)
00963         ref = m_render->GetSurfaceOwner(render->surface);
00964     return m_reference_frames.contains(ref);
00965 }
00966 
00967 void VideoOutputVDPAU::ClearReferenceFrames(void)
00968 {
00969     m_lock.lock();
00970     m_reference_frames.clear();
00971     m_lock.unlock();
00972 }
00973 
00974 void VideoOutputVDPAU::DiscardFrame(VideoFrame *frame)
00975 {
00976     if (!frame)
00977         return;
00978 
00979     m_lock.lock();
00980     if (FrameIsInUse(frame))
00981         vbuffers.safeEnqueue(kVideoBuffer_displayed, frame);
00982     else
00983     {
00984         vbuffers.DoneDisplayingFrame(frame);
00985     }
00986     m_lock.unlock();
00987 }
00988 
00989 void VideoOutputVDPAU::DiscardFrames(bool next_frame_keyframe)
00990 {
00991     m_lock.lock();
00992     LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("DiscardFrames(%1)")
00993             .arg(next_frame_keyframe));
00994     CheckFrameStates();
00995     ClearReferenceFrames();
00996     vbuffers.DiscardFrames(next_frame_keyframe);
00997     LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("DiscardFrames() 3: %1 -- done()")
00998             .arg(vbuffers.GetStatus()));
00999     m_lock.unlock();
01000 }
01001 
01002 void VideoOutputVDPAU::DoneDisplayingFrame(VideoFrame *frame)
01003 {
01004     m_lock.lock();
01005     if (vbuffers.contains(kVideoBuffer_used, frame))
01006         DiscardFrame(frame);
01007     CheckFrameStates();
01008     m_lock.unlock();
01009 }
01010 
01011 void VideoOutputVDPAU::CheckFrameStates(void)
01012 {
01013     m_lock.lock();
01014     frame_queue_t::iterator it;
01015     it = vbuffers.begin_lock(kVideoBuffer_displayed);
01016     while (it != vbuffers.end(kVideoBuffer_displayed))
01017     {
01018         VideoFrame* frame = *it;
01019         if (!FrameIsInUse(frame))
01020         {
01021             if (vbuffers.contains(kVideoBuffer_decode, frame))
01022             {
01023                 LOG(VB_PLAYBACK, LOG_INFO, LOC +
01024                     QString("Frame %1 is in use by avlib and so is "
01025                             "being held for later discarding.")
01026                             .arg(DebugString(frame, true)));
01027             }
01028             else
01029             {
01030                 vbuffers.safeEnqueue(kVideoBuffer_avail, frame);
01031                 vbuffers.end_lock();
01032                 it = vbuffers.begin_lock(kVideoBuffer_displayed);
01033                 continue;
01034             }
01035         }
01036         ++it;
01037     }
01038     vbuffers.end_lock();
01039     m_lock.unlock();
01040 }
01041 
01042 bool VideoOutputVDPAU::InitPIPLayer(QSize size)
01043 {
01044     if (!m_render)
01045         return false;
01046 
01047     if (!m_pip_surface)
01048         m_pip_surface = m_render->CreateOutputSurface(size);
01049 
01050     if (!m_pip_layer && m_pip_surface)
01051         m_pip_layer = m_render->CreateLayer(m_pip_surface);
01052 
01053     return (m_pip_surface && m_pip_layer);
01054 }
01055 
01056 void VideoOutputVDPAU::DeinitPIPS(void)
01057 {
01058     while (!m_pips.empty())
01059     {
01060         RemovePIP(m_pips.begin().key());
01061         m_pips.erase(m_pips.begin());
01062     }
01063 
01064     m_pip_ready = false;
01065 }
01066 
01067 void VideoOutputVDPAU::DeinitPIPLayer(void)
01068 {
01069     if (m_render)
01070     {
01071         if (m_pip_surface)
01072         {
01073             m_render->DestroyOutputSurface(m_pip_surface);
01074             m_pip_surface = 0;
01075         }
01076 
01077         if (m_pip_layer)
01078         {
01079             m_render->DestroyLayer(m_pip_layer);
01080             m_pip_layer = 0;
01081         }
01082     }
01083 
01084     m_pip_ready = false;
01085 }
01086 
01087 void VideoOutputVDPAU::ShowPIP(VideoFrame *frame, MythPlayer *pipplayer,
01088                                PIPLocation loc)
01089 {
01090     (void) frame;
01091     if (!pipplayer || !m_render)
01092         return;
01093 
01094     int pipw, piph;
01095     VideoFrame *pipimage       = pipplayer->GetCurrentFrame(pipw, piph);
01096     const bool  pipActive      = pipplayer->IsPIPActive();
01097     const bool  pipVisible     = pipplayer->IsPIPVisible();
01098     const float pipVideoAspect = pipplayer->GetVideoAspect();
01099     const QSize pipVideoDim    = pipplayer->GetVideoBufferSize();
01100 
01101     if ((pipVideoAspect <= 0) || !pipimage ||
01102         !pipimage->buf || pipimage->codec != FMT_YV12 || !pipVisible)
01103     {
01104         pipplayer->ReleaseCurrentFrame(pipimage);
01105         return;
01106     }
01107 
01108     if (InitPIPLayer(window.GetDisplayVisibleRect().size()))
01109     {
01110         if (m_pips.contains(pipplayer) &&
01111             m_pips[pipplayer].videoSize != pipVideoDim)
01112             RemovePIP(pipplayer);
01113 
01114         if (!m_pips.contains(pipplayer))
01115         {
01116             uint mixer = m_render->CreateVideoMixer(pipVideoDim, 0, 0);
01117             uint surf  = m_render->CreateVideoSurface(pipVideoDim);
01118             vdpauPIP tmp = { pipVideoDim, surf, mixer};
01119             m_pips.insert(pipplayer, tmp);
01120             if (!mixer || !surf)
01121                 RemovePIP(pipplayer);
01122             else
01123                 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Created pip %1x%2")
01124                     .arg(pipVideoDim.width()).arg(pipVideoDim.height()));
01125         }
01126 
01127         if (m_pips.contains(pipplayer))
01128         {
01129             QRect rect = GetPIPRect(loc, pipplayer);
01130 
01131             if (!m_pip_ready)
01132                 m_render->DrawBitmap(0, m_pip_surface, NULL, NULL,
01133                                      kVDPBlendNull);
01134 
01135             uint32_t pitches[] = {
01136                 pipimage->pitches[0],
01137                 pipimage->pitches[2],
01138                 pipimage->pitches[1] };
01139             void* const planes[] = {
01140                 pipimage->buf,
01141                 pipimage->buf + pipimage->offsets[2],
01142                 pipimage->buf + pipimage->offsets[1] };
01143 
01144             bool ok;
01145             ok = m_render->UploadYUVFrame(m_pips[pipplayer].videoSurface,
01146                                           planes, pitches);
01147             ok &= m_render->MixAndRend(m_pips[pipplayer].videoMixer,
01148                                        VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME,
01149                                        m_pips[pipplayer].videoSurface,
01150                                        m_pip_surface, NULL, false,
01151                                        QRect(QPoint(0,0), pipVideoDim),
01152                                        rect, rect);
01153             ok &= m_render->DrawBitmap(0, m_pip_surface, NULL, &rect,
01154                                        kVDPBlendPiP, 255);
01155 
01156             if (pipActive)
01157             {
01158                 // TODO this could be one rect rendered before the video frame
01159                 QRect l = QRect(QPoint(rect.x() - 10, rect.y() - 10),
01160                                 QSize(10, rect.height() + 20));
01161                 QRect t = QRect(QPoint(rect.x(), rect.y() - 10),
01162                                 QSize(rect.width(), 10));
01163                 QRect b = QRect(QPoint(rect.x(), rect.y() + rect.height()),
01164                                 QSize(rect.width(), 10));
01165                 QRect r = QRect(QPoint(rect.x() + rect.width(), rect.y() -10),
01166                                 QSize(10, rect.height() + 20));
01167                 m_render->DrawBitmap(0, m_pip_surface, NULL, &l, kVDPBlendNormal, 255, 127);
01168                 m_render->DrawBitmap(0, m_pip_surface, NULL, &t, kVDPBlendNormal, 255, 127);
01169                 m_render->DrawBitmap(0, m_pip_surface, NULL, &b, kVDPBlendNormal, 255, 127);
01170                 m_render->DrawBitmap(0, m_pip_surface, NULL, &r, kVDPBlendNormal, 255, 127);
01171             }
01172 
01173             m_pip_ready = ok;
01174         }
01175     }
01176     pipplayer->ReleaseCurrentFrame(pipimage);
01177 }
01178 
01179 void VideoOutputVDPAU::RemovePIP(MythPlayer *pipplayer)
01180 {
01181     if (!m_pips.contains(pipplayer))
01182         return;
01183 
01184     if (m_pips[pipplayer].videoSurface && m_render)
01185         m_render->DestroyVideoSurface(m_pips[pipplayer].videoSurface);
01186 
01187     if (m_pips[pipplayer].videoMixer)
01188         m_render->DestroyVideoMixer(m_pips[pipplayer].videoMixer);
01189 
01190     m_pips.remove(pipplayer);
01191     LOG(VB_PLAYBACK, LOG_INFO, LOC + "Removed 1 PIP");
01192 
01193     if (m_pips.empty())
01194         DeinitPIPLayer();
01195 }
01196 
01197 void VideoOutputVDPAU::ParseOptions(void)
01198 {
01199     m_skip_chroma = false;
01200     m_denoise     = 0.0f;
01201     m_sharpen     = 0.0f;
01202     m_colorspace  = VDP_COLOR_STANDARD_ITUR_BT_601;
01203     m_mixer_features = kVDPFeatNone;
01204 
01205     m_decoder_buffer_size = MAX_REFERENCE_FRAMES;
01206     m_process_buffer_size = DEF_PROCESS_BUFFER;
01207     if (codec_is_vdpau(video_codec_id))
01208         m_decoder_buffer_size = MIN_REFERENCE_FRAMES;
01209 
01210     QStringList list = GetFilters().split(",");
01211     if (list.empty())
01212         return;
01213 
01214     for (QStringList::Iterator i = list.begin(); i != list.end(); ++i)
01215     {
01216         QString name = (*i).section('=', 0, 0).toLower();
01217         QString opts = (*i).section('=', 1).toLower();
01218 
01219         if (!name.contains("vdpau"))
01220             continue;
01221 
01222         if (name.contains("vdpaubuffercount"))
01223         {
01224             uint num = opts.toUInt();
01225             if (MIN_PROCESS_BUFFER <= num && num <= MAX_PROCESS_BUFFER)
01226             {
01227                 LOG(VB_PLAYBACK, LOG_INFO, LOC +
01228                     QString("VDPAU process buffer size set to %1 (was %2)")
01229                         .arg(num).arg(m_process_buffer_size));
01230                 m_process_buffer_size = num;
01231             }
01232         }
01233         else if (name.contains("vdpauivtc"))
01234         {
01235             LOG(VB_PLAYBACK, LOG_INFO, LOC +
01236                 "Enabling VDPAU inverse telecine "
01237                 "(requires Basic or Advanced deinterlacer)");
01238             m_mixer_features |= kVDPFeatIVTC;
01239         }
01240         else if (name.contains("vdpauskipchroma"))
01241         {
01242             LOG(VB_PLAYBACK, LOG_INFO, LOC + "Enabling SkipChromaDeinterlace.");
01243             m_skip_chroma = true;
01244         }
01245         else if (name.contains("vdpaudenoise"))
01246         {
01247             float tmp = std::max(0.0f, std::min(1.0f, opts.toFloat()));
01248             if (tmp != 0.0)
01249             {
01250                 LOG(VB_PLAYBACK, LOG_INFO, LOC +
01251                     QString("VDPAU Denoise %1").arg(tmp,4,'f',2,'0'));
01252                 m_denoise = tmp;
01253                 m_mixer_features |= kVDPFeatDenoise;
01254             }
01255         }
01256         else if (name.contains("vdpausharpen"))
01257         {
01258             float tmp = std::max(-1.0f, std::min(1.0f, opts.toFloat()));
01259             if (tmp != 0.0)
01260             {
01261                 LOG(VB_PLAYBACK, LOG_INFO, LOC +
01262                     QString("VDPAU Sharpen %1").arg(tmp,4,'f',2,'0'));
01263                 m_sharpen = tmp;
01264                 m_mixer_features |= kVDPFeatSharpness;
01265             }
01266         }
01267         else if (name.contains("vdpaucolorspace"))
01268         {
01269             if (opts.contains("auto"))
01270                 m_colorspace = -1;
01271             else if (opts.contains("601"))
01272                 m_colorspace = VDP_COLOR_STANDARD_ITUR_BT_601;
01273             else if (opts.contains("709"))
01274                 m_colorspace = VDP_COLOR_STANDARD_ITUR_BT_709;
01275 
01276             if (m_colorspace > -1)
01277             {
01278                 LOG(VB_PLAYBACK, LOG_INFO, LOC +
01279                     QString("Forcing ITU BT.%1 colorspace")
01280                         .arg((m_colorspace == VDP_COLOR_STANDARD_ITUR_BT_601) ?
01281                              "BT.601" : "BT.709"));
01282             }
01283         }
01284         else if (name.contains("vdpauhqscaling"))
01285         {
01286             m_mixer_features |= kVDPFeatHQScaling;
01287             LOG(VB_PLAYBACK, LOG_INFO, LOC +
01288                 "Requesting high quality scaling.");
01289         }
01290     }
01291 }
01292 
01293 MythPainter *VideoOutputVDPAU::GetOSDPainter(void)
01294 {
01295     return m_osd_painter;
01296 }
01297 
01298 bool VideoOutputVDPAU::GetScreenShot(int width, int height, QString filename)
01299 {
01300     if (m_render)
01301         return m_render->GetScreenShot(width, height, filename);
01302     return false;
01303 }
01304 
01305 QStringList VideoOutputVDPAU::GetVisualiserList(void)
01306 {
01307     if (m_render)
01308         return VideoVisual::GetVisualiserList(m_render->Type());
01309     return VideoOutput::GetVisualiserList();
01310 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends