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;
float fpspos;
int bitrate;
+ int samplerate;
int finished;
int keyframe;
int showframe;
+ int skipframes;
+
float samplepos;
float framesamplepos;
int samplewritepos;
int soundstreamhead;
int seek;
+ int numframes;
+
double audio_fix;
int fixheader;
int prescale;
int scale;
+
+ int add_cut;
int domotion;
static int verbose = 0;
static int filelog = 0;
-static void logf(char*format, ...)
+static void msg(char*format, ...)
{
char buf[1024];
int l;
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;
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;t<rlen;t++) {
tmp[t] = a/video->channels;
}
- /* down/up-sample to 44khz */
+ /* down/up-sample to the desired input samplerate (swf_mp3_in_samplerate) */
for(t=0;t<len;t++) {
data[t] = tmp[(int)pos];
pos+=ratio;
}
- return 1;
+ return l == r;
}
-extern int swf_mp3_channels;
-extern int swf_mp3_bitrate;
-extern int swf_mp3_samplerate;
static void writeAudioForOneFrame(v2swf_internal_t* i)
{
int blocksize;
int pos = 0;
S16 block1[576*4 * 2];
- logf("writeAudioForOneFrame()");
+ msg("writeAudioForOneFrame()");
- if(i->video->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;
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;
}
/* 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;
}
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;pos<num;pos++) {
- logf("pos: %d- getsamples", pos);
- if(!getSamples(i->video, 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);
}
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)
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;
}
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) {
}
/* 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)
{
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];
//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;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;
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) {
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);
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);
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));
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;
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;
}
{
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) {
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;
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[] =
{
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;
}
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")) {
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;
}
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;
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);
}
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) {
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);
}