Menu

#419 Fuse FMFv2

future
open
nobody
5
2019-05-08
2019-05-08
No

Here is a (WIP) patch for fuse (and fuse utils), to implement FMF V2 format (or V1.5?)
(Sorry Fred, a totally forget about your idea: [patches:#390], so I did not implement your concept ... yet)-:

First of all with the new code (and format), we can record timex hires and hicolor movies. I test it with timmy.

What is new in this format:
- the whole file is double linked, so a video player (ffmpeg) can play the file natively as any ordinary video file
- There are index frames in the file, with PTS
- The screen types are changed, now we use only 'N'ormal and 'T'imex hires screens, because we do not need 'hicolor' and 'normal timex'
- The 'new frame' chunk changed
- The screen area ($ - slice) Y coord and height coded on 1 byte (instead of 2)
- The ($)lice chunk now contain a 'compressed size' length, so we can skip this chunk without decode.
- The compression scheme is changed

The fuse patch implement the new format recording.
The fuse-utils patch implement the V1 and V2 format.

Here is the description of chunks:
Fuse Movie File V2:


File Header:
  off  len  data          description
  0    4    "FMF_"      Magic header
  4    2    "V2"        Version
  6    1    <e|E>       Endianness (e - little / E- big)
  7    1    <U|4|Z>     Compression ( U - uncompressed / 4 - LZ4 compressed / Z - zlib compressed )
  8    1    #       Frame rate ( 1:# )
  9    1    <N|T>       Screen type (Spectrum, Timex HiRes)
  10   1    <A|B|C|D|E> timing code
  11   1    <P|U|A>     Sound encoding
  12   2    Freq        Sound freq in Hz
  14   1    <S|M>       Sound stereo / mono
  15   1    "\n"        padding (<new line>)
  Head length: 16
  Data length: 0

e.g. FMF_V2eZ\001$AZ\000\175M   -> little endian compressed normal screen, 48k timing, u-Law mono 32000Hz sound

 Data
Data chunk header
  off  len  data          description
  0    1    <$|S|N|T|I|x|X> Data chunk type
  1    ?    data        chunk specific data

  $ -> screen area (slice)
  off  len  data          description
  0    1    "$"     Marker
  1    1    x       X coord (0-39)
  2    1    y       Y coord (0-239)
  3    1    w       width (1-40)
  4    1    h       height (1-240)
  5    2    length-1    length of compressed data (max. 3x 1.5x40x240 -> 43200)
  7    ?    runlength encoded data bytes
            bitmap1; attrib1        ZX$/HiCol ($/C)
            bitmap1; bitmap2; attrib    HiRes   (R)
          runlength encoding:
            abcdefghbb#gg# -> two identical byte plus len code a #+2 len
  Head length: 7
  Data length: (uint16_t)[5] + 1

  S -> sound chunk
  off  len  data          description
  0    1    "S"     Marker
  1    1    <P|U|A> sound encoding type P-> 16bit signed PCM, U -> u-Law, A -> A-Law
  2    2    Freq        sound freq in Hz always LE
  4    1    <S|M>       channels S-> stereo, M-> mono
  5    2    length-1    length in frames (0-65535) -> 1-65536 sound frame (always LE)
  7    ?    data (16bit PCM LE or BE)
  Head length: 7
  Data length: (uint16_t)[5] + 1

  I -> Index Frame marker
  off  len  data          description
  0    1    "I"     Marker
  1    2    prev-1          length of previouse frame in byte (sound and all slices up to prev I or X)
  3    2    next-1          length of next frame in byte (sound and all slices up to next I or X)
  5    1    high bits of lens,pts   bit0, bit1 -> prev(9,10); bit2, bit3 -> next(9,10), bit4-bit7 -> pts(33-36)
  6    4    pts     presentation time stamp in milliseconds
  Head length: 10
  Data length: 0

  After an "I" chunk there is a New frame (N|C|R) and a full $lice 0,0 40x240 from byte offset 16. So the next
  chunk always a (N)ew frame (or "I")!

  N|T -> New Frame (Normal or Timex)
  off  len  data          description
  0    1    "N"|"T"     Marker
  1    1    #       frame rate 1:#  (1:1 -> ~50/s, 1:2 -> ~25/s ...)
  2    1    <A|B|C|D>   frame timing code A - 16, 48, TC2048, TC2068, Scorpion, SE
                                              B - 128, +2, +2A, +3, +3E
                                              C - TS2068
                                              D - Pentagon
                                              E - 48 NTSC
  Head length: 3
  Data length: 0
  In a frame there are no, one or several screen rectangle (and of course sound data), changed from
  the previouse frame. In an "N" frame there is a bitmap and an attribute, in an
  "R" frame there are two bitmap and an atribute part in $lices.

  x -> link chunk
  off  len  data          description
  0    1    "x"     Marker
  1    2    prev-1          length of previouse frame in byte (sound and all slices up to prev I or x)
  3    2    next-1          length of next frame in byte (sound and all slices up to next I, x or X)
  5    1    high bits of lens   bit0, bit1 -> prev(9,10); bit2, bit3 -> next(9,10)
  Head length: 6
  Data length: 0

  X -> End marker
  off  len  data            description
  0    1    "X"         Marker
  1    2    prev-1          length of previouse frame in byte (sound and all slices up to prev I or x)
  3    1    high bits of length bit0, bit1 -> prev(9,10)
  4    4    pts         presentation time stamp in milliseconds
  8    2    "\r\n"          padding
  Head length: 10
  Data length: 0
  It marks the end of the last frame. So we can concatenate several
  FMF file without any problem...

Note1: all 16bit and 32 bit data writen as LE only sound samples writen with machine native endianness (same as in V1!)
Note2: all screen position data only 1 byte length (max y=239, max w=240)
Note3: there is no "X" Timex normal screen type (the same as $)
Note4: the whole file is "fully" double linked with "x", "I" (and "X") chunks, so we can easily fast rewind and forward
in the file without sync lost. The max distance between link chunks is 256k, ( the max compressed block length is 256k too )
Note5: recommended to insert at least one "I" frame per 1-5 sec
Note6: New frame (N|R|C chunk) exactly means: show prevoiuse frame and now start a new frame, so X "show" the very last frame
Note7: the "I" chunk marks the "prev" frame's PTS, so the just (fully) decoded one's


--Compression--


  z|Z -> compressed block
  off  len  data            description
  0    1    "z"|"Z"         Marker
  1    2    prev-1          length of previouse block
  3    2    next-1          length of next block in byte
  5    1    high bits of lens,pts   bit0, bit1 -> prev(9,10); bit2, bit3 -> next(9,10), bit4-bit7 -> pts(33-36)
  6    4    pts         presentation time stamp in milliseconds
  10   ?    raw deflate stream 
  Head length: 10
  Data length: 0

Note1: In a "Z" block (after uncomressed it) there is at least one "I" chunk.
Note2: In a "z" block (after uncomressed it) there is no any "I" chunk.
Note3: The maximum length of a compressed block is 256k

Compressed file


  File header (not compressed)

  z 1 len1 pts
    [ First block start with a full screen slice ($)
      data chunk
      data chunk
      I len1 pts len2
      after i frame, we start with a full screen slice ($)
      ...
    ]
  Z len1 len2 pts
    [ data chunk
      data chunk
      data chunk
      ...
    ]
  z len2 len3 pts
    [ data chunk
      data chunk
      data chunk
      ...
    ]
  ...
  X len1
2 Attachments

Related

Patches: #390

Discussion


Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.