1 /* videoreader_avifile.cc
2 Read avi files using the avifile library.
4 Part of the swftools package.
6 Copyright (c) 2001,2002,2003 Matthias Kramm <kramm@quiss.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
25 #include "../config.h"
32 #ifdef HAVE_AVIFILE_VERSION_H
33 #include <avifile/version.h>
36 #if (AVIFILE_MAJOR_VERSION == 0) && (AVIFILE_MINOR_VERSION>=6)
41 #include <StreamInfo.h>
62 #include "videoreader.h"
64 static int shutdown_avi2swf
= 0;
65 static int verbose
= 0;
67 typedef struct _videoreader_avifile_internal
70 IAviReadStream
* astream
;
71 IAviReadStream
* vstream
;
78 ringbuffer_t audio_buffer
;
79 } videoreader_avifile_internal
;
81 static void readSamples(videoreader_avifile_internal
*i
, void*buffer
, int buffer_size
, int numsamples
)
84 while(i
->audio_buffer
.available
< buffer_size
) {
85 unsigned int samples_read
= 0, bytes_read
= 0;
86 ret
= i
->astream
->ReadFrames(buffer
, buffer_size
, numsamples
, samples_read
, bytes_read
);
89 ringbuffer_put(&i
->audio_buffer
, buffer
, bytes_read
);
91 ringbuffer_read(&i
->audio_buffer
, buffer
, buffer_size
);
93 static int videoreader_avifile_getsamples(videoreader_t
* v
, void*buffer
, int num
)
96 printf("videoreader_getsamples(%d)\n", num
);fflush(stdout
);
98 videoreader_avifile_internal
*i
= (videoreader_avifile_internal
*)v
->internal
;
99 if(i
->soundbits
== 8) {
100 readSamples(i
, buffer
, num
/2, num
/(v
->channels
*2));
101 unsigned char*b
= (unsigned char*)buffer
;
103 for(t
=num
-2;t
>=0;t
-=2) {
104 unsigned char x
= b
[t
/2];
110 if(i
->soundbits
== 16) {
111 readSamples(i
, buffer
, num
, num
/(v
->channels
*2));
116 static int videoreader_avifile_getimage(videoreader_t
* v
, void*buffer
)
118 videoreader_avifile_internal
*i
= (videoreader_avifile_internal
*)v
->internal
;
120 printf("videoreader_getimage()\n");fflush(stdout
);
129 if(i
->vstream
->ReadFrame() < 0) {
130 if(verbose
) printf("vstream->ReadFrame() returned value < 0, shutting down...\n");
135 CImage
*img
= i
->vstream
->GetFrame();
137 if(verbose
) printf("vstream->GetFrame() returned NULL, shutting down...\n");
141 /* we convert the image to YUV first, because we can convert to RGB from YUV only */
144 if(img
->Bpp() != 3) {
145 if(verbose
) printf("Warning: converthing from bpp %d to bpp 3, this fails on older avifile versions...\n", img
->Bpp());
146 BitmapInfo
tmp(v
->width
, v
->height
, 24);
147 img2
= new CImage(img
, &tmp
);
153 unsigned char*data
= img
->Data();
154 int bpp
= img
->Bpp();
157 for(y
=0;y
<v
->height
;y
++) {
158 unsigned char*from
,*to
;
159 to
= &((unsigned char*)buffer
)[y
*v
->width
*4];
161 from
= img
->At(v
->height
-y
-1);
164 for(x
=0;x
<v
->width
;x
++) {
166 to
[x
*4+1] = from
[x
*3+2];
167 to
[x
*4+2] = from
[x
*3+1];
168 to
[x
*4+3] = from
[x
*3+0];
171 if(img2
) delete img2
;
172 return v
->width
*v
->height
*4;
174 if(img2
) delete img2
;
175 if(verbose
) printf("Can't handle bpp %d, shutting down...\n", bpp
);
179 static bool videoreader_avifile_eof(videoreader_t
* v
)
181 videoreader_avifile_internal
*i
= (videoreader_avifile_internal
*)v
->internal
;
183 printf("videoreader_eof()\n");fflush(stdout
);
187 static void videoreader_avifile_close(videoreader_t
* v
)
189 videoreader_avifile_internal
*i
= (videoreader_avifile_internal
*)v
->internal
;
191 printf("videoreader_close()\n");fflush(stdout
);
194 ringbuffer_clear(&i
->audio_buffer
);
197 static void videoreader_avifile_setparameter(videoreader_t
*v
, char*name
, char*value
)
199 videoreader_avifile_internal
*i
= (videoreader_avifile_internal
*)v
->internal
;
200 if(!strcmp(name
, "verbose")) {
201 verbose
= atoi(value
);
203 if(!strcmp(name
, "flip")) {
204 i
->flip
= atoi(value
);
207 printf("videoreader_setparameter(%s, %s)\n", name
, value
);fflush(stdout
);
211 int videoreader_avifile_open(videoreader_t
* v
, char* filename
)
213 videoreader_avifile_internal
* i
;
214 i
= (videoreader_avifile_internal
*)malloc(sizeof(videoreader_avifile_internal
));
215 memset(i
, 0, sizeof(videoreader_avifile_internal
));
216 memset(v
, 0, sizeof(videoreader_t
));
217 v
->getsamples
= videoreader_avifile_getsamples
;
218 v
->close
= videoreader_avifile_close
;
219 v
->eof
= videoreader_avifile_eof
;
220 v
->getimage
= videoreader_avifile_getimage
;
221 v
->getsamples
= videoreader_avifile_getsamples
;
222 v
->setparameter
= videoreader_avifile_setparameter
;
229 i
->player
= CreateIAviReadFile(filename
);
231 printf("%d streams (%d video, %d audio)\n",
232 i
->player
->StreamCount(),
233 i
->player
->VideoStreamCount(),
234 i
->player
->AudioStreamCount());
236 i
->astream
= i
->player
->GetStream(0, AviStream::Audio
);
237 i
->vstream
= i
->player
->GetStream(0, AviStream::Video
);
239 printf("Couldn't open video stream\n");
243 printf("Couldn't open video stream\n");
248 printf(stderr
, "MP3 support has been disabled at compile time, not converting soundtrack");
253 if(!i
->do_video
&& !i
->do_audio
) {
254 printf("File has neither audio nor video streams.(?)\n");
260 int dwMicroSecPerFrame
= 0;
261 player
->GetFileHeader(&head
);
262 printf("fps: %d\n", 1000000/head
.dwMicroSecPerFrame
);
263 printf("frames: %d\n", head
.dwTotalFrames
);
264 printf("streams: %d\n", head
.dwStreams
);
265 printf("width: %d\n", head
.dwWidth
);
266 printf("height: %d\n", head
.dwHeight
);
267 printf("sound: %u samples (%f seconds)\n", i
->astream
->GetEndPos(), i
->astream
->GetEndTime());
268 v
->width
= head
.dwWidth
;
269 v
->height
= head
.dwHeight
;
270 dwMicroSecPerFrame
= head
.dwMicroSecPerFrame
;
271 samplesperframe
= astream
->GetEndPos()/astream
->GetEndTime()*head
.dwMicroSecPerFrame
/1000000;
272 v
->rate
= (int)(astream
->GetEndPos()/astream
->GetEndTime());
273 v
->fps
= 1000000.0/dwMicroSecPerFrame
;
278 StreamInfo
*videoinfo
;
279 videoinfo
= i
->vstream
->GetStreamInfo();
280 v
->width
= videoinfo
->GetVideoWidth();
281 v
->height
= videoinfo
->GetVideoHeight();
282 v
->fps
= (double)(videoinfo
->GetFps());
287 StreamInfo
*audioinfo
;
289 i
->astream
->GetAudioFormatInfo(&wave
,0);
290 audioinfo
= i
->astream
->GetStreamInfo();
292 v
->channels
= wave
.nChannels
;
293 v
->rate
= wave
.nSamplesPerSec
;
294 i
->soundbits
= wave
.wBitsPerSample
;
296 if(v
->channels
==0 || v
->rate
==0 || i
->soundbits
==0 || wave
.wFormatTag
!=1) {
297 v
->rate
= audioinfo
->GetAudioSamplesPerSec();
298 v
->channels
= audioinfo
->GetAudioChannels();
299 i
->soundbits
= audioinfo
->GetAudioBitsPerSample();
303 printf("formatinfo: format %d, %d channels, %d bits/sample, rate %d, blockalign %d\n", wave
.wFormatTag
, wave
.nChannels
, wave
.wBitsPerSample
, wave
.nSamplesPerSec
, wave
.nBlockAlign
);
304 printf("audioinfo: %d channels, %d bits/sample, rate %d\n", audioinfo
->GetAudioChannels(), audioinfo
->GetAudioBitsPerSample(), audioinfo
->GetAudioSamplesPerSec());
306 if(i
->soundbits
!= 8 && i
->soundbits
!= 16) {
307 printf("Can't handle %d bit audio, disabling sound\n", wave
.wBitsPerSample
);
315 i
->vstream
-> StartStreaming();
317 i
->astream
-> StartStreaming();
318 ringbuffer_init(&i
->audio_buffer
);
321 i
->astream
-> GetOutputFormat(&wave
, sizeof(wave
));
322 printf("formatinfo: format %d, %d channels, %d bits/sample, rate %d, blockalign %d\n", wave
.wFormatTag
, wave
.nChannels
, wave
.wBitsPerSample
, wave
.nSamplesPerSec
, wave
.nBlockAlign
);