X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=avi2swf%2Fv2swf.c;h=c974bfbacdb286e546c9c46f56aedd872641201b;hp=572019947d494428e1c208dc53d6bbb5cda384e7;hb=f29d8006b1d8253c50808d6eb4941bdeb808c601;hpb=2426d04359ede90a92f33740c7086cafa789ff9f diff --git a/avi2swf/v2swf.c b/avi2swf/v2swf.c index 5720199..c974bfb 100644 --- a/avi2swf/v2swf.c +++ b/avi2swf/v2swf.c @@ -22,7 +22,7 @@ #include #include "v2swf.h" #include "../lib/rfxswf.h" -#include "ringbuffer.c" +#include "../lib/q.h" typedef struct _v2swf_internal_t { @@ -34,15 +34,19 @@ typedef struct _v2swf_internal_t int myframes; - struct writer_t out; - struct writer_t out2; + writer_t out; + writer_t out2; ringbuffer_t r; videoreader_t* video; + double video_fps; int width; int height; + int video_eof; + int audio_eof; + unsigned char* vrbuffer; unsigned char* buffer; unsigned char* lastbitmap; @@ -60,11 +64,14 @@ typedef struct _v2swf_internal_t float fpspos; int bitrate; + int samplerate; int finished; int keyframe; int showframe; + int skipframes; + float samplepos; float framesamplepos; int samplewritepos; @@ -72,11 +79,15 @@ typedef struct _v2swf_internal_t int soundstreamhead; int seek; + int numframes; + double audio_fix; int fixheader; int prescale; int scale; + + int add_cut; int domotion; @@ -91,7 +102,7 @@ typedef struct _v2swf_internal_t static int verbose = 0; static int filelog = 0; -static void logf(char*format, ...) +static void msg(char*format, ...) { char buf[1024]; int l; @@ -99,7 +110,7 @@ static void logf(char*format, ...) if(!verbose) return; va_start(arglist, format); - vsprintf(buf, format, arglist); + vsnprintf(buf, sizeof(buf)-1, format, arglist); va_end(arglist); l = strlen(buf); while(l && buf[l-1]=='\n') { @@ -118,6 +129,12 @@ static void logf(char*format, ...) fflush(stdout); } +extern int swf_mp3_in_samplerate; +extern int swf_mp3_out_samplerate; +extern int swf_mp3_channels; +extern int swf_mp3_bitrate; + + static void writeShape(v2swf_internal_t*i, int id, int gfxid, int width, int height) { RGBA rgb; @@ -158,18 +175,25 @@ static void writeShape(v2swf_internal_t*i, int id, int gfxid, int width, int hei swf_ShapeFree(shape); } +/* returns 0 on partial read */ static int getSamples(videoreader_t*video, S16*data, int len, double speedup) { double pos = 0; - double ratio = video->rate * speedup / 44100.0; + double ratio = (double) video->samplerate * speedup / swf_mp3_in_samplerate; int rlen = (int)(len * ratio); int t; S16 tmp[576*32]; int r = /*resampled len */ rlen * /* s16_le */ 2 * video->channels; - if(videoreader_getsamples(video, tmp, r) < r) + int l = 0; + memset(tmp, 0, sizeof(tmp)); + if(r>0) + l = videoreader_getsamples(video, tmp, r); + if(l <= 0) { return 0; + } + msg("%d samples read", l); /* convert to 1 channel */ for(t=0;tchannels; } - /* down/up-sample to 44khz */ + /* down/up-sample to the desired input samplerate (swf_mp3_in_samplerate) */ for(t=0;tvideo->channels<=0 || i->video->rate<=0) + if(i->audio_eof || i->video->channels<=0 || i->video->samplerate<=0) { + i->audio_eof = 1; return; /* no sound in video */ + } - blocksize = 576; /* 11khz samples per mp3 block */ - blockspersecond = 11025.0/blocksize; + blocksize = (i->samplerate > 22050) ? 1152 : 576; + blockspersecond = ((double)i->samplerate)/blocksize; /* notice: for framerates greater than about 35, audio starts getting choppy. */ framespersecond = i->framerate; @@ -218,17 +241,23 @@ static void writeAudioForOneFrame(v2swf_internal_t* i) samplesperframe = (blocksize * blockspersecond) / framespersecond; /* 11khz-samples per frame */ samplesperblock = samplesperframe * framesperblock; - logf("samplesperblock: %f", samplesperblock); + msg("samplesperblock: %f", samplesperblock); if(!i->soundstreamhead) { + swf_mp3_out_samplerate = i->samplerate; + /* The pre-processing of sound samples in getSamples(..) above + re-samples the sound to swf_mp3_in_samplerate. It is best to + simply make it the original samplerate: */ + swf_mp3_in_samplerate = i->video->samplerate; + /* first run - initialize */ swf_mp3_channels = 1;//i->video->channels; swf_mp3_bitrate = i->bitrate; swf_ResetTag(i->tag, ST_SOUNDSTREAMHEAD); /* samplesperframe overrides the movie framerate: */ - logf("swf_SetSoundStreamHead(): %08x %d", i->tag, samplesperframe); + msg("swf_SetSoundStreamHead(): %08x %d", i->tag, samplesperframe); swf_SetSoundStreamHead(i->tag, samplesperframe); - logf("swf_SetSoundStreamHead() done"); + msg("swf_SetSoundStreamHead() done"); i->filesize += swf_WriteTag2(&i->out, i->tag); i->soundstreamhead = 1; } @@ -236,7 +265,9 @@ static void writeAudioForOneFrame(v2swf_internal_t* i) /* for framerates greater than 19.14, every now and then a frame hasn't a soundstreamblock. Determine whether this is the case. */ + msg("SOUND: frame:%d soundframepos:%f samplewritepos:%d samplepos:%f\n", i->frames, i->soundframepos, i->samplewritepos, i->samplepos); if(i->frames < i->soundframepos) { + msg("SOUND: block skipped\n"); i->samplepos += samplesperframe; return; } @@ -244,26 +275,22 @@ static void writeAudioForOneFrame(v2swf_internal_t* i) seek = i->seek; //while(i->samplewritepos + num * blocksize < i->samplepos + blocksize) { - while(i->samplewritepos < i->samplepos + blocksize) { + do { i->samplewritepos += blocksize; i->soundframepos += framesperblock; num++; } - if(!num) { - logf("num is zero"); - printf(" num is zero\n"); - fprintf(stderr, " num is zero\n"); - } - logf("num: %d", num); + while(i->samplewritepos < i->samplepos); + + msg("SOUND: number of blocks: %d", num); /* write num frames, max 1 block */ for(pos=0;posvideo, block1, 576*4, speedup)) { /* 4 = 44100/11025 */ - i->video->rate = i->video->channels = 0; //end of soundtrack - return; + if(!getSamples(i->video, block1, blocksize * (double)swf_mp3_in_samplerate/swf_mp3_out_samplerate, speedup)) { + i->audio_eof = 1; i->video->samplerate = i->video->channels = 0; //end of soundtrack + /* fall through, this probably was a partial read. (We did, after all, + come to this point, so i->audio_eof must have been false so far) */ } - logf("pos: %d- encode mp3", pos); if(!pos) { swf_ResetTag(i->tag, ST_SOUNDSTREAMBLOCK); swf_SetSoundStreamBlock(i->tag, block1, seek, num); @@ -273,9 +300,8 @@ static void writeAudioForOneFrame(v2swf_internal_t* i) } i->filesize += swf_WriteTag2(&i->out, i->tag); - i->seek = i->samplewritepos - (i->samplepos + blocksize); + i->seek = blocksize - (i->samplewritepos - i->samplepos); i->samplepos += samplesperframe; - logf("writeSamplesForOneFrame(): done"); } static void writeShowFrame(v2swf_internal_t* i) @@ -311,14 +337,14 @@ static void writeShowTags(v2swf_internal_t* i, int shapeid, int bmid, int width, i->showframe = 1; } -static int wwrite(struct writer_t*w, void*data, int len) +static int wwrite(writer_t*w, void*data, int len) { v2swf_internal_t* i = (v2swf_internal_t*)w->internal; ringbuffer_put(&i->r, data, len); return len; } -static void wfinish(struct writer_t*w) +static void wfinish(writer_t*w) { v2swf_internal_t* i = (v2swf_internal_t*)w->internal; } @@ -391,12 +417,26 @@ static void writehead(v2swf_internal_t*i) static void finish(v2swf_internal_t*i) { - logf("finish(): i->finished=%d\n", i->finished); + msg("finish(): i->finished=%d\n", i->finished); if(!i->finished) { - logf("write endtag\n", i->finished); + msg("write endtag\n", i->finished); + + if(i->add_cut) { + swf_ResetTag(i->tag, ST_SHOWFRAME); + i->filesize += swf_WriteTag2(&i->out, i->tag); + + swf_ResetTag(i->tag, ST_REMOVEOBJECT2); + swf_SetU16(i->tag, 1); //depth + i->filesize += swf_WriteTag2(&i->out, i->tag); + + swf_ResetTag(i->tag, ST_DOACTION); + swf_SetU16(i->tag, 0x0007); + i->filesize += swf_WriteTag2(&i->out, i->tag); + } swf_ResetTag(i->tag, ST_END); i->filesize += swf_WriteTag2(&i->out, i->tag); + i->out.finish(&i->out); if(i->version>=6) { @@ -413,12 +453,12 @@ static void finish(v2swf_internal_t*i) } /* FIXME: we shouldn't be doing this. the caller should */ - logf("call videoreader_close(%08x)\n", i->video); + msg("call videoreader_close(%08x)\n", i->video); videoreader_close(i->video); i->finished = 1; } - logf("finishing done\n"); + msg("finishing done\n"); } static void cleanup(v2swf_internal_t*i) { @@ -553,6 +593,11 @@ static void scaleimage(v2swf_internal_t*i) int xv,yv; int xm = (i->video->width*65536)/i->width; int ym = (i->video->height*65536)/i->height; + msg("scaling from %dx%d to %dx%d\n", + i->video->width, i->video->height, + i->width, i->height + ); + memset(i->buffer, 255, i->width*i->height*4); for(y=0,yv=0;yheight;y++,yv+=ym) { int*src = &((int*)i->vrbuffer)[(yv>>16)*i->video->width]; @@ -564,6 +609,35 @@ static void scaleimage(v2swf_internal_t*i) //memcpy(i->buffer, i->vrbuffer, i->width*i->height*4); } +static int writeAudioOnly(v2swf_internal_t*i) +{ + if(i->showframe) { + i->fpspos += i->fpsratio; + /* skip frames */ + if(i->fpspos<1.0) { + return 0; + } + writeShowFrame(i); + } + i->showframe = 1; + return 1; +} + +static int getframe(v2swf_internal_t*i) +{ + if(!i->skipframes) + return videoreader_getimage(i->video, i->vrbuffer); + else { + int t; + for(t=0;tskipframes;t++) { + int ret = videoreader_getimage(i->video, i->vrbuffer); + if(!ret) + return 0; + } + return 1; + } +} + static int encodeoneframe(v2swf_internal_t*i) { videoreader_t*video = i->video; @@ -571,30 +645,41 @@ static int encodeoneframe(v2swf_internal_t*i) checkInit(i); - if(videoreader_eof(i->video) || !videoreader_getimage(i->video, i->vrbuffer)) - { - logf("videoreader returned eof\n"); - finish(i); + if(i->video_eof && i->audio_eof) { + if(!i->finished) + finish(i); return 0; } - i->fpspos += i->fpsratio; + if(!i->audio_eof && i->video_eof) { + return writeAudioOnly(i); + } - /* skip frames */ - if(i->fpspos<1.0) { - return 0; + if(!getframe(i) || (i->numframes && i->frames==i->numframes)) + { + i->video_eof = 1; + msg("videoreader returned eof\n"); + if(i->audio_eof || (i->numframes && i->frames==i->numframes)) { + finish(i); + return 0; + } else { + return writeAudioOnly(i); + } } - - logf("encoding image for frame %d\n", i->frames); - if(i->showframe) + msg("encoding image for frame %d\n", i->frames); + if(i->showframe) { + i->fpspos += i->fpsratio; + /* skip frames */ + if(i->fpspos<1.0) { + return 0; + } writeShowFrame(i); - - logf("scaling\n"); - + } + scaleimage(i); - logf("version is %d\n", i->version); + msg("version is %d\n", i->version); if(i->version <= 4) { @@ -633,7 +718,7 @@ static int encodeoneframe(v2swf_internal_t*i) cleanup(i); if(!i->lastbitmap) { - logf("Creating bitmap buffer for %dx%d (%dx%d), (%dx%d)\n", i->width, i->height, width2, i->height, width8, height8); + msg("Creating bitmap buffer for %dx%d (%dx%d), (%dx%d)\n", i->width, i->height, width2, i->height, width8, height8); i->lastbitmap = (U8*)malloc(width2*i->height); } memcpy(i->lastbitmap, i->buffer, width2*i->height); @@ -748,11 +833,11 @@ static int encodeoneframe(v2swf_internal_t*i) swf_ResetTag(i->tag, ST_VIDEOFRAME); swf_SetU16(i->tag, 99); if(!(--i->keyframe)) { - logf("setting video I-frame, ratio=%d\n", i->stream.frame); + msg("setting video I-frame, ratio=%d\n", i->stream.frame); swf_SetVideoStreamIFrame(i->tag, &i->stream, (RGBA*)i->buffer, quant); i->keyframe = i->keyframe_interval; } else { - logf("setting video P-frame, ratio=%d\n", i->stream.frame); + msg("setting video P-frame, ratio=%d\n", i->stream.frame); swf_SetVideoStreamPFrame(i->tag, &i->stream, (RGBA*)i->buffer, quant); } i->filesize += swf_WriteTag2(&i->out, i->tag); @@ -765,12 +850,21 @@ static int encodeoneframe(v2swf_internal_t*i) return 1; } +static void init_fps(v2swf_internal_t*i) +{ + int oldframerate = i->framerate; + i->framerate = i->video->fps / i->skipframes; + i->video_fps = ((int)(i->framerate*256))/256.0; + if(oldframerate) + msg("setting new framerate to %f\n", i->framerate); +} + int v2swf_init(v2swf_t*v2swf, videoreader_t * video) { int ret = 0; int t=0; v2swf_internal_t* i; - logf("v2swf_init()\n"); + msg("v2swf_init()\n"); memset(v2swf, 0, sizeof(v2swf_t)); i = (v2swf_internal_t*)malloc(sizeof(v2swf_internal_t)); memset(i, 0, sizeof(v2swf_internal_t)); @@ -778,20 +872,27 @@ int v2swf_init(v2swf_t*v2swf, videoreader_t * video) ringbuffer_init(&i->r); - logf("video: %dx%d, fps %f\n", video->width, video->height, video->fps); - + i->skipframes = 1; + i->framerate = 0; i->video = video; + init_fps(i); + + msg("video: %dx%d, fps %f\n", video->width, video->height, video->fps); + i->blockdiff = 64; i->keyframe_interval = 8; i->quality = 20; i->scale = 65536; + i->add_cut = 1; + i->samplerate = 11025; i->prescale = 0; + i->numframes= 0; + i->skipframes = 0; i->head_done = 0; i->diffmode = DIFFMODE_QMEAN; i->audio_fix = 1.0; i->fixheader = 0; - i->framerate = video->fps; - i->fpsratio = 1.00000000; + i->fpsratio = 1.00000000000; i->fpspos = 0.0; i->bitrate = 32; i->version = 6; @@ -804,8 +905,8 @@ int v2swf_init(v2swf_t*v2swf, videoreader_t * video) i->keyframe = 1; i->showframe = 0; - memset(&i->out, 0, sizeof(struct writer_t)); - memset(&i->out2, 0, sizeof(struct writer_t)); + memset(&i->out, 0, sizeof(writer_t)); + memset(&i->out2, 0, sizeof(writer_t)); return 0; } @@ -813,7 +914,7 @@ int v2swf_read(v2swf_t*v2swf, void*buffer, int len) { v2swf_internal_t* i; int l; - logf("v2swf_read(%d)\n", len); + msg("v2swf_read(%d)\n", len); i = (v2swf_internal_t*)v2swf->internal; while(!i->finished && i->r.available < len) { @@ -821,7 +922,7 @@ int v2swf_read(v2swf_t*v2swf, void*buffer, int len) break; } } - logf("v2swf_read() done: %d bytes available in ringbuffer\n", i->r.available); + msg("v2swf_read() done: %d bytes available in ringbuffer\n", i->r.available); l = ringbuffer_read(&i->r, buffer, len); return l; @@ -829,15 +930,15 @@ int v2swf_read(v2swf_t*v2swf, void*buffer, int len) void v2swf_close(v2swf_t*v2swf) { v2swf_internal_t* i = (v2swf_internal_t*)v2swf->internal; - logf("close(): i->finished=%d\n", i->finished); + msg("close(): i->finished=%d\n", i->finished); /* needed only if aborting: */ finish(i); - logf("freeing memory\n"); + msg("freeing memory\n"); free(v2swf->internal); memset(v2swf, 0, sizeof(v2swf_t)); - logf("close() done\n"); + msg("close() done\n"); } static int mp3_bitrates[] = @@ -847,11 +948,11 @@ void v2swf_setparameter(v2swf_t*v2swf, char*name, char*value) { v2swf_internal_t* i; - logf("set parameters %s to %s\n", name, value); + msg("set parameters %s to %s\n", name, value); if(!strcmp(name, "verbose")) { verbose = 1; - logf("set parameters %s to %s\n", name, value); + msg("set parameters %s to %s\n", name, value); return; } @@ -865,12 +966,19 @@ void v2swf_setparameter(v2swf_t*v2swf, char*name, char*value) i->version = atoi(value); } else if(!strcmp(name, "audiosync")) { i->audio_fix = (int)(atof(value)); + } else if(!strcmp(name, "addcut")) { + i->add_cut = atoi(value); } else if(!strcmp(name, "scale")) { i->scale = (int)(atof(value)*65536); } else if(!strcmp(name, "scale65536")) { i->scale = atoi(value); } else if(!strcmp(name, "quality")) { i->quality = atoi(value); + } else if(!strcmp(name, "skipframes")) { + i->skipframes = atoi(value); + init_fps(i); + } else if(!strcmp(name, "numframes")) { + i->numframes = atoi(value); } else if(!strcmp(name, "motioncompensation")) { i->domotion = atoi(value); } else if(!strcmp(name, "prescale")) { @@ -879,9 +987,11 @@ void v2swf_setparameter(v2swf_t*v2swf, char*name, char*value) i->blockdiff = atoi(value); } else if(!strcmp(name, "fixheader")) { i->fixheader = atoi(value); + } else if(!strcmp(name, "samplerate")) { + i->samplerate = atoi(value); } else if(!strcmp(name, "framerate")) { i->framerate = atof(value); - i->fpsratio = i->framerate / i->video->fps; + i->fpsratio = i->framerate / i->video_fps; } else if(!strcmp(name, "mp3_bitrate")) { int t=0,o; @@ -895,7 +1005,7 @@ void v2swf_setparameter(v2swf_t*v2swf, char*name, char*value) } t++; } - logf("bitrate %d requested, setting to %d", o, i->bitrate); + msg("bitrate %d requested, setting to %d", o, i->bitrate); } else if(!strcmp(name, "blockdiff_mode")) { if(!strcmp(value, "max")) i->diffmode = DIFFMODE_MAX; @@ -922,7 +1032,7 @@ void v2swf_backpatch(v2swf_t*v2swf, char*filename) FILE* fi; unsigned char f; v2swf_internal_t* i = (v2swf_internal_t*)v2swf->internal; - logf("v2swf_backpatch %s\n", filename); + msg("v2swf_backpatch %s\n", filename); if(!i) { printf("call backpatch before close\n");fflush(stdout); } @@ -946,7 +1056,7 @@ void v2swf_backpatch(v2swf_t*v2swf, char*filename) if(i->fixheader) { SWF tmp; int fi; - logf("v2swf_backpatch %s - fix header\n", filename); + msg("v2swf_backpatch %s - fix header\n", filename); memset(&tmp, 0, sizeof(tmp)); fi = open(filename, O_RDONLY|O_BINARY); if(fi>=0) { @@ -954,40 +1064,17 @@ void v2swf_backpatch(v2swf_t*v2swf, char*filename) close(fi); fi = open(filename, O_WRONLY|O_BINARY|O_TRUNC|O_CREAT, 0666); if(fi>=0) { - swf_WriteSWC(fi, &tmp); + swf_WriteSWF(fi, &tmp); close(fi); - logf("v2swf_backpatch %s - fix header: success\n", filename); + msg("v2swf_backpatch %s - fix header: success\n", filename); } } } } } -float v2swf_getprogress(v2swf_t*v2swf) -{ - float* p; - v2swf_internal_t* i; - logf("v2swf_getprogress()"); - if(!v2swf || !v2swf->internal) { - return 0.0; - } - i = (v2swf_internal_t*)v2swf->internal; - - p = (float*)videoreader_getinfo(i->video, "position"); - - if(p) { - return *p; - } else { - float f = i->frames/1500.0; /*fake*/ - if(f>1.0) - return 1.0; - else - return f; - } -} - void v2swf_setvideoparameter(videoreader_t*v, char*name, char*value) { - logf("v2swf_setvideoparameter()"); + msg("v2swf_setvideoparameter()"); videoreader_setparameter(v, name, value); }