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"
26 #include "videoreader.h"
35 #ifdef HAVE_AVIFILE_VERSION_H
36 #include <avifile/version.h>
39 #if (AVIFILE_MAJOR_VERSION == 0) && (AVIFILE_MINOR_VERSION>=6)
42 #include <avm_fourcc.h>
43 #include <avm_creators.h>
44 #include <StreamInfo.h>
66 static int verbose
= 0;
68 typedef struct _videoreader_avifile_internal
71 IAviReadStream
* astream
;
72 IAviReadStream
* vstream
;
80 ringbuffer_t audio_buffer
;
81 } videoreader_avifile_internal
;
83 static int readSamples(videoreader_avifile_internal
*i
, void*buffer
, int buffer_size
, int numsamples
)
86 while(i
->audio_buffer
.available
< buffer_size
) {
87 unsigned int samples_read
= 0, bytes_read
= 0;
88 ret
= i
->astream
->ReadFrames(buffer
, buffer_size
, numsamples
, samples_read
, bytes_read
);
91 printf("ReadFrames() returns %d\n", ret
);fflush(stdout
);
95 int l
= i
->audio_buffer
.available
;
96 ringbuffer_read(&i
->audio_buffer
, buffer
, l
);
99 ringbuffer_put(&i
->audio_buffer
, buffer
, bytes_read
);
101 ringbuffer_read(&i
->audio_buffer
, buffer
, buffer_size
);
104 static int videoreader_avifile_getsamples(videoreader_t
* v
, void*buffer
, int num
)
106 videoreader_avifile_internal
*i
= (videoreader_avifile_internal
*)v
->internal
;
108 printf("videoreader_getsamples(%d)\n", num
);fflush(stdout
);
112 if(i
->soundbits
== 8) {
113 int num_read
= readSamples(i
, buffer
, num
/2, num
/(v
->channels
*2))*2;
114 unsigned char*b
= (unsigned char*)buffer
;
116 for(t
=num_read
-2;t
>=0;t
-=2) {
117 unsigned char x
= b
[t
/2];
123 printf("end of audio\n");fflush(stdout
);
129 if(i
->soundbits
== 16) {
130 int num_read
= readSamples(i
, buffer
, num
, num
/(v
->channels
*2));
133 printf("end of audio\n");fflush(stdout
);
141 static int videoreader_avifile_getimage(videoreader_t
* v
, void*buffer
)
143 videoreader_avifile_internal
*i
= (videoreader_avifile_internal
*)v
->internal
;
145 printf("videoreader_getimage()\n");fflush(stdout
);
151 if(i
->vstream
->ReadFrame() < 0) {
152 if(verbose
) printf("vstream->ReadFrame() returned value < 0, shutting down...\n");
157 CImage
*img
= i
->vstream
->GetFrame();
159 if(verbose
) printf("vstream->GetFrame() returned NULL, shutting down...\n");
163 /* we convert the image to YUV first, because we can convert to RGB from YUV only */
166 if(img
->Bpp() != 3) {
167 if(verbose
) printf("Warning: converthing from bpp %d to bpp 3, this fails on older avifile versions...\n", img
->Bpp());
168 BitmapInfo
tmp(v
->width
, v
->height
, 24);
169 img2
= new CImage(img
, &tmp
);
175 unsigned char*data
= img
->Data();
176 int bpp
= img
->Bpp();
179 for(y
=0;y
<v
->height
;y
++) {
180 unsigned char*from
,*to
;
181 to
= &((unsigned char*)buffer
)[y
*v
->width
*4];
183 from
= img
->At(v
->height
-y
-1);
186 for(x
=0;x
<v
->width
;x
++) {
188 to
[x
*4+1] = from
[x
*3+2];
189 to
[x
*4+2] = from
[x
*3+1];
190 to
[x
*4+3] = from
[x
*3+0];
193 if(img2
) delete img2
;
194 return v
->width
*v
->height
*4;
196 if(img2
) delete img2
;
197 if(verbose
) printf("Can't handle bpp %d, shutting down...\n", bpp
);
202 static void videoreader_avifile_close(videoreader_t
* v
)
204 videoreader_avifile_internal
*i
= (videoreader_avifile_internal
*)v
->internal
;
206 printf("videoreader_close()\n");fflush(stdout
);
209 ringbuffer_clear(&i
->audio_buffer
);
212 static void videoreader_avifile_setparameter(videoreader_t
*v
, char*name
, char*value
)
214 videoreader_avifile_internal
*i
= (videoreader_avifile_internal
*)v
->internal
;
215 if(!strcmp(name
, "verbose")) {
216 verbose
= atoi(value
);
218 if(!strcmp(name
, "flip")) {
219 i
->flip
= atoi(value
);
222 printf("videoreader_setparameter(%s, %s)\n", name
, value
);fflush(stdout
);
226 int videoreader_avifile_open(videoreader_t
* v
, char* filename
)
232 videoreader_avifile_internal
* i
;
233 i
= (videoreader_avifile_internal
*)malloc(sizeof(videoreader_avifile_internal
));
234 memset(i
, 0, sizeof(videoreader_avifile_internal
));
235 memset(v
, 0, sizeof(videoreader_t
));
236 v
->getsamples
= videoreader_avifile_getsamples
;
237 v
->close
= videoreader_avifile_close
;
238 v
->getimage
= videoreader_avifile_getimage
;
239 v
->getsamples
= videoreader_avifile_getsamples
;
240 v
->setparameter
= videoreader_avifile_setparameter
;
247 i
->player
= CreateIAviReadFile(filename
);
249 printf("%d streams (%d video, %d audio)\n",
250 i
->player
->StreamCount(),
251 i
->player
->VideoStreamCount(),
252 i
->player
->AudioStreamCount());
254 i
->astream
= i
->player
->GetStream(0, AviStream::Audio
);
255 i
->vstream
= i
->player
->GetStream(0, AviStream::Video
);
257 printf("Couldn't open video stream\n");
261 printf("Couldn't open video stream\n");
266 printf(stderr
, "MP3 support has been disabled at compile time, not converting soundtrack");
271 if(!i
->do_video
&& !i
->do_audio
) {
272 printf("File has neither audio nor video streams.(?)\n");
278 int dwMicroSecPerFrame
= 0;
279 player
->GetFileHeader(&head
);
280 printf("fps: %d\n", 1000000/head
.dwMicroSecPerFrame
);
281 printf("frames: %d\n", head
.dwTotalFrames
);
282 printf("streams: %d\n", head
.dwStreams
);
283 printf("width: %d\n", abs(head
.dwWidth
));
284 printf("height: %d\n", abs(head
.dwHeight
));
285 printf("sound: %u samples (%f seconds)\n", i
->astream
->GetEndPos(), i
->astream
->GetEndTime());
286 v
->width
= abs(head
.dwWidth
);
287 v
->height
= abs(head
.dwHeight
);
288 dwMicroSecPerFrame
= head
.dwMicroSecPerFrame
;
289 samplesperframe
= astream
->GetEndPos()/astream
->GetEndTime()*head
.dwMicroSecPerFrame
/1000000;
290 v
->samplerate
= (int)(astream
->GetEndPos()/astream
->GetEndTime());
291 v
->fps
= 1000000.0/dwMicroSecPerFrame
;
296 StreamInfo
*videoinfo
;
297 videoinfo
= i
->vstream
->GetStreamInfo();
298 v
->width
= abs(videoinfo
->GetVideoWidth());
299 v
->height
= abs(videoinfo
->GetVideoHeight());
300 v
->fps
= (double)(videoinfo
->GetFps());
305 StreamInfo
*audioinfo
;
307 i
->astream
->GetAudioFormatInfo(&wave
,0);
308 audioinfo
= i
->astream
->GetStreamInfo();
310 v
->channels
= wave
.nChannels
;
311 v
->samplerate
= wave
.nSamplesPerSec
;
312 i
->soundbits
= wave
.wBitsPerSample
;
314 if(v
->channels
==0 || v
->samplerate
==0 || i
->soundbits
==0 || wave
.wFormatTag
!=1) {
315 v
->samplerate
= audioinfo
->GetAudioSamplesPerSec();
316 v
->channels
= audioinfo
->GetAudioChannels();
317 i
->soundbits
= audioinfo
->GetAudioBitsPerSample();
321 printf("formatinfo: format %d, %d channels, %d bits/sample, rate %d, blockalign %d\n", wave
.wFormatTag
, wave
.nChannels
, wave
.wBitsPerSample
, wave
.nSamplesPerSec
, wave
.nBlockAlign
);
322 printf("audioinfo: %d channels, %d bits/sample, rate %d\n", audioinfo
->GetAudioChannels(), audioinfo
->GetAudioBitsPerSample(), audioinfo
->GetAudioSamplesPerSec());
324 if(i
->soundbits
!= 8 && i
->soundbits
!= 16) {
325 printf("Can't handle %d bit audio, disabling sound\n", wave
.wBitsPerSample
);
333 i
->vstream
-> StartStreaming();
335 i
->astream
-> StartStreaming();
336 ringbuffer_init(&i
->audio_buffer
);
339 i
->astream
-> GetOutputFormat(&wave
, sizeof(wave
));
340 printf("formatinfo: format %d, %d channels, %d bits/sample, rate %d, blockalign %d\n", wave
.wFormatTag
, wave
.nChannels
, wave
.wBitsPerSample
, wave
.nSamplesPerSec
, wave
.nBlockAlign
);
349 int videoreader_avifile_open(videoreader_t
* v
, char* filename
)
354 #endif //HAVE_AVIFILE