diff options
author | hschang <chang@dev3> | 2016-05-16 07:51:49 (GMT) |
---|---|---|
committer | hschang <chang@dev3> | 2016-05-16 07:51:49 (GMT) |
commit | 27e06ba9c8b055c20ea8c70a405deb0e4019edc5 (patch) | |
tree | d44d65aa4e81951fa783718cbfe1815c72e4bdc5 /lib/dvb/decoder.cpp | |
parent | 004d6db4a1dda8f08f5ce63f30c102c81b7b0693 (diff) |
Support fast channel change.
Diffstat (limited to 'lib/dvb/decoder.cpp')
-rw-r--r-- | lib/dvb/decoder.cpp | 264 |
1 files changed, 257 insertions, 7 deletions
diff --git a/lib/dvb/decoder.cpp b/lib/dvb/decoder.cpp index 8a4a82d..e3d97af 100644 --- a/lib/dvb/decoder.cpp +++ b/lib/dvb/decoder.cpp @@ -34,6 +34,8 @@ #include <sys/stat.h> #include <errno.h> +#include <lib/dvb/fccdecoder.h> + /* these are quite new... */ #ifndef AUDIO_GET_PTS #define AUDIO_GET_PTS _IOR('o', 19, __u64) @@ -206,9 +208,9 @@ int eDVBAudio::startPid(int pid, int type) case aDTSHD: bypass = 0x10; break; - case aDDP: - bypass = 0x22; - break; + case aDDP: + bypass = 0x22; + break; } @@ -304,8 +306,8 @@ eDVBAudio::~eDVBAudio() DEFINE_REF(eDVBVideo); -eDVBVideo::eDVBVideo(eDVBDemux *demux, int dev) - : m_demux(demux), m_dev(dev), +eDVBVideo::eDVBVideo(eDVBDemux *demux, int dev, bool fcc_enable) + : m_demux(demux), m_dev(dev), m_fcc_enable(fcc_enable), m_width(-1), m_height(-1), m_framerate(-1), m_aspect(-1), m_progressive(-1) { char filename[128]; @@ -408,6 +410,9 @@ int eDVBVideo::startPid(int pid, int type) { int streamtype = VIDEO_STREAMTYPE_MPEG2; + if (m_fcc_enable) + return 0; + if ((m_fd < 0) || (m_fd_demux < 0)) return -1; dmx_pes_filter_params pes; @@ -474,6 +479,9 @@ int eDVBVideo::startPid(int pid, int type) void eDVBVideo::stop() { + if (m_fcc_enable) + return; + #if HAVE_DVB_API_VERSION > 2 eDebugNoNewLine("DEMUX_STOP - video - "); if (::ioctl(m_fd_demux, DMX_STOP) < 0) @@ -996,7 +1004,7 @@ int eTSMPEGDecoder::setState() { if ((m_vpid >= 0) && (m_vpid < 0x1FFF)) { - m_video = new eDVBVideo(m_demux, m_decoder); + m_video = new eDVBVideo(m_demux, m_decoder, m_fcc_enable); m_video->connectEvent(slot(*this, &eTSMPEGDecoder::video_event), m_video_event_conn); if (m_video->startPid(m_vpid, m_vtype)) res = -1; @@ -1102,7 +1110,8 @@ RESULT eTSMPEGDecoder::setAC3Delay(int delay) 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), - m_changed(0), m_decoder(decoder), m_video_clip_fd(-1), m_showSinglePicTimer(eTimer::create(eApp)) + m_changed(0), m_decoder(decoder), m_video_clip_fd(-1), m_showSinglePicTimer(eTimer::create(eApp)), + m_fcc_fd(-1), m_fcc_enable(false), m_fcc_state(fcc_state_stop), m_fcc_feid(-1), m_fcc_vpid(-1), m_fcc_vtype(-1), m_fcc_pcrpid(-1) { demux->connectEvent(slot(*this, &eTSMPEGDecoder::demux_event), m_demux_event_conn); CONNECT(m_showSinglePicTimer->timeout, eTSMPEGDecoder::finishShowSinglePic); @@ -1115,6 +1124,8 @@ eTSMPEGDecoder::~eTSMPEGDecoder() m_vpid = m_apid = m_pcrpid = m_textpid = pidNone; m_changed = -1; setState(); + fccStop(); + fccFreeFD(); } RESULT eTSMPEGDecoder::setVideoPID(int vpid, int type) @@ -1421,3 +1432,242 @@ int eTSMPEGDecoder::getVideoAspect() return m_video->getAspect(); return -1; } + +#define FCC_SET_VPID 100 +#define FCC_SET_APID 101 +#define FCC_SET_PCRPID 102 +#define FCC_SET_VCODEC 103 +#define FCC_SET_ACODEC 104 +#define FCC_SET_FRONTEND_ID 105 +#define FCC_START 106 +#define FCC_STOP 107 +#define FCC_DECODER_START 108 +#define FCC_DECODER_STOP 109 + +RESULT eTSMPEGDecoder::prepareFCC(int fe_id, int vpid, int vtype, int pcrpid) +{ + //eDebug("[eTSMPEGDecoder::prepareFCC] vp : %d, vt : %d, pp : %d, fe : %d", vpid, vtype, pcrpid, fe_id); + + if ((fccGetFD() == -1) || (fccSetPids(fe_id, vpid, vtype, pcrpid) < 0) || (fccStart() < 0)) + { + fccFreeFD(); + return -1; + } + + m_fcc_enable = true; + + return 0; +} + +RESULT eTSMPEGDecoder::fccDecoderStart() +{ + if (m_fcc_fd == -1) + return -1; + + if (m_fcc_state != fcc_state_ready) + { + eDebug("FCC decoder is already in decoding state."); + return 0; + } + + if (ioctl(m_fcc_fd, FCC_DECODER_START) < 0) + { + eDebug("ioctl FCC_DECODER_START failed! (%m)"); + return -1; + } + + m_fcc_state = fcc_state_decoding; + + eDebug("[eTSMPEGDecoder] FCC_DECODER_START OK!"); + return 0; +} + +RESULT eTSMPEGDecoder::fccDecoderStop() +{ + if (m_fcc_fd == -1) + return -1; + + if (m_fcc_state != fcc_state_decoding) + { + eDebug("FCC decoder is not in decoding state."); + } + else if (ioctl(m_fcc_fd, FCC_DECODER_STOP) < 0) + { + eDebug("ioctl FCC_DECODER_STOP failed! (%m)"); + return -1; + } + + m_fcc_state = fcc_state_ready; + + /* stop pcr, video, audio, text */ + finishShowSinglePic(); + + m_vpid = m_apid = m_pcrpid = m_textpid = pidNone; + m_changed = -1; + setState(); + + eDebug("[eTSMPEGDecoder] FCC_DECODER_STOP OK!"); + return 0; +} + +RESULT eTSMPEGDecoder::fccUpdatePids(int fe_id, int vpid, int vtype, int pcrpid) +{ + //eDebug("[eTSMPEGDecoder] vp : %d, vt : %d, pp : %d, fe : %d", vpid, vtype, pcrpid, fe_id); + + if ((fe_id != m_fcc_feid) || (vpid != m_fcc_vpid) || (vtype != m_fcc_vtype) || (pcrpid != m_fcc_pcrpid)) + { + int cur_fcc_state = m_fcc_state; + fccStop(); + if (prepareFCC(fe_id, vpid, vtype, pcrpid)) + { + eDebug("[eTSMPEGDecoder] prepare FCC failed!"); + return -1; + } + } + return 0; +} + +RESULT eTSMPEGDecoder::fccStart() +{ + if (m_fcc_fd == -1) + return -1; + + if (m_fcc_state != fcc_state_stop) + { + eDebug("[eTSMPEGDecoder] FCC is already started!"); + return 0; + } + else if (ioctl(m_fcc_fd, FCC_START) < 0) + { + eDebug("ioctl FCC_START failed! (%m)"); + return -1; + } + + eDebug("[eTSMPEGDecoder] FCC_START OK!"); + + m_fcc_state = fcc_state_ready; + return 0; +} + +RESULT eTSMPEGDecoder::fccStop() +{ + if (m_fcc_fd == -1) + return -1; + + if (m_fcc_state == fcc_state_stop) + { + eDebug("[eTSMPEGDecoder] FCC is already stopped!"); + return 0; + } + + else if (m_fcc_state == fcc_state_decoding) + { + fccDecoderStop(); + } + + if (ioctl(m_fcc_fd, FCC_STOP) < 0) + { + eDebug("ioctl FCC_STOP failed! (%m)"); + return -1; + } + + m_fcc_state = fcc_state_stop; + + eDebug("[eTSMPEGDecoder] FCC_STOP OK!"); + return 0; +} + +RESULT eTSMPEGDecoder::fccSetPids(int fe_id, int vpid, int vtype, int pcrpid) +{ + int streamtype = VIDEO_STREAMTYPE_MPEG2; + + if (m_fcc_fd == -1) + return -1; + + if (ioctl(m_fcc_fd, FCC_SET_FRONTEND_ID, fe_id) < 0) + { + eDebug("[eTSMPEGDecoder] FCC_SET_FRONTEND_ID failed! (%m)"); + return -1; + } + + else if(ioctl(m_fcc_fd, FCC_SET_PCRPID, pcrpid) < 0) + { + eDebug("[eTSMPEGDecoder] FCC_SET_PCRPID failed! (%m)"); + return -1; + } + + else if (ioctl(m_fcc_fd, FCC_SET_VPID, vpid) < 0) + { + eDebug("[eTSMPEGDecoder] FCC_SET_VPID failed! (%m)"); + return -1; + } + + switch(vtype) + { + default: + case eDVBVideo::MPEG2: + break; + case eDVBVideo::MPEG4_H264: + streamtype = VIDEO_STREAMTYPE_MPEG4_H264; + break; + case eDVBVideo::MPEG1: + streamtype = VIDEO_STREAMTYPE_MPEG1; + break; + case eDVBVideo::MPEG4_Part2: + streamtype = VIDEO_STREAMTYPE_MPEG4_Part2; + break; + case eDVBVideo::VC1: + streamtype = VIDEO_STREAMTYPE_VC1; + break; + case eDVBVideo::VC1_SM: + streamtype = VIDEO_STREAMTYPE_VC1_SM; + break; + case eDVBVideo::H265_HEVC: + streamtype = VIDEO_STREAMTYPE_H265_HEVC; + break; + } + + if(ioctl(m_fcc_fd, FCC_SET_VCODEC, streamtype) < 0) + { + eDebug("[eTSMPEGDecoder] FCC_SET_VCODEC failed! (%m)"); + return -1; + } + + m_fcc_feid = fe_id; + m_fcc_vpid = vpid; + m_fcc_vtype = vtype; + m_fcc_pcrpid = pcrpid; + + //eDebug("[eTSMPEGDecoder] SET PIDS OK!"); + return 0; +} + +RESULT eTSMPEGDecoder::fccGetFD() +{ + if (m_fcc_fd == -1) + { + eFCCDecoder* fcc = eFCCDecoder::getInstance(); + if (fcc != NULL) + { + m_fcc_fd = fcc->allocateFcc(); + } + } + + return m_fcc_fd; +} + +RESULT eTSMPEGDecoder::fccFreeFD() +{ + if (m_fcc_fd != -1) + { + eFCCDecoder* fcc = eFCCDecoder::getInstance(); + if (fcc != NULL) + { + fcc->freeFcc(m_fcc_fd); + m_fcc_fd = -1; + } + } + + return 0; +} + |