Example #1
0
int
psf_set_string (SF_PRIVATE *psf, int str_type, const char *str)
{	if (psf->mode == SFM_READ)
		return SFE_STR_NOT_WRITE ;

	return psf_store_string (psf, str_type, str) ;
} /* psf_set_string */
Example #2
0
static int
vorbis_read_header (SF_PRIVATE *psf, int log_data)
{	OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
	VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
	char *buffer ;
	int	bytes ;
	int i, nn ;

	odata->eos = 0 ;

	/* Weird stuff happens if these aren't called. */
	ogg_stream_reset (&odata->ostream) ;
	ogg_sync_reset (&odata->osync) ;

	/*
	**	Grab some data at the head of the stream.  We want the first page
	**	(which is guaranteed to be small and only contain the Vorbis
	**	stream initial header) We need the first page to get the stream
	**	serialno.
	*/

	/* Expose the buffer */
	buffer = ogg_sync_buffer (&odata->osync, 4096L) ;

	/* Grab the part of the header that has already been read. */
	memcpy (buffer, psf->header, psf->headindex) ;
	bytes = psf->headindex ;

	/* Submit a 4k block to libvorbis' Ogg layer */
	bytes += psf_fread (buffer + psf->headindex, 1, 4096 - psf->headindex, psf) ;
	ogg_sync_wrote (&odata->osync, bytes) ;

	/* Get the first page. */
	if ((nn = ogg_sync_pageout (&odata->osync, &odata->opage)) != 1)
	{	/* Have we simply run out of data?  If so, we're done. */
		if (bytes < 4096)
			return 0 ;

		/* Error case.  Must not be Vorbis data */
		psf_log_printf (psf, "Input does not appear to be an Ogg bitstream.\n") ;
		return SFE_MALFORMED_FILE ;
	} ;

	/*
	**	Get the serial number and set up the rest of decode.
	**	Serialno first ; use it to set up a logical stream.
	*/
	ogg_stream_clear (&odata->ostream) ;
	ogg_stream_init (&odata->ostream, ogg_page_serialno (&odata->opage)) ;

	if (ogg_stream_pagein (&odata->ostream, &odata->opage) < 0)
	{	/* Error ; stream version mismatch perhaps. */
		psf_log_printf (psf, "Error reading first page of Ogg bitstream data\n") ;
		return SFE_MALFORMED_FILE ;
	} ;

	if (ogg_stream_packetout (&odata->ostream, &odata->opacket) != 1)
	{	/* No page? must not be vorbis. */
		psf_log_printf (psf, "Error reading initial header packet.\n") ;
		return SFE_MALFORMED_FILE ;
	} ;

	/*
	**	This function (vorbis_read_header) gets called multiple times, so the OGG
	**	and vorbis structs have to be cleared every time we pass through to
	**	prevent memory leaks.
	*/
	vorbis_block_clear (&vdata->vblock) ;
	vorbis_dsp_clear (&vdata->vdsp) ;
	vorbis_comment_clear (&vdata->vcomment) ;
	vorbis_info_clear (&vdata->vinfo) ;

	/*
	**	Extract the initial header from the first page and verify that the
	**	Ogg bitstream is in fact Vorbis data.
	**
	**	I handle the initial header first instead of just having the code
	**	read all three Vorbis headers at once because reading the initial
	**	header is an easy way to identify a Vorbis bitstream and it's
	**	useful to see that functionality seperated out.
	*/
	vorbis_info_init (&vdata->vinfo) ;
	vorbis_comment_init (&vdata->vcomment) ;

	if (vorbis_synthesis_headerin (&vdata->vinfo, &vdata->vcomment, &odata->opacket) < 0)
	{	/* Error case ; not a vorbis header. */
		psf_log_printf (psf, "Found Vorbis in stream header, but vorbis_synthesis_headerin failed.\n") ;
		return SFE_MALFORMED_FILE ;
	} ;

	/*
	**	Common Ogg metadata fields?
	**	TITLE, VERSION, ALBUM, TRACKNUMBER, ARTIST, PERFORMER, COPYRIGHT, LICENSE,
	**	ORGANIZATION, DESCRIPTION, GENRE, DATE, LOCATION, CONTACT, ISRC,
	*/

	if (log_data)
	{	int k ;

		for (k = 0 ; k < ARRAY_LEN (vorbis_metatypes) ; k++)
		{	char *dd ;

			dd = vorbis_comment_query (&vdata->vcomment, vorbis_metatypes [k].name, 0) ;
			if (dd == NULL)
				continue ;
			psf_store_string (psf, vorbis_metatypes [k].id, dd) ;
		} ;
	} ;

	/*
	**	At this point, we're sure we're Vorbis.	We've set up the logical (Ogg)
	**	bitstream decoder. Get the comment and codebook headers and set up the
	**	Vorbis decoder.
	**
	**	The next two packets in order are the comment and codebook headers.
	**	They're likely large and may span multiple pages.  Thus we reead
	**	and submit data until we get our two pacakets, watching that no
	**	pages are missing.  If a page is missing, error out ; losing a
	**	header page is the only place where missing data is fatal.
	*/

	i = 0 ;			/* Count of number of packets read */
	while (i < 2)
	{	int result = ogg_sync_pageout (&odata->osync, &odata->opage) ;
		if (result == 0)
		{	/* Need more data */
			buffer = ogg_sync_buffer (&odata->osync, 4096) ;
			bytes = psf_fread (buffer, 1, 4096, psf) ;

			if (bytes == 0 && i < 2)
			{	psf_log_printf (psf, "End of file before finding all Vorbis headers!\n") ;
				return SFE_MALFORMED_FILE ;
			} ;
			nn = ogg_sync_wrote (&odata->osync, bytes) ;
		}
		else if (result == 1)
		{	/*
			**	Don't complain about missing or corrupt data yet. We'll
			**	catch it at the packet output phase.
			**
			**	We can ignore any errors here as they'll also become apparent
			**	at packetout.
			*/
			nn = ogg_stream_pagein (&odata->ostream, &odata->opage) ;
			while (i < 2)
			{	result = ogg_stream_packetout (&odata->ostream, &odata->opacket) ;
				if (result == 0)
					break ;
				if (result < 0)
				{	/*	Uh oh ; data at some point was corrupted or missing!
					**	We can't tolerate that in a header. Die. */
					psf_log_printf (psf, "Corrupt secondary header.	Exiting.\n") ;
					return SFE_MALFORMED_FILE ;
				} ;

				vorbis_synthesis_headerin (&vdata->vinfo, &vdata->vcomment, &odata->opacket) ;
				i++ ;
			} ;
		} ;
	} ;

	if (log_data)
	{	int printed_metadata_msg = 0 ;
		int k ;

		psf_log_printf (psf, "Bitstream is %d channel, %D Hz\n", vdata->vinfo.channels, vdata->vinfo.rate) ;
		psf_log_printf (psf, "Encoded by : %s\n", vdata->vcomment.vendor) ;

		/* Throw the comments plus a few lines about the bitstream we're decoding. */
		for (k = 0 ; k < ARRAY_LEN (vorbis_metatypes) ; k++)
		{	char *dd ;

			dd = vorbis_comment_query (&vdata->vcomment, vorbis_metatypes [k].name, 0) ;
			if (dd == NULL)
				continue ;

			if (printed_metadata_msg == 0)
			{	psf_log_printf (psf, "Metadata :\n") ;
				printed_metadata_msg = 1 ;
			} ;

			psf_store_string (psf, vorbis_metatypes [k].id, dd) ;
			psf_log_printf (psf, "  %-10s : %s\n", vorbis_metatypes [k].name, dd) ;
		} ;

		psf_log_printf (psf, "End\n") ;
	} ;

	psf->sf.samplerate	= vdata->vinfo.rate ;
	psf->sf.channels	= vdata->vinfo.channels ;
	psf->sf.format		= SF_FORMAT_OGG | SF_FORMAT_VORBIS ;

	/*	OK, got and parsed all three headers. Initialize the Vorbis
	**	packet->PCM decoder.
	**	Central decode state. */
	vorbis_synthesis_init (&vdata->vdsp, &vdata->vinfo) ;

	/*	Local state for most of the decode so multiple block decodes can
	**	proceed in parallel. We could init multiple vorbis_block structures
	**	for vd here. */
	vorbis_block_init (&vdata->vdsp, &vdata->vblock) ;

	vdata->loc = 0 ;

	return 0 ;
} /* vorbis_read_header */
Example #3
0
static int caf_read_strings (SF_PRIVATE * psf, sf_count_t chunk_size)
{
    //char buf [chunk_size - 4] ;
    char *buf = (char*)malloc(chunk_size-4);
    char *key, *value ;
    uint32_t count, hash ;

    psf_binheader_readf (psf, "E4b", &count, buf, make_size_t (chunk_size - 4)) ;
    psf_log_printf (psf, " count: %u\n", count) ;

    /* Force terminate `buf` to make sure. */
    buf [chunk_size-4 - 1] = 0 ;

    for (key = buf ; key < buf + chunk_size-4 ; )
    {	value = key + strlen (key) + 1 ;
    if (value > buf + chunk_size-4)
        break ;
    psf_log_printf (psf, "   %-12s : %s\n", key, value) ;

    hash = string_hash32 (key) ;
    switch (hash)
    {	case 0xC4861943 : /* 'title' */
    psf_store_string (psf, SF_STR_TITLE, value) ;
    break ;
    case 0xAD47A394 : /* 'software' */
        psf_store_string (psf, SF_STR_SOFTWARE, value) ;
        break ;
    case 0x5D178E2A : /* 'copyright' */
        psf_store_string (psf, SF_STR_COPYRIGHT, value) ;
        break ;
    case 0x60E4D0C8 : /* 'artist' */
        psf_store_string (psf, SF_STR_ARTIST, value) ;
        break ;
    case 0x83B5D16A : /* 'genre' */
        psf_store_string (psf, SF_STR_GENRE, value) ;
        break ;
    case 0x15E5FC88 : /* 'comment' */
    case 0x7C297D5B : /* 'comments' */
        psf_store_string (psf, SF_STR_COMMENT, value) ;
        break ;
    case 0x24A7C347 : /* 'tracknumber' */
        psf_store_string (psf, SF_STR_TRACKNUMBER, value) ;
        break ;
    case 0x50A31EB7 : /* 'date' */
        psf_store_string (psf, SF_STR_DATE, value) ;
        break ;
    case 0x6583545A : /* 'album' */
        psf_store_string (psf, SF_STR_ALBUM, value) ;
        break ;
    case 0xE7C64B6C : /* 'license' */
        psf_store_string (psf, SF_STR_LICENSE, value) ;
        break ;
    default :
        psf_log_printf (psf, " Unhandled hash 0x%x : /* '%s' */\n", hash, key) ;
        break ;
    } ;

    key = value + strlen (value) + 1 ;
    } ;
    free(buf);

    return 0 ;
}