Merge branch 'bug_271_ac3pcm_delay_servicemp3'
authorghost <andreas.monzner@multimedia-labs.de>
Tue, 22 Dec 2009 15:08:24 +0000 (16:08 +0100)
committerghost <andreas.monzner@multimedia-labs.de>
Tue, 22 Dec 2009 15:08:24 +0000 (16:08 +0100)
1  2 
lib/dvb/decoder.cpp
lib/service/servicedvb.cpp
lib/service/servicemp3.cpp

diff --combined lib/dvb/decoder.cpp
@@@ -222,6 -222,9 +222,6 @@@ int eDVBAudio::startPid(int pid, int ty
  
  void eDVBAudio::stop()
  {
 -#if HAVE_DVB_API_VERSION > 2
 -      flush();
 -#endif
        eDebugNoNewLine("AUDIO_STOP - ");
        if (::ioctl(m_fd, AUDIO_STOP) < 0)
                eDebug("failed (%m)");
@@@ -1045,9 -1048,9 +1045,9 @@@ int eTSMPEGDecoder::setState(
  int eTSMPEGDecoder::m_pcm_delay=-1,
        eTSMPEGDecoder::m_ac3_delay=-1;
  
- RESULT eTSMPEGDecoder::setPCMDelay(int delay)
+ RESULT eTSMPEGDecoder::setHwPCMDelay(int delay)
  {
-       if (m_decoder == 0 && delay != m_pcm_delay )
+       if (delay != m_pcm_delay )
        {
                FILE *fp = fopen("/proc/stb/audio/audio_delay_pcm", "w");
                if (fp)
        return -1;
  }
  
- RESULT eTSMPEGDecoder::setAC3Delay(int delay)
+ RESULT eTSMPEGDecoder::setHwAC3Delay(int delay)
  {
-       if ( m_decoder == 0 && delay != m_ac3_delay )
+       if ( delay != m_ac3_delay )
        {
                FILE *fp = fopen("/proc/stb/audio/audio_delay_bitstream", "w");
                if (fp)
        return -1;
  }
  
+ RESULT eTSMPEGDecoder::setPCMDelay(int delay)
+ {
+       return m_decoder == 0 ? setHwPCMDelay(delay) : -1;
+ }
+ RESULT eTSMPEGDecoder::setAC3Delay(int delay)
+ {
+       return m_decoder == 0 ? setHwAC3Delay(delay) : -1;
+ }
  eTSMPEGDecoder::eTSMPEGDecoder(eDVBDemux *demux, int decoder)
        : m_demux(demux), 
                m_vpid(-1), m_vtype(-1), m_apid(-1), m_atype(-1), m_pcrpid(-1), m_textpid(-1),
@@@ -917,7 -917,7 +917,7 @@@ eDVBServicePlay::eDVBServicePlay(const 
        m_is_pvr = !m_reference.path.empty();
        
        m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
 -      m_skipmode = 0;
 +      m_skipmode = m_fastforward = m_slowmotion = 0;
        
        CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
        CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
@@@ -1185,10 -1185,7 +1185,10 @@@ RESULT eDVBServicePlay::setSlowMotion(i
        eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
        setFastForward_internal(0);
        if (m_decoder)
 +      {
 +              m_slowmotion = ratio;
                return m_decoder->setSlowMotion(ratio);
 +      }
        else
                return -1;
  }
@@@ -1200,11 -1197,10 +1200,11 @@@ RESULT eDVBServicePlay::setFastForward(
        return setFastForward_internal(ratio);
  }
  
 -RESULT eDVBServicePlay::setFastForward_internal(int ratio)
 +RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
  {
 -      int skipmode, ffratio;
 -      
 +      int skipmode, ffratio, ret = 0;
 +      pts_t pos=0;
 +
        if (ratio > 8)
        {
                skipmode = ratio;
                if (m_cue)
                        m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
        }
 -      
 +
        m_skipmode = skipmode;
 -      
 +
 +      if (final_seek)
 +              eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
 +
 +      m_fastforward = ffratio;
 +
        if (!m_decoder)
                return -1;
 -              
 +
        if (ffratio == 0)
                ; /* return m_decoder->play(); is done in caller*/
        else if (ffratio != 1)
 -              return m_decoder->setFastForward(ffratio);
 +              ret = m_decoder->setFastForward(ffratio);
        else
 -              return m_decoder->setTrickmode();
 -      return 0;
 +              ret = m_decoder->setTrickmode();
 +
 +      if (pos)
 +              eDebug("final seek after trickplay ret %d", seekTo(pos));
 +
 +      return ret;
  }
  
  RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
@@@ -1279,10 -1266,9 +1279,10 @@@ RESULT eDVBServicePlay::getLength(pts_
  RESULT eDVBServicePlay::pause()
  {
        eDebug("eDVBServicePlay::pause");
 -      setFastForward_internal(0);
 +      setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
        if (m_decoder)
        {
 +              m_slowmotion = 0;
                m_is_paused = 1;
                return m_decoder->pause();
        } else
  RESULT eDVBServicePlay::unpause()
  {
        eDebug("eDVBServicePlay::unpause");
 -      setFastForward_internal(0);
 +      setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
        if (m_decoder)
        {
 +              m_slowmotion = 0;
                m_is_paused = 0;
                return m_decoder->play();
        } else
@@@ -1743,7 -1728,6 +1743,7 @@@ int eDVBServicePlay::selectAudioStream(
  {
        eDVBServicePMTHandler::program program;
        eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
 +      pts_t position = -1;
  
        if (h.getProgramInfo(program))
                return -1;
                apidtype = program.audioStreams[stream].type;
        }
  
 +      if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
 +              eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
 +
        m_current_audio_pid = apid;
  
        if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
                return -4;
        }
  
 +      if (position != -1)
 +              eDebug("seekTo ret %d", seekTo(position));
 +
        int rdsPid = apid;
  
                /* if we are not in PVR mode, timeshift is not active and we are not in pip mode, check if we need to enable the rds reader */
@@@ -2251,7 -2229,7 +2251,7 @@@ void eDVBServicePlay::switchToLive(
        m_new_subtitle_page_connection = 0;
        m_rds_decoder_event_connection = 0;
        m_video_event_connection = 0;
 -      m_is_paused = m_skipmode = 0; /* not supported in live mode */
 +      m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
  
                /* free the timeshift service handler, we need the resources */
        m_service_handler_timeshift.free();
@@@ -2285,13 -2263,12 +2285,13 @@@ void eDVBServicePlay::switchToTimeshift
        r.path = m_timeshift_file;
  
        m_cue = new eCueSheet();
 +      m_cue->seekTo(0, -1000);
        m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
  
        eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
        pause();
        updateDecoder(); /* mainly to switch off PCR, and to set pause */
 -      
 +
        m_event((iPlayableService*)this, evSeekableStatusChanged);
  }
  
@@@ -2421,17 -2398,8 +2421,8 @@@ void eDVBServicePlay::updateDecoder(
                        }
                }
  
-               std::string config_delay;
-               int config_delay_int = 0;
-               if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
-                       config_delay_int = atoi(config_delay.c_str());
-               m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
-               if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
-                       config_delay_int = atoi(config_delay.c_str());
-               else
-                       config_delay_int = 0;
-               m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
+               setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
+               setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
  
                m_decoder->setVideoPID(vpid, vpidtype);
                selectAudioStream();
@@@ -2955,16 -2923,28 +2946,28 @@@ void eDVBServicePlay::setAC3Delay(int d
  {
        if (m_dvb_service)
                m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
-       if (m_decoder)
-               m_decoder->setAC3Delay(delay);
+       if (m_decoder) {
+               std::string config_delay;
+               int config_delay_int = 0;
+               if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
+                       config_delay_int = atoi(config_delay.c_str());
+               m_decoder->setAC3Delay(delay + config_delay_int);
+       }
  }
  
  void eDVBServicePlay::setPCMDelay(int delay)
  {
        if (m_dvb_service)
                m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
-       if (m_decoder)
-               m_decoder->setPCMDelay(delay);
+       if (m_decoder) {
+               std::string config_delay;
+               int config_delay_int = 0;
+               if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
+                       config_delay_int = atoi(config_delay.c_str());
+               else
+                       config_delay_int = 0;
+               m_decoder->setPCMDelay(delay + config_delay_int);
+       }
  }
  
  void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
@@@ -2,20 -2,23 +2,23 @@@
  
        /* note: this requires gstreamer 0.10.x and a big list of plugins. */
        /* it's currently hardcoded to use a big-endian alsasink as sink. */
+ #include <lib/base/ebase.h>
  #include <lib/base/eerror.h>
+ #include <lib/base/init_num.h>
+ #include <lib/base/init.h>
+ #include <lib/base/nconfig.h>
  #include <lib/base/object.h>
- #include <lib/base/ebase.h>
- #include <string>
+ #include <lib/dvb/decoder.h>
+ #include <lib/components/file_eraser.h>
+ #include <lib/gui/esubtitle.h>
  #include <lib/service/servicemp3.h>
  #include <lib/service/service.h>
- #include <lib/components/file_eraser.h>
- #include <lib/base/init_num.h>
- #include <lib/base/init.h>
+ #include <string>
  #include <gst/gst.h>
  #include <gst/pbutils/missing-plugins.h>
  #include <sys/stat.h>
- /* for subtitles */
- #include <lib/gui/esubtitle.h>
  
  // eServiceFactoryMP3
  
@@@ -34,7 -37,6 +37,7 @@@ eServiceFactoryMP3::eServiceFactoryMP3(
                extensions.push_back("vob");
                extensions.push_back("wav");
                extensions.push_back("wave");
 +              extensions.push_back("m4v");
                extensions.push_back("mkv");
                extensions.push_back("avi");
                extensions.push_back("divx");
@@@ -187,6 -189,8 +190,8 @@@ int eStaticServiceMP3Info::getLength(co
  }
  
  // eServiceMP3
+ int eServiceMP3::ac3_delay,
+     eServiceMP3::pcm_delay;
  
  eServiceMP3::eServiceMP3(eServiceReference ref)
        :m_ref(ref), m_pump(eApp, 1)
                sourceinfo.containertype = ctAVI;
                sourceinfo.is_video = TRUE;
        }
 -      else if ( strcasecmp(ext, ".mp4") == 0 || strcasecmp(ext, ".mov") == 0)
 +      else if ( strcasecmp(ext, ".mp4") == 0 || strcasecmp(ext, ".mov") == 0 || strcasecmp(ext, ".m4v") == 0)
        {
                sourceinfo.containertype = ctMP4;
                sourceinfo.is_video = TRUE;
@@@ -659,7 -663,6 +664,6 @@@ RESULT eServiceMP3::getName(std::strin
        return 0;
  }
  
  int eServiceMP3::getInfo(int w)
  {
        const gchar *tag = 0;
@@@ -955,6 -958,12 +959,12 @@@ RESULT eServiceMP3::subtitle(ePtr<iSubt
        return 0;
  }
  
+ RESULT eServiceMP3::audioDelay(ePtr<iAudioDelay> &ptr)
+ {
+       ptr = this;
+       return 0;
+ }
  int eServiceMP3::getNumberOfTracks()
  {
        return m_audioStreams.size();
@@@ -1093,6 -1102,8 +1103,8 @@@ void eServiceMP3::gstBusCall(GstBus *bu
                                                g_object_set (G_OBJECT (sink), "emit-signals", TRUE, NULL);
                                                gst_object_unref(sink);
                                        }
+                                       setAC3Delay(ac3_delay);
+                                       setPCMDelay(pcm_delay);
                                }       break;
                                case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
                                {
@@@ -1579,6 -1590,96 +1591,96 @@@ int eServiceMP3::setBufferSize(int size
        return 0;
  }
  
+ int eServiceMP3::getAC3Delay()
+ {
+       return ac3_delay;
+ }
+ int eServiceMP3::getPCMDelay()
+ {
+       return pcm_delay;
+ }
+ void eServiceMP3::setAC3Delay(int delay)
+ {
+       ac3_delay = delay;
+       if (!m_gst_playbin || m_state != stRunning)
+               return;
+       else
+       {
+               GstElement *sink;
+               int config_delay_int = delay;
+               g_object_get (G_OBJECT (m_gst_playbin), "video-sink", &sink, NULL);
+               if (sink)
+               {
+                       std::string config_delay;
+                       if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
+                               config_delay_int += atoi(config_delay.c_str());
+                       gst_object_unref(sink);
+               }
+               else
+               {
+                       eDebug("dont apply ac3 delay when no video is running!");
+                       config_delay_int = 0;
+               }
+               g_object_get (G_OBJECT (m_gst_playbin), "audio-sink", &sink, NULL);
+               if (sink)
+               {
+                       gchar *name = gst_element_get_name(sink);
+                       if (strstr(name, "dvbaudiosink"))
+                               eTSMPEGDecoder::setHwAC3Delay(config_delay_int);
+                       g_free(name);
+                       gst_object_unref(sink);
+               }
+       }
+ }
+ void eServiceMP3::setPCMDelay(int delay)
+ {
+       pcm_delay = delay;
+       if (!m_gst_playbin || m_state != stRunning)
+               return;
+       else
+       {
+               GstElement *sink;
+               int config_delay_int = delay;
+               g_object_get (G_OBJECT (m_gst_playbin), "video-sink", &sink, NULL);
+               if (sink)
+               {
+                       std::string config_delay;
+                       if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
+                               config_delay_int += atoi(config_delay.c_str());
+                       gst_object_unref(sink);
+               }
+               else
+               {
+                       eDebug("dont apply pcm delay when no video is running!");
+                       config_delay_int = 0;
+               }
+               g_object_get (G_OBJECT (m_gst_playbin), "audio-sink", &sink, NULL);
+               if (sink)
+               {
+                       gchar *name = gst_element_get_name(sink);
+                       if (strstr(name, "dvbaudiosink"))
+                               eTSMPEGDecoder::setHwPCMDelay(config_delay_int);
+                       else
+                       {
+                               // this is realy untested..and not used yet
+                               gint64 offset = config_delay_int;
+                               offset *= 1000000; // milli to nano
+                               g_object_set (G_OBJECT (m_gst_playbin), "ts-offset", offset, NULL);
+                       }
+                       g_free(name);
+                       gst_object_unref(sink);
+               }
+       }
+ }
  
  #else
  #warning gstreamer not available, not building media player