source: roaraudio/roard/codecfilter_vorbis.c @ 5823:f9f70dbaa376

Last change on this file since 5823:f9f70dbaa376 was 5823:f9f70dbaa376, checked in by phi, 11 years ago

updated copyright

File size: 16.5 KB
RevLine 
[204]1//codecfilter_vorbis.c:
2
[668]3/*
[5823]4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2013
[668]5 *
6 *  This file is part of roard a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  RoarAudio is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
[3517]21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
[668]23 *
24 */
25
[1185]26#define ROAR_REQUIRE_LIBVORBISFILE
27
[204]28#include "roard.h"
29
[362]30#ifdef ROAR_HAVE_LIBVORBISFILE
31
[2107]32#define FIFAC ((float)((uint64_t)1<<(ROAR_VORBIS_BITS-1)))
33
[741]34int _g_cf_vorbis_vfvio_return_err (void) {
35 return -1;
36}
37
38ov_callbacks _g_cf_vorbis_vfvio = {
39  .read_func  = cf_vorbis_vfvio_read,
[743]40  .seek_func  = (int    (*)(void *, ogg_int64_t, int      )) _g_cf_vorbis_vfvio_return_err,
41  .close_func = (int    (*)(void *                        )) _g_cf_vorbis_vfvio_return_err,
42  .tell_func  = (long   (*)(void *                        )) _g_cf_vorbis_vfvio_return_err
[741]43};
44
45size_t cf_vorbis_vfvio_read (void *ptr, size_t size, size_t nmemb, void *datasource) {
46 ssize_t r;
[746]47
[741]48 r = stream_vio_s_read(ROAR_STREAM_SERVER(datasource), ptr, size*nmemb);
49
[5651]50 ROAR_DBG("cf_vorbis_vfvio_read(ptr=%p, size=%lu, nmemb=%lu, datasource=%p): r=%i", ptr, (unsigned long int)size, (unsigned long int)nmemb, datasource, r);
[741]51
[4987]52 if ( r == -1 ) {
[5651]53  ROAR_DBG("cf_vorbis_vfvio_read(ptr=%p, size=%lu, nmemb=%lu, datasource=%p) = 0 // roar_error=%i(%s)", ptr, (unsigned long int)size, (unsigned long int)nmemb, datasource, roar_error, roar_error2str(roar_error));
[741]54  return 0;
[4987]55 }
[741]56
[5218]57 if ( r > 0 ) {
58  roar_err_clear_all();
59 }
[744]60
61 r /= size;
[741]62 
[5651]63 ROAR_DBG("cf_vorbis_vfvio_read(ptr=%p, size=%lu, nmemb=%lu, datasource=%p) = %i", ptr, (unsigned long int)size, (unsigned long int)nmemb, datasource, r);
[744]64 return r;
[741]65}
66
[205]67int cf_vorbis_open(CODECFILTER_USERDATA_T * inst, int codec,
68                                            struct roar_stream_server * info,
69                                            struct roar_codecfilter   * filter) {
[4822]70 struct codecfilter_vorbis_inst * self = roar_mm_malloc(sizeof(struct codecfilter_vorbis_inst));
[569]71 struct roar_stream * s = ROAR_STREAM(info);
[205]72
[5270]73 (void)codec, (void)filter;
74
75 if ( self == NULL )
[205]76  return -1;
77
78 self->current_section      = -1;
79 self->last_section         = -1;
[382]80 self->opened               =  0;
81 self->got_it_running       =  0;
[205]82 self->stream               = info;
83// self->outlen               = ROAR_OUTPUT_BUFFER_SAMPLES * s->info.channels * s->info.bits / 8; // optimal size
[569]84#ifdef ROAR_HAVE_LIBVORBISENC
[1226]85 self->encoding               = 0;
86 self->encoder.v_base_quality = 0.3;
[1238]87 self->encoder.srn            = -1;
[569]88#endif
[205]89
[486]90 ROAR_DBG("cf_vorbis_open(*): info->id=%i", ROAR_STREAM(info)->id);
91
[205]92 *inst = (CODECFILTER_USERDATA_T) self;
93
[4765]94#if ROAR_CODEC_DEFAULT == ROAR_CODEC_PCM_S_LE
95 self->bigendianp = 0;
[569]96 s->info.codec = ROAR_CODEC_DEFAULT;
[4765]97#else
98 self->bigendianp = 1;
99 s->info.codec = ROAR_CODEC_PCM_S_BE; // force because ROAR_CODEC_DEFAULT can be something non-BE, too.
100#endif
101
[569]102 s->info.bits  = 16;
103
104 if ( s->dir == ROAR_DIR_PLAY ) {
105  return 0;
[634]106 } else if ( s->dir == ROAR_DIR_MONITOR || s->dir == ROAR_DIR_OUTPUT ) {
[569]107#ifdef ROAR_HAVE_LIBVORBISENC
108  // set up the encoder here
[2087]109// this is delayed to the write function
110/*
[1226]111 if ( cf_vorbis_encode_start(self) == -1 ) {
[4822]112  roar_mm_free(self);
[1226]113  return -1;
114 }
[2087]115*/
[2107]116 s->info.bits  = ROAR_VORBIS_BITS;
[569]117#else
[4822]118 roar_mm_free(self);
[569]119 return -1;
120#endif
121 } else {
[4822]122  roar_mm_free(self);
[569]123  return -1;
124 }
[206]125
126 return 0;
[205]127}
128
129int cf_vorbis_close(CODECFILTER_USERDATA_T   inst) {
130 struct codecfilter_vorbis_inst * self = (struct codecfilter_vorbis_inst *) inst;
131
[4822]132 if ( self == NULL )
[205]133  return -1;
134
[382]135 if ( self->got_it_running )
136  ov_clear(&(self->vf));
[205]137
[569]138#ifdef ROAR_HAVE_LIBVORBISENC
139 if ( self->encoding ) {
[1226]140  cf_vorbis_encode_end(self);
[569]141 }
142#endif
143
[4822]144 roar_mm_free(self);
[206]145 return 0;
[205]146}
147
[582]148int cf_vorbis_write(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
149#ifdef ROAR_HAVE_LIBVORBISENC
150 struct codecfilter_vorbis_inst * self = (struct codecfilter_vorbis_inst *) inst;
151 struct roar_stream * s = ROAR_STREAM(self->stream);
152 ogg_packet header;
153 ogg_packet header_comm;
154 ogg_packet header_code;
[586]155 float ** encbuf;
156 int i, c;
157 int chans;
158 int end;
[2816]159 int sid;
160 void * prethrubuf;
[2107]161#if ROAR_VORBIS_BITS == 8
162 int8_t  * data = (int8_t  *) buf;
163#elif ROAR_VORBIS_BITS == 16
[586]164 int16_t * data = (int16_t *) buf;
[2107]165#elif ROAR_VORBIS_BITS == 32
166 int32_t * data = (int32_t *) buf;
167#else
168#error value of ROAR_VORBIS_BITS not supported
169#endif
[582]170
[584]171 if ( ! self->opened ) {
[2087]172  if ( !self->encoding ) {
173   if ( cf_vorbis_encode_start(self) == -1 ) {
174    return -1;
175   }
176  }
177
[2816]178  sid = ROAR_STREAM(self->stream)->id;
179
[582]180  vorbis_analysis_headerout(&(self->encoder.vd), &(self->encoder.vc), &header, &header_comm, &header_code);
181
182  ogg_stream_packetin(&(self->encoder.os), &header);
183  ogg_stream_packetin(&(self->encoder.os), &header_comm);
184  ogg_stream_packetin(&(self->encoder.os), &header_code);
185
[2816]186  stream_prethru_destroy(sid);
187
[582]188  while (ogg_stream_flush(&(self->encoder.os), &(self->encoder.og))) {
[598]189   if ( stream_vio_s_write(self->stream, self->encoder.og.header, self->encoder.og.header_len)
190                                                                 != self->encoder.og.header_len ||
191        stream_vio_s_write(self->stream, self->encoder.og.body,   self->encoder.og.body_len  )
192                                                                 != self->encoder.og.body_len     ) {
[4822]193    roar_mm_free(self); // TODO: do we need addional cleanup?
[582]194    return -1;
195   }
[2816]196   // we ignore errors at the moment...
197   if ( stream_prethru_add_data(sid, &prethrubuf, self->encoder.og.header_len + self->encoder.og.body_len) != -1 ) {
198    memcpy(prethrubuf,                               self->encoder.og.header, self->encoder.og.header_len);
199    memcpy(prethrubuf + self->encoder.og.header_len, self->encoder.og.body,   self->encoder.og.body_len  );
200   }
[582]201  }
[584]202  self->opened = 1;
[586]203 } else {
204  encbuf = vorbis_analysis_buffer(&(self->encoder.vd), len /* TODO: need to lookup the menaing of this */);
205  chans  = s->info.channels;
[2107]206  end    = len*8/(ROAR_VORBIS_BITS*chans);
[586]207
208  if ( chans == 1 ) { // use optimized code
209   for (i = 0; i < end; i++)
[2107]210    encbuf[0][i] = data[i]/FIFAC;
[586]211
212  } else if ( chans == 2 ) { // use optimized code
213   for (i = 0; i < end; i++) {
[2107]214    encbuf[0][i] = data[2*i  ]/FIFAC;
215    encbuf[1][i] = data[2*i+1]/FIFAC;
[586]216   }
217  } else { // use generic multi channel code
218   for (i = 0; i < end; i++) {
219    for (c = 0; c < chans; c++) {
[2107]220     encbuf[c][i] = data[chans*i+c]/FIFAC;
[586]221    }
222   }
223  }
[587]224
225  vorbis_analysis_wrote(&(self->encoder.vd), i);
226
[1238]227  if ( cf_vorbis_encode_flushout(self) == -1 )
228   return -1;
[584]229 }
[582]230
231  return len; // we assume every thing was written (at least into our dsp anaylises buffer
232#else
[5218]233 roar_err_set(ROAR_ERROR_NOSYS);
234 roar_err_to_errno();
[582]235 return -1;
236#endif
237}
[205]238int cf_vorbis_read(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
239 struct codecfilter_vorbis_inst * self = (struct codecfilter_vorbis_inst *) inst;
240 long r;
[206]241 long todo = len;
242 long done = 0;
[4987]243 int ret;
[205]244
[4987]245 ROAR_DBG("cf_vorbis_read(inst=%p, buf=%p, len=%i) = ?", inst, buf, len);
[206]246
247 self->opened++;
248 if ( self->opened == 16 ) {
[744]249
[4987]250  ROAR_DBG("cf_vorbis_read(*): opening...");
251  if ( (ret = ov_open_callbacks((void*)self->stream, &(self->vf), NULL, 0, _g_cf_vorbis_vfvio)) < 0 ) {
252   ROAR_DBG("cf_vorbis_read(*): ret=%i", ret);
253   ROAR_DBG("cf_vorbis_read(*) = 0");
[206]254   return 0;
[205]255  }
[4987]256
257  ROAR_DBG("cf_vorbis_read(*) = -1 // errno=EAGAIN");
[5218]258  roar_err_set(ROAR_ERROR_AGAIN);
259  roar_err_to_errno();
[742]260  return -1;
[205]261 }
[206]262
263 if ( self->opened < 16 ) {
[4987]264  ROAR_DBG("cf_vorbis_read(*) = -1 // errno=EAGAIN");
[5218]265  roar_err_set(ROAR_ERROR_AGAIN);
266  roar_err_to_errno();
[206]267  return -1;
268 }
[205]269
[382]270
271 self->got_it_running = 1;
272
[206]273 while (todo) {
[4765]274  r = ov_read(&(self->vf), buf+done, todo, self->bigendianp, 2, 1, &(self->current_section));
[4987]275  ROAR_DBG("cf_vorbis_read(*): r=%li", r);
[744]276  if ( r == OV_HOLE ) {
[745]277   ROAR_DBG("cf_vorbis_read(*): Hole in stream");
[744]278  } else if ( r < 1 ) {
[206]279   break;
280  } else {
[207]281   if ( self->last_section != self->current_section )
282    if ( cf_vorbis_update_stream(self) == -1 )
283     return 0;
284
285   self->last_section = self->current_section;
[206]286   todo -= r;
287   done += r;
288  }
289 }
[205]290
[5651]291 ROAR_DBG("ov_read(*) = %li", (long int)done);
[206]292
293 if ( done == 0 ) {
[205]294  // do some EOF handling...
[206]295  return 0;
[205]296 } else {
[206]297  return len;
[205]298 }
299}
300
[207]301int cf_vorbis_update_stream (struct codecfilter_vorbis_inst * self) {
[1493]302#ifdef ROAR_SUPPORT_META
[207]303 vorbis_info *vi = ov_info(&(self->vf), -1);
304 char **ptr = ov_comment(&(self->vf), -1)->user_comments;
[716]305 char key[ROAR_META_MAX_NAMELEN] = {0}, value[LIBROAR_BUFFER_MSGDATA] = {0};
[583]306 struct roar_stream * s = ROAR_STREAM(self->stream);
[5624]307 struct roar_stream_rpg rpg;
[207]308 int type;
309 int j, h = 0;
[5624]310 float rpg_track = 0, rpg_album = 0, rpg_final;
[716]311 int meta_ok;
[207]312
313 s->info.channels = vi->channels;
314 s->info.rate     = vi->rate;
315 s->info.bits     = 16;
[4765]316#if ROAR_CODEC_DEFAULT == ROAR_CODEC_PCM_S_LE
[207]317 s->info.codec    = ROAR_CODEC_DEFAULT;
[4765]318#else
319 s->info.codec    = ROAR_CODEC_PCM_S_BE;
320#endif
[207]321
322 stream_meta_clear(s->id);
323
324 while(*ptr){
[716]325  meta_ok = 1;
[207]326
[716]327   for (j = 0; (*ptr)[j] != 0 && (*ptr)[j] != '='; j++) {
328    if ( j == ROAR_META_MAX_NAMELEN ) {
329     ROAR_ERR("cf_vorbis_update_stream(*): invalid meta data on stream %i: meta data key too long", s->id);
330     meta_ok = 0;
331     j = 0;
332     break;
333    }
334    key[j] = (*ptr)[j];
335   }
336   key[j] = 0;
[222]337
[716]338   if ( meta_ok ) {
339    for (j++, h = 0; (*ptr)[j] != 0 && (*ptr)[j] != '='; j++) {
340     if ( h == LIBROAR_BUFFER_MSGDATA ) {
341      ROAR_ERR("update_stream(*): invalid meta data on stream %i: meta data value for key '%s' too long", s->id, key);
[717]342      meta_ok = 0;
[716]343      h = 0;
344      break;
345     }
346     value[h++] = (*ptr)[j];
347    }
348    value[h]   = 0;
[222]349   }
350
[716]351   if ( meta_ok ) {
352    type = roar_meta_inttype(key);
353    if ( type != -1 )
354     stream_meta_set(s->id, type, "", value);
355
356    ROAR_DBG("cf_vorbis_update_stream(*): Meta %-16s: %s", key, value);
357
358    if ( strcmp(key, "REPLAYGAIN_TRACK_PEAK") == 0 ) {
359     rpg_track = 1/atof(value);
360/*
361    } else if ( strcmp(key, "REPLAYGAIN_TRACK_GAIN") == 0 ) {
362     rpg_track = powf(10, atof(value)/20);
363*/
364    } else if ( strcmp(key, "REPLAYGAIN_ALBUM_PEAK") == 0 ) {
365     rpg_album = 1/atof(value);
366/*
367    } else if ( strcmp(key, "REPLAYGAIN_ALBUM_GAIN") == 0 ) {
368     rpg_album = powf(10, atof(value)/20);
369*/
370    }
371   }
372
373   ptr++;
[207]374 }
375
[5624]376 if ( streams_get_rpg(ROAR_STREAM(self->stream)->id, &rpg) != -1 ) {
377  rpg_final = 0;
378
379  switch (rpg.mode) {
380   case ROAR_RPGMODE_NONE: rpg_final =  0.; break;
381   case ROAR_RPGMODE_USER: rpg_final = -1.; break;
382   case ROAR_RPGMODE_ALBUM: rpg_final = rpg_album; break;
383   case ROAR_RPGMODE_TRACK: rpg_final = rpg_track; break;
384   case ROAR_RPGMODE_ALBUMTRACK: rpg_final = rpg_album ? rpg_album : rpg_track; break;
385   case ROAR_RPGMODE_TRACKALBUM: rpg_final = rpg_track ? rpg_track : rpg_album; break;
386  }
387
388  if ( rpg_final > 0 ) {
389   self->stream->mixer.rpg_div = 2718;
390   self->stream->mixer.rpg_mul = (float)rpg_final*2718;
391  } else if ( !rpg_final ) {
392   self->stream->mixer.rpg_div = 1;
393   self->stream->mixer.rpg_mul = 1;
394  }
[222]395 }
396
[1041]397 stream_meta_finalize(s->id);
[1493]398#endif
[223]399 //printf("RPG: mul=%i, div=%i\n", self->stream->mixer.rpg_mul, self->stream->mixer.rpg_div);
[207]400 return 0;
401}
402
[1226]403int cf_vorbis_encode_start  (struct codecfilter_vorbis_inst * self) {
404#ifdef ROAR_HAVE_LIBVORBISENC
[1238]405 int srn = self->encoder.srn; // this value is allrady inited...
[1493]406#ifdef ROAR_SUPPORT_META
[1238]407 int len = 0;
408 int i;
409 int types[ROAR_META_MAX_PER_STREAM];
[1493]410#endif
[1238]411 int sid = ROAR_STREAM(self->stream)->id;
[2087]412 float v_base_quality = self->encoder.v_base_quality;
[1238]413 char val[LIBROAR_BUFFER_MSGDATA];
414
415  val[LIBROAR_BUFFER_MSGDATA-1] = 0;
416
[1226]417  memset(&(self->encoder), 0, sizeof(self->encoder));
418
419  self->encoding = 1;
[2087]420  self->encoder.srn = srn + 1;
421  self->encoder.v_base_quality = v_base_quality;
[1226]422
423  vorbis_info_init(&(self->encoder.vi));
424  vorbis_comment_init(&(self->encoder.vc));
425  vorbis_comment_add_tag(&(self->encoder.vc), "SERVER", "RoarAudio");
426  vorbis_comment_add_tag(&(self->encoder.vc), "ENCODER", "RoarAudio Vorbis codecfilter");
427
[1493]428#ifdef ROAR_SUPPORT_META
[1238]429  if ( (len = stream_meta_list(sid, types, ROAR_META_MAX_PER_STREAM)) != -1 ) {
430   for (i = 0; i < len; i++) {
431//int stream_meta_get     (int id, int type, char * name, char * val, size_t len);
432    if ( stream_meta_get(sid, types[i], NULL, val, LIBROAR_BUFFER_MSGDATA-1) == 0 )
[5625]433     vorbis_comment_add_tag(&(self->encoder.vc), (char * /* remove this later, it has been fixed upstream */)roar_meta_strtype(types[i]), val);
[1238]434   }
435  }
[1493]436#endif
[1238]437
[2087]438  ROAR_DBG("cf_vorbis_encode_start(*): q=%f", v_base_quality);
439
[1226]440  if( vorbis_encode_init_vbr(&(self->encoder.vi), (long) ROAR_STREAM(self->stream)->info.channels,
441                                                  (long) ROAR_STREAM(self->stream)->info.rate,
[2087]442                                                  v_base_quality) != 0 ) {
[1226]443   ROAR_ERR("cf_vorbis_encode_start(*): Can not vorbis_encode_init_vbr(*)!");
444   vorbis_info_clear(&(self->encoder.vi)); // TODO: do we need to free vc also?
445   return -1;
446  }
447
448  vorbis_analysis_init(&(self->encoder.vd), &(self->encoder.vi));
449  vorbis_block_init(&(self->encoder.vd), &(self->encoder.vb));
[362]450
[1239]451  ROAR_DBG("cf_vorbis_encode_start(*): srn=%i", self->encoder.srn);
[1226]452                                     //  "RA"<<16 + PID<<8 + Stream ID
[1238]453  ogg_stream_init(&(self->encoder.os),
[1239]454                   (((0x5241 + self->encoder.srn) & 0xffff)<<16) +
455                   ( (getpid()                    & 0x00ff)<< 8) +
456                   (  sid                         & 0x00ff));
[1226]457 return 0;
458#else
459 return -1;
460#endif
461}
462
463int cf_vorbis_encode_end    (struct codecfilter_vorbis_inst * self) {
464#ifdef ROAR_HAVE_LIBVORBISENC
465 if ( self->encoding ) {
[1238]466  // try to flush up to an EOS page...
467  vorbis_analysis_buffer(&(self->encoder.vd), 2*ROAR_MAX_CHANNELS);
468  vorbis_analysis_wrote(&(self->encoder.vd), 0);
469  cf_vorbis_encode_flushout(self);
470
471  // clean up...
[1226]472  ogg_stream_clear(&(self->encoder.os));
473  vorbis_block_clear(&(self->encoder.vb));
474  vorbis_dsp_clear(&(self->encoder.vd));
475  vorbis_info_clear(&(self->encoder.vi));
476  self->opened = 0;
477 }
478
479 return 0;
480#else
481 return -1;
482#endif
483}
484
[1238]485int cf_vorbis_encode_flushout(struct codecfilter_vorbis_inst * self) {
486#ifdef ROAR_HAVE_LIBVORBISENC
487 while ( vorbis_analysis_blockout(&(self->encoder.vd), &(self->encoder.vb)) == 1 ) {
488  vorbis_analysis(&(self->encoder.vb), &(self->encoder.op));
489  vorbis_bitrate_addblock(&(self->encoder.vb));
490
491  while ( vorbis_bitrate_flushpacket(&(self->encoder.vd), &(self->encoder.op)) ) {
492   ogg_stream_packetin(&(self->encoder.os), &(self->encoder.op));
493
494   while( ogg_stream_pageout(&(self->encoder.os), &(self->encoder.og)) ) {
495    if (
496         stream_vio_s_write(self->stream, self->encoder.og.header, self->encoder.og.header_len) == -1 ||
497         stream_vio_s_write(self->stream, self->encoder.og.body,   self->encoder.og.body_len  ) == -1   ) {
498     return -1;
499    }
500   }
501  }
502 }
503
504 return 0;
505#else
506 return -1;
507#endif
508}
509
510int cf_vorbis_ctl(CODECFILTER_USERDATA_T   inst, int cmd, void * data) {
511 struct codecfilter_vorbis_inst * self = (struct codecfilter_vorbis_inst *) inst;
[2084]512 int_least32_t type = cmd & ROAR_STREAM_CTL_TYPEMASK;
513
514 cmd -= type;
[1238]515
516 switch (cmd) {
517  case ROAR_CODECFILTER_CTL2CMD(ROAR_CODECFILTER_CTL_META_UPDATE):
[2084]518    if ( type != ROAR_STREAM_CTL_TYPE_VOID )
519     return -1;
520
[1239]521    ROAR_DBG("cf_vorbis_ctl(*): stoping stream...");
[1238]522    if ( cf_vorbis_encode_end(self) == -1 )
523     return -1;
[1239]524    ROAR_DBG("cf_vorbis_ctl(*): restarting stream...");
[1238]525    if ( cf_vorbis_encode_start(self) == -1 )
526     return -1;
527
528    return 0;
529   break;
[2084]530  case ROAR_CODECFILTER_CTL2CMD(ROAR_CODECFILTER_CTL_SET_Q):
531    if ( type != ROAR_STREAM_CTL_TYPE_FLOAT )
532     return -1;
533
[2087]534    ROAR_DBG("cf_vorbis_ctl(*): setting quality to q=%f", *(float*)data);
535
536    self->encoder.v_base_quality = *(float*)data / 10;
[2084]537
538    if ( self->encoding ) {
539     ROAR_DBG("cf_vorbis_ctl(*): we are allready encoding, restart...");
540     ROAR_DBG("cf_vorbis_ctl(*): stoping stream...");
541     if ( cf_vorbis_encode_end(self) == -1 )
542      return -1;
543     ROAR_DBG("cf_vorbis_ctl(*): restarting stream...");
544     if ( cf_vorbis_encode_start(self) == -1 )
545      return -1;
546    }
547
548    return 0;
549   break;
[1238]550  default:
[2087]551    ROAR_DBG("cf_vorbis_ctl(*): Unknown command: cmd=0x%.8x, type=0x%.8x, pcmd=0x%.8x",
552                    cmd, type, ROAR_CODECFILTER_CTL2CMD(cmd));
[1238]553    return -1;
554 }
555
556 return -1;
557}
558
[1226]559#endif
[204]560//ll
Note: See TracBrowser for help on using the repository browser.