4 Copyright (C) 2003 Matthias Kramm <kramm@quiss.org>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
24 #include "../lib/rfxswf.h"
27 typedef struct _v2swf_internal_t
50 unsigned char* vrbuffer;
51 unsigned char* buffer;
52 unsigned char* lastbitmap;
59 int keyframe_interval;
102 static int verbose = 0;
103 static int filelog = 0;
105 static void msg(char*format, ...)
112 va_start(arglist, format);
113 vsnprintf(buf, sizeof(buf)-1, format, arglist);
116 while(l && buf[l-1]=='\n') {
122 FILE*fi = fopen("debug.log", "ab+");
123 fprintf(fi, "(v2swf) %s\n", buf);
128 printf("(v2swf) %s\n", buf);
132 extern int swf_mp3_in_samplerate;
133 extern int swf_mp3_out_samplerate;
134 extern int swf_mp3_channels;
135 extern int swf_mp3_bitrate;
138 static void writeShape(v2swf_internal_t*i, int id, int gfxid, int width, int height)
146 swf_ResetTag(i->tag, ST_DEFINESHAPE);
147 swf_ShapeNew(&shape);
148 rgb.b = rgb.g = rgb.r = 0xff;
150 ls = swf_ShapeAddLineStyle(shape,20,&rgb);
151 swf_GetMatrix(NULL,&m);
155 fs = swf_ShapeAddBitmapFillStyle(shape,&m,gfxid,0);
156 swf_SetU16(i->tag,id); // ID
161 swf_SetRect(i->tag,&r);
163 swf_SetShapeStyles(i->tag,shape);
164 swf_ShapeCountBits(shape,NULL,NULL);
165 swf_SetShapeBits(i->tag,shape);
167 swf_ShapeSetAll(i->tag,shape,0,0,lines?ls:0,fs,0);
169 swf_ShapeSetLine(i->tag,shape,width*20,0);
170 swf_ShapeSetLine(i->tag,shape,0,height*20);
171 swf_ShapeSetLine(i->tag,shape,-width*20,0);
172 swf_ShapeSetLine(i->tag,shape,0,-height*20);
173 swf_ShapeSetEnd(i->tag);
174 i->filesize += swf_WriteTag2(&i->out, i->tag);
175 swf_ShapeFree(shape);
178 /* returns 0 on partial read */
179 static int getSamples(videoreader_t*video, S16*data, int len, double speedup)
182 double ratio = (double) video->samplerate * speedup / swf_mp3_in_samplerate;
183 int rlen = (int)(len * ratio);
186 int r = /*resampled len */ rlen *
190 memset(tmp, 0, sizeof(tmp));
192 l = videoreader_getsamples(video, tmp, r);
196 msg("%d samples read", l);
198 /* convert to 1 channel */
199 for(t=0;t<rlen;t++) {
202 for(s=0;s<video->channels;s++)
203 a += tmp[t*video->channels+s];
204 tmp[t] = a/video->channels;
207 /* down/up-sample to the desired input samplerate (swf_mp3_in_samplerate) */
209 data[t] = tmp[(int)pos];
215 static void writeAudioForOneFrame(v2swf_internal_t* i)
218 double blockspersecond;
219 double framespersecond, framesperblock, samplesperframe, samplesperblock;
222 double speedup = i->audio_fix;
225 S16 block1[576*4 * 2];
227 msg("writeAudioForOneFrame()");
229 if(i->audio_eof || i->video->channels<=0 || i->video->samplerate<=0) {
231 return; /* no sound in video */
234 blocksize = (i->samplerate > 22050) ? 1152 : 576;
235 blockspersecond = ((double)i->samplerate)/blocksize;
237 /* notice: for framerates greater than about 35, audio starts getting choppy. */
238 framespersecond = i->framerate;
240 framesperblock = framespersecond / blockspersecond;
241 samplesperframe = (blocksize * blockspersecond) / framespersecond; /* 11khz-samples per frame */
242 samplesperblock = samplesperframe * framesperblock;
244 msg("samplesperblock: %f", samplesperblock);
246 if(!i->soundstreamhead) {
247 swf_mp3_out_samplerate = i->samplerate;
248 /* The pre-processing of sound samples in getSamples(..) above
249 re-samples the sound to swf_mp3_in_samplerate. It is best to
250 simply make it the original samplerate: */
251 swf_mp3_in_samplerate = i->video->samplerate;
253 /* first run - initialize */
254 swf_mp3_channels = 1;//i->video->channels;
255 swf_mp3_bitrate = i->bitrate;
256 swf_ResetTag(i->tag, ST_SOUNDSTREAMHEAD);
257 /* samplesperframe overrides the movie framerate: */
258 msg("swf_SetSoundStreamHead(): %08x %d", i->tag, samplesperframe);
259 swf_SetSoundStreamHead(i->tag, samplesperframe);
260 msg("swf_SetSoundStreamHead() done");
261 i->filesize += swf_WriteTag2(&i->out, i->tag);
262 i->soundstreamhead = 1;
265 /* for framerates greater than 19.14, every now and then a frame
266 hasn't a soundstreamblock. Determine whether this is the case.
268 msg("SOUND: frame:%d soundframepos:%f samplewritepos:%d samplepos:%f\n", i->frames, i->soundframepos, i->samplewritepos, i->samplepos);
269 if(i->frames < i->soundframepos) {
270 msg("SOUND: block skipped\n");
271 i->samplepos += samplesperframe;
277 //while(i->samplewritepos + num * blocksize < i->samplepos + blocksize) {
279 i->samplewritepos += blocksize;
280 i->soundframepos += framesperblock;
283 while(i->samplewritepos < i->samplepos);
285 msg("SOUND: number of blocks: %d", num);
287 /* write num frames, max 1 block */
288 for(pos=0;pos<num;pos++) {
289 if(!getSamples(i->video, block1, blocksize * (double)swf_mp3_in_samplerate/swf_mp3_out_samplerate, speedup)) {
290 i->audio_eof = 1; i->video->samplerate = i->video->channels = 0; //end of soundtrack
291 /* fall through, this probably was a partial read. (We did, after all,
292 come to this point, so i->audio_eof must have been false so far) */
295 swf_ResetTag(i->tag, ST_SOUNDSTREAMBLOCK);
296 swf_SetSoundStreamBlock(i->tag, block1, seek, num);
298 swf_SetSoundStreamBlock(i->tag, block1, seek, 0);
301 i->filesize += swf_WriteTag2(&i->out, i->tag);
303 i->seek = blocksize - (i->samplewritepos - i->samplepos);
304 i->samplepos += samplesperframe;
307 static void writeShowFrame(v2swf_internal_t* i)
310 writeAudioForOneFrame(i);
312 swf_ResetTag(i->tag, ST_SHOWFRAME);
313 i->filesize += swf_WriteTag2(&i->out, i->tag);
318 while(i->fpspos >= 1.0);
322 static void writeShowTags(v2swf_internal_t* i, int shapeid, int bmid, int width, int height)
324 writeShape(i, shapeid, bmid, width, height);
326 swf_ResetTag(i->tag, ST_PLACEOBJECT2);
329 swf_GetMatrix(0, &m);
330 m.sx = m.sy = i->scale;
331 swf_ObjectPlace(i->tag,shapeid,shapeid,&m,0,0);
333 swf_ObjectPlace(i->tag,shapeid,shapeid,0,0,0);
335 i->filesize += swf_WriteTag2(&i->out, i->tag);
340 static int wwrite(writer_t*w, void*data, int len)
342 v2swf_internal_t* i = (v2swf_internal_t*)w->internal;
343 ringbuffer_put(&i->r, data, len);
347 static void wfinish(writer_t*w)
349 v2swf_internal_t* i = (v2swf_internal_t*)w->internal;
352 static void writehead(v2swf_internal_t*i)
354 char header[]="FWS\6\0\0\0\4";
359 header[3] = i->version;
360 if(i->version >= 6) { //MX
363 i->out2.write = wwrite;
364 i->out2.finish = wfinish;
365 i->out2.internal = i;
370 writer_init_zlibdeflate(&i->out, &i->out2);
372 i->out.write = wwrite;
373 i->out.finish = wfinish;
383 i->width = (int)(i->video->width*(i->scale/65536.0));
384 i->height = (int)(i->video->height*(i->scale/65536.0));
386 i->width = i->video->width;
387 i->height = i->video->height;
393 i->buffer = (unsigned char*)malloc(i->width*i->height*4);
394 i->vrbuffer = (unsigned char*)malloc(i->video->width*i->video->height*4);
396 memset(&swf, 0, sizeof(SWF));
397 swf.fileVersion=i->version;
399 swf.frameCount = 65535;
400 swf.movieSize.xmax=i->width*20;
401 swf.movieSize.ymax=i->height*20;
402 swf.compressed = 8; /* 8 = compression done by caller (us) */
403 swf.frameRate = (int)(i->framerate*0x100);//25*0x100;
405 /* write the first 8 bytes to out */
406 i->out2.write(&i->out2, header, 8);
408 i->filesize += swf_WriteHeader2(&i->out, &swf);
409 i->headersize = i->filesize;
411 i->tag = swf_InsertTag(NULL, ST_SETBACKGROUNDCOLOR);
412 swf_SetU8(i->tag, 0); //black
413 swf_SetU8(i->tag, 0);
414 swf_SetU8(i->tag, 0);
415 i->filesize += swf_WriteTag2(&i->out, i->tag);
418 static void finish(v2swf_internal_t*i)
420 msg("finish(): i->finished=%d\n", i->finished);
422 msg("write endtag\n", i->finished);
425 swf_ResetTag(i->tag, ST_SHOWFRAME);
426 i->filesize += swf_WriteTag2(&i->out, i->tag);
428 swf_ResetTag(i->tag, ST_REMOVEOBJECT2);
429 swf_SetU16(i->tag, 1); //depth
430 i->filesize += swf_WriteTag2(&i->out, i->tag);
432 swf_ResetTag(i->tag, ST_DOACTION);
433 swf_SetU16(i->tag, 0x0007);
434 i->filesize += swf_WriteTag2(&i->out, i->tag);
437 swf_ResetTag(i->tag, ST_END);
438 i->filesize += swf_WriteTag2(&i->out, i->tag);
440 i->out.finish(&i->out);
443 swf_VideoStreamClear(&i->stream);
446 free(i->buffer);i->buffer = 0;
449 free(i->vrbuffer);i->vrbuffer = 0;
452 free(i->lastbitmap);i->lastbitmap = 0;
455 /* FIXME: we shouldn't be doing this. the caller should */
456 msg("call videoreader_close(%08x)\n", i->video);
457 videoreader_close(i->video);
461 msg("finishing done\n");
463 static void cleanup(v2swf_internal_t*i)
466 for(t=i->lastid;t<i->id;t++) {
468 swf_ResetTag(i->tag, ST_REMOVEOBJECT2);
469 swf_SetU16(i->tag, t);
470 i->filesize += swf_WriteTag2(&i->out, i->tag);
472 swf_ResetTag(i->tag, ST_FREECHARACTER);
473 swf_SetU16(i->tag, t);
474 i->filesize += swf_WriteTag2(&i->out, i->tag);
479 #define DIFFMODE_MAX 1
480 #define DIFFMODE_MEAN 2
481 #define DIFFMODE_EXACT 3
482 #define DIFFMODE_QMEAN 4
484 static int blockdiff_max(U8*d1,U8*d2,int yadd, int maxdiff, int xl, int yl)
489 int rd = d1[1] - d2[1];
490 int gd = d1[2] - d2[2];
491 int bd = d1[3] - d2[3];
500 d1 += yadd; d2 += yadd;
505 static int blockdiff_mean(U8*d1,U8*d2,int yadd, int maxdiff, int xl, int yl)
511 int rd = d1[1] - d2[1];
512 int gd = d1[2] - d2[2];
513 int bd = d1[3] - d2[3];
521 d1 += yadd; d2 += yadd;
523 if(mean/(xl*yl) > maxdiff)
528 static int blockdiff_qmean(U8*d1,U8*d2,int yadd, int maxdiff, int xl, int yl)
534 int rd = d1[1] - d2[1];
535 int gd = d1[2] - d2[2];
536 int bd = d1[3] - d2[3];
546 d1 += yadd; d2 += yadd;
548 if(mean/(xl*yl) > maxdiff*maxdiff)
553 static int blockdiff_exact(U8*d1,U8*d2,int yadd, int xl, int yl)
558 if((*(U32*)d1^*(U32*)d2)&0xffffff00) { //bits [RGB_] of [RGBA] differ
563 d1 += yadd; d2 += yadd;
568 /*U32 r = (*(U32*)d1^-(U32*)d2)&0xffffff00;
569 U32 g = ((r << 3) ^ r)&0x80808080;
573 static void checkInit(v2swf_internal_t*i)
578 swf_ResetTag(i->tag, ST_DEFINEVIDEOSTREAM);
579 swf_SetU16(i->tag, 99);
580 swf_SetVideoStreamDefine(i->tag, &i->stream, 65535, i->width, i->height);
581 i->filesize += swf_WriteTag2(&i->out, i->tag);
583 i->stream.do_motion = 1;
590 static void scaleimage(v2swf_internal_t*i)
594 int xm = (i->video->width*65536)/i->width;
595 int ym = (i->video->height*65536)/i->height;
596 msg("scaling from %dx%d to %dx%d\n",
597 i->video->width, i->video->height,
601 memset(i->buffer, 255, i->width*i->height*4);
602 for(y=0,yv=0;y<i->height;y++,yv+=ym) {
603 int*src = &((int*)i->vrbuffer)[(yv>>16)*i->video->width];
604 int*dest = &((int*)i->buffer)[y*i->width];
605 for(x=0,xv=0;x<i->width;x++,xv+=xm) {
606 dest[x] = src[xv>>16];
609 //memcpy(i->buffer, i->vrbuffer, i->width*i->height*4);
612 static int writeAudioOnly(v2swf_internal_t*i)
615 i->fpspos += i->fpsratio;
626 static int getframe(v2swf_internal_t*i)
629 return videoreader_getimage(i->video, i->vrbuffer);
632 for(t=0;t<i->skipframes;t++) {
633 int ret = videoreader_getimage(i->video, i->vrbuffer);
641 static int encodeoneframe(v2swf_internal_t*i)
643 videoreader_t*video = i->video;
648 if(i->video_eof && i->audio_eof) {
654 if(!i->audio_eof && i->video_eof) {
655 return writeAudioOnly(i);
658 if(!getframe(i) || (i->numframes && i->frames==i->numframes))
661 msg("videoreader returned eof\n");
662 if(i->audio_eof || (i->numframes && i->frames==i->numframes)) {
666 return writeAudioOnly(i);
670 msg("encoding image for frame %d\n", i->frames);
672 i->fpspos += i->fpsratio;
682 msg("version is %d\n", i->version);
684 if(i->version <= 4) {
687 int shapeid = i->id++;
688 int width2 = i->width * 4;
691 swf_ResetTag(i->tag, ST_REMOVEOBJECT2);
692 swf_SetU16(i->tag, i->id-3);
693 i->filesize += swf_WriteTag2(&i->out, i->tag);
694 swf_ResetTag(i->tag, ST_FREECHARACTER);
695 swf_SetU16(i->tag, i->id-4);
696 i->filesize += swf_WriteTag2(&i->out, i->tag);
699 swf_ResetTag(i->tag, ST_DEFINEBITSJPEG2);
700 swf_SetU16(i->tag, bmid);
701 swf_SetJPEGBits2(i->tag, i->width, i->height, (RGBA*)i->buffer, i->quality);
702 i->filesize += swf_WriteTag2(&i->out, i->tag);
704 writeShowTags(i, shapeid, bmid, i->width, i->height);
706 } else if(i->version == 5) {
707 int width2 = i->width * 4;
708 int width8 = (i->width+7)/8;
709 int height8 = (i->height+7)/8;
711 /* the idea is here to only update those jpeg 8x8 blocks
712 which actually have changed. This means that we have to keep
713 the bitmap from the last frame for the comparison. */
716 if(!i->lastbitmap || !i->keyframe) {
721 msg("Creating bitmap buffer for %dx%d (%dx%d), (%dx%d)\n", i->width, i->height, width2, i->height, width8, height8);
722 i->lastbitmap = (U8*)malloc(width2*i->height);
724 memcpy(i->lastbitmap, i->buffer, width2*i->height);
726 i->keyframe = i->keyframe_interval;
730 width2 = i->width * 4;
731 swf_ResetTag(i->tag, ST_DEFINEBITSJPEG2);
732 swf_SetU16(i->tag, bmid);
733 swf_SetJPEGBits2(i->tag, i->width, i->height, (RGBA*)i->buffer, i->quality);
734 i->filesize += swf_WriteTag2(&i->out, i->tag);
736 writeShowTags(i, shapeid, bmid, i->width, i->height);
739 /* The following looks so ugly because it's somewhat optimized.
740 What it does is walk through all the 8x8 blocks, find those
741 which have changed too much and set all others to (R,G,B,A)=(0,0,0,0).
742 It also set's alpha to 255 in those who haven't changed, and
743 copies them to lastbitmap.
747 //int maxdiff = ((100 - i->quality)*256)/100;
748 int maxdiff = i->blockdiff*3;
749 for(y8=0;y8<height8;y8++)
750 for(x8=0;x8<width8;x8++) {
755 if(x8*8+xl > i->width)
756 xl = i->width - x8*8;
757 if(y8*8+yl > i->height)
758 yl = i->height - y8*8;
759 d1 = &i->buffer[width2*y8*8+x8*8*4];
761 d2 = &i->lastbitmap[width2*y8*8+x8*8*4];
763 yadd = width2 - (xl*4);
765 if(i->diffmode == DIFFMODE_MAX) {
766 if(blockdiff_max(d1, d2, yadd, maxdiff, xl, yl))
768 } else if(i->diffmode == DIFFMODE_MEAN) {
769 if(blockdiff_mean(d1, d2, yadd, maxdiff, xl, yl))
771 } else if(i->diffmode == DIFFMODE_EXACT) {
772 if(blockdiff_exact(d1, d2, yadd, xl, yl))
774 } else if(i->diffmode == DIFFMODE_QMEAN) {
775 if(blockdiff_qmean(d1, d2, yadd, maxdiff, xl, yl))
790 *(U32*)d2b = *(U32*)d1b;
794 d1b += yadd; d2b += yadd;
798 /* ok, done. Now a) data is zeroed out in regions which haven't changed
799 b) lastbitmap equals the bitmap we were called with
800 c) data's alpha value is set to 255 in regions which did change */
806 int shapeid = i->id++;
808 swf_ResetTag(i->tag, ST_DEFINEBITSJPEG3);
809 swf_SetU16(i->tag, bmid);
810 swf_SetJPEGBits3(i->tag, i->width, i->height, (RGBA*)i->buffer, i->quality);
811 i->filesize += swf_WriteTag2(&i->out, i->tag);
813 writeShowTags(i, shapeid, bmid, i->width, i->height);
816 int quant = 1+(30-(30*i->quality)/100);
819 swf_GetPlaceObject(0, &obj);
821 obj.matrix.sx = obj.matrix.sy = i->scale;
824 if(i->stream.frame==0) {
830 obj.ratio = i->stream.frame;
833 swf_ResetTag(i->tag, ST_VIDEOFRAME);
834 swf_SetU16(i->tag, 99);
835 if(!(--i->keyframe)) {
836 msg("setting video I-frame, ratio=%d\n", i->stream.frame);
837 swf_SetVideoStreamIFrame(i->tag, &i->stream, (RGBA*)i->buffer, quant);
838 i->keyframe = i->keyframe_interval;
840 msg("setting video P-frame, ratio=%d\n", i->stream.frame);
841 swf_SetVideoStreamPFrame(i->tag, &i->stream, (RGBA*)i->buffer, quant);
843 i->filesize += swf_WriteTag2(&i->out, i->tag);
845 swf_ResetTag(i->tag, ST_PLACEOBJECT2);
846 swf_SetPlaceObject(i->tag,&obj);
847 i->filesize += swf_WriteTag2(&i->out, i->tag);
853 static void init_fps(v2swf_internal_t*i)
855 int oldframerate = i->framerate;
856 i->framerate = i->video->fps / i->skipframes;
857 i->video_fps = ((int)(i->framerate*256))/256.0;
859 msg("setting new framerate to %f\n", i->framerate);
862 int v2swf_init(v2swf_t*v2swf, videoreader_t * video)
867 msg("v2swf_init()\n");
868 memset(v2swf, 0, sizeof(v2swf_t));
869 i = (v2swf_internal_t*)malloc(sizeof(v2swf_internal_t));
870 memset(i, 0, sizeof(v2swf_internal_t));
873 ringbuffer_init(&i->r);
880 msg("video: %dx%d, fps %f\n", video->width, video->height, video->fps);
883 i->keyframe_interval = 8;
887 i->samplerate = 11025;
892 i->diffmode = DIFFMODE_QMEAN;
895 i->fpsratio = 1.00000000000;
908 memset(&i->out, 0, sizeof(writer_t));
909 memset(&i->out2, 0, sizeof(writer_t));
913 int v2swf_read(v2swf_t*v2swf, void*buffer, int len)
917 msg("v2swf_read(%d)\n", len);
918 i = (v2swf_internal_t*)v2swf->internal;
920 while(!i->finished && i->r.available < len) {
921 if(!encodeoneframe(i)) {
925 msg("v2swf_read() done: %d bytes available in ringbuffer\n", i->r.available);
926 l = ringbuffer_read(&i->r, buffer, len);
930 void v2swf_close(v2swf_t*v2swf)
932 v2swf_internal_t* i = (v2swf_internal_t*)v2swf->internal;
933 msg("close(): i->finished=%d\n", i->finished);
935 /* needed only if aborting: */
938 msg("freeing memory\n");
939 free(v2swf->internal);
940 memset(v2swf, 0, sizeof(v2swf_t));
941 msg("close() done\n");
944 static int mp3_bitrates[] =
945 { 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0};
947 void v2swf_setparameter(v2swf_t*v2swf, char*name, char*value)
951 msg("set parameters %s to %s\n", name, value);
953 if(!strcmp(name, "verbose")) {
955 msg("set parameters %s to %s\n", name, value);
959 if(!v2swf || !v2swf->internal) {
960 printf("error- couldn't set parameter %s: not initialized yet\n", name);fflush(stdout);
963 i = (v2swf_internal_t*)v2swf->internal;
965 if(!strcmp(name, "flash_version")) {
966 i->version = atoi(value);
967 } else if(!strcmp(name, "audiosync")) {
968 i->audio_fix = (int)(atof(value));
969 } else if(!strcmp(name, "addcut")) {
970 i->add_cut = atoi(value);
971 } else if(!strcmp(name, "scale")) {
972 i->scale = (int)(atof(value)*65536);
973 } else if(!strcmp(name, "scale65536")) {
974 i->scale = atoi(value);
975 } else if(!strcmp(name, "quality")) {
976 i->quality = atoi(value);
977 } else if(!strcmp(name, "skipframes")) {
978 i->skipframes = atoi(value);
980 } else if(!strcmp(name, "numframes")) {
981 i->numframes = atoi(value);
982 } else if(!strcmp(name, "motioncompensation")) {
983 i->domotion = atoi(value);
984 } else if(!strcmp(name, "prescale")) {
985 i->prescale = atoi(value);
986 } else if(!strcmp(name, "blockdiff")) {
987 i->blockdiff = atoi(value);
988 } else if(!strcmp(name, "fixheader")) {
989 i->fixheader = atoi(value);
990 } else if(!strcmp(name, "samplerate")) {
991 i->samplerate = atoi(value);
992 } else if(!strcmp(name, "framerate")) {
993 i->framerate = atof(value);
994 i->fpsratio = i->framerate / i->video_fps;
996 else if(!strcmp(name, "mp3_bitrate")) {
998 i->bitrate = o = atoi(value);
1001 while(mp3_bitrates[t]) {
1002 if(i->bitrate <= mp3_bitrates[t]) {
1003 i->bitrate = mp3_bitrates[t];
1008 msg("bitrate %d requested, setting to %d", o, i->bitrate);
1010 else if(!strcmp(name, "blockdiff_mode")) {
1011 if(!strcmp(value, "max")) i->diffmode = DIFFMODE_MAX;
1012 else if(!strcmp(value, "mean")) i->diffmode = DIFFMODE_MEAN;
1013 else if(!strcmp(value, "qmean")) i->diffmode = DIFFMODE_QMEAN;
1014 else if(!strcmp(value, "exact")) i->diffmode = DIFFMODE_EXACT;
1016 printf("diffmode %s not recognized\n", value);
1017 printf("valid diffmodes are: %s\n", "max, mean, qmean, exact");
1020 else if(!strcmp(name, "keyframe_interval")
1021 || !strcmp(name, "keyframe")) {
1022 int k = atoi(value);if(k<=0) k=1;
1023 i->keyframe_interval = k;
1026 printf("Setting encoder.%s not recognized!\n", name);fflush(stdout);
1030 void v2swf_backpatch(v2swf_t*v2swf, char*filename)
1034 v2swf_internal_t* i = (v2swf_internal_t*)v2swf->internal;
1035 msg("v2swf_backpatch %s\n", filename);
1037 printf("call backpatch before close\n");fflush(stdout);
1039 fi = fopen(filename, "rb+");
1041 printf("can't open %s\n", filename);
1044 fseek(fi, 4, SEEK_SET);
1045 f = i->filesize ;fwrite(&f,1,1,fi);
1046 f = i->filesize >> 8 ;fwrite(&f,1,1,fi);
1047 f = i->filesize >> 16;fwrite(&f,1,1,fi);
1048 f = i->filesize >> 24;fwrite(&f,1,1,fi);
1050 /* no compression- we can backpatch the frames too */
1051 fseek(fi, i->headersize-2, SEEK_SET);
1052 f = i->frames ;fwrite(&f,1,1,fi);
1053 f = i->frames >> 8 ;fwrite(&f,1,1,fi);
1059 msg("v2swf_backpatch %s - fix header\n", filename);
1060 memset(&tmp, 0, sizeof(tmp));
1061 fi = open(filename, O_RDONLY|O_BINARY);
1063 if(swf_ReadSWF(fi, &tmp)>=0) {
1065 fi = open(filename, O_WRONLY|O_BINARY|O_TRUNC|O_CREAT, 0666);
1067 swf_WriteSWF(fi, &tmp);
1069 msg("v2swf_backpatch %s - fix header: success\n", filename);
1076 void v2swf_setvideoparameter(videoreader_t*v, char*name, char*value)
1078 msg("v2swf_setvideoparameter()");
1079 videoreader_setparameter(v, name, value);