Patch title: Release 94 bulk changes
Abstract:
File: /pliant/linux/multimedia/libmpeg2.pli
Key:
    Removed line
    Added line
   
module "/pliant/language/compiler.pli"
module "/pliant/language/stream.pli"
module "/pliant/util/pml/io.pli"
module "/pliant/language/type/misc/blob.pli"

module "/pliant/graphic/console/prototype.pli"
module "/pliant/graphic/console/x11.pli"
module "/pliant/graphic/image/prototype.pli"
module "/pliant/graphic/image/pixmap.pli"
module "/pliant/graphic/color/gamut.pli"

constant libmpeg2 (shunt (file_query "file:/lib/libmpeg2.so" standard)=defined or (file_query "file:/usr/lib/libmpeg2.so" standard)=defined "libmpeg2.so" (file_query "file:/usr/lib/libmpeg2.so.0" standard)=defined "libmpeg2.so.0" "libmpeg2.so")
constant libmpeg2convert (shunt (file_query "file:/lib/libmpeg2convert.so" standard)=defined or (file_query "file:/usr/lib/libmpeg2convert.so" standard)=defined "libmpeg2convert.so" (file_query "file:/usr/lib/libmpeg2convert.so.0" standard)=defined "libmpeg2convert.so.0" "libmpeg2convert.so")


function mpeg2_init -> decoder
  arg Address decoder
  external libmpeg2 "mpeg2_init"

type mpeg2_size
  field Int x y

type mpeg2_sequence
  field Int width height
  field Int chroma_width chroma_height
  field Int byte_rate
  field Int bvb_buffer_size
  field uInt32 flags
  field Int picture_width picture_height
  field Int display_width display_height
  field Int pixel_width pixel_height
  field Int frame_period
  field uInt8 profile_level_id color_primaries transfer_characteristics matrix_coefficients
# console "mpeg2_sequence size = " mpeg2_sequence:size eol
  
type mpeg2_picture
  field Int temporal_reference
  field Int nb_fields
  field uInt32 tag tag2 flags
  field (Array mpeg2_size 3) display_offset

type mpeg2_fbuf
  field (Array Address 3) buf
  field Address id

type mpeg2_info
  field Pointer:mpeg2_sequence sequence
  field Address gop
  field Pointer:mpeg2_picture current_picture current_picture_2nd
  field Pointer:mpeg2_fbuf current_fbuf
  field Pointer:mpeg2_picture display_picture display_picture_2nd
  field Pointer:mpeg2_fbuf display_fbuf discard_fbuf
  field Address user_data
  field Int user_data_len

function mpeg2_info decoder -> info
  arg Address decoder ; arg_C mpeg2_info info
  external libmpeg2 "mpeg2_info"

function mpeg2_close decoder
  arg Address decoder
  external libmpeg2 "mpeg2_close"

function mpeg2_parse decoder -> state
  arg Address decoder ; arg Int state
  external libmpeg2 "mpeg2_parse"

function mpeg2_buffer decoder start stop
  arg Address decoder ; arg Address start stop
  external libmpeg2 "mpeg2_buffer"

function mpeg2_convert decoder func data
  arg Address decoder func data
  external libmpeg2 "mpeg2_convert"

function mpeg2convert_rgb order bpp -> func
  arg Int order bpp ; arg Address func
  external libmpeg2convert "mpeg2convert_rgb"

function mpeg2_skip decoder skip
  arg Address decoder ; arg Int skip
  external libmpeg2 "mpeg2_skip"

function mpeg2_reset decoder full_reset
  arg Address decoder ; arg CBool full_reset
  external libmpeg2 "mpeg2_reset"

constant STATE_BUFFER 0
constant STATE_SEQUENCE 1
constant STATE_GOP 3
constant STATE_PICTURE 4
constant STATE_SLICE 7
constant STATE_END 8
constant STATE_INVALID 9
constant STATE_INVALID_END 10

function libmpeg2_play filename options start late sem
  arg Str filename options ; arg DateTime start ; arg_rw Float late ; arg_rw FastSem sem
  (var Stream input) open filename in
  var Address decoder := mpeg2_init
  var Pointer:mpeg2_info info :> mpeg2_info decoder
  var CBool continue := true
  var Float hz := options option "hz" Float 25
  var Int counter := 0
  var CBool multiplexed := options option "multiplexed"
  var Int scale_x := options option "scale_x" Int (options option "scale" Int 1)
  var Int scale_y := options option "scale_y" Int (options option "scale" Int 1)
  while continue
    var Int state := mpeg2_parse decoder
    if state=STATE_BUFFER
      var Address adr ; var Int size
      if multiplexed
        if (input iraw (var Float ts))
          void
        if (input iraw (var Blob blob))
          adr := blob content
          size := blob size
      else
        input read_available adr size
      mpeg2_buffer decoder adr (adr translate Byte size)
      if size=0
        continue := false
    eif state=STATE_SEQUENCE
      # console "sequence" eol
      var Link:ConsolePrototype video :> graphic_console "x11"
      var Int video_x := info:sequence width
      var Int video_y := info:sequence height
      # console "video " video_x " x " video_y eol
      # console "frame period is " info:sequence:frame_period eol
      # console "screen gamut is " video:query:gamut:name eol
      var ImagePrototype proto := image_prototype 0 0 1 1 video_x*scale_x video_y*scale_y video:query:gamut
      if (video open proto "")=failure
        console "failed to open video hardware" eol
        return
      var Link:ImagePixmap pixmap :> new ImagePixmap
      pixmap setup proto ""
      mpeg2_convert decoder (mpeg2convert_rgb (shunt (proto:gamut:name parse "rgb" any) 1 0) proto:gamut:pixel_size*8) null
    eif state=STATE_GOP
      # console "gop" eol
      void
    eif state=STATE_SLICE or state=STATE_END
      var Float wait := start:seconds+counter/hz-datetime:seconds
      sem request ; wait += late ; sem release
      if wait>(-1/hz)
        if (exists info:display_fbuf)
          for (var Int y) 0 pixmap:size_y-1
            var Address src := info:display_fbuf:buf:0 translate uInt8 y\scale_y*pixmap:line_size\scale_x
            var Address dest := pixmap pixel 0 y
            if scale_x=1
              memory_copy src dest pixmap:line_size
            eif y%scale_y<>0
              src := dest translate Byte -(pixmap:line_size)
              memory_copy src dest pixmap:line_size
            else
              var Int ps := pixmap pixel_size
              for (var Int i) 0 video_x-1
                for (var Int j) 0 scale_x-1
                  dest map uInt32 := src map uInt32
                  dest := dest translate Byte ps
                src := src translate Byte ps
        var Float wait := start:seconds+counter/hz-datetime:seconds
        sem request ; wait += late ; sem release
        if wait>0
          sleep wait
        video paint pixmap 0 0
      if state=STATE_END
        continue := false
      counter += 1
    eif state=STATE_INVALID
      console "unexpected mpeg2 state " state eol
      continue := false
  mpeg2_close decoder

function play filename
  arg Str filename
  var Float late := 0
  libmpeg2_play filename "" datetime late (var FastSem sem)

export libmpeg2_play play