added 16 bit support (yet untested).
[swftools.git] / avi2swf / videoreader_vfw.cc
index 2e0c787..f9558b9 100644 (file)
@@ -53,8 +53,9 @@ typedef struct _videoreader_vfw_internal {
 } videoreader_vfw_internal_t;
 
 static int avifile_initialized = 0;
+static int verbose;
 
-#define _TRACE_ {printf("%s: %d (%s)\n",__FILE__,__LINE__,__func__);fflush(stdout);}
+#define _TRACE_ {printf("vfw: %s: %d (%s)\n",__FILE__,__LINE__,__func__);fflush(stdout);}
 
 static bool videoreader_vfw_eof(videoreader_t* vr)
 {
@@ -62,7 +63,7 @@ static bool videoreader_vfw_eof(videoreader_t* vr)
     return (i->video_pos >= i->video_end);
 }
 
-static int bitmap_to_rgba(BITMAPINFOHEADER*bi, void*buffer, const int dest_width, const int dest_height)
+static int bitmap_to_rgba(BITMAPINFOHEADER*bi, void*buffer, const int dest_width, const int dest_height, int flip)
 {
     UCHAR*data = (UCHAR*)(bi+1); // actual bitmap data starts after the header
 
@@ -89,14 +90,18 @@ static int bitmap_to_rgba(BITMAPINFOHEADER*bi, void*buffer, const int dest_width
     int linex = ((bytesperpixel/8)+3)&~3;
     memset(dest, 255, dest_width*dest_height*4);//pre-fill alpha channel
 
-    int starty = i->flip? 0 : dest_height-1;
-    int endy   = i->flip? dest_height-1 : 0;
-    int yinc   = i->flip? 1 : -1;
+    const int starty = flip? 0 : dest_height-1;
+    const int endy   = flip? dest_height : -1;
+    const int yinc   = flip? 1 : -1;
+
+    if(verbose) {
+       printf("vfw: Convering scanlines %d to %d from bpp %d, %d stepping, flip=%d\n", starty, endy, bi->biBitCount, yinc, flip);
+    }
 
     if(bi->biBitCount==1) {
        UCHAR*img = data;
        int y;
-       for(y=starty;y<=endy;y+=yinc) {
+       for(y=starty;y!=endy;y+=yinc) {
            UCHAR*line = &img[linex*y];
            int x;
            for(x=0;x<dest_width;x++) {
@@ -107,7 +112,7 @@ static int bitmap_to_rgba(BITMAPINFOHEADER*bi, void*buffer, const int dest_width
        UCHAR*img = &data[bi->biClrUsed*4];
        UCHAR*pal = data;
        int y;
-       for(y=starty;y<=endy;y+=yinc) {
+       for(y=starty;y!=endy;y+=yinc) {
            UCHAR*line = &img[linex*y];
            int x;
            for(x=0;x<dest_width/2;x++) {
@@ -120,7 +125,7 @@ static int bitmap_to_rgba(BITMAPINFOHEADER*bi, void*buffer, const int dest_width
        UCHAR*img = &data[bi->biClrUsed*4];
        UCHAR*pal = data;
        int y;
-       for(y=starty;y<=endy;y+=yinc) {
+       for(y=starty;y!=endy;y+=yinc) {
            UCHAR*line = &img[linex*y];
            int x;
            for(x=0;x<dest_width;x++) {
@@ -128,10 +133,22 @@ static int bitmap_to_rgba(BITMAPINFOHEADER*bi, void*buffer, const int dest_width
                line++;
            }
        }
+    } else if(bi->biBitCount==16) {
+       UCHAR*img = data;
+       int y;
+       for(y=starty;y!=endy;y+=yinc) {
+           UCHAR*line = &img[linex*y];
+           int x;
+           for(x=0;x<dest_width;x++) {
+               U16 c = line[0]|line[1]<<8;
+               *dest++ = 255|(c&0x1f)<<(8+3)|(c>>5&0x1f)<<(16+3)|(c>>10&0x1f)<<(24+3);
+               line+=2;
+           }
+       }
     } else if(bi->biBitCount==24) {
        UCHAR*img = data;
        int y;
-       for(y=starty;y<=endy;y+=yinc) {
+       for(y=starty;y!=endy;y+=yinc) {
            UCHAR*line = &img[linex*y];
            int x;
            for(x=0;x<dest_width;x++) {
@@ -142,7 +159,7 @@ static int bitmap_to_rgba(BITMAPINFOHEADER*bi, void*buffer, const int dest_width
     } else if(bi->biBitCount==32) {
        UCHAR*img = data;
        int y;
-       for(y=starty;y<=endy;y+=yinc) {
+       for(y=starty;y!=endy;y+=yinc) {
            UCHAR*line = &img[linex*y];
            int x;
            for(x=0;x<dest_width;x++) {
@@ -175,7 +192,7 @@ static int videoreader_vfw_getimage(videoreader_t* vr, void*buffer)
        return 0;
     }
     
-    if(!bitmap_to_rgba(bi, buffer, i->width, i->height)) {
+    if(!bitmap_to_rgba(bi, buffer, i->width, i->height, i->flip)) {
        fprintf(stderr, "couldn't convert bitmap to RGBA.\n");
        return 0;
     }
@@ -244,6 +261,8 @@ static void videoreader_vfw_setparameter(videoreader_t*vr, char*name, char*value
     videoreader_vfw_internal_t* i = (videoreader_vfw_internal_t*)vr->internal;
     if(!strcmp(name, "flip")) {
        i->flip = atoi(value);
+    } else if(!strcmp(name, "verbose")) {
+       verbose = atoi(value);
     }
 }
 
@@ -278,6 +297,10 @@ int videoreader_vfw_open(videoreader_t* vr, char* filename)
     /* calculate framerate */
     i->fps = (double)info.dwRate/(double)info.dwScale;
 
+    if(verbose) {
+       printf("vfw: file %s has %f fps, and %d streams\n", i->fps, info.dwStreams);
+    }
+
     unsigned int t=0;
     while(t<info.dwStreams) {
        PAVISTREAM stream;
@@ -328,6 +351,9 @@ int videoreader_vfw_open(videoreader_t* vr, char* filename)
     }
 
     if(i->vs) {
+       if(verbose) {
+           printf("vfw: video stream: %dx%d, %.2f\n", i->width, i->height, i->fps);
+       }
        vr->width = i->width;
        vr->height = i->height;
        vr->fps = i->fps;
@@ -335,6 +361,9 @@ int videoreader_vfw_open(videoreader_t* vr, char* filename)
        fprintf(stderr, "AVIReader: Warning: No video stream\n");
     }
     if(i->as) {
+       if(verbose) {
+           printf("vfw: audio stream: %d channels, %d samples/sec", i->channels, i->samplerate);
+       }
        vr->channels = i->channels;
        vr->samplerate = i->samplerate;
     } else {