splayer.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108
  1. /********************************************************************
  2. * *
  3. * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
  4. * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
  5. * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  6. * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
  7. * *
  8. * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
  9. * by the Xiph.Org Foundation http://www.xiph.org/ *
  10. * *
  11. ********************************************************************
  12. function: example SDL player application; plays Ogg Theora files (with
  13. optional Vorbis audio second stream)
  14. * Modified by M. Piacentini http://www.tabuleiro.com
  15. * from the original Theora Alpha player_sample files
  16. *
  17. * Modified to build on Windows and use PortAudio as the audio
  18. * and synchronization layer, calculating license.
  19. *
  20. * With SDL PortAudio it should be easy to compile on other platforms and
  21. * sound providers like DirectSound
  22. * just include the corresponding .c file (see PortAudio main documentation
  23. * for additional information)
  24. ********************************************************************/
  25. #ifdef HAVE_CONFIG_H
  26. # include <config.h>
  27. #endif
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <fcntl.h>
  32. #include <math.h>
  33. #include <signal.h>
  34. #include "theora/theora.h"
  35. #include "vorbis/codec.h"
  36. #ifdef WIN32
  37. #include <windows.h>
  38. #include <io.h>
  39. #endif
  40. #include <portaudio.h>
  41. #include <SDL.h>
  42. /* for portaudio */
  43. #define FRAMES_PER_BUFFER (256)
  44. /*start of portaudio helper functions, extracted from pablio directory*/
  45. /* Pa_streamio routines modified by mauricio at xiph.org
  46. * Modified version of Portable Audio Blocking read/write utility.
  47. * from the original PABLIO files
  48. * Modified to support only playback buffers, direct access
  49. * to the underlying stream time and remove blocking operations*/
  50. /* PortAudio copyright notice follows */
  51. /*
  52. * Author: Phil Burk, http://www.softsynth.com
  53. *
  54. * This program uses the PortAudio Portable Audio Library.
  55. * For more information see: http://www.audiomulch.com/portaudio/
  56. * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
  57. *
  58. * Permission is hereby granted, free of charge, to any person obtaining
  59. * a copy of this software and associated documentation files
  60. * (the "Software"), to deal in the Software without restriction,
  61. * including without limitation the rights to use, copy, modify, merge,
  62. * publish, distribute, sublicense, and/or sell copies of the Software,
  63. * and to permit persons to whom the Software is furnished to do so,
  64. * subject to the following conditions:
  65. *
  66. * The above copyright notice and this permission notice shall be
  67. * included in all copies or substantial portions of the Software.
  68. *
  69. */
  70. typedef struct
  71. {
  72. long bufferSize; /* Number of bytes in FIFO. Power of 2. Set by RingBuffer_Init. */
  73. /* These are declared volatile because they are written by a different thread than the reader. */
  74. volatile long writeIndex; /* Index of next writable byte. Set by RingBuffer_AdvanceWriteIndex. */
  75. volatile long readIndex; /* Index of next readable byte. Set by RingBuffer_AdvanceReadIndex. */
  76. long bigMask; /* Used for wrapping indices with extra bit to distinguish full/empty. */
  77. long smallMask; /* Used for fitting indices to buffer. */
  78. char *buffer;
  79. }
  80. RingBuffer;
  81. typedef struct
  82. {
  83. RingBuffer outFIFO;
  84. PortAudioStream *stream;
  85. int bytesPerFrame;
  86. int samplesPerFrame;
  87. }
  88. PASTREAMIO_Stream;
  89. /* Values for flags for OpenAudioStream(). */
  90. /* Keep PABLIO ones*/
  91. #define PASTREAMIO_READ (1<<0)
  92. #define PASTREAMIO_WRITE (1<<1)
  93. #define PASTREAMIO_READ_WRITE (PABLIO_READ|PABLIO_WRITE)
  94. #define PASTREAMIO_MONO (1<<2)
  95. #define PASTREAMIO_STEREO (1<<3)
  96. /***************************************************************************
  97. ** Helper function added to report stream time. */
  98. PaTimestamp GetAudioStreamTime( PASTREAMIO_Stream *aStream ){
  99. return Pa_StreamTime( aStream->stream ) ;
  100. }
  101. /***************************************************************************
  102. ** Clear buffer. Should only be called when buffer is NOT being read. */
  103. void RingBuffer_Flush( RingBuffer *rbuf )
  104. {
  105. rbuf->writeIndex = rbuf->readIndex = 0;
  106. }
  107. /***************************************************************************
  108. * Initialize FIFO.
  109. * numBytes must be power of 2, returns -1 if not.
  110. */
  111. long RingBuffer_Init( RingBuffer *rbuf, long numBytes, void *dataPtr )
  112. {
  113. if( ((numBytes-1) & numBytes) != 0) return -1; /* Not Power of two. */
  114. rbuf->bufferSize = numBytes;
  115. rbuf->buffer = (char *)dataPtr;
  116. RingBuffer_Flush( rbuf );
  117. rbuf->bigMask = (numBytes*2)-1;
  118. rbuf->smallMask = (numBytes)-1;
  119. return 0;
  120. }
  121. /***************************************************************************
  122. ** Return number of bytes available for reading. */
  123. long RingBuffer_GetReadAvailable( RingBuffer *rbuf )
  124. {
  125. return ( (rbuf->writeIndex - rbuf->readIndex) & rbuf->bigMask );
  126. }
  127. /***************************************************************************
  128. ** Return number of bytes available for writing. */
  129. long RingBuffer_GetWriteAvailable( RingBuffer *rbuf )
  130. {
  131. return ( rbuf->bufferSize - RingBuffer_GetReadAvailable(rbuf));
  132. }
  133. /***************************************************************************
  134. ** Get address of region(s) to which we can write data.
  135. ** If the region is contiguous, size2 will be zero.
  136. ** If non-contiguous, size2 will be the size of second region.
  137. ** Returns room available to be written or numBytes, whichever is smaller.
  138. */
  139. long RingBuffer_GetWriteRegions( RingBuffer *rbuf, long numBytes,
  140. void **dataPtr1, long *sizePtr1,
  141. void **dataPtr2, long *sizePtr2 )
  142. {
  143. long index;
  144. long available = RingBuffer_GetWriteAvailable( rbuf );
  145. if( numBytes > available ) numBytes = available;
  146. /* Check to see if write is not contiguous. */
  147. index = rbuf->writeIndex & rbuf->smallMask;
  148. if( (index + numBytes) > rbuf->bufferSize )
  149. {
  150. /* Write data in two blocks that wrap the buffer. */
  151. long firstHalf = rbuf->bufferSize - index;
  152. *dataPtr1 = &rbuf->buffer[index];
  153. *sizePtr1 = firstHalf;
  154. *dataPtr2 = &rbuf->buffer[0];
  155. *sizePtr2 = numBytes - firstHalf;
  156. }
  157. else
  158. {
  159. *dataPtr1 = &rbuf->buffer[index];
  160. *sizePtr1 = numBytes;
  161. *dataPtr2 = NULL;
  162. *sizePtr2 = 0;
  163. }
  164. return numBytes;
  165. }
  166. /***************************************************************************
  167. */
  168. long RingBuffer_AdvanceWriteIndex( RingBuffer *rbuf, long numBytes )
  169. {
  170. return rbuf->writeIndex = (rbuf->writeIndex + numBytes) & rbuf->bigMask;
  171. }
  172. /***************************************************************************
  173. ** Get address of region(s) from which we can read data.
  174. ** If the region is contiguous, size2 will be zero.
  175. ** If non-contiguous, size2 will be the size of second region.
  176. ** Returns room available to be written or numBytes, whichever is smaller.
  177. */
  178. long RingBuffer_GetReadRegions( RingBuffer *rbuf, long numBytes,
  179. void **dataPtr1, long *sizePtr1,
  180. void **dataPtr2, long *sizePtr2 )
  181. {
  182. long index;
  183. long available = RingBuffer_GetReadAvailable( rbuf );
  184. if( numBytes > available ) numBytes = available;
  185. /* Check to see if read is not contiguous. */
  186. index = rbuf->readIndex & rbuf->smallMask;
  187. if( (index + numBytes) > rbuf->bufferSize )
  188. {
  189. /* Write data in two blocks that wrap the buffer. */
  190. long firstHalf = rbuf->bufferSize - index;
  191. *dataPtr1 = &rbuf->buffer[index];
  192. *sizePtr1 = firstHalf;
  193. *dataPtr2 = &rbuf->buffer[0];
  194. *sizePtr2 = numBytes - firstHalf;
  195. }
  196. else
  197. {
  198. *dataPtr1 = &rbuf->buffer[index];
  199. *sizePtr1 = numBytes;
  200. *dataPtr2 = NULL;
  201. *sizePtr2 = 0;
  202. }
  203. return numBytes;
  204. }
  205. /***************************************************************************
  206. */
  207. long RingBuffer_AdvanceReadIndex( RingBuffer *rbuf, long numBytes )
  208. {
  209. return rbuf->readIndex = (rbuf->readIndex + numBytes) & rbuf->bigMask;
  210. }
  211. /***************************************************************************
  212. ** Return bytes written. */
  213. long RingBuffer_Write( RingBuffer *rbuf, void *data, long numBytes )
  214. {
  215. long size1, size2, numWritten;
  216. void *data1, *data2;
  217. numWritten = RingBuffer_GetWriteRegions( rbuf, numBytes, &data1, &size1, &data2, &size2 );
  218. if( size2 > 0 )
  219. {
  220. memcpy( data1, data, size1 );
  221. data = ((char *)data) + size1;
  222. memcpy( data2, data, size2 );
  223. }
  224. else
  225. {
  226. memcpy( data1, data, size1 );
  227. }
  228. RingBuffer_AdvanceWriteIndex( rbuf, numWritten );
  229. return numWritten;
  230. }
  231. /***************************************************************************
  232. ** Return bytes read. */
  233. long RingBuffer_Read( RingBuffer *rbuf, void *data, long numBytes )
  234. {
  235. long size1, size2, numRead;
  236. void *data1, *data2;
  237. numRead = RingBuffer_GetReadRegions( rbuf, numBytes, &data1, &size1, &data2, &size2 );
  238. if( size2 > 0 )
  239. {
  240. memcpy( data, data1, size1 );
  241. data = ((char *)data) + size1;
  242. memcpy( data, data2, size2 );
  243. }
  244. else
  245. {
  246. memcpy( data, data1, size1 );
  247. }
  248. RingBuffer_AdvanceReadIndex( rbuf, numRead );
  249. return numRead;
  250. }
  251. /************************************************************************/
  252. /******** Functions *****************************************************/
  253. /************************************************************************/
  254. /* Called from PortAudio.
  255. * Read and write data only if there is room in FIFOs.
  256. */
  257. static int audioIOCallback( void *inputBuffer, void *outputBuffer,
  258. unsigned long framesPerBuffer,
  259. PaTimestamp outTime, void *userData )
  260. {
  261. PASTREAMIO_Stream *data = (PASTREAMIO_Stream*)userData;
  262. long numBytes = data->bytesPerFrame * framesPerBuffer;
  263. (void) outTime;
  264. (void) inputBuffer;
  265. if( outputBuffer != NULL )
  266. {
  267. int i;
  268. int numRead = RingBuffer_Read( &data->outFIFO, outputBuffer, numBytes );
  269. /* Zero out remainder of buffer if we run out of data. */
  270. for( i=numRead; i<numBytes; i++ )
  271. {
  272. ((char *)outputBuffer)[i] = 0;
  273. }
  274. }
  275. return 0;
  276. }
  277. /* Allocate buffer. */
  278. static PaError PASTREAMIO_InitFIFO( RingBuffer *rbuf, long numFrames, long bytesPerFrame )
  279. {
  280. long numBytes = numFrames * bytesPerFrame;
  281. char *buffer = (char *) malloc( numBytes );
  282. if( buffer == NULL ) return paInsufficientMemory;
  283. memset( buffer, 0, numBytes );
  284. return (PaError) RingBuffer_Init( rbuf, numBytes, buffer );
  285. }
  286. /* Free buffer. */
  287. static PaError PASTREAMIO_TermFIFO( RingBuffer *rbuf )
  288. {
  289. if( rbuf->buffer ) free( rbuf->buffer );
  290. rbuf->buffer = NULL;
  291. return paNoError;
  292. }
  293. /************************************************************
  294. * Write data to ring buffer.
  295. * Will not return until all the data has been written.
  296. */
  297. long WriteAudioStream( PASTREAMIO_Stream *aStream, void *data, long numFrames )
  298. {
  299. long bytesWritten;
  300. char *p = (char *) data;
  301. long numBytes = aStream->bytesPerFrame * numFrames;
  302. while( numBytes > 0)
  303. {
  304. bytesWritten = RingBuffer_Write( &aStream->outFIFO, p, numBytes );
  305. numBytes -= bytesWritten;
  306. p += bytesWritten;
  307. if( numBytes > 0) Pa_Sleep(10);
  308. }
  309. return numFrames;
  310. }
  311. /************************************************************
  312. * Return the number of frames that could be written to the stream without
  313. * having to wait.
  314. */
  315. long GetAudioStreamWriteable( PASTREAMIO_Stream *aStream )
  316. {
  317. int bytesEmpty = RingBuffer_GetWriteAvailable( &aStream->outFIFO );
  318. return bytesEmpty / aStream->bytesPerFrame;
  319. }
  320. /************************************************************/
  321. unsigned long RoundUpToNextPowerOf2( unsigned long n )
  322. {
  323. long numBits = 0;
  324. if( ((n-1) & n) == 0) return n; /* Already Power of two. */
  325. while( n > 0 )
  326. {
  327. n= n>>1;
  328. numBits++;
  329. }
  330. return (1<<numBits);
  331. }
  332. /* forward prototype */
  333. PaError CloseAudioStream( PASTREAMIO_Stream *aStream );
  334. /************************************************************
  335. * Opens a PortAudio stream with default characteristics.
  336. * Allocates PASTREAMIO_Stream structure.
  337. *
  338. * flags parameter can be an ORed combination of:
  339. * PABLIO_WRITE,
  340. * and either PABLIO_MONO or PABLIO_STEREO
  341. */
  342. PaError OpenAudioStream( PASTREAMIO_Stream **rwblPtr, double sampleRate,
  343. PaSampleFormat format, long flags )
  344. {
  345. long bytesPerSample;
  346. long doWrite = 0;
  347. PaError err;
  348. PASTREAMIO_Stream *aStream;
  349. long minNumBuffers;
  350. long numFrames;
  351. /* Allocate PASTREAMIO_Stream structure for caller. */
  352. aStream = (PASTREAMIO_Stream *) malloc( sizeof(PASTREAMIO_Stream) );
  353. if( aStream == NULL ) return paInsufficientMemory;
  354. memset( aStream, 0, sizeof(PASTREAMIO_Stream) );
  355. /* Determine size of a sample. */
  356. bytesPerSample = Pa_GetSampleSize( format );
  357. if( bytesPerSample < 0 )
  358. {
  359. err = (PaError) bytesPerSample;
  360. goto error;
  361. }
  362. aStream->samplesPerFrame = ((flags&PASTREAMIO_MONO) != 0) ? 1 : 2;
  363. aStream->bytesPerFrame = bytesPerSample * aStream->samplesPerFrame;
  364. /* Initialize PortAudio */
  365. err = Pa_Initialize();
  366. if( err != paNoError ) goto error;
  367. /* Warning: numFrames must be larger than amount of data processed per interrupt
  368. * inside PA to prevent glitches. Just to be safe, adjust size upwards.
  369. */
  370. minNumBuffers = 2 * Pa_GetMinNumBuffers( FRAMES_PER_BUFFER, sampleRate );
  371. numFrames = minNumBuffers * FRAMES_PER_BUFFER;
  372. numFrames = RoundUpToNextPowerOf2( numFrames );
  373. /* Initialize Ring Buffer */
  374. doWrite = ((flags & PASTREAMIO_WRITE) != 0);
  375. if(doWrite)
  376. {
  377. err = PASTREAMIO_InitFIFO( &aStream->outFIFO, numFrames, aStream->bytesPerFrame );
  378. if( err != paNoError ) goto error;
  379. /* Make Write FIFO appear full initially.
  380. numBytes = RingBuffer_GetWriteAvailable( &aStream->outFIFO );
  381. RingBuffer_AdvanceWriteIndex( &aStream->outFIFO, numBytes );*/
  382. }
  383. /* Open a PortAudio stream that we will use to communicate with the underlying
  384. * audio drivers. */
  385. err = Pa_OpenStream(
  386. &aStream->stream,
  387. paNoDevice,
  388. 0 ,
  389. format,
  390. NULL,
  391. Pa_GetDefaultOutputDeviceID() ,
  392. aStream->samplesPerFrame ,
  393. format,
  394. NULL,
  395. sampleRate,
  396. FRAMES_PER_BUFFER,
  397. minNumBuffers,
  398. paClipOff, /* we won't output out of range samples so don't bother clipping them */
  399. audioIOCallback,
  400. aStream );
  401. if( err != paNoError ) goto error;
  402. *rwblPtr = aStream;
  403. return paNoError;
  404. error:
  405. CloseAudioStream( aStream );
  406. *rwblPtr = NULL;
  407. return err;
  408. }
  409. PaError StartAudioStream( PASTREAMIO_Stream *aStream)
  410. {
  411. PaError err;
  412. err = Pa_StartStream( aStream->stream );
  413. if( err != paNoError ) goto error;
  414. return paNoError;
  415. error:
  416. CloseAudioStream( aStream );
  417. return err;
  418. }
  419. /************************************************************/
  420. PaError CloseAudioStream( PASTREAMIO_Stream *aStream )
  421. {
  422. PaError err;
  423. int bytesEmpty;
  424. int byteSize = aStream->outFIFO.bufferSize;
  425. /* If we are writing data, make sure we play everything written. */
  426. if( byteSize > 0 )
  427. {
  428. bytesEmpty = RingBuffer_GetWriteAvailable( &aStream->outFIFO );
  429. while( bytesEmpty < byteSize )
  430. {
  431. Pa_Sleep( 10 );
  432. bytesEmpty = RingBuffer_GetWriteAvailable( &aStream->outFIFO );
  433. }
  434. }
  435. err = Pa_StopStream( aStream->stream );
  436. if( err != paNoError ) goto error;
  437. err = Pa_CloseStream( aStream->stream );
  438. if( err != paNoError ) goto error;
  439. Pa_Terminate();
  440. error:
  441. PASTREAMIO_TermFIFO( &aStream->outFIFO );
  442. free( aStream );
  443. return err;
  444. }
  445. /* -- end of portaudio specific routines --*/
  446. /* portaudio related global types */
  447. #define PA_SAMPLE_TYPE paInt16
  448. typedef short SAMPLE;
  449. #define SAMPLE_SILENCE (0)
  450. PASTREAMIO_Stream *aOutStream; /* our modified stream buffer*/
  451. SAMPLE *samples; /*local buffer for samples*/
  452. double latency_sec = 0;
  453. /* ticks information to be used if the audio stream is not present */
  454. int currentTicks = -1;
  455. /* initial state of the audio stream */
  456. int isPlaying = 0;
  457. PaError err;
  458. /* Ogg and codec state for demux/decode */
  459. ogg_sync_state oy;
  460. ogg_page og;
  461. ogg_stream_state vo;
  462. ogg_stream_state to;
  463. theora_info ti;
  464. theora_comment tc;
  465. theora_state td;
  466. vorbis_info vi;
  467. vorbis_dsp_state vd;
  468. vorbis_block vb;
  469. vorbis_comment vc;
  470. int theora_p=0;
  471. int vorbis_p=0;
  472. int stateflag=0;
  473. FILE * infile = NULL;
  474. /* SDL Video playback structures */
  475. SDL_Surface *screen;
  476. SDL_Overlay *yuv_overlay;
  477. SDL_Rect rect;
  478. /* single frame video buffering */
  479. int videobuf_ready=0;
  480. ogg_int64_t videobuf_granulepos=-1;
  481. double videobuf_time=0;
  482. int audiobuf_ready=0;
  483. ogg_int64_t audiobuf_granulepos=0; /* time position of last sample */
  484. static int open_audio(){
  485. /* this will open one circular audio stream */
  486. /* build on top of portaudio routines */
  487. /* implementation based on file pastreamio.c */
  488. int numSamples;
  489. int numBytes;
  490. int minNumBuffers;
  491. int numFrames;
  492. minNumBuffers = 2 * Pa_GetMinNumBuffers( FRAMES_PER_BUFFER, vi.rate );
  493. numFrames = minNumBuffers * FRAMES_PER_BUFFER;
  494. numFrames = RoundUpToNextPowerOf2( numFrames );
  495. numSamples = numFrames * vi.channels;
  496. numBytes = numSamples * sizeof(SAMPLE);
  497. samples = (SAMPLE *) malloc( numBytes );
  498. /* store our latency calculation here */
  499. latency_sec = (double) numFrames / vi.rate / vi.channels;
  500. printf( "Latency: %.04f\n", latency_sec );
  501. err = OpenAudioStream( &aOutStream, vi.rate, PA_SAMPLE_TYPE,
  502. (PASTREAMIO_WRITE | PASTREAMIO_STEREO) );
  503. if( err != paNoError ) goto error;
  504. return err;
  505. error:
  506. CloseAudioStream( aOutStream );
  507. printf( "An error occured while opening the portaudio stream\n" );
  508. printf( "Error number: %d\n", err );
  509. printf( "Error message: %s\n", Pa_GetErrorText( err ) );
  510. return err;
  511. }
  512. static int start_audio(){
  513. err = StartAudioStream(aOutStream);
  514. if( err != paNoError ) goto error;
  515. return err;
  516. error:
  517. CloseAudioStream( aOutStream );
  518. printf( "An error occured while opening the portaudio stream\n" );
  519. printf( "Error number: %d\n", err );
  520. printf( "Error message: %s\n", Pa_GetErrorText( err ) );
  521. return err;
  522. }
  523. static int audio_close(void){
  524. err = CloseAudioStream( aOutStream );
  525. if( err != paNoError ) goto error;
  526. free(samples);
  527. return err;
  528. error:
  529. Pa_Terminate();
  530. printf( "An error occured while closing the portaudio stream\n" );
  531. printf( "Error number: %d\n", err );
  532. printf( "Error message: %s\n", Pa_GetErrorText( err ) );
  533. return err;
  534. }
  535. double get_time() {
  536. static Uint32 startticks = 0;
  537. double curtime;
  538. if (vorbis_p) {
  539. /* not entirely accurate with the WAVE OUT device, but good enough
  540. at this stage. Needs to be reworked to account for blank audio
  541. data written to the stream... */
  542. curtime = (double) (GetAudioStreamTime( aOutStream ) / vi.rate) - latency_sec;
  543. if (curtime<0.0) curtime = 0.0;
  544. } else {
  545. /* initialize timer variable if not set yet */
  546. if (startticks==0)
  547. startticks = SDL_GetTicks();
  548. curtime = 1.0e-3 * (double)(SDL_GetTicks() - startticks);
  549. }
  550. return curtime;
  551. }
  552. static void open_video(void){
  553. /* taken from player_sample.c test file for theora alpha */
  554. if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
  555. printf("Unable to initialize SDL: %s\n", SDL_GetError());
  556. exit(1);
  557. }
  558. screen = SDL_SetVideoMode(ti.frame_width, ti.frame_height, 0, SDL_SWSURFACE);
  559. if ( screen == NULL ) {
  560. printf("Unable to set %dx%d video mode: %s\n",
  561. ti.frame_width,ti.frame_height,SDL_GetError());
  562. exit(1);
  563. }
  564. yuv_overlay = SDL_CreateYUVOverlay(ti.frame_width, ti.frame_height,
  565. SDL_YV12_OVERLAY,
  566. screen);
  567. if ( yuv_overlay == NULL ) {
  568. printf("SDL: Couldn't create SDL_yuv_overlay: %s\n",
  569. SDL_GetError());
  570. exit(1);
  571. }
  572. rect.x = 0;
  573. rect.y = 0;
  574. rect.w = ti.frame_width;
  575. rect.h = ti.frame_height;
  576. SDL_DisplayYUVOverlay(yuv_overlay, &rect);
  577. }
  578. static void video_write(void){
  579. /* taken from player_sample.c test file for theora alpha */
  580. int i;
  581. yuv_buffer yuv;
  582. int crop_offset;
  583. theora_decode_YUVout(&td,&yuv);
  584. /* Lock SDL_yuv_overlay */
  585. if ( SDL_MUSTLOCK(screen) ) {
  586. if ( SDL_LockSurface(screen) < 0 ) return;
  587. }
  588. if (SDL_LockYUVOverlay(yuv_overlay) < 0) return;
  589. /* let's draw the data (*yuv[3]) on a SDL screen (*screen) */
  590. /* deal with border stride */
  591. /* reverse u and v for SDL */
  592. /* and crop input properly, respecting the encoded frame rect */
  593. crop_offset=ti.offset_x+yuv.y_stride*ti.offset_y;
  594. for(i=0;i<yuv_overlay->h;i++)
  595. memcpy(yuv_overlay->pixels[0]+yuv_overlay->pitches[0]*i,
  596. yuv.y+crop_offset+yuv.y_stride*i,
  597. yuv_overlay->w);
  598. crop_offset=(ti.offset_x/2)+(yuv.uv_stride)*(ti.offset_y/2);
  599. for(i=0;i<yuv_overlay->h/2;i++){
  600. memcpy(yuv_overlay->pixels[1]+yuv_overlay->pitches[1]*i,
  601. yuv.v+crop_offset+yuv.uv_stride*i,
  602. yuv_overlay->w/2);
  603. memcpy(yuv_overlay->pixels[2]+yuv_overlay->pitches[2]*i,
  604. yuv.u+crop_offset+yuv.uv_stride*i,
  605. yuv_overlay->w/2);
  606. }
  607. /* Unlock SDL_yuv_overlay */
  608. SDL_UnlockYUVOverlay(yuv_overlay);
  609. if ( SDL_MUSTLOCK(screen) ) {
  610. SDL_UnlockSurface(screen);
  611. }
  612. /* Show, baby, show! */
  613. SDL_DisplayYUVOverlay(yuv_overlay, &rect);
  614. }
  615. static void usage(void){
  616. printf("Usage: splayer <ogg_file>\n"
  617. #ifdef WIN32
  618. "\n"
  619. "or drag and drop an ogg file over the .exe\n\n"
  620. #endif
  621. );
  622. }
  623. /* dump the theora (or vorbis) comment header */
  624. static int dump_comments(theora_comment *tc){
  625. int i, len;
  626. char *value;
  627. printf("Encoded by %s\n",tc->vendor);
  628. if(tc->comments){
  629. printf("theora comment header:\n");
  630. for(i=0;i<tc->comments;i++){
  631. if(tc->user_comments[i]){
  632. len=tc->comment_lengths[i];
  633. value=malloc(len+1);
  634. memcpy(value,tc->user_comments[i],len);
  635. value[len]='\0';
  636. printf("\t%s\n", value);
  637. free(value);
  638. }
  639. }
  640. }
  641. return(0);
  642. }
  643. /* Report the encoder-specified colorspace for the video, if any.
  644. We don't actually make use of the information in this example;
  645. a real player should attempt to perform color correction for
  646. whatever display device it supports. */
  647. static void report_colorspace(theora_info *ti)
  648. {
  649. switch(ti->colorspace){
  650. case OC_CS_UNSPECIFIED:
  651. /* nothing to report */
  652. break;;
  653. case OC_CS_ITU_REC_470M:
  654. fprintf(stderr," encoder specified ITU Rec 470M color.\n");
  655. break;;
  656. case OC_CS_ITU_REC_470BG:
  657. fprintf(stderr," encoder specified ITU Rec 470BG color.\n");
  658. break;;
  659. default:
  660. fprintf(stderr,"warning: encoder specified unknown colorspace (%d).\n",
  661. ti->colorspace);
  662. break;;
  663. }
  664. }
  665. /* Helper; just grab some more compressed bitstream and sync it for
  666. page extraction */
  667. int buffer_data(ogg_sync_state *oy){
  668. char *buffer=ogg_sync_buffer(oy,4096);
  669. int bytes=fread(buffer,1,4096,infile);
  670. ogg_sync_wrote(oy,bytes);
  671. return(bytes);
  672. }
  673. /* helper: push a page into the appropriate stream */
  674. /* this can be done blindly; a stream won't accept a page
  675. that doesn't belong to it */
  676. static int queue_page(ogg_page *page){
  677. if(theora_p)ogg_stream_pagein(&to,page);
  678. if(vorbis_p)ogg_stream_pagein(&vo,page);
  679. return 0;
  680. }
  681. void parseHeaders(){
  682. /* extracted from player_sample.c test file for theora alpha */
  683. ogg_packet op;
  684. /* Parse the headers */
  685. /* Only interested in Vorbis/Theora streams */
  686. while(!stateflag){
  687. int ret=buffer_data(&oy);
  688. if(ret==0)break;
  689. while(ogg_sync_pageout(&oy,&og)>0){
  690. ogg_stream_state test;
  691. /* is this a mandated initial header? If not, stop parsing */
  692. if(!ogg_page_bos(&og)){
  693. /* don't leak the page; get it into the appropriate stream */
  694. queue_page(&og);
  695. stateflag=1;
  696. break;
  697. }
  698. ogg_stream_init(&test,ogg_page_serialno(&og));
  699. ogg_stream_pagein(&test,&og);
  700. ogg_stream_packetout(&test,&op);
  701. /* identify the codec: try theora */
  702. if(!theora_p && theora_decode_header(&ti,&tc,&op)>=0){
  703. /* it is theora */
  704. memcpy(&to,&test,sizeof(test));
  705. theora_p=1;
  706. }else if(!vorbis_p && vorbis_synthesis_headerin(&vi,&vc,&op)>=0){
  707. /* it is vorbis */
  708. memcpy(&vo,&test,sizeof(test));
  709. vorbis_p=1;
  710. }else{
  711. /* whatever it is, we don't care about it */
  712. ogg_stream_clear(&test);
  713. }
  714. }
  715. }
  716. /* we've now identified all the bitstreams. parse the secondary header packets. */
  717. while((theora_p && theora_p<3) || (vorbis_p && vorbis_p<3)){
  718. int ret;
  719. /* look for further theora headers */
  720. while(theora_p && (theora_p<3) && (ret=ogg_stream_packetout(&to,&op))){
  721. if(ret<0){
  722. printf("Error parsing Theora stream headers; corrupt stream?\n");
  723. exit(1);
  724. }
  725. if(theora_decode_header(&ti,&tc,&op)){
  726. printf("Error parsing Theora stream headers; corrupt stream?\n");
  727. exit(1);
  728. }
  729. theora_p++;
  730. if(theora_p==3)break;
  731. }
  732. /* look for more vorbis header packets */
  733. while(vorbis_p && (vorbis_p<3) && (ret=ogg_stream_packetout(&vo,&op))){
  734. if(ret<0){
  735. printf("Error parsing Vorbis stream headers; corrupt stream?\n");
  736. exit(1);
  737. }
  738. if(vorbis_synthesis_headerin(&vi,&vc,&op)){
  739. printf("Error parsing Vorbis stream headers; corrupt stream?\n");
  740. exit(1);
  741. }
  742. vorbis_p++;
  743. if(vorbis_p==3)break;
  744. }
  745. /* The header pages/packets will arrive before anything else we
  746. care about, or the stream is not obeying spec */
  747. if(ogg_sync_pageout(&oy,&og)>0){
  748. queue_page(&og); /* demux into the appropriate stream */
  749. }else{
  750. int ret=buffer_data(&oy);
  751. if(ret==0){
  752. fprintf(stderr,"End of file while searching for codec headers.\n");
  753. exit(1);
  754. }
  755. }
  756. }
  757. }
  758. int main( int argc, char* argv[] ){
  759. int i,j;
  760. ogg_packet op;
  761. SDL_Event event;
  762. int hasdatatobuffer = 1;
  763. int playbackdone = 0;
  764. double now, delay, last_frame_time = 0;
  765. int frameNum=0;
  766. int skipNum=0;
  767. /* takes first argument as file to play */
  768. /* this works better on Windows and is more convenient
  769. for drag and drop ogg files over the .exe */
  770. if( argc != 2 )
  771. {
  772. usage();
  773. exit(0);
  774. }
  775. infile = fopen( argv[1], "rb" );
  776. /* start up Ogg stream synchronization layer */
  777. ogg_sync_init(&oy);
  778. /* init supporting Vorbis structures needed in header parsing */
  779. vorbis_info_init(&vi);
  780. vorbis_comment_init(&vc);
  781. /* init supporting Theora structures needed in header parsing */
  782. theora_comment_init(&tc);
  783. theora_info_init(&ti);
  784. parseHeaders();
  785. /* force audio off */
  786. /* vorbis_p = 0; */
  787. /* initialize decoders */
  788. if(theora_p){
  789. theora_decode_init(&td,&ti);
  790. printf("Ogg logical stream %x is Theora %dx%d %.02f fps video\n"
  791. " Frame content is %dx%d with offset (%d,%d).\n",
  792. to.serialno,ti.width,ti.height, (double)ti.fps_numerator/ti.fps_denominator,
  793. ti.frame_width, ti.frame_height, ti.offset_x, ti.offset_y);
  794. report_colorspace(&ti);
  795. dump_comments(&tc);
  796. }else{
  797. /* tear down the partial theora setup */
  798. theora_info_clear(&ti);
  799. theora_comment_clear(&tc);
  800. }
  801. if(vorbis_p){
  802. vorbis_synthesis_init(&vd,&vi);
  803. vorbis_block_init(&vd,&vb);
  804. printf("Ogg logical stream %x is Vorbis %d channel %d Hz audio.\n",
  805. vo.serialno,vi.channels,vi.rate);
  806. }else{
  807. /* tear down the partial vorbis setup */
  808. vorbis_info_clear(&vi);
  809. vorbis_comment_clear(&vc);
  810. }
  811. /* open audio */
  812. if(vorbis_p)open_audio();
  813. /* open video */
  814. if(theora_p)open_video();
  815. /* our main loop */
  816. while(!playbackdone){
  817. /* break out on SDL quit event */
  818. if ( SDL_PollEvent ( &event ) )
  819. {
  820. if ( event.type == SDL_QUIT ) break ;
  821. }
  822. /* get some audio data */
  823. while(vorbis_p && !audiobuf_ready){
  824. int ret;
  825. float **pcm;
  826. int count = 0;
  827. int maxBytesToWrite;
  828. /* is there pending audio? does it fit our circular buffer without blocking? */
  829. ret=vorbis_synthesis_pcmout(&vd,&pcm);
  830. maxBytesToWrite = GetAudioStreamWriteable(aOutStream);
  831. if (maxBytesToWrite<=FRAMES_PER_BUFFER){
  832. /* break out until there is a significant amount of
  833. data to avoid a series of small write operations. */
  834. break;
  835. }
  836. /* if there's pending, decoded audio, grab it */
  837. if((ret>0)&&(maxBytesToWrite>0)){
  838. for(i=0;i<ret && i<(maxBytesToWrite/vi.channels);i++)
  839. for(j=0;j<vi.channels;j++){
  840. int val=(int)(pcm[j][i]*32767.f);
  841. if(val>32767)val=32767;
  842. if(val<-32768)val=-32768;
  843. samples[count]=val;
  844. count++;
  845. }
  846. if(WriteAudioStream( aOutStream, samples, i )) {
  847. if(count==maxBytesToWrite){
  848. audiobuf_ready=1;
  849. }
  850. }
  851. vorbis_synthesis_read(&vd,i);
  852. if(vd.granulepos>=0)
  853. audiobuf_granulepos=vd.granulepos-ret+i;
  854. else
  855. audiobuf_granulepos+=i;
  856. }else{
  857. /* no pending audio; is there a pending packet to decode? */
  858. if(ogg_stream_packetout(&vo,&op)>0){
  859. if(vorbis_synthesis(&vb,&op)==0) /* test for success! */
  860. vorbis_synthesis_blockin(&vd,&vb);
  861. }else /* we need more data; break out to suck in another page */
  862. break;
  863. }
  864. } /* end audio cycle */
  865. while(theora_p && !videobuf_ready){
  866. /* get one video packet... */
  867. if(ogg_stream_packetout(&to,&op)>0){
  868. theora_decode_packetin(&td,&op);
  869. videobuf_granulepos=td.granulepos;
  870. videobuf_time=theora_granule_time(&td,videobuf_granulepos);
  871. /* update the frame counter */
  872. frameNum++;
  873. /* check if this frame time has not passed yet.
  874. If the frame is late we need to decode additonal
  875. ones and keep looping, since theora at this stage
  876. needs to decode all frames */
  877. now=get_time();
  878. delay=videobuf_time-now;
  879. if(delay>=0.0){
  880. /* got a good frame, not late, ready to break out */
  881. videobuf_ready=1;
  882. }else if(now-last_frame_time>=1.0){
  883. /* display at least one frame per second, regardless */
  884. videobuf_ready=1;
  885. }else{
  886. fprintf(stderr, "dropping frame %d (%.3fs behind)\n",
  887. frameNum, -delay);
  888. }
  889. }else{
  890. /* need more data */
  891. break;
  892. }
  893. }
  894. if(!hasdatatobuffer && !videobuf_ready && !audiobuf_ready){
  895. isPlaying = 0;
  896. playbackdone = 1;
  897. }
  898. /* if we're set for the next frame, sleep */
  899. if((!theora_p || videobuf_ready) &&
  900. (!vorbis_p || audiobuf_ready)){
  901. int ticks = 1.0e3*(videobuf_time-get_time());
  902. if(ticks>0)
  903. SDL_Delay(ticks);
  904. }
  905. if(videobuf_ready){
  906. /* time to write our cached frame */
  907. video_write();
  908. videobuf_ready=0;
  909. last_frame_time=get_time();
  910. /* if audio has not started (first frame) then start it */
  911. if ((!isPlaying)&&(vorbis_p)){
  912. start_audio();
  913. isPlaying = 1;
  914. }
  915. }
  916. /* HACK: always look for more audio data */
  917. audiobuf_ready=0;
  918. /* buffer compressed data every loop */
  919. if(hasdatatobuffer){
  920. hasdatatobuffer=buffer_data(&oy);
  921. if(hasdatatobuffer==0){
  922. printf("Ogg buffering stopped, end of file reached.\n");
  923. }
  924. }
  925. if (ogg_sync_pageout(&oy,&og)>0){
  926. queue_page(&og);
  927. }
  928. } /* playbackdone */
  929. /* show number of video frames decoded */
  930. printf( "\n");
  931. printf( "Frames decoded: %d", frameNum );
  932. if(skipNum)
  933. printf( " (only %d shown)", frameNum-skipNum);
  934. printf( "\n" );
  935. /* tear it all down */
  936. fclose( infile );
  937. if(vorbis_p){
  938. audio_close();
  939. ogg_stream_clear(&vo);
  940. vorbis_block_clear(&vb);
  941. vorbis_dsp_clear(&vd);
  942. vorbis_comment_clear(&vc);
  943. vorbis_info_clear(&vi);
  944. }
  945. if(theora_p){
  946. ogg_stream_clear(&to);
  947. theora_clear(&td);
  948. theora_comment_clear(&tc);
  949. theora_info_clear(&ti);
  950. }
  951. ogg_sync_clear(&oy);
  952. printf("\r "
  953. "\nDone.\n");
  954. SDL_Quit();
  955. return(0);
  956. }