Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with channel change when audio changes from dd5.1 to aac #108

Open
mrmojo666 opened this issue Sep 3, 2019 · 2 comments
Open

Problem with channel change when audio changes from dd5.1 to aac #108

mrmojo666 opened this issue Sep 3, 2019 · 2 comments

Comments

@mrmojo666
Copy link

I post also here the same message taht i posted on the forum:
https://forum.kodi.tv/showthread.php?tid=342732&pid=2882328#pid2882328

I still trying to understand this issue.
I've tried also a different pvr server (Nextpvr) a different kodi addon Nextpvr client.
At the start i had the same audio switch issue on channel change, but juggling with their addon i found they have a setting that stop the stream during a channel change. And it made the magic: no more audio issues when channge change.
At this point I started to be confused, in mediaportal client setting there is a fastchannel switch that if i'm not wrong should do the same, so if the fast change switch is not selected I'm expecting that th stream is closed on each channel change.
So i started to look at your code on github and i found that in the very early implemetation of your plugin there is a function that is named switchchannel that check that setting and in case call CloseLiveStream before the OpenLiveStream.

https://github.com/margro/xbmc-pvr-addons/blob/development/addons/pvr.mediaportal.tvserver/src/pvrclient-mediaportal.cpp

bool cPVRClientMediaPortal::SwitchChannel(const PVR_CHANNEL &channel)
{
if (((int)channel.iUniqueId) == m_iCurrentChannel)
return true;
if (g_eStreamingMethod == TSReader)
{
XBMC->Log(LOG_NOTICE, "SwitchChannel(uid=%i) tsreader: open a new live stream", channel.iUniqueId);
if (!g_bFastChannelSwitch)
{
// Close existing live stream before opening a new one.
// This is slower, but it helps XBMC playback when the streams change types (e.g. SD->HD)
TRACE("Fast channel switching is disabled. Closing the existing live stream first");
CloseLiveStream();
}
return OpenLiveStream(channel);
}
else
{
XBMC->Log(LOG_DEBUG, "SwitchChannel(uid=%i) ffmpeg rtsp: nothing to be done here... GetLiveSteamURL() should fetch a new rtsp url from the backend.", channel.iUniqueId);
return false;
}
}

in the new implementations i can't find a SwitchChannel function but (if I've correctly understood) it is always called a OpenLiveStream function for start tv or to change channel.

inside this fuction i can't find any check on fastchannel switch setting , so the CloseStream is called only in case of errors.

https://github.com/kodi-pvr/pvr.mediaportal.tvserver/blob/63de57a99ba5deabe2a710124224fd593bccdba4/src/pvrclient-mediaportal.cpp

