Kodi Community Forum
New MythTV add-on using libcmyth - Printable Version

+- Kodi Community Forum (https://forum.kodi.tv)
+-- Forum: Development (https://forum.kodi.tv/forumdisplay.php?fid=32)
+--- Forum: Add-ons (https://forum.kodi.tv/forumdisplay.php?fid=26)
+---- Forum: PVR (https://forum.kodi.tv/forumdisplay.php?fid=136)
+---- Thread: New MythTV add-on using libcmyth (/showthread.php?tid=110694)



RE: New MythTV add-on using libcmyth - janbar - 2012-10-08

(2012-10-07, 20:23)cfetzer Wrote:
(2012-10-07, 20:02)janbar Wrote:
(2012-10-07, 15:48)cfetzer Wrote: @janbar: Did you have a closer look at the mythtv/mythfrontend sources and how they handle the chain updates and those 2 related events? The mythtv sources helped me a lot when implementing the multiplex detection. Both libcmyth and the myth protocol docs lack docs very often but mythtv's code itself is pretty readable.
I'm almost done with the fileops rework. If you and aubrian have a proper fix for the 'show stopping' and the 'delayed start', I can help integrating those changes into my repo.

@cfetzer
Yes had a look and to resolve it i added event LIVETV_WATCH to manage the program break. Now it is closed and i am preparing to merge with you. Aubrien has a special context needing a delay to refill buffer after each stage: spawn tv, switch channel and program break. At the moment libcmyth or xbmc player does not manage any delay before retry. So retries to read live stream loop without delay and after 150 retries in a short time the player close live stream. I try to find a global solution with him to manage this case without adding unnecessary waiting time. I think it is possible and it will be an improvement for the addon.
Soon i will pull request to you. This merge it is an hard work and i don't want to break anything. br

Also i will making more than one pull request to simplify the merge. My updated cmyth is fully compatible even without program break management.

Great Smile I'm done now with the cleanups.
FileOps uses now XBMC's internal file system access methods and no more boost::filesystem and I also fixed the bug that images for new recordings were only present after a xbmc restart.
Also the translations are now done via Transifex ( https://www.transifex.com/projects/p/pvrmythtvcmyth ). Anyone is welcome to contribute translations!

@janbar: Yes, please add either different commits to a single PR or create multiple PRs. Please split / combine them by topics and please split all cmyth related commits (so they can be merged to libcmyth upstream at some time). Currently I have all cmyth related commits prefixed with [cmyth] and all plugin related commits with [mythtv-cmyth].
Then it would be great if you could either comment your changes quite verbose (either in the source files or in the PRs). That helps to understand all the details.
And just let me know if you need any help with the merge!

I seen this message to late. I committed without [topic]. Also your cleaning is GREAT. I am a newbie with c++, i prefer basic language like c, but it seem very clean now. :-)



RE: New MythTV add-on using libcmyth - janbar - 2012-10-08

@cfetzer,

Great, Great thing. I merged in one pass only and made build and then:

+--------------------------------------+--------+----------+---------------------+---------------------+----------+
| chainid | chanid | chainpos | starttime | endtime | cardtype |
+--------------------------------------+--------+----------+---------------------+---------------------+----------+
| live-jlb-desktop-2012-10-08T02:07:36 | 1009 | 0 | 2012-10-08 02:07:37 | 2012-10-08 02:07:39 | DUMMY |
| live-jlb-desktop-2012-10-08T02:07:36 | 1009 | 1 | 2012-10-08 02:07:39 | 2012-10-08 02:08:55 | DVB |
| live-jlb-desktop-2012-10-08T02:07:36 | 1009 | 2 | 2012-10-08 02:08:53 | 2012-10-08 02:08:58 | DVB |
| live-jlb-desktop-2012-10-08T02:07:36 | 1009 | 3 | 2012-10-08 02:08:56 | 2012-10-08 02:09:01 | DVB |
| live-jlb-desktop-2012-10-08T02:07:36 | 1009 | 4 | 2012-10-08 02:08:59 | 2012-10-08 02:09:05 | DVB |
| live-jlb-desktop-2012-10-08T02:07:36 | 1009 | 5 | 2012-10-08 02:09:02 | 2012-10-08 02:12:33 | DVB |
| live-jlb-desktop-2012-10-08T02:07:36 | 1009 | 6 | 2012-10-08 02:12:31 | 2012-10-08 02:15:14 | DVB |
+--------------------------------------+--------+----------+---------------------+---------------------+----------+

On musical channel with lot of program breaks, all is okay now.



RE: New MythTV add-on using libcmyth - Aubrien - 2012-10-08

That's awsome. I see the PR at cftezer's repo and it looks like the buffer fill code will be merged as well and the delay before program change setting will be removed. I'm happy about that as once the buffer code is working correctly it will fix the channel change delay at the same time. Good work guys!


RE: New MythTV add-on using libcmyth - janbar - 2012-10-08

@Aubrien,

I just finished the merge with cftezer and requested to pull my changes. At the moment you will find on my repo:

- branch old_master : My old addon pvr.cmyth with all improvements designed with you.

- branch new_old_master : My first merge (containing all improvements) with cfetzer, addon is named pvr.mythtv.cmyth and xbmc api is 1.3.0 (10 days ago).

- banch master : My final merge with last cftezer based on xbmc api 1.4.0 (nightly).




@Aubrien

also, i included a timeout on buffer empty. Let me know how it improves addon on your system.


RE: New MythTV add-on using libcmyth - Aubrien - 2012-10-08

You're the man Jan! As soon as the new Dexter is over I'll check it out, lol.


RE: New MythTV add-on using libcmyth - Aubrien - 2012-10-08

@janbar
(2012-10-07, 18:41)janbar Wrote: @Aubrien,

I had a timeout on empty buffer to manage your case. It is not related to program break. Just player need to wait refilling buffer. commit is 4bb5093.
I hope it close your issue. Think player retry x150 reads before closing live stream. So waiting 0.5s x 150 ~ 1 minute. At the moment i fixed 0.5s per retry.
br.

As I mentioned earlier, this feature isn't working yet but I have a question. The block of code that has the 0.5s delay you mentioned is in the cmyth_livetv_chain_switch function. This isn't getting called every read so I don't think it will be called up to 150 times as you said. Was this supposed to be located somewhere different in the code perhaps?

Code:
    /* JLB: Current buffer is empty on the last file.
* We are waiting refilling the buffer until file data
* connection is up.
* Timeout is 0.5 seconde before release.
*/
else {
cmyth_dbg(CMYTH_DBG_ERROR,
"%s: wait some time before request block\n",
__FUNCTION__);
//for ( i = 0; i < 4; i++ ) {
pthread_mutex_unlock(&mutex);
/* Check file data connection. If up then wait */
if ( cmyth_file_data_conn_fd(rec->rec_livetv_file) == 1 )
usleep(500000);
pthread_mutex_lock(&mutex);
//}
}



RE: New MythTV add-on using libcmyth - Aubrien - 2012-10-08

I have played with the new buffer wait code and it looks like it just freezes at both a show transition and when attempting to tune with a 0s tuning delay.


RE: New MythTV add-on using libcmyth - dteirney - 2012-10-08

(2012-10-03, 21:11)Aubrien Wrote: OK, I have had live tv playing for hours now without it stopping so I think its time to post the solution. There are two delays needed as well as an object lock. I based this on cfetzer's code not janbar's since that is where we are moving to anyway. The changes are below...

addons/pvr.mythtv.cmyth/src/pvrclient-mythtv.cpp
Code:
bool PVRClientMythTV::OpenLiveStream(const PVR_CHANNEL &channel)
{
  if (g_bExtraDebug)
    XBMC->Log(LOG_DEBUG,"%s - chanID: %i, channumber: %i", __FUNCTION__, channel.iUniqueId, channel.iChannelNumber);

  SingleLock<PLATFORM::CMutex> lock(&m_lock);
  if (m_rec.IsNull())
  {
    MythChannel chan = m_channels.at(channel.iUniqueId);
    for (std::vector<int>::iterator it = m_sources.at(chan.SourceID()).begin(); it != m_sources.at(chan.SourceID()).end(); it++)
    {
      m_rec = m_con.GetRecorder(*it);
      if (!m_rec.IsRecording() && m_rec.IsTunable(chan))
      {
        if (g_bExtraDebug)
          XBMC->Log(LOG_DEBUG,"%s: Opening new recorder %i", __FUNCTION__, m_rec.ID());

        if (m_pEventHandler)
          m_pEventHandler->SetRecorder(m_rec);

        if (m_rec.SpawnLiveTV(chan))
        {
          usleep(10000000); //Channel change delay of 10s
          return true;
        }
      }
      m_rec = MythRecorder();
      if (m_pEventHandler)
      {
        m_pEventHandler->SetRecorder(m_rec); // Redundant
      }
    }

    if (g_bExtraDebug)
      XBMC->Log(LOG_DEBUG,"%s - Done", __FUNCTION__);
    return false;
  }
  else
  {
    if (g_bExtraDebug)
      XBMC->Log(LOG_DEBUG,"%s - Done", __FUNCTION__);

    return true;
  }
}
Add the delay for changing channels.

addons/pvr.mythtv.cmyth/src/cppmyth/MythRecorder.cpp
Code:
bool MythRecorder::LiveTVChainUpdate(CStdString chainID)
{
  char* buffer=strdup(chainID.c_str());
  m_recorder_t->Lock();
  int retval = 0;

  usleep(5000000); // Program switch delay of 5s

  CMYTH_REC_CALL( retval, retval < 0, cmyth_livetv_chain_update( *m_recorder_t, buffer, 16*1024 ) );
  if(retval != 0)
    XBMC->Log(LOG_ERROR,"LiveTVChainUpdate failed on chainID: %s",buffer);
  *livechainupdated=1;
  m_recorder_t->Unlock();
  free(buffer);
  return retval==0;
}
Uncomment the lock/unlock. Add the delay for between shows.

addons/pvr.mythtv.cmyth/src/cppmyth/MythRecorder.cpp
Code:
int MythRecorder::ReadLiveTV(void* buffer,unsigned long length)
{

  m_recorder_t->Lock();
  int bytesRead=0;
  CMYTH_REC_CALL( bytesRead, bytesRead < 0, cmyth_livetv_read( *m_recorder_t, static_cast<char*>( buffer ), length ) );
  m_recorder_t->Unlock();
  return bytesRead;
}
Uncomment the lock/unlock

The end result of this makes the channels change properly either from nothing being played or from already watching tv. The delay is especially useful for those of us with IR blasters and analog tuners. Additionally, when the chain is updated (program transition) it locks the recorder for 5s. During this time read operations delay and the user is prevented from underrunning the buffer on the backend. Both the channel change delay and the program switch delay should be made into addon settings to be user configured. Mine works with the static values I inserted for developing the fix. Between program transitions you will see a "Buffering %" dialog for a second or so. This buffering is essential as each program transition causes no data for a small period and eventually the buffer is depleted and this makes it refill.

Rather than a hard-coded 5 second delay could you look at doing something more like was done in one of my branches. Unfortunately still not cleaned up and ready for PR to upstream libcmyth. https://github.com/dteirney/xbmc/commit/afe18e73725c66bde621f4bd0643bd96ecac88b2

That commit also has the fix for the LiveTV locking problem as well.



RE: New MythTV add-on using libcmyth - dteirney - 2012-10-08

Information in http://forum.xbmc.org/showthread.php?tid=131011 that related to the delay issue for HD Homerun type tuners.


RE: New MythTV add-on using libcmyth - janbar - 2012-10-08

(2012-10-08, 05:51)Aubrien Wrote: @janbar
(2012-10-07, 18:41)janbar Wrote: @Aubrien,

I had a timeout on empty buffer to manage your case. It is not related to program break. Just player need to wait refilling buffer. commit is 4bb5093.
I hope it close your issue. Think player retry x150 reads before closing live stream. So waiting 0.5s x 150 ~ 1 minute. At the moment i fixed 0.5s per retry.
br.

As I mentioned earlier, this feature isn't working yet but I have a question. The block of code that has the 0.5s delay you mentioned is in the cmyth_livetv_chain_switch function. This isn't getting called every read so I don't think it will be called up to 150 times as you said. Was this supposed to be located somewhere different in the code perhaps?

Code:
    /* JLB: Current buffer is empty on the last file.
* We are waiting refilling the buffer until file data
* connection is up.
* Timeout is 0.5 seconde before release.
*/
else {
cmyth_dbg(CMYTH_DBG_ERROR,
"%s: wait some time before request block\n",
__FUNCTION__);
//for ( i = 0; i < 4; i++ ) {
pthread_mutex_unlock(&mutex);
/* Check file data connection. If up then wait */
if ( cmyth_file_data_conn_fd(rec->rec_livetv_file) == 1 )
usleep(500000);
pthread_mutex_lock(&mutex);
//}
}
Hi aubrien. When data block are requested and backend return 0 bytes available then at each time we try to switch file. So every time you have zero bytes it pass by this way. Only here we know exactly what to do: wait or switch next file if exists.
Retry with extra log like previous and we ll see what it does. Also please can you have a look on your mythbackend log to try to understand what is it doing at this moment and why it doesn t push data. It will be interesting. You can post logs to me. Thanks.
Also you can try dteirney solution to see what happen.

@dteirney: hi, yes it could run. But it set a constant delay even if it is not required. With this solution spawn and swicth get 5 or 10 second more. Please read my previous post where i explained what happen during program break. I finished the merge with cfetzer and i requested to pull my last change containing the resolution of program breaks based on mythfrontend strategy. Br


RE: New MythTV add-on using libcmyth - koehn - 2012-10-08

While I'm a bit of an XBMC n00b, I'm a very experienced developer. Just wondering what the status of the Addon is at this point and how close it might be to making it into the XBMC PVR addons build. I'd love to get it running on RaspBMC.

Thanks all for the hard work!


RE: New MythTV add-on using libcmyth - janbar - 2012-10-08

@dteirney:
Solution could be great as a workaround until we have enough time to manage this case using myth protocol. Aubrien could collect log from his Mythtv backend or any others having same type of device. I sure we will find the best solution. br



RE: New MythTV add-on using libcmyth - janbar - 2012-10-08

(2012-10-08, 09:03)dteirney Wrote:
(2012-10-03, 21:11)Aubrien Wrote: OK, I have had live tv playing for hours now without it stopping so I think its time to post the solution. There are two delays needed as well as an object lock. I based this on cfetzer's code not janbar's since that is where we are moving to anyway. The changes are below...

addons/pvr.mythtv.cmyth/src/pvrclient-mythtv.cpp
Code:
bool PVRClientMythTV::OpenLiveStream(const PVR_CHANNEL &channel)
{
  if (g_bExtraDebug)
    XBMC->Log(LOG_DEBUG,"%s - chanID: %i, channumber: %i", __FUNCTION__, channel.iUniqueId, channel.iChannelNumber);

  SingleLock<PLATFORM::CMutex> lock(&m_lock);
  if (m_rec.IsNull())
  {
    MythChannel chan = m_channels.at(channel.iUniqueId);
    for (std::vector<int>::iterator it = m_sources.at(chan.SourceID()).begin(); it != m_sources.at(chan.SourceID()).end(); it++)
    {
      m_rec = m_con.GetRecorder(*it);
      if (!m_rec.IsRecording() && m_rec.IsTunable(chan))
      {
        if (g_bExtraDebug)
          XBMC->Log(LOG_DEBUG,"%s: Opening new recorder %i", __FUNCTION__, m_rec.ID());

        if (m_pEventHandler)
          m_pEventHandler->SetRecorder(m_rec);

        if (m_rec.SpawnLiveTV(chan))
        {
          usleep(10000000); //Channel change delay of 10s
          return true;
        }
      }
      m_rec = MythRecorder();
      if (m_pEventHandler)
      {
        m_pEventHandler->SetRecorder(m_rec); // Redundant
      }
    }

    if (g_bExtraDebug)
      XBMC->Log(LOG_DEBUG,"%s - Done", __FUNCTION__);
    return false;
  }
  else
  {
    if (g_bExtraDebug)
      XBMC->Log(LOG_DEBUG,"%s - Done", __FUNCTION__);

    return true;
  }
}
Add the delay for changing channels.

addons/pvr.mythtv.cmyth/src/cppmyth/MythRecorder.cpp
Code:
bool MythRecorder::LiveTVChainUpdate(CStdString chainID)
{
  char* buffer=strdup(chainID.c_str());
  m_recorder_t->Lock();
  int retval = 0;

  usleep(5000000); // Program switch delay of 5s

  CMYTH_REC_CALL( retval, retval < 0, cmyth_livetv_chain_update( *m_recorder_t, buffer, 16*1024 ) );
  if(retval != 0)
    XBMC->Log(LOG_ERROR,"LiveTVChainUpdate failed on chainID: %s",buffer);
  *livechainupdated=1;
  m_recorder_t->Unlock();
  free(buffer);
  return retval==0;
}
Uncomment the lock/unlock. Add the delay for between shows.

addons/pvr.mythtv.cmyth/src/cppmyth/MythRecorder.cpp
Code:
int MythRecorder::ReadLiveTV(void* buffer,unsigned long length)
{

  m_recorder_t->Lock();
  int bytesRead=0;
  CMYTH_REC_CALL( bytesRead, bytesRead < 0, cmyth_livetv_read( *m_recorder_t, static_cast<char*>( buffer ), length ) );
  m_recorder_t->Unlock();
  return bytesRead;
}
Uncomment the lock/unlock

The end result of this makes the channels change properly either from nothing being played or from already watching tv. The delay is especially useful for those of us with IR blasters and analog tuners. Additionally, when the chain is updated (program transition) it locks the recorder for 5s. During this time read operations delay and the user is prevented from underrunning the buffer on the backend. Both the channel change delay and the program switch delay should be made into addon settings to be user configured. Mine works with the static values I inserted for developing the fix. Between program transitions you will see a "Buffering %" dialog for a second or so. This buffering is essential as each program transition causes no data for a small period and eventually the buffer is depleted and this makes it refill.

Rather than a hard-coded 5 second delay could you look at doing something more like was done in one of my branches. Unfortunately still not cleaned up and ready for PR to upstream libcmyth. https://github.com/dteirney/xbmc/commit/afe18e73725c66bde621f4bd0643bd96ecac88b2

That commit also has the fix for the LiveTV locking problem as well.

@dteirney: I read your commit. It is a way. But i think we must to find a solution without use backend's database at least for liveTV. Would not be better to use only Mythtv protocol ?


RE: New MythTV add-on using libcmyth - janbar - 2012-10-08

@Aubrien,

cfetzer has same issue like you with lock on reading live stream. I am updating the code to manage the lock. soon.


RE: New MythTV add-on using libcmyth - janbar - 2012-10-09

@Aubrien,

I committed the code to avoid the lock caused by timeout on buffer empty. Hopefully it will be better like that.
You can use my branch old_master if you use my old addon.
Else use my branch new_old_master if you use the new addon pvr.mythtv.cmyth with old xbmc (not nightly).
And finally my branch master if you use the new addon pvr.mythtv.cmyth with lastest xbmc.
br.