Skip to content

Commit

Permalink
Fix issues with seeking routine.
Browse files Browse the repository at this point in the history
  • Loading branch information
MayaPosch committed Mar 19, 2020
1 parent a23118d commit 69ce84c
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 11 deletions.
34 changes: 29 additions & 5 deletions src/server/NymphCastServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ void resetDataBuffer() {
media_buffer.currentSlot = 0; // The current vector slot we're using.
media_buffer.numSlots = 50; // Total number of slots in the data vector.
media_buffer.nextSlot = 0; // Next slot to fill in the buffer vector.
media_buffer.buffSlotLow = 0;
media_buffer.buffIndexLow = 0; // File index at the buffer front.
media_buffer.buffIndexHigh = 0;
media_buffer.freeSlots = 50;
Expand All @@ -284,20 +285,29 @@ void resetDataBuffer() {
// If we're in the midst of a seeking operation, we are done here.
if (media_buffer.seeking) {
// Set high/low indices for the buffer in preparation for new data.
media_buffer.buffIndexLow = media_buffer.seekingPosition.load();
media_buffer.buffIndexHigh = media_buffer.seekingPosition.load();
//media_buffer.buffIndexLow = media_buffer.seekingPosition.load();
//media_buffer.buffIndexHigh = media_buffer.seekingPosition.load();

// Send message to client indicating that we're seeking in the file.
std::vector<NymphType*> values;
values.push_back(new NymphUint64(media_buffer.seekingPosition));
std::string result;
NymphBoolean* resVal = 0;
if (!NymphRemoteClient::callCallback(media_buffer.activeSession, "MediaSeekCallback", values, result)) {
std::cerr << "Calling media stop callback failed: " << result << std::endl;
std::cerr << "Calling media seek callback failed: " << result << std::endl;
media_buffer.seeking = false;
return;
}
media_buffer.seeking = false;

// Wait for the seeking condition variable to be called or time out.
media_buffer.seekingMutex.lock();
if (!media_buffer.seekingCondition.tryWait(media_buffer.seekingMutex, 500)) {
// Condition variable wasn't signalled before time-out. Return.
// Signal seeking operation failure by not resetting the 'seeking' boolean condition.
return;
}

media_buffer.seeking = false;
return;
}

Expand Down Expand Up @@ -592,7 +602,7 @@ NymphMessage* connectClient(int session, NymphMessage* msg, void* data) {
values.push_back(getPlaybackStatus());
std::string result;
NymphBoolean* resVal = 0;
if (!NymphRemoteClient::callCallback(media_buffer.activeSession, "MediaStatusCallback", values, result)) {
if (!NymphRemoteClient::callCallback(session, "MediaStatusCallback", values, result)) {
std::cerr << "Calling media status callback failed: " << result << std::endl;
}

Expand Down Expand Up @@ -685,6 +695,11 @@ NymphMessage* session_data(int session, NymphMessage* msg, void* data) {
// TODO: if this boolean is false already, dismiss message?
media_buffer.requestInFlight = false;

if (media_buffer.seeking) {
// Signal condition variable to indicate seeking operation succeeded.
media_buffer.seekingCondition.signal();
}

// Get iterator to the session instance for the client.
std::map<int, CastClient>::iterator it;
it = clients.find(session);
Expand All @@ -709,6 +724,14 @@ NymphMessage* session_data(int session, NymphMessage* msg, void* data) {
media_buffer.slotBytesLeft = mediaData.length();
}

// Update buffer lower bound slot if necessary.
if (media_buffer.nextSlot == media_buffer.buffSlotLow) {
media_buffer.buffIndexLow += media_buffer.slotSize;
if (!(++media_buffer.buffSlotLow < media_buffer.numSlots)) {
media_buffer.buffSlotLow = 0;
}
}

media_buffer.nextSlot++;
if (!(media_buffer.nextSlot < media_buffer.numSlots)) { media_buffer.nextSlot = 0; }

Expand Down Expand Up @@ -1513,6 +1536,7 @@ int main(int argc, char** argv) {
media_buffer.currentSlot = 0; // The current vector slot we're using.
media_buffer.numSlots = 50; // Total number of slots in the data vector.
media_buffer.nextSlot = 0; // Next slot to fill in the buffer vector.
media_buffer.buffSlotLow = 0;
media_buffer.buffIndexLow = 0; // File index at the buffer start (low).
media_buffer.buffIndexHigh = 0; // File index at the buffer end (high).
media_buffer.freeSlots = 50;
Expand Down
25 changes: 19 additions & 6 deletions src/server/ffplay/ffplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,6 @@ int Ffplay::media_read(void* opaque, uint8_t* buf, int buf_size) {
db->currentIndex = 0;
db->slotBytesLeft = db->slotSize.load();
db->freeSlots++; // The used buffer slot just became available for more data.
db->buffIndexLow += db->slotSize;
}
else {
db->currentIndex += byteCount;
Expand Down Expand Up @@ -453,26 +452,40 @@ int Ffplay::media_read(void* opaque, uint8_t* buf, int buf_size) {
*
* @param opaque A pointer to the user-defined IO data structure.
* @param offset The position to seek to.
* @param origin The relative point (origin) from which the seek is performed.
* @param whence .
*
* @return The new position in the file.
* @return The new byte position in the file or -1 in case of failure.
*/
int64_t Ffplay::media_seek(void* opaque, int64_t offset, int origin) {
int64_t Ffplay::media_seek(void* opaque, int64_t offset, int whence) {
std::cout << "media_seek: offset " << offset << ", origin " << whence << std::endl;
if (whence == AVSEEK_SIZE) {
std::cout << "media_seek: received AVSEEK_SIZE, returning unknown file size." << std::endl;
return -1; // FIXME: we don't know the file handle size.
}

DataBuffer* db = static_cast<DataBuffer*>(opaque);
std::cout << "IdxLow: " << db->buffIndexLow << ", IdxHigh: " << db->buffIndexHigh << std::endl;

// Try to find the index in the buffered data. If unavailable, request new data from client.
if (offset < db->buffIndexLow || offset > db->buffIndexHigh) {
// Reset the buffer and send request to client.
db->seeking = true;
db->seekingPosition = offset;
std::cout << "Resetting data buffer..." << std::endl;
resetDataBuffer();
if (db->seeking) {
// Seeking operation failed.
std::cerr << "Seeking failed." << std::endl;
return -1;
}

db->seeking = false;
}
else {
// Set the new position of the index in the appropriate buffer.
uint64_t adjusted_offset = offset - db->buffIndexLow;
uint32_t oldSlot = db->currentSlot;
uint32_t wholeSlots = adjusted_offset / db->slotSize;
uint32_t newSlot = (adjusted_offset / db->slotSize) + db->currentSlot;
uint32_t newSlot = (adjusted_offset / db->slotSize) + db->buffSlotLow;
if ((newSlot + 1) > db->numSlots) {
newSlot -= (db->numSlots - 1);
}
Expand Down
3 changes: 3 additions & 0 deletions src/server/ffplay/ffplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ struct DataBuffer {
std::atomic<uint32_t> buffBytesLeft; // Number of bytes available for reading in the buffer.
std::atomic<bool> eof; // Whether End of File for the source file has been reached.

std::atomic<uint32_t> buffSlotLow; // Current slot containing the low index.
std::atomic<uint64_t> buffIndexLow; // File index at the buffer front (low index).
std::atomic<uint64_t> buffIndexHigh; // File index at the buffer back (high index).
Poco::Mutex mutex;
Expand All @@ -55,6 +56,8 @@ struct DataBuffer {
std::atomic<bool> requestInFlight;
std::atomic<bool> seeking; // Are we performing a seeking operation?
std::atomic<uint64_t> seekingPosition; // Position to seek to.
Poco::Condition seekingCondition;
Poco::Mutex seekingMutex;

Poco::Mutex streamTrackQueueMutex;
std::queue<std::string> streamTrackQueue;
Expand Down

0 comments on commit 69ce84c

Please sign in to comment.