bool cPVRClientMediaPortal::OpenLiveStream(const PVR_CHANNEL &channelinfo)
{
string result;
char command[256] = "";
const char* sResolveRTSPHostname = booltostring(g_bResolveRTSPHostname);
vector<string> timeshiftfields;
KODI->Log(LOG_NOTICE, "Open Live stream for channel uid=%i", channelinfo.iUniqueId);
if (!IsUp())
{
m_iCurrentChannel = -1;
m_bTimeShiftStarted = false;
m_bSkipCloseLiveStream = false; //initialization
m_signalStateCounter = 0;
KODI->Log(LOG_ERROR, "Open Live stream failed. No connection to backend.");
return false;
}
if (((int)channelinfo.iUniqueId) == m_iCurrentChannel)
{
KODI->Log(LOG_NOTICE, "New channel uid equal to the already streaming channel. Skipping re-tune.");
return true;
}
m_iCurrentChannel = -1; // make sure that it is not a valid channel nr in case it will fail lateron
m_signalStateCounter = 0;
m_bTimeShiftStarted = false;
m_bSkipCloseLiveStream = false; //initialization
// Start the timeshift
// Use the optimized TimeshiftChannel call (don't stop a running timeshift)
snprintf(command, 256, "TimeshiftChannel:%i|%s|False\n", channelinfo.iUniqueId, sResolveRTSPHostname);
result = SendCommand(command);
if (result.find("ERROR") != std:tring::npos || result.length() == 0)
{
KODI->Log(LOG_ERROR, "Could not start the timeshift for channel uid=%i. Reason: %s", channelinfo.iUniqueId, result.c_str());
if (g_iTVServerKodiBuild>=109)
{
Tokenize(result, timeshiftfields, "|");
//[0] = string error message
//[1] = TvResult (optional field. SendCommand can also return a timeout)
if(timeshiftfields.size()>1)
{
//For TVServer 1.2.1:
//enum TvResult
//{
// Succeeded = 0, (this is not an error)
// AllCardsBusy = 1,
// ChannelIsScrambled = 2,
// NoVideoAudioDetected = 3,
// NoSignalDetected = 4,
// UnknownError = 5,
// UnableToStartGraph = 6,
// UnknownChannel = 7,
// NoTuningDetails = 8,
// ChannelNotMappedToAnyCard = 9,
// CardIsDisabled = 10,
// ConnectionToSlaveFailed = 11,
// NotTheOwner = 12,
// GraphBuildingFailed = 13,
// SWEncoderMissing = 14,
// NoFreeDiskSpace = 15,
// NoPmtFound = 16,
//};
int tvresult = atoi(timeshiftfields[1].c_str());
// Display one of the localized error messages 30060-30075
KODI->QueueNotification(QUEUE_ERROR, KODI->GetLocalizedString(30059 + tvresult));
}
else
{
KODI->QueueNotification(QUEUE_ERROR, result.c_str());
}
}
else
{
if (result.find("[ERROR]: TVServer answer: ") != std:tring::npos)
{
//Skip first part: "[ERROR]: TVServer answer: "
KODI->QueueNotification(QUEUE_ERROR, "TVServer: %s", result.substr(26).c_str());
}
else
{
//Skip first part: "[ERROR]: "
KODI->QueueNotification(QUEUE_ERROR, result.substr(7).c_str());
}
}
m_iCurrentChannel = -1;
if (m_tsreader != nullptr)
{
SAFE_DELETE(m_tsreader);
}
return false;
}
else
{
Tokenize(result, timeshiftfields, "|");
if(timeshiftfields.size()<4)
{
KODI->Log(LOG_ERROR, "OpenLiveStream: Field count mismatch (<4). Data: %s\n", result.c_str());
m_iCurrentChannel = -1;
return false;
}
//[0] = rtsp url
//[1] = original (unresolved) rtsp url
//[2] = timeshift buffer filename
//[3] = card id (TVServerKodi build >= 106)
//[4] = tsbuffer pos (TVServerKodi build >= 110)
//[5] = tsbuffer file nr (TVServerKodi build >= 110)
m_PlaybackURL = timeshiftfields[0];
if (g_eStreamingMethod == TSReader)
{
KODI->Log(LOG_NOTICE, "Channel timeshift buffer: %s", timeshiftfields[2].c_str());
if (channelinfo.bIsRadio)
{
usleep(100000); // 100 ms sleep to allow the buffer to fill
}
}
else
{
KODI->Log(LOG_NOTICE, "Channel stream URL: %s", m_PlaybackURL.c_str());
}
if (g_iSleepOnRTSPurl > 0)
{
KODI->Log(LOG_NOTICE, "Sleeping %i ms before opening stream: %s", g_iSleepOnRTSPurl, timeshiftfields[0].c_str());
usleep(g_iSleepOnRTSPurl * 1000);
}
// Check the returned stream URL. When the URL is an rtsp stream, we need
// to close it again after watching to stop the timeshift.
// A radio web stream (added to the TV Server) will return the web stream
// URL without starting a timeshift.
if(timeshiftfields[0].compare(0,4, "rtsp") == 0)
{
m_bTimeShiftStarted = true;
}
if (g_eStreamingMethod == TSReader)
{
if (m_tsreader != NULL)
{
bool bReturn = false;
// Continue with the existing TsReader.
KODI->Log(LOG_NOTICE, "Re-using existing TsReader...");
//if(g_bDirectTSFileRead)
if(g_bUseRTSP == false)
{
m_tsreader->SetCardId(atoi(timeshiftfields[3].c_str()));
if ((g_iTVServerKodiBuild >=110) && (timeshiftfields.size()>=6))
bReturn = m_tsreader->OnZap(timeshiftfields[2].c_str(), atoll(timeshiftfields[4].c_str()), atol(timeshiftfields[5].c_str()));
else
bReturn = m_tsreader->OnZap(timeshiftfields[2].c_str(), -1, -1);
}
else
{
// RTSP url
KODI->Log(LOG_NOTICE, "Skipping OnZap for TSReader RTSP");
bReturn = true; //Fast forward seek (OnZap) does not work for RTSP
}
if (bReturn)
{
m_iCurrentChannel = (int) channelinfo.iUniqueId;
m_iCurrentCard = atoi(timeshiftfields[3].c_str());
m_bCurrentChannelIsRadio = channelinfo.bIsRadio;
}
else
{
KODI->Log(LOG_ERROR, "Re-using the existing TsReader failed.");
CloseLiveStream();
}
return bReturn;
}
else
{
KODI->Log(LOG_NOTICE, "Creating a new TsReader...");
m_tsreader = new CTsReader();
}
if (!g_bUseRTSP)
{
// Reading directly from the Timeshift buffer
m_tsreader->SetCardSettings(&m_cCards);
m_tsreader->SetCardId(atoi(timeshiftfields[3].c_str()));
//if (g_szTimeshiftDir.length() > 0)
// m_tsreader->SetDirectory(g_szTimeshiftDir);
if ( m_tsreader->Open(timeshiftfields[2].c_str()) != S_OK )
{
KODI->Log(LOG_ERROR, "Cannot open timeshift buffer %s", timeshiftfields[2].c_str());
CloseLiveStream();
return false;
}
}
else
{
// use the RTSP url and live555
if ( m_tsreader->Open(timeshiftfields[0].c_str()) != S_OK)
{
KODI->Log(LOG_ERROR, "Cannot open channel url %s", timeshiftfields[0].c_str());
CloseLiveStream();
return false;
}
usleep(400000);
}
}
// at this point everything is ready for playback
m_iCurrentChannel = (int) channelinfo.iUniqueId;
m_iCurrentCard = atoi(timeshiftfields[3].c_str());
m_bCurrentChannelIsRadio = channelinfo.bIsRadio;
}
KODI->Log(LOG_NOTICE, "OpenLiveStream: success for channel id %i (%s) on card %i", m_iCurrentChannel, channelinfo.strChannelName, m_iCurrentCard);
return true;
}

Can you confirm that I'm not wrong and the fastchannel setting is ignored ?

Thank you

@mrmojo666
Copy link
Author

mrmojo666 commented Sep 3, 2019

I've forked this repo , and I'm going to try to modify this :

snprintf(command, 256, "TimeshiftChannel:%i|%s|False\n", channelinfo.iUniqueId, sResolveRTSPHostname);

in to this:
snprintf(command, 256, "TimeshiftChannel:%i|%s|True\n", channelinfo.iUniqueId, sResolveRTSPHostname);

if I've understood, looking at the mediaportal server plugin code. If i pset that parameter to True it should trigger a timeshift stop on the server before tuning the new channel.

I'll let you know the result of this test

@mrmojo666
Copy link
Author

unfortunately is not that simple...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant