OGG playback error

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
Criptych
Posts: 64
Joined: Sat Sep 12, 2009 5:18 am

OGG playback error

Post by Criptych »

I'm trying to add OGG playback to a program. Everything compiles fine, but when I try to play a file, I get the following error:

Code: Select all

Program received signal SIGBUS, Bus error.
_malloc_r &#40;reent_ptr=0x88ca8e0, bytes=<value optimized out>&#41;
    at ../../../../../../newlib-1.17.0/newlib/libc/stdlib/mallocr.c&#58;2376
2376    ../../../../../../newlib-1.17.0/newlib/libc/stdlib/mallocr.c&#58; No such file or directory.
        in ../../../../../../newlib-1.17.0/newlib/libc/stdlib/mallocr.c
&#40;gdb&#41; bt
#0  _malloc_r &#40;reent_ptr=0x88ca8e0, bytes=<value optimized out>&#41;
    at ../../../../../../newlib-1.17.0/newlib/libc/stdlib/mallocr.c&#58;2376
#1  0x0888fb40 in _calloc_r &#40;reent_ptr=0x88ca8e0, n=<value optimized out>, elem_size=0&#41;
    at ../../../../../../newlib-1.17.0/newlib/libc/stdlib/mallocr.c&#58;3202
#2  0x0883f558 in vorbis_synthesis_headerin &#40;&#41;
#3  0x0882f990 in _fetch_headers &#40;&#41;
#4  0x08830260 in _ov_open1 &#40;&#41;
#5  0x08832c60 in ov_open_callbacks &#40;&#41;
#6  0x0880a8a4 in oggFileLoad &#40;filename=0x8a9e110 "voice/0002.ogg"&#41;
    at oggplay.c&#58;95
#7  0x0880ab90 in oggPlay &#40;filename=0x8a9e110 "voice/0002.ogg"&#41;
    at oggplay.c&#58;164
Sometimes the error occurs in ov_read instead of ov_open_callbacks. I've run out of ideas; what could be causing this?
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

It's in malloc, are you running out of RAM by any chance? Bus errors can also be caused by alignment problems. It's also possible (and more likely) that you are just corrupting memory and that's messing with the malloc data structures. If you can, try compiling the same code on the PC and run it under valgrind.
Criptych
Posts: 64
Joined: Sat Sep 12, 2009 5:18 am

Post by Criptych »

jimparis wrote:It's in malloc, are you running out of RAM by any chance? Bus errors can also be caused by alignment problems. It's also possible (and more likely) that you are just corrupting memory and that's messing with the malloc data structures. If you can, try compiling the same code on the PC and run it under valgrind.
I thought malloc just returned NULL if there wasn't enough RAM? Anyway, I printed the available RAM as close to the crash as possible, and got ~17MB. The OGG I played is only a few hundred K, so that's probably not it.
The actual player code is sort of stripped-down from Sakya's LightMP3 OGG player, with some changes and additions to accommodate the way I'm using it:

Code: Select all

#include "common.h"

#include <pspaudiolib.h>

#include <tremor/ivorbiscodec.h> //libtremor
#include <tremor/ivorbisfile.h>  //libtremor

struct oggFile_t
&#123;
   struct OggVorbis_File vf;
   int loop, autounload;
   int lvol, rvol;
&#125;;

size_t ogg_read&#40;void *ptr, size_t size, size_t nmemb, void *datasource&#41;
&#123;
    return pgeFileRead&#40;&#40;pgeFile *&#41;datasource, ptr, size * nmemb&#41; / size;
&#125;
int ogg_seek&#40;void *datasource, ogg_int64_t offset, int whence&#41;
&#123;
    return pgeFileSeek&#40;&#40;pgeFile *&#41;datasource, &#40;long&#41;offset, whence&#41;;
&#125;
long ogg_tell&#40;void *datasource&#41;
&#123;
    return pgeFileSeek&#40;&#40;pgeFile *&#41;datasource, 0, PGE_FILE_CUR&#41;;
&#125;
int ogg_close&#40;void *datasource&#41;
&#123;
    return pgeFileClose&#40;&#40;pgeFile *&#41;datasource&#41;;
&#125;

static ov_callbacks pspio_callbacks = &#123; ogg_read, ogg_seek, ogg_close, ogg_tell &#125;;

static oggFile *ogg_info&#91;PSP_NUM_AUDIO_CHANNELS&#93; = &#123; 0 &#125;;

static void oggDecodeCallback&#40;void *buffer, u32 nsamples, void *pdata&#41;
&#123;
   if &#40;!&#40;buffer && nsamples&#41;&#41; return;

   oggFile *ogg = &#40;oggFile *&#41;pdata;

   int sect = 0;

   int nbytes = nsamples * 4;

   int res = 0;

   while &#40;nbytes > 0&#41;
   &#123;
      res = ov_read&#40;&&#40;ogg->vf&#41;, buffer, nbytes, &sect&#41;;
      if &#40;res == OV_HOLE&#41; continue;
      if &#40;res <= 0&#41; break;
      nbytes -= res;
   &#125;

   if &#40;res <= 0 && ogg->autounload&#41;
   &#123;
      oggFileUnload&#40;ogg&#41;;
   &#125;
&#125;

int oggInit&#40;&#41;
&#123;
   return pspAudioInit&#40;&#41; < 0 ? 0 &#58; 1;
&#125;

void oggShutdown&#40;&#41;
&#123;
   pspAudioEnd&#40;&#41;;
&#125;

void oggFileUnload&#40;oggFile *ogg&#41;
&#123;
   ov_clear&#40;&&#40;ogg->vf&#41;&#41;;
&#125;

