Main Page   Data Structures   File List   Data Fields   Globals   Related Pages  

mpbuf.cpp

Go to the documentation of this file.
00001 /*  mpbuf.cpp
00002     buffered mpeg stream functions.
00003 
00004     17.09.2001: tk, stupid bug fixed. One assert for bufCount wasn't
00005                     enclosed in a enable/disable, and caused sporadic
00006                     errors (after ~2h of mp3 streaming..).
00007     15.09.2001: tk, added disable/enable pairs, because the
00008                     long integers could get updated by the callback
00009                     in the middle of an access. (it really matters!)
00010     12.09.2001: tk, the function calls are now similar to the
00011                     DirectX Audio DSB interface. It's actually
00012                     quite nice, and fits perfectly for the task.
00013     10.08.2001: tk, initial implementation.
00014 
00015     Copyright (c)2000 by Thomas Kindler, thomas.kindler@gmx.de
00016 
00017     This program is free software; you can redistribute it and/or
00018     modify it under the terms of the GNU General Public License as
00019     published by the Free Software Foundation; either version 2 of
00020     the License, or (at your option) any later version. Read the
00021     full License at http://www.gnu.org/copyleft for more details.
00022 */
00023 
00024 // include files -----
00025 //
00026 #include <stdlib.h>
00027 #include <stdio.h>
00028 #include <alloc.h>
00029 #include <assert.h>
00030 #include <mem.h>
00031 #include "clib/rtos.h"
00032 #include "vs1001.h"
00033 #include "mpbuf.h"
00034 
00035 // farmalloc'd buffer for mpeg data
00036 //
00037 static char huge  *bufPtr;
00038 static long        bufSize;
00039 
00040 // current playing position, and number of bytes.
00041 //
00042 // ** IMPORTANT **
00043 // The long volatiles may only be read or modified inside
00044 // a disable/enable section. The callback function might get
00045 // called in the middle of an access otherwise.
00046 //
00047 static volatile long  bufHead, bufCount;
00048 static volatile int   bufState;
00049 static long           bufThreshold;
00050 
00051 
00058 void callback(void *param)
00059 {
00060   bufHead  += (long)param;
00061   bufHead  %= bufSize;
00062   bufCount -= (long)param;
00063 
00064   if (bufState == BUF_STOPPING)
00065     bufState = BUF_STOPPED;
00066   if (bufState == BUF_PLAYING )
00067     BUF_Play();
00068 }
00069 
00070 
00076 long BUF_GetSize()
00077 {
00078   return  bufSize;
00079 }
00080 
00081 
00086 long BUF_GetCount()
00087 {
00088   disable();
00089   long count = bufCount;
00090   enable();
00091   return  count;
00092 }
00093 
00094 
00102 long BUF_GetFreeBytes()
00103 {
00104   return BUF_GetSize()-BUF_GetCount();
00105 }
00106 
00107 
00125 int  BUF_GetState()
00126 {
00127   return bufState;
00128 }
00129 
00130 
00146 void BUF_SetThreshold(long threshold)
00147 {
00148   bufThreshold = threshold;
00149 }
00150 
00151 
00164 void BUF_GetPositions(long *playpos, long *writepos)
00165 {
00166   disable();
00167   if (playpos)
00168     *playpos = bufHead;
00169   if (writepos)
00170     *writepos = (bufHead+bufCount) % bufSize;
00171   enable();
00172 }
00173 
00174 
00202 void BUF_Lock(long offset, long length,
00203               char **buf1, long *len1,
00204               char **buf2, long *len2 )
00205 {
00206   if (offset == BUF_FROMWRITEPOS)
00207     BUF_GetPositions(NULL, &offset);
00208 
00209   offset = offset % bufSize;
00210   if (length > bufSize)
00211     length = bufSize;
00212 
00213   *buf1 = &bufPtr[offset];
00214   *len1 = min(length, bufSize-offset);
00215   if (buf2 && len2) {
00216     if (*len1 < length) {
00217       *buf2 = bufPtr;
00218       *len2 = length - *len1;
00219     } else {
00220       *buf2 = NULL;
00221       *len2 = 0;
00222     }
00223   }
00224 }
00225 
00226 
00237 void BUF_Unlock(long bytesWritten)
00238 {
00239   disable();
00240   bufCount += bytesWritten;
00241   bool   ok = bufCount <= bufSize;
00242   enable();
00243   assert(ok);
00244 
00245   // continue playback (if buffer was stalled)
00246   //
00247   if (bufState == BUF_STALLED &&
00248       bufCount >= bufThreshold)
00249     BUF_Play();
00250 }
00251 
00252 
00273 unsigned BUF_Write(char *src, unsigned length)
00274 {
00275   char *buf1, *buf2;
00276   long  len1,  len2;
00277 
00278   length = min(length, BUF_GetFreeBytes());
00279 
00280   BUF_Lock( BUF_FROMWRITEPOS, length,
00281             &buf1, &len1, &buf2, &len2);
00282 
00283   memcpy(buf1, src, len1);
00284   if (buf2)
00285     memcpy(buf2, &src[len1], len2);
00286   BUF_Unlock(len1+len2);
00287 
00288   return len1+len2;
00289 }
00290 
00291 
00306 void BUF_Play()
00307 {
00308   if (BUF_GetCount() == 0) {
00309     bufState = BUF_STALLED;
00310   } else if (VS_IsPlaying()) {
00311     bufState = BUF_PLAYING;
00312   } else {
00313     char *buf1;
00314     long  len1 = BUF_GetCount();
00315 
00316     if (len1 > VS_FIFOSIZE)
00317       len1 = VS_FIFOSIZE;
00318 
00319     BUF_Lock(bufHead, len1, &buf1, &len1, NULL, NULL);
00320     VS_PlayMpegAsync(buf1, len1, callback, (void*)len1);
00321 
00322     bufState = BUF_PLAYING;
00323   }
00324 }
00325 
00326 
00333 void BUF_Stop()
00334 {
00335   if (bufState == BUF_STALLED)
00336     bufState = BUF_STOPPED;
00337   else if (bufState == BUF_PLAYING)
00338     bufState = BUF_STOPPING;
00339 }
00340 
00341 
00346 void BUF_Flush()
00347 {
00348   BUF_Play();
00349   while (bufState != BUF_STALLED)
00350     RTX_Sleep_Time(10);
00351   BUF_Stop();
00352 }
00353 
00354 
00359 void BUF_Clear()
00360 {
00361   BUF_Stop();
00362   while (bufState != BUF_STOPPED) {};
00363 
00364   bufCount = 0;
00365   bufHead  = 0;
00366 }
00367 
00368 
00382 long BUF_Init(long minsize, long maxsize)
00383 {
00384   printf("BUF_Init: ");
00385 
00386   bufSize = maxsize;
00387   while (bufSize >= minsize) {
00388     bufPtr = (char*)farmalloc(bufSize);
00389     if (bufPtr)
00390       break;
00391     bufSize -= 16*1024;
00392   }
00393 
00394   if (bufPtr) {
00395     printf( "allocated %ldkb at %p.\n", bufSize>>10, bufPtr );
00396   } else {
00397     printf( "couldn't allocate at least %ld bytes.\n", minsize);
00398     bufSize = 0;
00399   }
00400 
00401   bufState     = BUF_STOPPED;
00402   bufHead      = 0;
00403   bufCount     = 0;
00404   bufThreshold = VS_FIFOSIZE;
00405   return bufSize;
00406 }
00407 
00408 
00413 void BUF_Done()
00414 {
00415   BUF_Stop();
00416   if (bufPtr)
00417     farfree(bufPtr);
00418   bufSize=0;
00419 }
00420 

Generated on Sun Aug 4 21:47:28 2002 for k/os mp3v2 by doxygen1.2.16