diff options
Diffstat (limited to 'source/ap/vorbis-tools/ogg123.opus.diff')
-rw-r--r-- | source/ap/vorbis-tools/ogg123.opus.diff | 544 |
1 files changed, 544 insertions, 0 deletions
diff --git a/source/ap/vorbis-tools/ogg123.opus.diff b/source/ap/vorbis-tools/ogg123.opus.diff new file mode 100644 index 00000000..894845bc --- /dev/null +++ b/source/ap/vorbis-tools/ogg123.opus.diff @@ -0,0 +1,544 @@ +diff --git a/configure.ac b/configure.ac +index 800d3b8..0ba91ce 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -159,16 +159,26 @@ then + if test "x$ac_cv_have_decl_OV_ECTL_COUPLING_SET" = "xno" + then + AC_MSG_ERROR([Vorbis >= 1.3.0 required !]) + HAVE_VORBIS=no + fi + fi + AM_CONDITIONAL(HAVE_OV_READ_FILTER, test "x$have_ov_read_filter" = "xyes") + ++if test "x$HAVE_PKG_CONFIG" = "xyes" ++then ++ PKG_CHECK_MODULES(OPUSFILE, opusfile >= 0.2, HAVE_LIBOPUSFILE=yes, HAVE_LIBOPUSFILE=no) ++ AC_SUBST(OPUSFILE_LIBS) ++ if test "x$HAVE_LIBOPUSFILE" = xyes; then ++ AC_DEFINE(HAVE_LIBOPUSFILE, 1, [Defined if we have libopusfile]) ++ fi ++fi ++AM_CONDITIONAL(HAVE_LIBOPUSFILE, test "x$HAVE_LIBOPUSFILE" = "xyes") ++ + + SHARE_LIBS='$(top_builddir)/share/libutf8.a $(top_builddir)/share/libgetopt.a' + SHARE_CFLAGS='-I$(top_srcdir)/include' + + I18N_CFLAGS='-I$(top_srcdir)/intl' + I18N_LIBS=$INTLLIBS + + SOCKET_LIBS= +diff --git a/ogg123/Makefile.am b/ogg123/Makefile.am +index f7c5b46..df39c91 100644 +--- a/ogg123/Makefile.am ++++ b/ogg123/Makefile.am +@@ -4,50 +4,58 @@ flac_sources = flac_format.c easyflac.c easyflac.h + else + flac_sources = + endif + if HAVE_LIBSPEEX + speex_sources = speex_format.c + else + speex_sources = + endif ++if HAVE_LIBOPUSFILE ++opus_sources = opus_format.c ++else ++opus_sources = ++endif ++ + if HAVE_OV_READ_FILTER + vgfilter_sources = vgfilter.c vgfilter.h + else + vgfilter_sources = + endif + + datadir = @datadir@ + localedir = $(datadir)/locale + DEFS = -DSYSCONFDIR=\"$(sysconfdir)\" -DLOCALEDIR=\"$(localedir)\" @DEFS@ + + docdir = $(datadir)/doc/$(PACKAGE)-$(VERSION) + mandir = @MANDIR@ + + bin_PROGRAMS = ogg123 + +-INCLUDES = @OGG_CFLAGS@ @VORBIS_CFLAGS@ @AO_CFLAGS@ @CURL_CFLAGS@ \ ++INCLUDES = @OGG_CFLAGS@ @VORBIS_CFLAGS@ @OPUSFILE_CFLAGS@ @AO_CFLAGS@ @CURL_CFLAGS@ \ + @PTHREAD_CFLAGS@ @SHARE_CFLAGS@ @I18N_CFLAGS@ + + ogg123_LDADD = @SHARE_LIBS@ \ + @VORBISFILE_LIBS@ @VORBIS_LIBS@ @OGG_LIBS@ @AO_LIBS@ \ + @SOCKET_LIBS@ @LIBICONV@ @CURL_LIBS@ @PTHREAD_CFLAGS@ \ +- @PTHREAD_LIBS@ @I18N_LIBS@ @FLAC_LIBS@ @SPEEX_LIBS@ ++ @PTHREAD_LIBS@ @I18N_LIBS@ @FLAC_LIBS@ @SPEEX_LIBS@ \ ++ @OPUSFILE_LIBS@ + + ogg123_DEPENDENCIES = @SHARE_LIBS@ + ogg123_SOURCES = audio.c buffer.c callbacks.c \ + cfgfile_options.c cmdline_options.c \ + file_transport.c format.c http_transport.c \ + ogg123.c oggvorbis_format.c playlist.c \ + status.c remote.c transport.c vorbis_comments.c \ + audio.h buffer.h callbacks.h compat.h \ + cfgfile_options.h cmdline_options.h \ + format.h ogg123.h playlist.h status.h \ + transport.h remote.h vorbis_comments.h \ +- $(flac_sources) $(speex_sources) $(vgfilter_sources) ++ $(flac_sources) $(speex_sources) $(vgfilter_sources) \ ++ $(opus_sources) + + man_MANS = ogg123.1 + doc_DATA = ogg123rc-example + + EXTRA_ogg123_SOURCES = \ + $(man_MANS) $(doc_DATA) + + debug: +diff --git a/ogg123/cmdline_options.c b/ogg123/cmdline_options.c +index f3107f9..2194ffc 100644 +--- a/ogg123/cmdline_options.c ++++ b/ogg123/cmdline_options.c +@@ -314,16 +314,20 @@ void cmdline_usage (void) + #ifdef HAVE_LIBFLAC + printf (_("FLAC, ")); + #endif + + #ifdef HAVE_LIBSPEEX + printf (_("Speex, ")); + #endif + ++#ifdef HAVE_LIBOPUSFILE ++ printf (_("Opus, ")); ++#endif ++ + printf (_("Ogg Vorbis.\n\n")); + + printf (_("Output options\n")); + printf (_(" -d dev, --device dev Use output device \"dev\". Available devices:\n")); + printf (" "); + printf (_("Live:")); + + for(i = 0, j = 0; i < driver_count; i++) { +diff --git a/ogg123/format.c b/ogg123/format.c +index 8392afd..6e8c449 100644 +--- a/ogg123/format.c ++++ b/ogg123/format.c +@@ -33,24 +33,32 @@ extern format_t speex_format; + extern format_t flac_format; + extern format_t oggflac_format; + #endif + + #ifdef HAVE_LIBSPEEX + extern format_t speex_format; + #endif + ++#ifdef HAVE_LIBOPUSFILE ++extern format_t opus_format; ++#endif ++ ++ + format_t *formats[] = { + #ifdef HAVE_LIBFLAC + &flac_format, + &oggflac_format, + #endif + #ifdef HAVE_LIBSPEEX + &speex_format, + #endif ++#ifdef HAVE_LIBOPUSFILE ++ &opus_format, ++#endif + &oggvorbis_format, + NULL }; + + + format_t *get_format_by_name (char *name) + { + int i = 0; + +diff --git a/ogg123/opus_format.c b/ogg123/opus_format.c +new file mode 100644 +index 0000000..98298e9 +--- /dev/null ++++ b/ogg123/opus_format.c +@@ -0,0 +1,379 @@ ++/******************************************************************** ++ * * ++ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * ++ * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * ++ * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. * ++ * PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * ++ * * ++ * THE Ogg123 SOURCE CODE IS (C) COPYRIGHT 2000-2003 * ++ * by Stan Seibert <volsung@xiph.org> AND OTHER CONTRIBUTORS * ++ * http://www.xiph.org/ * ++ * * ++ ******************************************************************** ++ ++ last mod: $Id: opus_format.c 16825 2010-01-27 04:14:08Z xiphmont $ ++ ++ ********************************************************************/ ++ ++#ifdef HAVE_CONFIG_H ++#include <config.h> ++#endif ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <ctype.h> ++#include <ogg/ogg.h> ++#include <opus/opusfile.h> ++#include "transport.h" ++#include "format.h" ++#include "vorbis_comments.h" ++#include "utf8.h" ++#include "i18n.h" ++ ++typedef struct opf_private_t { ++ OggOpusFile *of; ++ const OpusTags *ot; ++ const OpusHead *oh; ++ int current_section; ++ ++ int bos; /* At beginning of logical bitstream */ ++ ++ decoder_stats_t stats; ++} opf_private_t; ++ ++/* Forward declarations */ ++format_t opus_format; ++OpusFileCallbacks opusfile_callbacks; ++ ++ ++void print_opus_stream_info (decoder_t *decoder); ++void print_opus_comments (const OpusTags *ot, decoder_callbacks_t *cb, ++ void *callback_arg); ++ ++ ++/* ----------------------------------------------------------- */ ++ ++ ++int opf_can_decode (data_source_t *source) ++{ ++ char buf[36]; ++ int len; ++ ++ len = source->transport->peek(source, buf, sizeof(char), 36); ++ ++ if (len >= 32 && memcmp(buf, "OggS", 4) == 0 ++ && memcmp(buf+28, "OpusHead", 8) == 0) /* 3 trailing spaces */ ++ return 1; ++ else ++ return 0; ++} ++ ++ ++decoder_t* opf_init (data_source_t *source, ogg123_options_t *ogg123_opts, ++ audio_format_t *audio_fmt, ++ decoder_callbacks_t *callbacks, void *callback_arg) ++{ ++ decoder_t *decoder; ++ opf_private_t *private; ++ int ret; ++ ++ ++ /* Allocate data source structures */ ++ decoder = malloc(sizeof(decoder_t)); ++ private = malloc(sizeof(opf_private_t)); ++ ++ if (decoder != NULL && private != NULL) { ++ decoder->source = source; ++ decoder->actual_fmt = decoder->request_fmt = *audio_fmt; ++ decoder->format = &opus_format; ++ decoder->callbacks = callbacks; ++ decoder->callback_arg = callback_arg; ++ decoder->private = private; ++ ++ private->bos = 1; ++ private->current_section = -1; ++ ++ private->stats.total_time = 0.0; ++ private->stats.current_time = 0.0; ++ private->stats.instant_bitrate = 0; ++ private->stats.avg_bitrate = 0; ++ ++ } else { ++ fprintf(stderr, _("ERROR: Out of memory.\n")); ++ exit(1); ++ } ++ ++ /* Initialize opusfile decoder */ ++ ++ private->of = op_open_callbacks (decoder, &opusfile_callbacks, NULL, 0, &ret); ++ ++ if (private->of == NULL) { ++ free(private); ++/* free(source); nope. caller frees. */ ++ return NULL; ++ } ++ ++ return decoder; ++} ++ ++ ++int opf_read (decoder_t *decoder, void *ptr, int nbytes, int *eos, ++ audio_format_t *audio_fmt) ++{ ++ opf_private_t *priv = decoder->private; ++ decoder_callbacks_t *cb = decoder->callbacks; ++ int bytes_read = 0; ++ int ret; ++ int old_section; ++ ++ /* Read comments and audio info at the start of a logical bitstream */ ++ if (priv->bos) { ++ priv->ot = op_tags(priv->of, -1); ++ priv->oh = op_head(priv->of, -1); ++ ++ decoder->actual_fmt.channels = priv->oh->channel_count; ++ decoder->actual_fmt.rate = 48000; ++ ++ switch(decoder->actual_fmt.channels){ ++ case 1: ++ decoder->actual_fmt.matrix="M"; ++ break; ++ case 2: ++ decoder->actual_fmt.matrix="L,R"; ++ break; ++ case 3: ++ decoder->actual_fmt.matrix="L,C,R"; ++ break; ++ case 4: ++ decoder->actual_fmt.matrix="L,R,BL,BR"; ++ break; ++ case 5: ++ decoder->actual_fmt.matrix="L,C,R,BL,BR"; ++ break; ++ case 6: ++ decoder->actual_fmt.matrix="L,C,R,BL,BR,LFE"; ++ break; ++ case 7: ++ decoder->actual_fmt.matrix="L,C,R,SL,SR,BC,LFE"; ++ break; ++ case 8: ++ decoder->actual_fmt.matrix="L,C,R,SL,SR,BL,BR,LFE"; ++ break; ++ default: ++ decoder->actual_fmt.matrix=NULL; ++ break; ++ } ++ ++ ++ print_opus_stream_info(decoder); ++ print_opus_comments(priv->ot, cb, decoder->callback_arg); ++ priv->bos = 0; ++ } ++ ++ *audio_fmt = decoder->actual_fmt; ++ ++ /* Attempt to read as much audio as is requested */ ++ while (nbytes >= audio_fmt->word_size * audio_fmt->channels) { ++ ++ old_section = priv->current_section; ++ ret = op_read(priv->of, ptr, nbytes/2, NULL); ++ ++ if (ret == 0) { ++ ++ /* EOF */ ++ *eos = 1; ++ break; ++ ++ } else if (ret == OP_HOLE) { ++ ++ if (cb->printf_error != NULL) ++ cb->printf_error(decoder->callback_arg, INFO, ++ _("--- Hole in the stream; probably harmless\n")); ++ ++ } else if (ret < 0) { ++ ++ if (cb->printf_error != NULL) ++ cb->printf_error(decoder->callback_arg, ERROR, ++ _("=== Vorbis library reported a stream error.\n")); ++ ++ /* EOF */ ++ *eos = 1; ++ break; ++ } else { ++ ++ bytes_read += ret*2*audio_fmt->channels; ++ ptr = (void *)((unsigned char *)ptr + ret*2*audio_fmt->channels); ++ nbytes -= ret*2*audio_fmt->channels; ++ ++ /* did we enter a new logical bitstream? */ ++ if (old_section != priv->current_section && old_section != -1) { ++ ++ *eos = 1; ++ priv->bos = 1; /* Read new headers next time through */ ++ break; ++ } ++ } ++ ++ } ++ ++ return bytes_read; ++} ++ ++ ++int opf_seek (decoder_t *decoder, double offset, int whence) ++{ ++ opf_private_t *priv = decoder->private; ++ int ret; ++ int cur; ++ int samples = offset * 48000; ++ ++ if (whence == DECODER_SEEK_CUR) { ++ cur = op_pcm_tell(priv->of); ++ if (cur >= 0) ++ samples += cur; ++ else ++ return 0; ++ } ++ ++ ret = op_pcm_seek(priv->of, samples); ++ if (ret == 0) ++ return 1; ++ else ++ return 0; ++} ++ ++ ++decoder_stats_t *opf_statistics (decoder_t *decoder) ++{ ++ opf_private_t *priv = decoder->private; ++ long instant_bitrate; ++ long avg_bitrate; ++ ++ /* ov_time_tell() doesn't work on non-seekable streams, so we use ++ ov_pcm_tell() */ ++ priv->stats.total_time = (double) op_pcm_total(priv->of, -1) / ++ (double) decoder->actual_fmt.rate; ++ priv->stats.current_time = (double) op_pcm_tell(priv->of) / ++ (double) decoder->actual_fmt.rate; ++ ++ /* opusfile returns 0 when no bitrate change has occurred */ ++ instant_bitrate = op_bitrate_instant(priv->of); ++ if (instant_bitrate > 0) ++ priv->stats.instant_bitrate = instant_bitrate; ++ ++ avg_bitrate = op_bitrate(priv->of, priv->current_section); ++ /* Catch error case caused by non-seekable stream */ ++ priv->stats.avg_bitrate = avg_bitrate > 0 ? avg_bitrate : 0; ++ ++ ++ return malloc_decoder_stats(&priv->stats); ++} ++ ++ ++void opf_cleanup (decoder_t *decoder) ++{ ++ opf_private_t *priv = decoder->private; ++ ++ op_free(priv->of); ++ ++ free(decoder->private); ++ free(decoder); ++} ++ ++ ++format_t opus_format = { ++ "oggopus", ++ &opf_can_decode, ++ &opf_init, ++ &opf_read, ++ &opf_seek, ++ &opf_statistics, ++ &opf_cleanup, ++}; ++ ++ ++/* ------------------- Opusfile Callbacks ----------------- */ ++ ++int opusfile_cb_read (void *stream, unsigned char *ptr, int nbytes) ++{ ++ decoder_t *decoder = stream; ++ ++ return decoder->source->transport->read(decoder->source, ptr, 1, nbytes); ++} ++ ++int opusfile_cb_seek (void *arg, opus_int64 offset, int whence) ++{ ++ decoder_t *decoder = arg; ++ ++ return decoder->source->transport->seek(decoder->source, offset, whence); ++} ++ ++int opusfile_cb_close (void *arg) ++{ ++ return 1; /* Ignore close request so transport can be closed later */ ++} ++ ++opus_int64 opusfile_cb_tell (void *arg) ++{ ++ decoder_t *decoder = arg; ++ ++ return decoder->source->transport->tell(decoder->source); ++} ++ ++ ++OpusFileCallbacks opusfile_callbacks = { ++ &opusfile_cb_read, ++ &opusfile_cb_seek, ++ &opusfile_cb_tell, ++ &opusfile_cb_close ++}; ++ ++ ++/* ------------------- Private functions -------------------- */ ++ ++ ++void print_opus_stream_info (decoder_t *decoder) ++{ ++ opf_private_t *priv = decoder->private; ++ decoder_callbacks_t *cb = decoder->callbacks; ++ ++ ++ if (cb == NULL || cb->printf_metadata == NULL) ++ return; ++ ++ cb->printf_metadata(decoder->callback_arg, 2, ++ _("Ogg Opus stream: %d channel, 48000 Hz"), ++ priv->oh->channel_count); ++ ++ cb->printf_metadata(decoder->callback_arg, 3, ++ _("Vorbis format: Version %d"), ++ priv->oh->version); ++ ++ cb->printf_metadata(decoder->callback_arg, 3, ++ _("Encoded by: %s"), priv->ot->vendor); ++} ++ ++void print_opus_comments (const OpusTags *ot, decoder_callbacks_t *cb, ++ void *callback_arg) ++{ ++ int i; ++ char *temp = NULL; ++ int temp_len = 0; ++ ++ for (i = 0; i < ot->comments; i++) { ++ ++ /* Gotta null terminate these things */ ++ if (temp_len < ot->comment_lengths[i] + 1) { ++ temp_len = ot->comment_lengths[i] + 1; ++ temp = realloc(temp, sizeof(char) * temp_len); ++ } ++ ++ strncpy(temp, ot->user_comments[i], ot->comment_lengths[i]); ++ temp[ot->comment_lengths[i]] = '\0'; ++ ++ print_vorbis_comment(temp, cb, callback_arg); ++ } ++ ++ free(temp); ++} |