[MPlayer-dev-eng] Lots of stuff for NUT
Oded Shimon
ods15 at ods15.dyndns.org
Thu Jan 5 19:30:25 CET 2006
On Thu, Jan 05, 2006 at 08:14:08PM +0200, Oded Shimon wrote:
> yes, ofcourse EOR streams are ignored in back ptr, however we cannot
> enforce EOR being set for every subtitle gap, it SHOULD be used, but not
> MUST.
>
> BTW, with the "ancient" index method with max_index_distance, we were NOT
> under 10kb an hour, unless max_index_distance was 512kb. When it was 32kb,
> the index was 100kb or so. However a syncpoint index with single back_ptr
> and syncpoints collapsed, the index is indeed 5-8kb.
>
> Anyway, here are my new patches, we're back to single back_ptr, hurray.
>
> step 1: mosly cosmetic
> 1) change date and goals slightly
> 2) fix 's' in info packets
> 3) rename sync_point to syncpoint, and frame_startcode to syncpoint_startcode
>
> step 2:
> 1) MN rule
>
> step 3:
> 1) remove global_timebase
> 2) define convert_ts
> 3) use coded_pts for syncpoint
>
> step 4:
> 1) rearrange main header
> 2) add coded_stream_flags
> 3) add EOR
>
> step 5:
> 1) remove max_index_distance
> 2) change goals
> 3) change index
> 4) Add pts rule for syncpoint - the max pts of all keyframes in all
> streams. I've given this much thought before we were dealing with per
> stream stuff, and it is the only perfectly correct pts, the one that
> will only ever rewind you too much, and not not enough.
>
> I never did commit 1 & 3, but I think now I can commit everything here?
> I guess rearranging main header is probably thing we're still undecided on.
Modification to step 5, to the pts rule. The most sane value is:
MAX(MIN(pts of all keyframes in a single stream between back_ptr and syncpoint) across all streams)
otherwise you might not pick this syncpoint because the pts is after
your requested P, even though it is a good syncpoint for you.
The disadvantage for this is I think the implementation is tricky. :/
However it really is the most correct value.
- ods15
-------------- next part --------------
--- mpcf.txt 2006-01-04 07:53:43.000000000 +0200
+++ mpcf.1.txt 2006-01-04 16:20:56.000000000 +0200
@@ -1,5 +1,5 @@
========================================
-NUT Open Container Format DRAFT 20051118
+NUT Open Container Format DRAFT 20060105
========================================
@@ -23,7 +23,7 @@
~0.2% overhead, for normal bitrates
index is <10kb per hour (1 keyframe every 3sec)
a usual header for a file is about 100 bytes (audio + video headers together)
- a packet header is about ~1-8 bytes
+ a packet header is about ~1-5 bytes
Error resistant
seeking / playback without an index
@@ -243,6 +243,8 @@
name vb
if(type=="v")
value v
+ else if(type=="s")
+ value s
else
value vb
}
@@ -254,8 +256,8 @@
packet header
info_frame
-sync_point:
- frame_startcode f(64)
+syncpoint:
+ syncpoint_startcode f(64)
global_timestamp v
back_ptr v
@@ -277,8 +279,8 @@
info_packet
}
while(next_code != main_startcode){
- if(next_code == frame_startcode)
- sync_point
+ if(next_code == syncpoint_startcode)
+ syncpoint
frame
}
}
@@ -316,10 +318,10 @@
stream_starcode
0x11405BF2F9DBULL + (((uint64_t)('N'<<8) + 'S')<<48)
-frame_startcode
+syncpoint_startcode
0xE4ADEECA4569ULL + (((uint64_t)('N'<<8) + 'K')<<48)
- frame_startcodes SHOULD be placed immediately before a keyframe if the
+ syncpoint_startcodes SHOULD be placed immediately before a keyframe if the
previous frame of the same stream was a non-keyframe, unless such
non-keyframe - keyframe transitions are very frequent
@@ -333,8 +335,8 @@
NUT version. The current value is 2.
max_distance
- max distance of frame_startcodes, the distance may only be larger if
- there is only a single frame between the two frame_startcodes this can
+ max distance of syncpoints, the distance may only be larger if
+ there is no more than a single frame between the two syncpoints. This can
be used by the demuxer to detect damaged frame headers if the damage
results in too long of a chain
-------------- next part --------------
--- mpcf.1.txt 2006-01-04 16:20:56.000000000 +0200
+++ mpcf.2.txt 2006-01-04 17:26:05.000000000 +0200
@@ -481,9 +481,9 @@
stream, into which the current pts is inserted and the element with
the smallest value is removed, this is then the current dts
this buffer is initalized with decode_delay -1 elements
- all frames must be monotone, that means a frame
- which occurs later in the stream must have a larger or equal dts
- than an earlier frame
+
+ Pts of all frames in all streams MUST be bigger or equal to dts of all
+ previous frames in all streams, compared in common timebase.
width/height
MUST be set to the coded width/height
-------------- next part --------------
--- mpcf.2.txt 2006-01-04 17:26:05.000000000 +0200
+++ mpcf.3.txt 2006-01-04 17:24:32.000000000 +0200
@@ -135,8 +135,6 @@
stream_count v
max_distance v
max_index_distance v
- global_time_base_nom v
- global_time_base_denom v
for(i=0; i<256; ){
tmp_flag v
tmp_fields v
@@ -258,7 +256,9 @@
syncpoint:
syncpoint_startcode f(64)
- global_timestamp v
+ coded_pts v
+ stream = coded_pts % stream_count
+ global_key_pts = coded_pts/stream_count
back_ptr v
Complete definition:
@@ -306,6 +306,10 @@
one keyframe for each stream lies between the syncpoint to which
real_back_ptr points, and the current syncpoint.
+global_key_pts
+ After a syncpoint, last_pts of each stream is to be set to:
+ last_pts[i] = convert_ts(global_key_pts, timebase[stream], timebase[i])
+
file_id_string
"nut/multimedia container\0"
@@ -383,22 +387,15 @@
29.97 1001 30000
23.976 1001 24000
-global_time_base_nom / global_time_base_denom = global_time_base
- the length of a timer tick in seconds
- global_time_base_nom and global_time_base_denom MUST NOT be 0
- global_time_base_nom and global_time_base_denom MUST be relatively prime
- global_time_base_denom MUST be < 2^31
-
-global_timestamp
- timestamp in global_time_base units
- when a global_timestamp is encountered the last_pts of all
- streams is set to the following:
-
- ln = global_time_base_nom*time_base_denom
- sn = global_timestamp
- d1 = global_time_base_denom
- d2 = time_base_nom
- last_pts = (ln/d1*sn + ln%d1*sn/d1)/d2
+convert_ts
+ To switch from 2 different timebases, the following calculation is
+ defined:
+
+ ln = from_time_base_nom*to_time_base_denom
+ sn = from_timestamp
+ d1 = from_time_base_denom
+ d2 = to_time_base_nom
+ timestamp = (ln/d1*sn + ln%d1*sn/d1)/d2
Note: this calculation MUST be done with unsigned 64 bit integers, and
is equivalent to (ln*sn)/(d1*d2) but this would require a 96bit integer
-------------- next part --------------
--- mpcf.3.txt 2006-01-04 17:24:32.000000000 +0200
+++ mpcf.4.txt 2006-01-05 19:41:53.000000000 +0200
@@ -138,20 +138,26 @@
for(i=0; i<256; ){
tmp_flag v
tmp_fields v
- if(tmp_fields>0) tmp_pts s
- if(tmp_fields>1) tmp_mul v
- if(tmp_fields>2) tmp_stream v
- if(tmp_fields>3) tmp_size v
+ if(tmp_fields>0) tmp_mul v
+ else tmp_mul=1
+ if(tmp_fields>1) tmp_sflag v
+ else tmp_sflag=0
+ if(tmp_fields>2) tmp_pts s
+ else tmp_pts=0
+ if(tmp_fields>3) tmp_stream v
+ else tmp_stream=0
+ if(tmp_fields>4) tmp_size v
else tmp_size=0
- if(tmp_fields>4) tmp_res v
+ if(tmp_fields>5) tmp_res v
else tmp_res=0
- if(tmp_fields>5) count v
+ if(tmp_fields>6) count v
else count= tmp_mul - tmp_size
- for(j=6; j<tmp_fields; j++){
+ for(j=7; j<tmp_fields; j++){
tmp_reserved[i] v
}
for(j=0; j<count && i<256; j++, i++){
flags[i]= tmp_flag;
+ stream_flags[i]= tmp_sflag;
stream_id_plus1[i]= tmp_stream;
data_size_mul[i]= tmp_mul;
data_size_lsb[i]= tmp_size + j;
@@ -212,6 +218,9 @@
if(flags[frame_code]&1){
data_size_msb v
}
+ if(flags[frame_code]&2){
+ coded_stream_flags v
+ }
for(i=0; i<reserved_count[frame_code]; i++)
reserved v
data
@@ -306,6 +315,11 @@
one keyframe for each stream lies between the syncpoint to which
real_back_ptr points, and the current syncpoint.
+ A stream where EOR is set is to be ignored for back_ptr.
+
+ Note: back_ptr can be zero if there is only a single relavent stream
+ and has a keyframe immediately following the syncpoint.
+
global_key_pts
After a syncpoint, last_pts of each stream is to be set to:
last_pts[i] = convert_ts(global_key_pts, timebase[stream], timebase[i])
@@ -421,17 +435,27 @@
different from the first byte of any startcode
flags[frame_code]
- first of the flags from MSB to LSB are called KD
- if D is 1 then data_size_msb is coded, otherwise data_size_msb is 0
- K is the keyframe_type
- 0 -> no keyframe,
- 1 -> keyframe,
- flags=4 can be used to mark illegal frame_code bytes
- frame_code=78 must have flags=4
- Note: frames MUST NOT depend(1) upon frames prior to the last
- frame_startcode
- Important: depend(1) means dependency on the container level (NUT) not
- dependency on the codec level
+ Bit Name Description
+ 1 data_size_msb if set, data_size_msb is at frame header,
+ otherwise data_size_msb is 0
+ 2 more_flags if set, stream control flags are at frame header.
+ 4 invalid if set, frame_code is invalid.
+
+ frame_code=78 ('N') MUST have flags=64
+
+stream_flags
+ stream_flags is "stream_flags[frame_code] ^ coded_stream_flags"
+
+ Bit Name Description
+ 1 is_key if set, frame is keyframe
+ 2 end_of_relevance if set, stream has no relevance on
+ presentation. (EOR)
+
+ EOR frames MUST be zero-length and must be set keyframe.
+ All streams SHOULD end with EOR, where the pts of the EOR indicates the
+ end presentation time of the final frame.
+ An EOR set stream is unset by the first content frames.
+ When an EOR is unset, dts_cache of the stream is reset to -1.
stream_id_plus1[frame_code]
must be <250
@@ -480,7 +504,8 @@
this buffer is initalized with decode_delay -1 elements
Pts of all frames in all streams MUST be bigger or equal to dts of all
- previous frames in all streams, compared in common timebase.
+ previous frames in all streams, compared in common timebase. (EOR
+ frames are NOT exempt from this rule)
width/height
MUST be set to the coded width/height
-------------- next part --------------
--- mpcf.4.txt 2006-01-05 19:41:53.000000000 +0200
+++ mpcf.final.txt 2006-01-05 20:28:03.000000000 +0200
@@ -27,7 +27,7 @@
Error resistant
seeking / playback without an index
- headers & index can be repeated
+ headers can be repeated
damaged files can be played back with minimal data loss and fast
resync times
@@ -134,7 +134,6 @@
version v
stream_count v
max_distance v
- max_index_distance v
for(i=0; i<256; ){
tmp_flag v
tmp_fields v
@@ -228,7 +227,6 @@
index:
index_startcode f(64)
packet header
- stream_id v
max_pts v
index_length v
for(i=0; i<index_length; i++){
@@ -294,9 +292,7 @@
}
}
if (next_code == index_startcode){
- while(!eof){
- index
- }
+ index
index_ptr u(64)
}
@@ -324,6 +320,14 @@
After a syncpoint, last_pts of each stream is to be set to:
last_pts[i] = convert_ts(global_key_pts, timebase[stream], timebase[i])
+ global_key_pts is defined:
+ key_pts = MIN(pts of all keyframes in a single stream between back_ptr
+ and syncpoint)
+ global_key_pts = MAX(key_pts across all streams)
+
+ If back_ptr is zero, global_key_pts MUST be the pts of the frame
+ immediately following the syncpoint.
+
file_id_string
"nut/multimedia container\0"
@@ -339,10 +343,6 @@
syncpoint_startcode
0xE4ADEECA4569ULL + (((uint64_t)('N'<<8) + 'K')<<48)
- syncpoint_startcodes SHOULD be placed immediately before a keyframe if the
- previous frame of the same stream was a non-keyframe, unless such
- non-keyframe - keyframe transitions are very frequent
-
index_startcode
0xDD672F23E64EULL + (((uint64_t)('N'<<8) + 'X')<<48)
@@ -358,17 +358,14 @@
be used by the demuxer to detect damaged frame headers if the damage
results in too long of a chain
+ syncpoints SHOULD be placed immediately before a keyframe if the
+ previous frame of the same stream was a non-keyframe, unless such
+ non-keyframe - keyframe transitions are very frequent
+
SHOULD be set to <=32768 or at least <=65536 unless there is a very
good reason to set it higher, otherwise reasonable error recovery will
be impossible
-max_index_distance
- max distance of keyframes which are represented in the index, the
- distance between consecutive entries A and B may only be larger if
- there are no keyframes within this stream between A and B
- SHOULD be set to <=32768 or at least <=65536 unless there is a very
- good reason to set it higher
-
stream_id
Stream identifier
stream_id MUST be < stream_count
@@ -532,23 +529,30 @@
forward_ptr until last byte before the checksum).
max_pts
- The highest pts in the stream.
+ s = max_pts % stream_count
+ pts = max_pts / stream_count
+ The highest pts in the entire file in the timebase of stream 's'.
index_pts
- value of the pts of a keyframe relative to the last keyframe
- stored in this index
+ s = index_pts % stream_count
+ pts = index_pts / stream_count
+ pts is relative to last index entry by:
+ pts += convert(last_index_pts, timebase[last_index_s], timebase[s])
+ pts is the lowest global_key_pts of a group of syncpoints with a common
+ back_ptr.
index_position
- position in bytes of the first byte of a keyframe, relative to the
- last keyframe stored in this index
- there MUST be no keyframe with the same stream_id as this index between
- two consecutive index entries if they are more than max_index_distance
- apart
+ relative to last index_position.
+ real_back_ptr = index_position * 8
+ offset from begginning of file to up to 7 bytes before the syncpoint,
+ pointed to by the back_ptr of the syncpoint referred to in this index
+ entry. All syncpoints with a common back_ptr MUST be reduced to a
+ single index entry, with the pts of the first syncpoint.
index_ptr
- Length in bytes from the first byte of the first index startcode
- to the first byte of the index_ptr. If there is no index, index_ptr
- MUST NOT be written.
+ Length in bytes from the first byte of the index startcode to the first
+ byte of the index_ptr. If there is no index, index_ptr MUST NOT be
+ written.
id
the ID of the type/name pair, so it is more compact
More information about the MPlayer-dev-eng
mailing list