/* GridFlow Copyright (c) 2001-2010 by Mathieu Bouchard This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See file ../COPYING for further informations on licensing terms. This program 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 General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define QUICKTIMEHW_INCLUDE_HERE #include "gridflow.hxx.fcs" #include #include #include #include #include static map *> codecs; static map fourccs; \class FormatQuickTimeHW : Format { quicktime_t *anim; int track; Dim dim; bool gotdim; char *m_codec; int colorspace; int channels; bool started; Dim force; bool doforce; float64 m_framerate; P bit_packing; int jpeg_quality; // in theory we shouldn't need this, but... float advance; ~FormatQuickTimeHW() {if (anim) quicktime_close(anim);} \constructor (t_symbol *mode, string filename) { track=0; gotdim=false; m_codec=const_cast(QUICKTIME_RAW); started=false; doforce=false; m_framerate=29.97; bit_packing=0; jpeg_quality=75; advance = 0; // libquicktime may be nice, but it won't take a filehandle, only filename filename = gf_find_file(filename); anim = quicktime_open((char *)filename.data(),mode==gensym("in"),mode==gensym("out")); if (!anim) RAISE("can't open file `%s': see error message above",filename.data()); if (mode==gensym("in")) { /* This doesn't really work: (is it just for encoding?) if (!quicktime_supported_video(anim,track)) RAISE("quicktime: unsupported codec: %s", quicktime_video_compressor(anim,track)); */ } _0_colorspace(string("rgb")); quicktime_set_cpus(anim,1); uint32 mask[3] = {0x0000ff,0x00ff00,0xff0000}; bit_packing = new BitPacking(is_le(),3,3,mask); with_audio = false; } \decl 0 bang (); \decl 0 seek (int32 frame) { quicktime_set_video_position(anim,clip(frame,int32(0),int32(quicktime_video_length(anim,track)-1)),track); } \decl 0 rewind () {_0_seek(0);} \decl 0 force_size (int32 height, int32 width) {force = Dim(height, width); doforce=true;} \decl 0 colorspace (string c); //!@#$ should also support symbol values (how?) \decl 0 parameter (string name, int32 value) { int val = value; //post("quicktime_set_parameter %s %d",name.data(), val); quicktime_set_parameter(anim, const_cast(name.data()), &val); if (name=="jpeg_quality") jpeg_quality=value; } \decl 0 size (int32 height, int32 width) { if (gotdim) RAISE("video size already set!"); // first frame: have to do setup dim = Dim(height,width,3); gotdim = true; quicktime_set_video(anim,1,dim[1],dim[0],m_framerate,m_codec); quicktime_set_cmodel(anim,colorspace); } \grin 0 int \attr int32 frames(); \attr float64 framerate(); \attr int32 height(); \attr int32 width(); \attr int32 depth(); \attr string codec(); \attr bool with_audio; }; \def 0 framerate (float64 f) {m_framerate=f; quicktime_set_framerate(anim, f);} \def 0 bang () { if (with_audio) { int track = 0; float a_rate = quicktime_sample_rate(anim,track); float v_rate = quicktime_frame_rate(anim,track); advance -= a_rate/v_rate; if (advance < 0) { int samples = 2*1024; //post("audio rate = %f, video rate = %f, ratio = %f",a_rate,v_rate,a_rate/v_rate); int achannels = quicktime_track_channels(anim,track); float sound[achannels*samples]; float *output_f[achannels]; for (int j=0; j= length) {out[0](); return;} /* if it works, only do it once, to avoid silly stderr messages forgotten in LQT */ if (!quicktime_reads_cmodel(anim,colorspace,0) && !started) { RAISE("LQT says this video cannot be decoded into the chosen colorspace"); } int sx = quicktime_video_width(anim,track); int sy = quicktime_video_height(anim,track); int sz = quicktime_video_depth(anim,track); channels = sz/8; // hack. how do i get the video's native colormodel ? switch (sz) { case 24: colorspace=BC_RGB888; break; case 32: colorspace=BC_RGBA8888; break; default: post("strange quicktime. ask matju."); break; } if (doforce) {sy = force[0]; sx = force[1];} uint8 buf[sy*sx*channels]; uint8 *rows[sy]; for (int i=0; i1) { uint8 data2[n]; bit_packing->pack(sx*sy,data,(uint8 *)data2); for (int i=0; iname) {fprintf(stderr,"[#in quicktime]: skipping codec with null name!\n"); continue;} string name = string(s->name); vector *f = new vector(s->num_fourccs); if (!s->fourccs) {post("WARNING: no fourccs (quicktime library is broken?)"); goto hell;} //fprintf(stderr,"num_fourccs=%d fourccs=%p\n",s->num_fourccs,s->fourccs); for (int j=0; jnum_fourccs; j++) { string fn = string(s->fourccs[j]); f->push_back(fn); fourccs[fn]=name; } codecs[name]=f; hell:; } #endif } \end class FormatQuickTimeHW void gf_lqt_log_callback(lqt_log_level_t level, const char *domain, const char *message, void *data) { if (level&1) post("libquicktime: %s",message); } void startup_quicktimehw () { \startall lqt_set_log_callback(gf_lqt_log_callback,0); }