PageRenderTime 47ms CodeModel.GetById 13ms app.highlight 26ms RepoModel.GetById 1ms app.codeStats 0ms

/project/jni/sdl_mixer/load_ogg.c

https://github.com/aichunyu/FFPlayer
C | 161 lines | 105 code | 31 blank | 25 comment | 18 complexity | aa0d20dcbb868c6414239ac381477f19 MD5 | raw file
  1/*
  2    SDL_mixer:  An audio mixer library based on the SDL library
  3    Copyright (C) 1997-2009 Sam Lantinga
  4
  5    This library is free software; you can redistribute it and/or
  6    modify it under the terms of the GNU Library General Public
  7    License as published by the Free Software Foundation; either
  8    version 2 of the License, or (at your option) any later version.
  9
 10    This library is distributed in the hope that it will be useful,
 11    but WITHOUT ANY WARRANTY; without even the implied warranty of
 12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13    Library General Public License for more details.
 14
 15    You should have received a copy of the GNU Library General Public
 16    License along with this library; if not, write to the Free
 17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 18
 19    This is the source needed to decode an Ogg Vorbis into a waveform.
 20    This file by Vaclav Slavik (vaclav.slavik@matfyz.cz).
 21*/
 22
 23/* $Id: load_ogg.c 5214 2009-11-08 17:11:09Z slouken $ */
 24
 25#ifdef OGG_MUSIC
 26
 27#include <stdio.h>
 28#include <stdlib.h>
 29#include <string.h>
 30
 31#include "SDL_mutex.h"
 32#include "SDL_endian.h"
 33#include "SDL_timer.h"
 34
 35#include "SDL_mixer.h"
 36#include "dynamic_ogg.h"
 37#include "load_ogg.h"
 38
 39static size_t sdl_read_func(void *ptr, size_t size, size_t nmemb, void *datasource)
 40{
 41    return SDL_RWread((SDL_RWops*)datasource, ptr, size, nmemb);
 42}
 43
 44static int sdl_seek_func(void *datasource, ogg_int64_t offset, int whence)
 45{
 46    return SDL_RWseek((SDL_RWops*)datasource, (int)offset, whence);
 47}
 48
 49static int sdl_close_func_freesrc(void *datasource)
 50{
 51    return SDL_RWclose((SDL_RWops*)datasource);
 52}
 53
 54static int sdl_close_func_nofreesrc(void *datasource)
 55{
 56    return SDL_RWseek((SDL_RWops*)datasource, 0, RW_SEEK_SET);
 57}
 58
 59static long sdl_tell_func(void *datasource)
 60{
 61    return SDL_RWtell((SDL_RWops*)datasource);
 62}
 63
 64
 65/* don't call this directly; use Mix_LoadWAV_RW() for now. */
 66SDL_AudioSpec *Mix_LoadOGG_RW (SDL_RWops *src, int freesrc,
 67        SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
 68{
 69    OggVorbis_File vf;
 70    ov_callbacks callbacks;
 71    vorbis_info *info;
 72    Uint8 *buf;
 73    int bitstream = -1;
 74    long samplesize;
 75    long samples;
 76    int read, to_read;
 77    int must_close = 1;
 78    int was_error = 1;
 79    
 80    if ( (!src) || (!audio_buf) || (!audio_len) )   /* sanity checks. */
 81        goto done;
 82
 83    if ( !Mix_Init(MIX_INIT_OGG) )
 84        goto done;
 85
 86    callbacks.read_func = sdl_read_func;
 87    callbacks.seek_func = sdl_seek_func;
 88    callbacks.tell_func = sdl_tell_func;
 89    callbacks.close_func = freesrc ? 
 90                           sdl_close_func_freesrc : sdl_close_func_nofreesrc;
 91
 92    if (vorbis.ov_open_callbacks(src, &vf, NULL, 0, callbacks) != 0)
 93    {
 94        SDL_SetError("OGG bitstream is not valid Vorbis stream!");
 95        goto done;
 96    }
 97
 98    must_close = 0;
 99    
100    info = vorbis.ov_info(&vf, -1);
101    
102    *audio_buf = NULL;
103    *audio_len = 0;
104    memset(spec, '\0', sizeof (SDL_AudioSpec));
105
106    spec->format = AUDIO_S16;
107    spec->channels = info->channels;
108    spec->freq = info->rate;
109    spec->samples = 4096; /* buffer size */
110    
111    samples = (long)vorbis.ov_pcm_total(&vf, -1);
112
113    *audio_len = spec->size = samples * spec->channels * 2;
114    *audio_buf = malloc(*audio_len);
115    if (*audio_buf == NULL)
116        goto done;
117
118    buf = *audio_buf;
119    to_read = *audio_len;
120#ifdef OGG_USE_TREMOR
121    for (read = vorbis.ov_read(&vf, (char *)buf, to_read, &bitstream);
122	 read > 0;
123	 read = vorbis.ov_read(&vf, (char *)buf, to_read, &bitstream))
124#else
125    for (read = vorbis.ov_read(&vf, (char *)buf, to_read, 0/*LE*/, 2/*16bit*/, 1/*signed*/, &bitstream);
126         read > 0;
127         read = vorbis.ov_read(&vf, (char *)buf, to_read, 0, 2, 1, &bitstream))
128#endif	 
129    {
130        if (read == OV_HOLE || read == OV_EBADLINK)
131            break; /* error */
132        
133        to_read -= read;
134        buf += read;
135    }
136
137    vorbis.ov_clear(&vf);
138    was_error = 0;
139
140    /* Don't return a buffer that isn't a multiple of samplesize */
141    samplesize = ((spec->format & 0xFF)/8)*spec->channels;
142    *audio_len &= ~(samplesize-1);
143
144done:
145    if (src && must_close)
146    {
147        if (freesrc)
148            SDL_RWclose(src);
149        else
150            SDL_RWseek(src, 0, RW_SEEK_SET);
151    }
152
153    if ( was_error )
154        spec = NULL;
155
156    return(spec);
157} /* Mix_LoadOGG_RW */
158
159/* end of load_ogg.c ... */
160
161#endif