X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=avi2swf%2Favi2swf.cc;h=3c63920aa63d827c92830d716d7be9401481717c;hb=750fcbdf1641a11f6050361021859337ceb3997d;hp=d75c0c55bda1ea7f6db35779af48ebf0f110a39f;hpb=a5c69d1a1ff3e1d3908bf7b23cc7be815acb24d0;p=swftools.git diff --git a/avi2swf/avi2swf.cc b/avi2swf/avi2swf.cc index d75c0c5..3c63920 100644 --- a/avi2swf/avi2swf.cc +++ b/avi2swf/avi2swf.cc @@ -1,7 +1,5 @@ /* avi2swf.cc Convert avi movie files into swf. - As soon as the size of the generated swfs is reasonable, this file - will go to ../../src Part of the swftools package. @@ -15,8 +13,23 @@ extern "C" { #include "../lib/rfxswf.h" #include "../lib/args.h" } -#include "avifile.h" -#include "aviplay.h" +#include +#if (AVIFILE_MAJOR_VERSION == 0) && (AVIFILE_MINOR_VERSION==6) + #include + #include + #include + #include + #include + #define VERSION6 +#else + #include + #include + #include + #define Width width + #define Height height + #define Data data + #define Bpp bpp +#endif /* statistics: (for now) @@ -33,18 +46,23 @@ statistics: (for now) 2 bytes per showframe */ -int cache_size=38; //in frames +static int cache_size=38; //in frames + +static char * filename = 0; +static char * outputfilename = "output.swf"; +static unsigned int firstframe = 0; +static unsigned int lastframe = 0x7fffffff; -char * filename = 0; -char * outputfilename = "output.swf"; -unsigned int firstframe = 0; -unsigned int lastframe = 0x7fffffff; +static int jpeg_quality = 20; -int jpeg_quality = 20; +static char zlib = 0; +static double scale = 1.0; #ifndef ST_DEFINEBITSJPEG #define ST_DEFINEBITSJPEG 6 #endif + +int filesize = 0; struct options_t options[] = { @@ -52,6 +70,7 @@ struct options_t options[] = {"o","output"}, {"n","num"}, {"s","start"}, + {"z","zlib"}, {"V","version"}, {0,0} }; @@ -74,6 +93,20 @@ int args_callback_option(char*name,char*val) firstframe = atoi(val); return 1; } + else if(!strcmp(name, "d")) { + scale = atoi(val)/100.0; + if(scale>1.0 || scale<=0) { + fprintf(stderr, "Scale must be in the range 1-100!\n"); + exit(1); + } + return 1; + } + else if(!strcmp(name, "z")) { + zlib = 1; + return 0; + } + fprintf(stderr, "Unknown option: -%s\n", name); + exit(1); } int args_callback_longoption(char*name,char*val) { @@ -81,11 +114,12 @@ int args_callback_longoption(char*name,char*val) } void args_callback_usage(char*name) { - printf("\nUsage: %s file.swf\n", name); + printf("\nUsage: %s file.avi\n", name); printf("\t-h , --help\t\t Print help and exit\n"); - printf("\t-o , --output=filename\t Specify output filename\n"); - printf("\t-n , --num=frames\t\t Number of frames to encode\n"); - printf("\t-s , --start=frame\t\t First frame to encode\n"); + printf("\t-o , --output filename\t Specify output filename\n"); + printf("\t-n , --num frames\t Number of frames to encode\n"); + printf("\t-s , --start frame\t First frame to encode\n"); + printf("\t-d , --scale factor\t Scale to factor percent\n"); printf("\t-V , --version\t\t Print program version and exit\n"); exit(0); } @@ -151,7 +185,7 @@ void makeshape(int file, int id, int gfxid, int width, int height) swf_ShapeSetLine(tag,s,-width*20,0); swf_ShapeSetLine(tag,s,0,-height*20); swf_ShapeSetEnd(tag); - swf_WriteTag(file, tag); + filesize += swf_WriteTag(file, tag); swf_DeleteTag(tag); swf_ShapeFree(s); } @@ -168,7 +202,7 @@ void setshape(int file,int id,int depth,int x,int y,CXFORM*cx) ||(cx->a1|cx->r1|cx->g1|cx->b1))) cx = 0; tag = swf_InsertTag(NULL,ST_PLACEOBJECT2); swf_ObjectPlace(tag,id,depth,&m,cx,0); - swf_WriteTag(file, tag); + filesize += swf_WriteTag(file, tag); swf_DeleteTag(tag); } @@ -299,8 +333,10 @@ class GfxBlockCache { { int t; printf("destroying cache...\n"); - printf("hits:%d (%02d%%)\n", hits, hits*100/(hits+misses)); - printf("misses:%d (%02d%%)\n", misses, misses*100/(hits+misses)); + if(hits+misses) { + printf("hits:%d (%02d%%)\n", hits, hits*100/(hits+misses)); + printf("misses:%d (%02d%%)\n", misses, misses*100/(hits+misses)); + } for(t=0;tdata[y*sizex*3]); swf_SetJPEGBitsFinish(jb); - swf_WriteTag(file, tag); + filesize += swf_WriteTag(file, tag); swf_DeleteTag(tag); cache->insert(block, shapeid); @@ -420,7 +456,7 @@ void initdisplay(int file) TAG*tag = swf_InsertTag(NULL, ST_JPEGTABLES); JPEGBITS * jpeg = swf_SetJPEGBitsStart(tag, xblocksize, yblocksize, jpeg_quality); - swf_WriteTag(file, tag); + filesize += swf_WriteTag(file, tag); swf_DeleteTag(tag); free(jpeg); } @@ -435,17 +471,93 @@ void destroydisplay(int file) SWF swf; TAG*tag; +class SoundReader +{ + + short int* sound_buffer; + int mp3_block_size; + int write_pos; + int read_pos; + IAviReadStream* astream; + void readBlock() + { + unsigned samples_read, bytes_read; + int ret; + short int tmpbuf[4096]; + ret = astream->ReadFrames(tmpbuf, 4096*sizeof(short int), + 4096, samples_read, bytes_read); + if(ret<0) { + printf("couldn't read %d samples\n", mp3_block_size); + exit(1); + } + int t; + samples_read = bytes_read/sizeof(short int); + for(t=0;t= mp3_block_size*8) + { + if(write_pos > mp3_block_size*8) + memcpy(&sound_buffer[0],&sound_buffer[mp3_block_size*8],write_pos - mp3_block_size*8); + write_pos %= (mp3_block_size*8); + } + } + public: + + SoundReader(IAviReadStream*astream) + { + this->astream = astream; + this->write_pos = 0; + this->read_pos = 0; + this->mp3_block_size = 2304; + this->sound_buffer = new short int[mp3_block_size*16]; + } + ~SoundReader() + { + delete sound_buffer; + } + int available() + { + if(read_pos<=write_pos) + return write_pos-read_pos; + else + return (write_pos+mp3_block_size*8)-read_pos; + } + short int* readFrame() + { + int tmp; + while(available()GetStream(0, AviStream::Audio); + vstream = player->GetStream(0, AviStream::Video); + if(!vstream) + do_video = 0; + if(!astream) + do_audio = 0; +#ifndef VERSION6 + MainAVIHeader head; + int dwMicroSecPerFrame = 0; player->GetFileHeader(&head); printf("fps: %d\n", 1000000/head.dwMicroSecPerFrame); printf("frames: %d\n", head.dwTotalFrames); printf("streams: %d\n", head.dwStreams); - printf("streams: %d\n", player->StreamCount()); printf("width: %d\n", head.dwWidth); printf("height: %d\n", head.dwHeight); - - astream = player->GetStream(0, AviStream::Audio); - vstream = player->GetStream(0, AviStream::Video); - - vstream -> StartStreaming(); - astream -> StartStreaming(); - - width = head.dwWidth; - height = head.dwHeight; - printf("sound: %u samples (%f seconds)\n", astream->GetEndPos(), astream->GetEndTime()); + oldwidth = head.dwWidth; + oldheight = head.dwHeight; + dwMicroSecPerFrame = head.dwMicroSecPerFrame; samplesperframe = astream->GetEndPos()/astream->GetEndTime()*head.dwMicroSecPerFrame/1000000; - printf("%f samples/frame\n", samplesperframe); samplerate = (int)(astream->GetEndPos()/astream->GetEndTime()); - printf("%d samplerate\n", samplerate); - samplefix = 44100/samplerate; + fps = 1000000.0/dwMicroSecPerFrame; +#else + StreamInfo*audioinfo; + StreamInfo*videoinfo; + if(do_video) + { + videoinfo = vstream->GetStreamInfo(); + oldwidth = videoinfo->GetVideoWidth(); + oldheight = videoinfo->GetVideoHeight(); + fps = (double)(videoinfo->GetFps()); + delete(videoinfo); + } + if(do_audio) + { + audioinfo = astream->GetStreamInfo(); + samplerate = audioinfo->GetAudioSamplesPerSec(); + samplesperframe = audioinfo->GetAudioSamplesPerSec()/videoinfo->GetFps(); + delete(audioinfo); + } +#endif + width = (int)(oldwidth*scale); + height = (int)(oldheight*scale); + reziscale = 1/scale; - if(!samplefix) { - printf("samplerate too high!\n"); - return 0; + vstream -> StartStreaming(); + if(do_audio) + { + astream -> StartStreaming(); + printf("%f framerate\n", fps); + printf("%f samples/frame\n", samplesperframe); + printf("%d samplerate\n", samplerate); } - printf("%d mp3 samples per movie sample\n", samplefix); - file = open(outputfilename,O_WRONLY|O_CREAT|O_TRUNC, 0644); + if(zlib) + file = open("__tmp__.swf", O_WRONLY|O_CREAT|O_TRUNC, 0644); + else + file = open(outputfilename, O_WRONLY|O_CREAT|O_TRUNC, 0644); memset(&swf, 0, sizeof(swf)); - swf.frameRate = (int)(1000000.0/head.dwMicroSecPerFrame*256); + swf.frameRate = (int)(fps*256); swf.fileVersion = 4; - swf.fileSize = 476549;//0x0fffffff; + swf.fileSize = 0x0fffffff; swf.frameCount = lastframe - firstframe; r.xmin = 0; r.ymin = 0; @@ -499,45 +638,40 @@ int main (int argc,char ** argv) r.ymax = height*20; swf.movieSize = r; - swf_WriteHeader(file, &swf); + filesize += swf_WriteHeader(file, &swf); tag = swf_InsertTag(NULL, ST_SETBACKGROUNDCOLOR); swf_SetU8(tag,0); //black swf_SetU8(tag,0); swf_SetU8(tag,0); - swf_WriteTag(file, tag); + filesize += swf_WriteTag(file, tag); swf_DeleteTag(tag); tag = swf_InsertTag(NULL, ST_SOUNDSTREAMHEAD2); - swf_SetSoundStreamHead(tag, 1152); - swf_WriteTag(file, tag); + swf_SetSoundStreamHead(tag, (int)samplesperframe/4); + filesize += swf_WriteTag(file, tag); swf_DeleteTag(tag); int frame = 0; initdisplay(file); - int mp3_block_size = 1152; - - int bufsize = mp3_block_size; - if(mp3_block_size < (int)(samplesperframe+1)) - bufsize = (int)(samplesperframe + 1); - unsigned char*buffer = (unsigned char*)malloc(bufsize); - short*block = (short*)malloc(bufsize*2*samplefix); - - unsigned samples_read, bytes_read; - double movie_sound_pos = 0; int mp3_sound_pos = 0; - WAVEFORMATEX wave; - astream->GetAudioFormatInfo(&wave,0); + if(do_audio) + { + WAVEFORMATEX wave; + astream->GetAudioFormatInfo(&wave,0); + + printf("nChannels:%d\n", wave.nChannels); + printf("nSamplesPerSec:%d\n", wave.nSamplesPerSec); + printf("nAvgBytesPerSec:%d\n", wave.nAvgBytesPerSec); + printf("nBlockAlign:%d\n", wave.nBlockAlign); + printf("wBitsPerSample:%d\n", wave.wBitsPerSample); + printf("cbSize:%d\n", wave.cbSize); + } - printf("nChannels:%d\n", wave.nChannels); - printf("nSamplesPerSec:%d\n", wave.nChannels); - printf("nAvgBytesPerSec:%d\n", wave.nAvgBytesPerSec); - printf("nBlockAlign:%d\n", wave.nBlockAlign); - printf("wBitsPerSample:%d\n", wave.wBitsPerSample); - printf("cbSize:%d\n", wave.cbSize); + SoundReader* sound = new SoundReader(astream); while(1) { if(vstream->ReadFrame()<0) { @@ -547,12 +681,12 @@ int main (int argc,char ** argv) if(frame < firstframe) { - if(astream->ReadFrames(buffer, bufsize, - (int)samplesperframe, - samples_read, bytes_read)<0) { - printf("\n"); - break; - }; + movie_sound_pos += samplesperframe; + if(do_audio) + while(mp3_sound_posreadFrame(); + mp3_sound_pos += mp3_block_size; + } printf("\rskipping frame %d",frame); fflush(stdout); frame++; @@ -560,7 +694,7 @@ int main (int argc,char ** argv) printf("\n"); continue; } - + printf("\rconvert frame %d",frame); fflush(stdout); @@ -568,35 +702,23 @@ int main (int argc,char ** argv) movie_sound_pos += samplesperframe; int first=1; + if(do_audio) while(mp3_sound_posReadFrames(buffer, bufsize, - mp3_block_size/samplefix, - samples_read, bytes_read)<0) { - printf("couldn't read %d samples\n", mp3_block_size); - break; - }; - int t=0; + // rawplay -s 44100 -f s16_le -c 2 samples.test + short int* samples = sound->readFrame(); int s; int c=0; - for(s=0;s=movie_sound_pos) { // last run - swf_WriteTag(file, tag); + filesize += swf_WriteTag(file, tag); swf_DeleteTag(tag); } first = 0; @@ -606,8 +728,8 @@ int main (int argc,char ** argv) CImage*img = vstream->GetFrame(); img->ToRGB(); - U8*data = img->data(); - int bpp = img->bpp(); + U8*data = img->Data(); + int bpp = img->Bpp(); int x,y; int xx,yy; int fs,ls; @@ -617,11 +739,13 @@ int main (int argc,char ** argv) RGBA rgb; /* some movies have changing dimensions */ - if(img->width() != width || - img->height() != height) { + if(img->Width() != oldwidth || + img->Height() != oldheight) { printf("\n"); - width = img->width(); - height = img->height(); + oldwidth = img->Width(); + oldheight = img->Height(); + width = (int)(oldwidth*scale); + height = (int)(oldheight*scale); initdisplay(file); } @@ -630,11 +754,15 @@ int main (int argc,char ** argv) { int x,y; for(y=0;yat(yy*yblocksize+y); +#ifdef VERSION6 + U8*mydata = img->At(oldheight-(int)((yy*yblocksize+y)*reziscale)); +#else + U8*mydata = img->At((int)((yy*yblocksize+y)*reziscale)); +#endif for(x=0;xnewframe(); @@ -653,14 +781,42 @@ int main (int argc,char ** argv) if(frame == lastframe) break; } + delete sound; printf("\n"); destroydisplay(file); tag = swf_InsertTag(NULL, ST_END); - swf_WriteTag(file, tag); + filesize += swf_WriteTag(file, tag); swf_DeleteTag(tag); close(file); + + FILE*fi; + if(zlib) + fi=fopen("tmp.swf", "r+"); + else + fi=fopen(outputfilename, "r+"); + + if(fi) + { + fseek(fi,4,SEEK_SET); + unsigned char f; + f = filesize ;fwrite(&f,1,1,fi); + f = filesize >> 8 ;fwrite(&f,1,1,fi); + f = filesize >> 16;fwrite(&f,1,1,fi); + f = filesize >> 24;fwrite(&f,1,1,fi); + fclose(fi); + } + + if(zlib) { + char buffer[1024]; + snprintf(buffer, 1024, "swfcombine -dz __tmp__.swf -o %s", outputfilename); + printf("%s\n", buffer); + system(buffer); + sprintf(buffer, "rm __tmp__.swf"); + printf("%s\n", buffer); + system(buffer); + } return 0; }