1
0
mirror of http://mpg123.de/trunk/.git synced 2025-10-23 16:48:31 +03:00

libmpg123, mpg123: add mpg123_decode_fixed()

git-svn-id: svn://scm.orgis.org/mpg123/trunk@4675 35dc7657-300d-0410-a2e5-dc2837fedb53
This commit is contained in:
thor
2020-05-01 20:06:32 +00:00
parent e5c830c086
commit 8fc60f29f0
16 changed files with 349 additions and 32 deletions

View File

@@ -19,6 +19,7 @@ include_HEADERS =
dist_man_MANS =
CLEANFILES =
TESTS =
XFAIL_TESTS =
check_PROGRAMS =
AM_CPPFLAGS = -DPKGLIBDIR="\"$(pkglibdir)\""

9
NEWS
View File

@@ -45,6 +45,8 @@
-- Reformat audio capabilities table, more condensed, fits into 80 columns.
Forced rate on a separated line.
-- Make --pitch actually work, not just interactive changes.
-- Added --no-frankenstein.
-- Frameflags as long variable, 32 bits are needed since some time now.
- out123:
-- Document --STDOUT, make it more robust regarding fwrite() interruptions.
-- Removed the implicit phase shift that made generated waves exactly at
@@ -94,6 +96,8 @@
also for OUT123_QUIET being effect.
-- Dummy output accepts any encoding now.
- libmpg123:
-- Added mpg123_open_fixed() to ease API for applications that just
want to decode well-behaved local files.
-- The user buffers for audio output data are now declared as void* for
mpg123_read(), mpg123_decode(), and mpg123_replace_buffer() to avoid
the useless need for casting your nice int16_t buffer to unsigned char
@@ -154,6 +158,11 @@
seek index.
-- Eliminated a spots where error messages would still be printed
also for MPG123_QUIET being effect.
-- Added MPG123_NO_FRANKENSTEIN, MPG123_FLOAT_FALLBACK flags.
-- Now actually try floating point encoding if format matrix allows it
(can be disabled by unsetting MPG123_FLOAT_FALLBACK).
-- Added mpg123_feature2() that takes an int, as enums are not ABI-safe,
also added feature queries for floating point output.
1.25.13
-------

View File

@@ -21,6 +21,10 @@ Changes in libmpg123 libtool interface versions...
- included float and >16 bit integer encodings in default
format search
- added MPG123_FLOAT_FALLBACK
- added MPG123_NO_FRANKENSTEIN
- added mpg123_feature2(), added MPG123_FEATURE_OUTPUT_FLOAT32 and
MPG123_FEATURE_OUTPUT_FLOAT32
- added mpg123_open_fixed()
44.0.44
- added mpg123_getformat2()

View File

@@ -61,6 +61,17 @@ With this switch you can make it bail out on data errors
(and perhaps spare your ears a bad time). Note that this switch has been renamed from \-\-resync.
The old name still works, but is not advertised or recommened to use (subject to removal in future).
.TP
.BR \-F ", " \-\^\-no\-frankenstein
Disable support for Frankenstein streams. Normally, mpg123 stays true to the concept of MPEG audio being
just a concatenation of MPEG frames. It will continue decoding even if the type of MPEG frames varies
wildly. With this switch, it will only decode the input as long as it does not change its character
(from layer I to layer III, changing sampling rate, from mono to stereo), silently assuming end of
stream on such occasion. The switch also stops decoding of compatible MPEG frames if there was an
Info frame (Xing header, Lame tag) that contained a length of the track in MPEG frames.
This comes a bit closer to the notion of a MP3 file as a defined collection
of MPEG frames that belong together, but gets rid of the flexibility that can be fun at times but
mostly is hell for the programmer of the parser and decoder ...
.TP
\fB\-\^-resync\-limit \fIbytes\fR
Set number of bytes to search for valid MPEG data once lost in stream; <0 means search whole stream.
If you know there are huge chunks of invalid data in your files... here is your hammer.

View File

