summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthlo <smarttv640@gmail.com>2013-12-15 10:43:59 +0100
committerthlo <smarttv640@gmail.com>2013-12-15 10:43:59 +0100
commitb5482027fced864558ec2bb2ea11191eec525e66 (patch)
tree0401c4822a31e41c71179c3da6a3097710d8a5d7
parent823ce3ed7d0060e08955c8c6379f634c0f4539e8 (diff)
downloadvdr-plugin-smarttvweb-b5482027fced864558ec2bb2ea11191eec525e66.tar.gz
vdr-plugin-smarttvweb-b5482027fced864558ec2bb2ea11191eec525e66.tar.bz2
additional built-in live modes.
-rw-r--r--responselive.c693
-rw-r--r--responselive.h23
-rwxr-xr-xstvw_cfg.c13
-rwxr-xr-xstvw_cfg.h2
4 files changed, 533 insertions, 198 deletions
diff --git a/responselive.c b/responselive.c
index 6204cc2..df2aaa0 100644
--- a/responselive.c
+++ b/responselive.c
@@ -130,22 +130,22 @@ void cLiveRelay::Receive(uchar* data, int length) {
//----------------------------------------------
cResponseLive::cResponseLive(cHttpResource* req, string chan_id) : cResponseBase(req), mChannelId(chan_id),
- mPatPmtGen(NULL), mInStartPhase(true), mFrameDetector(NULL), mVpid(0), mVtype(0), mPpid(0), mStartThreshold(75*188) {
+ mPatPmtGen(NULL), mInStartPhase(true), mFrameDetector(NULL), mVpid(0), mVtype(0), mPpid(0), mStartThreshold(75*188),
+ mCurOffset (0), mTuneInState(0), mFirstPcr (-1), mFirstPcrOffset(0), mCurPcr(-1), mCurPcrOffset(0), mNoFrames(0) ,
+ mIFrameOffset(-1), mLowerOffset(0) {
mStartThreshold= mRequest->mFactory->getConfig()->getBuiltInLivePktBuf4Sd() * 188;
- *(mLog->log()) << DEBUGPREFIX << " cResponseLive::cResponseLive - Constructor "
- << "mStartThreshold= " << mStartThreshold
- << " (" << mStartThreshold/188 << " Pkts)" << endl;
+ *(mLog->log()) << DEBUGPREFIX << " cResponseLive - Constructor "
+ << "mStartThreshold= " << mStartThreshold/188 << " Pkts"
+ << " Mode= " << mRequest->mFactory->getConfig()->getBuiltInLiveStartMode()
+ << endl;
if (InitRelay(chan_id)) {
mRelay->setNotifRequired();
mRequest->mFactory->clrWriteFlag(mRequest->mFd);
}
- if (mRelay != NULL) {
- sendHeaders(200, "OK", NULL, "video/mpeg", -1, -1);
- }
- else {
+ if (mRelay == NULL) {
*(mLog->log()) << DEBUGPREFIX << " cResponseLive::cResponseLive - Constructor - sending Error" << endl;
sendError(404, "Not Found.", NULL, "004 Resource Busy");
}
@@ -162,13 +162,13 @@ cResponseLive::~cResponseLive() {
}
bool cResponseLive::InitRelay(string channel_id) {
-
cChannel * channel = Channels.GetByChannelID(tChannelID::FromString(channel_id.c_str()));
int priority = 99;
if (!channel ){
*(mLog->log()) << DEBUGPREFIX
- << " " << channel_id << " No channel found: " << endl;
+ << " " << channel_id << " No channel found! " << endl;
+ mRequest->mFactory->OsdStatusMessage("Channel not found!");
return false;
}
@@ -195,7 +195,6 @@ bool cResponseLive::InitRelay(string channel_id) {
mPpid = channel->Ppid();
if (mVtype == 27) {
- // mStartThreshold = 150 * 188;
mStartThreshold= mRequest->mFactory->getConfig()->getBuiltInLivePktBuf4Hd() * 188;
*(mLog->log()) << DEBUGPREFIX << " cResponseLive::InitRelay H.264 detected. mStartThreshold is " << mStartThreshold
@@ -243,12 +242,12 @@ bool cResponseLive::InitRelay(string channel_id) {
}
void cResponseLive::WritePatPmt() {
- mBlkPos = 0;
- mBlkLen = 0;
+ // mBlkPos = 0;
+ // mBlkLen = 0;
uchar* ptr = mPatPmtGen->GetPat();
- memcpy(mBlkData, ptr, 188);
- mBlkLen = 188;
+ memcpy(mBlkData + mBlkLen, ptr, 188);
+ mBlkLen += 188;
int idx = 0;
while ((ptr = mPatPmtGen->GetPmt(idx)) != NULL) {
@@ -258,16 +257,20 @@ void cResponseLive::WritePatPmt() {
}
int cResponseLive::fillDataBlk() {
+ if (mError)
+ return ERROR;
+
switch (mRequest->mFactory->getConfig()->getBuiltInLiveStartMode()){
case 0:
return fillDataBlk_straight();
break;
- case 1:
- return fillDataBlk_pcr();
+ case 3:
+ return fillDataBlk_duration();
+ break;
+ case 4:
+ default:
+ return fillDataBlk_iPlusDuration();
break;
- case 2:
- return fillDataBlk_iframe();
- break;
};
*(mLog->log()) << DEBUGPREFIX
@@ -276,15 +279,20 @@ int cResponseLive::fillDataBlk() {
return ERROR;
}
-int cResponseLive::fillDataBlk_pcr() {
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+
+int cResponseLive::fillDataBlk_straight() {
mBlkPos = 0;
mBlkLen = 0;
if (mError)
return ERROR;
-
+
int threshold = (mInStartPhase) ? mStartThreshold : (1*188);
-
+
if (mRelay->mRingBuffer->Available() >= threshold) {
pthread_mutex_lock(&(mRelay->processedRingLock));
@@ -292,81 +300,31 @@ int cResponseLive::fillDataBlk_pcr() {
char *b = (char*)mRelay->mRingBuffer->Get(r);
if (b != NULL) {
- // mInStartPhase = false;
+ if (mInStartPhase)
+ sendHeaders(200, "OK", NULL, "video/mpeg", -1, -1);
+
+ mInStartPhase = false;
if ((r % 188) != 0) {
- *(mLog->log()) << DEBUGPREFIX << " ERROR: r= " << r << " %188 = " << (r%188) << endl;
+ *(mLog->log()) << DEBUGPREFIX
+ << " ERROR: r= " << r << " %188 = " << (r%188) << endl;
}
- if (mInStartPhase) {
- int offset = 0;
- bool already_deleted = false;
- while ((offset +188) <= r) {
-
- if (TsPid((const uchar*) (b+offset)) == mPpid){
- int64_t pcr = TsGetPcr((const uchar*) (b+offset));
- if (pcr != -1) {
- // pcr pkt found
- if ((r - (offset+188)) < threshold) {
- *(mLog->log()) << DEBUGPREFIX
- << " cResponseLive::fillDataBlk() - PCR found but not sufficient data "
- << pcr << endl;
- already_deleted = true;
- mRelay->mRingBuffer->Del(offset);
- break;
- }
- *(mLog->log()) << DEBUGPREFIX
- << " cResponseLive::fillDataBlk() - PCR found, starting now pcr= "
- << pcr << endl;
-
- // fill the memblock
- mInStartPhase = false;
- WritePatPmt();
- int len = ((r - offset ) > (MAXLEN - mBlkLen)) ? (MAXLEN - mBlkLen): (r - offset );
-
- if ((r - offset ) > (MAXLEN - mBlkLen)) {
- *(mLog->log()) << DEBUGPREFIX
- << " cResponseLive::fillDataBlk() mInStartPhase = true - ((r - offset ) > (MAXLEN - mBlkLen))"
- << endl;
- }
- memcpy(mBlkData + mBlkLen, b+offset, len);
-
- mBlkLen += len;
- already_deleted = true;
- mRelay->mRingBuffer->Del(len + offset);
- break;
- } // if (pcr != 0)
- } // if (TsPid((
-
- // end of find pcr
-
- offset += 188;
- } // while (offset < r) {
-
- if (!already_deleted) {
- *(mLog->log()) << DEBUGPREFIX << " cResponseLive::fillDataBlk() - Not sufficient data. Deleting "
- << offset +188 << " Byte corresponding to " << (offset / 188) +1 << " pkts" << endl;
- mRelay->mRingBuffer->Del(offset + 188);
- }
- } // if (mInStartPhase)
+ WritePatPmt();
+ int len = (r > (MAXLEN - mBlkLen)) ? (MAXLEN - mBlkLen): r;
+
+ if (r > (MAXLEN - mBlkLen)) {
+ *(mLog->log()) << DEBUGPREFIX
+ << " cResponseLive::fillDataBlk() mInStartPhase = false - ((r - offset ) > (MAXLEN - mBlkLen)) len= " << len
+ << " MAXLEN= " << MAXLEN
+ << " mBlkLen= " << mBlkLen
+ << endl;
+ }
+ memcpy(mBlkData + mBlkLen, b, len);
+
+ mBlkLen += len;
+ mRelay->mRingBuffer->Del(len);
- else {
-
- WritePatPmt();
- int len = (r > (MAXLEN - mBlkLen)) ? (MAXLEN - mBlkLen): r;
-
- if (r > (MAXLEN - mBlkLen)) {
- *(mLog->log()) << DEBUGPREFIX
- << " cResponseLive::fillDataBlk() mInStartPhase = false - ((r - offset ) > (MAXLEN - mBlkLen)) len= " << len
- << " MAXLEN= " << MAXLEN
- << " mBlkLen= " << mBlkLen
- << endl;
- }
- memcpy(mBlkData + mBlkLen, b, len);
-
- mBlkLen += len;
- mRelay->mRingBuffer->Del(len);
- } // else
} // if (b != NULL)
else {
*(mLog->log()) << DEBUGPREFIX << " WARNING - cResponseLive::fillDataBlk() - b== NULL" << endl;
@@ -381,151 +339,500 @@ int cResponseLive::fillDataBlk_pcr() {
return OKAY;
}
-int cResponseLive::fillDataBlk_iframe() {
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+
+int cResponseLive::fillDataBlk_duration() {
mBlkPos = 0;
mBlkLen = 0;
-
+
if (mError)
return ERROR;
-
- int threshold = (mInStartPhase) ? mStartThreshold : (1*188);
-
- if (mRelay->mRingBuffer->Available() >= threshold) {
-
+
+ if (mInStartPhase) {
pthread_mutex_lock(&(mRelay->processedRingLock));
int r;
char *b = (char*)mRelay->mRingBuffer->Get(r);
-
- if (b != NULL) {
- // mInStartPhase = false;
+ if (b != NULL) {
if ((r % 188) != 0) {
*(mLog->log()) << DEBUGPREFIX << " ERROR: r= " << r << " %188 = " << (r%188) << endl;
}
+
+ *(mLog->log()) << DEBUGPREFIX
+ << " --------------- pkts= " << r / 188 << endl;
+
+ while ((mCurOffset +188) <= r) {
+ // while ((offset +188) <= r) {
+ if (TsPid((const uchar*) (b+mCurOffset)) == mPpid){
+ int64_t pcr = TsGetPcr((const uchar*) (b+mCurOffset));
+ if (pcr != -1) {
+ // pcr found
+ // *(mLog->log()) << DEBUGPREFIX << " pcr found offset= " << offset << " pcr= " <<pcr << " pkt= " << offset / 188<< endl;
+
+ if (mCurPcr == -1){
+ mCurPcr = pcr;
- if (mInStartPhase) {
- int offset = 0;
- bool already_deleted = false;
- cFrameDetector frame_detector(mVpid, mVtype);
+ *(mLog->log()) << DEBUGPREFIX
+ << " cResponseLive::fillDataBlk_duration() - first_pcr= " << mCurPcr
+ << " pkt= " << mCurOffset / 188 << endl;
+ if (mCurOffset != 0) {
+ // deleting the packets before the pcr packet.
+ *(mLog->log()) << DEBUGPREFIX
+ << " cResponseLive::fillDataBlk_duration() - deleting packets " << mCurOffset
+ << " pkt= " << mCurOffset / 188 << endl;
+ mRelay->mRingBuffer->Del(mCurOffset);
- while ((offset +188) <= r) {
-
- if (TsPid((const uchar*) (b+offset)) == mVpid){
- // check payload unit start ind
- if (!TsPayloadStart((const uchar*) (b+offset))) {
- offset += 188;
- continue;
- }
+ pthread_mutex_unlock(&(mRelay->processedRingLock));
- //ok. point to frame start now. check whether i frame
- if (frame_detector.Analyze((const uchar*) (b+offset), (r - offset) ) == 0) {
- // not sufficient data. delete and return
- already_deleted = true;
- mRelay->mRingBuffer->Del(offset + 188);
- break;
- }
- if (frame_detector.IndependentFrame()) {
- // was an I-Frame
- if ((r - (offset +188)) < threshold) {
- *(mLog->log()) << DEBUGPREFIX
- << " IFrame found, but not sufficient data to start. " << endl;
- already_deleted = true;
- mRelay->mRingBuffer->Del(offset);
- break;
+ // sleep for a while
+ mRequest->mFactory->clrWriteFlag(mRequest->mFd);
+ mRelay->setNotifRequired();
+ return OKAY;
}
+ mCurOffset += 188;
+ continue; // process next packet
+ }
+ if (mCurPcr > pcr) {
+ mCurPcr = pcr;
+
+ *(mLog->log()) << DEBUGPREFIX
+ << " cResponseLive::fillDataBlk_duration() - ERROR - wired. setting new first_pcr= " << mCurPcr
+ << " pkt= " << mCurOffset / 188 << endl;
+
+ mCurOffset += 188;
+ continue; // process next packet
+
+ }
+ // if ((pcr - first_pcr) > (0.8 * 27000000.0)) {
+ if ((pcr - mCurPcr) > (mRequest->mFactory->getConfig()->getBuiltInLiveBufDur() * 27000000.0)) {
+
+ // ok start now
*(mLog->log()) << DEBUGPREFIX
- << " IFrame found, starting now " << endl;
+ << " cResponseLive::fillDataBlk_duration() - starting "
+ << "pcr= " << pcr
+ << "(pcr - first_pcr) / 27000000.0 = "
+ << (pcr - mCurPcr) / 27000000.0
+ << " ts pkts= " << ((mCurOffset +188)/ 188)
+ << endl;
+
mInStartPhase = false;
+ sendHeaders(200, "OK", NULL, "video/mpeg", -1, -1);
WritePatPmt();
- int len = ((r - offset ) > (MAXLEN - mBlkLen)) ? (MAXLEN - mBlkLen): (r - offset );
- if ((r - offset ) > (MAXLEN - mBlkLen)) {
+ int len = (r > (MAXLEN - mBlkLen)) ? (MAXLEN - mBlkLen): r;
+
+ if (r > (MAXLEN - mBlkLen)) {
*(mLog->log()) << DEBUGPREFIX
- << " cResponseLive::fillDataBlk_iframe() mInStartPhase = true - ((r - offset ) > (MAXLEN - mBlkLen))"
+ << " cResponseLive::fillDataBlk_duration() mInStartPhase = false - ((r - offset ) > (MAXLEN - mBlkLen)) len= " << len
+ << " MAXLEN= " << MAXLEN
+ << " mBlkLen= " << mBlkLen
<< endl;
}
- memcpy(mBlkData + mBlkLen, b+offset, len);
+ memcpy(mBlkData + mBlkLen, b, len);
mBlkLen += len;
- already_deleted = true;
- mRelay->mRingBuffer->Del(len + offset);
+ mRelay->mRingBuffer->Del(len);
+
break;
- }
-
- } // if (TsPid((
+ } // if ((pcr - first_pcr) > (0.25 * 90000.0)) {
+ } // if (pcr != -1) {
+ } // if (TsPid((const uchar*) (b+offset)) == mPpid){
+ mCurOffset += 188;
+ } // while ((offset +188) <= r) {
+ } // if (b != NULL) {
+ else
+ *(mLog->log()) << DEBUGPREFIX
+ << " cResponseLive::fillDataBlk_duration() - b is ZERO" << endl;
+
+ if (mInStartPhase) {
+ // still in start Phase, so wait
+ *(mLog->log()) << DEBUGPREFIX
+ << " cResponseLive::fillDataBlk_duration() - still in start phase, so wait" << endl;
+ mRequest->mFactory->clrWriteFlag(mRequest->mFd);
+ mRelay->setNotifRequired();
+ }
+
+ pthread_mutex_unlock(&(mRelay->processedRingLock));
+
+
+ } // if (mInStartPhase) {
+ else {
+ if (mRelay->mRingBuffer->Available() < 188) {
+ // nothing to send, sleep
+ mRequest->mFactory->clrWriteFlag(mRequest->mFd);
+ mRelay->setNotifRequired();
+ return OKAY;
+ }
+
+ pthread_mutex_lock(&(mRelay->processedRingLock));
+ int r;
+ char *b = (char*)mRelay->mRingBuffer->Get(r);
+
+ if (b != NULL) {
+ if ((r % 188) != 0) {
+ *(mLog->log()) << DEBUGPREFIX << " ERROR: r= " << r << " %188 = " << (r%188) << endl;
+ }
+
+ WritePatPmt();
+ int len = (r > (MAXLEN - mBlkLen)) ? (MAXLEN - mBlkLen): r;
+
+ if (r > (MAXLEN - mBlkLen)) {
+ *(mLog->log()) << DEBUGPREFIX
+ << " cResponseLive::fillDataBlk_duration() mInStartPhase = false - ((r - offset ) > (MAXLEN - mBlkLen)) len= " << len
+ << " MAXLEN= " << MAXLEN
+ << " mBlkLen= " << mBlkLen
+ << endl;
+ }
+ memcpy(mBlkData + mBlkLen, b, len);
+
+ mBlkLen += len;
+ mRelay->mRingBuffer->Del(len);
+
+ }
+ else {
+ *(mLog->log()) << DEBUGPREFIX
+ << " cResponseLive::fillDataBlk_duration() - b is ZERO" << endl;
+ }
+
+ pthread_mutex_unlock(&(mRelay->processedRingLock));
+ } // else
+
+ return OKAY;
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+
+bool cResponseLive::findIFrame(char *b, int r) {
+ // search from mCurOffset onwards for the iframe.
+ // return true, when found
+
+ cFrameDetector frame_detector(mVpid, mVtype);
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration findIFrame continue in state " << mTuneInState << " at ts " << mCurOffset/188
+ << endl;
+
+ // run here only if mTuneInState is ZERO
+ if (mTuneInState != 0)
+ return true;
+
+ while ((mCurOffset +188) <= r) {
+
+ if ((b+mCurOffset)[0] != 0x47) {
+ *(mLog->log()) << " fillDataBlk_iPlusDuration - ERROR: ******* Out of Sync " << endl;
+ }
+
+ if (TsPid((const uchar*) (b+mCurOffset)) == mPpid){
+ int64_t pcr = TsGetPcr((const uchar*) (b+mCurOffset));
+ if (pcr != -1) {
+ if (mFirstPcr == -1) {
+
+ mFirstPcr = pcr;
+ mFirstPcrOffset = mCurOffset;
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration - setting mFirstPcr " << mFirstPcr
+ << endl;
+ }
+ mCurPcr = pcr;
+ mCurPcrOffset = mCurOffset;
+ }
+ } // if (TsPid((const uchar*) (b+offset)) == mPpid){
+ if (TsPid((const uchar*) (b+mCurOffset)) == mVpid){
+
+ //ok. point to frame start now. check whether i frame
+ if (TsIsScrambled((const uchar*) (b+mCurOffset)))
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration - TsIsScrambled" << endl;
+
+ if (frame_detector.Analyze((const uchar*) (b+mCurOffset), (r - mCurOffset) ) == 0) {
+ // not sufficient data. delete and return
+ return false;
+ }
+
+ if (frame_detector.NewFrame()) {
+ mNoFrames ++;
+ }
+ else {
+ mCurOffset += 188;
+ continue;
+ }
+
+ if (frame_detector.IndependentFrame()) {
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration iframe found at " << mCurOffset/188
+ << " pkts r= " << r/188 << " mCurPcr= " << mCurPcr
+ << " at " << (mCurPcrOffset/188) << endl;
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration mFirstPcr= " << mFirstPcr
+ << " (mCurPcr - mFirstPcr) / 27MHz= " << (mCurPcr - mFirstPcr) / 27000000.0
+ << endl;
+ mIFrameOffset = mCurOffset;
+
+ mTuneInState = 1;
+ return true;
+ break;
+ }
+
+ } // if (TsPid((const uchar*) (b+offset)) == mVpid){
+ mCurOffset += 188;
+ } // while ((offset +188) <= r) {
+
+ // I should have now the offset of the iframe.
+ if (mIFrameOffset == -1){
+ return false;
+ }
+
+ return false;
+}
+
+bool cResponseLive::bufferData(char* b, int r) {
+ // buffer additional data, after the iframe.
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration bufferData continue in state " << mTuneInState << " at ts "<< mCurOffset/188
+ << " with mCurPcr= " << mCurPcr
+ << endl;
+
+ while ((mCurOffset +188) <= r) {
+ if (TsPid((const uchar*) (b+mCurOffset)) == mPpid){
+ int64_t pcr = TsGetPcr((const uchar*) (b+mCurOffset));
+ if (pcr != -1) {
+
+ if (mFirstPcr == -1) {
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration - WARNING - re setting mFirstPcr " << mCurOffset/188
+ << endl;
+ mFirstPcr = pcr;
+ mFirstPcrOffset = mCurOffset;
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration - setting mFirstPcr " << mFirstPcr
+ << endl;
+
+ }
+
+ if (mCurPcr == -1){
+ mCurPcr = pcr;
+ mCurPcrOffset = mCurOffset;
+ mCurOffset += 188;
+ continue; // process next packet
+ }
+ if (mCurPcr > pcr) {
+ mCurPcr = pcr;
+ mCurPcrOffset = mCurOffset;
- offset += 188;
- } // while (offset < r) {
-
- if (!already_deleted) {
- *(mLog->log()) << DEBUGPREFIX << " cResponseLive::fillDataBlk() - Not sufficient data. Deleting "
- << offset << " Byte" << endl;
- mRelay->mRingBuffer->Del(offset + 188);
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration - ERROR - wired. setting new mCurPcr= " << mCurPcr
+ << " pkt= " << mCurOffset / 188 << endl;
+ mCurOffset += 188;
+ continue; // process next packet
}
- } // if (mInStartPhase)
+ // if ((pcr - first_pcr) > (0.8 * 27000000.0)) {
+ if ((pcr - mCurPcr) > (mRequest->mFactory->getConfig()->getBuiltInLiveBufDur() * 27000000.0)) {
+ // OK, sufficient data to start
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration - starting "
+ << "pcr= " << pcr
+ << " mCurPcr= " << mCurPcr
+ << " (pcr - mCurPcr ) / 27MHz = "
+ << (pcr - mCurPcr) / 27000000.0
+ << endl ;
+
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration --- "
+ << " pcr= " << pcr
+ << " mFirstPcr= " << mFirstPcr
+ << " (pcr - mFirstPcr) / 27MGz= " << (pcr - mFirstPcr ) / 27000000.0
+ << endl;
- else {
-
- WritePatPmt();
- int len = (r > (MAXLEN - mBlkLen)) ? (MAXLEN - mBlkLen): r;
-
- if (r > (MAXLEN - mBlkLen)) {
*(mLog->log()) << DEBUGPREFIX
- << " cResponseLive::fillDataBlk() mInStartPhase = false - ((r - offset ) > (MAXLEN - mBlkLen)) len= " << len
- << " MAXLEN= " << MAXLEN
- << " mBlkLen= " << mBlkLen
- << endl;
+ << " fillDataBlk_iPlusDuration mFirstPcr= " << mFirstPcr
+ << " (mCurPcr - mFirstPcr) / 27MHz= " << (mCurPcr - mFirstPcr) / 27000000.0
+ << endl;
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration "
+ << " no_frames " << mNoFrames
+ << " ts pkts= " << ((mCurOffset +188)/ 188)
+ << " offset= " << mCurOffset
+ << endl;
+
+
+ mInStartPhase = false;
+ mTuneInState = 2;
+
+ sendHeaders(200, "OK", NULL, "video/mpeg", -1, -1);
+ WritePatPmt();
+
+ return true;
+ break;
+
+ } // if ((pcr - first_pcr) > (0.8 * 27000000.0)) {
+ }
+ } // if (TsPid((const uchar*) (b+offset)) == mPpid){ // find pcr
+ mCurOffset += 188;
+ } //while ((offset +188) <= r) { // find pcr
+
+ return false;
+}
+
+bool cResponseLive::setLowerOffset(char *b, int r) {
+ mLowerOffset = 0;
+
+ if (mCurPcr != -1) {
+ int idx = 0;
+ while ((idx +188) <= mIFrameOffset) {
+ // I only need to run until the offset of the i frame.
+ if (TsPid((const uchar*) (b+idx)) == mPpid){
+ int64_t pcr = TsGetPcr((const uchar*) (b+idx));
+ if (pcr != -1) {
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration find lower_offset pkt= " << idx / 188
+ << " pcr= " << pcr
+ << " ((mCurPcr - pcr) / 27000000.0)= " << ((mCurPcr - pcr) / 27000000.0)
+ << endl;
+ if (((mCurPcr - pcr) / 27000000.0) < 0.55) {
+ if (((mCurPcr - pcr) / 27000000.0) > 0.48) {
+ // from here.
+ mLowerOffset = idx;
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration - lower_offset= " << mLowerOffset
+ << " pcr= " << pcr
+ << " ((pcr - mFirst_pcr) / 27MHz)= " << (( pcr - mFirstPcr) / 27000000.0)
+ << endl;
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration - lower_offset= "
+ << " ((mCurPcr - pcr ) / 27MHz)= " << (( mCurPcr - pcr ) / 27000000.0)
+ << endl;
+
+ }
+ break;
+ }
}
- memcpy(mBlkData + mBlkLen, b, len);
-
- mBlkLen += len;
- mRelay->mRingBuffer->Del(len);
- } // else
- } // if (b != NULL)
- else {
- *(mLog->log()) << DEBUGPREFIX << " WARNING - cResponseLive::fillDataBlk() - b== NULL" << endl;
- }
- pthread_mutex_unlock(&(mRelay->processedRingLock));
- }
- else {
- mRequest->mFactory->clrWriteFlag(mRequest->mFd);
- mRelay->setNotifRequired();
+ }
+ idx += 188;
+ } // while ((idx +188) <= offset)
}
-
- return OKAY;
+ return true;
}
+void cResponseLive::justFillDataBlk(char *b, int r) {
+ int len = ((r - mLowerOffset) > (MAXLEN - mBlkLen)) ? (MAXLEN - mBlkLen): (r - mLowerOffset);
+
+ if (( r - mLowerOffset) > (MAXLEN - mBlkLen)) {
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration - mInStartPhase = false - ((r - offset ) > (MAXLEN - mBlkLen)) len= " << len
+ << " MAXLEN= " << MAXLEN
+ << " mBlkLen= " << mBlkLen
+ << endl;
+ }
+ memcpy(mBlkData + mBlkLen, (b + mLowerOffset), len);
+
+ mBlkLen += len;
+ mRelay->mRingBuffer->Del(mLowerOffset + len);
+
+};
+
+// new method: 200ms after the IFrame
+int cResponseLive::fillDataBlk_iPlusDuration() {
+ //TODO: Prapably, I need to delete some data before the i_frame offset
-int cResponseLive::fillDataBlk_straight() {
mBlkPos = 0;
mBlkLen = 0;
if (mError)
return ERROR;
- int threshold = (mInStartPhase) ? mStartThreshold : (1*188);
-
- if (mRelay->mRingBuffer->Available() >= threshold) {
-
+ if (mInStartPhase) {
pthread_mutex_lock(&(mRelay->processedRingLock));
int r;
char *b = (char*)mRelay->mRingBuffer->Get(r);
-
- if (b != NULL) {
- mInStartPhase = false;
+ if (b != NULL) {
if ((r % 188) != 0) {
*(mLog->log()) << DEBUGPREFIX
- << " ERROR: r= " << r << " %188 = " << (r%188) << endl;
+ << " fillDataBlk_iPlusDuration - ERROR: r= " << r << " %188 = " << (r%188) << endl;
+ }
+
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration --------------- pkts= " << r / 188 << endl;
+
+ if((r / 188) > 40000) {
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration Risk an overrun, so starting " << r / 188 << endl;
+
+ sendHeaders(200, "OK", NULL, "video/mpeg", -1, -1);
+ WritePatPmt();
+
+ justFillDataBlk(b,r);
+ mInStartPhase = false;
+ pthread_mutex_unlock(&(mRelay->processedRingLock));
+ return OKAY;
+ }
+
+ if (!findIFrame(b, r)) {
+
+ pthread_mutex_unlock(&(mRelay->processedRingLock));
+ // sleep for a while, not sufficient data
+ mRequest->mFactory->clrWriteFlag(mRequest->mFd);
+ mRelay->setNotifRequired();
+ return OKAY;
}
+ if (!bufferData(b, r)) {
+ // return;
+ pthread_mutex_unlock(&(mRelay->processedRingLock));
+
+ // sleep for a while, not sufficient data
+ mRequest->mFactory->clrWriteFlag(mRequest->mFd);
+ mRelay->setNotifRequired();
+ return OKAY;
+ }
+ else {
+ // have all data now!
+ // pthread_mutex_unlock(&(mRelay->processedRingLock));
+ // return OKAY;
+ }
+
+ // here I have all data.
+ setLowerOffset(b,r);
+ justFillDataBlk(b,r);
+
+ } // if (b != NULL) { in startPhase
+ else
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration - b is ZERO" << endl;
+ pthread_mutex_unlock(&(mRelay->processedRingLock));
+
+ } // if (mInStartPhase) {
+ else {
+ // not in start phase
+
+ if (mRelay->mRingBuffer->Available() < 188) {
+ // nothing to send, sleep
+ mRequest->mFactory->clrWriteFlag(mRequest->mFd);
+ mRelay->setNotifRequired();
+ return OKAY;
+ }
+
+ pthread_mutex_lock(&(mRelay->processedRingLock));
+ int r;
+ char *b = (char*)mRelay->mRingBuffer->Get(r);
+
+ if (b != NULL) {
+ if ((r % 188) != 0) {
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration - ERROR: r= " << r << " %188 = " << (r%188) << endl;
+ }
WritePatPmt();
int len = (r > (MAXLEN - mBlkLen)) ? (MAXLEN - mBlkLen): r;
if (r > (MAXLEN - mBlkLen)) {
*(mLog->log()) << DEBUGPREFIX
- << " cResponseLive::fillDataBlk() mInStartPhase = false - ((r - offset ) > (MAXLEN - mBlkLen)) len= " << len
+ << " fillDataBlk_iPlusDuration - mInStartPhase = false - ((r - offset ) > (MAXLEN - mBlkLen)) len= " << len
<< " MAXLEN= " << MAXLEN
<< " mBlkLen= " << mBlkLen
<< endl;
@@ -535,17 +842,17 @@ int cResponseLive::fillDataBlk_straight() {
mBlkLen += len;
mRelay->mRingBuffer->Del(len);
-
- } // if (b != NULL)
+ } // if (b != NULL) {
else {
- *(mLog->log()) << DEBUGPREFIX << " WARNING - cResponseLive::fillDataBlk() - b== NULL" << endl;
+ *(mLog->log()) << DEBUGPREFIX
+ << " fillDataBlk_iPlusDuration - b is ZERO" << endl;
+
}
- pthread_mutex_unlock(&(mRelay->processedRingLock));
- }
- else {
- mRequest->mFactory->clrWriteFlag(mRequest->mFd);
- mRelay->setNotifRequired();
- }
+ pthread_mutex_unlock(&(mRelay->processedRingLock));
+
+ } // else
+
return OKAY;
}
+
diff --git a/responselive.h b/responselive.h
index 2c8792f..c1d2186 100644
--- a/responselive.h
+++ b/responselive.h
@@ -101,8 +101,15 @@ class cResponseLive : public cResponseBase {
int fillDataBlk();
int fillDataBlk_straight();
- int fillDataBlk_pcr();
- int fillDataBlk_iframe();
+ // int fillDataBlk_pcr();
+ // int fillDataBlk_iframe();
+ int fillDataBlk_duration();
+ int fillDataBlk_iPlusDuration();
+
+ bool findIFrame(char *b, int r);
+ bool bufferData(char *b, int r);
+ bool setLowerOffset(char *b, int r);
+ void justFillDataBlk(char *b, int r);
private:
bool InitRelay(string chan_id);
@@ -119,6 +126,18 @@ class cResponseLive : public cResponseBase {
int mPpid;
int mStartThreshold;
+
+ // Mode 4
+ int mCurOffset;
+ int mTuneInState;
+ uint64_t mFirstPcr;
+ int mFirstPcrOffset;
+ uint64_t mCurPcr;
+ int mCurPcrOffset;
+ int mNoFrames;
+ int mIFrameOffset;
+
+ int mLowerOffset;
};
#endif
diff --git a/stvw_cfg.c b/stvw_cfg.c
index 14acffc..2c0f252 100755
--- a/stvw_cfg.c
+++ b/stvw_cfg.c
@@ -34,7 +34,7 @@
cSmartTvConfig::cSmartTvConfig(string d): mConfigDir(d), mLog(NULL), mCfgFile(NULL),
mLogFile(), mMediaFolder(), mSegmentDuration(), mHasMinBufferTime(), mHasBitrateCorrection(),
mLiveChannels(), mGroupSep(IGNORE), mServerAddress(""), mServerPort(8000), mCmds(false), mUseStreamDev4Live(true),
- mBuiltInLiveStartMode (2), mBuiltInLivePktBuf4Hd(150), mBuiltInLivePktBuf4Sd(75) {
+ mBuiltInLiveStartMode (2), mBuiltInLivePktBuf4Hd(150), mBuiltInLivePktBuf4Sd(75), mBuiltInLiveBufDur(0.6) {
#ifndef STANDALONE
mLogFile= "";
@@ -73,7 +73,7 @@ void cSmartTvConfig::printConfig() {
*(mLog->log()) << " BuiltInLiveStartMode: " << mBuiltInLiveStartMode << endl;
*(mLog->log()) << " BuiltInLivePktBuf4Hd: " << mBuiltInLivePktBuf4Hd << endl;
*(mLog->log()) << " BuiltInLivePktBuf4Sd: " << mBuiltInLivePktBuf4Sd << endl;
-
+ *(mLog->log()) << " BuiltInLiveBufDur: " << mBuiltInLiveBufDur << endl;
}
@@ -169,7 +169,7 @@ void cSmartTvConfig::readConfig() {
if (strcmp(attr, "BuiltInLiveStartMode") == 0) {
mBuiltInLiveStartMode = atoi(value);
- if ((mBuiltInLiveStartMode <0) || (mBuiltInLiveStartMode > 2))
+ if ((mBuiltInLiveStartMode <0) || (mBuiltInLiveStartMode > 4))
mBuiltInLiveStartMode = 0;
continue;
}
@@ -182,6 +182,13 @@ void cSmartTvConfig::readConfig() {
mBuiltInLivePktBuf4Sd = atoi(value);
continue;
}
+
+ if (strcmp(attr, "BuiltInLiveBufDur") == 0) {
+ mBuiltInLiveBufDur = atoi(value) /1000.0;
+ if (mBuiltInLiveBufDur <= 0.0)
+ mBuiltInLiveBufDur = 0.5;
+ continue;
+ }
#ifndef STANDALONE
esyslog("WARNING in SmartTvWeb: Attribute= %s with value= %s was not processed, thus ignored.", attr, value);
diff --git a/stvw_cfg.h b/stvw_cfg.h
index 983a5f0..3c134d0 100755
--- a/stvw_cfg.h
+++ b/stvw_cfg.h
@@ -60,6 +60,7 @@ class cSmartTvConfig {
int mBuiltInLiveStartMode;
int mBuiltInLivePktBuf4Hd;
int mBuiltInLivePktBuf4Sd;
+ double mBuiltInLiveBufDur;
public:
cSmartTvConfig(string dir);
@@ -82,6 +83,7 @@ class cSmartTvConfig {
int getBuiltInLiveStartMode() {return mBuiltInLiveStartMode; };
int getBuiltInLivePktBuf4Hd() { return mBuiltInLivePktBuf4Hd; };
int getBuiltInLivePktBuf4Sd() { return mBuiltInLivePktBuf4Sd; };
+ double getBuiltInLiveBufDur() { return mBuiltInLiveBufDur; };
};