bool VideoOutputOpenGLVAAPI::CreateVAAPIContext(QSize size) { // FIXME During a video stream change this is called from the decoder // thread - which breaks all other efforts to remove non-UI thread // access to the OpenGL context. There is no obvious fix however - if we // don't delete and re-create the VAAPI decoder context immediately then // the decoder fails and playback exits. OpenGLLocker ctx_lock(gl_context); if (m_ctx) DeleteVAAPIContext(); m_ctx = new VAAPIContext(video_codec_id); if (m_ctx && m_ctx->CreateDisplay(size) && m_ctx->CreateBuffers()) { int num_buffers = m_ctx->GetNumBuffers(); const QSize video_dim = window.GetActualVideoDim(); bool ok = true; for (int i = 0; i < num_buffers; i++) { ok &= vbuffers.CreateBuffer(video_dim.width(), video_dim.height(), i, m_ctx->GetVideoSurface(i), FMT_VAAPI); } InitPictureAttributes(); return ok; } LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create VAAPI context."); errorState = kError_Unknown; return false; }
bool VideoOutputVDPAU::Init(int width, int height, float aspect, WId winid, const QRect &win_rect, MythCodecID codec_id) { // Attempt to free up as much video memory as possible // only works when using the VDPAU painter for the UI MythPainter *painter = GetMythPainter(); if (painter) painter->FreeResources(); m_win = winid; QMutexLocker locker(&m_lock); window.SetNeedRepaint(true); bool ok = VideoOutput::Init(width, height, aspect, winid, win_rect,codec_id); if (db_vdisp_profile) db_vdisp_profile->SetVideoRenderer("vdpau"); InitDisplayMeasurements(width, height, true); ParseOptions(); if (ok) ok = InitRender(); if (ok) ok = InitBuffers(); if (!ok) { TearDown(); return ok; } InitPictureAttributes(); MoveResize(); LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Created VDPAU context (%1 decode)") .arg(codec_is_std(video_codec_id) ? "software" : "GPU")); return ok; }
bool VideoOutputOpenGL::Init(const QSize &video_dim_buf, const QSize &video_dim_disp, float aspect, WId winid, const QRect &win_rect, MythCodecID codec_id) { QMutexLocker locker(&gl_context_lock); bool success = true; window.SetAllowPreviewEPG(true); gl_parent_win = winid; success &= VideoOutput::Init(video_dim_buf, video_dim_disp, aspect, winid, win_rect, codec_id); SetProfile(); InitPictureAttributes(); success &= CreateCPUResources(); if (!gCoreContext->IsUIThread()) { LOG(VB_GENERAL, LOG_NOTICE, LOC + "Deferring creation of OpenGL resources"); gl_valid = false; } else { success &= CreateGPUResources(); success &= CreateVideoResources(); } if (!success) TearDown(); return success; }
bool VideoOutputOpenGL::Init(int width, int height, float aspect, WId winid, const QRect &win_rect, MythCodecID codec_id) { QMutexLocker locker(&gl_context_lock); bool success = true; // FIXME Mac OS X overlay does not work with preview window.SetAllowPreviewEPG(true); gl_parent_win = winid; VideoOutput::Init(width, height, aspect, winid, win_rect, codec_id); SetProfile(); InitPictureAttributes(); success &= SetupContext(); InitDisplayMeasurements(width, height, false); success &= CreateBuffers(); success &= CreatePauseFrame(); success &= SetupOpenGL(); InitOSD(); MoveResize(); if (!success) TearDown(); return success; }
bool VideoOutputOpenGLVAAPI::CreateVAAPIContext(QSize size) { // FIXME During a video stream change this is called from the decoder // thread - which breaks all other efforts to remove non-UI thread // access to the OpenGL context. There is no obvious fix however - if we // don't delete and re-create the VAAPI decoder context immediately then // the decoder fails and playback exits. // lvr 27-oct-13 // in 0.27 if m_ctx->CreateDisplay is called outside of the UI thread then // it fails, which then causes subsequent unbalanced calls to doneCurrent // which results in Qt aborting. So just fail if non-UI. if (!gCoreContext->IsUIThread()) { LOG(VB_GENERAL, LOG_ERR, LOC + "CreateVAAPIContext called from non-UI thread"); return false; } OpenGLLocker ctx_lock(gl_context); if (m_ctx) DeleteVAAPIContext(); m_ctx = new VAAPIContext(kVADisplayGLX, video_codec_id); if (m_ctx && m_ctx->CreateDisplay(size) && m_ctx->CreateBuffers()) { int num_buffers = m_ctx->GetNumBuffers(); const QSize video_dim = window.GetActualVideoDim(); bool ok = true; for (int i = 0; i < num_buffers; i++) { ok &= vbuffers.CreateBuffer(video_dim.width(), video_dim.height(), i, m_ctx->GetVideoSurface(i), FMT_VAAPI); } InitPictureAttributes(); return ok; } LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create VAAPI context."); errorState = kError_Unknown; return false; }
bool DTVChannel::SetChannelByString(const QString &channum) { QString loc = LOC + QString("SetChannelByString(%1): ").arg(channum); LOG(VB_CHANNEL, LOG_INFO, loc); ClearDTVInfo(); if (!IsOpen() && !Open()) { LOG(VB_GENERAL, LOG_ERR, loc + "Channel object " "will not open, can not change channels."); return false; } if (m_inputs.size() > 1) { QString inputName; if (!CheckChannel(channum, inputName)) { LOG(VB_GENERAL, LOG_ERR, loc + "CheckChannel failed.\n\t\t\tPlease verify the channel " "in the 'mythtv-setup' Channel Editor."); return false; } // If CheckChannel filled in the inputName then we need to // change inputs and return, since the act of changing // inputs will change the channel as well. if (!inputName.isEmpty()) return SwitchToInput(inputName, channum); } InputMap::const_iterator it = m_inputs.find(m_currentInputID); if (it == m_inputs.end()) return false; uint mplexid_restriction; uint chanid_restriction; if (!IsInputAvailable(m_currentInputID, mplexid_restriction, chanid_restriction)) { LOG(VB_GENERAL, LOG_INFO, loc + QString("Requested channel '%1' is on input '%2' " "which is in a busy input group") .arg(channum).arg(m_currentInputID)); return false; } // Fetch tuning data from the database. QString tvformat, modulation, freqtable, freqid, si_std; int finetune; uint64_t frequency; int mpeg_prog_num; uint atsc_major, atsc_minor, mplexid, chanid, tsid, netid; if (!ChannelUtil::GetChannelData( (*it)->sourceid, chanid, channum, tvformat, modulation, freqtable, freqid, finetune, frequency, si_std, mpeg_prog_num, atsc_major, atsc_minor, tsid, netid, mplexid, m_commfree)) { LOG(VB_GENERAL, LOG_ERR, loc + "Unable to find channel in database."); return false; } if ((mplexid_restriction && (mplexid != mplexid_restriction)) || (chanid_restriction && (chanid != chanid_restriction))) { LOG(VB_GENERAL, LOG_ERR, loc + QString("Requested channel '%1' is not available because " "the tuner is currently in use on another transport.") .arg(channum)); return false; } // If the frequency is zeroed out, don't use it directly. if (frequency == 0) { frequency = (freqid.toULongLong() + finetune) * 1000; mplexid = 0; } bool isFrequency = (frequency > 10000000); bool hasTuneToChan = !(*it)->tuneToChannel.isEmpty() && (*it)->tuneToChannel != "Undefined"; // If we are tuning to a freqid, rather than an actual frequency, // we may need to set the frequency table to use. if (!isFrequency || hasTuneToChan) SetFreqTable(freqtable); // Set NTSC, PAL, ATSC, etc. SetFormat(tvformat); // If a tuneToChannel is set make sure we're still on it if (hasTuneToChan) Tune((*it)->tuneToChannel, 0); // Clear out any old PAT or PMT & save version info uint version = 0; if (genPAT) { version = (genPAT->Version()+1) & 0x1f; delete genPAT; genPAT = NULL; delete genPMT; genPMT = NULL; } bool ok = true; if ((*it)->externalChanger.isEmpty()) { if (IsIPTV()) { int chanid = ChannelUtil::GetChanID((*it)->sourceid, channum); IPTVTuningData tuning = ChannelUtil::GetIPTVTuningData(chanid); if (!Tune(tuning, false)) { LOG(VB_GENERAL, LOG_ERR, loc + "Tuning to IPTV URL"); ClearDTVInfo(); ok = false; } } else if ((*it)->name.contains("composite", Qt::CaseInsensitive) || (*it)->name.contains("s-video", Qt::CaseInsensitive)) { LOG(VB_GENERAL, LOG_WARNING, loc + "You have not set " "an external channel changing" "\n\t\t\tscript for a composite or s-video " "input. Channel changing will do nothing."); } else if (isFrequency && Tune(frequency, "")) { } else if (isFrequency) { // Initialize basic the tuning parameters DTVMultiplex tuning; if (!mplexid || !tuning.FillFromDB(tunerType, mplexid)) { LOG(VB_GENERAL, LOG_ERR, loc + "Failed to initialize multiplex options"); ok = false; } else { // Try to fix any problems with the multiplex CheckOptions(tuning); // Tune to proper multiplex if (!Tune(tuning, (*it)->name)) { LOG(VB_GENERAL, LOG_ERR, loc + "Tuning to frequency."); ClearDTVInfo(); ok = false; } } } else { // ExternalChannel justs wants the channum ok = freqid.isEmpty() && finetune == 0 ? Tune(channum) : Tune(freqid, finetune); } } LOG(VB_CHANNEL, LOG_INFO, loc + ((ok) ? "success" : "failure")); if (!ok) return false; if (atsc_minor || (mpeg_prog_num>=0)) { SetSIStandard(si_std); SetDTVInfo(atsc_major, atsc_minor, netid, tsid, mpeg_prog_num); } else if (IsPIDTuningSupported()) { // We need to pull the pid_cache since there are no tuning tables pid_cache_t pid_cache; int chanid = ChannelUtil::GetChanID((*it)->sourceid, channum); ChannelUtil::GetCachedPids(chanid, pid_cache); if (pid_cache.empty()) { LOG(VB_GENERAL, LOG_ERR, loc + "PID cache is empty"); return false; } // Now we construct the PAT & PMT vector<uint> pnum; pnum.push_back(1); vector<uint> pid; pid.push_back(9999); genPAT = ProgramAssociationTable::Create(0,version,pnum,pid); int pcrpid = -1; vector<uint> pids; vector<uint> types; pid_cache_t::iterator pit = pid_cache.begin(); for (; pit != pid_cache.end(); ++pit) { if (!pit->GetStreamID()) continue; pids.push_back(pit->GetPID()); types.push_back(pit->GetStreamID()); if (pit->IsPCRPID()) pcrpid = pit->GetPID(); if ((pcrpid < 0) && StreamID::IsVideo(pit->GetStreamID())) pcrpid = pit->GetPID(); } if (pcrpid < 0) pcrpid = pid_cache[0].GetPID(); genPMT = ProgramMapTable::Create( pnum.back(), pid.back(), pcrpid, version, pids, types); SetSIStandard("mpeg"); SetDTVInfo(0,0,0,0,-1); } // Set the current channum to the new channel's channum m_curchannelname = channum; // Setup filters & recording picture attributes for framegrabing recorders // now that the new curchannelname has been established. if (m_pParent) m_pParent->SetVideoFiltersForChannel(GetCurrentSourceID(), channum); InitPictureAttributes(); HandleScript(freqid); return ok; }