aae7a508 by David LaPalomento

Close off all FLV tags at the end of a segment

The segment parser allows fragmentary input to the muxing process so it's not always clear when a tag should be finalized at the end of the input. By calling segmentParser.flushTags(), the parser is instructed to wrap up whatever input it currently has buffered into an FLV tag. Before this change, the last tag of the video stream would be buffered in the parser, waiting for additional input (i.e. another segment download) to flush it out. When you seeked within a segment, that last tag would have a timestamp greater than your seek point and we were assuming that timestamp values were sorted in ascending order. We would see the timestamp value greater than the desired seek location and start feeding tags into the media source, which resulted in the segment appearing to restart. Now, we close off any tags that are buffered at the end of a segment so the inter-segment seeking routine can assume that tags are delivered in the order of playback.
1 parent 216ff405
......@@ -292,7 +292,7 @@
//(pts:uint, dts:uint, dataAligned:Boolean):void
this.setNextTimeStamp = function(pts, dts, dataAligned) {
if (0>pts_delta) {
if (pts_delta < 0) {
// We assume the very first pts is less than 0x8FFFFFFF (max signed
// int32)
pts_delta = pts;
......@@ -310,7 +310,7 @@
this.finishFrame = function() {
if (h264Frame) {
// Push SPS before EVERY IDR frame fo seeking
// Push SPS before EVERY IDR frame for seeking
if (newExtraData.extraDataExists()) {
oldExtraData = newExtraData;
newExtraData = new H264ExtraData();
......
......@@ -358,9 +358,6 @@
offset += pesHeaderLength;
if (pid === self.stream.programMapTable[STREAM_TYPES.h264]) {
// Stash this frame for future use.
// console.assert(videoFrames.length < 3);
h264Stream.setNextTimeStamp(pts,
dts,
dataAlignmentIndicator);
......
......@@ -293,8 +293,8 @@ var
sortedPlaylists.sort(playlistBandwidth);
// map playlist options by bandwidth and select
// best variant as appropriate
// filter out any variant that has greater effective bitrate
// than the current estimated bandwidth
while (i--) {
variant = sortedPlaylists[i];
......@@ -305,39 +305,36 @@ var
effectiveBitrate = variant.attributes.BANDWIDTH * bandwidthVariance;
// since the playlists are sorted in ascending order by bandwidth, the
// current variant is the best as long as its effective bitrate is
// below the current bandwidth estimate
// NOTE - only set once
if (effectiveBitrate < player.hls.bandwidth) {
bandwidthPlaylists.push(variant);
// since the playlists are sorted in ascending order by
// bandwidth, the first viable variant is the best
if (!bandwidthBestVariant) {
bandwidthBestVariant = variant;
}
}
}
// set index to the available bandwidth mapped renditions
i = bandwidthPlaylists.length;
// sort those by resolution [currently widths]
// sort variants by resolution
bandwidthPlaylists.sort(playlistResolution);
// iterate through bandwidth related playlists and find
// iterate through the bandwidth-filtered playlists and find
// best rendition by player dimension
// Tests
// Seeking - find if you've seeked correctly?
// SelectPlaylist -
while (i--) {
variant = bandwidthPlaylists[i];
// ignored playlists without resolution information
// ignore playlists without resolution information
if (!variant.attributes || !variant.attributes.RESOLUTION ||
!variant.attributes.RESOLUTION.width || !variant.attributes.RESOLUTION.height) {
continue;
}
// since the playlists are sorted, the first variant that has
// dimensions less than or equal to the player size is the
// best
if (variant.attributes.RESOLUTION.width <= player.width() &&
variant.attributes.RESOLUTION.height <= player.height()) {
resolutionBestVariant = variant;
......@@ -526,13 +523,13 @@ var
// transmux the segment data from MP2T to FLV
segmentParser.parseSegmentBinaryData(new Uint8Array(this.response));
segmentParser.flushTags();
// if we're refilling the buffer after a seek, scan through the muxed
// FLV tags until we find the one that is closest to the desired
// playback time
if (offset !== undefined && typeof offset === "number") {
while (segmentParser.getTags()[0].pts < offset) {
// we're seeking past this tag, so ignore it
segmentParser.getNextTag();
}
}
......