123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364(*
* Copyright 2011 The Savonet Team
*
* This file is part of ocaml-mm.
*
* ocaml-mm is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ocaml-mm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with ocaml-mm; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* As a special exception to the GNU Library General Public License, you may
* link, statically or dynamically, a "work that uses the Library" with a publicly
* distributed version of the Library to produce an executable file containing
* portions of the Library, and distribute that executable file under terms of
* your choice, without any of the additional requirements listed in clause 6
* of the GNU Library General Public License.
* By "a publicly distributed version of the Library", we mean either the unmodified
* Library as distributed by The Savonet Team, or a modified version of the Library that is
* distributed under the conditions defined in clause 3 of the GNU Library General
* Public License. This exception does not however invalidate any other reasons why
* the executable file might be covered by the GNU Library General Public License.
*
*)openMm_base(* open Mm_image *)(** Images from which are made videos. *)moduletypeImage=sigtypetvalcreate:int->int->tvalsize:t->intvalblit_all:t->t->unitvalcopy:t->tvalblank:t->unitvalrandomize:t->unitendmoduleImage=structincludeMm_image.Image.YUV420letcreatewh=createwhletscale=scale~proportional:falseendmoduleMake(Image:Image)=structmoduleI=Imagetypet=Image.tarraytypebuffer=tletmakelenwidthheight=Array.initlen(fun_->Image.createwidthheight)letsingleimg=[|img|]letblitsbufsofsdbufdofslen=fori=0tolen-1doImage.blit_allsbuf.(sofs+i)dbuf.(dofs+i)doneletcopyvid=Array.mapImage.copyvidletlengthvid=Array.lengthvidletsizevid=letn=ref0infori=0toArray.lengthvid-1don:=!n+Image.sizevid.(i)done;!nletgetvidi=vid.(i)letsetvidiimg=vid.(i)<-imgletiterfvidofflen=fori=offtooff+len-1dofvid.(i)doneletblankvidofflen=iterImage.blankvidofflenletrandomizevidofflen=iterImage.randomizevidofflenendincludeMake(Image)(* Canvas are not in place so that we have to make a slightly different
implementation. *)moduleCanvas=structmoduleImage=Mm_image.Image.Canvas(Image)typeimage=Image.ttypet=Image.tarrayletmakelen(width,height):t=Array.initlen(fun_->Image.createwidthheight)letsingleimg=[|img|]letsingle_imageimg=single(Image.makeimg)letlength(v:t)=Array.lengthvletcopy(v:t)=Array.init(lengthv)(funi->v.(i))letsize(v:t)=letn=ref0infori=0toArray.lengthv-1don:=!n+Image.sizev.(i)done;!nletgetvi=v.(i)letsetviimg=v.(i)<-imgletmap_imagefvi=v.(i)<-fv.(i)letrendervi=Image.renderv.(i)letputviimg=v.(i)<-Image.makeimgletblitsbufsofsdbufdofslen=fori=0tolen-1dodbuf.(dofs+i)<-sbuf.(sofs+i)doneletmapfbufofslen=fori=ofstoofs+len-1dobuf.(i)<-fbuf.(i)doneletblankbufofslen=map(funimg->Image.create(Image.widthimg)(Image.heightimg))bufofslenletiterfbufofslen=fori=ofstoofs+len-1dobuf.(i)<-Image.iterfbuf.(i)doneend(*
module RE = struct
type t = Image.t
let create () = Image.create 0 0
let blit = blit
end
*)(* module Ringbuffer_ext = Ringbuffer.Make_ext (RE) *)(* module Ringbuffer = Ringbuffer.Make (RE) *)moduleFPS=structtypet=float(* TODO: improve this! *)letto_fracf=letn=floor((f*.100.)+.0.5)inletn=int_of_floatninifnmod100=0then(n/100,1)else(n,100)endmoduleIO=structexceptionInvalid_filemoduleReader=structclasstypet=objectmethodwidth:intmethodheight:intmethodframe_rate:float(* method set_target_size : int -> int -> unit *)methodread:buffer->int->int->int(* method read_audio : Audio.buffer -> int -> int -> int *)methodclose:unitendendmoduleWriter=structclasstypet=objectmethodwrite:buffer->int->int->unit(* method write_audio : Audio.buffer -> int -> int -> unit *)methodclose:unitendclassvirtualaviframe_ratewh=letframes_per_chunk=int_of_float(frame_rate+.0.5)inletframe_size=w*h*3inobject(self)inheritIO.helpermethodvirtualprivatestream_write:string->int->int->intmethodvirtualprivatestream_seek:int->unitmethodvirtualprivatestream_close:unitinitializerself#output"RIFF";self#output_int0;(* TOFILL: file size *)self#output"AVI ";(* file type *)(* Headers *)self#output"LIST";self#output_int192;(* size of the list *)self#output"hdrl";(* AVI header *)self#output"avih";self#output_int56;(* AVI header size *)self#output_int(int_of_float(1000000./.frame_rate));(* microseconds per frame *)self#output_int0;(* max bytes per sec *)self#output_int0;(* pad to multiples of this size *)self#output_byte0;(* flags *)self#output_byte1;(* flags (interleaved) *)self#output_byte0;(* flags *)self#output_byte0;(* flags *)self#output_int0;(* TOFILL: total number of frames *)self#output_int0;(* initial frame *)self#output_int1;(* number of streams (TODO: change if audio) *)self#output_int0;(* suggested buffer size *)self#output_intw;(* width *)self#output_inth;(* height *)self#output_int0;(* scale *)self#output_int0;(* rate *)self#output_int0;(* start *)self#output_int0;(* length *)(* Stream headers *)self#output"LIST";self#output_int116;self#output"strl";(* Stream header *)self#output"strh";self#output_int56;self#output"vids";self#output"RGB ";(* codec *)self#output_int0;(* flags *)self#output_int0;(* stream priority and language *)self#output_int0;(* initial frames *)self#output_int10;(* scale : rate / scale = frames / second or samples / second *)self#output_int(int_of_float(frame_rate*.10.));(* rate *)self#output_int0;(* stream start time (in frames). *)self#output_int0;(* TOFILL: stream length (= number of frames) *)self#output_int(frames_per_chunk*frame_size);(* suggested buffer size *)self#output_int0;(* stream quality *)self#output_int0;(* size of samples *)self#output_short0;(* destination rectangle: left *)self#output_short0;(* top *)self#output_shortw;(* right *)self#output_shorth;(* bottom *)(* Stream format *)self#output"strf";self#output_int40;self#output_int40;(* video size (????) *)self#output_intw;(* width *)self#output_inth;(* height *)self#output_short1;(* panes *)self#output_short24;(* color depth *)self#output_int0;(* tag1 (????) *)self#output_intframe_size;(* image size *)self#output_int0;(* X pixels per meter *)self#output_int0;(* Y pixels per meter *)self#output_int0;(* colors used *)self#output_int0;(* important colors *)(* movie data *)self#output"LIST";self#output_int0;(* TOFILL: movie size *)self#output"movi";(* video chunks follow *)self#output"00dc";self#output_int0(* TOFILL: size *)valmutabledatalen=0valmutabledataframes=0methodwrite(_:buffer)ofslen=for_=ofstoofs+len-1do(* let s = Image.to_RGB24_string buf.(i) in *)lets=failwith"TODO: output YUV420 avi"inself#outputs;datalen<-datalen+String.lengthsdone;dataframes<-dataframes+lenmethodclose=Printf.printf"completing... (%d frames)\n%!"dataframes;self#stream_seek4;self#output_int(datalen+(56*4));self#stream_seek(12*4);self#output_intdataframes;self#stream_seek(35*4);self#output_intdataframes;self#stream_seek(54*4);self#output_int(datalen+(3*4));self#stream_seek(57*4);self#output_intdatalen;self#stream_closeendclassto_avi_filefnamefrwh=objectinheritavifrwhinheritIO.Unix.rw~write:truefnameendendend