BITMAPINFOHEADER bitmap;
WAVEFORMATEX waveformat;
+ int audio_eof;
+ int video_eof;
+
int video_pos;
int video_end;
int samplerate;
int channels;
+ int flip;
} videoreader_vfw_internal_t;
static int avifile_initialized = 0;
+static int verbose;
-#define _TRACE_ {printf("%s: %d (%s)\n",__FILE__,__LINE__,__func__);fflush(stdout);}
-
-bool videoreader_vfw_eof(videoreader_t* vr)
-{
- videoreader_vfw_internal_t* i = (videoreader_vfw_internal_t*)vr->internal;
- return (i->video_pos >= i->video_end);
-}
+#define _TRACE_ {printf("vfw: %s: %d (%s)\n",__FILE__,__LINE__,__func__);fflush(stdout);}
-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
int bytesperpixel = ((bi->biWidth*bi->biBitCount)+7)&~7;
int linex = ((bytesperpixel/8)+3)&~3;
memset(dest, 255, dest_width*dest_height*4);//pre-fill alpha channel
+
+ 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) {
- int y;
UCHAR*img = data;
- for(y=0;y<dest_height;y++) {
+ int y;
+ for(y=starty;y!=endy;y+=yinc) {
UCHAR*line = &img[linex*y];
int x;
for(x=0;x<dest_width;x++) {
}
}
} else if(bi->biBitCount==4) {
- int y;
UCHAR*img = &data[bi->biClrUsed*4];
UCHAR*pal = data;
- for(y=0;y<dest_height;y++) {
+ int y;
+ for(y=starty;y!=endy;y+=yinc) {
UCHAR*line = &img[linex*y];
int x;
for(x=0;x<dest_width/2;x++) {
}
}
} else if(bi->biBitCount==8) {
- int y;
UCHAR*img = &data[bi->biClrUsed*4];
UCHAR*pal = data;
- for(y=0;y<dest_height;y++) {
+ int y;
+ for(y=starty;y!=endy;y+=yinc) {
UCHAR*line = &img[linex*y];
int x;
for(x=0;x<dest_width;x++) {
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++) {
+ USHORT c = line[0]|line[1]<<8;
+ *dest++ = 255|(c&0x1f)<<(24+3)|(c>>5&0x1f)<<(16+3)|(c>>10&0x1f)<<(8+3);
+ line+=2;
+ }
+ }
} else if(bi->biBitCount==24) {
UCHAR*img = data;
int y;
- for(y=0;y<dest_height;y++) {
+ for(y=starty;y!=endy;y+=yinc) {
UCHAR*line = &img[linex*y];
int x;
for(x=0;x<dest_width;x++) {
} else if(bi->biBitCount==32) {
UCHAR*img = data;
int y;
- for(y=0;y<dest_height;y++) {
+ for(y=starty;y!=endy;y+=yinc) {
UCHAR*line = &img[linex*y];
int x;
for(x=0;x<dest_width;x++) {
return 1;
}
-int videoreader_vfw_getimage(videoreader_t* vr, void*buffer)
+static int videoreader_vfw_getimage(videoreader_t* vr, void*buffer)
{
videoreader_vfw_internal_t* i = (videoreader_vfw_internal_t*)vr->internal;
- if(videoreader_vfw_eof(vr))
+ if (i->video_pos >= i->video_end)
+ i->video_eof = 1;
+
+ if(i->video_eof)
return 0;
LPBITMAPINFOHEADER bi;
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;
}
return bytes;
}
-int videoreader_vfw_getsamples(videoreader_t* vr, void*buf, int num)
+static int videoreader_vfw_getsamples(videoreader_t* vr, void*buf, int num)
{
videoreader_vfw_internal_t* i = (videoreader_vfw_internal_t*)vr->internal;
+
+ if(i->audio_eof)
+ return 0;
switch(i->waveformat.wBitsPerSample) {
case 1: {
do {
((SHORT*)buf)[t] = ((((BYTE*)buf)[t>>3])>>(t&7))<<15;
} while(--t>=0);
+ if(!len) i->audio_eof = 1;
return len*8;
}
case 8: {
do {
((SHORT*)buf)[t] = (((BYTE*)buf)[t]<<8)^0x8000;
} while(--t>=0);
+ if(!len) i->audio_eof = 1;
return len*2;
}
case 16: {
- return readAudioBlock(i, buf, num);
+ int len = readAudioBlock(i, buf, num);
+ if(!len) i->audio_eof = 1;
+ return len;
}
default: {
return 0;
}
}
-void videoreader_vfw_close(videoreader_t* vr)
+static void videoreader_vfw_close(videoreader_t* vr)
{
videoreader_vfw_internal_t* i = (videoreader_vfw_internal_t*)vr->internal;
free(vr->internal); vr->internal = 0;
}
-void videoreader_vfw_setparameter(videoreader_t* vr, char*name, char*value) {}
+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);
+ }
+}
int videoreader_vfw_open(videoreader_t* vr, char* filename)
{
memset(i, 0, sizeof(videoreader_vfw_internal_t));
vr->internal = i;
- vr->eof = videoreader_vfw_eof;
vr->getimage = videoreader_vfw_getimage;
vr->getsamples = videoreader_vfw_getsamples;
vr->close = videoreader_vfw_close;
/* 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;
}
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;
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 {