Patch title: Release 94 bulk changes
Abstract:
File: /pliant/linux/multimedia/libmpeg3.pli
Key:
    Removed line
    Added line
   
module "/pliant/language/compiler.pli"
module "/pliant/language/generator.pli"
module "/pliant/language/stream.pli"
module "/pliant/admin/file.pli"

module "audio.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 libmpeg3 (shunt (file_query "file:/lib/libmpeg3.so" standard)=defined or (file_query "file:/usr/lib/libmpeg3.so" standard)=defined "libmpeg3.so" (file_query "file:/usr/lib/libmpeg3.so.1" standard)=defined "libmpeg3.so.1" "libmpeg3.so")


function i386_fstp f
  arg_w Float f
function generate_i386_fstp64 i f
  arg_rw Instruction i ; arg_rw Function f
  i386_regmem f 11011101b 1 011b i:0
(the_function i386_fstp Float) set_generate_binary (the_function generate_i386_fstp64 Instruction Function)

function assemble_pick i gc
  arg_rw Instruction i ; arg_rw GeneratorContext gc
  gc insert_after_instruction i (instruction (the_function i386_fstp Float) i:0)
  gc remove i

function pick_result f
  arg_w Float f
(the_function pick_result Float) set_generate_assembly (the_function assemble_pick Instruction GeneratorContext)



function mpeg3_open filename -> handle
  arg CStr filename ; arg Address handle
  external libmpeg3 "mpeg3_open"

function mpeg3_set_cpus handle cpus
  arg Address handle ; arg Int cpus
  external libmpeg3 "mpeg3_set_cpus"

function mpeg3_set_mmx handle mmx
  arg Address handle ; arg CBool mmx
  external libmpeg3 "mpeg3_set_mmx"

function mpeg3_close handle
  arg Address handle
  external libmpeg3 "mpeg3_close"


function mpeg3_has_audio handle -> c
  arg Address handle ; arg CBool c
  external libmpeg3 "mpeg3_has_audio"

function mpeg3_total_astreams handle -> streams
  arg Address handle ; arg Int streams
  external libmpeg3 "mpeg3_total_astreams"

function mpeg3_audio_channels handle stream -> channels
  arg Address handle ; arg Int stream channels
  external libmpeg3 "mpeg3_audio_channels"

function mpeg3_sample_rate handle stream -> channels
  arg Address handle ; arg Int stream channels
  external libmpeg3 "mpeg3_sample_rate"

function mpeg3_read_audio handle floats ints channel samples stream -> err
  arg Address handle floats ints ; arg Int channel samples stream err
  external libmpeg3 "mpeg3_read_audio"

function mpeg3_reread_audio handle floats ints channel samples stream
  arg Address handle floats ints ; arg Int channel samples stream
  external libmpeg3 "mpeg3_reread_audio"

function mpeg3_end_of_audio handle stream -> c
  arg Address handle ; arg Int stream ; arg CBool c
  external libmpeg3 "mpeg3_end_of_audio"

function mpeg3_read_audio_chunk handle output size max_size stream -> err
  arg Address handle ; arg Address output ; arg_w Int size ; arg Int max_size stream err
  external libmpeg3 "mpeg3_read_audio_chunk"


function mpeg3_has_video handle -> c
  arg Address handle ; arg CBool c
  external libmpeg3 "mpeg3_has_video"

function mpeg3_total_vstreams handle -> streams
  arg Address handle ; arg Int streams
  external libmpeg3 "mpeg3_total_vstreams"

function mpeg3_video_width handle stream -> w
  arg Address handle ; arg Int stream w
  external libmpeg3 "mpeg3_video_width"

function mpeg3_video_height handle stream -> h
  arg Address handle ; arg Int stream h
  external libmpeg3 "mpeg3_video_height"

function mpeg3_frame_rate handle stream
  arg Address handle ; arg Int stream
  external libmpeg3 "mpeg3_frame_rate"

function mpeg3_read_frame handle rows_ptrs in_x in_y in_w in_h out_w out_h color_model stream -> err
  arg Address handle rows_ptrs ; arg Int in_x in_y in_w in_h out_w out_h color_model stream ; arg CBool err
  external libmpeg3 "mpeg3_read_frame"
  # You must allocate 4 extra bytes in the last output_row. This is scratch area for the MMX routines.

function mpeg3_drop_frames handle frames stream
  arg Address handle ; arg Int frames stream
  external libmpeg3 "mpeg3_drop_frames"

function mpeg3_end_of_video handle stream -> c
  arg Address handle ; arg Int stream ; arg CBool c
  external libmpeg3 "mpeg3_end_of_video"

function mpeg3_read_video_chunk handle output size max_size stream -> err
  arg Address handle ; arg Address output ; arg_w Int size ; arg Int max_size stream err
  external libmpeg3 "mpeg3_read_video_chunk"





