From c9cd529927916eea53f1db02342bf6e112f83f65 Mon Sep 17 00:00:00 2001 From: Marco Date: Mon, 15 Feb 2021 14:16:47 +0100 Subject: [PATCH] Fixes for playlist support Track matching fixes: Input MP4 is not getting dimensions properly, causing resume to not find a collision Fixed by overwriting dimensions when media frames are read Detecting collisions using track identifier can cause issues (ie audio_AAC_2ch_44100hz_eng VS audio_AAC_2ch_44100hz) Fixed by matching using init data, then check by identifier if there is more than 1 match Fixed buffering code for playlist streams, ensuring correct page creation: In resume mode new pages do not get created, but existing one(s) fill up Keyframes were not being recognized due to them being deleted during track switching Fixed by changing negotiationProxy::bufferNext: Removed seemingly unnecessary function which cleared keyframes Lastly, the offset of a resumed track seems wrong Added to NegotiationProxy::continueNegotiate pagesByTrack[tid][firstPage].curOffset = 0; Added to negotiationProxy::bufferSinglePacket: if (!pagesByTrack[tid][currentPageNum].curOffset) { pagesByTrack[tid][currentPageNum].firstTime = packet.getTime(); } Fixed numbering for keys from the buffer when accepting tracks (was amount of buffered keys, not last key number) --- src/input/input_buffer.cpp | 31 ++++++++++++++++++++++++------- src/input/input_mp4.cpp | 8 ++++---- src/io.cpp | 14 +++++++++----- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/input/input_buffer.cpp b/src/input/input_buffer.cpp index 688ded63..eea8e9c2 100644 --- a/src/input/input_buffer.cpp +++ b/src/input/input_buffer.cpp @@ -741,7 +741,11 @@ namespace Mist { //Write the final mapped track number and keyframe number to the user page element //This is used to resume pushing as well as pushing new tracks userConn.setTrackId(index, finalMap); - userConn.setKeynum(index, myMeta.tracks[finalMap].keys.size()); + if (myMeta.tracks[finalMap].keys.size()){ + userConn.setKeynum(index, myMeta.tracks[finalMap].keys.rbegin()->getNumber()); + }else{ + userConn.setKeynum(index, 0); + } continue; } //Set the temporary track id for this item, and increase the temporary value for use with the next track @@ -800,14 +804,27 @@ namespace Mist { continue; } - std::string trackIdentifier = trackMeta.tracks.find(value)->second.getIdentifier(); - DEBUG_MSG(DLVL_HIGH, "Attempting colision detection for track %s", trackIdentifier.c_str()); - //Get the identifier for the track, and attempt colission detection. + //Get the identifier for the track, and attempt colision detection. + ///\todo Maybe switch to a new form of detecting collisions, especially with regards to multiple audio languages and camera angles. int collidesWith = -1; + std::string newTrackIdentifier = trackMeta.tracks.find(value)->second.getIdentifier(); + std::string newTrackInit = trackMeta.tracks.find(value)->second.init; + INFO_MSG("Attempting colision detection for track %s", newTrackIdentifier.c_str()); + + //First check for matches on INIT data for (std::map::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++) { - //If the identifier of an existing track and the current track match, assume the are the same track and reject the negotiated one. - ///\todo Maybe switch to a new form of detecting collisions, especially with regards to multiple audio languages and camera angles. - if (it->second.getIdentifier() == trackIdentifier) { + if (it->second.init == newTrackInit) { + // It is the first match + if (collidesWith == -1){ + collidesWith = it->first; + } + // More than one match: check if identifier matches + else if (it->second.getIdentifier() == newTrackIdentifier) { + collidesWith = it->first; + break; + } + } + else if (it->second.getIdentifier() == newTrackIdentifier) { collidesWith = it->first; break; } diff --git a/src/input/input_mp4.cpp b/src/input/input_mp4.cpp index 1a99baaa..7ddd2e15 100644 --- a/src/input/input_mp4.cpp +++ b/src/input/input_mp4.cpp @@ -289,10 +289,10 @@ namespace Mist{ MP4::VisualSampleEntry & vEntryBox = (MP4::VisualSampleEntry&)sEntryBox; myMeta.tracks[trackNo].type = "video"; myMeta.tracks[trackNo].codec = "H264"; - if (!myMeta.tracks[trackNo].width){ - myMeta.tracks[trackNo].width = vEntryBox.getWidth(); - myMeta.tracks[trackNo].height = vEntryBox.getHeight(); - } + + myMeta.tracks[trackNo].width = vEntryBox.getWidth(); + myMeta.tracks[trackNo].height = vEntryBox.getHeight(); + MP4::Box initBox = vEntryBox.getCLAP(); if (initBox.isType("avcC")){ myMeta.tracks[trackNo].init.assign(initBox.payload(), initBox.payloadSize()); diff --git a/src/io.cpp b/src/io.cpp index a6c8d234..a3448415 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -381,9 +381,8 @@ namespace Mist { if (myMeta.live){ myMeta.update(pack); - for (std::map::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++) { - it->second.clearParts(); - } + // unsigned long cleanTrackID = pack.getTrackId(); + // myMeta.tracks[cleanTrackID].removeOldKeyframes(pack.getTime() - pack.timeOffset); } //End of brain melt @@ -550,10 +549,14 @@ namespace Mist { } //Take the last allocated page std::map::reverse_iterator tmpIt = pagesByTrack[tid].rbegin(); + int currentPageNum = tmpIt->second.pageNum; + if (!pagesByTrack[tid][currentPageNum].curOffset) { + pagesByTrack[tid][currentPageNum].firstTime = packet.getTime(); + } //Compare on 8 mb boundary - if (tmpIt->second.curOffset > FLIP_DATA_PAGE_SIZE || packet.getTime() - tmpIt->second.firstTime > FLIP_TARGET_DURATION) { + if ((tmpIt->second.curOffset > FLIP_DATA_PAGE_SIZE || (packet.getTime() - tmpIt->second.firstTime) > FLIP_TARGET_DURATION) && tmpIt->second.keyNum > 0) { //Create the book keeping data for the new page - nextPageNum = tmpIt->second.pageNum + tmpIt->second.keyNum; + nextPageNum = currentPageNum + tmpIt->second.keyNum; HIGH_MSG("We should go to next page now, transition from %lu to %d", tmpIt->second.pageNum, nextPageNum); pagesByTrack[tid][nextPageNum].dataSize = DEFAULT_DATA_PAGE_SIZE; pagesByTrack[tid][nextPageNum].pageNum = nextPageNum; @@ -812,6 +815,7 @@ namespace Mist { pagesByTrack[tid][firstPage].dataSize = DEFAULT_DATA_PAGE_SIZE;//Initialize op 25mb pagesByTrack[tid][firstPage].pageNum = firstPage; pagesByTrack[tid][firstPage].firstTime = 0; + pagesByTrack[tid][firstPage].curOffset = 0; } break; }