<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.multimedia.cx/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ods15</id>
	<title>MultimediaWiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.multimedia.cx/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ods15"/>
	<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php/Special:Contributions/Ods15"/>
	<updated>2026-05-05T08:55:29Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.5</generator>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=FFmpeg_/_Libav_Summer_Of_Code&amp;diff=8762</id>
		<title>FFmpeg / Libav Summer Of Code</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=FFmpeg_/_Libav_Summer_Of_Code&amp;diff=8762"/>
		<updated>2007-10-20T22:24:56Z</updated>

		<summary type="html">&lt;p&gt;Ods15: /* Vorbis Encoder */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The [[FFmpeg]] project has been a participant in the [http://code.google.com/soc/ Google Summer of Code] program during the 2006 and 2007 seaons.&lt;br /&gt;
&lt;br /&gt;
* [[FFmpeg Summer Of Code 2006|2006 project page]]&lt;br /&gt;
* [[FFmpeg Summer Of Code 2007|2007 project page]]&lt;br /&gt;
&lt;br /&gt;
Each accepted project is developed in its own sandbox, separate from the main FFmpeg codebase. Naturally, the end goal of each of the accepted FFmpeg projects ought to be to have that code in shape for acceptance into the production codebase. This page tracks the status of each project.&lt;br /&gt;
&lt;br /&gt;
== 2006 Projects ==&lt;br /&gt;
&lt;br /&gt;
=== VC-1 Decoder ===&lt;br /&gt;
* Student: [[User:Kostya|Kostya Shishkov]]&lt;br /&gt;
* Mentor: [[User:Multimedia Mike|Mike Melanson]]&lt;br /&gt;
* Status: &amp;lt;font color=&amp;quot;#00CC00&amp;quot;&amp;gt;Accepted into the FFmpeg codebase.&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== AMR Decoder ===&lt;br /&gt;
* Student: [[User:superdump|Robert Swain]]&lt;br /&gt;
* Mentor: [[User:Merbanan|Benjamin Larsson]]&lt;br /&gt;
* Status: unfinished but slowly progressing&lt;br /&gt;
&lt;br /&gt;
=== AC3 Decoder ===&lt;br /&gt;
* Student: [[User:Cloud9|Kartikey Mahendra BHATT]]&lt;br /&gt;
* Mentor: [[User:Merbanan|Benjamin Larsson]]&lt;br /&gt;
* Status: Not finished by the student but picked up by Justin Ruggles and &amp;lt;font color=&amp;quot;#00CC00&amp;quot;&amp;gt;committed to FFmpeg&amp;lt;/font&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== AAC Decoder ===&lt;br /&gt;
* Student: Maxim Gavrilov&lt;br /&gt;
* Mentor: [[User:ods15|Oded Shimon]]&lt;br /&gt;
* Status: unfinished, orphaned&lt;br /&gt;
&lt;br /&gt;
=== Vorbis Encoder ===&lt;br /&gt;
* Student: Mathew Philip&lt;br /&gt;
* Mentor: [[User:ods15|Oded Shimon]]&lt;br /&gt;
* Status: Not finished by the student but picked up by [[User:ods15|Oded Shimon]] and &amp;lt;font color=&amp;quot;#00CC00&amp;quot;&amp;gt;committed to FFmpeg&amp;lt;/font&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 2007 Projects ==&lt;br /&gt;
&lt;br /&gt;
=== RealVideo 4 Decoder ===&lt;br /&gt;
* Student: [[User:Kostya|Kostya Shishkov]]&lt;br /&gt;
* Mentor: [[User:Multimedia Mike|Mike Melanson]]&lt;br /&gt;
* Status: Not in FFmpeg codebase yet; project goal has also morphed to include RealVideo 3 decoder since the 2 schemes are so similar.&lt;br /&gt;
&lt;br /&gt;
=== QCELP Decoder ===&lt;br /&gt;
* Student: [[User:Reynaldo|Reynaldo Verdejo Pinochet]]&lt;br /&gt;
* Mentor: [[User:Merbanan|Benjamin Larsson]]&lt;br /&gt;
* Status: slowly progressing, it's working though&lt;br /&gt;
&lt;br /&gt;
=== Matroska Muxer ===&lt;br /&gt;
* Student: David Conrad&lt;br /&gt;
* Mentor: [[User:aurel|Aurélien Jacobs]]&lt;br /&gt;
* Status: &amp;lt;font color=&amp;quot;#00CC00&amp;quot;&amp;gt;Accepted into the FFmpeg codebase.&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Video Filter API ===&lt;br /&gt;
* Student: [[User:Koorogi|Bobby Bingham]]&lt;br /&gt;
* Mentor: [[User:Merbanan|Benjamin Larsson]] and Michael Niedermayer&lt;br /&gt;
* Status: Working code for ffplay, colorspace negotiation is missing though, worked on by Vitor Sessak&lt;br /&gt;
&lt;br /&gt;
=== E-AC3 Decoder ===&lt;br /&gt;
* Student: Bartlomiej Wolowiec&lt;br /&gt;
* Mentor: Justin Ruggles&lt;br /&gt;
* Status:&lt;br /&gt;
&lt;br /&gt;
=== JPEG 2000 Encoder and Decoder ===&lt;br /&gt;
* Student: Kamil Nowosad&lt;br /&gt;
* Mentor: [[User:pengvado|Loren Merritt]]&lt;br /&gt;
* Status: The code is working but all features aren't supported.&lt;br /&gt;
&lt;br /&gt;
=== Dirac Encoder and Decoder ===&lt;br /&gt;
* Student: Marco Gerards&lt;br /&gt;
* Mentor: [[User:Lu_zero|Luca Barbato]]&lt;br /&gt;
* Status:&lt;br /&gt;
&lt;br /&gt;
=== TS Muxer ===&lt;br /&gt;
* Student: Xiaohui Sun&lt;br /&gt;
* Mentor:  [[User:bcoudurier|Baptiste Coudurier]]&lt;br /&gt;
* Status: Changes requested during the review process for FFmpeg inclusion were never made, then the student disappeared.&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=5950</id>
		<title>NUT</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=5950"/>
		<updated>2006-09-12T22:26:34Z</updated>

		<summary type="html">&lt;p&gt;Ods15: /* Bounds of linear search */  fix &amp;lt;nowiki&amp;gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Extensions: nut&lt;br /&gt;
* Website: http://www.nut.hu/&lt;br /&gt;
&lt;br /&gt;
NUT is a container format under construction by [[MPlayer]] and [[FFmpeg]] developers.&lt;br /&gt;
Its main goals are to be simple to parse and easy to implement, flexible regarding the kind of codec supported and error-resistant while maintaining the smallest possible overhead.&lt;br /&gt;
&lt;br /&gt;
== NUT seeking algo in libnut ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Binary search and linear interpolation ===&lt;br /&gt;
&lt;br /&gt;
==== Startup ====&lt;br /&gt;
Go to beginning of file if first syncpoint has not been found, and then go to EOF and search backward to find last syncpoint.&lt;br /&gt;
Pick the closest possible syncpoints for requested pts from syncpoint cache, one higher and one lower. If requested pts is lower than first syncpoint or higher than last syncpoint, then seek to either of those syncpoints and end seek.&lt;br /&gt;
&lt;br /&gt;
Binary search is ended when the entire region between the 2 syncpoints picked has been scanned. Which could even be before it has begun thanks to syncpoint cache.&lt;br /&gt;
&lt;br /&gt;
==== Guess position ====&lt;br /&gt;
Best results have been achieved by combining both linear interpolation and binary search, giving most of the weight to interpolation.&lt;br /&gt;
&lt;br /&gt;
;hi, hi_pd: file position and timestamp of the top edge of the binary search.&lt;br /&gt;
;lo, lo_pd: file position and timestamp of the bottom edge of the binary search.&lt;br /&gt;
;time_pos: Requested pts.&lt;br /&gt;
;guess: beginning of linear search for syncpoint.&lt;br /&gt;
&lt;br /&gt;
 #define INTERPOLATE_WEIGHT (19./20)&lt;br /&gt;
 if (hi - lo &amp;amp;lt; nut-&amp;amp;gt;max_distance*2) guess = lo + 16;&lt;br /&gt;
 else { // linear interpolation&lt;br /&gt;
     double a = (double)(hi - lo) / (hi_pd - lo_pd);&lt;br /&gt;
     guess = lo + a * (time_pos - lo_pd);&lt;br /&gt;
     guess = guess * INTERPOLATE_WEIGHT + (lo+hi)/2 * (1 - INTERPOLATE_WEIGHT);&lt;br /&gt;
     if (hi - guess &amp;amp;lt; nut-&amp;amp;gt;max_distance*2) guess = hi - nut-&amp;amp;gt;max_distance*2; //(lo + hi)/2;&lt;br /&gt;
 }&lt;br /&gt;
 if (guess &amp;amp;lt; lo + 16) guess = lo + 16;&lt;br /&gt;
&lt;br /&gt;
The first conditional prevents too much recursing when the distance is already low. The last conditional prevents an infinite loop of syncpoint search constantly finding ''lo'' and achieving nothing.&lt;br /&gt;
&lt;br /&gt;
==== Binary search ====&lt;br /&gt;
Now, find a syncpoint, bounded between ''guess'' and ''hi''. If it has a timestamp higher than requested pts, then replace ''hi'' and ''hi_pd'', otherwise replace ''lo'' and ''lo_pd''.&lt;br /&gt;
If a syncpoint was not found between ''guess'' and ''hi'', then, if ''guess'' is smaller or equal to ''lo + 16'', then you have scanned the entire area between ''lo'' and ''hi'', and your binary search is done. Otherwise, replace ''hi'' with ''guess'' and repeat the binary search.&lt;br /&gt;
&lt;br /&gt;
After finding the 2 closest syncpoints bounding your requested pts, the bounds of linear are search are:&lt;br /&gt;
&lt;br /&gt;
 *start = lo_s.pos - (lo_s.back_ptr * 16 + 15);&lt;br /&gt;
 *end = hi_s.pos;&lt;br /&gt;
 *stopper = hi_s;&lt;br /&gt;
&lt;br /&gt;
''stopper'' is used later to end linear search prematurely. Note that it is the '''top''' edge of binary search, meaning, it has a timestamp higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Linear search ===&lt;br /&gt;
&lt;br /&gt;
==== Bounds of linear search ====&lt;br /&gt;
Linear search of course ends at ''end'', however, it can end earlier:&lt;br /&gt;
* When you find a frame of any stream, with a dts higher than requested pts.&lt;br /&gt;
* When you find a frame for '''all''' active streams with a pts higher than requested pts.&lt;br /&gt;
* When you find a syncpoint immediately following the syncpoint pointed to by ''stopper'''s back_ptr, (from here on this syncpoint will be called ''stopper_syncpoint'') '''and''' all streams are active.&lt;br /&gt;
* When you reach ''stopper_syncpoint'', and you have not found a keyframe for any '''non'''-active between ''stopper''&amp;lt;nowiki&amp;gt;'&amp;lt;/nowiki&amp;gt;s back_ptr and ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp''. The reason for this is that ''stopper'' did not point because to ''stopper_syncpoint'' can only be because of active stream keyframes, and not non-active ones.&lt;br /&gt;
* When you find a keyframe for all '''non'''-active streams after ''stopper_syncpoint'' with a pts lower than ''stopper.timestamp'', which had a keyframe in the region in the previous condition. The logic is:&lt;br /&gt;
** ''stopper.timestamp'' is higher than requested pts.&lt;br /&gt;
** ''stopper_syncpoint'' is '''not''' the syncpoint pointed to by ''stopper.back_ptr'', but the one immediately following.&lt;br /&gt;
** If there was a keyframe for every non active stream after ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp'', then the reason ''stopper'' does not point to ''stopper_syncpoint'' must be that there are no keyframes for '''active''' streams with a pts lower than ''stopper.timestamp'' after ''stopper_syncpoint''.&lt;br /&gt;
** There might be more keyframes in the region with a pts higher than ''stopper.timestamp'', but those are irrelevant because they are higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
The last 3 conditions can be phrased differently:&lt;br /&gt;
* When saying keyframes, only keyframes with a pts lower than ''stopper.timestamp'' are intended. Any other keyframes are irrelevant.&lt;br /&gt;
* The region ''stopper.back_ptr'' to ''stopper_syncpoint'' has a set of keyframes between it. These keyframes are the ones responsible for ''stopper'' pointing to ''stopper.back_ptr'' and not ''stopper_syncpoint''.&lt;br /&gt;
* If all streams are active, then it's impossible for there to be better keyframes for '''all''' active streams between ''stopper_syncpoint'' to the end of the linear search, because if there was, ''stopper.back_ptr'' would point there.&lt;br /&gt;
* If some streams are inactive, but none of them have a keyframe in the region specified above, then the keyframes responsible for ''stopper'' pointing to ''stopper.back_ptr'' are only from active streams, so again it is impossible there is a better position later in the linear search.&lt;br /&gt;
* If some streams are inactive, and some of them '''do''' have a keyframe in the region specified above, then those keyframes are ''possibly'' responsible for ''stopper'' pointing to ''stopper.back_ptr''. However, if we find more keyframes of those same inactive streams '''after''' the region, then they had nothing to do with ''stopper.back_ptr'', and again the condition is met.&lt;br /&gt;
&lt;br /&gt;
==== Linear search implementation ====&lt;br /&gt;
&lt;br /&gt;
# Start at ''start''.&lt;br /&gt;
# Search for syncpoint. If it is further than ''start + 15'', then the file is errored, and you can start playing immediately from this syncpoint.&lt;br /&gt;
# Perform full demuxing, buffering everything read. If you encounter any NUT error during demuxing, seek back to the syncpoint after ''start'' and end seek.&lt;br /&gt;
# On every syncpoint, flush the buffer and cache the syncpoint position.&lt;br /&gt;
#* If this syncpoint is ''stopper_syncpoint'', then do not flush the buffer, as it would be possible the linear search would end immediatelty afterwards and a second underlying seek would not be necessary.&lt;br /&gt;
# When finding keyframe of active stream with pts lower than requested pts, store position of keyframe. Discard previous value.&lt;br /&gt;
# End linear search as necessary by bounds given above.&lt;br /&gt;
# Pick the lowest value from positions of keyframes for active streams. This is the final position.&lt;br /&gt;
# Seek to closest syncpoint before the final position, preform a minimal demuxing until final position (to get proper last_pts context across all streams).&lt;br /&gt;
#* With luck this seek will not need an underlying seek, if you have not flushed the buffer since the requested position.&lt;br /&gt;
#* In most common case, ''stopper.back_ptr'' points to same syncpoint as the start of the linear search, as both syncpoints point to the same rare video keyframe.&lt;br /&gt;
#* If only video stream is active and the only non active stream is audio, you will most likely end your linear search immediately after ''stopper_syncpoint'' by finding an audio keyframe. Afterwards you will rewind right back to ''start'', and, since buffer hasn't been flushed, this will not need an underlying seek.&lt;br /&gt;
&lt;br /&gt;
=== Index ===&lt;br /&gt;
With index, binary search step is skipped, and a much more limited linear search used, between two immediate syncpoints. The syncpoint picked is the highest possible one that has a keyframe for each active stream past the syncpoint with a pts lower than requested pts. The end of the linear search is the syncpoint immediately following.&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Index ===&lt;br /&gt;
Create the index in the same manner as creating the index in the muxer, remembering keyframes and EOR at syncpoint positions.&lt;br /&gt;
With one big difference - dynamic index can have gaps, thanks to seeking. Every syncpiont entry in the dynamic index has a flag indicating if it has a &amp;amp;quot;unresearched region&amp;amp;quot; gap from last syncpoint.&lt;br /&gt;
&lt;br /&gt;
In seeking, dynamic index is used in the same manner as complete index. However, when deciding a syncpoint, the entire range of the syncpoint picked until the first syncpoint with a pts higher than requested is checked for having been already researched. If a &amp;amp;quot;hole&amp;amp;quot; is found anywhere in this range, dynamic index is disregarded and full binary search is performed.&lt;br /&gt;
&lt;br /&gt;
=== End of Relevance (EOR) ===&lt;br /&gt;
Behavior with linear search:&lt;br /&gt;
* Treat EOR frames same as keyframes. Seeing an EOR frame for an active stream causes the stream to be ignored until the next keyframe of same stream.&lt;br /&gt;
* If all active streams are EOR by end of linear search, just use start of linear search as final seeking position.&lt;br /&gt;
&lt;br /&gt;
For index:&lt;br /&gt;
* When picking the correct syncpoint to start linear search, ignore streams which have EOR with pts lower than requested pts and no keyframe with pts lower than requested pts.&lt;br /&gt;
* If all active streams are EOR, pick the syncpoint immediately before the syncpoint with the last EOR across all streams with pts lower than requested pts.&lt;br /&gt;
&lt;br /&gt;
[[Category:Container Formats]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=User_talk:Ods15&amp;diff=3796</id>
		<title>User talk:Ods15</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=User_talk:Ods15&amp;diff=3796"/>
		<updated>2006-04-01T06:34:27Z</updated>

		<summary type="html">&lt;p&gt;Ods15: reply to diego&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Oded, you have removed a little more than just spam from the [[NUT]] page... -- [[User:DonDiego|DonDiego]] 11:05, 29 March 2006 (EST)&lt;br /&gt;
:Heh, I forgot you don't accept my mails, I sent you this e-mail:&lt;br /&gt;
 Uhh... no I didn't&lt;br /&gt;
 Look carefully, I removed multiple data. (Am I missing something here or are you?&lt;br /&gt;
 Look exactly at the data that I removed and what is left)&lt;br /&gt;
:-- [[User:Ods15|ods15]] 01:34, 1 April 2006 (EST)&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=3687</id>
		<title>NUT</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=3687"/>
		<updated>2006-03-27T08:08:15Z</updated>

		<summary type="html">&lt;p&gt;Ods15: Revert spam&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Extensions: nut&lt;br /&gt;
* Website: http://www.nut.hu/&lt;br /&gt;
&lt;br /&gt;
NUT is a container format under construction by [[MPlayer]] and [[FFmpeg]] developers.&lt;br /&gt;
Its main goals are to be simple, flexible and error-resistant while maintaining the smallest possible overhead.&lt;br /&gt;
&lt;br /&gt;
== NUT seeking algo in libnut ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Binary search and linear interpolation ===&lt;br /&gt;
&lt;br /&gt;
==== Startup ====&lt;br /&gt;
Go to beginning of file if first syncpoint has not been found, and then go to EOF and search backward to find last syncpoint.&lt;br /&gt;
Pick the closest possible syncpoints for requested pts from syncpoint cache, one higher and one lower. If requested pts is lower than first syncpoint or higher than last syncpoint, then seek to either of those syncpoints and end seek.&lt;br /&gt;
&lt;br /&gt;
Binary search is ended when the entire region between the 2 syncpoints picked has been scanned. Which could even be before it has begun thanks to syncpoint cache.&lt;br /&gt;
&lt;br /&gt;
==== Guess position ====&lt;br /&gt;
Best results have been achieved by combining both linear interpolation and binary search, giving most of the weight to interpolation.&lt;br /&gt;
&lt;br /&gt;
;hi, hi_pd: file position and timestamp of the top edge of the binary search.&lt;br /&gt;
;lo, lo_pd: file position and timestamp of the bottom edge of the binary search.&lt;br /&gt;
;time_pos: Requested pts.&lt;br /&gt;
;guess: beginning of linear search for syncpoint.&lt;br /&gt;
&lt;br /&gt;
 #define INTERPOLATE_WEIGHT (19./20)&lt;br /&gt;
 if (hi - lo &amp;amp;lt; nut-&amp;amp;gt;max_distance*2) guess = lo + 16;&lt;br /&gt;
 else { // linear interpolation&lt;br /&gt;
     double a = (double)(hi - lo) / (hi_pd - lo_pd);&lt;br /&gt;
     guess = lo + a * (time_pos - lo_pd);&lt;br /&gt;
     guess = guess * INTERPOLATE_WEIGHT + (lo+hi)/2 * (1 - INTERPOLATE_WEIGHT);&lt;br /&gt;
     if (hi - guess &amp;amp;lt; nut-&amp;amp;gt;max_distance*2) guess = hi - nut-&amp;amp;gt;max_distance*2; //(lo + hi)/2;&lt;br /&gt;
 }&lt;br /&gt;
 if (guess &amp;amp;lt; lo + 16) guess = lo + 16;&lt;br /&gt;
&lt;br /&gt;
The first conditional prevents too much recursing when the distance is already low. The last conditional prevents an infinite loop of syncpoint search constantly finding ''lo'' and achieving nothing.&lt;br /&gt;
&lt;br /&gt;
==== Binary search ====&lt;br /&gt;
Now, find a syncpoint, bounded between ''guess'' and ''hi''. If it has a timestamp higher than requested pts, then replace ''hi'' and ''hi_pd'', otherwise replace ''lo'' and ''lo_pd''.&lt;br /&gt;
If a syncpoint was not found between ''guess'' and ''hi'', then, if ''guess'' is smaller or equal to ''lo + 16'', then you have scanned the entire area between ''lo'' and ''hi'', and your binary search is done. Otherwise, replace ''hi'' with ''guess'' and repeat the binary search.&lt;br /&gt;
&lt;br /&gt;
After finding the 2 closest syncpoints bounding your requested pts, the bounds of linear are search are:&lt;br /&gt;
&lt;br /&gt;
 *start = lo_s.pos - (lo_s.back_ptr * 16 + 15);&lt;br /&gt;
 *end = hi_s.pos;&lt;br /&gt;
 *stopper = hi_s;&lt;br /&gt;
&lt;br /&gt;
''stopper'' is used later to end linear search prematurely. Note that it is the '''top''' edge of binary search, meaning, it has a timestamp higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Linear search ===&lt;br /&gt;
&lt;br /&gt;
==== Bounds of linear search ====&lt;br /&gt;
Linear search of course ends at ''end'', however, it can end earlier:&lt;br /&gt;
* When you find a frame of any stream, with a dts higher than requested pts.&lt;br /&gt;
* When you find a frame for '''all''' active streams with a pts higher than requested pts.&lt;br /&gt;
* When you find a syncpoint immediately following the syncpoint pointed to by ''stopper'''s back_ptr, (from here on this syncpoint will be called ''stopper_syncpoint'') '''and''' all streams are active.&lt;br /&gt;
* When you reach ''stopper_syncpoint'', and you have not found a keyframe for any '''non'''-active between ''stopper''&amp;amp;lt;nowiki&amp;amp;gt;'&amp;amp;lt;/nowiki&amp;amp;gt;s back_ptr and ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp''. The reason for this is that ''stopper'' did not point because to ''stopper_syncpoint'' can only be because of active stream keyframes, and not non-active ones.&lt;br /&gt;
* When you find a keyframe for all '''non'''-active streams after ''stopper_syncpoint'' with a pts lower than ''stopper.timestamp'', which had a keyframe in the region in the previous condition. The logic is:&lt;br /&gt;
** ''stopper.timestamp'' is higher than requested pts.&lt;br /&gt;
** ''stopper_syncpoint'' is '''not''' the syncpoint pointed to by ''stopper.back_ptr'', but the one immediately following.&lt;br /&gt;
** If there was a keyframe for every non active stream after ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp'', then the reason ''stopper'' does not point to ''stopper_syncpoint'' must be that there are no keyframes for '''active''' streams with a pts lower than ''stopper.timestamp'' after ''stopper_syncpoint''.&lt;br /&gt;
** There might be more keyframes in the region with a pts higher than ''stopper.timestamp'', but those are irrelevant because they are higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
The last 3 conditions can be phrased differently:&lt;br /&gt;
* When saying keyframes, only keyframes with a pts lower than ''stopper.timestamp'' are intended. Any other keyframes are irrelevant.&lt;br /&gt;
* The region ''stopper.back_ptr'' to ''stopper_syncpoint'' has a set of keyframes between it. These keyframes are the ones responsible for ''stopper'' pointing to ''stopper.back_ptr'' and not ''stopper_syncpoint''.&lt;br /&gt;
* If all streams are active, then it's impossible for there to be better keyframes for '''all''' active streams between ''stopper_syncpoint'' to the end of the linear search, because if there was, ''stopper.back_ptr'' would point there.&lt;br /&gt;
* If some streams are inactive, but none of them have a keyframe in the region specified above, then the keyframes responsible for ''stopper'' pointing to ''stopper.back_ptr'' are only from active streams, so again it is impossible there is a better position later in the linear search.&lt;br /&gt;
* If some streams are inactive, and some of them '''do''' have a keyframe in the region specified above, then those keyframes are ''possibly'' responsible for ''stopper'' pointing to ''stopper.back_ptr''. However, if we find more keyframes of those same inactive streams '''after''' the region, then they had nothing to do with ''stopper.back_ptr'', and again the condition is met.&lt;br /&gt;
&lt;br /&gt;
==== Linear search implementation ====&lt;br /&gt;
&lt;br /&gt;
# Start at ''start''.&lt;br /&gt;
# Search for syncpoint. If it is further than ''start + 15'', then the file is errored, and you can start playing immediately from this syncpoint.&lt;br /&gt;
# Perform full demuxing, buffering everything read. If you encounter any NUT error during demuxing, seek back to the syncpoint after ''start'' and end seek.&lt;br /&gt;
# On every syncpoint, flush the buffer and cache the syncpoint position.&lt;br /&gt;
#* If this syncpoint is ''stopper_syncpoint'', then do not flush the buffer, as it would be possible the linear search would end immediatelty afterwards and a second underlying seek would not be necessary.&lt;br /&gt;
# When finding keyframe of active stream with pts lower than requested pts, store position of keyframe. Discard previous value.&lt;br /&gt;
# End linear search as necessary by bounds given above.&lt;br /&gt;
# Pick the lowest value from positions of keyframes for active streams. This is the final position.&lt;br /&gt;
# Seek to closest syncpoint before the final position, preform a minimal demuxing until final position (to get proper last_pts context across all streams).&lt;br /&gt;
#* With luck this seek will not need an underlying seek, if you have not flushed the buffer since the requested position.&lt;br /&gt;
#* In most common case, ''stopper.back_ptr'' points to same syncpoint as the start of the linear search, as both syncpoints point to the same rare video keyframe.&lt;br /&gt;
#* If only video stream is active and the only non active stream is audio, you will most likely end your linear search immediately after ''stopper_syncpoint'' by finding an audio keyframe. Afterwards you will rewind right back to ''start'', and, since buffer hasn't been flushed, this will not need an underlying seek.&lt;br /&gt;
&lt;br /&gt;
=== Index ===&lt;br /&gt;
With index, binary search step is skipped, and a much more limited linear search used, between two immediate syncpoints. The syncpoint picked is the highest possible one that has a keyframe for each active stream past the syncpoint with a pts lower than requested pts. The end of the linear search is the syncpoint immediately following.&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Index ===&lt;br /&gt;
Create the index in the same manner as creating the index in the muxer, remembering keyframes and EOR at syncpoint positions.&lt;br /&gt;
With one big difference - dynamic index can have gaps, thanks to seeking. Every syncpiont entry in the dynamic index has a flag indicating if it has a &amp;amp;quot;unresearched region&amp;amp;quot; gap from last syncpoint.&lt;br /&gt;
&lt;br /&gt;
In seeking, dynamic index is used in the same manner as complete index. However, when deciding a syncpoint, the entire range of the syncpoint picked until the first syncpoint with a pts higher than requested is checked for having been already researched. If a &amp;amp;quot;hole&amp;amp;quot; is found anywhere in this range, dynamic index is disregarded and full binary search is performed.&lt;br /&gt;
&lt;br /&gt;
=== End of Relevance (EOR) ===&lt;br /&gt;
Behavior with linear search:&lt;br /&gt;
* Treat EOR frames same as keyframes. Seeing an EOR frame for an active stream causes the stream to be ignored until the next keyframe of same stream.&lt;br /&gt;
* If all active streams are EOR by end of linear search, just use start of linear search as final seeking position.&lt;br /&gt;
&lt;br /&gt;
For index:&lt;br /&gt;
* When picking the correct syncpoint to start linear search, ignore streams which have EOR with pts lower than requested pts and no keyframe with pts lower than requested pts.&lt;br /&gt;
* If all active streams are EOR, pick the syncpoint immediately before the syncpoint with the last EOR across all streams with pts lower than requested pts.&lt;br /&gt;
&lt;br /&gt;
[[Category:Container Formats]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=Understanding_AAC&amp;diff=2880</id>
		<title>Understanding AAC</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=Understanding_AAC&amp;diff=2880"/>
		<updated>2006-03-16T19:00:40Z</updated>

		<summary type="html">&lt;p&gt;Ods15: /* Overview */  Explain bitpacking&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This portion of the MultimediaWiki tracks an effort to get an open, freely-distributable, usable, and clear specification for the Advanced Audio Coding (AAC) format. The goal is to understand enough details about the format to create new decoder implementations that can handle production bitstreams starting with data packaged inside MPEG-4 files.&lt;br /&gt;
&lt;br /&gt;
The homepage for libfaad has a Wiki that provides some decent details regarding the background coding concepts:&lt;br /&gt;
[http://www.audiocoding.com/modules/wiki/?page=AAC http://www.audiocoding.com/modules/wiki/?page=AAC]&lt;br /&gt;
&lt;br /&gt;
More possible details here: [http://www.ietf.org/proceedings/99nov/I-D/draft-ietf-avt-rtp-mpeg2aac-00.txt http://www.ietf.org/proceedings/99nov/I-D/draft-ietf-avt-rtp-mpeg2aac-00.txt] or [http://tools.ietf.org/wg/avt/draft-ietf-avt-rtp-mpeg2aac/ http://tools.ietf.org/wg/avt/draft-ietf-avt-rtp-mpeg2aac/]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
AAC is a perceptual audio codec which means that it throws away certain information during the compression process, information that has been deemed less important.&lt;br /&gt;
&lt;br /&gt;
Surface details of the format can be found at Wikipedia: [http://en.wikipedia.org/wiki/Advanced_Audio_Coding http://en.wikipedia.org/wiki/Advanced_Audio_Coding]&lt;br /&gt;
&lt;br /&gt;
Conformance vectors can be obtained here: [ftp://mpaudconf:adif2mp4@ftp.iis.fhg.de/ ftp://mpaudconf:adif2mp4@ftp.iis.fhg.de/]&lt;br /&gt;
&lt;br /&gt;
AAC is a variable bitrate (VBR) block-based codec where each block decodes to 1024 time-domain samples. Allegedly, each frame stands alone and does not depend on previous frames (whereas many perceptual audio codecs overlap data with the previous frame).&lt;br /&gt;
&lt;br /&gt;
AAC includes a variety of profiles:&lt;br /&gt;
* low complexity (LC): reported to be the simplest (Apple iTunes files)&lt;br /&gt;
* main (MAIN): LC profile with backwards prediction&lt;br /&gt;
* sample-rate scalability (SRS): submitted by Sony and reportedly similar to ATRAC/3&lt;br /&gt;
* long term prediction (LTP): main profile with forward prediction&lt;br /&gt;
* high efficiency (HE, HE-AAC, aacPlus): uses spectral band replication (SBR) and may use parametric stereo&lt;br /&gt;
* FAAD refers to another profile named LD, possibly the same as SRS&lt;br /&gt;
* provisions all over the libfaad source for error recovery (ER)&lt;br /&gt;
== Bitpacking ==&lt;br /&gt;
Done in most significant byte first, most significant bit first. Example:&lt;br /&gt;
 5 bits: 2 (00010)&lt;br /&gt;
 4 bits: 4 (0100)&lt;br /&gt;
 4 bits: 2 (0010)&lt;br /&gt;
 3 bits: 0 (000)&lt;br /&gt;
 &lt;br /&gt;
 Byte 1: 00010010&lt;br /&gt;
 Byte 2: 00010000&lt;br /&gt;
 &lt;br /&gt;
 00010010 00010000&lt;br /&gt;
 [ 2 ][ 4 ][2 ][0]&lt;br /&gt;
&lt;br /&gt;
== Packaging/Encapsulation And Setup Data==&lt;br /&gt;
There is a variety of methods for packaging AAC data from transport. 2 methods used in packaging raw streams are to use ADTS and ADIF headers. The libfaad knowledge base also makes reference to LATM and LOAS packaging.&lt;br /&gt;
&lt;br /&gt;
Much AAC data is encapsulated in MPEG-4 files which is an extension of the [[Apple QuickTime]] container format. the MPEG-4 file will have an audio 'trak' atom which will contain a 'stsd' description atom which will contain an 'mp4a' atom which will contain an 'esds' atom. Part of the esds  atom contains the setup data for associated AAC stream. '''(TODO: need to document the precise format and method for obtaining the setup data.)''' This setup data is generally 2 bytes. This setup data has the following layout:&lt;br /&gt;
 5 bits: object type&lt;br /&gt;
 4 bits: frequency index&lt;br /&gt;
 if (frequency index == 15)&lt;br /&gt;
     24 bits: frequency&lt;br /&gt;
 4 bits: channel configuration&lt;br /&gt;
 1 bit: frame length flag&lt;br /&gt;
 1 bit: dependsOnCoreCoder&lt;br /&gt;
 1 bit: extensionFlag&lt;br /&gt;
These are the possible object types:&lt;br /&gt;
* 0: NULL&lt;br /&gt;
* 1: AAC Main&lt;br /&gt;
* 2: AAC Low complexity&lt;br /&gt;
* 3: AAC SSR&lt;br /&gt;
* 4: AAC Long term prediction&lt;br /&gt;
* 5: AAC High efficiency&lt;br /&gt;
* 6: Scalable&lt;br /&gt;
* 7: [[TwinVQ]]&lt;br /&gt;
* 8: CELP&lt;br /&gt;
* 9: HVXC&lt;br /&gt;
* 10: Reserved&lt;br /&gt;
* 11: Reserved&lt;br /&gt;
* 12: TTSI&lt;br /&gt;
* 13: Main synthetic&lt;br /&gt;
* 14: Wavetable synthesis&lt;br /&gt;
* 15: General MIDI&lt;br /&gt;
* 16: Algorithmic Synthesis and Audio FX&lt;br /&gt;
* 17: AAC Low complexity with error recovery&lt;br /&gt;
* 18: Reserved&lt;br /&gt;
* 19: AAC Long term prediction with error recovery&lt;br /&gt;
* 20: AAC scalable with error recovery&lt;br /&gt;
* 21: TwinVQ with error recovery&lt;br /&gt;
* 22: BSAC with error recovery&lt;br /&gt;
* 23: AAC LD with error recovery&lt;br /&gt;
* 24: CELP with error recovery&lt;br /&gt;
* 25: HXVC with error recovery&lt;br /&gt;
* 26: HILN with error recovery&lt;br /&gt;
* 27: Parametric with error recovery&lt;br /&gt;
* 28: Reserved&lt;br /&gt;
* 29: Reserved&lt;br /&gt;
* 30: Reserved&lt;br /&gt;
* 31: Reserved&lt;br /&gt;
There are 13 supported frequencies (frequency indices 13..14 are invalid):&lt;br /&gt;
* 0: 96000 Hz&lt;br /&gt;
* 1: 88200 Hz&lt;br /&gt;
* 2: 64000 Hz&lt;br /&gt;
* 3: 48000 Hz&lt;br /&gt;
* 4: 44100 Hz&lt;br /&gt;
* 5: 32000 Hz&lt;br /&gt;
* 6: 24000 Hz&lt;br /&gt;
* 7: 22050 Hz&lt;br /&gt;
* 8: 16000 Hz&lt;br /&gt;
* 9: 12000 Hz&lt;br /&gt;
* 10: 11025 Hz&lt;br /&gt;
* 11: 8000 Hz&lt;br /&gt;
* 12: 7350 Hz&lt;br /&gt;
* 15: frequency is written explictly&lt;br /&gt;
These are the channel configurations:&lt;br /&gt;
* 0: custom configuration '''(TODO)'''&lt;br /&gt;
* 1: 1 channel: front-center&lt;br /&gt;
* 2: 2 channels: front-left, front-right&lt;br /&gt;
* 3: 3 channels: front-center, front-left, front-right&lt;br /&gt;
* 4: 4 channels: front-center, front-left, front-right, back-center&lt;br /&gt;
* 5: 5 channels: front-center, front-left, front-right, back-left, back-right&lt;br /&gt;
* 6: 6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel&lt;br /&gt;
* 7: 8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-channel&lt;br /&gt;
frame length flag:&lt;br /&gt;
* 0: Each packet contains 1024 samples&lt;br /&gt;
* 1: Each packet contains 960 samples&lt;br /&gt;
&lt;br /&gt;
== Frames And Syntax Elements ==&lt;br /&gt;
In an MPEG-4 file, the AAC data is broken up into a series of variable length frames. &lt;br /&gt;
&lt;br /&gt;
An AAC frame is comprised of blocks called syntax elements. Read the first 3 bits from the frame's bitstream to find the first element type. Decode the element. Proceed to read the first 3 bits of the next element and repeat the decoding process until the frame is depleted.&lt;br /&gt;
&lt;br /&gt;
There are 8 different syntax elements:&lt;br /&gt;
* 0 SCE  single channel element (codes a single audio channel)&lt;br /&gt;
* 1 CPE  channel pair element (codes stereo signal)&lt;br /&gt;
* 2 CCE  something to do with channel coupling, not implemented in libfaad2&lt;br /&gt;
* 3 LFE  low-frequency effects? referenced as &amp;quot;special effects&amp;quot; in RTP doc&lt;br /&gt;
* 4 DSE  data stream element (user data)&lt;br /&gt;
* 5 PCE  program configuration element (describe bitstream)&lt;br /&gt;
* 6 FIL  fill element (pad space/extension data)&lt;br /&gt;
* 7 END  marks the end of the frame&lt;br /&gt;
This is an example layout for a 5.1 audio stream:&lt;br /&gt;
 SCE CPE CPE LFE END&lt;br /&gt;
indicates &lt;br /&gt;
 center - left/right - surround left/right - lfe - end &lt;br /&gt;
An ID within the respective CPE blocks indicates its channel assignments (front vs. surround).&lt;br /&gt;
&lt;br /&gt;
== Decoding Process ==&lt;br /&gt;
First, let's list a few basic terms that FAAD2 uses throughout its decoding process:&lt;br /&gt;
&lt;br /&gt;
* ics = individual channel stream, the basic audio unit that FAAD2 is concerned with&lt;br /&gt;
* ms = any parameter with this in its name deals with mid/side coding&lt;br /&gt;
* sfb = probably something to do with scale factors&lt;br /&gt;
* swb = scalefactor window band&lt;br /&gt;
* is = intensity stereo&lt;br /&gt;
&lt;br /&gt;
As mentioned above, the ics is an important data structure in AAC decoding. These are its fields, according to FAAD2:&lt;br /&gt;
&lt;br /&gt;
  max_sfb&lt;br /&gt;
  num_swb&lt;br /&gt;
  num_window_groups&lt;br /&gt;
  num_windows&lt;br /&gt;
  window_sequence&lt;br /&gt;
  window_group_length[8]&lt;br /&gt;
  window_shape&lt;br /&gt;
  scale_factor_grouping&lt;br /&gt;
  section_sfb_offset[8][8*15]&lt;br /&gt;
  swb_offset&lt;br /&gt;
  section_codebook[8][15*8]&lt;br /&gt;
  section_start[8][15*8]&lt;br /&gt;
  section_end[8][15*8]&lt;br /&gt;
  sfb_codebook[8][15*8]&lt;br /&gt;
  number_sections[8]  ''// number of sections in a group''&lt;br /&gt;
  global_gain&lt;br /&gt;
  scale_factors[8][51]  ''// FAAD2 comment: [0..255]?''&lt;br /&gt;
  ms_mask_present&lt;br /&gt;
  ms_used[MAX_WINDOW_GROUPS][MAX_SFB]  ''// dimensions = [8][51]''&lt;br /&gt;
  noise_used&lt;br /&gt;
  pulse_data_present&lt;br /&gt;
  tns_data_present&lt;br /&gt;
  gain_control_data_present&lt;br /&gt;
  predictor_data_present&lt;br /&gt;
  pulse_info pulse&lt;br /&gt;
  tns_info tns&lt;br /&gt;
  ''data structures for main profile, document later''&lt;br /&gt;
  ''data structures for LTP, document later''&lt;br /&gt;
  ''data structures for SSR, document later''&lt;br /&gt;
  ''data structures for error resilience, document later''&lt;br /&gt;
&lt;br /&gt;
These pages detail the process for decoding the various syntax elements:&lt;br /&gt;
&lt;br /&gt;
* [[Decoding AAC SCE and LFE]]&lt;br /&gt;
* [[Decoding AAC CPE]]&lt;br /&gt;
** [[Reconstructing AAC CPE]]&lt;br /&gt;
* Decoding AAC CCE&lt;br /&gt;
* Decoding AAC DSE&lt;br /&gt;
* Decoding AAC PCE&lt;br /&gt;
* [[Decoding AAC FIL]]&lt;br /&gt;
* [[Decoding AAC END]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=Understanding_AAC&amp;diff=2879</id>
		<title>Understanding AAC</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=Understanding_AAC&amp;diff=2879"/>
		<updated>2006-03-16T18:56:20Z</updated>

		<summary type="html">&lt;p&gt;Ods15: /* Packaging/Encapsulation And Setup Data */  Corrections, updates&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This portion of the MultimediaWiki tracks an effort to get an open, freely-distributable, usable, and clear specification for the Advanced Audio Coding (AAC) format. The goal is to understand enough details about the format to create new decoder implementations that can handle production bitstreams starting with data packaged inside MPEG-4 files.&lt;br /&gt;
&lt;br /&gt;
The homepage for libfaad has a Wiki that provides some decent details regarding the background coding concepts:&lt;br /&gt;
[http://www.audiocoding.com/modules/wiki/?page=AAC http://www.audiocoding.com/modules/wiki/?page=AAC]&lt;br /&gt;
&lt;br /&gt;
More possible details here: [http://www.ietf.org/proceedings/99nov/I-D/draft-ietf-avt-rtp-mpeg2aac-00.txt http://www.ietf.org/proceedings/99nov/I-D/draft-ietf-avt-rtp-mpeg2aac-00.txt] or [http://tools.ietf.org/wg/avt/draft-ietf-avt-rtp-mpeg2aac/ http://tools.ietf.org/wg/avt/draft-ietf-avt-rtp-mpeg2aac/]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
AAC is a perceptual audio codec which means that it throws away certain information during the compression process, information that has been deemed less important.&lt;br /&gt;
&lt;br /&gt;
Surface details of the format can be found at Wikipedia: [http://en.wikipedia.org/wiki/Advanced_Audio_Coding http://en.wikipedia.org/wiki/Advanced_Audio_Coding]&lt;br /&gt;
&lt;br /&gt;
Conformance vectors can be obtained here: [ftp://mpaudconf:adif2mp4@ftp.iis.fhg.de/ ftp://mpaudconf:adif2mp4@ftp.iis.fhg.de/]&lt;br /&gt;
&lt;br /&gt;
AAC is a variable bitrate (VBR) block-based codec where each block decodes to 1024 time-domain samples. Allegedly, each frame stands alone and does not depend on previous frames (whereas many perceptual audio codecs overlap data with the previous frame).&lt;br /&gt;
&lt;br /&gt;
AAC includes a variety of profiles:&lt;br /&gt;
* low complexity (LC): reported to be the simplest (Apple iTunes files)&lt;br /&gt;
* main (MAIN): LC profile with backwards prediction&lt;br /&gt;
* sample-rate scalability (SRS): submitted by Sony and reportedly similar to ATRAC/3&lt;br /&gt;
* long term prediction (LTP): main profile with forward prediction&lt;br /&gt;
* high efficiency (HE, HE-AAC, aacPlus): uses spectral band replication (SBR) and may use parametric stereo&lt;br /&gt;
* FAAD refers to another profile named LD, possibly the same as SRS&lt;br /&gt;
* provisions all over the libfaad source for error recovery (ER)&lt;br /&gt;
&lt;br /&gt;
== Packaging/Encapsulation And Setup Data==&lt;br /&gt;
There is a variety of methods for packaging AAC data from transport. 2 methods used in packaging raw streams are to use ADTS and ADIF headers. The libfaad knowledge base also makes reference to LATM and LOAS packaging.&lt;br /&gt;
&lt;br /&gt;
Much AAC data is encapsulated in MPEG-4 files which is an extension of the [[Apple QuickTime]] container format. the MPEG-4 file will have an audio 'trak' atom which will contain a 'stsd' description atom which will contain an 'mp4a' atom which will contain an 'esds' atom. Part of the esds  atom contains the setup data for associated AAC stream. '''(TODO: need to document the precise format and method for obtaining the setup data.)''' This setup data is generally 2 bytes. This setup data has the following layout:&lt;br /&gt;
 5 bits: object type&lt;br /&gt;
 4 bits: frequency index&lt;br /&gt;
 if (frequency index == 15)&lt;br /&gt;
     24 bits: frequency&lt;br /&gt;
 4 bits: channel configuration&lt;br /&gt;
 1 bit: frame length flag&lt;br /&gt;
 1 bit: dependsOnCoreCoder&lt;br /&gt;
 1 bit: extensionFlag&lt;br /&gt;
These are the possible object types:&lt;br /&gt;
* 0: NULL&lt;br /&gt;
* 1: AAC Main&lt;br /&gt;
* 2: AAC Low complexity&lt;br /&gt;
* 3: AAC SSR&lt;br /&gt;
* 4: AAC Long term prediction&lt;br /&gt;
* 5: AAC High efficiency&lt;br /&gt;
* 6: Scalable&lt;br /&gt;
* 7: [[TwinVQ]]&lt;br /&gt;
* 8: CELP&lt;br /&gt;
* 9: HVXC&lt;br /&gt;
* 10: Reserved&lt;br /&gt;
* 11: Reserved&lt;br /&gt;
* 12: TTSI&lt;br /&gt;
* 13: Main synthetic&lt;br /&gt;
* 14: Wavetable synthesis&lt;br /&gt;
* 15: General MIDI&lt;br /&gt;
* 16: Algorithmic Synthesis and Audio FX&lt;br /&gt;
* 17: AAC Low complexity with error recovery&lt;br /&gt;
* 18: Reserved&lt;br /&gt;
* 19: AAC Long term prediction with error recovery&lt;br /&gt;
* 20: AAC scalable with error recovery&lt;br /&gt;
* 21: TwinVQ with error recovery&lt;br /&gt;
* 22: BSAC with error recovery&lt;br /&gt;
* 23: AAC LD with error recovery&lt;br /&gt;
* 24: CELP with error recovery&lt;br /&gt;
* 25: HXVC with error recovery&lt;br /&gt;
* 26: HILN with error recovery&lt;br /&gt;
* 27: Parametric with error recovery&lt;br /&gt;
* 28: Reserved&lt;br /&gt;
* 29: Reserved&lt;br /&gt;
* 30: Reserved&lt;br /&gt;
* 31: Reserved&lt;br /&gt;
There are 13 supported frequencies (frequency indices 13..14 are invalid):&lt;br /&gt;
* 0: 96000 Hz&lt;br /&gt;
* 1: 88200 Hz&lt;br /&gt;
* 2: 64000 Hz&lt;br /&gt;
* 3: 48000 Hz&lt;br /&gt;
* 4: 44100 Hz&lt;br /&gt;
* 5: 32000 Hz&lt;br /&gt;
* 6: 24000 Hz&lt;br /&gt;
* 7: 22050 Hz&lt;br /&gt;
* 8: 16000 Hz&lt;br /&gt;
* 9: 12000 Hz&lt;br /&gt;
* 10: 11025 Hz&lt;br /&gt;
* 11: 8000 Hz&lt;br /&gt;
* 12: 7350 Hz&lt;br /&gt;
* 15: frequency is written explictly&lt;br /&gt;
These are the channel configurations:&lt;br /&gt;
* 0: custom configuration '''(TODO)'''&lt;br /&gt;
* 1: 1 channel: front-center&lt;br /&gt;
* 2: 2 channels: front-left, front-right&lt;br /&gt;
* 3: 3 channels: front-center, front-left, front-right&lt;br /&gt;
* 4: 4 channels: front-center, front-left, front-right, back-center&lt;br /&gt;
* 5: 5 channels: front-center, front-left, front-right, back-left, back-right&lt;br /&gt;
* 6: 6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel&lt;br /&gt;
* 7: 8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-channel&lt;br /&gt;
frame length flag:&lt;br /&gt;
* 0: Each packet contains 1024 samples&lt;br /&gt;
* 1: Each packet contains 960 samples&lt;br /&gt;
&lt;br /&gt;
== Frames And Syntax Elements ==&lt;br /&gt;
In an MPEG-4 file, the AAC data is broken up into a series of variable length frames. &lt;br /&gt;
&lt;br /&gt;
An AAC frame is comprised of blocks called syntax elements. Read the first 3 bits from the frame's bitstream to find the first element type. Decode the element. Proceed to read the first 3 bits of the next element and repeat the decoding process until the frame is depleted.&lt;br /&gt;
&lt;br /&gt;
There are 8 different syntax elements:&lt;br /&gt;
* 0 SCE  single channel element (codes a single audio channel)&lt;br /&gt;
* 1 CPE  channel pair element (codes stereo signal)&lt;br /&gt;
* 2 CCE  something to do with channel coupling, not implemented in libfaad2&lt;br /&gt;
* 3 LFE  low-frequency effects? referenced as &amp;quot;special effects&amp;quot; in RTP doc&lt;br /&gt;
* 4 DSE  data stream element (user data)&lt;br /&gt;
* 5 PCE  program configuration element (describe bitstream)&lt;br /&gt;
* 6 FIL  fill element (pad space/extension data)&lt;br /&gt;
* 7 END  marks the end of the frame&lt;br /&gt;
This is an example layout for a 5.1 audio stream:&lt;br /&gt;
 SCE CPE CPE LFE END&lt;br /&gt;
indicates &lt;br /&gt;
 center - left/right - surround left/right - lfe - end &lt;br /&gt;
An ID within the respective CPE blocks indicates its channel assignments (front vs. surround).&lt;br /&gt;
&lt;br /&gt;
== Decoding Process ==&lt;br /&gt;
First, let's list a few basic terms that FAAD2 uses throughout its decoding process:&lt;br /&gt;
&lt;br /&gt;
* ics = individual channel stream, the basic audio unit that FAAD2 is concerned with&lt;br /&gt;
* ms = any parameter with this in its name deals with mid/side coding&lt;br /&gt;
* sfb = probably something to do with scale factors&lt;br /&gt;
* swb = scalefactor window band&lt;br /&gt;
* is = intensity stereo&lt;br /&gt;
&lt;br /&gt;
As mentioned above, the ics is an important data structure in AAC decoding. These are its fields, according to FAAD2:&lt;br /&gt;
&lt;br /&gt;
  max_sfb&lt;br /&gt;
  num_swb&lt;br /&gt;
  num_window_groups&lt;br /&gt;
  num_windows&lt;br /&gt;
  window_sequence&lt;br /&gt;
  window_group_length[8]&lt;br /&gt;
  window_shape&lt;br /&gt;
  scale_factor_grouping&lt;br /&gt;
  section_sfb_offset[8][8*15]&lt;br /&gt;
  swb_offset&lt;br /&gt;
  section_codebook[8][15*8]&lt;br /&gt;
  section_start[8][15*8]&lt;br /&gt;
  section_end[8][15*8]&lt;br /&gt;
  sfb_codebook[8][15*8]&lt;br /&gt;
  number_sections[8]  ''// number of sections in a group''&lt;br /&gt;
  global_gain&lt;br /&gt;
  scale_factors[8][51]  ''// FAAD2 comment: [0..255]?''&lt;br /&gt;
  ms_mask_present&lt;br /&gt;
  ms_used[MAX_WINDOW_GROUPS][MAX_SFB]  ''// dimensions = [8][51]''&lt;br /&gt;
  noise_used&lt;br /&gt;
  pulse_data_present&lt;br /&gt;
  tns_data_present&lt;br /&gt;
  gain_control_data_present&lt;br /&gt;
  predictor_data_present&lt;br /&gt;
  pulse_info pulse&lt;br /&gt;
  tns_info tns&lt;br /&gt;
  ''data structures for main profile, document later''&lt;br /&gt;
  ''data structures for LTP, document later''&lt;br /&gt;
  ''data structures for SSR, document later''&lt;br /&gt;
  ''data structures for error resilience, document later''&lt;br /&gt;
&lt;br /&gt;
These pages detail the process for decoding the various syntax elements:&lt;br /&gt;
&lt;br /&gt;
* [[Decoding AAC SCE and LFE]]&lt;br /&gt;
* [[Decoding AAC CPE]]&lt;br /&gt;
** [[Reconstructing AAC CPE]]&lt;br /&gt;
* Decoding AAC CCE&lt;br /&gt;
* Decoding AAC DSE&lt;br /&gt;
* Decoding AAC PCE&lt;br /&gt;
* [[Decoding AAC FIL]]&lt;br /&gt;
* [[Decoding AAC END]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=2741</id>
		<title>NUT</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=2741"/>
		<updated>2006-03-12T18:12:27Z</updated>

		<summary type="html">&lt;p&gt;Ods15: /* Linear search implementation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Extensions: nut&lt;br /&gt;
* Website: http://www.nut.hu/&lt;br /&gt;
&lt;br /&gt;
NUT is a container format under construction by [[MPlayer]] and [[FFmpeg]] developers.&lt;br /&gt;
Its main goals are to be simple, flexible and error-resistant while maintaining the smallest possible overhead.&lt;br /&gt;
&lt;br /&gt;
== NUT seeking algo in libnut ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Binary search and linear interpolation ===&lt;br /&gt;
&lt;br /&gt;
==== Startup ====&lt;br /&gt;
Go to beginning of file if first syncpoint has not been found, and then go to EOF and search backward to find last syncpoint.&lt;br /&gt;
Pick the closest possible syncpoints for requested pts from syncpoint cache, one higher and one lower. If requested pts is lower than first syncpoint or higher than last syncpoint, then seek to either of those syncpoints and end seek.&lt;br /&gt;
&lt;br /&gt;
Binary search is ended when the entire region between the 2 syncpoints picked has been scanned. Which could even be before it has begun thanks to syncpoint cache.&lt;br /&gt;
&lt;br /&gt;
==== Guess position ====&lt;br /&gt;
Best results have been achieved by combining both linear interpolation and binary search, giving most of the weight to interpolation.&lt;br /&gt;
&lt;br /&gt;
;hi, hi_pd: file position and timestamp of the top edge of the binary search.&lt;br /&gt;
;lo, lo_pd: file position and timestamp of the bottom edge of the binary search.&lt;br /&gt;
;time_pos: Requested pts.&lt;br /&gt;
;guess: begginning of linear search for syncpoint.&lt;br /&gt;
&lt;br /&gt;
 #define INTERPOLATE_WEIGHT (19./20)&lt;br /&gt;
 if (hi - lo &amp;lt; nut-&amp;gt;max_distance*2) guess = lo + 16;&lt;br /&gt;
 else { // linear interpolation&lt;br /&gt;
     double a = (double)(hi - lo) / (hi_pd - lo_pd);&lt;br /&gt;
     guess = lo + a * (time_pos - lo_pd);&lt;br /&gt;
     guess = guess * INTERPOLATE_WEIGHT + (lo+hi)/2 * (1 - INTERPOLATE_WEIGHT);&lt;br /&gt;
     if (hi - guess &amp;lt; nut-&amp;gt;max_distance*2) guess = hi - nut-&amp;gt;max_distance*2; //(lo + hi)/2;&lt;br /&gt;
 }&lt;br /&gt;
 if (guess &amp;lt; lo + 16) guess = lo + 16;&lt;br /&gt;
&lt;br /&gt;
The first conditional prevents too much recursing when the distance is already low. The last conditional prevents infinite loop of syncpoint search constantly finding ''lo'' and achieving nothing.&lt;br /&gt;
&lt;br /&gt;
==== Binary search ====&lt;br /&gt;
Now, find a syncpoint, bounded between ''guess'' and ''hi''. If it has a timestamp higher than requested pts, then replace ''hi'' and ''hi_pd'', otherwise replace ''lo'' and ''lo_pd''.&lt;br /&gt;
If a syncpoint was not found between ''guess'' and ''hi'', then, if ''guess'' is smaller or equal to ''lo + 16'', then you have scanned the entire area between ''lo'' and ''hi'', and your binary search is done. Otherwise, replace ''hi'' with ''guess'' and repeat the binary search.&lt;br /&gt;
&lt;br /&gt;
After finding the 2 closest syncpoints bounding your requested pts, the bounds of linear are search are:&lt;br /&gt;
&lt;br /&gt;
 *start = lo_s.pos - (lo_s.back_ptr * 16 + 15);&lt;br /&gt;
 *end = hi_s.pos;&lt;br /&gt;
 *stopper = hi_s;&lt;br /&gt;
&lt;br /&gt;
''stopper'' is used later to end linear search prematurely. Note that it is the '''top''' edge of binary search, meaning, it has a timestamp higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Linear search ===&lt;br /&gt;
&lt;br /&gt;
==== Bounds of linear search ====&lt;br /&gt;
Linear search of course ends at ''end'', however, it can end earlier:&lt;br /&gt;
* When you find a frame of any stream, with a dts higher than requested pts.&lt;br /&gt;
* When you find a frame for '''all''' active streams with a pts higher than requested pts.&lt;br /&gt;
* When you find a syncpoint immediately following the syncpoint pointed to by ''stopper'''s back_ptr, (from here on this syncpoint will be called ''stopper_syncpoint'') '''and''' all streams are active.&lt;br /&gt;
* When you reach ''stopper_syncpoint'', and you have not found a keyframe for any '''non'''-active between ''stopper''&amp;lt;nowiki&amp;gt;'&amp;lt;/nowiki&amp;gt;s back_ptr and ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp''. The reason for this is that ''stopper'' did not point because to ''stopper_syncpoint'' can only be because of active stream keyframes, and not non active ones.&lt;br /&gt;
* When you find a keyframe for all '''non'''-active streams after ''stopper_syncpoint'' with a pts lower than ''stopper.timestamp'', which had a keyframe in the region in the previous condition. The logic is:&lt;br /&gt;
** ''stopper.timestamp'' is higher than requested pts.&lt;br /&gt;
** ''stopper_syncpoint'' is '''not''' the syncpoint pointed to by ''stopper.back_ptr'', but the one immediately following.&lt;br /&gt;
** If there was a keyframe for every non active stream after ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp'', then the reason ''stopper'' does not point to ''stopper_syncpoint'' must be that there are no keyframes for '''active''' streams with a pts lower than ''stopper.timestamp'' after ''stopper_syncpoint''.&lt;br /&gt;
** There might be more keyframes in the region with a pts higher than ''stopper.timestamp'', but those are irrelevant because they are higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
The last 3 conditions can be phrased differently:&lt;br /&gt;
* When saying keyframes, only keyframes with a pts lower than ''stopper.timestamp'' are intended. Any other keyframes are irrelavent.&lt;br /&gt;
* The region ''stopper.back_ptr'' to ''stopper_syncpoint'' has a set of keyframes between it. These keyframes are the ones responsible for ''stopper'' pointing to ''stopper.back_ptr'' and not ''stopper_syncpoint''.&lt;br /&gt;
* If all streams are active, then it's impossible for there to be better keyframes for '''all''' active streams between ''stopper_syncpoint'' to the end of the linear search, because if there was, ''stopper.back_ptr'' would point there.&lt;br /&gt;
* If some streams are inactive, but none of them have a keyframe in the region specified above, then the keyframes responsible for ''stopper'' pointing to ''stopper.back_ptr'' are only from active streams, so again it is impossible there is a better position later in the linear search.&lt;br /&gt;
* If some streams are inactive, and some of them '''do''' have a keyframe in the region specified above, then those keyframes are ''possibly'' responsible for ''stopper'' pointing to ''stopper.back_ptr''. However, if we find more keyframes of those same inactive streams '''after''' the region, then they had nothing to do with ''stopper.back_ptr'', and again the condition is met.&lt;br /&gt;
&lt;br /&gt;
==== Linear search implementation ====&lt;br /&gt;
&lt;br /&gt;
# Start at ''start''.&lt;br /&gt;
# Search for syncpoint. If it is further than ''start + 15'', then the file is errored, and you can start playing immediately from this syncpoint.&lt;br /&gt;
# Perform full demuxing, buffering everything read. If you encounter any NUT error during demuxing, seek back to the syncpoint after ''start'' and end seek.&lt;br /&gt;
# On every syncpoint, flush the buffer and cache the syncpoint position.&lt;br /&gt;
#* If this syncpoint is ''stopper_syncpoint'', then do not flush the buffer, as it would be possible the linear search would end immediatelty afterwards and a second underlying seek would not be necessary.&lt;br /&gt;
# When finding keyframe of active stream with pts lower than requested pts, store position of keyframe. Discard previous value.&lt;br /&gt;
# End linear search as necessary by bounds given above.&lt;br /&gt;
# Pick the lowest value from positions of keyframes for active streams. This is the final position.&lt;br /&gt;
# Seek to closest syncpoint before the final position, preform a minimal demuxing until final position (to get proper last_pts context across all streams).&lt;br /&gt;
#* With luck this seek will not need an underlying seek, if you have not flushed the buffer since the requested position.&lt;br /&gt;
#* In most common case, ''stopper.back_ptr'' points to same syncpoint as the start of the linear search, as both syncpoints point to the same rare video keyframe.&lt;br /&gt;
#* If only video stream is active and the only non active stream is audio, you will most likely end your linear search immediately after ''stopper_syncpoint'' by finding an audio keyframe. Afterwards you will rewind right back to ''start'', and, since buffer hasn't been flushed, this will not need an underlying seek.&lt;br /&gt;
&lt;br /&gt;
=== Index ===&lt;br /&gt;
With index, binary search step is skipped, and a much more limited linear search used, between two immediate syncpoints. The syncpoint picked is the highest possible one that has a keyframe for each active stream past the syncpoint with a pts lower than requested pts. The end of the linear search is the syncpoint immediately following.&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Index ===&lt;br /&gt;
Create the index in the same manner as creating the index in the muxer, remembering keyframes and EOR at syncpoint positions.&lt;br /&gt;
With one big difference - dynamic index can have gaps, thanks to seeking. Every syncpiont entry in the dynamic index has a flag indicating if it has a &amp;quot;unresearched region&amp;quot; gap from last syncpoint.&lt;br /&gt;
&lt;br /&gt;
In seeking, dynamic index is used in the same manner as complete index. However, when deciding a syncpoint, the entire range of the syncpoint picked until the first syncpoint with a pts higher than requested is checked for having been already researched. If a &amp;quot;hole&amp;quot; is found anywhere in this range, dynamic index is disregarded and full binary search is performed.&lt;br /&gt;
&lt;br /&gt;
=== End of Relavence ===&lt;br /&gt;
Behavior with linear search:&lt;br /&gt;
* Treat EOR frames same as keyframes. Seeing an EOR frame for an active stream causes the stream to be ignored until the next keyframe of same stream.&lt;br /&gt;
* If all active streams are EOR by end of linear search, just use start of linear search as final seeking position.&lt;br /&gt;
&lt;br /&gt;
For index:&lt;br /&gt;
* When picking the correct syncpoint to start linear search, ignore streams which have EOR with pts lower than requested pts and no keyframe with pts lower than requested pts.&lt;br /&gt;
* If all active streams are EOR, pick the syncpoint immediately before the syncpoint with the last EOR across all streams with pts lower than requested pts.&lt;br /&gt;
&lt;br /&gt;
[[Category:Container Formats]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=2740</id>
		<title>NUT</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=2740"/>
		<updated>2006-03-12T18:11:46Z</updated>

		<summary type="html">&lt;p&gt;Ods15: /* Binary search */  some fixes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Extensions: nut&lt;br /&gt;
* Website: http://www.nut.hu/&lt;br /&gt;
&lt;br /&gt;
NUT is a container format under construction by [[MPlayer]] and [[FFmpeg]] developers.&lt;br /&gt;
Its main goals are to be simple, flexible and error-resistant while maintaining the smallest possible overhead.&lt;br /&gt;
&lt;br /&gt;
== NUT seeking algo in libnut ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Binary search and linear interpolation ===&lt;br /&gt;
&lt;br /&gt;
==== Startup ====&lt;br /&gt;
Go to beginning of file if first syncpoint has not been found, and then go to EOF and search backward to find last syncpoint.&lt;br /&gt;
Pick the closest possible syncpoints for requested pts from syncpoint cache, one higher and one lower. If requested pts is lower than first syncpoint or higher than last syncpoint, then seek to either of those syncpoints and end seek.&lt;br /&gt;
&lt;br /&gt;
Binary search is ended when the entire region between the 2 syncpoints picked has been scanned. Which could even be before it has begun thanks to syncpoint cache.&lt;br /&gt;
&lt;br /&gt;
==== Guess position ====&lt;br /&gt;
Best results have been achieved by combining both linear interpolation and binary search, giving most of the weight to interpolation.&lt;br /&gt;
&lt;br /&gt;
;hi, hi_pd: file position and timestamp of the top edge of the binary search.&lt;br /&gt;
;lo, lo_pd: file position and timestamp of the bottom edge of the binary search.&lt;br /&gt;
;time_pos: Requested pts.&lt;br /&gt;
;guess: begginning of linear search for syncpoint.&lt;br /&gt;
&lt;br /&gt;
 #define INTERPOLATE_WEIGHT (19./20)&lt;br /&gt;
 if (hi - lo &amp;lt; nut-&amp;gt;max_distance*2) guess = lo + 16;&lt;br /&gt;
 else { // linear interpolation&lt;br /&gt;
     double a = (double)(hi - lo) / (hi_pd - lo_pd);&lt;br /&gt;
     guess = lo + a * (time_pos - lo_pd);&lt;br /&gt;
     guess = guess * INTERPOLATE_WEIGHT + (lo+hi)/2 * (1 - INTERPOLATE_WEIGHT);&lt;br /&gt;
     if (hi - guess &amp;lt; nut-&amp;gt;max_distance*2) guess = hi - nut-&amp;gt;max_distance*2; //(lo + hi)/2;&lt;br /&gt;
 }&lt;br /&gt;
 if (guess &amp;lt; lo + 16) guess = lo + 16;&lt;br /&gt;
&lt;br /&gt;
The first conditional prevents too much recursing when the distance is already low. The last conditional prevents infinite loop of syncpoint search constantly finding ''lo'' and achieving nothing.&lt;br /&gt;
&lt;br /&gt;
==== Binary search ====&lt;br /&gt;
Now, find a syncpoint, bounded between ''guess'' and ''hi''. If it has a timestamp higher than requested pts, then replace ''hi'' and ''hi_pd'', otherwise replace ''lo'' and ''lo_pd''.&lt;br /&gt;
If a syncpoint was not found between ''guess'' and ''hi'', then, if ''guess'' is smaller or equal to ''lo + 16'', then you have scanned the entire area between ''lo'' and ''hi'', and your binary search is done. Otherwise, replace ''hi'' with ''guess'' and repeat the binary search.&lt;br /&gt;
&lt;br /&gt;
After finding the 2 closest syncpoints bounding your requested pts, the bounds of linear are search are:&lt;br /&gt;
&lt;br /&gt;
 *start = lo_s.pos - (lo_s.back_ptr * 16 + 15);&lt;br /&gt;
 *end = hi_s.pos;&lt;br /&gt;
 *stopper = hi_s;&lt;br /&gt;
&lt;br /&gt;
''stopper'' is used later to end linear search prematurely. Note that it is the '''top''' edge of binary search, meaning, it has a timestamp higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Linear search ===&lt;br /&gt;
&lt;br /&gt;
==== Bounds of linear search ====&lt;br /&gt;
Linear search of course ends at ''end'', however, it can end earlier:&lt;br /&gt;
* When you find a frame of any stream, with a dts higher than requested pts.&lt;br /&gt;
* When you find a frame for '''all''' active streams with a pts higher than requested pts.&lt;br /&gt;
* When you find a syncpoint immediately following the syncpoint pointed to by ''stopper'''s back_ptr, (from here on this syncpoint will be called ''stopper_syncpoint'') '''and''' all streams are active.&lt;br /&gt;
* When you reach ''stopper_syncpoint'', and you have not found a keyframe for any '''non'''-active between ''stopper''&amp;lt;nowiki&amp;gt;'&amp;lt;/nowiki&amp;gt;s back_ptr and ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp''. The reason for this is that ''stopper'' did not point because to ''stopper_syncpoint'' can only be because of active stream keyframes, and not non active ones.&lt;br /&gt;
* When you find a keyframe for all '''non'''-active streams after ''stopper_syncpoint'' with a pts lower than ''stopper.timestamp'', which had a keyframe in the region in the previous condition. The logic is:&lt;br /&gt;
** ''stopper.timestamp'' is higher than requested pts.&lt;br /&gt;
** ''stopper_syncpoint'' is '''not''' the syncpoint pointed to by ''stopper.back_ptr'', but the one immediately following.&lt;br /&gt;
** If there was a keyframe for every non active stream after ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp'', then the reason ''stopper'' does not point to ''stopper_syncpoint'' must be that there are no keyframes for '''active''' streams with a pts lower than ''stopper.timestamp'' after ''stopper_syncpoint''.&lt;br /&gt;
** There might be more keyframes in the region with a pts higher than ''stopper.timestamp'', but those are irrelevant because they are higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
The last 3 conditions can be phrased differently:&lt;br /&gt;
* When saying keyframes, only keyframes with a pts lower than ''stopper.timestamp'' are intended. Any other keyframes are irrelavent.&lt;br /&gt;
* The region ''stopper.back_ptr'' to ''stopper_syncpoint'' has a set of keyframes between it. These keyframes are the ones responsible for ''stopper'' pointing to ''stopper.back_ptr'' and not ''stopper_syncpoint''.&lt;br /&gt;
* If all streams are active, then it's impossible for there to be better keyframes for '''all''' active streams between ''stopper_syncpoint'' to the end of the linear search, because if there was, ''stopper.back_ptr'' would point there.&lt;br /&gt;
* If some streams are inactive, but none of them have a keyframe in the region specified above, then the keyframes responsible for ''stopper'' pointing to ''stopper.back_ptr'' are only from active streams, so again it is impossible there is a better position later in the linear search.&lt;br /&gt;
* If some streams are inactive, and some of them '''do''' have a keyframe in the region specified above, then those keyframes are ''possibly'' responsible for ''stopper'' pointing to ''stopper.back_ptr''. However, if we find more keyframes of those same inactive streams '''after''' the region, then they had nothing to do with ''stopper.back_ptr'', and again the condition is met.&lt;br /&gt;
&lt;br /&gt;
==== Linear search implementation ====&lt;br /&gt;
&lt;br /&gt;
# Start at ''start''.&lt;br /&gt;
# Search for syncpoint. If it is further than ''start + 7'', then the file is errored, and you can start playing immediately from this syncpoint.&lt;br /&gt;
# Perform full demuxing, buffering everything read. If you encounter any NUT error during demuxing, seek back to the syncpoint after ''start'' and end seek.&lt;br /&gt;
# On every syncpoint, flush the buffer and cache the syncpoint position.&lt;br /&gt;
#* If this syncpoint is ''stopper_syncpoint'', then do not flush the buffer, as it would be possible the linear search would end immediatelty afterwards and a second underlying seek would not be necessary.&lt;br /&gt;
# When finding keyframe of active stream with pts lower than requested pts, store position of keyframe. Discard previous value.&lt;br /&gt;
# End linear search as necessary by bounds given above.&lt;br /&gt;
# Pick the lowest value from positions of keyframes for active streams. This is the final position.&lt;br /&gt;
# Seek to closest syncpoint before the final position, preform a minimal demuxing until final position (to get proper last_pts context across all streams).&lt;br /&gt;
#* With luck this seek will not need an underlying seek, if you have not flushed the buffer since the requested position.&lt;br /&gt;
#* In most common case, ''stopper.back_ptr'' points to same syncpoint as the start of the linear search, as both syncpoints point to the same rare video keyframe.&lt;br /&gt;
#* If only video stream is active and the only non active stream is audio, you will most likely end your linear search immediately after ''stopper_syncpoint'' by finding an audio keyframe. Afterwards you will rewind right back to ''start'', and, since buffer hasn't been flushed, this will not need an underlying seek.&lt;br /&gt;
&lt;br /&gt;
=== Index ===&lt;br /&gt;
With index, binary search step is skipped, and a much more limited linear search used, between two immediate syncpoints. The syncpoint picked is the highest possible one that has a keyframe for each active stream past the syncpoint with a pts lower than requested pts. The end of the linear search is the syncpoint immediately following.&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Index ===&lt;br /&gt;
Create the index in the same manner as creating the index in the muxer, remembering keyframes and EOR at syncpoint positions.&lt;br /&gt;
With one big difference - dynamic index can have gaps, thanks to seeking. Every syncpiont entry in the dynamic index has a flag indicating if it has a &amp;quot;unresearched region&amp;quot; gap from last syncpoint.&lt;br /&gt;
&lt;br /&gt;
In seeking, dynamic index is used in the same manner as complete index. However, when deciding a syncpoint, the entire range of the syncpoint picked until the first syncpoint with a pts higher than requested is checked for having been already researched. If a &amp;quot;hole&amp;quot; is found anywhere in this range, dynamic index is disregarded and full binary search is performed.&lt;br /&gt;
&lt;br /&gt;
=== End of Relavence ===&lt;br /&gt;
Behavior with linear search:&lt;br /&gt;
* Treat EOR frames same as keyframes. Seeing an EOR frame for an active stream causes the stream to be ignored until the next keyframe of same stream.&lt;br /&gt;
* If all active streams are EOR by end of linear search, just use start of linear search as final seeking position.&lt;br /&gt;
&lt;br /&gt;
For index:&lt;br /&gt;
* When picking the correct syncpoint to start linear search, ignore streams which have EOR with pts lower than requested pts and no keyframe with pts lower than requested pts.&lt;br /&gt;
* If all active streams are EOR, pick the syncpoint immediately before the syncpoint with the last EOR across all streams with pts lower than requested pts.&lt;br /&gt;
&lt;br /&gt;
[[Category:Container Formats]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=2739</id>
		<title>NUT</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=2739"/>
		<updated>2006-03-12T07:12:31Z</updated>

		<summary type="html">&lt;p&gt;Ods15: /* Guess position */  Change to 16 and wheight&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Extensions: nut&lt;br /&gt;
* Website: http://www.nut.hu/&lt;br /&gt;
&lt;br /&gt;
NUT is a container format under construction by [[MPlayer]] and [[FFmpeg]] developers.&lt;br /&gt;
Its main goals are to be simple, flexible and error-resistant while maintaining the smallest possible overhead.&lt;br /&gt;
&lt;br /&gt;
== NUT seeking algo in libnut ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Binary search and linear interpolation ===&lt;br /&gt;
&lt;br /&gt;
==== Startup ====&lt;br /&gt;
Go to beginning of file if first syncpoint has not been found, and then go to EOF and search backward to find last syncpoint.&lt;br /&gt;
Pick the closest possible syncpoints for requested pts from syncpoint cache, one higher and one lower. If requested pts is lower than first syncpoint or higher than last syncpoint, then seek to either of those syncpoints and end seek.&lt;br /&gt;
&lt;br /&gt;
Binary search is ended when the entire region between the 2 syncpoints picked has been scanned. Which could even be before it has begun thanks to syncpoint cache.&lt;br /&gt;
&lt;br /&gt;
==== Guess position ====&lt;br /&gt;
Best results have been achieved by combining both linear interpolation and binary search, giving most of the weight to interpolation.&lt;br /&gt;
&lt;br /&gt;
;hi, hi_pd: file position and timestamp of the top edge of the binary search.&lt;br /&gt;
;lo, lo_pd: file position and timestamp of the bottom edge of the binary search.&lt;br /&gt;
;time_pos: Requested pts.&lt;br /&gt;
;guess: begginning of linear search for syncpoint.&lt;br /&gt;
&lt;br /&gt;
 #define INTERPOLATE_WEIGHT (19./20)&lt;br /&gt;
 if (hi - lo &amp;lt; nut-&amp;gt;max_distance*2) guess = lo + 16;&lt;br /&gt;
 else { // linear interpolation&lt;br /&gt;
     double a = (double)(hi - lo) / (hi_pd - lo_pd);&lt;br /&gt;
     guess = lo + a * (time_pos - lo_pd);&lt;br /&gt;
     guess = guess * INTERPOLATE_WEIGHT + (lo+hi)/2 * (1 - INTERPOLATE_WEIGHT);&lt;br /&gt;
     if (hi - guess &amp;lt; nut-&amp;gt;max_distance*2) guess = hi - nut-&amp;gt;max_distance*2; //(lo + hi)/2;&lt;br /&gt;
 }&lt;br /&gt;
 if (guess &amp;lt; lo + 16) guess = lo + 16;&lt;br /&gt;
&lt;br /&gt;
The first conditional prevents too much recursing when the distance is already low. The last conditional prevents infinite loop of syncpoint search constantly finding ''lo'' and achieving nothing.&lt;br /&gt;
&lt;br /&gt;
==== Binary search ====&lt;br /&gt;
Now, find a syncpoint, bounded between ''guess'' and ''hi''. If it has a timestamp higher than requested pts, then replace ''hi'' and ''hi_pd'', otherwise replace ''lo'' and ''lo_pd''.&lt;br /&gt;
If a syncpoint was not found between ''guess'' and ''hi'', then, if ''guess'' is smaller or equal to ''lo + 11'', then you have scanned the entire area between ''lo'' and ''hi'', and your binary search is done. Otherwise, replace ''hi'' with ''guess'' and repeat the binary search.&lt;br /&gt;
&lt;br /&gt;
After finding the 2 closest syncpoints bounding your requested pts, the bounds of linear are search are:&lt;br /&gt;
&lt;br /&gt;
 *start = lo_s.pos - (lo_s.back_ptr * 8 + 7);&lt;br /&gt;
 *end = lo_s.pos;&lt;br /&gt;
 *stopper = hi_s;&lt;br /&gt;
&lt;br /&gt;
''stopper'' is used later to end linear search prematurely. Note that it is the '''top''' edge of binary search, meaning, it has a timestamp higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Linear search ===&lt;br /&gt;
&lt;br /&gt;
==== Bounds of linear search ====&lt;br /&gt;
Linear search of course ends at ''end'', however, it can end earlier:&lt;br /&gt;
* When you find a frame of any stream, with a dts higher than requested pts.&lt;br /&gt;
* When you find a frame for '''all''' active streams with a pts higher than requested pts.&lt;br /&gt;
* When you find a syncpoint immediately following the syncpoint pointed to by ''stopper'''s back_ptr, (from here on this syncpoint will be called ''stopper_syncpoint'') '''and''' all streams are active.&lt;br /&gt;
* When you reach ''stopper_syncpoint'', and you have not found a keyframe for any '''non'''-active between ''stopper''&amp;lt;nowiki&amp;gt;'&amp;lt;/nowiki&amp;gt;s back_ptr and ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp''. The reason for this is that ''stopper'' did not point because to ''stopper_syncpoint'' can only be because of active stream keyframes, and not non active ones.&lt;br /&gt;
* When you find a keyframe for all '''non'''-active streams after ''stopper_syncpoint'' with a pts lower than ''stopper.timestamp'', which had a keyframe in the region in the previous condition. The logic is:&lt;br /&gt;
** ''stopper.timestamp'' is higher than requested pts.&lt;br /&gt;
** ''stopper_syncpoint'' is '''not''' the syncpoint pointed to by ''stopper.back_ptr'', but the one immediately following.&lt;br /&gt;
** If there was a keyframe for every non active stream after ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp'', then the reason ''stopper'' does not point to ''stopper_syncpoint'' must be that there are no keyframes for '''active''' streams with a pts lower than ''stopper.timestamp'' after ''stopper_syncpoint''.&lt;br /&gt;
** There might be more keyframes in the region with a pts higher than ''stopper.timestamp'', but those are irrelevant because they are higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
The last 3 conditions can be phrased differently:&lt;br /&gt;
* When saying keyframes, only keyframes with a pts lower than ''stopper.timestamp'' are intended. Any other keyframes are irrelavent.&lt;br /&gt;
* The region ''stopper.back_ptr'' to ''stopper_syncpoint'' has a set of keyframes between it. These keyframes are the ones responsible for ''stopper'' pointing to ''stopper.back_ptr'' and not ''stopper_syncpoint''.&lt;br /&gt;
* If all streams are active, then it's impossible for there to be better keyframes for '''all''' active streams between ''stopper_syncpoint'' to the end of the linear search, because if there was, ''stopper.back_ptr'' would point there.&lt;br /&gt;
* If some streams are inactive, but none of them have a keyframe in the region specified above, then the keyframes responsible for ''stopper'' pointing to ''stopper.back_ptr'' are only from active streams, so again it is impossible there is a better position later in the linear search.&lt;br /&gt;
* If some streams are inactive, and some of them '''do''' have a keyframe in the region specified above, then those keyframes are ''possibly'' responsible for ''stopper'' pointing to ''stopper.back_ptr''. However, if we find more keyframes of those same inactive streams '''after''' the region, then they had nothing to do with ''stopper.back_ptr'', and again the condition is met.&lt;br /&gt;
&lt;br /&gt;
==== Linear search implementation ====&lt;br /&gt;
&lt;br /&gt;
# Start at ''start''.&lt;br /&gt;
# Search for syncpoint. If it is further than ''start + 7'', then the file is errored, and you can start playing immediately from this syncpoint.&lt;br /&gt;
# Perform full demuxing, buffering everything read. If you encounter any NUT error during demuxing, seek back to the syncpoint after ''start'' and end seek.&lt;br /&gt;
# On every syncpoint, flush the buffer and cache the syncpoint position.&lt;br /&gt;
#* If this syncpoint is ''stopper_syncpoint'', then do not flush the buffer, as it would be possible the linear search would end immediatelty afterwards and a second underlying seek would not be necessary.&lt;br /&gt;
# When finding keyframe of active stream with pts lower than requested pts, store position of keyframe. Discard previous value.&lt;br /&gt;
# End linear search as necessary by bounds given above.&lt;br /&gt;
# Pick the lowest value from positions of keyframes for active streams. This is the final position.&lt;br /&gt;
# Seek to closest syncpoint before the final position, preform a minimal demuxing until final position (to get proper last_pts context across all streams).&lt;br /&gt;
#* With luck this seek will not need an underlying seek, if you have not flushed the buffer since the requested position.&lt;br /&gt;
#* In most common case, ''stopper.back_ptr'' points to same syncpoint as the start of the linear search, as both syncpoints point to the same rare video keyframe.&lt;br /&gt;
#* If only video stream is active and the only non active stream is audio, you will most likely end your linear search immediately after ''stopper_syncpoint'' by finding an audio keyframe. Afterwards you will rewind right back to ''start'', and, since buffer hasn't been flushed, this will not need an underlying seek.&lt;br /&gt;
&lt;br /&gt;
=== Index ===&lt;br /&gt;
With index, binary search step is skipped, and a much more limited linear search used, between two immediate syncpoints. The syncpoint picked is the highest possible one that has a keyframe for each active stream past the syncpoint with a pts lower than requested pts. The end of the linear search is the syncpoint immediately following.&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Index ===&lt;br /&gt;
Create the index in the same manner as creating the index in the muxer, remembering keyframes and EOR at syncpoint positions.&lt;br /&gt;
With one big difference - dynamic index can have gaps, thanks to seeking. Every syncpiont entry in the dynamic index has a flag indicating if it has a &amp;quot;unresearched region&amp;quot; gap from last syncpoint.&lt;br /&gt;
&lt;br /&gt;
In seeking, dynamic index is used in the same manner as complete index. However, when deciding a syncpoint, the entire range of the syncpoint picked until the first syncpoint with a pts higher than requested is checked for having been already researched. If a &amp;quot;hole&amp;quot; is found anywhere in this range, dynamic index is disregarded and full binary search is performed.&lt;br /&gt;
&lt;br /&gt;
=== End of Relavence ===&lt;br /&gt;
Behavior with linear search:&lt;br /&gt;
* Treat EOR frames same as keyframes. Seeing an EOR frame for an active stream causes the stream to be ignored until the next keyframe of same stream.&lt;br /&gt;
* If all active streams are EOR by end of linear search, just use start of linear search as final seeking position.&lt;br /&gt;
&lt;br /&gt;
For index:&lt;br /&gt;
* When picking the correct syncpoint to start linear search, ignore streams which have EOR with pts lower than requested pts and no keyframe with pts lower than requested pts.&lt;br /&gt;
* If all active streams are EOR, pick the syncpoint immediately before the syncpoint with the last EOR across all streams with pts lower than requested pts.&lt;br /&gt;
&lt;br /&gt;
[[Category:Container Formats]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=Rewind&amp;diff=2516</id>
		<title>Rewind</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=Rewind&amp;diff=2516"/>
		<updated>2006-03-03T16:13:19Z</updated>

		<summary type="html">&lt;p&gt;Ods15: category&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Rewind is the project name of my ([[User:merbanan|Benjamin Larsson]]) collection of different tools to aid Reverse Engineering.&lt;br /&gt;
The goal is to combine all the tools into 'the' tool for codec RE'ing work under Linux.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Elftractor ==&lt;br /&gt;
This Perl script can analyze elf binaries to extract the data tables. The produced tables look quite good&lt;br /&gt;
and tables with 1 or 2 dimensions can be produced. The script uses a database which can be edited to adjust&lt;br /&gt;
the different types of possibe tables. Rudimentary function skeleton generation can also be done.&lt;br /&gt;
&lt;br /&gt;
Features missing:&lt;br /&gt;
* &amp;gt;2 dimensions for table generation&lt;br /&gt;
* always generate compilable tables&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== REbug ==&lt;br /&gt;
A set of macros and functions that can trace a selected calltree. Based partly on this code [http://www.multimedia.cx/pre/loadxan.c.txt].&lt;br /&gt;
Currently the output can then be processed to produce call graphs over executed code.&lt;br /&gt;
&lt;br /&gt;
Current features:&lt;br /&gt;
* function call tracing&lt;br /&gt;
* function argument dumping&lt;br /&gt;
* function return value dumping&lt;br /&gt;
* executed calltree graphing&lt;br /&gt;
&lt;br /&gt;
Features missing:&lt;br /&gt;
* memory tracking - lookup the use of malloc in the executed code&lt;br /&gt;
* structure resolver - check all malloced memory for pointers to other malloced memory&lt;br /&gt;
* argument typing - check/guess if the arguments are pointers to allocateded or stack memory, table elements or something else&lt;br /&gt;
* loop detection - guess existence of loop construct by checking the amount of consecutive calls &lt;br /&gt;
* code skeleton generation - generate a code template with the generated information&lt;br /&gt;
* structure graphing - generate a nice looking graph over the relations in the structures&lt;br /&gt;
&lt;br /&gt;
== Argument resolver ==&lt;br /&gt;
This Perl script can analyse the IDA Pro produced assembly of a binary and give a fairly accurate number of arguments to a function&lt;br /&gt;
and its return type. This script is meant to be used together with REbug output.&lt;br /&gt;
&lt;br /&gt;
[[Category: RE Tools]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=2412</id>
		<title>NUT</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=2412"/>
		<updated>2006-02-25T07:55:23Z</updated>

		<summary type="html">&lt;p&gt;Ods15: /* Bounds of linear search */  Clarify...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Extensions: nut&lt;br /&gt;
* Website: http://www.nut.hu/&lt;br /&gt;
&lt;br /&gt;
NUT is a container format under construction by [[MPlayer]] and [[FFmpeg]] developers.&lt;br /&gt;
Its main goals are to be simple, flexible and error-resistant while maintaining the smallest possible overhead.&lt;br /&gt;
&lt;br /&gt;
== NUT seeking algo in libnut ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Binary search and linear interpolation ===&lt;br /&gt;
&lt;br /&gt;
==== Startup ====&lt;br /&gt;
Go to beginning of file if first syncpoint has not been found, and then go to EOF and search backward to find last syncpoint.&lt;br /&gt;
Pick the closest possible syncpoints for requested pts from syncpoint cache, one higher and one lower. If requested pts is lower than first syncpoint or higher than last syncpoint, then seek to either of those syncpoints and end seek.&lt;br /&gt;
&lt;br /&gt;
Binary search is ended when the entire region between the 2 syncpoints picked has been scanned. Which could even be before it has begun thanks to syncpoint cache.&lt;br /&gt;
&lt;br /&gt;
==== Guess position ====&lt;br /&gt;
Best results have been achieved by combining both linear interpolation and binary search, giving most of the weight to interpolation.&lt;br /&gt;
&lt;br /&gt;
;hi, hi_pd: file position and timestamp of the top edge of the binary search.&lt;br /&gt;
;lo, lo_pd: file position and timestamp of the bottom edge of the binary search.&lt;br /&gt;
;time_pos: Requested pts.&lt;br /&gt;
;guess: begginning of linear search for syncpoint.&lt;br /&gt;
&lt;br /&gt;
 #define INTERPOLATE_WEIGHT (7./8)&lt;br /&gt;
 if (hi - lo &amp;lt; nut-&amp;gt;max_distance*2) guess = lo + 8;&lt;br /&gt;
 else { // linear interpolation&lt;br /&gt;
     double a = (double)(hi - lo) / (hi_pd - lo_pd);&lt;br /&gt;
     guess = lo + a * (time_pos - lo_pd);&lt;br /&gt;
     guess = guess * INTERPOLATE_WEIGHT + (lo+hi)/2 * (1 - INTERPOLATE_WEIGHT);&lt;br /&gt;
     if (hi - guess &amp;lt; nut-&amp;gt;max_distance*2) guess = hi - nut-&amp;gt;max_distance*2; //(lo + hi)/2;&lt;br /&gt;
 }&lt;br /&gt;
 if (guess &amp;lt; lo + 8) guess = lo + 8;&lt;br /&gt;
&lt;br /&gt;
The first conditional prevents too much recursing when the distance is already low. The last conditional prevents infinite loop of syncpoint search constantly finding ''lo'' and achieving nothing.&lt;br /&gt;
&lt;br /&gt;
==== Binary search ====&lt;br /&gt;
Now, find a syncpoint, bounded between ''guess'' and ''hi''. If it has a timestamp higher than requested pts, then replace ''hi'' and ''hi_pd'', otherwise replace ''lo'' and ''lo_pd''.&lt;br /&gt;
If a syncpoint was not found between ''guess'' and ''hi'', then, if ''guess'' is smaller or equal to ''lo + 11'', then you have scanned the entire area between ''lo'' and ''hi'', and your binary search is done. Otherwise, replace ''hi'' with ''guess'' and repeat the binary search.&lt;br /&gt;
&lt;br /&gt;
After finding the 2 closest syncpoints bounding your requested pts, the bounds of linear are search are:&lt;br /&gt;
&lt;br /&gt;
 *start = lo_s.pos - (lo_s.back_ptr * 8 + 7);&lt;br /&gt;
 *end = lo_s.pos;&lt;br /&gt;
 *stopper = hi_s;&lt;br /&gt;
&lt;br /&gt;
''stopper'' is used later to end linear search prematurely. Note that it is the '''top''' edge of binary search, meaning, it has a timestamp higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Linear search ===&lt;br /&gt;
&lt;br /&gt;
==== Bounds of linear search ====&lt;br /&gt;
Linear search of course ends at ''end'', however, it can end earlier:&lt;br /&gt;
* When you find a frame of any stream, with a dts higher than requested pts.&lt;br /&gt;
* When you find a frame for '''all''' active streams with a pts higher than requested pts.&lt;br /&gt;
* When you find a syncpoint immediately following the syncpoint pointed to by ''stopper'''s back_ptr, (from here on this syncpoint will be called ''stopper_syncpoint'') '''and''' all streams are active.&lt;br /&gt;
* When you reach ''stopper_syncpoint'', and you have not found a keyframe for any '''non'''-active between ''stopper''&amp;lt;nowiki&amp;gt;'&amp;lt;/nowiki&amp;gt;s back_ptr and ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp''. The reason for this is that ''stopper'' did not point because to ''stopper_syncpoint'' can only be because of active stream keyframes, and not non active ones.&lt;br /&gt;
* When you find a keyframe for all '''non'''-active streams after ''stopper_syncpoint'' with a pts lower than ''stopper.timestamp'', which had a keyframe in the region in the previous condition. The logic is:&lt;br /&gt;
** ''stopper.timestamp'' is higher than requested pts.&lt;br /&gt;
** ''stopper_syncpoint'' is '''not''' the syncpoint pointed to by ''stopper.back_ptr'', but the one immediately following.&lt;br /&gt;
** If there was a keyframe for every non active stream after ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp'', then the reason ''stopper'' does not point to ''stopper_syncpoint'' must be that there are no keyframes for '''active''' streams with a pts lower than ''stopper.timestamp'' after ''stopper_syncpoint''.&lt;br /&gt;
** There might be more keyframes in the region with a pts higher than ''stopper.timestamp'', but those are irrelevant because they are higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
The last 3 conditions can be phrased differently:&lt;br /&gt;
* When saying keyframes, only keyframes with a pts lower than ''stopper.timestamp'' are intended. Any other keyframes are irrelavent.&lt;br /&gt;
* The region ''stopper.back_ptr'' to ''stopper_syncpoint'' has a set of keyframes between it. These keyframes are the ones responsible for ''stopper'' pointing to ''stopper.back_ptr'' and not ''stopper_syncpoint''.&lt;br /&gt;
* If all streams are active, then it's impossible for there to be better keyframes for '''all''' active streams between ''stopper_syncpoint'' to the end of the linear search, because if there was, ''stopper.back_ptr'' would point there.&lt;br /&gt;
* If some streams are inactive, but none of them have a keyframe in the region specified above, then the keyframes responsible for ''stopper'' pointing to ''stopper.back_ptr'' are only from active streams, so again it is impossible there is a better position later in the linear search.&lt;br /&gt;
* If some streams are inactive, and some of them '''do''' have a keyframe in the region specified above, then those keyframes are ''possibly'' responsible for ''stopper'' pointing to ''stopper.back_ptr''. However, if we find more keyframes of those same inactive streams '''after''' the region, then they had nothing to do with ''stopper.back_ptr'', and again the condition is met.&lt;br /&gt;
&lt;br /&gt;
==== Linear search implementation ====&lt;br /&gt;
&lt;br /&gt;
# Start at ''start''.&lt;br /&gt;
# Search for syncpoint. If it is further than ''start + 7'', then the file is errored, and you can start playing immediately from this syncpoint.&lt;br /&gt;
# Perform full demuxing, buffering everything read. If you encounter any NUT error during demuxing, seek back to the syncpoint after ''start'' and end seek.&lt;br /&gt;
# On every syncpoint, flush the buffer and cache the syncpoint position.&lt;br /&gt;
#* If this syncpoint is ''stopper_syncpoint'', then do not flush the buffer, as it would be possible the linear search would end immediatelty afterwards and a second underlying seek would not be necessary.&lt;br /&gt;
# When finding keyframe of active stream with pts lower than requested pts, store position of keyframe. Discard previous value.&lt;br /&gt;
# End linear search as necessary by bounds given above.&lt;br /&gt;
# Pick the lowest value from positions of keyframes for active streams. This is the final position.&lt;br /&gt;
# Seek to closest syncpoint before the final position, preform a minimal demuxing until final position (to get proper last_pts context across all streams).&lt;br /&gt;
#* With luck this seek will not need an underlying seek, if you have not flushed the buffer since the requested position.&lt;br /&gt;
#* In most common case, ''stopper.back_ptr'' points to same syncpoint as the start of the linear search, as both syncpoints point to the same rare video keyframe.&lt;br /&gt;
#* If only video stream is active and the only non active stream is audio, you will most likely end your linear search immediately after ''stopper_syncpoint'' by finding an audio keyframe. Afterwards you will rewind right back to ''start'', and, since buffer hasn't been flushed, this will not need an underlying seek.&lt;br /&gt;
&lt;br /&gt;
=== Index ===&lt;br /&gt;
With index, binary search step is skipped, and a much more limited linear search used, between two immediate syncpoints. The syncpoint picked is the highest possible one that has a keyframe for each active stream past the syncpoint with a pts lower than requested pts. The end of the linear search is the syncpoint immediately following.&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Index ===&lt;br /&gt;
Create the index in the same manner as creating the index in the muxer, remembering keyframes and EOR at syncpoint positions.&lt;br /&gt;
With one big difference - dynamic index can have gaps, thanks to seeking. Every syncpiont entry in the dynamic index has a flag indicating if it has a &amp;quot;unresearched region&amp;quot; gap from last syncpoint.&lt;br /&gt;
&lt;br /&gt;
In seeking, dynamic index is used in the same manner as complete index. However, when deciding a syncpoint, the entire range of the syncpoint picked until the first syncpoint with a pts higher than requested is checked for having been already researched. If a &amp;quot;hole&amp;quot; is found anywhere in this range, dynamic index is disregarded and full binary search is performed.&lt;br /&gt;
&lt;br /&gt;
=== End of Relavence ===&lt;br /&gt;
Behavior with linear search:&lt;br /&gt;
* Treat EOR frames same as keyframes. Seeing an EOR frame for an active stream causes the stream to be ignored until the next keyframe of same stream.&lt;br /&gt;
* If all active streams are EOR by end of linear search, just use start of linear search as final seeking position.&lt;br /&gt;
&lt;br /&gt;
For index:&lt;br /&gt;
* When picking the correct syncpoint to start linear search, ignore streams which have EOR with pts lower than requested pts and no keyframe with pts lower than requested pts.&lt;br /&gt;
* If all active streams are EOR, pick the syncpoint immediately before the syncpoint with the last EOR across all streams with pts lower than requested pts.&lt;br /&gt;
&lt;br /&gt;
[[Category:Container Formats]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=2411</id>
		<title>NUT</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=2411"/>
		<updated>2006-02-25T07:36:29Z</updated>

		<summary type="html">&lt;p&gt;Ods15: /* Bounds of linear search */  Fix wiki&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Extensions: nut&lt;br /&gt;
* Website: http://www.nut.hu/&lt;br /&gt;
&lt;br /&gt;
NUT is a container format under construction by [[MPlayer]] and [[FFmpeg]] developers.&lt;br /&gt;
Its main goals are to be simple, flexible and error-resistant while maintaining the smallest possible overhead.&lt;br /&gt;
&lt;br /&gt;
== NUT seeking algo in libnut ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Binary search and linear interpolation ===&lt;br /&gt;
&lt;br /&gt;
==== Startup ====&lt;br /&gt;
Go to beginning of file if first syncpoint has not been found, and then go to EOF and search backward to find last syncpoint.&lt;br /&gt;
Pick the closest possible syncpoints for requested pts from syncpoint cache, one higher and one lower. If requested pts is lower than first syncpoint or higher than last syncpoint, then seek to either of those syncpoints and end seek.&lt;br /&gt;
&lt;br /&gt;
Binary search is ended when the entire region between the 2 syncpoints picked has been scanned. Which could even be before it has begun thanks to syncpoint cache.&lt;br /&gt;
&lt;br /&gt;
==== Guess position ====&lt;br /&gt;
Best results have been achieved by combining both linear interpolation and binary search, giving most of the weight to interpolation.&lt;br /&gt;
&lt;br /&gt;
;hi, hi_pd: file position and timestamp of the top edge of the binary search.&lt;br /&gt;
;lo, lo_pd: file position and timestamp of the bottom edge of the binary search.&lt;br /&gt;
;time_pos: Requested pts.&lt;br /&gt;
;guess: begginning of linear search for syncpoint.&lt;br /&gt;
&lt;br /&gt;
 #define INTERPOLATE_WEIGHT (7./8)&lt;br /&gt;
 if (hi - lo &amp;lt; nut-&amp;gt;max_distance*2) guess = lo + 8;&lt;br /&gt;
 else { // linear interpolation&lt;br /&gt;
     double a = (double)(hi - lo) / (hi_pd - lo_pd);&lt;br /&gt;
     guess = lo + a * (time_pos - lo_pd);&lt;br /&gt;
     guess = guess * INTERPOLATE_WEIGHT + (lo+hi)/2 * (1 - INTERPOLATE_WEIGHT);&lt;br /&gt;
     if (hi - guess &amp;lt; nut-&amp;gt;max_distance*2) guess = hi - nut-&amp;gt;max_distance*2; //(lo + hi)/2;&lt;br /&gt;
 }&lt;br /&gt;
 if (guess &amp;lt; lo + 8) guess = lo + 8;&lt;br /&gt;
&lt;br /&gt;
The first conditional prevents too much recursing when the distance is already low. The last conditional prevents infinite loop of syncpoint search constantly finding ''lo'' and achieving nothing.&lt;br /&gt;
&lt;br /&gt;
==== Binary search ====&lt;br /&gt;
Now, find a syncpoint, bounded between ''guess'' and ''hi''. If it has a timestamp higher than requested pts, then replace ''hi'' and ''hi_pd'', otherwise replace ''lo'' and ''lo_pd''.&lt;br /&gt;
If a syncpoint was not found between ''guess'' and ''hi'', then, if ''guess'' is smaller or equal to ''lo + 11'', then you have scanned the entire area between ''lo'' and ''hi'', and your binary search is done. Otherwise, replace ''hi'' with ''guess'' and repeat the binary search.&lt;br /&gt;
&lt;br /&gt;
After finding the 2 closest syncpoints bounding your requested pts, the bounds of linear are search are:&lt;br /&gt;
&lt;br /&gt;
 *start = lo_s.pos - (lo_s.back_ptr * 8 + 7);&lt;br /&gt;
 *end = lo_s.pos;&lt;br /&gt;
 *stopper = hi_s;&lt;br /&gt;
&lt;br /&gt;
''stopper'' is used later to end linear search prematurely. Note that it is the '''top''' edge of binary search, meaning, it has a timestamp higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Linear search ===&lt;br /&gt;
&lt;br /&gt;
==== Bounds of linear search ====&lt;br /&gt;
Linear search of course ends at ''end'', however, it can end earlier:&lt;br /&gt;
* When you find a frame of any stream, with a dts higher than requested pts.&lt;br /&gt;
* When you find a frame for '''all''' active streams with a pts higher than requested pts.&lt;br /&gt;
* When you find a syncpoint immediately following the syncpoint pointed to by ''stopper'''s back_ptr, (from here on this syncpoint will be called ''stopper_syncpoint'') '''and''' all streams are active.&lt;br /&gt;
* When you reach ''stopper_syncpoint'', and you have not found a keyframe for any '''non'''-active between ''stopper''&amp;lt;nowiki&amp;gt;'&amp;lt;/nowiki&amp;gt;s back_ptr and ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp''. The reason for this is that ''stopper'' did not point because to ''stopper_syncpoint'' can only be because of active stream keyframes, and not non active ones.&lt;br /&gt;
* When you find a keyframe for all '''non'''-active streams after ''stopper_syncpoint'' with a pts lower than ''stopper.timestamp'', which had a keyframe in the region in the previous condition. The logic is:&lt;br /&gt;
** ''stopper.timestamp'' is higher than requested pts.&lt;br /&gt;
** ''stopper_syncpoint'' is '''not''' the syncpoint pointed to by ''stopper.back_ptr'', but the one immediately following.&lt;br /&gt;
** If there was a keyframe for every non active stream after ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp'', then the reason ''stopper'' does not point to ''stopper_syncpoint'' must be that there are no keyframes for '''active''' streams with a pts lower than ''stopper.timestamp'' after ''stopper_syncpoint''.&lt;br /&gt;
** There might be more keyframes in the region with a pts higher than ''stopper.timestamp'', but those are irrelevant because they are higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
==== Linear search implementation ====&lt;br /&gt;
&lt;br /&gt;
# Start at ''start''.&lt;br /&gt;
# Search for syncpoint. If it is further than ''start + 7'', then the file is errored, and you can start playing immediately from this syncpoint.&lt;br /&gt;
# Perform full demuxing, buffering everything read. If you encounter any NUT error during demuxing, seek back to the syncpoint after ''start'' and end seek.&lt;br /&gt;
# On every syncpoint, flush the buffer and cache the syncpoint position.&lt;br /&gt;
#* If this syncpoint is ''stopper_syncpoint'', then do not flush the buffer, as it would be possible the linear search would end immediatelty afterwards and a second underlying seek would not be necessary.&lt;br /&gt;
# When finding keyframe of active stream with pts lower than requested pts, store position of keyframe. Discard previous value.&lt;br /&gt;
# End linear search as necessary by bounds given above.&lt;br /&gt;
# Pick the lowest value from positions of keyframes for active streams. This is the final position.&lt;br /&gt;
# Seek to closest syncpoint before the final position, preform a minimal demuxing until final position (to get proper last_pts context across all streams).&lt;br /&gt;
#* With luck this seek will not need an underlying seek, if you have not flushed the buffer since the requested position.&lt;br /&gt;
#* In most common case, ''stopper.back_ptr'' points to same syncpoint as the start of the linear search, as both syncpoints point to the same rare video keyframe.&lt;br /&gt;
#* If only video stream is active and the only non active stream is audio, you will most likely end your linear search immediately after ''stopper_syncpoint'' by finding an audio keyframe. Afterwards you will rewind right back to ''start'', and, since buffer hasn't been flushed, this will not need an underlying seek.&lt;br /&gt;
&lt;br /&gt;
=== Index ===&lt;br /&gt;
With index, binary search step is skipped, and a much more limited linear search used, between two immediate syncpoints. The syncpoint picked is the highest possible one that has a keyframe for each active stream past the syncpoint with a pts lower than requested pts. The end of the linear search is the syncpoint immediately following.&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Index ===&lt;br /&gt;
Create the index in the same manner as creating the index in the muxer, remembering keyframes and EOR at syncpoint positions.&lt;br /&gt;
With one big difference - dynamic index can have gaps, thanks to seeking. Every syncpiont entry in the dynamic index has a flag indicating if it has a &amp;quot;unresearched region&amp;quot; gap from last syncpoint.&lt;br /&gt;
&lt;br /&gt;
In seeking, dynamic index is used in the same manner as complete index. However, when deciding a syncpoint, the entire range of the syncpoint picked until the first syncpoint with a pts higher than requested is checked for having been already researched. If a &amp;quot;hole&amp;quot; is found anywhere in this range, dynamic index is disregarded and full binary search is performed.&lt;br /&gt;
&lt;br /&gt;
=== End of Relavence ===&lt;br /&gt;
Behavior with linear search:&lt;br /&gt;
* Treat EOR frames same as keyframes. Seeing an EOR frame for an active stream causes the stream to be ignored until the next keyframe of same stream.&lt;br /&gt;
* If all active streams are EOR by end of linear search, just use start of linear search as final seeking position.&lt;br /&gt;
&lt;br /&gt;
For index:&lt;br /&gt;
* When picking the correct syncpoint to start linear search, ignore streams which have EOR with pts lower than requested pts and no keyframe with pts lower than requested pts.&lt;br /&gt;
* If all active streams are EOR, pick the syncpoint immediately before the syncpoint with the last EOR across all streams with pts lower than requested pts.&lt;br /&gt;
&lt;br /&gt;
[[Category:Container Formats]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=2410</id>
		<title>NUT</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=2410"/>
		<updated>2006-02-25T07:34:35Z</updated>

		<summary type="html">&lt;p&gt;Ods15: /* Bounds of linear search */  Another condition for stopping linear search&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Extensions: nut&lt;br /&gt;
* Website: http://www.nut.hu/&lt;br /&gt;
&lt;br /&gt;
NUT is a container format under construction by [[MPlayer]] and [[FFmpeg]] developers.&lt;br /&gt;
Its main goals are to be simple, flexible and error-resistant while maintaining the smallest possible overhead.&lt;br /&gt;
&lt;br /&gt;
== NUT seeking algo in libnut ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Binary search and linear interpolation ===&lt;br /&gt;
&lt;br /&gt;
==== Startup ====&lt;br /&gt;
Go to beginning of file if first syncpoint has not been found, and then go to EOF and search backward to find last syncpoint.&lt;br /&gt;
Pick the closest possible syncpoints for requested pts from syncpoint cache, one higher and one lower. If requested pts is lower than first syncpoint or higher than last syncpoint, then seek to either of those syncpoints and end seek.&lt;br /&gt;
&lt;br /&gt;
Binary search is ended when the entire region between the 2 syncpoints picked has been scanned. Which could even be before it has begun thanks to syncpoint cache.&lt;br /&gt;
&lt;br /&gt;
==== Guess position ====&lt;br /&gt;
Best results have been achieved by combining both linear interpolation and binary search, giving most of the weight to interpolation.&lt;br /&gt;
&lt;br /&gt;
;hi, hi_pd: file position and timestamp of the top edge of the binary search.&lt;br /&gt;
;lo, lo_pd: file position and timestamp of the bottom edge of the binary search.&lt;br /&gt;
;time_pos: Requested pts.&lt;br /&gt;
;guess: begginning of linear search for syncpoint.&lt;br /&gt;
&lt;br /&gt;
 #define INTERPOLATE_WEIGHT (7./8)&lt;br /&gt;
 if (hi - lo &amp;lt; nut-&amp;gt;max_distance*2) guess = lo + 8;&lt;br /&gt;
 else { // linear interpolation&lt;br /&gt;
     double a = (double)(hi - lo) / (hi_pd - lo_pd);&lt;br /&gt;
     guess = lo + a * (time_pos - lo_pd);&lt;br /&gt;
     guess = guess * INTERPOLATE_WEIGHT + (lo+hi)/2 * (1 - INTERPOLATE_WEIGHT);&lt;br /&gt;
     if (hi - guess &amp;lt; nut-&amp;gt;max_distance*2) guess = hi - nut-&amp;gt;max_distance*2; //(lo + hi)/2;&lt;br /&gt;
 }&lt;br /&gt;
 if (guess &amp;lt; lo + 8) guess = lo + 8;&lt;br /&gt;
&lt;br /&gt;
The first conditional prevents too much recursing when the distance is already low. The last conditional prevents infinite loop of syncpoint search constantly finding ''lo'' and achieving nothing.&lt;br /&gt;
&lt;br /&gt;
==== Binary search ====&lt;br /&gt;
Now, find a syncpoint, bounded between ''guess'' and ''hi''. If it has a timestamp higher than requested pts, then replace ''hi'' and ''hi_pd'', otherwise replace ''lo'' and ''lo_pd''.&lt;br /&gt;
If a syncpoint was not found between ''guess'' and ''hi'', then, if ''guess'' is smaller or equal to ''lo + 11'', then you have scanned the entire area between ''lo'' and ''hi'', and your binary search is done. Otherwise, replace ''hi'' with ''guess'' and repeat the binary search.&lt;br /&gt;
&lt;br /&gt;
After finding the 2 closest syncpoints bounding your requested pts, the bounds of linear are search are:&lt;br /&gt;
&lt;br /&gt;
 *start = lo_s.pos - (lo_s.back_ptr * 8 + 7);&lt;br /&gt;
 *end = lo_s.pos;&lt;br /&gt;
 *stopper = hi_s;&lt;br /&gt;
&lt;br /&gt;
''stopper'' is used later to end linear search prematurely. Note that it is the '''top''' edge of binary search, meaning, it has a timestamp higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Linear search ===&lt;br /&gt;
&lt;br /&gt;
==== Bounds of linear search ====&lt;br /&gt;
Linear search of course ends at ''end'', however, it can end earlier:&lt;br /&gt;
* When you find a frame of any stream, with a dts higher than requested pts.&lt;br /&gt;
* When you find a frame for '''all''' active streams with a pts higher than requested pts.&lt;br /&gt;
* When you find a syncpoint immediately following the syncpoint pointed to by ''stopper'''s back_ptr, (from here on this syncpoint will be called ''stopper_syncpoint'') '''and''' all streams are active.&lt;br /&gt;
* When you reach ''stopper_syncpoint'', and you have not found a keyframe for any '''non'''-active between ''stopper'''s back_ptr and ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp''. The reason for this is that ''stopper'' did not point because to ''stopper_syncpoint'' can only be because of active stream keyframes, and not non active ones.&lt;br /&gt;
* When you find a keyframe for all '''non'''-active streams after ''stopper_syncpoint'' with a pts lower than ''stopper.timestamp'', which had a keyframe in the region in the previous condition. The logic is:&lt;br /&gt;
** ''stopper.timestamp'' is higher than requested pts.&lt;br /&gt;
** ''stopper_syncpoint'' is '''not''' the syncpoint pointed to by ''stopper.back_ptr'', but the one immediately following.&lt;br /&gt;
** If there was a keyframe for every non active stream after ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp'', then the reason ''stopper'' does not point to ''stopper_syncpoint'' must be that there are no keyframes for '''active''' streams with a pts lower than ''stopper.timestamp'' after ''stopper_syncpoint''.&lt;br /&gt;
** There might be more keyframes in the region with a pts higher than ''stopper.timestamp'', but those are irrelevant because they are higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
==== Linear search implementation ====&lt;br /&gt;
&lt;br /&gt;
# Start at ''start''.&lt;br /&gt;
# Search for syncpoint. If it is further than ''start + 7'', then the file is errored, and you can start playing immediately from this syncpoint.&lt;br /&gt;
# Perform full demuxing, buffering everything read. If you encounter any NUT error during demuxing, seek back to the syncpoint after ''start'' and end seek.&lt;br /&gt;
# On every syncpoint, flush the buffer and cache the syncpoint position.&lt;br /&gt;
#* If this syncpoint is ''stopper_syncpoint'', then do not flush the buffer, as it would be possible the linear search would end immediatelty afterwards and a second underlying seek would not be necessary.&lt;br /&gt;
# When finding keyframe of active stream with pts lower than requested pts, store position of keyframe. Discard previous value.&lt;br /&gt;
# End linear search as necessary by bounds given above.&lt;br /&gt;
# Pick the lowest value from positions of keyframes for active streams. This is the final position.&lt;br /&gt;
# Seek to closest syncpoint before the final position, preform a minimal demuxing until final position (to get proper last_pts context across all streams).&lt;br /&gt;
#* With luck this seek will not need an underlying seek, if you have not flushed the buffer since the requested position.&lt;br /&gt;
#* In most common case, ''stopper.back_ptr'' points to same syncpoint as the start of the linear search, as both syncpoints point to the same rare video keyframe.&lt;br /&gt;
#* If only video stream is active and the only non active stream is audio, you will most likely end your linear search immediately after ''stopper_syncpoint'' by finding an audio keyframe. Afterwards you will rewind right back to ''start'', and, since buffer hasn't been flushed, this will not need an underlying seek.&lt;br /&gt;
&lt;br /&gt;
=== Index ===&lt;br /&gt;
With index, binary search step is skipped, and a much more limited linear search used, between two immediate syncpoints. The syncpoint picked is the highest possible one that has a keyframe for each active stream past the syncpoint with a pts lower than requested pts. The end of the linear search is the syncpoint immediately following.&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Index ===&lt;br /&gt;
Create the index in the same manner as creating the index in the muxer, remembering keyframes and EOR at syncpoint positions.&lt;br /&gt;
With one big difference - dynamic index can have gaps, thanks to seeking. Every syncpiont entry in the dynamic index has a flag indicating if it has a &amp;quot;unresearched region&amp;quot; gap from last syncpoint.&lt;br /&gt;
&lt;br /&gt;
In seeking, dynamic index is used in the same manner as complete index. However, when deciding a syncpoint, the entire range of the syncpoint picked until the first syncpoint with a pts higher than requested is checked for having been already researched. If a &amp;quot;hole&amp;quot; is found anywhere in this range, dynamic index is disregarded and full binary search is performed.&lt;br /&gt;
&lt;br /&gt;
=== End of Relavence ===&lt;br /&gt;
Behavior with linear search:&lt;br /&gt;
* Treat EOR frames same as keyframes. Seeing an EOR frame for an active stream causes the stream to be ignored until the next keyframe of same stream.&lt;br /&gt;
* If all active streams are EOR by end of linear search, just use start of linear search as final seeking position.&lt;br /&gt;
&lt;br /&gt;
For index:&lt;br /&gt;
* When picking the correct syncpoint to start linear search, ignore streams which have EOR with pts lower than requested pts and no keyframe with pts lower than requested pts.&lt;br /&gt;
* If all active streams are EOR, pick the syncpoint immediately before the syncpoint with the last EOR across all streams with pts lower than requested pts.&lt;br /&gt;
&lt;br /&gt;
[[Category:Container Formats]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=2400</id>
		<title>NUT</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=2400"/>
		<updated>2006-02-24T19:22:23Z</updated>

		<summary type="html">&lt;p&gt;Ods15: Dynamic index and EOR&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Extensions: nut&lt;br /&gt;
* Website: http://www.nut.hu/&lt;br /&gt;
&lt;br /&gt;
NUT is a container format under construction by [[MPlayer]] and [[FFmpeg]] developers.&lt;br /&gt;
Its main goals are to be simple, flexible and error-resistant while maintaining the smallest possible overhead.&lt;br /&gt;
&lt;br /&gt;
== NUT seeking algo in libnut ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Binary search and linear interpolation ===&lt;br /&gt;
&lt;br /&gt;
==== Startup ====&lt;br /&gt;
Go to beginning of file if first syncpoint has not been found, and then go to EOF and search backward to find last syncpoint.&lt;br /&gt;
Pick the closest possible syncpoints for requested pts from syncpoint cache, one higher and one lower. If requested pts is lower than first syncpoint or higher than last syncpoint, then seek to either of those syncpoints and end seek.&lt;br /&gt;
&lt;br /&gt;
Binary search is ended when the entire region between the 2 syncpoints picked has been scanned. Which could even be before it has begun thanks to syncpoint cache.&lt;br /&gt;
&lt;br /&gt;
==== Guess position ====&lt;br /&gt;
Best results have been achieved by combining both linear interpolation and binary search, giving most of the weight to interpolation.&lt;br /&gt;
&lt;br /&gt;
;hi, hi_pd: file position and timestamp of the top edge of the binary search.&lt;br /&gt;
;lo, lo_pd: file position and timestamp of the bottom edge of the binary search.&lt;br /&gt;
;time_pos: Requested pts.&lt;br /&gt;
;guess: begginning of linear search for syncpoint.&lt;br /&gt;
&lt;br /&gt;
 #define INTERPOLATE_WEIGHT (7./8)&lt;br /&gt;
 if (hi - lo &amp;lt; nut-&amp;gt;max_distance*2) guess = lo + 8;&lt;br /&gt;
 else { // linear interpolation&lt;br /&gt;
     double a = (double)(hi - lo) / (hi_pd - lo_pd);&lt;br /&gt;
     guess = lo + a * (time_pos - lo_pd);&lt;br /&gt;
     guess = guess * INTERPOLATE_WEIGHT + (lo+hi)/2 * (1 - INTERPOLATE_WEIGHT);&lt;br /&gt;
     if (hi - guess &amp;lt; nut-&amp;gt;max_distance*2) guess = hi - nut-&amp;gt;max_distance*2; //(lo + hi)/2;&lt;br /&gt;
 }&lt;br /&gt;
 if (guess &amp;lt; lo + 8) guess = lo + 8;&lt;br /&gt;
&lt;br /&gt;
The first conditional prevents too much recursing when the distance is already low. The last conditional prevents infinite loop of syncpoint search constantly finding ''lo'' and achieving nothing.&lt;br /&gt;
&lt;br /&gt;
==== Binary search ====&lt;br /&gt;
Now, find a syncpoint, bounded between ''guess'' and ''hi''. If it has a timestamp higher than requested pts, then replace ''hi'' and ''hi_pd'', otherwise replace ''lo'' and ''lo_pd''.&lt;br /&gt;
If a syncpoint was not found between ''guess'' and ''hi'', then, if ''guess'' is smaller or equal to ''lo + 11'', then you have scanned the entire area between ''lo'' and ''hi'', and your binary search is done. Otherwise, replace ''hi'' with ''guess'' and repeat the binary search.&lt;br /&gt;
&lt;br /&gt;
After finding the 2 closest syncpoints bounding your requested pts, the bounds of linear are search are:&lt;br /&gt;
&lt;br /&gt;
 *start = lo_s.pos - (lo_s.back_ptr * 8 + 7);&lt;br /&gt;
 *end = lo_s.pos;&lt;br /&gt;
 *stopper = hi_s;&lt;br /&gt;
&lt;br /&gt;
''stopper'' is used later to end linear search prematurely. Note that it is the '''top''' edge of binary search, meaning, it has a timestamp higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Linear search ===&lt;br /&gt;
&lt;br /&gt;
==== Bounds of linear search ====&lt;br /&gt;
Linear search of course ends at ''end'', however, it can end earlier:&lt;br /&gt;
* When you find a frame of any stream, with a dts higher than requested pts.&lt;br /&gt;
* When you find a frame for '''all''' active streams with a pts higher than requested pts.&lt;br /&gt;
* When you find a syncpoint immediately following the syncpoint pointed to by ''stopper'''s back_ptr, (from here on this syncpoint will be called ''stopper_syncpoint'') '''and''' all streams are active.&lt;br /&gt;
* When you find a keyframe for all '''non'''-active streams after ''stopper_syncpoint'' with a pts lower than ''stopper.timestamp''. The logic is:&lt;br /&gt;
** ''stopper.timestamp'' is higher than requested pts.&lt;br /&gt;
** ''stopper_syncpoint'' is '''not''' the syncpoint pointed to by ''stopper.back_ptr'', but the one immediately following.&lt;br /&gt;
** If there was a keyframe for every non active stream after ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp'', then the reason ''stopper'' does not point to ''stopper_syncpoint'' must be that there are no keyframes for '''active''' streams with a pts lower than ''stopper.timestamp'' after ''stopper_syncpoint''.&lt;br /&gt;
** There might be more keyframes in the region with a pts higher than ''stopper.timestamp'', but those are irrelevant because they are higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
==== Linear search implementation ====&lt;br /&gt;
&lt;br /&gt;
# Start at ''start''.&lt;br /&gt;
# Search for syncpoint. If it is further than ''start + 7'', then the file is errored, and you can start playing immediately from this syncpoint.&lt;br /&gt;
# Perform full demuxing, buffering everything read. If you encounter any NUT error during demuxing, seek back to the syncpoint after ''start'' and end seek.&lt;br /&gt;
# On every syncpoint, flush the buffer and cache the syncpoint position.&lt;br /&gt;
#* If this syncpoint is ''stopper_syncpoint'', then do not flush the buffer, as it would be possible the linear search would end immediatelty afterwards and a second underlying seek would not be necessary.&lt;br /&gt;
# When finding keyframe of active stream with pts lower than requested pts, store position of keyframe. Discard previous value.&lt;br /&gt;
# End linear search as necessary by bounds given above.&lt;br /&gt;
# Pick the lowest value from positions of keyframes for active streams. This is the final position.&lt;br /&gt;
# Seek to closest syncpoint before the final position, preform a minimal demuxing until final position (to get proper last_pts context across all streams).&lt;br /&gt;
#* With luck this seek will not need an underlying seek, if you have not flushed the buffer since the requested position.&lt;br /&gt;
#* In most common case, ''stopper.back_ptr'' points to same syncpoint as the start of the linear search, as both syncpoints point to the same rare video keyframe.&lt;br /&gt;
#* If only video stream is active and the only non active stream is audio, you will most likely end your linear search immediately after ''stopper_syncpoint'' by finding an audio keyframe. Afterwards you will rewind right back to ''start'', and, since buffer hasn't been flushed, this will not need an underlying seek.&lt;br /&gt;
&lt;br /&gt;
=== Index ===&lt;br /&gt;
With index, binary search step is skipped, and a much more limited linear search used, between two immediate syncpoints. The syncpoint picked is the highest possible one that has a keyframe for each active stream past the syncpoint with a pts lower than requested pts. The end of the linear search is the syncpoint immediately following.&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Index ===&lt;br /&gt;
Create the index in the same manner as creating the index in the muxer, remembering keyframes and EOR at syncpoint positions.&lt;br /&gt;
With one big difference - dynamic index can have gaps, thanks to seeking. Every syncpiont entry in the dynamic index has a flag indicating if it has a &amp;quot;unresearched region&amp;quot; gap from last syncpoint.&lt;br /&gt;
&lt;br /&gt;
In seeking, dynamic index is used in the same manner as complete index. However, when deciding a syncpoint, the entire range of the syncpoint picked until the first syncpoint with a pts higher than requested is checked for having been already researched. If a &amp;quot;hole&amp;quot; is found anywhere in this range, dynamic index is disregarded and full binary search is performed.&lt;br /&gt;
&lt;br /&gt;
=== End of Relavence ===&lt;br /&gt;
Behavior with linear search:&lt;br /&gt;
* Treat EOR frames same as keyframes. Seeing an EOR frame for an active stream causes the stream to be ignored until the next keyframe of same stream.&lt;br /&gt;
* If all active streams are EOR by end of linear search, just use start of linear search as final seeking position.&lt;br /&gt;
&lt;br /&gt;
For index:&lt;br /&gt;
* When picking the correct syncpoint to start linear search, ignore streams which have EOR with pts lower than requested pts and no keyframe with pts lower than requested pts.&lt;br /&gt;
* If all active streams are EOR, pick the syncpoint immediately before the syncpoint with the last EOR across all streams with pts lower than requested pts.&lt;br /&gt;
&lt;br /&gt;
[[Category:Container Formats]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=User_talk:Snacky&amp;diff=2002</id>
		<title>User talk:Snacky</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=User_talk:Snacky&amp;diff=2002"/>
		<updated>2006-02-03T20:54:13Z</updated>

		<summary type="html">&lt;p&gt;Ods15: that redirect probably doesn't belong there&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1965</id>
		<title>NUT</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1965"/>
		<updated>2006-02-02T08:48:43Z</updated>

		<summary type="html">&lt;p&gt;Ods15: /* Bounds of linear search */  typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Extensions: nut&lt;br /&gt;
* Website: http://www.nut.hu/&lt;br /&gt;
&lt;br /&gt;
NUT is a container format under construction by [[MPlayer]] and [[FFmpeg]] developers.&lt;br /&gt;
Its main goals are to be simple, flexible and error-resistant while maintaining the smallest possible overhead.&lt;br /&gt;
&lt;br /&gt;
== NUT seeking algo in libnut ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Binary search and linear interpolation ===&lt;br /&gt;
&lt;br /&gt;
==== Startup ====&lt;br /&gt;
Go to beginning of file if first syncpoint has not been found, and then go to EOF and search backward to find last syncpoint.&lt;br /&gt;
Pick the closest possible syncpoints for requested pts from syncpoint cache, one higher and one lower. If requested pts is lower than first syncpoint or higher than last syncpoint, then seek to either of those syncpoints and end seek.&lt;br /&gt;
&lt;br /&gt;
Binary search is ended when the entire region between the 2 syncpoints picked has been scanned. Which could even be before it has begun thanks to syncpoint cache.&lt;br /&gt;
&lt;br /&gt;
==== Guess position ====&lt;br /&gt;
Best results have been achieved by combining both linear interpolation and binary search, giving most of the weight to interpolation.&lt;br /&gt;
&lt;br /&gt;
;hi, hi_pd: file position and timestamp of the top edge of the binary search.&lt;br /&gt;
;lo, lo_pd: file position and timestamp of the bottom edge of the binary search.&lt;br /&gt;
;time_pos: Requested pts.&lt;br /&gt;
;guess: begginning of linear search for syncpoint.&lt;br /&gt;
&lt;br /&gt;
 #define INTERPOLATE_WEIGHT (7./8)&lt;br /&gt;
 if (hi - lo &amp;lt; nut-&amp;gt;max_distance*2) guess = lo + 8;&lt;br /&gt;
 else { // linear interpolation&lt;br /&gt;
     double a = (double)(hi - lo) / (hi_pd - lo_pd);&lt;br /&gt;
     guess = lo + a * (time_pos - lo_pd);&lt;br /&gt;
     guess = guess * INTERPOLATE_WEIGHT + (lo+hi)/2 * (1 - INTERPOLATE_WEIGHT);&lt;br /&gt;
     if (hi - guess &amp;lt; nut-&amp;gt;max_distance*2) guess = hi - nut-&amp;gt;max_distance*2; //(lo + hi)/2;&lt;br /&gt;
 }&lt;br /&gt;
 if (guess &amp;lt; lo + 8) guess = lo + 8;&lt;br /&gt;
&lt;br /&gt;
The first conditional prevents too much recursing when the distance is already low. The last conditional prevents infinite loop of syncpoint search constantly finding ''lo'' and achieving nothing.&lt;br /&gt;
&lt;br /&gt;
==== Binary search ====&lt;br /&gt;
Now, find a syncpoint, bounded between ''guess'' and ''hi''. If it has a timestamp higher than requested pts, then replace ''hi'' and ''hi_pd'', otherwise replace ''lo'' and ''lo_pd''.&lt;br /&gt;
If a syncpoint was not found between ''guess'' and ''hi'', then, if ''guess'' is smaller or equal to ''lo + 11'', then you have scanned the entire area between ''lo'' and ''hi'', and your binary search is done. Otherwise, replace ''hi'' with ''guess'' and repeat the binary search.&lt;br /&gt;
&lt;br /&gt;
After finding the 2 closest syncpoints bounding your requested pts, the bounds of linear are search are:&lt;br /&gt;
&lt;br /&gt;
 *start = lo_s.pos - (lo_s.back_ptr * 8 + 7);&lt;br /&gt;
 *end = lo_s.pos;&lt;br /&gt;
 *stopper = hi_s;&lt;br /&gt;
&lt;br /&gt;
''stopper'' is used later to end linear search prematurely. Note that it is the '''top''' edge of binary search, meaning, it has a timestamp higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Linear search ===&lt;br /&gt;
&lt;br /&gt;
==== Bounds of linear search ====&lt;br /&gt;
Linear search of course ends at ''end'', however, it can end earlier:&lt;br /&gt;
* When you find a frame of any stream, with a dts higher than requested pts.&lt;br /&gt;
* When you find a frame for '''all''' active streams with a pts higher than requested pts.&lt;br /&gt;
* When you find a syncpoint immediately following the syncpoint pointed to by ''stopper'''s back_ptr, (from here on this syncpoint will be called ''stopper_syncpoint'') '''and''' all streams are active.&lt;br /&gt;
* When you find a keyframe for all '''non'''-active streams after ''stopper_syncpoint'' with a pts lower than ''stopper.timestamp''. The logic is:&lt;br /&gt;
** ''stopper.timestamp'' is higher than requested pts.&lt;br /&gt;
** ''stopper_syncpoint'' is '''not''' the syncpoint pointed to by ''stopper.back_ptr'', but the one immediately following.&lt;br /&gt;
** If there was a keyframe for every non active stream after ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp'', then the reason ''stopper'' does not point to ''stopper_syncpoint'' must be that there are no keyframes for '''active''' streams with a pts lower than ''stopper.timestamp'' after ''stopper_syncpoint''.&lt;br /&gt;
** There might be more keyframes in the region with a pts higher than ''stopper.timestamp'', but those are irrelevant because they are higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
==== Linear search implementation ====&lt;br /&gt;
&lt;br /&gt;
# Start at ''start''.&lt;br /&gt;
# Search for syncpoint. If it is further than ''start + 7'', then the file is errored, and you can start playing immediately from this syncpoint.&lt;br /&gt;
# Perform full demuxing, buffering everything read. If you encounter any NUT error during demuxing, seek back to the syncpoint after ''start'' and end seek.&lt;br /&gt;
# On every syncpoint, flush the buffer and cache the syncpoint position.&lt;br /&gt;
#* If this syncpoint is ''stopper_syncpoint'', then do not flush the buffer, as it would be possible the linear search would end immediatelty afterwards and a second underlying seek would not be necessary.&lt;br /&gt;
# When finding keyframe of active stream with pts lower than requested pts, store position of keyframe. Discard previous value.&lt;br /&gt;
# End linear search as necessary by bounds given above.&lt;br /&gt;
# Pick the lowest value from positions of keyframes for active streams. This is the final position.&lt;br /&gt;
# Seek to closest syncpoint before the final position, preform a minimal demuxing until final position (to get proper last_pts context across all streams).&lt;br /&gt;
#* With luck this seek will not need an underlying seek, if you have not flushed the buffer since the requested position.&lt;br /&gt;
#* In most common case, ''stopper.back_ptr'' points to same syncpoint as the start of the linear search, as both syncpoints point to the same rare video keyframe.&lt;br /&gt;
#* If only video stream is active and the only non active stream is audio, you will most likely end your linear search immediately after ''stopper_syncpoint'' by finding an audio keyframe. Afterwards you will rewind right back to ''start'', and, since buffer hasn't been flushed, this will not need an underlying seek.&lt;br /&gt;
&lt;br /&gt;
=== Index ===&lt;br /&gt;
With index, binary search step is skipped, and a much more limited linear search used, between two immediate syncpoints. The syncpoint picked is the highest possible one that has a keyframe for each active stream past the syncpoint with a pts lower than requested pts. The end of the linear search is the syncpoint immediately following.&lt;br /&gt;
&lt;br /&gt;
Dynamic index is used in the same manner as complete index. However, when deciding a syncpoint, the entire range of the syncpoint picked until the first syncpoint with a pts higher than requested is checked for having been already researched. If a &amp;quot;hole&amp;quot; is found anywhere in this range, dynamic index is disregarded and full binary search is performed.&lt;br /&gt;
&lt;br /&gt;
[[Category:Container Formats]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1964</id>
		<title>NUT</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1964"/>
		<updated>2006-02-02T08:02:03Z</updated>

		<summary type="html">&lt;p&gt;Ods15: /* Guess position */  libnut changed, max_distance*2&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Extensions: nut&lt;br /&gt;
* Website: http://www.nut.hu/&lt;br /&gt;
&lt;br /&gt;
NUT is a container format under construction by [[MPlayer]] and [[FFmpeg]] developers.&lt;br /&gt;
Its main goals are to be simple, flexible and error-resistant while maintaining the smallest possible overhead.&lt;br /&gt;
&lt;br /&gt;
== NUT seeking algo in libnut ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Binary search and linear interpolation ===&lt;br /&gt;
&lt;br /&gt;
==== Startup ====&lt;br /&gt;
Go to beginning of file if first syncpoint has not been found, and then go to EOF and search backward to find last syncpoint.&lt;br /&gt;
Pick the closest possible syncpoints for requested pts from syncpoint cache, one higher and one lower. If requested pts is lower than first syncpoint or higher than last syncpoint, then seek to either of those syncpoints and end seek.&lt;br /&gt;
&lt;br /&gt;
Binary search is ended when the entire region between the 2 syncpoints picked has been scanned. Which could even be before it has begun thanks to syncpoint cache.&lt;br /&gt;
&lt;br /&gt;
==== Guess position ====&lt;br /&gt;
Best results have been achieved by combining both linear interpolation and binary search, giving most of the weight to interpolation.&lt;br /&gt;
&lt;br /&gt;
;hi, hi_pd: file position and timestamp of the top edge of the binary search.&lt;br /&gt;
;lo, lo_pd: file position and timestamp of the bottom edge of the binary search.&lt;br /&gt;
;time_pos: Requested pts.&lt;br /&gt;
;guess: begginning of linear search for syncpoint.&lt;br /&gt;
&lt;br /&gt;
 #define INTERPOLATE_WEIGHT (7./8)&lt;br /&gt;
 if (hi - lo &amp;lt; nut-&amp;gt;max_distance*2) guess = lo + 8;&lt;br /&gt;
 else { // linear interpolation&lt;br /&gt;
     double a = (double)(hi - lo) / (hi_pd - lo_pd);&lt;br /&gt;
     guess = lo + a * (time_pos - lo_pd);&lt;br /&gt;
     guess = guess * INTERPOLATE_WEIGHT + (lo+hi)/2 * (1 - INTERPOLATE_WEIGHT);&lt;br /&gt;
     if (hi - guess &amp;lt; nut-&amp;gt;max_distance*2) guess = hi - nut-&amp;gt;max_distance*2; //(lo + hi)/2;&lt;br /&gt;
 }&lt;br /&gt;
 if (guess &amp;lt; lo + 8) guess = lo + 8;&lt;br /&gt;
&lt;br /&gt;
The first conditional prevents too much recursing when the distance is already low. The last conditional prevents infinite loop of syncpoint search constantly finding ''lo'' and achieving nothing.&lt;br /&gt;
&lt;br /&gt;
==== Binary search ====&lt;br /&gt;
Now, find a syncpoint, bounded between ''guess'' and ''hi''. If it has a timestamp higher than requested pts, then replace ''hi'' and ''hi_pd'', otherwise replace ''lo'' and ''lo_pd''.&lt;br /&gt;
If a syncpoint was not found between ''guess'' and ''hi'', then, if ''guess'' is smaller or equal to ''lo + 11'', then you have scanned the entire area between ''lo'' and ''hi'', and your binary search is done. Otherwise, replace ''hi'' with ''guess'' and repeat the binary search.&lt;br /&gt;
&lt;br /&gt;
After finding the 2 closest syncpoints bounding your requested pts, the bounds of linear are search are:&lt;br /&gt;
&lt;br /&gt;
 *start = lo_s.pos - (lo_s.back_ptr * 8 + 7);&lt;br /&gt;
 *end = lo_s.pos;&lt;br /&gt;
 *stopper = hi_s;&lt;br /&gt;
&lt;br /&gt;
''stopper'' is used later to end linear search prematurely. Note that it is the '''top''' edge of binary search, meaning, it has a timestamp higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Linear search ===&lt;br /&gt;
&lt;br /&gt;
==== Bounds of linear search ====&lt;br /&gt;
Linear search of course ends at ''end'', however, it can end earlier:&lt;br /&gt;
* When you find a frame of any stream, with a dts higher than requested pts.&lt;br /&gt;
* When you find a frame for '''all''' active streams with a pts higher than requested pts.&lt;br /&gt;
* When you find a syncpoint immediately following the syncpoint pointed to by ''stopper'''s back_ptr, (from here on this syncpoint will be called ''stopper_syncpoint'') '''and''' all streams are active.&lt;br /&gt;
* When you find a keyframe for all '''non'''-active streams after after ''stopper_syncpoint'' with a pts lower than ''stopper.timestamp''. The logic is:&lt;br /&gt;
** ''stopper.timestamp'' is higher than requested pts.&lt;br /&gt;
** ''stopper_syncpoint'' is '''not''' the syncpoint pointed to by ''stopper.back_ptr'', but the one immediately following.&lt;br /&gt;
** If there was a keyframe for every non active stream after ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp'', then the reason ''stopper'' does not point to ''stopper_syncpoint'' must be that there are no keyframes for '''active''' streams with a pts lower than ''stopper.timestamp'' after ''stopper_syncpoint''.&lt;br /&gt;
** There might be more keyframes in the region with a pts higher than ''stopper.timestamp'', but those are irrelevant because they are higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
==== Linear search implementation ====&lt;br /&gt;
&lt;br /&gt;
# Start at ''start''.&lt;br /&gt;
# Search for syncpoint. If it is further than ''start + 7'', then the file is errored, and you can start playing immediately from this syncpoint.&lt;br /&gt;
# Perform full demuxing, buffering everything read. If you encounter any NUT error during demuxing, seek back to the syncpoint after ''start'' and end seek.&lt;br /&gt;
# On every syncpoint, flush the buffer and cache the syncpoint position.&lt;br /&gt;
#* If this syncpoint is ''stopper_syncpoint'', then do not flush the buffer, as it would be possible the linear search would end immediatelty afterwards and a second underlying seek would not be necessary.&lt;br /&gt;
# When finding keyframe of active stream with pts lower than requested pts, store position of keyframe. Discard previous value.&lt;br /&gt;
# End linear search as necessary by bounds given above.&lt;br /&gt;
# Pick the lowest value from positions of keyframes for active streams. This is the final position.&lt;br /&gt;
# Seek to closest syncpoint before the final position, preform a minimal demuxing until final position (to get proper last_pts context across all streams).&lt;br /&gt;
#* With luck this seek will not need an underlying seek, if you have not flushed the buffer since the requested position.&lt;br /&gt;
#* In most common case, ''stopper.back_ptr'' points to same syncpoint as the start of the linear search, as both syncpoints point to the same rare video keyframe.&lt;br /&gt;
#* If only video stream is active and the only non active stream is audio, you will most likely end your linear search immediately after ''stopper_syncpoint'' by finding an audio keyframe. Afterwards you will rewind right back to ''start'', and, since buffer hasn't been flushed, this will not need an underlying seek.&lt;br /&gt;
&lt;br /&gt;
=== Index ===&lt;br /&gt;
With index, binary search step is skipped, and a much more limited linear search used, between two immediate syncpoints. The syncpoint picked is the highest possible one that has a keyframe for each active stream past the syncpoint with a pts lower than requested pts. The end of the linear search is the syncpoint immediately following.&lt;br /&gt;
&lt;br /&gt;
Dynamic index is used in the same manner as complete index. However, when deciding a syncpoint, the entire range of the syncpoint picked until the first syncpoint with a pts higher than requested is checked for having been already researched. If a &amp;quot;hole&amp;quot; is found anywhere in this range, dynamic index is disregarded and full binary search is performed.&lt;br /&gt;
&lt;br /&gt;
[[Category:Container Formats]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1963</id>
		<title>NUT</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1963"/>
		<updated>2006-02-02T07:53:13Z</updated>

		<summary type="html">&lt;p&gt;Ods15: syncpoints have timestamps, not pts.  Bounds of linear search are wrong&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Extensions: nut&lt;br /&gt;
* Website: http://www.nut.hu/&lt;br /&gt;
&lt;br /&gt;
NUT is a container format under construction by [[MPlayer]] and [[FFmpeg]] developers.&lt;br /&gt;
Its main goals are to be simple, flexible and error-resistant while maintaining the smallest possible overhead.&lt;br /&gt;
&lt;br /&gt;
== NUT seeking algo in libnut ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Binary search and linear interpolation ===&lt;br /&gt;
&lt;br /&gt;
==== Startup ====&lt;br /&gt;
Go to beginning of file if first syncpoint has not been found, and then go to EOF and search backward to find last syncpoint.&lt;br /&gt;
Pick the closest possible syncpoints for requested pts from syncpoint cache, one higher and one lower. If requested pts is lower than first syncpoint or higher than last syncpoint, then seek to either of those syncpoints and end seek.&lt;br /&gt;
&lt;br /&gt;
Binary search is ended when the entire region between the 2 syncpoints picked has been scanned. Which could even be before it has begun thanks to syncpoint cache.&lt;br /&gt;
&lt;br /&gt;
==== Guess position ====&lt;br /&gt;
Best results have been achieved by combining both linear interpolation and binary search, giving most of the weight to interpolation.&lt;br /&gt;
&lt;br /&gt;
;hi, hi_pd: file position and timestamp of the top edge of the binary search.&lt;br /&gt;
;lo, lo_pd: file position and timestamp of the bottom edge of the binary search.&lt;br /&gt;
;time_pos: Requested pts.&lt;br /&gt;
;guess: begginning of linear search for syncpoint.&lt;br /&gt;
&lt;br /&gt;
 #define INTERPOLATE_WEIGHT (7./8)&lt;br /&gt;
 if (hi - lo &amp;lt; nut-&amp;gt;max_distance) guess = lo + 8;&lt;br /&gt;
 else { // linear interpolation&lt;br /&gt;
     double a = (double)(hi - lo) / (hi_pd - lo_pd);&lt;br /&gt;
     guess = lo + a * (time_pos - lo_pd);&lt;br /&gt;
     guess = guess * INTERPOLATE_WEIGHT + (lo+hi)/2 * (1 - INTERPOLATE_WEIGHT);&lt;br /&gt;
     if (hi - guess &amp;lt; nut-&amp;gt;max_distance*2) guess = hi - nut-&amp;gt;max_distance*2; //(lo + hi)/2;&lt;br /&gt;
 }&lt;br /&gt;
 if (guess &amp;lt; lo + 8) guess = lo + 8;&lt;br /&gt;
&lt;br /&gt;
The first conditional prevents too much recursing when the distance is already low. The last conditional prevents infinite loop of syncpoint search constantly finding ''lo'' and achieving nothing.&lt;br /&gt;
&lt;br /&gt;
==== Binary search ====&lt;br /&gt;
Now, find a syncpoint, bounded between ''guess'' and ''hi''. If it has a timestamp higher than requested pts, then replace ''hi'' and ''hi_pd'', otherwise replace ''lo'' and ''lo_pd''.&lt;br /&gt;
If a syncpoint was not found between ''guess'' and ''hi'', then, if ''guess'' is smaller or equal to ''lo + 11'', then you have scanned the entire area between ''lo'' and ''hi'', and your binary search is done. Otherwise, replace ''hi'' with ''guess'' and repeat the binary search.&lt;br /&gt;
&lt;br /&gt;
After finding the 2 closest syncpoints bounding your requested pts, the bounds of linear are search are:&lt;br /&gt;
&lt;br /&gt;
 *start = lo_s.pos - (lo_s.back_ptr * 8 + 7);&lt;br /&gt;
 *end = lo_s.pos;&lt;br /&gt;
 *stopper = hi_s;&lt;br /&gt;
&lt;br /&gt;
''stopper'' is used later to end linear search prematurely. Note that it is the '''top''' edge of binary search, meaning, it has a timestamp higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Linear search ===&lt;br /&gt;
&lt;br /&gt;
==== Bounds of linear search ====&lt;br /&gt;
Linear search of course ends at ''end'', however, it can end earlier:&lt;br /&gt;
* When you find a frame of any stream, with a dts higher than requested pts.&lt;br /&gt;
* When you find a frame for '''all''' active streams with a pts higher than requested pts.&lt;br /&gt;
* When you find a syncpoint immediately following the syncpoint pointed to by ''stopper'''s back_ptr, (from here on this syncpoint will be called ''stopper_syncpoint'') '''and''' all streams are active.&lt;br /&gt;
* When you find a keyframe for all '''non'''-active streams after after ''stopper_syncpoint'' with a pts lower than ''stopper.timestamp''. The logic is:&lt;br /&gt;
** ''stopper.timestamp'' is higher than requested pts.&lt;br /&gt;
** ''stopper_syncpoint'' is '''not''' the syncpoint pointed to by ''stopper.back_ptr'', but the one immediately following.&lt;br /&gt;
** If there was a keyframe for every non active stream after ''stopper_syncpoint'', with a pts lower than ''stopper.timestamp'', then the reason ''stopper'' does not point to ''stopper_syncpoint'' must be that there are no keyframes for '''active''' streams with a pts lower than ''stopper.timestamp'' after ''stopper_syncpoint''.&lt;br /&gt;
** There might be more keyframes in the region with a pts higher than ''stopper.timestamp'', but those are irrelevant because they are higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
==== Linear search implementation ====&lt;br /&gt;
&lt;br /&gt;
# Start at ''start''.&lt;br /&gt;
# Search for syncpoint. If it is further than ''start + 7'', then the file is errored, and you can start playing immediately from this syncpoint.&lt;br /&gt;
# Perform full demuxing, buffering everything read. If you encounter any NUT error during demuxing, seek back to the syncpoint after ''start'' and end seek.&lt;br /&gt;
# On every syncpoint, flush the buffer and cache the syncpoint position.&lt;br /&gt;
#* If this syncpoint is ''stopper_syncpoint'', then do not flush the buffer, as it would be possible the linear search would end immediatelty afterwards and a second underlying seek would not be necessary.&lt;br /&gt;
# When finding keyframe of active stream with pts lower than requested pts, store position of keyframe. Discard previous value.&lt;br /&gt;
# End linear search as necessary by bounds given above.&lt;br /&gt;
# Pick the lowest value from positions of keyframes for active streams. This is the final position.&lt;br /&gt;
# Seek to closest syncpoint before the final position, preform a minimal demuxing until final position (to get proper last_pts context across all streams).&lt;br /&gt;
#* With luck this seek will not need an underlying seek, if you have not flushed the buffer since the requested position.&lt;br /&gt;
#* In most common case, ''stopper.back_ptr'' points to same syncpoint as the start of the linear search, as both syncpoints point to the same rare video keyframe.&lt;br /&gt;
#* If only video stream is active and the only non active stream is audio, you will most likely end your linear search immediately after ''stopper_syncpoint'' by finding an audio keyframe. Afterwards you will rewind right back to ''start'', and, since buffer hasn't been flushed, this will not need an underlying seek.&lt;br /&gt;
&lt;br /&gt;
=== Index ===&lt;br /&gt;
With index, binary search step is skipped, and a much more limited linear search used, between two immediate syncpoints. The syncpoint picked is the highest possible one that has a keyframe for each active stream past the syncpoint with a pts lower than requested pts. The end of the linear search is the syncpoint immediately following.&lt;br /&gt;
&lt;br /&gt;
Dynamic index is used in the same manner as complete index. However, when deciding a syncpoint, the entire range of the syncpoint picked until the first syncpoint with a pts higher than requested is checked for having been already researched. If a &amp;quot;hole&amp;quot; is found anywhere in this range, dynamic index is disregarded and full binary search is performed.&lt;br /&gt;
&lt;br /&gt;
[[Category:Container Formats]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1961</id>
		<title>NUT</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1961"/>
		<updated>2006-02-02T01:22:50Z</updated>

		<summary type="html">&lt;p&gt;Ods15: /* Linear search implementation */  i meant bullets&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Extensions: nut&lt;br /&gt;
* Website: http://www.nut.hu/&lt;br /&gt;
&lt;br /&gt;
NUT is a container format under construction by [[MPlayer]] and [[FFmpeg]] developers.&lt;br /&gt;
Its main goals are to be simple, flexible and error-resistant while maintaining the smallest possible overhead.&lt;br /&gt;
&lt;br /&gt;
== NUT seeking algo in libnut ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Binary search and linear interpolation ===&lt;br /&gt;
&lt;br /&gt;
==== Startup ====&lt;br /&gt;
Go to beginning of file if first syncpoint has not been found, and then go to EOF and search backward to find last syncpoint.&lt;br /&gt;
Pick the closest possible syncpoints for requested pts, one higher and one lower. If requested pts is lower than first syncpoint or higher than last syncpoint, then seek to either of those syncpoints and end seek.&lt;br /&gt;
&lt;br /&gt;
Binary search is ended when the entire region between the 2 syncpoints picked has been scanned. Which could even be before it has begun thanks to syncpoint cache.&lt;br /&gt;
&lt;br /&gt;
==== Guess position ====&lt;br /&gt;
Best results have been achieved by combining both linear interpolation and binary search, giving most of the weight to interpolation.&lt;br /&gt;
&lt;br /&gt;
;hi, hi_pd: file position and timestamp of the top edge of the binary search.&lt;br /&gt;
;lo, lo_pd: file position and timestamp of the bottom edge of the binary search.&lt;br /&gt;
;time_pos: Requested pts.&lt;br /&gt;
;guess: begginning of linear search for syncpoint.&lt;br /&gt;
&lt;br /&gt;
 #define INTERPOLATE_WEIGHT (7./8)&lt;br /&gt;
 if (hi - lo &amp;lt; nut-&amp;gt;max_distance) guess = lo + 8;&lt;br /&gt;
 else { // linear interpolation&lt;br /&gt;
     double a = (double)(hi - lo) / (hi_pd - lo_pd);&lt;br /&gt;
     guess = lo + a * (time_pos - lo_pd);&lt;br /&gt;
     guess = guess * INTERPOLATE_WEIGHT + (lo+hi)/2 * (1 - INTERPOLATE_WEIGHT);&lt;br /&gt;
     if (hi - guess &amp;lt; nut-&amp;gt;max_distance*2) guess = hi - nut-&amp;gt;max_distance*2; //(lo + hi)/2;&lt;br /&gt;
 }&lt;br /&gt;
 if (guess &amp;lt; lo + 8) guess = lo + 8;&lt;br /&gt;
&lt;br /&gt;
The first conditional prevents too much recursing when the distance is already low. The last conditional prevents infinite loop of syncpoint search constantly finding ''lo'' and achieving nothing.&lt;br /&gt;
&lt;br /&gt;
==== Binary search ====&lt;br /&gt;
Now, find a syncpoint, bounded between ''guess'' and ''hi''. If it has a pts higher than requested pts, then replace ''hi'' and ''hi_pd'', otherwise replace ''lo'' and ''lo_pd''.&lt;br /&gt;
If a syncpoint was not found between ''guess'' and ''hi'', then, if ''guess'' is smaller or equal to ''lo + 11'', then you have scanned the entire area between ''lo'' and ''hi'', and your binary search is done. Otherwise, replace ''hi'' with ''guess'' and repeat the binary search.&lt;br /&gt;
&lt;br /&gt;
After finding the 2 closest syncpoints bounding your requested pts, the bounds of linear are search are:&lt;br /&gt;
&lt;br /&gt;
 *start = lo_s.pos - (lo_s.back_ptr * 8 + 7);&lt;br /&gt;
 *end = lo_s.pos;&lt;br /&gt;
 *stopper = hi_s;&lt;br /&gt;
&lt;br /&gt;
''stopper'' is used later to end linear search prematurely. Note that it is the '''top''' edge of binary search, meaning, it has a pts higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Linear search ===&lt;br /&gt;
&lt;br /&gt;
==== Bounds of linear search ====&lt;br /&gt;
Linear search of course ends at ''end'', however, it can end earlier:&lt;br /&gt;
* When you find any frame of an active stream, with a pts higher than requested pts.&lt;br /&gt;
* When you find a syncpoint immediately following the syncpoint pointed to by ''stopper'''s back_ptr, (from here on this syncpoint will be called ''stopper_syncpoint'') '''and''' all streams are active.&lt;br /&gt;
* When you find a keyframe for all '''non'''-active streams after after ''stopper_syncpoint'' with a pts lower than ''stopper.pts''. The logic is:&lt;br /&gt;
** ''stopper.pts'' is higher than requested pts.&lt;br /&gt;
** ''stopper_syncpoint'' is '''not''' the syncpoint pointed to by ''stopper.back_ptr'', but the one immediately following.&lt;br /&gt;
** If there was a keyframe for every non active stream after ''stopper_syncpoint'', with a pts lower than ''stopper.pts'', then the reason ''stopper'' does not point to ''stopper_syncpoint'' must be that there are no keyframes for '''active''' streams with a pts lower than ''stopper.pts'' after ''stopper_syncpoint''.&lt;br /&gt;
** There might be more keyframes in the region with a pts higher than ''stopper.pts'', but those are irrelevant because they are higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
==== Linear search implementation ====&lt;br /&gt;
&lt;br /&gt;
# Start at ''start''.&lt;br /&gt;
# Search for syncpoint. If it is further than ''start + 7'', then the file is errored, and you can start playing immediately from this syncpoint.&lt;br /&gt;
# Perform full demuxing, buffering everything read. If you encounter any NUT error during demuxing, seek back to the syncpoint after ''start'' and end seek.&lt;br /&gt;
# On every syncpoint, flush the buffer and cache the syncpoint position.&lt;br /&gt;
#* If this syncpoint is ''stopper_syncpoint'', then do not flush the buffer, as it would be possible the linear search would end immediatelty afterwards and a second underlying seek would not be necessary.&lt;br /&gt;
# When finding keyframe of active stream with pts lower than requested pts, store position of keyframe. Discard previous value.&lt;br /&gt;
# End linear search as necessary by bounds given above.&lt;br /&gt;
# Pick the lowest value from positions of keyframes for active streams. This is the final position.&lt;br /&gt;
# Seek to closest syncpoint before the final position, preform a minimal demuxing until final position (to get proper last_pts context across all streams).&lt;br /&gt;
#* With luck this seek will not need an underlying seek, if you have not flushed the buffer since the requested position.&lt;br /&gt;
#* In most common case, ''stopper.back_ptr'' points to same syncpoint as the start of the linear search, as both syncpoints point to the same rare video keyframe.&lt;br /&gt;
#* If only video stream is active and the only non active stream is audio, you will most likely end your linear search immediately after ''stopper_syncpoint'' by finding an audio keyframe. Afterwards you will rewind right back to ''start'', and, since buffer hasn't been flushed, this will not need an underlying seek.&lt;br /&gt;
&lt;br /&gt;
=== Index ===&lt;br /&gt;
With index, binary search step is skipped, and a much more limited linear search used, between two immediate syncpoints. The syncpoint picked is the highest possible one that has a keyframe for each active stream past the syncpoint with a pts lower than requested pts. The end of the linear search is the syncpoint immediately following.&lt;br /&gt;
&lt;br /&gt;
Dynamic index is used in the same manner as complete index. However, when deciding a syncpoint, the entire range of the syncpoint picked until the first syncpoint with a pts higher than requested is checked for having been already researched. If a &amp;quot;hole&amp;quot; is found anywhere in this range, dynamic index is disregarded and full binary search is performed.&lt;br /&gt;
&lt;br /&gt;
[[Category:Container Formats]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1960</id>
		<title>NUT</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1960"/>
		<updated>2006-02-02T01:22:23Z</updated>

		<summary type="html">&lt;p&gt;Ods15: /* Linear search implementation */  more about buffering and seeking&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Extensions: nut&lt;br /&gt;
* Website: http://www.nut.hu/&lt;br /&gt;
&lt;br /&gt;
NUT is a container format under construction by [[MPlayer]] and [[FFmpeg]] developers.&lt;br /&gt;
Its main goals are to be simple, flexible and error-resistant while maintaining the smallest possible overhead.&lt;br /&gt;
&lt;br /&gt;
== NUT seeking algo in libnut ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Binary search and linear interpolation ===&lt;br /&gt;
&lt;br /&gt;
==== Startup ====&lt;br /&gt;
Go to beginning of file if first syncpoint has not been found, and then go to EOF and search backward to find last syncpoint.&lt;br /&gt;
Pick the closest possible syncpoints for requested pts, one higher and one lower. If requested pts is lower than first syncpoint or higher than last syncpoint, then seek to either of those syncpoints and end seek.&lt;br /&gt;
&lt;br /&gt;
Binary search is ended when the entire region between the 2 syncpoints picked has been scanned. Which could even be before it has begun thanks to syncpoint cache.&lt;br /&gt;
&lt;br /&gt;
==== Guess position ====&lt;br /&gt;
Best results have been achieved by combining both linear interpolation and binary search, giving most of the weight to interpolation.&lt;br /&gt;
&lt;br /&gt;
;hi, hi_pd: file position and timestamp of the top edge of the binary search.&lt;br /&gt;
;lo, lo_pd: file position and timestamp of the bottom edge of the binary search.&lt;br /&gt;
;time_pos: Requested pts.&lt;br /&gt;
;guess: begginning of linear search for syncpoint.&lt;br /&gt;
&lt;br /&gt;
 #define INTERPOLATE_WEIGHT (7./8)&lt;br /&gt;
 if (hi - lo &amp;lt; nut-&amp;gt;max_distance) guess = lo + 8;&lt;br /&gt;
 else { // linear interpolation&lt;br /&gt;
     double a = (double)(hi - lo) / (hi_pd - lo_pd);&lt;br /&gt;
     guess = lo + a * (time_pos - lo_pd);&lt;br /&gt;
     guess = guess * INTERPOLATE_WEIGHT + (lo+hi)/2 * (1 - INTERPOLATE_WEIGHT);&lt;br /&gt;
     if (hi - guess &amp;lt; nut-&amp;gt;max_distance*2) guess = hi - nut-&amp;gt;max_distance*2; //(lo + hi)/2;&lt;br /&gt;
 }&lt;br /&gt;
 if (guess &amp;lt; lo + 8) guess = lo + 8;&lt;br /&gt;
&lt;br /&gt;
The first conditional prevents too much recursing when the distance is already low. The last conditional prevents infinite loop of syncpoint search constantly finding ''lo'' and achieving nothing.&lt;br /&gt;
&lt;br /&gt;
==== Binary search ====&lt;br /&gt;
Now, find a syncpoint, bounded between ''guess'' and ''hi''. If it has a pts higher than requested pts, then replace ''hi'' and ''hi_pd'', otherwise replace ''lo'' and ''lo_pd''.&lt;br /&gt;
If a syncpoint was not found between ''guess'' and ''hi'', then, if ''guess'' is smaller or equal to ''lo + 11'', then you have scanned the entire area between ''lo'' and ''hi'', and your binary search is done. Otherwise, replace ''hi'' with ''guess'' and repeat the binary search.&lt;br /&gt;
&lt;br /&gt;
After finding the 2 closest syncpoints bounding your requested pts, the bounds of linear are search are:&lt;br /&gt;
&lt;br /&gt;
 *start = lo_s.pos - (lo_s.back_ptr * 8 + 7);&lt;br /&gt;
 *end = lo_s.pos;&lt;br /&gt;
 *stopper = hi_s;&lt;br /&gt;
&lt;br /&gt;
''stopper'' is used later to end linear search prematurely. Note that it is the '''top''' edge of binary search, meaning, it has a pts higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Linear search ===&lt;br /&gt;
&lt;br /&gt;
==== Bounds of linear search ====&lt;br /&gt;
Linear search of course ends at ''end'', however, it can end earlier:&lt;br /&gt;
* When you find any frame of an active stream, with a pts higher than requested pts.&lt;br /&gt;
* When you find a syncpoint immediately following the syncpoint pointed to by ''stopper'''s back_ptr, (from here on this syncpoint will be called ''stopper_syncpoint'') '''and''' all streams are active.&lt;br /&gt;
* When you find a keyframe for all '''non'''-active streams after after ''stopper_syncpoint'' with a pts lower than ''stopper.pts''. The logic is:&lt;br /&gt;
** ''stopper.pts'' is higher than requested pts.&lt;br /&gt;
** ''stopper_syncpoint'' is '''not''' the syncpoint pointed to by ''stopper.back_ptr'', but the one immediately following.&lt;br /&gt;
** If there was a keyframe for every non active stream after ''stopper_syncpoint'', with a pts lower than ''stopper.pts'', then the reason ''stopper'' does not point to ''stopper_syncpoint'' must be that there are no keyframes for '''active''' streams with a pts lower than ''stopper.pts'' after ''stopper_syncpoint''.&lt;br /&gt;
** There might be more keyframes in the region with a pts higher than ''stopper.pts'', but those are irrelevant because they are higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
==== Linear search implementation ====&lt;br /&gt;
&lt;br /&gt;
# Start at ''start''.&lt;br /&gt;
# Search for syncpoint. If it is further than ''start + 7'', then the file is errored, and you can start playing immediately from this syncpoint.&lt;br /&gt;
# Perform full demuxing, buffering everything read. If you encounter any NUT error during demuxing, seek back to the syncpoint after ''start'' and end seek.&lt;br /&gt;
# On every syncpoint, flush the buffer and cache the syncpoint position.&lt;br /&gt;
## If this syncpoint is ''stopper_syncpoint'', then do not flush the buffer, as it would be possible the linear search would end immediatelty afterwards and a second underlying seek would not be necessary.&lt;br /&gt;
# When finding keyframe of active stream with pts lower than requested pts, store position of keyframe. Discard previous value.&lt;br /&gt;
# End linear search as necessary by bounds given above.&lt;br /&gt;
# Pick the lowest value from positions of keyframes for active streams. This is the final position.&lt;br /&gt;
# Seek to closest syncpoint before the final position, preform a minimal demuxing until final position (to get proper last_pts context across all streams).&lt;br /&gt;
## With luck this seek will not need an underlying seek, if you have not flushed the buffer since the requested position.&lt;br /&gt;
## In most common case, ''stopper.back_ptr'' points to same syncpoint as the start of the linear search, as both syncpoints point to the same rare video keyframe.&lt;br /&gt;
## If only video stream is active and the only non active stream is audio, you will most likely end your linear search immediately after ''stopper_syncpoint'' by finding an audio keyframe. Afterwards you will rewind right back to ''start'', and, since buffer hasn't been flushed, this will not need an underlying seek.&lt;br /&gt;
&lt;br /&gt;
=== Index ===&lt;br /&gt;
With index, binary search step is skipped, and a much more limited linear search used, between two immediate syncpoints. The syncpoint picked is the highest possible one that has a keyframe for each active stream past the syncpoint with a pts lower than requested pts. The end of the linear search is the syncpoint immediately following.&lt;br /&gt;
&lt;br /&gt;
Dynamic index is used in the same manner as complete index. However, when deciding a syncpoint, the entire range of the syncpoint picked until the first syncpoint with a pts higher than requested is checked for having been already researched. If a &amp;quot;hole&amp;quot; is found anywhere in this range, dynamic index is disregarded and full binary search is performed.&lt;br /&gt;
&lt;br /&gt;
[[Category:Container Formats]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1959</id>
		<title>NUT</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1959"/>
		<updated>2006-02-02T01:12:46Z</updated>

		<summary type="html">&lt;p&gt;Ods15: /* Linear search implementation */  handling NUT errors&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Extensions: nut&lt;br /&gt;
* Website: http://www.nut.hu/&lt;br /&gt;
&lt;br /&gt;
NUT is a container format under construction by [[MPlayer]] and [[FFmpeg]] developers.&lt;br /&gt;
Its main goals are to be simple, flexible and error-resistant while maintaining the smallest possible overhead.&lt;br /&gt;
&lt;br /&gt;
== NUT seeking algo in libnut ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Binary search and linear interpolation ===&lt;br /&gt;
&lt;br /&gt;
==== Startup ====&lt;br /&gt;
Go to beginning of file if first syncpoint has not been found, and then go to EOF and search backward to find last syncpoint.&lt;br /&gt;
Pick the closest possible syncpoints for requested pts, one higher and one lower. If requested pts is lower than first syncpoint or higher than last syncpoint, then seek to either of those syncpoints and end seek.&lt;br /&gt;
&lt;br /&gt;
Binary search is ended when the entire region between the 2 syncpoints picked has been scanned. Which could even be before it has begun thanks to syncpoint cache.&lt;br /&gt;
&lt;br /&gt;
==== Guess position ====&lt;br /&gt;
Best results have been achieved by combining both linear interpolation and binary search, giving most of the weight to interpolation.&lt;br /&gt;
&lt;br /&gt;
;hi, hi_pd: file position and timestamp of the top edge of the binary search.&lt;br /&gt;
;lo, lo_pd: file position and timestamp of the bottom edge of the binary search.&lt;br /&gt;
;time_pos: Requested pts.&lt;br /&gt;
;guess: begginning of linear search for syncpoint.&lt;br /&gt;
&lt;br /&gt;
 #define INTERPOLATE_WEIGHT (7./8)&lt;br /&gt;
 if (hi - lo &amp;lt; nut-&amp;gt;max_distance) guess = lo + 8;&lt;br /&gt;
 else { // linear interpolation&lt;br /&gt;
     double a = (double)(hi - lo) / (hi_pd - lo_pd);&lt;br /&gt;
     guess = lo + a * (time_pos - lo_pd);&lt;br /&gt;
     guess = guess * INTERPOLATE_WEIGHT + (lo+hi)/2 * (1 - INTERPOLATE_WEIGHT);&lt;br /&gt;
     if (hi - guess &amp;lt; nut-&amp;gt;max_distance*2) guess = hi - nut-&amp;gt;max_distance*2; //(lo + hi)/2;&lt;br /&gt;
 }&lt;br /&gt;
 if (guess &amp;lt; lo + 8) guess = lo + 8;&lt;br /&gt;
&lt;br /&gt;
The first conditional prevents too much recursing when the distance is already low. The last conditional prevents infinite loop of syncpoint search constantly finding ''lo'' and achieving nothing.&lt;br /&gt;
&lt;br /&gt;
==== Binary search ====&lt;br /&gt;
Now, find a syncpoint, bounded between ''guess'' and ''hi''. If it has a pts higher than requested pts, then replace ''hi'' and ''hi_pd'', otherwise replace ''lo'' and ''lo_pd''.&lt;br /&gt;
If a syncpoint was not found between ''guess'' and ''hi'', then, if ''guess'' is smaller or equal to ''lo + 11'', then you have scanned the entire area between ''lo'' and ''hi'', and your binary search is done. Otherwise, replace ''hi'' with ''guess'' and repeat the binary search.&lt;br /&gt;
&lt;br /&gt;
After finding the 2 closest syncpoints bounding your requested pts, the bounds of linear are search are:&lt;br /&gt;
&lt;br /&gt;
 *start = lo_s.pos - (lo_s.back_ptr * 8 + 7);&lt;br /&gt;
 *end = lo_s.pos;&lt;br /&gt;
 *stopper = hi_s;&lt;br /&gt;
&lt;br /&gt;
''stopper'' is used later to end linear search prematurely. Note that it is the '''top''' edge of binary search, meaning, it has a pts higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Linear search ===&lt;br /&gt;
&lt;br /&gt;
==== Bounds of linear search ====&lt;br /&gt;
Linear search of course ends at ''end'', however, it can end earlier:&lt;br /&gt;
* When you find any frame of an active stream, with a pts higher than requested pts.&lt;br /&gt;
* When you find a syncpoint immediately following the syncpoint pointed to by ''stopper'''s back_ptr, (from here on this syncpoint will be called ''stopper_syncpoint'') '''and''' all streams are active.&lt;br /&gt;
* When you find a keyframe for all '''non'''-active streams after after ''stopper_syncpoint'' with a pts lower than ''stopper.pts''. The logic is:&lt;br /&gt;
** ''stopper.pts'' is higher than requested pts.&lt;br /&gt;
** ''stopper_syncpoint'' is '''not''' the syncpoint pointed to by ''stopper.back_ptr'', but the one immediately following.&lt;br /&gt;
** If there was a keyframe for every non active stream after ''stopper_syncpoint'', with a pts lower than ''stopper.pts'', then the reason ''stopper'' does not point to ''stopper_syncpoint'' must be that there are no keyframes for '''active''' streams with a pts lower than ''stopper.pts'' after ''stopper_syncpoint''.&lt;br /&gt;
** There might be more keyframes in the region with a pts higher than ''stopper.pts'', but those are irrelevant because they are higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
==== Linear search implementation ====&lt;br /&gt;
&lt;br /&gt;
# Start at ''start''.&lt;br /&gt;
# Search for syncpoint. If it is further than ''start + 7'', then the file is errored, and you can start playing immediately from this syncpoint.&lt;br /&gt;
# Perform full demuxing, buffering everything read. If you encounter any NUT error during demuxing, seek back to the syncpoint after ''start'' and end seek.&lt;br /&gt;
# On every syncpoint, flush the buffer and cache the syncpoint position.&lt;br /&gt;
# When finding keyframe of active stream with pts lower than requested pts, store position of keyframe. Discard previous value.&lt;br /&gt;
# End linear search as necessary by bounds given above.&lt;br /&gt;
# Pick the lowest value from positions of keyframes for active streams. This is the final position.&lt;br /&gt;
# Seek to closest syncpoint before the final position, preform a minimal demuxing until final position (to get proper last_pts context across all streams).&lt;br /&gt;
&lt;br /&gt;
=== Index ===&lt;br /&gt;
With index, binary search step is skipped, and a much more limited linear search used, between two immediate syncpoints. The syncpoint picked is the highest possible one that has a keyframe for each active stream past the syncpoint with a pts lower than requested pts. The end of the linear search is the syncpoint immediately following.&lt;br /&gt;
&lt;br /&gt;
Dynamic index is used in the same manner as complete index. However, when deciding a syncpoint, the entire range of the syncpoint picked until the first syncpoint with a pts higher than requested is checked for having been already researched. If a &amp;quot;hole&amp;quot; is found anywhere in this range, dynamic index is disregarded and full binary search is performed.&lt;br /&gt;
&lt;br /&gt;
[[Category:Container Formats]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1958</id>
		<title>NUT</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1958"/>
		<updated>2006-02-02T01:04:07Z</updated>

		<summary type="html">&lt;p&gt;Ods15: /* Binary search */  clarify&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Extensions: nut&lt;br /&gt;
* Website: http://www.nut.hu/&lt;br /&gt;
&lt;br /&gt;
NUT is a container format under construction by [[MPlayer]] and [[FFmpeg]] developers.&lt;br /&gt;
Its main goals are to be simple, flexible and error-resistant while maintaining the smallest possible overhead.&lt;br /&gt;
&lt;br /&gt;
== NUT seeking algo in libnut ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Binary search and linear interpolation ===&lt;br /&gt;
&lt;br /&gt;
==== Startup ====&lt;br /&gt;
Go to beginning of file if first syncpoint has not been found, and then go to EOF and search backward to find last syncpoint.&lt;br /&gt;
Pick the closest possible syncpoints for requested pts, one higher and one lower. If requested pts is lower than first syncpoint or higher than last syncpoint, then seek to either of those syncpoints and end seek.&lt;br /&gt;
&lt;br /&gt;
Binary search is ended when the entire region between the 2 syncpoints picked has been scanned. Which could even be before it has begun thanks to syncpoint cache.&lt;br /&gt;
&lt;br /&gt;
==== Guess position ====&lt;br /&gt;
Best results have been achieved by combining both linear interpolation and binary search, giving most of the weight to interpolation.&lt;br /&gt;
&lt;br /&gt;
;hi, hi_pd: file position and timestamp of the top edge of the binary search.&lt;br /&gt;
;lo, lo_pd: file position and timestamp of the bottom edge of the binary search.&lt;br /&gt;
;time_pos: Requested pts.&lt;br /&gt;
;guess: begginning of linear search for syncpoint.&lt;br /&gt;
&lt;br /&gt;
 #define INTERPOLATE_WEIGHT (7./8)&lt;br /&gt;
 if (hi - lo &amp;lt; nut-&amp;gt;max_distance) guess = lo + 8;&lt;br /&gt;
 else { // linear interpolation&lt;br /&gt;
     double a = (double)(hi - lo) / (hi_pd - lo_pd);&lt;br /&gt;
     guess = lo + a * (time_pos - lo_pd);&lt;br /&gt;
     guess = guess * INTERPOLATE_WEIGHT + (lo+hi)/2 * (1 - INTERPOLATE_WEIGHT);&lt;br /&gt;
     if (hi - guess &amp;lt; nut-&amp;gt;max_distance*2) guess = hi - nut-&amp;gt;max_distance*2; //(lo + hi)/2;&lt;br /&gt;
 }&lt;br /&gt;
 if (guess &amp;lt; lo + 8) guess = lo + 8;&lt;br /&gt;
&lt;br /&gt;
The first conditional prevents too much recursing when the distance is already low. The last conditional prevents infinite loop of syncpoint search constantly finding ''lo'' and achieving nothing.&lt;br /&gt;
&lt;br /&gt;
==== Binary search ====&lt;br /&gt;
Now, find a syncpoint, bounded between ''guess'' and ''hi''. If it has a pts higher than requested pts, then replace ''hi'' and ''hi_pd'', otherwise replace ''lo'' and ''lo_pd''.&lt;br /&gt;
If a syncpoint was not found between ''guess'' and ''hi'', then, if ''guess'' is smaller or equal to ''lo + 11'', then you have scanned the entire area between ''lo'' and ''hi'', and your binary search is done. Otherwise, replace ''hi'' with ''guess'' and repeat the binary search.&lt;br /&gt;
&lt;br /&gt;
After finding the 2 closest syncpoints bounding your requested pts, the bounds of linear are search are:&lt;br /&gt;
&lt;br /&gt;
 *start = lo_s.pos - (lo_s.back_ptr * 8 + 7);&lt;br /&gt;
 *end = lo_s.pos;&lt;br /&gt;
 *stopper = hi_s;&lt;br /&gt;
&lt;br /&gt;
''stopper'' is used later to end linear search prematurely. Note that it is the '''top''' edge of binary search, meaning, it has a pts higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Linear search ===&lt;br /&gt;
&lt;br /&gt;
==== Bounds of linear search ====&lt;br /&gt;
Linear search of course ends at ''end'', however, it can end earlier:&lt;br /&gt;
* When you find any frame of an active stream, with a pts higher than requested pts.&lt;br /&gt;
* When you find a syncpoint immediately following the syncpoint pointed to by ''stopper'''s back_ptr, (from here on this syncpoint will be called ''stopper_syncpoint'') '''and''' all streams are active.&lt;br /&gt;
* When you find a keyframe for all '''non'''-active streams after after ''stopper_syncpoint'' with a pts lower than ''stopper.pts''. The logic is:&lt;br /&gt;
** ''stopper.pts'' is higher than requested pts.&lt;br /&gt;
** ''stopper_syncpoint'' is '''not''' the syncpoint pointed to by ''stopper.back_ptr'', but the one immediately following.&lt;br /&gt;
** If there was a keyframe for every non active stream after ''stopper_syncpoint'', with a pts lower than ''stopper.pts'', then the reason ''stopper'' does not point to ''stopper_syncpoint'' must be that there are no keyframes for '''active''' streams with a pts lower than ''stopper.pts'' after ''stopper_syncpoint''.&lt;br /&gt;
** There might be more keyframes in the region with a pts higher than ''stopper.pts'', but those are irrelevant because they are higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
==== Linear search implementation ====&lt;br /&gt;
&lt;br /&gt;
# Start at ''start''.&lt;br /&gt;
# Search for syncpoint. If it is further than ''start + 7'', then the file is errored, and you can start playing immediately from this syncpoint.&lt;br /&gt;
# Perform full demuxing, buffering everything read.&lt;br /&gt;
# On every syncpoint, flush the buffer and cache the syncpoint position.&lt;br /&gt;
# When finding keyframe of active stream with pts lower than requested pts, store position of keyframe. Discard previous value.&lt;br /&gt;
# End linear search as necessary by bounds given above.&lt;br /&gt;
# Pick the lowest value from positions of keyframes for active streams. This is the final position.&lt;br /&gt;
# Seek to closest syncpoint before the final position, preform a minimal demuxing until final position (to get proper last_pts context across all streams).&lt;br /&gt;
&lt;br /&gt;
=== Index ===&lt;br /&gt;
With index, binary search step is skipped, and a much more limited linear search used, between two immediate syncpoints. The syncpoint picked is the highest possible one that has a keyframe for each active stream past the syncpoint with a pts lower than requested pts. The end of the linear search is the syncpoint immediately following.&lt;br /&gt;
&lt;br /&gt;
Dynamic index is used in the same manner as complete index. However, when deciding a syncpoint, the entire range of the syncpoint picked until the first syncpoint with a pts higher than requested is checked for having been already researched. If a &amp;quot;hole&amp;quot; is found anywhere in this range, dynamic index is disregarded and full binary search is performed.&lt;br /&gt;
&lt;br /&gt;
[[Category:Container Formats]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1957</id>
		<title>NUT</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1957"/>
		<updated>2006-02-02T01:00:53Z</updated>

		<summary type="html">&lt;p&gt;Ods15: /* Bounds of linear search */  oops, lower, not higher&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Extensions: nut&lt;br /&gt;
* Website: http://www.nut.hu/&lt;br /&gt;
&lt;br /&gt;
NUT is a container format under construction by [[MPlayer]] and [[FFmpeg]] developers.&lt;br /&gt;
Its main goals are to be simple, flexible and error-resistant while maintaining the smallest possible overhead.&lt;br /&gt;
&lt;br /&gt;
== NUT seeking algo in libnut ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Binary search and linear interpolation ===&lt;br /&gt;
&lt;br /&gt;
==== Startup ====&lt;br /&gt;
Go to beginning of file if first syncpoint has not been found, and then go to EOF and search backward to find last syncpoint.&lt;br /&gt;
Pick the closest possible syncpoints for requested pts, one higher and one lower. If requested pts is lower than first syncpoint or higher than last syncpoint, then seek to either of those syncpoints and end seek.&lt;br /&gt;
&lt;br /&gt;
Binary search is ended when the entire region between the 2 syncpoints picked has been scanned. Which could even be before it has begun thanks to syncpoint cache.&lt;br /&gt;
&lt;br /&gt;
==== Guess position ====&lt;br /&gt;
Best results have been achieved by combining both linear interpolation and binary search, giving most of the weight to interpolation.&lt;br /&gt;
&lt;br /&gt;
;hi, hi_pd: file position and timestamp of the top edge of the binary search.&lt;br /&gt;
;lo, lo_pd: file position and timestamp of the bottom edge of the binary search.&lt;br /&gt;
;time_pos: Requested pts.&lt;br /&gt;
;guess: begginning of linear search for syncpoint.&lt;br /&gt;
&lt;br /&gt;
 #define INTERPOLATE_WEIGHT (7./8)&lt;br /&gt;
 if (hi - lo &amp;lt; nut-&amp;gt;max_distance) guess = lo + 8;&lt;br /&gt;
 else { // linear interpolation&lt;br /&gt;
     double a = (double)(hi - lo) / (hi_pd - lo_pd);&lt;br /&gt;
     guess = lo + a * (time_pos - lo_pd);&lt;br /&gt;
     guess = guess * INTERPOLATE_WEIGHT + (lo+hi)/2 * (1 - INTERPOLATE_WEIGHT);&lt;br /&gt;
     if (hi - guess &amp;lt; nut-&amp;gt;max_distance*2) guess = hi - nut-&amp;gt;max_distance*2; //(lo + hi)/2;&lt;br /&gt;
 }&lt;br /&gt;
 if (guess &amp;lt; lo + 8) guess = lo + 8;&lt;br /&gt;
&lt;br /&gt;
The first conditional prevents too much recursing when the distance is already low. The last conditional prevents infinite loop of syncpoint search constantly finding ''lo'' and achieving nothing.&lt;br /&gt;
&lt;br /&gt;
==== Binary search ====&lt;br /&gt;
Now, find a syncpoint, bounded between ''guess'' and ''hi''. If it has a pts higher than requested pts, then replace ''hi'' and ''hi_pd'', otherwise replace ''lo'' and ''lo_pd''.&lt;br /&gt;
If a syncpoint was not found between ''guess'' and ''hi'', then, if ''guess'' is smaller or equal to ''lo + 11'', then you have scanned the entire area between ''lo'' and ''hi'', and your binary search is done. Otherwise, replace ''hi'' with ''guess'' and repeat the binary search.&lt;br /&gt;
&lt;br /&gt;
After finding the 2 closest syncpoints bounding your requested pts, the bounds of linear are search are:&lt;br /&gt;
&lt;br /&gt;
 *start = lo_s.pos - (lo_s.back_ptr * 8 + 7);&lt;br /&gt;
 *end = lo_s.pos;&lt;br /&gt;
 *stopper = hi_s;&lt;br /&gt;
&lt;br /&gt;
''stopper'' is used later to end linear search prematurely.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Linear search ===&lt;br /&gt;
&lt;br /&gt;
==== Bounds of linear search ====&lt;br /&gt;
Linear search of course ends at ''end'', however, it can end earlier:&lt;br /&gt;
* When you find any frame of an active stream, with a pts higher than requested pts.&lt;br /&gt;
* When you find a syncpoint immediately following the syncpoint pointed to by ''stopper'''s back_ptr, (from here on this syncpoint will be called ''stopper_syncpoint'') '''and''' all streams are active.&lt;br /&gt;
* When you find a keyframe for all '''non'''-active streams after after ''stopper_syncpoint'' with a pts lower than ''stopper.pts''. The logic is:&lt;br /&gt;
** ''stopper.pts'' is higher than requested pts.&lt;br /&gt;
** ''stopper_syncpoint'' is '''not''' the syncpoint pointed to by ''stopper.back_ptr'', but the one immediately following.&lt;br /&gt;
** If there was a keyframe for every non active stream after ''stopper_syncpoint'', with a pts lower than ''stopper.pts'', then the reason ''stopper'' does not point to ''stopper_syncpoint'' must be that there are no keyframes for '''active''' streams with a pts lower than ''stopper.pts'' after ''stopper_syncpoint''.&lt;br /&gt;
** There might be more keyframes in the region with a pts higher than ''stopper.pts'', but those are irrelevant because they are higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
==== Linear search implementation ====&lt;br /&gt;
&lt;br /&gt;
# Start at ''start''.&lt;br /&gt;
# Search for syncpoint. If it is further than ''start + 7'', then the file is errored, and you can start playing immediately from this syncpoint.&lt;br /&gt;
# Perform full demuxing, buffering everything read.&lt;br /&gt;
# On every syncpoint, flush the buffer and cache the syncpoint position.&lt;br /&gt;
# When finding keyframe of active stream with pts lower than requested pts, store position of keyframe. Discard previous value.&lt;br /&gt;
# End linear search as necessary by bounds given above.&lt;br /&gt;
# Pick the lowest value from positions of keyframes for active streams. This is the final position.&lt;br /&gt;
# Seek to closest syncpoint before the final position, preform a minimal demuxing until final position (to get proper last_pts context across all streams).&lt;br /&gt;
&lt;br /&gt;
=== Index ===&lt;br /&gt;
With index, binary search step is skipped, and a much more limited linear search used, between two immediate syncpoints. The syncpoint picked is the highest possible one that has a keyframe for each active stream past the syncpoint with a pts lower than requested pts. The end of the linear search is the syncpoint immediately following.&lt;br /&gt;
&lt;br /&gt;
Dynamic index is used in the same manner as complete index. However, when deciding a syncpoint, the entire range of the syncpoint picked until the first syncpoint with a pts higher than requested is checked for having been already researched. If a &amp;quot;hole&amp;quot; is found anywhere in this range, dynamic index is disregarded and full binary search is performed.&lt;br /&gt;
&lt;br /&gt;
[[Category:Container Formats]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1956</id>
		<title>NUT</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1956"/>
		<updated>2006-02-02T00:55:27Z</updated>

		<summary type="html">&lt;p&gt;Ods15: /* Index */  I really did mean a single syncpoint, this was a grammar mistake, not a typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Extensions: nut&lt;br /&gt;
* Website: http://www.nut.hu/&lt;br /&gt;
&lt;br /&gt;
NUT is a container format under construction by [[MPlayer]] and [[FFmpeg]] developers.&lt;br /&gt;
Its main goals are to be simple, flexible and error-resistant while maintaining the smallest possible overhead.&lt;br /&gt;
&lt;br /&gt;
== NUT seeking algo in libnut ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Binary search and linear interpolation ===&lt;br /&gt;
&lt;br /&gt;
==== Startup ====&lt;br /&gt;
Go to beginning of file if first syncpoint has not been found, and then go to EOF and search backward to find last syncpoint.&lt;br /&gt;
Pick the closest possible syncpoints for requested pts, one higher and one lower. If requested pts is lower than first syncpoint or higher than last syncpoint, then seek to either of those syncpoints and end seek.&lt;br /&gt;
&lt;br /&gt;
Binary search is ended when the entire region between the 2 syncpoints picked has been scanned. Which could even be before it has begun thanks to syncpoint cache.&lt;br /&gt;
&lt;br /&gt;
==== Guess position ====&lt;br /&gt;
Best results have been achieved by combining both linear interpolation and binary search, giving most of the weight to interpolation.&lt;br /&gt;
&lt;br /&gt;
;hi, hi_pd: file position and timestamp of the top edge of the binary search.&lt;br /&gt;
;lo, lo_pd: file position and timestamp of the bottom edge of the binary search.&lt;br /&gt;
;time_pos: Requested pts.&lt;br /&gt;
;guess: begginning of linear search for syncpoint.&lt;br /&gt;
&lt;br /&gt;
 #define INTERPOLATE_WEIGHT (7./8)&lt;br /&gt;
 if (hi - lo &amp;lt; nut-&amp;gt;max_distance) guess = lo + 8;&lt;br /&gt;
 else { // linear interpolation&lt;br /&gt;
     double a = (double)(hi - lo) / (hi_pd - lo_pd);&lt;br /&gt;
     guess = lo + a * (time_pos - lo_pd);&lt;br /&gt;
     guess = guess * INTERPOLATE_WEIGHT + (lo+hi)/2 * (1 - INTERPOLATE_WEIGHT);&lt;br /&gt;
     if (hi - guess &amp;lt; nut-&amp;gt;max_distance*2) guess = hi - nut-&amp;gt;max_distance*2; //(lo + hi)/2;&lt;br /&gt;
 }&lt;br /&gt;
 if (guess &amp;lt; lo + 8) guess = lo + 8;&lt;br /&gt;
&lt;br /&gt;
The first conditional prevents too much recursing when the distance is already low. The last conditional prevents infinite loop of syncpoint search constantly finding ''lo'' and achieving nothing.&lt;br /&gt;
&lt;br /&gt;
==== Binary search ====&lt;br /&gt;
Now, find a syncpoint, bounded between ''guess'' and ''hi''. If it has a pts higher than requested pts, then replace ''hi'' and ''hi_pd'', otherwise replace ''lo'' and ''lo_pd''.&lt;br /&gt;
If a syncpoint was not found between ''guess'' and ''hi'', then, if ''guess'' is smaller or equal to ''lo + 11'', then you have scanned the entire area between ''lo'' and ''hi'', and your binary search is done. Otherwise, replace ''hi'' with ''guess'' and repeat the binary search.&lt;br /&gt;
&lt;br /&gt;
After finding the 2 closest syncpoints bounding your requested pts, the bounds of linear are search are:&lt;br /&gt;
&lt;br /&gt;
 *start = lo_s.pos - (lo_s.back_ptr * 8 + 7);&lt;br /&gt;
 *end = lo_s.pos;&lt;br /&gt;
 *stopper = hi_s;&lt;br /&gt;
&lt;br /&gt;
''stopper'' is used later to end linear search prematurely.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Linear search ===&lt;br /&gt;
&lt;br /&gt;
==== Bounds of linear search ====&lt;br /&gt;
Linear search of course ends at ''end'', however, it can end earlier:&lt;br /&gt;
* When you find any frame of an active stream, with a pts higher than requested pts.&lt;br /&gt;
* When you find a syncpoint immediately following the syncpoint pointed to by ''stopper'''s back_ptr, (from here on this syncpoint will be called ''stopper_syncpoint'') '''and''' all streams are active.&lt;br /&gt;
* When you find a keyframe for all '''non'''-active streams after after ''stopper_syncpoint'' with a pts higher than ''stopper.pts''. The logic is:&lt;br /&gt;
** ''stopper.pts'' is higher than requested pts.&lt;br /&gt;
** ''stopper_syncpoint'' is '''not''' the syncpoint pointed to by ''stopper.back_ptr'', but the one immediately following.&lt;br /&gt;
** If there was a keyframe for every non active stream after ''stopper_syncpoint'', with a pts lower than ''stopper.pts'', then the reason ''stopper'' does not point to ''stopper_syncpoint'' must be that there are no keyframes for '''active''' streams with a pts lower than ''stopper.pts'' after ''stopper_syncpoint''.&lt;br /&gt;
** There might be more keyframes in the region with a pts higher than ''stopper.pts'', but those are irrelevant because they are higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
==== Linear search implementation ====&lt;br /&gt;
&lt;br /&gt;
# Start at ''start''.&lt;br /&gt;
# Search for syncpoint. If it is further than ''start + 7'', then the file is errored, and you can start playing immediately from this syncpoint.&lt;br /&gt;
# Perform full demuxing, buffering everything read.&lt;br /&gt;
# On every syncpoint, flush the buffer and cache the syncpoint position.&lt;br /&gt;
# When finding keyframe of active stream with pts lower than requested pts, store position of keyframe. Discard previous value.&lt;br /&gt;
# End linear search as necessary by bounds given above.&lt;br /&gt;
# Pick the lowest value from positions of keyframes for active streams. This is the final position.&lt;br /&gt;
# Seek to closest syncpoint before the final position, preform a minimal demuxing until final position (to get proper last_pts context across all streams).&lt;br /&gt;
&lt;br /&gt;
=== Index ===&lt;br /&gt;
With index, binary search step is skipped, and a much more limited linear search used, between two immediate syncpoints. The syncpoint picked is the highest possible one that has a keyframe for each active stream past the syncpoint with a pts lower than requested pts. The end of the linear search is the syncpoint immediately following.&lt;br /&gt;
&lt;br /&gt;
Dynamic index is used in the same manner as complete index. However, when deciding a syncpoint, the entire range of the syncpoint picked until the first syncpoint with a pts higher than requested is checked for having been already researched. If a &amp;quot;hole&amp;quot; is found anywhere in this range, dynamic index is disregarded and full binary search is performed.&lt;br /&gt;
&lt;br /&gt;
[[Category:Container Formats]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1952</id>
		<title>NUT</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=NUT&amp;diff=1952"/>
		<updated>2006-02-01T17:16:08Z</updated>

		<summary type="html">&lt;p&gt;Ods15: Explain NUT seeking algo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Extensions: nut&lt;br /&gt;
* Website: http://www.nut.hu/&lt;br /&gt;
&lt;br /&gt;
NUT is (still) experimental format under construction by [[MPlayer]] and [[FFmpeg]] developers.&lt;br /&gt;
Main goals are to be simple, flexible, error resistant and of course with smallest possible overhead.&lt;br /&gt;
&lt;br /&gt;
== NUT seeking algo in libnut ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Binary search and linear interpolation ===&lt;br /&gt;
&lt;br /&gt;
==== Startup ====&lt;br /&gt;
Go to begginning of file if first syncpoint has not been found, and then go to EOF and search backward to find last syncpoint.&lt;br /&gt;
Pick the closest possible syncpoints for requested pts, one higher and one lower. If requested pts is lower than first syncpoint or higher than last syncpoint, then seek to either of those syncpoints and end seek.&lt;br /&gt;
&lt;br /&gt;
Binary search is ended when the entire region between the 2 syncpoints picked has been scanned. Which could even be before it has begun thanks to syncpoint cache.&lt;br /&gt;
&lt;br /&gt;
==== Guess position ====&lt;br /&gt;
Best results have been achieved by combining both linear interpolation and binary search, giving most of the weight to interpolation.&lt;br /&gt;
&lt;br /&gt;
;hi, hi_pd: file position and timestamp of the top edge of the binary search.&lt;br /&gt;
;lo, lo_pd: file position and timestamp of the bottom edge of the binary search.&lt;br /&gt;
;time_pos: Requested pts.&lt;br /&gt;
;guess: begginning of linear search for syncpoint.&lt;br /&gt;
&lt;br /&gt;
 #define INTERPOLATE_WEIGHT (7./8)&lt;br /&gt;
 if (hi - lo &amp;lt; nut-&amp;gt;max_distance) guess = lo + 8;&lt;br /&gt;
 else { // linear interpolation&lt;br /&gt;
     double a = (double)(hi - lo) / (hi_pd - lo_pd);&lt;br /&gt;
     guess = lo + a * (time_pos - lo_pd);&lt;br /&gt;
     guess = guess * INTERPOLATE_WEIGHT + (lo+hi)/2 * (1 - INTERPOLATE_WEIGHT);&lt;br /&gt;
     if (hi - guess &amp;lt; nut-&amp;gt;max_distance*2) guess = hi - nut-&amp;gt;max_distance*2; //(lo + hi)/2;&lt;br /&gt;
 }&lt;br /&gt;
 if (guess &amp;lt; lo + 8) guess = lo + 8;&lt;br /&gt;
&lt;br /&gt;
The first conditional prevent too much recursing when the distance is already low. The last conditional prevents infinite loop of syncpoint search constantly finding ''lo'' and achieving nothing.&lt;br /&gt;
&lt;br /&gt;
==== Binary search ====&lt;br /&gt;
Now, find a syncpoint, bounded between ''guess'' and ''hi''. If it has a pts higher than requested pts, then replace ''hi'' and ''hi_pd'', otherwise replace ''lo'' and ''lo_pd''.&lt;br /&gt;
If a syncpoint was not found between ''guess'' and ''hi'', then, if ''guess'' is smaller or equal to ''lo + 11'', then you have scanned the entire area between ''lo'' and ''hi'', and your binary search is done. Otherwise, replace ''hi'' with ''guess'' and repeat the binary search.&lt;br /&gt;
&lt;br /&gt;
After finding the 2 closest syncpoints bounding your requested pts, the bounds of linear are search are:&lt;br /&gt;
&lt;br /&gt;
 *start = lo_s.pos - (lo_s.back_ptr * 8 + 7);&lt;br /&gt;
 *end = lo_s.pos;&lt;br /&gt;
 *stopper = hi_s;&lt;br /&gt;
&lt;br /&gt;
''stopper'' is used later to end linear search prematurely.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Linear search ===&lt;br /&gt;
&lt;br /&gt;
==== Bounds of linear search ====&lt;br /&gt;
Linear search ofcourse ends at ''end'', however, it can end earlier:&lt;br /&gt;
* When you find any frame of an active stream, with a pts higher than requested pts.&lt;br /&gt;
* When you find a syncpoint immediately following the syncpoint pointed to by ''stopper'''s back_ptr, (from here on this syncpoint will be called ''stopper_syncpoint'') '''and''' all streams are active.&lt;br /&gt;
* When you find a keyframe for all '''non'''-active streams after after ''stopper_syncpoint'' with a pts higher than ''stopper.pts''. The logic is:&lt;br /&gt;
** ''stopper.pts'' is higher than requested pts.&lt;br /&gt;
** ''stopper_syncpoint'' is '''not''' the syncpoint pointed to by ''stopper.back_ptr'', but the one immediately following.&lt;br /&gt;
** If there was a keyframe for every non active stream after ''stopper_syncpoint'', with a pts lower than ''stopper.pts'', then the reason ''stopper'' does not point to ''stopper_syncpoint'' must be that there are no keyframes for '''active''' streams with a pts lower than ''stopper.pts'' after ''stopper_syncpoint''.&lt;br /&gt;
** There might be more keyframes in the region with a pts higher than ''stopper.pts'', but those are irrelavent because they are higher than requested pts.&lt;br /&gt;
&lt;br /&gt;
==== Linear search implementation ====&lt;br /&gt;
&lt;br /&gt;
# Start at ''start''.&lt;br /&gt;
# Search for syncpoint. If it is further than ''start + 7'', then the file is errored, and you can start playing immediately from this syncpoint.&lt;br /&gt;
# Preform full demuxing, buffering everything read.&lt;br /&gt;
# On every syncpoint, flush the buffer and cache the syncpoint position.&lt;br /&gt;
# When finding keyframe of active stream with pts lower than requested pts, store position of keyframe. Discard previous value.&lt;br /&gt;
# End linear search as necessary by bounds given above.&lt;br /&gt;
# Pick the lowest value from positions of keyframes for active streams, This is the final position.&lt;br /&gt;
# Seek to closest syncpoint before the final position, preform a minimal demuxing until final position (to get proper last_pts context across all streams).&lt;br /&gt;
&lt;br /&gt;
=== Index ===&lt;br /&gt;
With index, binary search step is skipped, and a much more limited linear search used, between two immediate syncpoints. The syncpoint picked are the highest possible ones that have a keyframe for each active stream past the syncpoint with a pts lower than requested pts. The end of the linear search is the syncpoint immediately following.&lt;br /&gt;
&lt;br /&gt;
Dynamic index is used in the same manner as complete index. However, when deciding a syncpoint, the entire range of the syncpoint picked until the first syncpoint with a pts higher than requested is checked for having been already reaserched. If a &amp;quot;hole&amp;quot; is found anywhere in this range, dynamic index is disregarded and full binary search is preformed.&lt;br /&gt;
&lt;br /&gt;
[[Category:Container Formats]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=User:Ods15&amp;diff=1546</id>
		<title>User:Ods15</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=User:Ods15&amp;diff=1546"/>
		<updated>2006-01-17T05:31:32Z</updated>

		<summary type="html">&lt;p&gt;Ods15: me&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I'm Oded Shimon, [[MPlayer]] developer. My main current project right now is [[NUT]].&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=Microsoft_Audio/Video_Interleaved&amp;diff=1544</id>
		<title>Microsoft Audio/Video Interleaved</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=Microsoft_Audio/Video_Interleaved&amp;diff=1544"/>
		<updated>2006-01-16T18:56:07Z</updated>

		<summary type="html">&lt;p&gt;Ods15: /* AVI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Uses RIFF tree for structure.&lt;br /&gt;
&lt;br /&gt;
== RIFF ==&lt;br /&gt;
&lt;br /&gt;
General structure for all RIFF nodes:&lt;br /&gt;
&lt;br /&gt;
Nodes can be data or '''LIST''', data structure is:&lt;br /&gt;
&lt;br /&gt;
 4 bytes name (a.k.a. FourCC)&lt;br /&gt;
 4 bytes length, 32 bit integer in little-endian&lt;br /&gt;
 ''length'' bytes data&lt;br /&gt;
 optionally 1 byte padding if length is odd&lt;br /&gt;
&lt;br /&gt;
'''LIST''' structure is:&lt;br /&gt;
&lt;br /&gt;
 4 bytes string &amp;quot;LIST&amp;quot;&lt;br /&gt;
 4 bytes length, 32 bit integer in little-endian&lt;br /&gt;
 4 bytes name&lt;br /&gt;
 ''length'' bytes data - data is a list of nodes.&lt;br /&gt;
 optionally 1 byte padding if length is odd&lt;br /&gt;
&lt;br /&gt;
An entire RIFF file has the structure:&lt;br /&gt;
&lt;br /&gt;
 4 bytes string &amp;quot;RIFF&amp;quot;&lt;br /&gt;
 4 bytes length, 32 bit integer in little-endian&lt;br /&gt;
 4 bytes name&lt;br /&gt;
 ''length'' bytes data - data is a list of nodes.&lt;br /&gt;
&lt;br /&gt;
== AVI ==&lt;br /&gt;
&lt;br /&gt;
An AVI has this RIFF structure:&lt;br /&gt;
&lt;br /&gt;
 RIFF &amp;quot;AVI &amp;quot; (space at end)&lt;br /&gt;
     LIST &amp;quot;hdrl&amp;quot;&lt;br /&gt;
     DATA &amp;quot;avih&amp;quot;, len: 56&lt;br /&gt;
         LIST &amp;quot;strl&amp;quot;&lt;br /&gt;
             DATA &amp;quot;strh&amp;quot;, len: 56&lt;br /&gt;
             DATA &amp;quot;strf&amp;quot;&lt;br /&gt;
         ''LIST &amp;quot;strl&amp;quot;''&lt;br /&gt;
             ...&lt;br /&gt;
     ''LIST: name: `INFO''' (optional)&lt;br /&gt;
         ...&lt;br /&gt;
     LIST &amp;quot;movi&amp;quot;&lt;br /&gt;
         DATA &amp;quot;00dc&amp;quot;&lt;br /&gt;
         DATA &amp;quot;01wb&amp;quot;&lt;br /&gt;
         ...&lt;br /&gt;
     DATA &amp;quot;idx1&amp;quot;&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=AVI&amp;diff=1543</id>
		<title>AVI</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=AVI&amp;diff=1543"/>
		<updated>2006-01-16T18:50:24Z</updated>

		<summary type="html">&lt;p&gt;Ods15: redirect&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Microsoft Audio/Video Interleaved]]&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=Microsoft_Audio/Video_Interleaved&amp;diff=1542</id>
		<title>Microsoft Audio/Video Interleaved</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=Microsoft_Audio/Video_Interleaved&amp;diff=1542"/>
		<updated>2006-01-16T18:46:13Z</updated>

		<summary type="html">&lt;p&gt;Ods15: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Uses RIFF tree for structure.&lt;br /&gt;
&lt;br /&gt;
== RIFF ==&lt;br /&gt;
&lt;br /&gt;
General structure for all RIFF nodes:&lt;br /&gt;
&lt;br /&gt;
Nodes can be data or '''LIST''', data structure is:&lt;br /&gt;
&lt;br /&gt;
 4 bytes name (a.k.a. FourCC)&lt;br /&gt;
 4 bytes length, 32 bit integer in little-endian&lt;br /&gt;
 ''length'' bytes data&lt;br /&gt;
 optionally 1 byte padding if length is odd&lt;br /&gt;
&lt;br /&gt;
'''LIST''' structure is:&lt;br /&gt;
&lt;br /&gt;
 4 bytes string &amp;quot;LIST&amp;quot;&lt;br /&gt;
 4 bytes length, 32 bit integer in little-endian&lt;br /&gt;
 4 bytes name&lt;br /&gt;
 ''length'' bytes data - data is a list of nodes.&lt;br /&gt;
 optionally 1 byte padding if length is odd&lt;br /&gt;
&lt;br /&gt;
An entire RIFF file has the structure:&lt;br /&gt;
&lt;br /&gt;
 4 bytes string &amp;quot;RIFF&amp;quot;&lt;br /&gt;
 4 bytes length, 32 bit integer in little-endian&lt;br /&gt;
 4 bytes name&lt;br /&gt;
 ''length'' bytes data - data is a list of nodes.&lt;br /&gt;
&lt;br /&gt;
== AVI ==&lt;br /&gt;
&lt;br /&gt;
An AVI has this RIFF structure:&lt;br /&gt;
&lt;br /&gt;
 RIFF: name: `AVI ' (space at end)&lt;br /&gt;
     LIST: name: `hdrl'&lt;br /&gt;
     DATA: name: `avih', len: 56&lt;br /&gt;
         LIST: name: `strl'&lt;br /&gt;
             DATA: name: `strh', len: 56&lt;br /&gt;
             DATA: name: `strf'&lt;br /&gt;
         LIST: name: `strl'&lt;br /&gt;
             DATA: name: `strh', len: 56&lt;br /&gt;
             DATA: name: `strf'&lt;br /&gt;
     LIST: name: `INFO'&lt;br /&gt;
         optional info&lt;br /&gt;
     LIST: name: `movi'&lt;br /&gt;
         DATA: name: `00dc'&lt;br /&gt;
         DATA: name: `01wb'&lt;br /&gt;
         ...&lt;br /&gt;
     DATA: name: `idx1'&lt;/div&gt;</summary>
		<author><name>Ods15</name></author>
	</entry>
</feed>