void RtspTrackBuffer::Reset() { MonitorAutoLock monitor(mMonitor); mProducerIdx = 0; mConsumerIdx = 0; for (uint32_t i = 0; i < BUFFER_SLOT_NUM; ++i) { mBufferSlotData[i].mLength = BUFFER_SLOT_EMPTY; mBufferSlotData[i].mTime = BUFFER_SLOT_EMPTY; } mMonitor.NotifyAll(); }
Thread_Impl(concurrent_queue<Task *> &q, Monitor &mon) : queue(q) , monitor(mon.GetMutex()) , live(true) , started(false) , thread(ThreadFunction, ThreadFunctionArg(*this, started)) { while(!started){ monitor.NotifyAll(); } }
void RtspTrackBuffer::Reset() { MonitorAutoLock monitor(mMonitor); mProducerIdx = 0; mConsumerIdx = 0; for (uint32_t i = 0; i < BUFFER_SLOT_NUM; ++i) { mBufferSlotData[i].mLength = BUFFER_SLOT_EMPTY; mBufferSlotData[i].mTime = BUFFER_SLOT_EMPTY; mBufferSlotData[i].mFrameType = MEDIASTREAM_FRAMETYPE_NORMAL; } StopPlayoutDelay(); mMonitor.NotifyAll(); }
/* When we perform a WriteBuffer, we check mIsStarted and aFrameType first. * These flags prevent "garbage" frames from being written into the buffer. * * After writing the data into the buffer, we check to see if we wrote over a * slot, and update mConsumerIdx if necessary. * This ensures that the decoder will get the "oldest" data available in the * buffer. * * If the incoming data is larger than one slot size (isMultipleSlots), we do * |mBufferSlotData[].mLength = BUFFER_SLOT_INVALID;| for other slots except the * first slot, in order to notify the reader that some slots are unavailable. * * If the incoming data is isMultipleSlots and crosses the end of * BUFFER_SLOT_NUM, returnToHead is set to true and the data will continue to * be written from head(index 0). * * MEDIASTREAM_FRAMETYPE_DISCONTINUITY currently is used when we are seeking. * */ void RtspTrackBuffer::WriteBuffer(const char *aFromBuffer, uint32_t aWriteCount, uint64_t aFrameTime, uint32_t aFrameType) { MonitorAutoLock monitor(mMonitor); if (!mIsStarted) { RTSPMLOG("mIsStarted is false"); return; } if (mTotalBufferSize < aWriteCount) { RTSPMLOG("mTotalBufferSize < aWriteCount, incoming data is too large"); return; } // Checking the incoming data's frame type. // If we receive MEDIASTREAM_FRAMETYPE_DISCONTINUITY, clear the mFrameType // imply the RtspTrackBuffer is ready for receive data. if (aFrameType & MEDIASTREAM_FRAMETYPE_DISCONTINUITY) { mFrameType = mFrameType & (~MEDIASTREAM_FRAMETYPE_DISCONTINUITY); RTSPMLOG("Clear mFrameType"); return; } // Checking current buffer frame type. // If the MEDIASTREAM_FRAMETYPE_DISCONTINUNITY bit is set, imply the // RtspTrackBuffer can't receive data now. So we drop the frame until we // receive MEDIASTREAM_FRAMETYPE_DISCONTINUNITY. if (mFrameType & MEDIASTREAM_FRAMETYPE_DISCONTINUITY) { RTSPMLOG("Return because the mFrameType is set"); return; } // The flag is true if the incoming data is larger than one slot size. bool isMultipleSlots = false; // The flag is true if the incoming data is larger than remainder free slots bool returnToHead = false; // Calculate how many slots the incoming data needed. int32_t slots = 1; int32_t i; RTSPMLOG("WriteBuffer mTrackIdx %d mProducerIdx %d mConsumerIdx %d", mTrackIdx, mProducerIdx,mConsumerIdx); if (aWriteCount > mSlotSize) { isMultipleSlots = true; slots = (aWriteCount / mSlotSize) + 1; } if (isMultipleSlots && (aWriteCount > (BUFFER_SLOT_NUM - mProducerIdx) * mSlotSize)) { returnToHead = true; } RTSPMLOG("slots %d isMultipleSlots %d returnToHead %d", slots, isMultipleSlots, returnToHead); if (returnToHead) { // Clear the rest index of mBufferSlotData[].mLength for (i = mProducerIdx; i < BUFFER_SLOT_NUM; ++i) { mBufferSlotData[i].mLength = BUFFER_SLOT_INVALID; } // We wrote one or more slots that the decode thread has not yet read. // So the mConsumerIdx returns to the head of slot buffer and moves forward // to the oldest slot. if (mProducerIdx <= mConsumerIdx && mConsumerIdx < mProducerIdx + slots) { mConsumerIdx = 0; for (i = mConsumerIdx; i < BUFFER_SLOT_NUM; ++i) { if (mBufferSlotData[i].mLength > 0) { mConsumerIdx = i; break; } } } mProducerIdx = 0; } if (!(aFrameType & MEDIASTREAM_FRAMETYPE_END_OF_STREAM)) { memcpy(&(mRingBuffer[mSlotSize * mProducerIdx]), aFromBuffer, aWriteCount); } if (mProducerIdx <= mConsumerIdx && mConsumerIdx < mProducerIdx + slots && mBufferSlotData[mConsumerIdx].mLength > 0) { // Wrote one or more slots that the decode thread has not yet read. RTSPMLOG("overwrite!! %d time %lld" ,mTrackIdx,mBufferSlotData[mConsumerIdx].mTime); if (aFrameType & MEDIASTREAM_FRAMETYPE_END_OF_STREAM) { mBufferSlotData[mProducerIdx].mLength = 0; mBufferSlotData[mProducerIdx].mTime = 0; } else { mBufferSlotData[mProducerIdx].mLength = aWriteCount; mBufferSlotData[mProducerIdx].mTime = aFrameTime; } mBufferSlotData[mProducerIdx].mFrameType = aFrameType; // Clear the mBufferSlotDataLength except the start slot. if (isMultipleSlots) { for (i = mProducerIdx + 1; i < mProducerIdx + slots; ++i) { mBufferSlotData[i].mLength = BUFFER_SLOT_INVALID; } } mProducerIdx = (mProducerIdx + slots) % BUFFER_SLOT_NUM; // Move the mConsumerIdx forward to ensure that the decoder reads the // oldest data available. mConsumerIdx = mProducerIdx; } else { // Normal case, the writer doesn't take over the reader. if (aFrameType & MEDIASTREAM_FRAMETYPE_END_OF_STREAM) { mBufferSlotData[mProducerIdx].mLength = 0; mBufferSlotData[mProducerIdx].mTime = 0; } else { mBufferSlotData[mProducerIdx].mLength = aWriteCount; mBufferSlotData[mProducerIdx].mTime = aFrameTime; } mBufferSlotData[mProducerIdx].mFrameType = aFrameType; // Clear the mBufferSlotData[].mLength except the start slot. if (isMultipleSlots) { for (i = mProducerIdx + 1; i < mProducerIdx + slots; ++i) { mBufferSlotData[i].mLength = BUFFER_SLOT_INVALID; } } mProducerIdx = (mProducerIdx + slots) % BUFFER_SLOT_NUM; } mMonitor.NotifyAll(); }