/project/jni/sdl_sound/decoders/mpglib.c

https://github.com/aichunyu/FFPlayer · C · 298 lines · 171 code · 48 blank · 79 comment · 35 complexity · 2bd09d33c49e8a201c9206862a31a902 MD5 · raw file

  1. /*
  2. * SDL_sound -- An abstract sound format decoding API.
  3. * Copyright (C) 2001 Ryan C. Gordon.
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2.1 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. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. /*
  20. * MPGLIB decoder for SDL_sound. This is a very lightweight MP3 decoder,
  21. * which is included with the SDL_sound source, so that it doesn't rely on
  22. * unnecessary external libraries.
  23. *
  24. * The SMPEG decoder plays back more forms of MPEGs, and may behave better or
  25. * worse under various conditions. mpglib is (apparently) more efficient than
  26. * SMPEG, and, again, doesn't need an external library. You should test both
  27. * decoders and use what you find works best for you.
  28. *
  29. * mpglib is an LGPL'd portion of mpg123, which can be found in its original
  30. * form at: http://www.mpg123.de/
  31. *
  32. * Please see the file COPYING in the source's root directory. The included
  33. * source code for mpglib falls under the LGPL, which is the same license as
  34. * SDL_sound (so you can consider it a single work).
  35. *
  36. * This file written by Ryan C. Gordon. (icculus@icculus.org)
  37. */
  38. #if HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. #ifdef SOUND_SUPPORTS_MPGLIB
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <string.h>
  45. #include "mpglib/mpg123_sdlsound.h"
  46. #include "mpglib/mpglib_sdlsound.h"
  47. #include "SDL_sound.h"
  48. #define __SDL_SOUND_INTERNAL__
  49. #include "SDL_sound_internal.h"
  50. static int MPGLIB_init(void);
  51. static void MPGLIB_quit(void);
  52. static int MPGLIB_open(Sound_Sample *sample, const char *ext);
  53. static void MPGLIB_close(Sound_Sample *sample);
  54. static Uint32 MPGLIB_read(Sound_Sample *sample);
  55. static int MPGLIB_rewind(Sound_Sample *sample);
  56. static int MPGLIB_seek(Sound_Sample *sample, Uint32 ms);
  57. static const char *extensions_mpglib[] = { "MP3", NULL };
  58. const Sound_DecoderFunctions __Sound_DecoderFunctions_MPGLIB =
  59. {
  60. {
  61. extensions_mpglib,
  62. "MP3 decoding via internal mpglib",
  63. "Ryan C. Gordon <icculus@icculus.org>",
  64. "http://www.icculus.org/SDL_sound/"
  65. },
  66. MPGLIB_init, /* init() method */
  67. MPGLIB_quit, /* quit() method */
  68. MPGLIB_open, /* open() method */
  69. MPGLIB_close, /* close() method */
  70. MPGLIB_read, /* read() method */
  71. MPGLIB_rewind, /* rewind() method */
  72. MPGLIB_seek /* seek() method */
  73. };
  74. /* this is what we store in our internal->decoder_private field... */
  75. typedef struct
  76. {
  77. struct mpstr mp;
  78. Uint8 inbuf[16384];
  79. Uint8 outbuf[8192];
  80. int outleft;
  81. int outpos;
  82. } mpglib_t;
  83. static int MPGLIB_init(void)
  84. {
  85. return(1); /* always succeeds. */
  86. } /* MPGLIB_init */
  87. static void MPGLIB_quit(void)
  88. {
  89. /* it's a no-op. */
  90. } /* MPGLIB_quit */
  91. static int MPGLIB_open(Sound_Sample *sample, const char *ext)
  92. {
  93. Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
  94. mpglib_t *mpg = NULL;
  95. int rc;
  96. /*
  97. * If I understand things correctly, MP3 files don't really have any
  98. * magic header we can check for. The MP3 player is expected to just
  99. * pick the first thing that looks like a valid frame and start
  100. * playing from there.
  101. *
  102. * So here's what we do: If the caller insists that this is really
  103. * MP3 we'll take his word for it. Otherwise, use the same test as
  104. * SDL_mixer does and check if the stream starts with something that
  105. * looks like a frame.
  106. *
  107. * A frame begins with 11 bits of frame sync (all bits must be set),
  108. * followed by a two-bit MPEG Audio version ID:
  109. *
  110. * 00 - MPEG Version 2.5 (later extension of MPEG 2)
  111. * 01 - reserved
  112. * 10 - MPEG Version 2 (ISO/IEC 13818-3)
  113. * 11 - MPEG Version 1 (ISO/IEC 11172-3)
  114. *
  115. * Apparently we don't handle MPEG Version 2.5.
  116. */
  117. if (__Sound_strcasecmp(ext, "MP3") != 0)
  118. {
  119. Uint8 mp3_magic[2];
  120. if (SDL_RWread(internal->rw, mp3_magic, sizeof (mp3_magic), 1) != 1)
  121. BAIL_MACRO("MPGLIB: Could not read MP3 magic.", 0);
  122. if (mp3_magic[0] != 0xFF || (mp3_magic[1] & 0xF0) != 0xF0)
  123. BAIL_MACRO("MPGLIB: Not an MP3 stream.", 0);
  124. /* If the seek fails, we'll probably miss a frame, but oh well. */
  125. SDL_RWseek(internal->rw, -sizeof (mp3_magic), SEEK_CUR);
  126. } /* if */
  127. mpg = (mpglib_t *) malloc(sizeof (mpglib_t));
  128. BAIL_IF_MACRO(mpg == NULL, ERR_OUT_OF_MEMORY, 0);
  129. memset(mpg, '\0', sizeof (mpglib_t));
  130. InitMP3(&mpg->mp);
  131. rc = SDL_RWread(internal->rw, mpg->inbuf, 1, sizeof (mpg->inbuf));
  132. if (rc <= 0)
  133. {
  134. free(mpg);
  135. BAIL_MACRO("MPGLIB: Failed to read any data at all", 0);
  136. } /* if */
  137. if (decodeMP3(&mpg->mp, mpg->inbuf, rc,
  138. mpg->outbuf, sizeof (mpg->outbuf),
  139. &mpg->outleft) == MP3_ERR)
  140. {
  141. free(mpg);
  142. BAIL_MACRO("MPGLIB: Not an MP3 stream?", 0);
  143. } /* if */
  144. SNDDBG(("MPGLIB: Accepting data stream.\n"));
  145. internal->decoder_private = mpg;
  146. sample->actual.rate = mpglib_freqs[mpg->mp.fr.sampling_frequency];
  147. sample->actual.channels = mpg->mp.fr.stereo;
  148. sample->actual.format = AUDIO_S16SYS;
  149. sample->flags = SOUND_SAMPLEFLAG_NONE;
  150. return(1); /* we'll handle this data. */
  151. } /* MPGLIB_open */
  152. static void MPGLIB_close(Sound_Sample *sample)
  153. {
  154. Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
  155. mpglib_t *mpg = ((mpglib_t *) internal->decoder_private);
  156. ExitMP3(&mpg->mp);
  157. free(mpg);
  158. } /* MPGLIB_close */
  159. static Uint32 MPGLIB_read(Sound_Sample *sample)
  160. {
  161. Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
  162. mpglib_t *mpg = ((mpglib_t *) internal->decoder_private);
  163. Uint32 bw = 0;
  164. int rc;
  165. while (bw < internal->buffer_size)
  166. {
  167. if (mpg->outleft > 0)
  168. {
  169. size_t cpysize = internal->buffer_size - bw;
  170. if (cpysize > mpg->outleft)
  171. cpysize = mpg->outleft;
  172. memcpy(((Uint8 *) internal->buffer) + bw,
  173. mpg->outbuf + mpg->outpos, cpysize);
  174. bw += cpysize;
  175. mpg->outpos += cpysize;
  176. mpg->outleft -= cpysize;
  177. continue;
  178. } /* if */
  179. /* need to decode more from the MP3 stream... */
  180. mpg->outpos = 0;
  181. rc = decodeMP3(&mpg->mp, NULL, 0, mpg->outbuf,
  182. sizeof (mpg->outbuf), &mpg->outleft);
  183. if (rc == MP3_ERR)
  184. {
  185. sample->flags |= SOUND_SAMPLEFLAG_ERROR;
  186. return(bw);
  187. } /* if */
  188. else if (rc == MP3_NEED_MORE)
  189. {
  190. rc = SDL_RWread(internal->rw, mpg->inbuf, 1, sizeof (mpg->inbuf));
  191. if (rc == -1)
  192. {
  193. sample->flags |= SOUND_SAMPLEFLAG_ERROR;
  194. return(bw);
  195. } /* if */
  196. else if (rc == 0)
  197. {
  198. sample->flags |= SOUND_SAMPLEFLAG_EOF;
  199. return(bw);
  200. } /* else if */
  201. /* make sure there isn't an ID3 tag. */
  202. /*
  203. * !!! FIXME: This can fail under the following circumstances:
  204. * First, if there's the sequence "TAG" 128 bytes from the end
  205. * of a read that isn't the EOF. This is unlikely.
  206. * Second, if the TAG sequence is split between two reads (ie,
  207. * the last byte of a read is 'T', and the next read is the
  208. * final 127 bytes of the stream, being the rest of the ID3 tag).
  209. * While this is more likely, it's still not very likely at all.
  210. * Still, something SHOULD be done about this.
  211. * ID3v2 tags are more complex, too, not to mention LYRICS tags,
  212. * etc, which aren't handled, either. Hey, this IS meant to be
  213. * a lightweight decoder. Use SMPEG if you need an all-purpose
  214. * decoder. mpglib really assumes you control all your assets.
  215. */
  216. if (rc >= 128)
  217. {
  218. Uint8 *ptr = &mpg->inbuf[rc - 128];
  219. if ((ptr[0] == 'T') && (ptr[1] == 'A') && (ptr[2] == 'G'))
  220. rc -= 128; /* disregard it. */
  221. } /* if */
  222. rc = decodeMP3(&mpg->mp, mpg->inbuf, rc,
  223. mpg->outbuf, sizeof (mpg->outbuf),
  224. &mpg->outleft);
  225. if (rc == MP3_ERR)
  226. {
  227. sample->flags |= SOUND_SAMPLEFLAG_ERROR;
  228. return(bw);
  229. } /* if */
  230. } /* else if */
  231. } /* while */
  232. return(bw);
  233. } /* MPGLIB_read */
  234. static int MPGLIB_rewind(Sound_Sample *sample)
  235. {
  236. Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
  237. mpglib_t *mpg = ((mpglib_t *) internal->decoder_private);
  238. BAIL_IF_MACRO(SDL_RWseek(internal->rw, 0, SEEK_SET) != 0, ERR_IO_ERROR, 0);
  239. /* this is just resetting some fields in a structure; it's very fast. */
  240. ExitMP3(&mpg->mp);
  241. InitMP3(&mpg->mp);
  242. mpg->outpos = mpg->outleft = 0;
  243. return(1);
  244. } /* MPGLIB_rewind */
  245. static int MPGLIB_seek(Sound_Sample *sample, Uint32 ms)
  246. {
  247. BAIL_MACRO("MPGLIB: Seeking not implemented", 0);
  248. } /* MPGLIB_seek */
  249. #endif /* SOUND_SUPPORTS_MPGLIB */
  250. /* end of mpglib.c ... */