new parameter addspacechars
[swftools.git] / avi2swf / v2swf.c
index a536c08..c974bfb 100644 (file)
@@ -34,11 +34,12 @@ 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;
@@ -69,6 +70,8 @@ typedef struct _v2swf_internal_t
     int keyframe;
     int showframe;
 
+    int skipframes;
+
     float samplepos;
     float framesamplepos;
     int samplewritepos;
@@ -76,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;
 
@@ -103,7 +110,7 @@ static void msg(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') {
@@ -179,9 +186,10 @@ static int getSamples(videoreader_t*video, S16*data, int len, double speedup)
     int r = /*resampled len */ rlen * 
                  /* s16_le */ 2 * 
                               video->channels;
-    int l;
+    int l = 0;
     memset(tmp, 0, sizeof(tmp));
-    l = videoreader_getsamples(video, tmp, r);
+    if(r>0)
+       l = videoreader_getsamples(video, tmp, r);
     if(l <= 0) {
        return 0;
     }
@@ -329,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;
 }
@@ -413,8 +421,22 @@ static void finish(v2swf_internal_t*i)
     if(!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) {
@@ -571,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;y<i->height;y++,yv+=ym) {
        int*src = &((int*)i->vrbuffer)[(yv>>16)*i->video->width];
@@ -596,6 +623,21 @@ static int writeAudioOnly(v2swf_internal_t*i)
     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;t<i->skipframes;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;
@@ -613,11 +655,11 @@ static int encodeoneframe(v2swf_internal_t*i)
        return writeAudioOnly(i);
     }
 
-    if(!videoreader_getimage(i->video, i->vrbuffer)) 
+    if(!getframe(i) || (i->numframes && i->frames==i->numframes)) 
     {
        i->video_eof = 1;
        msg("videoreader returned eof\n");
-       if(i->audio_eof) {
+       if(i->audio_eof || (i->numframes && i->frames==i->numframes)) {
            finish(i);
            return 0;
        } else {
@@ -635,8 +677,6 @@ static int encodeoneframe(v2swf_internal_t*i)
        writeShowFrame(i);
     }
     
-    msg("scaling\n");
-
     scaleimage(i);
 
     msg("version is %d\n", i->version);
@@ -810,6 +850,15 @@ 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;
@@ -823,20 +872,26 @@ int v2swf_init(v2swf_t*v2swf, videoreader_t * video)
 
     ringbuffer_init(&i->r);
 
+    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->video = video;
     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.00000000000;
     i->fpspos = 0.0;
     i->bitrate = 32;
@@ -850,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;
 }
@@ -911,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")) {
@@ -929,7 +991,7 @@ void v2swf_setparameter(v2swf_t*v2swf, char*name, char*value)
        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;
@@ -1002,7 +1064,7 @@ 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);
                    msg("v2swf_backpatch %s - fix header: success\n", filename);
                }