API documentation for libmpg123, libout123, and libsyn123

Note: This API doc is automatically generated from the current development version that you can get via Subversion or as a daily snapshot from http://mpg123.org/snapshot. There may be differences (additions) compared to the latest stable release. See NEWS.libmpg123, NEWS.libout123, NEWS.libsyn123, and the overall NEWS file on libmpg123 versions and important changes between them.
Let me emphasize that the policy for the lib*123 family is to always stay backwards compatible -- only additions are planned (and it's not yet planned to change the plans;-).
feedseek.c
Go to the documentation of this file.
1 /*
2  feedseek: test program for libmpg123, showing how to use fuzzy seeking in feeder mode
3 
4  This is example code only sensible to be considered in the public domain.
5 
6  It takes MPEG data from standard input and feeds that to libmpg123, combined
7  with a fuzzy seek. Libmpg123 could access stdin in other ways directly, but
8  usage of the feeder API is the point here.
9 */
10 
11 #define _POSIX_C_SOURCE 200112L
12 #include <mpg123.h>
13 #include <out123.h>
14 #include <stdlib.h>
15 #include <stdio.h>
16 
17 #define INBUFF 16384 * 2 * 2
23 #define CHECK(cond, ...) if(!(cond)){ fprintf(stderr, __VA_ARGS__); goto bad_end; }
24 
26 int main(int argc, char **argv)
27 {
28  unsigned char buf[INBUFF];
29  mpg123_handle *m = NULL;
30  out123_handle *o = NULL;
31  const char *driver = NULL;
32  char *device = NULL;
33  int ret = 0;
34  off_t inoffset;
35  off_t cur_inoffset;
36  off_t seek_point = 0;
37  off_t seek_target;
38 
39  // 0. Argument parsing.
40 
41  if(argc < 2)
42  {
43  fprintf(stderr, "Usage:\n\n %s <offset> [outfile] < <MPEG input data>\n", argv[0]);
44  fprintf( stderr, "\n"
45  "This will decode standard input to the default audio device or the\n"
46  "given output file as decoded WAV after seeking to the given PCM sample\n"
47  "offset to demonstrate fuzzy seeking\n" );
48  return 1;
49  }
50 
51  seek_point = atol(argv[1]);
52  CHECK(seek_point >= 0, "No negative offset, please.\n")
53 
54  if(argc >= 3)
55  {
56  driver = "wav";
57  device = argv[2];
58  }
59 
60  // 1. Initialize libmpg123 and libout123 handles.
61 
62 #if MPG123_API_VERSION < 46
63  // Newer versions of the library don't need that anymore, but it is safe
64  // to have the no-op call present for compatibility with old versions.
65  mpg123_init();
66 #endif
67 
68  m = mpg123_new(NULL, &ret);
69  CHECK(m != NULL, "Unable to create mpg123 handle: %s\n", mpg123_plain_strerror(ret))
70 
71  o = out123_new();
72  CHECK(o != NULL, "Unable to create out123 handle.\n")
73 
74  ret = out123_open(o, driver, device);
75  CHECK(ret == OUT123_OK, "Failed to open output device: %s\n", out123_strerror(o))
76 
77  mpg123_param(m, MPG123_VERBOSE, 2, 0);
78 
80  CHECK(ret == MPG123_OK, "Unable to set library options: %s\n", mpg123_plain_strerror(ret))
81 
82  // 2. Open the feeder, feed data until libmpg123 can tell us where to go in the input
83  // for the desired output offset.
84 
85  ret = mpg123_open_feed(m);
86  CHECK(ret == MPG123_OK, "Unable open feed: %s\n", mpg123_plain_strerror(ret))
87 
88  fprintf(stderr, "\nDetermining input offset for seek ...\n");
89  /* That condition is tricky... parentheses are crucial... */
90  while( (seek_target = mpg123_feedseek(m, seek_point, SEEK_SET, &inoffset))
91  == MPG123_NEED_MORE )
92  {
93  fprintf(stderr, " *** need more data before deciding on fuzzy input offset ***\n");
94  size_t len = fread(buf, 1, INBUFF, stdin);
95  if(len < 0 || (len == 0 && (feof(stdin) || ferror(stdin))))
96  break;
97  ret = mpg123_feed(m, buf, len);
98  CHECK(ret == MPG123_OK, "Error feeding the decoder: %s", mpg123_strerror(m))
99  }
100  CHECK(ret == MPG123_OK, "Feedseek failed: %s\n", mpg123_strerror(m))
101  fprintf( stderr, "Fuzzy seek to %lld, actually to %lld.\n"
102  , (long long)seek_point, (long long)seek_target );
103  CHECK(inoffset >=0 , "Bogus input offset: %lld\n", (long long)inoffset)
104 
105  // 3. Go to the indicated input offset.
106 
107  fprintf(stderr, "\nSeeking to input offset ...\n");
108  // In a normal file, we would call fseek() here, for stdin, we just consume data.
109  while( (cur_inoffset=ftello(stdin)) < inoffset && !ferror(stdin) )
110  {
111  CHECK(cur_inoffset >= 0, "Cannot tell input position.\n")
112  off_t block = inoffset - cur_inoffset;
113  if(block > INBUFF)
114  block = INBUFF;
115  if(fread(buf, 1, block, stdin) == 0 && feof(stdin))
116  break;
117  }
118  CHECK( ftello(stdin) == inoffset, "Input seeking failed: %lld != %lld\n"
119  , (long long)ftello(stdin), (long long)inoffset )
120 
121  // 4. Feed the decoder from that point on and get the decoded audio.
122 
123  fprintf(stderr, "\nStarting decode...\n");
124  while(1)
125  {
126  size_t len = fread(buf, sizeof(unsigned char), INBUFF, stdin);
127  if(len <= 0)
128  break;
129  ret = mpg123_feed(m, buf, len);
130 
131  while(ret != MPG123_ERR && ret != MPG123_NEED_MORE)
132  {
133  off_t num;
134  unsigned char *audio;
135  size_t bytes;
136  ret = mpg123_decode_frame(m, &num, &audio, &bytes);
137  if(ret == MPG123_NEW_FORMAT)
138  {
139  long rate;
140  int channels, enc;
141  mpg123_getformat(m, &rate, &channels, &enc);
142  fprintf(stderr
143  , "New format: %li Hz, %i channels, encoding value %i\n"
144  , rate, channels, enc );
145  ret = out123_start(o, rate, channels, enc);
146  CHECK(ret == OUT123_OK, "Cannot (re)start audio output with given format.\n")
147  }
148  CHECK(out123_play(o, audio, bytes) == bytes, "Output error: %s", out123_strerror(o))
149  }
150 
151  CHECK(ret != MPG123_ERR, "Error: %s", mpg123_strerror(m))
152  }
153 
154  fprintf(stderr, "Finished\n");
155 
156 good_end: // Everything went fine: go directly to the cleanup section.
157  goto end;
158 bad_end: // Some unspecified error, set error state and clean up.
159  ret = -1;
160 end: // Clean up and return.
161  out123_del(o);
162  mpg123_delete(m);
163  return ret ? EXIT_FAILURE : EXIT_SUCCESS;
164 }
#define INBUFF
Definition: feedseek.c:17
#define CHECK(cond,...)
Definition: feedseek.c:23
int main(int argc, char **argv)
Definition: feedseek.c:26
MPG123_EXPORT const char * mpg123_strerror(mpg123_handle *mh)
MPG123_EXPORT const char * mpg123_plain_strerror(int errcode)
@ MPG123_NEED_MORE
Definition: mpg123.h:469
@ MPG123_ERR
Definition: mpg123.h:470
@ MPG123_NEW_FORMAT
Definition: mpg123.h:468
@ MPG123_OK
Definition: mpg123.h:471
MPG123_EXPORT mpg123_handle * mpg123_new(const char *decoder, int *error)
MPG123_EXPORT void mpg123_delete(mpg123_handle *mh)
struct mpg123_handle_struct mpg123_handle
Definition: mpg123.h:164
MPG123_EXPORT int mpg123_param(mpg123_handle *mh, enum mpg123_parms type, long value, double fvalue)
MPG123_EXPORT int mpg123_init(void)
@ MPG123_FUZZY
Definition: mpg123.h:268
@ MPG123_SEEKBUFFER
Definition: mpg123.h:267
@ MPG123_GAPLESS
Definition: mpg123.h:265
@ MPG123_VERBOSE
Definition: mpg123.h:228
@ MPG123_FLAGS
Definition: mpg123.h:229
MPG123_EXPORT int mpg123_open_feed(mpg123_handle *mh)
MPG123_EXPORT int mpg123_feed(mpg123_handle *mh, const unsigned char *in, size_t size)
MPG123_EXPORT int mpg123_decode_frame(mpg123_handle *mh, off_t *num, unsigned char **audio, size_t *bytes)
MPG123_EXPORT int mpg123_getformat(mpg123_handle *mh, long *rate, int *channels, int *encoding)
MPG123_EXPORT off_t mpg123_feedseek(mpg123_handle *mh, off_t sampleoff, int whence, off_t *input_offset)
MPG123_EXPORT int out123_open(out123_handle *ao, const char *driver, const char *device)
MPG123_EXPORT out123_handle * out123_new(void)
struct out123_struct out123_handle
Definition: out123.h:119
MPG123_EXPORT void out123_del(out123_handle *ao)
MPG123_EXPORT int out123_start(out123_handle *ao, long rate, int channels, int encoding)
MPG123_EXPORT size_t out123_play(out123_handle *ao, void *buffer, size_t bytes)
MPG123_EXPORT const char * out123_strerror(out123_handle *ao)
@ OUT123_OK
Definition: out123.h:230
Hopefully valid HTML! Valid CSS!