Skip to content
This repository was archived by the owner on May 19, 2022. It is now read-only.

Commit 73a8381

Browse files
author
Haeleth
committed
ponscr: original onscripter-insani source
1 parent 45f5866 commit 73a8381

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+32909
-0
lines changed

AVIWrapper.cpp

Lines changed: 364 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,364 @@
1+
/* -*- C++ -*-
2+
*
3+
* AVIWrapper.cpp - avifile library wrapper class to play AVI video & audio stream
4+
*
5+
* Copyright (c) 2001-2006 Ogapee. All rights reserved.
6+
*
7+
8+
*
9+
* This program is free software; you can redistribute it and/or modify
10+
* it under the terms of the GNU General Public License as published by
11+
* the Free Software Foundation; either version 2 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU General Public License
20+
* along with this program; if not, write to the Free Software
21+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22+
*/
23+
24+
#include "AVIWrapper.h"
25+
#include <SDL_mixer.h>
26+
#include <audiodecoder.h>
27+
#include <avm_cpuinfo.h>
28+
#include <avm_output.h>
29+
#include <stdlib.h>
30+
#include <string.h>
31+
32+
#define DEFAULT_AUDIOBUF 4096
33+
#define AVI_FINISH_EVENT 12345
34+
35+
AVIWrapper::AVIWrapper()
36+
{
37+
screen_overlay = NULL;
38+
i_avi = NULL;
39+
v_stream = NULL;
40+
a_stream = NULL;
41+
remaining_buffer = new char[DEFAULT_AUDIOBUF*4];
42+
remaining_count = 0;
43+
}
44+
45+
AVIWrapper::~AVIWrapper()
46+
{
47+
if ( v_stream )
48+
v_stream->StopStreaming();
49+
if ( a_stream )
50+
a_stream->StopStreaming();
51+
if ( i_avi ) delete i_avi;
52+
if ( screen_overlay ) SDL_FreeYUVOverlay( screen_overlay );
53+
if ( remaining_buffer ) delete[] remaining_buffer;
54+
}
55+
56+
int AVIWrapper::init( char *filename, bool debug_flag )
57+
{
58+
this->debug_flag = debug_flag;
59+
if ( !debug_flag ) avm::out.resetDebugLevels(-1);
60+
61+
i_avi = CreateIAviReadFile( filename );
62+
if ( i_avi == NULL || i_avi->IsValid() == false ){
63+
fprintf( stderr, "can't CreateIAviReadFile from %s\n", filename );
64+
return -1;
65+
}
66+
67+
v_stream = i_avi->GetStream(0, AviStream::Video );
68+
if ( v_stream == NULL ){
69+
fprintf( stderr, "Video Stream is NULL\n" );
70+
return -1;
71+
}
72+
73+
width = v_stream->GetStreamInfo()->GetVideoWidth();
74+
height = v_stream->GetStreamInfo()->GetVideoHeight();
75+
if ( debug_flag ) fprintf( stderr, "width %d height %d\n", width, height );
76+
77+
return 0;
78+
}
79+
80+
int AVIWrapper::initAV( SDL_Surface *surface, bool audio_open_flag )
81+
{
82+
screen_rect.x = screen_rect.y = 0;
83+
screen_rect.w = surface->w;
84+
screen_rect.h = surface->h;
85+
86+
v_stream->StartStreaming();
87+
if ( v_stream->GetVideoDecoder() == NULL ){
88+
if ( debug_flag ) fprintf( stderr, "GetVideoDecoder() return 0.\n" );
89+
return -1;
90+
}
91+
IVideoDecoder::CAPS cap = v_stream->GetVideoDecoder()->GetCapabilities();
92+
if ( debug_flag ) printf("cap %x\n", cap );
93+
94+
if ( cap & IVideoDecoder::CAP_YV12 ){
95+
v_stream->GetVideoDecoder()->SetDestFmt( 0, fccYV12 );
96+
screen_overlay = SDL_CreateYUVOverlay( width, height, SDL_YV12_OVERLAY, surface );
97+
}
98+
else if ( cap & IVideoDecoder::CAP_YUY2 ){
99+
v_stream->GetVideoDecoder()->SetDestFmt( 0, fccYUY2 );
100+
screen_overlay = SDL_CreateYUVOverlay( width, height, SDL_YUY2_OVERLAY, surface );
101+
}
102+
else{
103+
screen_overlay = SDL_CreateYUVOverlay( width, height, SDL_YV12_OVERLAY, surface );
104+
}
105+
106+
if ( !audio_open_flag ) return 0;
107+
a_stream = i_avi->GetStream(0, AviStream::Audio);
108+
if ( a_stream == NULL ){
109+
if ( debug_flag ) fprintf( stderr, "Audio Stream is NULL\n" );
110+
return 0;
111+
}
112+
113+
a_stream->StartStreaming();
114+
WAVEFORMATEX wave_fmt;
115+
a_stream->GetAudioDecoder()->GetOutputFormat( &wave_fmt );
116+
if ( debug_flag ) printf(" format %d ch %d sample %d bit %d avg Bps %d\n", wave_fmt.wFormatTag, wave_fmt.nChannels, wave_fmt.nSamplesPerSec, wave_fmt.wBitsPerSample, wave_fmt.nAvgBytesPerSec );
117+
118+
if ( Mix_OpenAudio( wave_fmt.nSamplesPerSec, MIX_DEFAULT_FORMAT, wave_fmt.nChannels, DEFAULT_AUDIOBUF ) < 0 ){
119+
fprintf( stderr, "can't open audio device\n" );
120+
a_stream->StopStreaming();
121+
delete a_stream;
122+
a_stream = NULL;
123+
}
124+
125+
return 0;
126+
}
127+
128+
static void audioCallback( void *userdata, Uint8 *stream, int len )
129+
{
130+
AVIWrapper &avi = *(AVIWrapper*)userdata;
131+
avi.audioCallback( userdata, stream, len );
132+
}
133+
134+
void AVIWrapper::audioCallback( void *userdata, Uint8 *stream, int len )
135+
{
136+
if ( len == 0 )
137+
status = AVI_STOP;
138+
139+
uint_t ocnt;
140+
uint_t samples;
141+
uint_t count = 0;
142+
143+
if ( remaining_count > 0 ){
144+
if ( remaining_count <= len ){
145+
memcpy( stream, remaining_buffer, remaining_count );
146+
count = remaining_count;
147+
len -= remaining_count;
148+
remaining_count = 0;
149+
}
150+
else{
151+
memmove( stream, remaining_buffer, len );
152+
count = len;
153+
len = 0;
154+
remaining_count -= len;
155+
return;
156+
}
157+
}
158+
159+
while ( len > 0 && !a_stream->Eof() ){
160+
a_stream->ReadFrames( remaining_buffer, len, len, samples, ocnt );
161+
if ( ocnt <= len ){
162+
memcpy( stream+count, remaining_buffer, ocnt );
163+
len -= ocnt;
164+
}
165+
else{
166+
memcpy( stream+count, remaining_buffer, len );
167+
if ( ocnt-len < DEFAULT_AUDIOBUF*4 - len ){
168+
memmove( remaining_buffer, remaining_buffer+len, ocnt-len );
169+
remaining_count = ocnt-len;
170+
}
171+
else{
172+
remaining_count = 0;
173+
}
174+
len = 0;
175+
}
176+
count += ocnt;
177+
}
178+
}
179+
180+
double AVIWrapper::getAudioTime()
181+
{
182+
if ( time_start == 0 )
183+
{
184+
frame_start = (v_stream) ? v_stream->GetTime() : 0.;
185+
time_start = longcount();
186+
}
187+
188+
if ( a_stream )
189+
return a_stream->GetTime();
190+
else
191+
return frame_start + to_float(longcount(), time_start);
192+
}
193+
194+
static int playVideo( void *userdata )
195+
{
196+
AVIWrapper &avi = *(AVIWrapper*)userdata;
197+
return avi.playVideo( userdata );
198+
}
199+
200+
#define NUM_CACHES 3
201+
int AVIWrapper::playVideo( void *userdata )
202+
{
203+
int i;
204+
205+
struct{
206+
bool valid;
207+
CImage *image;
208+
double time;
209+
} cache[NUM_CACHES];
210+
for ( i=0 ; i<NUM_CACHES ; i++ ){
211+
cache[i].valid = false;
212+
}
213+
int remaining_cache = NUM_CACHES;
214+
215+
while ( status == AVI_PLAYING && !v_stream->Eof() ){
216+
CImage *image = v_stream->GetFrame( true );
217+
if ( image == NULL ) break;
218+
219+
double current_time = v_stream->GetTime();
220+
double minimum_time = current_time;
221+
222+
// look for the nearest in the cache
223+
int nearest_cache=-1;
224+
for ( i=0 ; i<NUM_CACHES ; i++ ){
225+
if ( cache[i].valid ){
226+
if ( nearest_cache == -1 ||
227+
nearest_cache >= 0 &&
228+
cache[i].time < cache[nearest_cache].time ){
229+
nearest_cache = i;
230+
if ( minimum_time > cache[nearest_cache].time )
231+
minimum_time = cache[nearest_cache].time;
232+
}
233+
}
234+
}
235+
236+
double async = getAudioTime() - minimum_time;
237+
//printf("audio %f (%f - %f) minimum %d %f cur %f\n", async, getAudioTime(), minimum_time, nearest_cache, minimum_time, current_time );
238+
if ( async < -0.01 ){
239+
if ( remaining_cache == 0 ){
240+
//printf("sync0 %f %f %f %f\n", async, (a_stream)?a_stream->GetTime():0.0, v_stream->GetTime(), minimum_time );
241+
SDL_Delay( (int)(-async*1000) );
242+
}
243+
}
244+
if ( async < -0.01 && remaining_cache > 0 ||
245+
nearest_cache >= 0 ){
246+
// add cache
247+
for ( i=0 ; i<NUM_CACHES ; i++ ){
248+
if ( cache[i].valid == false ){
249+
cache[i].valid = true;
250+
cache[i].image = new CImage(image);
251+
cache[i].time = current_time;
252+
remaining_cache--;
253+
break;
254+
}
255+
}
256+
if ( async < -0.01 ){
257+
image->Release();
258+
continue;
259+
}
260+
}
261+
262+
if ( nearest_cache >= 0 && minimum_time == cache[nearest_cache].time ){
263+
//printf("draw cache %d %f\n", nearest_cache, cache[nearest_cache].time );
264+
//if ( async <= 0.033 ) // drop frame if necessary
265+
drawFrame( cache[nearest_cache].image );
266+
cache[nearest_cache].image->Release();
267+
cache[nearest_cache].valid = false;
268+
remaining_cache++;
269+
}
270+
else{
271+
//printf("draw real %f\n", current_time );
272+
//if ( async <= 0.033 ) // drop frame if necessary
273+
drawFrame( image );
274+
}
275+
image->Release();
276+
}
277+
status = AVI_STOP;
278+
279+
for ( i=0 ; i<NUM_CACHES ; i++ )
280+
if ( cache[i].valid ) cache[i].image->Release();
281+
282+
return 0;
283+
}
284+
285+
int AVIWrapper::play( bool click_flag )
286+
{
287+
int ret = 0;
288+
time_start = 0;
289+
status = AVI_PLAYING;
290+
if ( v_stream )
291+
thread_id = SDL_CreateThread( ::playVideo, this );
292+
if ( a_stream )
293+
Mix_HookMusic( ::audioCallback, this );
294+
295+
bool done_flag = false;
296+
while( !(done_flag & click_flag) && status == AVI_PLAYING ){
297+
SDL_Event event;
298+
299+
while( SDL_PollEvent( &event ) ){
300+
switch (event.type){
301+
case SDL_KEYDOWN:
302+
if ( ((SDL_KeyboardEvent *)&event)->keysym.sym == SDLK_RETURN ||
303+
((SDL_KeyboardEvent *)&event)->keysym.sym == SDLK_KP_ENTER ||
304+
((SDL_KeyboardEvent *)&event)->keysym.sym == SDLK_SPACE ||
305+
((SDL_KeyboardEvent *)&event)->keysym.sym == SDLK_ESCAPE )
306+
done_flag = true;
307+
break;
308+
case SDL_QUIT:
309+
ret = 1;
310+
case SDL_MOUSEBUTTONDOWN:
311+
done_flag = true;
312+
break;
313+
default:
314+
break;
315+
}
316+
}
317+
SDL_Delay( 10 );
318+
}
319+
320+
status = AVI_STOP;
321+
if ( v_stream )
322+
SDL_WaitThread( thread_id, NULL );
323+
if ( a_stream )
324+
Mix_HookMusic( NULL, NULL );
325+
326+
return ret;
327+
}
328+
329+
int AVIWrapper::drawFrame( CImage *image )
330+
{
331+
if ( image == NULL ) return -1;
332+
333+
unsigned int i, j;
334+
uint32_t comp = image->GetFmt()->biCompression;
335+
336+
unsigned char *buf = image->Data();
337+
SDL_LockYUVOverlay( screen_overlay );
338+
Uint8 *dst_y = screen_overlay->pixels[0];
339+
Uint8 *dst_u = screen_overlay->pixels[1];
340+
Uint8 *dst_v = screen_overlay->pixels[2];
341+
342+
if ( comp == 0 ){ // BGR
343+
image->ToYUV();
344+
for ( i=0 ; i<width*height ; i++ )
345+
*dst_y++ = buf[i*3];
346+
347+
for ( i=0 ; i<height/2 ; i++ ){
348+
for ( j=0 ; j<width/2 ; j++ ){
349+
*dst_v++ = buf[(i*width*2+j*2)*3+1];
350+
*dst_u++ = buf[(i*width*2+j*2)*3+2];
351+
}
352+
}
353+
}
354+
else if ( comp == IMG_FMT_YUY2 ){
355+
memcpy( dst_y, buf, width*height*2 );
356+
}
357+
else if ( comp == IMG_FMT_YV12 ){
358+
memcpy( dst_y, buf, width*height+width*height/2 );
359+
}
360+
SDL_UnlockYUVOverlay( screen_overlay );
361+
SDL_DisplayYUVOverlay( screen_overlay, &screen_rect );
362+
363+
return 0;
364+
}

0 commit comments

Comments
 (0)