function play filename
  arg Str filename
  var Address handle := mpeg3_open file_os_name:filename
  if handle=null
    console "failed to open multimedia file " filename eol
    return
  # mpeg3_set_mmx handle true
  var CBool has_audio := mpeg3_has_audio:handle and { var Int audio_streams := mpeg3_total_astreams handle ; audio_streams>0 }
  if has_audio
    var Int audio_channels := mpeg3_audio_channels handle 0
    var Int audio_rate := mpeg3_sample_rate handle 0
    console "audio: " audio_streams " stream(s) x " audio_channels " channels at " audio_rate " Hz" eol
    var ExtendedStatus status := (var Stream audio) open "audio:" "rate "+string:audio_rate+" channels "+string:audio_channels out+safe
    if status=failure
      console "failed to open audio hardware" eol
      return
  var CBool has_video := mpeg3_has_video:handle and { var Int video_streams := mpeg3_total_astreams handle ; video_streams>0 }
  if has_video
    var Int video_x := mpeg3_video_width handle 0
    var Int video_y := mpeg3_video_height handle 0
    mpeg3_frame_rate handle 0 ; pick_result (var Float video_rate)
    console "video: " video_streams " stream(s) x " video_x " x " video_y " x " video_rate " Hz" eol
    var Link:ConsolePrototype video :> graphic_console "x11"
    var ImagePrototype proto := image_prototype 0 0 1 1 video_x video_y color_gamut:"rgb"
    if (video open proto "")=failure
      console "failed to open video hardware" eol
      return
    var Link:ImagePixmap pixmap :> new ImagePixmap
    pixmap setup proto ""
    (var Array:Address video_rows) size := video_y
    for (var Int i) 0 video_y-1
      video_rows i := pixmap pixel 0 i
  else
    video_rate := 10
  if has_audio
    var Int audio_step := cast audio_rate/video_rate Int
    var Address audio_rough := memory_allocate audio_step*uInt16:size null
    var Address audio_final := memory_allocate audio_channels*audio_step*uInt16:size null
  var DateTime start := datetime
  var DateTime audio_expected := start
  var DateTime video_expected := start
  var Int display_count := 0 ; var Int frame_count := 0
  while has_audio and not (mpeg3_end_of_audio handle 0) or has_video and not (mpeg3_end_of_video handle 0)
    var DateTime now := datetime
    while has_audio and now>=audio_expected
      for (var Int ch) 0 audio_channels-1
        if ch=0
          mpeg3_read_audio handle null audio_rough 0 audio_step 0
        else
          mpeg3_reread_audio handle null audio_rough ch audio_step 0
        for (var Int i) 0 audio_step-1
          audio_final map uInt16 i*audio_channels+ch := audio_rough map uInt16 i
      audio raw_write audio_final audio_channels*audio_step*uInt16:size
      audio_expected seconds += audio_step/audio_rate
    if has_video and now>=video_expected
      audio flush anytime
      var Int drop := cast (now:seconds-video_expected:seconds)*video_rate Int
      if drop>0
        mpeg3_drop_frames handle drop 0
        video_expected seconds += drop/video_rate
        frame_count += drop
      mpeg3_read_frame handle (addressof video_rows:0) 0 0 video_x video_y video_x video_y 0 0
      video paint pixmap 0 0
      video_expected seconds += 1/video_rate
      display_count += 1 ; frame_count += 1
    else
      sleep 0.25/video_rate
      # console "." eol
  console (string 100.0*display_count/frame_count "fixed 0") " % frames rendered."
  if has_audio
    memory_free audio_rough
    memory_free audio_final
  mpeg3_close handle

export play


function mpeg_demux3 filename path -> status
  arg Str filename path ; arg ExtendedStatus status
  var Address handle := mpeg3_open file_os_name:filename
  if handle=null
    console "failed to open multimedia file " filename eol
    return
  var Int buffer_size := 2^20
  var Address buffer := memory_allocate buffer_size null
  # mpeg3_set_mmx handle true
  var CBool has_audio := mpeg3_has_audio:handle and { var Int audio_streams := mpeg3_total_astreams handle ; audio_streams>0 }
  if has_audio
    var Int audio_channels := mpeg3_audio_channels handle 0
    var Int audio_rate := mpeg3_sample_rate handle 0
    console "audio: " audio_streams " stream(s) x " audio_channels " channels at " audio_rate " Hz" eol
    (var Stream audio) open path+"test.mp2" out+safe
    while { var Int err1 := mpeg3_read_audio_chunk handle buffer (var Int size) buffer_size 0 ; err1=0 }
      audio raw_write buffer size
    audio close
  var CBool has_video := mpeg3_has_video:handle and { var Int video_streams := mpeg3_total_astreams handle ; video_streams>0 }
  if has_video
    var Int video_x := mpeg3_video_width handle 0
    var Int video_y := mpeg3_video_height handle 0
    mpeg3_frame_rate handle 0 ; pick_result (var Float video_rate)
    console "video: " video_streams " stream(s) x " video_x " x " video_y " x " video_rate " Hz" eol
    (var Stream video) open path+"test.mpv" out+safe
    while { var Int err2 := mpeg3_read_video_chunk handle buffer (var Int size) buffer_size 0 ; err2=0 }
      video raw_write buffer size
    video close
  memory_free buffer
  mpeg3_close handle

export mpeg_demux3