@@ -1,6 +1,11 @@
#include "mpg123lib_intern.h"
int mpg123_feature(const enum mpg123_feature_set key)
int attribute_align_arg mpg123_feature2(int key)
{
return mpg123_feature(key);
}
int attribute_align_arg mpg123_feature(const enum mpg123_feature_set key)
{
switch(key)
{
@@ -32,6 +37,20 @@ int mpg123_feature(const enum mpg123_feature_set key)
return 1;
#endif /* mpg123_output_32bit */
case MPG123_FEATURE_OUTPUT_FLOAT32:
#if defined(NO_REAL) || defined(REAL_IS_DOUBLE)
return 0;
#else
return 1;
#endif
case MPG123_FEATURE_OUTPUT_FLOAT64:
#if defined(NO_REAL) || !defined(REAL_IS_DOUBLE)
return 0;
#else
return 1;
#endif
case MPG123_FEATURE_PARSE_ID3V2:
#ifdef NO_ID3V2
return 0;

View File

@@ -1,7 +1,7 @@
/*
lfs_alias: Aliases to the small/native API functions with the size of long int as suffix.
copyright 2010-2013 by the mpg123 project - free software under the terms of the LGPL 2.1
copyright 2010-2020 by the mpg123 project - free software under the terms of the LGPL 2.1
see COPYING and AUTHORS files in distribution or http://mpg123.org
initially written by Thomas Orgis
@@ -100,6 +100,14 @@ EOT
}' < mpg123.h.in
*/
int NATIVE_NAME(mpg123_open_fixed)( mpg123_handle *mh, const char *path
, int channels, int encoding );
int attribute_align_arg ALIAS_NAME(mpg123_open_fixed)( mpg123_handle *mh, const char *path
, int channels, int encoding )
{
return NATIVE_NAME(mpg123_open_fixed)(mh, path, channels, encoding);
}
int NATIVE_NAME(mpg123_open)(mpg123_handle *mh, const char *path);
int attribute_align_arg ALIAS_NAME(mpg123_open)(mpg123_handle *mh, const char *path)
{

View File

@@ -1,7 +1,7 @@
/*
lfs_wrap: Crappy wrapper code for supporting crappy ambiguous large file support.
copyright 2010 by the mpg123 project - free software under the terms of the LGPL 2.1
copyright 2010-2020 by the mpg123 project - free software under the terms of the LGPL 2.1
see COPYING and AUTHORS files in distribution or http://mpg123.org
initially written by Thomas Orgis, thanks to Guido Draheim for consulting
@@ -570,6 +570,7 @@ off_t wrap_lseek(void *handle, off_t offset, int whence)
#undef mpg123_replace_reader
#undef mpg123_replace_reader_handle
#undef mpg123_open
#undef mpg123_open_fixed
#undef mpg123_open_fd
#undef mpg123_open_handle
@@ -698,6 +699,19 @@ int attribute_align_arg mpg123_open(mpg123_handle *mh, const char *path)
else return MPG123_LARGENAME(mpg123_open)(mh, path);
}
// This one needs to follow the logic of the original, and wrap the actual
// mpg123_open() here.
int attribute_align_arg mpg123_open_fixed( mpg123_handle *mh, const char *path
, int channels, int encoding )
{
int err = open_fixed_pre(mh, channels, encoding);
if(err == MPG123_OK)
err = mpg123_open(mh, path);
if(err == MPG123_OK)
err = open_fixed_post(mh, channels, encoding);
return err;
}
/*
This is in fact very similar to the above:
The open routines always need to watch out for a prepared wrapper handle to use replaced normal I/O.

View File

@@ -463,6 +463,54 @@ int attribute_align_arg mpg123_open(mpg123_handle *mh, const char *path)
return open_stream(mh, path, -1);
}
// The convenience function mpg123_open_fixed() wraps over acual mpg123_open
// and hence needs to have the exact same code in lfs_wrap.c. The flesh is
// in open_fixed_pre() and open_fixed_post(), wich are only defined here.
int open_fixed_pre(mpg123_handle *mh, int channels, int encoding)
{
if(!mh)
return MPG123_BAD_HANDLE;
mh->p.flags |= MPG123_NO_FRANKENSTEIN;
int err = mpg123_format_none(mh);
if(err == MPG123_OK)
err = mpg123_format2(mh, 0, channels, encoding);
return err;
}
int open_fixed_post(mpg123_handle *mh, int channels, int encoding)
{
if(!mh)
return MPG123_BAD_HANDLE;
long rate;
int err = mpg123_getformat(mh, &rate, &channels, &encoding);
if(err == MPG123_OK)
err = mpg123_format_none(mh);
if(err == MPG123_OK)
err = mpg123_format(mh, rate, channels, encoding);
if(err == MPG123_OK)
{
if(mh->track_frames < 1 && (mh->rdat.flags & READER_SEEKABLE))
{
debug("open_fixed_post: scan because we can seek and do not know track_frames");
err = mpg123_scan(mh);
}
}
if(err != MPG123_OK)
mpg123_close(mh);
return err;
}
int attribute_align_arg mpg123_open_fixed( mpg123_handle *mh, const char *path
, int channels, int encoding )
{
int err = open_fixed_pre(mh, channels, encoding);
if(err == MPG123_OK)
err = mpg123_open(mh, path);
if(err == MPG123_OK)
err = open_fixed_post(mh, channels, encoding);
return err;
}
int attribute_align_arg mpg123_open_fd(mpg123_handle *mh, int fd)
{
if(mh == NULL) return MPG123_BAD_HANDLE;

View File

@@ -83,6 +83,7 @@ typedef ptrdiff_t ssize_t;
#endif
#define MPG123_LARGENAME(func) MPG123_MACROCAT(func, MPG123_LARGESUFFIX)
#define mpg123_open_fixed MPG123_LARGENAME(mpg123_open_fixed)
#define mpg123_open MPG123_LARGENAME(mpg123_open)
#define mpg123_open_fd MPG123_LARGENAME(mpg123_open_fd)
#define mpg123_open_handle MPG123_LARGENAME(mpg123_open_handle)
@@ -249,6 +250,14 @@ enum mpg123_param_flags
* of libmpg123 which did not enable float automatically at all. If disabled,
* float is considered after the 16 bit default and higher-bit integer encodings
* for any rate. */
,MPG123_NO_FRANKENSTEIN = 0x1000000 /**< Disable support for Frankenstein streams
* (different MPEG streams stiched together). Do not accept serious change of MPEG
* header inside a single stream. With this flag, the audio output format cannot
* change during decoding unless you open a new stream. This also stops decoding
* after an announced end of stream (Info header contained a number of frames
* and this number has been reached). This makes your MP3 files behave more like
* ordinary media files with defined structure, rather than stream dumps with
* some sugar. */
};
/** choices for MPG123_RVA */
@@ -301,6 +310,8 @@ enum mpg123_feature_set
,MPG123_FEATURE_TIMEOUT_READ /**< Reader with timeout (network). */
,MPG123_FEATURE_EQUALIZER /**< tunable equalizer */
,MPG123_FEATURE_MOREINFO /**< more info extraction (for frame analyzer) */
,MPG123_FEATURE_OUTPUT_FLOAT32 /**< 32 bit float output */
,MPG123_FEATURE_OUTPUT_FLOAT64 /**< 64 bit float output (usually never) */
};
/** Query libmpg123 features.
@@ -309,6 +320,17 @@ enum mpg123_feature_set
*/
MPG123_EXPORT int mpg123_feature(const enum mpg123_feature_set key);
/** Query libmpg123 features with better ABI compatibility
*
* This is the same as mpg123_feature(), but this time not using
* the enum as argument. Compilers don't have to agree on the size of
* enums and hence they are not safe in public API.
*
* \param key feature selection
* \return 1 for success, 0 for unimplemented functions
*/
MPG123_EXPORT int mpg123_feature2(int key);
/* @} */
@@ -463,7 +485,12 @@ MPG123_EXPORT const char* mpg123_current_decoder(mpg123_handle *mh);
*
* Functions to get and select the format of the decoded audio.
*
* Before you dive in, please be warned that you might get confused by this. This seems to happen a lot, therefore I am trying to explain in advance.
* Before you dive in, please be warned that you might get confused by this.
* This seems to happen a lot, therefore I am trying to explain in advance.
* If you do feel confused and just want to decode your normal MPEG audio files that
* don't alter properties in the middle, just use mpg123_open_fixed() with a fixed encoding
* and channel count and forget about a matrix of audio formats. If you want to get funky,
* read ahead ...
*
* The mpg123 library decides what output format to use when encountering the first frame in a stream, or actually any frame that is still valid but differs from the frames before in the prompted output format. At such a deciding point, an internal table of allowed encodings, sampling rates and channel setups is consulted. According to this table, an output format is chosen and the decoding engine set up accordingly (including optimized routines for different output formats). This might seem unusual but it just follows from the non-existence of "MPEG audio files" with defined overall properties. There are streams, streams are concatenations of (semi) independent frames. We store streams on disk and call them "MPEG audio files", but that does not change their nature as the decoder is concerned (the LAME/Xing header for gapless decoding makes things interesting again).
*
@@ -587,8 +614,51 @@ MPG123_EXPORT int mpg123_getformat2( mpg123_handle *mh
* @{
*/
/* reading samples / triggering decoding, possible return values: */
/** Enumeration of the error codes returned by libmpg123 functions. */
/** Open a simple MPEG file with fixed properties.
*
* This function shall simplify the common use case of a plain MPEG
* file on disk that you want to decode, with one fixed sample
* rate and channel count, and usually a length defined by a Lame/Info/Xing
* tag. It will:
*
* - set the MPG123_NO_FRANKENSTEIN flag
* - set up format support according to given parameters,
* - open the file,
* - query audio format,
* - fix the audio format support table to ensure the format stays the same,
* - call mpg123_scan() if there is no header frame to tell the track length.
*
* From that on, you can call mpg123_getformat() for querying the sample
* rate (and channel count in case you allowed both) and mpg123_length()
* to get a pretty safe number for the duration.
* Only the sample rate is left open as that indeed is a fixed property of
* MPEG files. You could set MPG123_FORCE_RATE beforehand, but that may trigger
* low-quality resampling in the decoder, only do so if in dire need.
* The library will convert mono files to stereo for you, and vice versa.
* If any constraint cannot be satisified (most likely because of a non-default
* build of libmpg123), you get MPG123_ERR returned and can query the detailed
* cause from the handle. Only on MPG123_OK there will an open file that you
* then close using mpg123_close(), or implicitly on mpg123_delete() or the next
* call to open another file.
*
* So, for your usual CD rip collection, you could use
*
* mpg123_open_fixed(mh, path, MPG123_STEREO, MPG123_ENC_SIGNED_16)
*
* and be happy calling mpg123_getformat() to verify 44100 Hz rate, then just
* playing away with mpg123_read(). The occasional mono file, or MP2 file,
* will also be decoded without you really noticing. Just the speed could be
* wrong if you do not care about sample rate at all.
* \param mh handle
* \param path filesystem path
* \param channels allowed channel count, either 1 (MPG123_MONO) or
* 2 (MPG123_STEREO), or bitwise or of them, but then you're halfway back to
* calling mpg123_format() again;-)
* \param encoding a definite encoding from enum mpg123_enc_enum
* or a bitmask like for mpg123_format(), defeating the purpose somewhat
*/
MPG123_EXPORT int mpg123_open_fixed(mpg123_handle *mh, const char *path
, int channels, int encoding);
/** Open and prepare to decode the specified file by filesystem path.
* This does not open HTTP urls; libmpg123 contains no networking code.
@@ -1036,6 +1106,13 @@ MPG123_EXPORT off_t mpg123_framelength(mpg123_handle *mh);
/** Return, if possible, the full (expected) length of current
* track in samples (PCM frames).
*
* This relies either on an Info frame at the beginning or a previous
* call to mpg123_scan() to get the real number of MPEG frames in a
* file. It will guess based on file size if neither Info frame nor
* scan data are present. In any case, there is no guarantee that the
* decoder will not give you more data, for example in case the open
* file gets appended to during decoding.
* \param mh handle
* \return length >= 0 or MPG123_ERR if there is no length guess possible.
*/

View File

@@ -303,6 +303,9 @@ off_t outblock_bytes(mpg123_handle *fr, off_t s);
/* Postprocessing format conversion of freshly decoded buffer. */
void postprocess_buffer(mpg123_handle *fr);
int open_fixed_pre(mpg123_handle *mh, int channels, int encoding);
int open_fixed_post(mpg123_handle *mh, int channels, int encoding);
/* If networking is enabled and we really mean internal networking, the timeout_read function is available. */
#if defined (NETWORK) && !defined (WANT_WIN32_SOCKETS)
/* Does not work with win32 */

View File

@@ -1,7 +1,7 @@
/*
parse: spawned from common; clustering around stream/frame parsing
copyright ?-2014 by the mpg123 project - free software under the terms of the LGPL 2.1
copyright ?-2020 by the mpg123 project - free software under the terms of the LGPL 2.1
see COPYING and AUTHORS files in distribution or http://mpg123.org
initially written by Michael Hipp & Thomas Orgis
*/
@@ -513,6 +513,20 @@ int read_frame(mpg123_handle *fr)
/* From now on, old frame data is tainted by parsing attempts. */
fr->to_decode = fr->to_ignore = FALSE;
if( fr->p.flags & MPG123_NO_FRANKENSTEIN &&
( (fr->track_frames > 0 && fr->num >= fr->track_frames-1)
#ifdef GAPLESS
|| (fr->gapless_frames > 0 && fr->num >= fr->gapless_frames-1)
#endif
) )
{
mdebug( "stopping parsing at %"OFF_P
" frames as indicated fixed track length"
, (off_p)fr->num+1 );
return 0;
}
read_again:
/* In case we are looping to find a valid frame, discard any buffered data before the current position.
This is essential to prevent endless looping, always going back to the beginning when feeder buffer is exhausted. */
@@ -555,6 +569,16 @@ init_resync:
/* Now we should have our valid header and proceed to reading the frame. */
if(fr->p.flags & MPG123_NO_FRANKENSTEIN)
{
if(fr->firsthead && !head_compatible(fr->firsthead, newhead))
{
mdebug( "stopping before reading frame %"OFF_P
" as its header indicates Frankenstein coming for you", (off_p)fr->num );
return 0;
}
}
/* if filepos is invalid, so is framepos */
framepos = fr->rd->tell(fr) - 4;
/* flip/init buffer for Layer 3 */

View File

@@ -452,7 +452,7 @@ static void realtime_not_compiled(char *arg)
}
#endif
static int frameflag; /* ugly, but that's the way without hacking getlopt */
static long frameflag; /* ugly, but that's the way without hacking getlopt */
static void set_frameflag(char *arg, topt *opts)
{
/* Only one mono flag at a time! */
@@ -464,7 +464,7 @@ static void unset_frameflag(char *arg, topt *opts)
param.flags &= ~frameflag;
}
static int appflag; /* still ugly, but works */
long appflag; /* still ugly, but works */
static void set_appflag(char *arg, topt *opts)
{
param.appflags |= appflag;
@@ -533,23 +533,24 @@ topt opts[] = {
{'c', "check", GLO_INT, 0, &param.checkrange, TRUE},
{'v', "verbose", 0, set_verbose, 0, 0},
{'q', "quiet", 0, set_quiet, 0, 0},
{'y', "no-resync", GLO_INT, set_frameflag, &frameflag, MPG123_NO_RESYNC},
{'y', "no-resync", GLO_LONG, set_frameflag, &frameflag, MPG123_NO_RESYNC},
{'F', "no-frankenstein", GLO_LONG, set_frameflag, &frameflag, MPG123_NO_FRANKENSTEIN},
/* compatibility, no-resync is to be used nowadays */
{0, "resync", GLO_INT, set_frameflag, &frameflag, MPG123_NO_RESYNC},
{'0', "single0", GLO_INT, set_frameflag, &frameflag, MPG123_MONO_LEFT},
{0, "left", GLO_INT, set_frameflag, &frameflag, MPG123_MONO_LEFT},
{'1', "single1", GLO_INT, set_frameflag, &frameflag, MPG123_MONO_RIGHT},
{0, "right", GLO_INT, set_frameflag, &frameflag, MPG123_MONO_RIGHT},
{'m', "singlemix", GLO_INT, set_frameflag, &frameflag, MPG123_MONO_MIX},
{0, "mix", GLO_INT, set_frameflag, &frameflag, MPG123_MONO_MIX},
{0, "mono", GLO_INT, set_frameflag, &frameflag, MPG123_MONO_MIX},
{0, "stereo", GLO_INT, set_frameflag, &frameflag, MPG123_FORCE_STEREO},
{0, "resync", GLO_LONG, set_frameflag, &frameflag, MPG123_NO_RESYNC},
{'0', "single0", GLO_LONG, set_frameflag, &frameflag, MPG123_MONO_LEFT},
{0, "left", GLO_LONG, set_frameflag, &frameflag, MPG123_MONO_LEFT},
{'1', "single1", GLO_LONG, set_frameflag, &frameflag, MPG123_MONO_RIGHT},
{0, "right", GLO_LONG, set_frameflag, &frameflag, MPG123_MONO_RIGHT},
{'m', "singlemix", GLO_LONG, set_frameflag, &frameflag, MPG123_MONO_MIX},
{0, "mix", GLO_LONG, set_frameflag, &frameflag, MPG123_MONO_MIX},
{0, "mono", GLO_LONG, set_frameflag, &frameflag, MPG123_MONO_MIX},
{0, "stereo", GLO_LONG, set_frameflag, &frameflag, MPG123_FORCE_STEREO},
{0, "reopen", GLO_INT, 0, &param.force_reopen, 1},
{'g', "gain", GLO_ARG | GLO_LONG, 0, &param.gain, 0},
{'r', "rate", GLO_ARG | GLO_LONG, 0, &param.force_rate, 0},
{0, "resample", GLO_ARG | GLO_CHAR, set_resample, NULL, 0},
{0, "8bit", GLO_INT, set_frameflag, &frameflag, MPG123_FORCE_8BIT},
{0, "float", GLO_INT, set_frameflag, &frameflag, MPG123_FORCE_FLOAT},
{0, "8bit", GLO_LONG, set_frameflag, &frameflag, MPG123_FORCE_8BIT},
{0, "float", GLO_LONG, set_frameflag, &frameflag, MPG123_FORCE_FLOAT},
{0, "headphones", 0, set_output_h, 0,0},
{0, "speaker", 0, set_output_s, 0,0},
{0, "lineout", 0, set_output_l, 0,0},
@@ -611,14 +612,14 @@ topt opts[] = {
{'w', "wav", GLO_ARG | GLO_CHAR, set_out_wav, 0, 0 },
{0, "cdr", GLO_ARG | GLO_CHAR, set_out_cdr, 0, 0 },
{0, "au", GLO_ARG | GLO_CHAR, set_out_au, 0, 0 },
{0, "gapless", GLO_INT, set_frameflag, &frameflag, MPG123_GAPLESS},
{0, "no-gapless", GLO_INT, unset_frameflag, &frameflag, MPG123_GAPLESS},
{0, "no-infoframe", GLO_INT, set_frameflag, &frameflag, MPG123_IGNORE_INFOFRAME},
{0, "gapless", GLO_LONG, set_frameflag, &frameflag, MPG123_GAPLESS},
{0, "no-gapless", GLO_LONG, unset_frameflag, &frameflag, MPG123_GAPLESS},
{0, "no-infoframe", GLO_LONG, set_frameflag, &frameflag, MPG123_IGNORE_INFOFRAME},
{'?', "help", 0, want_usage, 0, 0 },
{0 , "longhelp" , 0, want_long_usage, 0, 0 },
{0 , "version" , 0, give_version, 0, 0 },
{'l', "listentry", GLO_ARG | GLO_LONG, 0, &param.listentry, 0 },
{0, "continue", GLO_INT, set_appflag, &appflag, MPG123APP_CONTINUE },
{0, "continue", GLO_LONG, set_appflag, &appflag, MPG123APP_CONTINUE },
{0, "rva-mix", GLO_INT, 0, &param.rva, 1 },
{0, "rva-radio", GLO_INT, 0, &param.rva, 1 },
{0, "rva-album", GLO_INT, 0, &param.rva, 2 },
@@ -635,20 +636,20 @@ topt opts[] = {
{0, "resync-limit", GLO_ARG | GLO_LONG, 0, &param.resync_limit, 0},
{0, "pitch", GLO_ARG|GLO_DOUBLE, 0, &param.pitch, 0},
#ifdef NETWORK
{0, "ignore-mime", GLO_INT, set_appflag, &appflag, MPG123APP_IGNORE_MIME },
{0, "ignore-mime", GLO_LONG, set_appflag, &appflag, MPG123APP_IGNORE_MIME },
#endif
{0, "lyrics", GLO_INT, set_appflag, &appflag, MPG123APP_LYRICS},
{0, "lyrics", GLO_LONG, set_appflag, &appflag, MPG123APP_LYRICS},
{0, "keep-open", GLO_INT, 0, &param.keep_open, 1},
{0, "utf8", GLO_INT, 0, &param.force_utf8, 1},
{0, "fuzzy", GLO_INT, set_frameflag, &frameflag, MPG123_FUZZY},
{0, "fuzzy", GLO_LONG, set_frameflag, &frameflag, MPG123_FUZZY},
{0, "index-size", GLO_ARG|GLO_LONG, 0, &param.index_size, 0},
{0, "no-seekbuffer", GLO_INT, unset_frameflag, &frameflag, MPG123_SEEKBUFFER},
{0, "no-seekbuffer", GLO_LONG, unset_frameflag, &frameflag, MPG123_SEEKBUFFER},
{'e', "encoding", GLO_ARG|GLO_CHAR, 0, &param.force_encoding, 0},
{0, "preframes", GLO_ARG|GLO_LONG, 0, &param.preframes, 0},
{0, "skip-id3v2", GLO_INT, set_frameflag, &frameflag, MPG123_SKIP_ID3V2},
{0, "skip-id3v2", GLO_LONG, set_frameflag, &frameflag, MPG123_SKIP_ID3V2},
{0, "streamdump", GLO_ARG|GLO_CHAR, 0, &param.streamdump, 0},
{0, "icy-interval", GLO_ARG|GLO_LONG, 0, &param.icy_interval, 0},
{0, "ignore-streamlength", GLO_INT, set_frameflag, &frameflag, MPG123_IGNORE_STREAMLENGTH},
{0, "ignore-streamlength", GLO_LONG, set_frameflag, &frameflag, MPG123_IGNORE_STREAMLENGTH},
{0, "name", GLO_ARG|GLO_CHAR, 0, &param.name, 0},
{0, "devbuffer", GLO_ARG|GLO_DOUBLE, 0, &param.device_buffer, 0},
{0, 0, 0, 0, 0, 0}
@@ -1581,6 +1582,7 @@ static void long_usage(int err)
fprintf(o," -n --frames <n> play only <n> frames of every stream\n");
fprintf(o," --fuzzy Enable fuzzy seeks (guessing byte offsets or using approximate seek points from Xing TOC)\n");
fprintf(o," -y --no-resync DISABLES resync on error (--resync is deprecated)\n");
fprintf(o," -F --no-frankenstein disable support for Frankenstein streams\n");
#ifdef NETWORK
fprintf(o," -p <f> --proxy <f> set WWW proxy\n");
fprintf(o," -u --auth set auth values for HTTP access\n");

View File

@@ -91,7 +91,7 @@ struct parameter
long start_frame; /* frame offset to begin with */
long frame_number; /* number of frames to decode */
long outscale;
int flags;
long flags;
long force_rate;
int resample;
int talk_icy;

View File

@@ -1,18 +1,25 @@
# Module for non-recursive mpg123 build system.
TESTS += \
src/tests/decode_fixed.sh \
src/tests/seek_whence.sh \
src/tests/seek_accuracy.sh \
src/tests/text \
src/tests/textprint
if NO_16_BIT
XFAIL_TESTS += src/tests/decode_fixed.sh
endif
# Why do I have to repeat the test scripts here?
EXTRA_DIST += \
src/tests/decode_fixed.sh \
src/tests/seek_whence.sh \
src/tests/seek_accuracy.sh \
src/tests/sweep.mp3
check_PROGRAMS += \
src/tests/decode_fixed \
src/tests/seek_whence \
src/tests/seek_accuracy \
src/tests/text \
@@ -20,6 +27,7 @@ check_PROGRAMS += \
EXTRA_PROGRAMS += \
src/tests/volume \
src/tests/decode_fixed \
src/tests/seek_whence \
src/tests/seek_accuracy \
src/tests/noise \
@@ -31,6 +39,12 @@ src_tests_volume_SOURCES = \
src_tests_volume_LDADD = \
src/libsyn123/libsyn123.la
src_tests_decode_fixed_SOURCES = \
src/tests/decode_fixed.c
src_tests_decode_fixed_LDADD = \
src/compat/libcompat.la \
src/libmpg123/libmpg123.la
src_tests_seek_whence_SOURCES = \
src/tests/seek_whence.c
src_tests_seek_whence_LDADD = \

61
src/tests/decode_fixed.c Normal file
View File

@@ -0,0 +1,61 @@
#include "compat.h"
#include <mpg123.h>
#include "debug.h"
int work(mpg123_handle *mh, int ch, int enc)
{
int16_t buffer[16348];
long rate;
int channels, encoding;
if(mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK)
return 1;
if(channels != ch || encoding != enc)
{
error("channel/encoding mismatch");
return 1;
}
fprintf(stderr, "openend fixed track with %ld %d %d\n"
, rate, channels, encoding );
int ret;
size_t done;
while( (ret=mpg123_read(mh, buffer, sizeof(buffer), &done)) == MPG123_OK)
{
if(!done)
continue;
fprintf(stderr, "Got first sample %d and last sample %d out of %zu\n"
, buffer[0], buffer[done/sizeof(*buffer)-1], done/sizeof(*buffer) );
unintr_write(STDOUT_FILENO, buffer, done);
}
if(ret != MPG123_DONE)
{
merror( "wrong mpg123_read() return value %d (%s, %s)"
, ret, mpg123_plain_strerror(ret), mpg123_strerror(mh) );
return 1;
} else
return 0;
}
int main(int argc, char **argv)
{
int ret = 1;
int enc = MPG123_ENC_SIGNED_16;
if(!mpg123_feature2(MPG123_FEATURE_OUTPUT_16BIT))
{
error("Libmpg123 doesn't do 16 bit output, cannot test.");
return 1;
}
if(argc < 2)
{
printf("Gimme a MPEG file name...\n");
return 0;
}
mpg123_init();
// Intentionally no error checking here. Let's see how the lib deals with it.
mpg123_handle *mh = mpg123_new(NULL, NULL);
// Let's fix it to mono.
if(mpg123_open_fixed(mh, argv[1], MPG123_MONO, enc) == MPG123_OK)
ret = work(mh, 1, enc);
mpg123_delete(mh);
return ret;
}

22
src/tests/decode_fixed.sh Executable file
View File

@@ -0,0 +1,22 @@
#!/bin/sh
set -e
set -x
sweep="$srcdir/src/tests/sweep.mp3"
sweepsweep="src/tests/sweepsweep.mp3"
stripsweep="src/tests/stripsweep.mp3"
echo "Test successful decoding as such:"
c1=$(src/tests/decode_fixed "$sweep" | wc -c)
echo "Test that track is decoded only once:"
cat "$sweep" "$sweep" > "$sweepsweep"
c2=$(src/tests/decode_fixed "$sweepsweep" | wc -c)
test "$c1" = "$c2"
echo "Test that stripped track is decoded twice:"
src/mpg123-strip -n < "$sweepsweep" > "$stripsweep"
c3=$(src/tests/decode_fixed "$stripsweep" | wc -c)
# Needs to be even larger as gapless info vanished.
test "$c3" -gt "$(($c2*2))"
echo PASS