PageRenderTime 56ms CodeModel.GetById 40ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/project/jni/sndfile/src/ogg.c

https://github.com/aichunyu/FFPlayer
C | 250 lines | 157 code | 54 blank | 39 comment | 20 complexity | 91853f4bdf066f4cc34c4f23b8bc1e00 MD5 | raw file
  1/*
  2** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
  3** Copyright (C) 2007 John ffitch
  4**
  5** This program is free software ; you can redistribute it and/or modify
  6** it under the terms of the GNU Lesser General Public License as published by
  7** the Free Software Foundation ; either version 2.1 of the License, or
  8** (at your option) any later version.
  9**
 10** This program 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
 13** GNU Lesser General Public License for more details.
 14**
 15** You should have received a copy of the GNU Lesser General Public License
 16** along with this program ; if not, write to the Free Software
 17** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 18*/
 19
 20#include "sfconfig.h"
 21
 22#include <stdio.h>
 23#include <fcntl.h>
 24#include <string.h>
 25#include <ctype.h>
 26#include <time.h>
 27#include <math.h>
 28
 29#if HAVE_UNISTD_H
 30#include <unistd.h>
 31#endif
 32
 33#include "sndfile.h"
 34#include "sfendian.h"
 35#include "common.h"
 36
 37#if HAVE_EXTERNAL_LIBS
 38
 39#include <ogg/ogg.h>
 40
 41#include "ogg.h"
 42
 43static int	ogg_close (SF_PRIVATE *psf) ;
 44static int	ogg_stream_classify (SF_PRIVATE *psf, OGG_PRIVATE * odata) ;
 45static int	ogg_page_classify (SF_PRIVATE * psf, const ogg_page * og) ;
 46
 47int
 48ogg_open (SF_PRIVATE *psf)
 49{	OGG_PRIVATE* odata = calloc (1, sizeof (OGG_PRIVATE)) ;
 50	sf_count_t pos = psf_ftell (psf) ;
 51	int	error = 0 ;
 52
 53	psf->container_data = odata ;
 54	psf->container_close = ogg_close ;
 55
 56	if (psf->file.mode == SFM_RDWR)
 57		return SFE_BAD_MODE_RW ;
 58
 59	if (psf->file.mode == SFM_READ)
 60		if ((error = ogg_stream_classify (psf, odata)) != 0)
 61			return error ;
 62
 63	/* Reset everything to an initial state. */
 64	ogg_sync_clear (&odata->osync) ;
 65	ogg_stream_clear (&odata->ostream) ;
 66	psf_fseek (psf, pos, SEEK_SET) ;
 67
 68	switch (psf->sf.format)
 69	{	case SF_FORMAT_OGG | SF_FORMAT_VORBIS :
 70			return ogg_vorbis_open (psf) ;
 71
 72		case SF_FORMAT_OGGFLAC :
 73			free (psf->container_data) ;
 74			psf->container_data = NULL ;
 75			psf->container_close = NULL ;
 76			return flac_open (psf) ;
 77
 78#if ENABLE_EXPERIMENTAL_CODE
 79		case SF_FORMAT_OGG | SF_FORMAT_SPEEX :
 80			return ogg_speex_open (psf) ;
 81
 82		case SF_FORMAT_OGG | SF_FORMAT_PCM_16 :
 83		case SF_FORMAT_OGG | SF_FORMAT_PCM_24 :
 84			return ogg_pcm_open (psf) ;
 85#endif
 86
 87		default :
 88			break ;
 89		} ;
 90
 91	psf_log_printf (psf, "%s : mode should be SFM_READ or SFM_WRITE.\n", __func__) ;
 92	return SFE_INTERNAL ;
 93} /* ogg_open */
 94
 95
 96static int
 97ogg_close (SF_PRIVATE *psf)
 98{	OGG_PRIVATE* odata = psf->container_data ;
 99
100	ogg_sync_clear (&odata->osync) ;
101	ogg_stream_clear (&odata->ostream) ;
102
103	return 0 ;
104} /* ogg_close */
105
106static int
107ogg_stream_classify (SF_PRIVATE *psf, OGG_PRIVATE* odata)
108{	char *buffer ;
109	int	 bytes, nn ;
110
111	/* Call this here so it only gets called once, so no memory is leaked. */
112	ogg_sync_init (&odata->osync) ;
113
114	odata->eos = 0 ;
115
116	/* Weird stuff happens if these aren't called. */
117	ogg_stream_reset (&odata->ostream) ;
118	ogg_sync_reset (&odata->osync) ;
119
120	/*
121	**	Grab some data at the head of the stream.  We want the first page
122	**	(which is guaranteed to be small and only contain the Vorbis
123	**	stream initial header) We need the first page to get the stream
124	**	serialno.
125	*/
126
127	/* Expose the buffer */
128	buffer = ogg_sync_buffer (&odata->osync, 4096L) ;
129
130	/* Grab the part of the header that has already been read. */
131	memcpy (buffer, psf->header, psf->headindex) ;
132	bytes = psf->headindex ;
133
134	/* Submit a 4k block to libvorbis' Ogg layer */
135	bytes += psf_fread (buffer + psf->headindex, 1, 4096 - psf->headindex, psf) ;
136	ogg_sync_wrote (&odata->osync, bytes) ;
137
138	/* Get the first page. */
139	if ((nn = ogg_sync_pageout (&odata->osync, &odata->opage)) != 1)
140	{
141		/* Have we simply run out of data?  If so, we're done. */
142		if (bytes < 4096)
143			return 0 ;
144
145		/* Error case.  Must not be Vorbis data */
146		psf_log_printf (psf, "Input does not appear to be an Ogg bitstream.\n") ;
147		return SFE_MALFORMED_FILE ;
148		} ;
149
150	/*
151	**	Get the serial number and set up the rest of decode.
152	**	Serialno first ; use it to set up a logical stream.
153	*/
154	ogg_stream_clear (&odata->ostream) ;
155	ogg_stream_init (&odata->ostream, ogg_page_serialno (&odata->opage)) ;
156
157	if (ogg_stream_pagein (&odata->ostream, &odata->opage) < 0)
158	{	/* Error ; stream version mismatch perhaps. */
159		psf_log_printf (psf, "Error reading first page of Ogg bitstream data\n") ;
160		return SFE_MALFORMED_FILE ;
161		} ;
162
163	if (ogg_stream_packetout (&odata->ostream, &odata->opacket) != 1)
164	{	/* No page? must not be vorbis. */
165		psf_log_printf (psf, "Error reading initial header packet.\n") ;
166		return SFE_MALFORMED_FILE ;
167		} ;
168
169	odata->codec = ogg_page_classify (psf, &odata->opage) ;
170
171	switch (odata->codec)
172	{	case OGG_VORBIS :
173			psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
174			return 0 ;
175
176		case OGG_FLAC :
177		case OGG_FLAC0 :
178			psf->sf.format = SF_FORMAT_OGGFLAC ;
179			return 0 ;
180
181		case OGG_SPEEX :
182			psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_SPEEX ;
183			return 0 ;
184
185		case OGG_PCM :
186			psf_log_printf (psf, "Detected Ogg/PCM data. This is not supported yet.\n") ;
187			return SFE_UNIMPLEMENTED ;
188
189		default :
190			break ;
191		} ;
192
193	psf_log_printf (psf, "This Ogg bitstream contains some uknown data type.\n") ;
194	return SFE_UNIMPLEMENTED ;
195} /* ogg_stream_classify */
196
197/*==============================================================================
198*/
199
200static struct
201{	const char *str, *name ;
202	int len, codec ;
203} codec_lookup [] =
204{	{	"Annodex",		"Annodex",	8, OGG_ANNODEX },
205	{	"AnxData",		"AnxData",	7, OGG_ANXDATA },
206	{	"\177FLAC",		"Flac1",	5, OGG_FLAC },
207	{	"fLaC",			"Flac0",	4, OGG_FLAC0 },
208	{	"PCM     ",		"PCM",		8, OGG_PCM },
209	{	"Speex",		"Speex",	5, OGG_SPEEX },
210	{	"\001vorbis",	"Vorbis",	7, OGG_VORBIS },
211} ;
212
213static int
214ogg_page_classify (SF_PRIVATE * psf, const ogg_page * og)
215{	int k, len ;
216
217	for (k = 0 ; k < ARRAY_LEN (codec_lookup) ; k++)
218	{	if (codec_lookup [k].len > og->body_len)
219			continue ;
220
221		if (memcmp (og->body, codec_lookup [k].str, codec_lookup [k].len) == 0)
222		{	psf_log_printf (psf, "Ogg stream data : %s\n", codec_lookup [k].name) ;
223			psf_log_printf (psf, "Stream serialno : %010D\n", (int64_t) ogg_page_serialno (og)) ;
224			return codec_lookup [k].codec ;
225			} ;
226		} ;
227
228	len = og->body_len < 8 ? og->body_len : 8 ;
229
230	psf_log_printf (psf, "Ogg_stream data : '") ;
231	for (k = 0 ; k < len ; k++)
232		psf_log_printf (psf, "%c", isprint (og->body [k]) ? og->body [k] : '.') ;
233	psf_log_printf (psf, "'     ") ;
234	for (k = 0 ; k < len ; k++)
235		psf_log_printf (psf, " %02x", og->body [k] & 0xff) ;
236	psf_log_printf (psf, "\n") ;
237
238	return 0 ;
239} /* ogg_page_classify */
240
241#else /* HAVE_EXTERNAL_LIBS */
242
243int
244ogg_open	(SF_PRIVATE *psf)
245{
246	psf_log_printf (psf, "This version of libsndfile was compiled without Ogg/Vorbis support.\n") ;
247	return SFE_UNIMPLEMENTED ;
248} /* ogg_open */
249
250#endif