oggFile *oggFileLoad&#40;const char *filename&#41;
&#123;
   pgeFile *file = pgeFileOpen&#40;&#40;char *&#41;filename, PGE_FILE_RDONLY&#41;;

   if &#40;!file&#41; return 0;

   DEBUG&#40;"Before&#58; %8dkB RAM free\n", pgeSystemGetFreeRam&#40;&#41; >> 10&#41;;

   oggFile *ogg = &#40;oggFile *&#41;pgeMalloc&#40;sizeof&#40;oggFile&#41;&#41;;

   if &#40;!ogg&#41; return 0;

   int res = ov_open_callbacks&#40;file, &&#40;ogg->vf&#41;, 0, 0, pspio_callbacks&#41;;

   DEBUG&#40;"After&#58;  %8dkB RAM free\n", pgeSystemGetFreeRam&#40;&#41; >> 10&#41;;

   if &#40;res < 0&#41;
   &#123;
      pgeFileClose&#40;file&#41;;
      return 0;
   &#125;

   vorbis_info *vi = ov_info&#40;&&#40;ogg->vf&#41;, -1&#41;;

   DEBUG&#40;"samplerate == %ld, channels == %d\n", vi->rate, vi->channels&#41;;

   if &#40;vi->channels > 2&#41;
   &#123;
      oggFileUnload&#40;ogg&#41;;
      return 0;
   &#125;

   ogg->loop = ogg->autounload = 0;
   ogg->lvol = ogg->rvol = 0x8000;

   return ogg;
&#125;

int oggFileLoop&#40;oggFile *ogg, int loop&#41;
&#123;
   if &#40;!ogg&#41; return 0;
   int old = ogg->loop;
   ogg->loop = loop;
   return old;
&#125;

void oggFileSetVolume&#40;oggFile *ogg, int lvol, int rvol&#41;
&#123;
   if &#40;!ogg&#41; return;
   ogg->lvol = lvol;
   ogg->rvol = rvol;
&#125;

int oggFilePlay&#40;oggFile *ogg&#41;
&#123;
   int slot;
   for &#40;slot = 0; slot < PSP_NUM_AUDIO_CHANNELS; ++slot&#41;
   &#123;
      if &#40;!ogg_info&#91;slot&#93;&#41; break;
   &#125;

   if &#40;slot < PSP_NUM_AUDIO_CHANNELS&#41;
   &#123;
      ogg_info&#91;slot&#93; = ogg;

      pspAudioSetVolume&#40;slot, ogg->lvol, ogg->rvol&#41;;

      pspAudioSetChannelCallback&#40;slot, oggDecodeCallback, ogg&#41;;

      return 1;
   &#125;
   else if &#40;ogg->autounload&#41;
   &#123;
      oggFileUnload&#40;ogg&#41;;
   &#125;

   return 0;
&#125;

int oggPlay&#40;const char *filename&#41;
&#123;
   oggFile *ogg = oggFileLoad&#40;filename&#41;;

   if &#40;!ogg&#41; return 0;

   ogg->autounload = 1;

   return oggFilePlay&#40;ogg&#41;;
&#125;
AFAIK I'm not messing with anything dangerous, system structures and whatnot...
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

I don't know what the pgeFile* functions do, but note that sceIoRead and sceIoWrite have buffer alignment restrictions that might be a problem. Can you add more debugging and see if it's reachign any of the callbacks? I don't necessarily trust the gdb backtrace.
Criptych
Posts: 64
Joined: Sat Sep 12, 2009 5:18 am

Post by Criptych »

jimparis wrote:I don't know what the pgeFile* functions do, but note that sceIoRead and sceIoWrite have buffer alignment restrictions that might be a problem.
pgeFile* are I/O abstraction, i.e. so memory and disk files can be handled the same way. For disk files, they ultimately use sceIo*.
jimparis wrote:Can you add more debugging and see if it's reachign any of the callbacks? I don't necessarily trust the gdb backtrace.
Sure, I was actually starting that when I saw your reply. :)

EDIT: From a test module that loads and plays an ~6MB track.

Code: Select all

Before&#58;    22528kB RAM free
ogg_seek&#40;0x88f6730, 0, 1&#41;
ogg_read&#40;0x0, 1, 8500, 0x88f6730&#41;
After&#58;         0kB RAM free
oggFileLoad&#58; ov_open_callbacks&#58; res == -128
oggPlay returned 0
Apparently it tries to read into a NULL pointer, which may be related to the malloc problem I had before? Especially considering it goes from 20MB free RAM to zero. I looked up the error code, -128 is OV_EREAD; obviously there's going to be a read error if there's no memory to read into. :(

EDIT: I tried replacing pgeFile* with sceIo* and with stdio functions, and still get the same result both times.

@!#&^%*&^#$! Changed a few lines to use standard vorbis instead of Tremor, and now it works - still needs some tweaking, but it works. I guess I'll try it like this for now. Thanks for your suggestions. :)
Last edited by Criptych on Thu Oct 29, 2009 3:32 am, edited 1 time in total.
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

libogg seems to have no error checking. If a malloc fails, calls like ogg_sync_buffer will return NULL which would lead directly to the read-into-NULL that you noticed. I don't know why, but it looks like you really are out of ram. Maybe try instrumenting libogg and libvorbis's malloc calls (they both use an _ogg_malloc macro that you can redefine)
Criptych
Posts: 64
Joined: Sat Sep 12, 2009 5:18 am

Post by Criptych »

That won't be necessary... I'm just very good at making stupid mistakes. I #included the Tremor headers, but linked with libvorbis and libvorbisfile - probably why it worked when I changed to the standard vorbis headers. Linking with libvorbisidec instead fixed it. Thanks for your help, anyway. :)
Post Reply