static void device_open(ripncode_t *r) { char *msg = NULL; r->cdio = cdio_open(r->device, driver_id(r)); if (r->cdio == NULL) ripncode_fatal(r, "failed to open CdIo device '%s' with driver '%s'", r->device, r->driver); r->cdda = cdio_cddap_identify_cdio(r->cdio, CDDA_MESSAGE_LOGIT, &msg); if (r->cdda == NULL) ripncode_fatal(r, "failed to identify CDDA device '%s' (%s)", r->device, msg ? msg : "unknown error"); cdio_cddap_free_messages(msg); if (cdio_cddap_open(r->cdda) < 0) ripncode_fatal(r, "failed to open CDDA device '%s' (%d: %s)", r->device, errno, strerror(errno)); r->cdpa = cdio_paranoia_init(r->cdda); if (r->cdpa == NULL) ripncode_fatal(r, "failed to open CD-Paranoia device '%s'", r->device); r->endian = data_bigendianp(r->cdda); ripncode_info(r, "Drive endianness: %d\n", r->endian); }
static int cdpa_open(rnc_dev_t *dev, const char *device) { cdpa_t *cdpa; char *msg; mrp_debug("opening device '%s' with cdparanoia", device); msg = NULL; cdpa = dev->data = mrp_allocz(sizeof(*cdpa)); if (cdpa == NULL) goto fail; cdpa->cdio = cdio_open(device, DRIVER_LINUX); if (cdpa->cdio == NULL) { msg = "failed open device"; goto fail; } cdpa->cdda = cdio_cddap_identify_cdio(cdpa->cdio, CDDA_MESSAGE_LOGIT, &msg); if (cdpa->cdda == NULL) goto fail; cdio_cddap_free_messages(msg); msg = NULL; if (cdio_cddap_open(cdpa->cdda) < 0) { msg = "failed to CDDAP-open device"; goto fail; } cdpa->cdpa = cdio_paranoia_init(cdpa->cdda); if (cdpa->cdpa == NULL) { msg = "failed to initialize cd-paranoia"; goto fail; } cdpa->ctrack = -1; return 0; fail: if (cdpa != NULL && msg != NULL) cdpa->errmsg = mrp_strdup(msg); return -1; }
void CddaImpl::open() { driver_id_t driver_id = DRIVER_UNKNOWN; if (_device.empty()) { char **ppsz_cd_drives = cdio_get_devices_with_cap_ret(NULL, CDIO_FS_AUDIO, false, &driver_id); if (ppsz_cd_drives && *ppsz_cd_drives) _device = ppsz_cd_drives[0]; cdio_free_device_list(ppsz_cd_drives); } _cdio = cdio_open(_device.c_str(), driver_id); if (_cdio == NULL) { THROW_EXCEPTION(CddaException, "Could not open device."); } // Detect empty drive if (cdio_get_first_track_num(_cdio) == CDIO_INVALID_TRACK) { close(); return; } _cdrom = cdio_cddap_identify_cdio(_cdio, CDDA_MESSAGE_LOGIT, NULL); if (_cdrom == NULL) { THROW_EXCEPTION(CddaException, "Could not read cdrom structure."); } cdio_cddap_verbose_set(_cdrom, CDDA_MESSAGE_LOGIT, CDDA_MESSAGE_LOGIT); int ret = cdio_cddap_open(_cdrom); if (ret != 0) { THROW_EXCEPTION(CddaException, cdda_error_message(ret)); } _is_open = true; read_toc(); //read_cddb(); }
static gboolean xmms_cdda_init (xmms_xform_t *xform) { CdIo_t *cdio = NULL; cdrom_drive_t *drive = NULL; const gchar *url; gchar **url_data = NULL; gchar *url_end; xmms_cdda_data_t *data; guint playtime; lsn_t first_lsn; track_t track; gchar *disc_id = NULL; gchar *cddb_id = NULL; xmms_config_property_t *val; const gchar *device; const gchar *metakey; gboolean ret = TRUE; g_return_val_if_fail (xform, FALSE); url = xmms_xform_indata_get_str (xform, XMMS_STREAM_TYPE_URL); if (g_ascii_strcasecmp (url, "cdda://") == 0) { xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE, "application/x-xmms2-playlist-entries", XMMS_STREAM_TYPE_END); return TRUE; } val = xmms_xform_config_lookup (xform, "device"); device = xmms_config_property_get_string (val); if (!get_disc_ids (device, &disc_id, &cddb_id, 0)) { return FALSE; } url += 7; url_data = g_strsplit (url, "/", 2); if (g_ascii_strcasecmp (url_data[0], disc_id)) { xmms_log_error ("Wrong disc inserted."); ret = FALSE; goto end; } if (url_data[1] == NULL) { xmms_log_error ("Missing track number."); ret = FALSE; goto end; } track = strtol (url_data[1], &url_end, 10); if (url_data[1] == url_end) { xmms_log_error ("Invalid track, need a number."); ret = FALSE; goto end; } cdio = open_cd (xform); if (!cdio) { ret = FALSE; goto end; } drive = cdio_cddap_identify_cdio (cdio, 1, NULL); if (!drive) { xmms_log_error ("Failed to identify drive."); ret = FALSE; goto end; } if (cdio_cddap_open (drive)) { xmms_log_error ("Unable to open disc."); ret = FALSE; goto end; } first_lsn = cdio_cddap_track_firstsector (drive, track); if (first_lsn == -1) { xmms_log_error ("No such track."); ret = FALSE; goto end; } data = g_new (xmms_cdda_data_t, 1); data->cdio = cdio; data->drive = drive; data->track = track; data->first_lsn = first_lsn; data->last_lsn = cdio_cddap_track_lastsector (drive, data->track); data->current_lsn = first_lsn; data->buf_used = CDIO_CD_FRAMESIZE_RAW; playtime = (data->last_lsn - data->first_lsn) * 1000.0 / CDIO_CD_FRAMES_PER_SEC; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION; xmms_xform_metadata_set_int (xform, metakey, playtime); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE; xmms_xform_metadata_set_int (xform, metakey, 141120); xmms_xform_metadata_set_str (xform, "disc_id", url_data[0]); xmms_xform_metadata_set_str (xform, "cddb_id", cddb_id); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_TRACKNR; xmms_xform_metadata_set_int (xform, metakey, track); xmms_xform_private_data_set (xform, data); xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE, "audio/pcm", XMMS_STREAM_TYPE_FMT_FORMAT, XMMS_SAMPLE_FORMAT_S16, XMMS_STREAM_TYPE_FMT_CHANNELS, 2, XMMS_STREAM_TYPE_FMT_SAMPLERATE, 44100, XMMS_STREAM_TYPE_END); end: /* These are to be destroyed in every cases... */ g_free (cddb_id); g_free (disc_id); g_strfreev (url_data); /* destroy cdio/drive in case of failure */ if (!ret) { if (drive) { cdio_cddap_close_no_free_cdio (drive); } if (cdio) { cdio_destroy (cdio); } } return ret; }
static void cued_rip_prologue(rip_context_t *rip) { rip->mmcBuf = NULL; rip->allocatedSectors = 0; #ifdef CUED_HAVE_PARANOIA if (ripUseParanoia) { char *msg = 0; int rc; // N.B. this behavior does not match documentation: // the 0 here appears to prevent the message "Checking <filename> for cdrom..." rip->paranoiaCtlObj = cdio_cddap_identify_cdio(rip->cdObj, 0, &msg); if (rip->paranoiaCtlObj) { if (msg) { cdio_warn("identify returned paranoia message(s) \"%s\"", msg); } cdio_cddap_verbose_set(rip->paranoiaCtlObj, CDDA_MESSAGE_LOGIT, CDDA_MESSAGE_LOGIT); rc = cdio_cddap_open(rip->paranoiaCtlObj); cdio2_paranoia_msg(rip->paranoiaCtlObj, "open of device"); if (!rc) { rip->paranoiaRipObj = cdio_paranoia_init(rip->paranoiaCtlObj); cdio2_paranoia_msg(rip->paranoiaCtlObj, "initialization of paranoia"); if (!rip->paranoiaRipObj) { cdio2_abort("out of memory initializing paranoia"); } cdio_paranoia_modeset(rip->paranoiaRipObj, PARANOIA_MODE_FULL ^ PARANOIA_MODE_NEVERSKIP); // N.B. not needed at the moment cdio2_paranoia_msg(rip->paranoiaCtlObj, "setting of paranoia mode"); rip->save_read_paranoid = rip->paranoiaCtlObj->read_audio; rip->paranoiaCtlObj->read_audio = cued_read_paranoid; } else { cdio_cddap_close_no_free_cdio(rip->paranoiaCtlObj); cdio_error("disabling paranoia"); CLRF(RIP_F_USE_PARANOIA, rip->flags); } } else { cdio_error("disabling paranoia due to the following message(s):\n%s", msg); CLRF(RIP_F_USE_PARANOIA, rip->flags); } } #endif // CUED_HAVE_PARANOIA if (rip->qSubChannelFileName) { if (!strcmp("-", rip->qSubChannelFileName)) { rip->qSubChannelFile = stdout; } else { (void) format_get_file_path(rip->cdObj, rip->cddbObj, rip->qSubChannelFileName, "", 0, rip->fileNameBuffer, rip->bufferSize); // replaced O_EXCL with O_TRUNC to allow using /dev/null for testing rip->qSubChannelFile = fopen2(rip->fileNameBuffer, O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, 0666); if (!rip->qSubChannelFile) { cdio2_unix_error("fopen2", rip->fileNameBuffer, 0); cdio_error("not creating sub-channel file \"%s\"", rip->fileNameBuffer); rip->qSubChannelFileName = 0; } } } rip->endOfDiscSector = cdio_get_disc_last_lsn(rip->cdObj); if (CDIO_INVALID_LSN == rip->endOfDiscSector) { cdio2_abort("failed to get last sector number"); } else { //cdio_debug("end of disc sector is %d", rip->endOfDiscSector); } }
/* return 0 if OK, -1 if drive is apparently not available */ int cdda_scan_drive(char * device_path, cdda_drive_t * cdda_drive) { track_t tracks; track_t first_track; track_t last_track; track_t skipped = 0; int i, n = 0; cdrom_drive_t * d; if (cdda_drive->cdio == NULL) { cdda_drive->cdio = cdio_open(device_path, DRIVER_DEVICE); if (!cdda_drive->cdio) { return -1; } strncpy(cdda_drive->device_path, device_path, CDDA_MAXLEN-1); } cdda_drive->disc.n_tracks = 0; tracks = cdio_get_num_tracks(cdda_drive->cdio); if (tracks < 1 || tracks >= 100) { cdda_drive->disc.hash_prev = cdda_drive->disc.hash; cdda_drive->disc.hash = 0L; return 0; } d = cdio_cddap_identify_cdio(cdda_drive->cdio, 0, NULL); if (d == NULL) { return -1; } first_track = cdio_get_first_track_num(cdda_drive->cdio); last_track = cdio_get_last_track_num(cdda_drive->cdio); for (i = first_track; i <= last_track; i++) { if (!cdio_cddap_track_audiop(d, i)) { skipped = i; last_track = i-1; break; } } cdio_cddap_close_no_free_cdio(d); if (last_track < first_track) { return 0; } cdda_drive->disc.n_tracks = last_track - first_track + 1; for (i = first_track; i <= last_track; i++) { lsn_t lsn = cdio_get_track_lsn(cdda_drive->cdio, i); if (lsn != CDIO_INVALID_LSN) { cdda_drive->disc.toc[n++] = lsn; } } if (skipped == 0) { cdda_drive->disc.toc[n] = cdio_get_track_lsn(cdda_drive->cdio, CDIO_CDROM_LEADOUT_TRACK); } else { cdda_drive->disc.toc[n] = cdio_get_track_lsn(cdda_drive->cdio, skipped); if ((cdda_drive->disc.toc[n] - cdda_drive->disc.toc[n-1]) >= 11400) { /* compensate end of track with multisession offset */ cdda_drive->disc.toc[n] -= 11400; } } cdda_drive->disc.hash_prev = cdda_drive->disc.hash; cdda_drive->disc.hash = calc_cdda_hash(&cdda_drive->disc); if (cdda_drive->disc.hash != cdda_drive->disc.hash_prev) { strncpy(cdda_drive->disc.artist_name, _("Unknown Artist"), MAXLEN-1); strncpy(cdda_drive->disc.record_name, _("Unknown Record"), MAXLEN-1); cdda_drive->swap_bytes = -1; /* unknown */ } return 0; }
static struct input_stream * input_cdio_open(const char *uri, GMutex *mutex, GCond *cond, GError **error_r) { struct input_cdio_paranoia *i; struct cdio_uri parsed_uri; if (!parse_cdio_uri(&parsed_uri, uri, error_r)) return NULL; i = g_new(struct input_cdio_paranoia, 1); input_stream_init(&i->base, &input_plugin_cdio_paranoia, uri, mutex, cond); /* initialize everything (should be already) */ i->drv = NULL; i->cdio = NULL; i->para = NULL; i->trackno = parsed_uri.track; pcm_buffer_init(&i->conv_buffer); /* get list of CD's supporting CD-DA */ char *device = parsed_uri.device[0] != 0 ? g_strdup(parsed_uri.device) : cdio_detect_device(); if (device == NULL) { g_set_error(error_r, cdio_quark(), 0, "Unable find or access a CD-ROM drive with an audio CD in it."); input_cdio_close(&i->base); return NULL; } /* Found such a CD-ROM with a CD-DA loaded. Use the first drive in the list. */ i->cdio = cdio_open(device, DRIVER_UNKNOWN); g_free(device); i->drv = cdio_cddap_identify_cdio(i->cdio, 1, NULL); if ( !i->drv ) { g_set_error(error_r, cdio_quark(), 0, "Unable to identify audio CD disc."); input_cdio_close(&i->base); return NULL; } cdda_verbose_set(i->drv, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT); if ( 0 != cdio_cddap_open(i->drv) ) { g_set_error(error_r, cdio_quark(), 0, "Unable to open disc."); input_cdio_close(&i->base); return NULL; } i->endian = data_bigendianp(i->drv); switch (i->endian) { case -1: g_debug("cdda: drive returns unknown audio data, assuming Little Endian"); i->endian = 0; break; case 0: g_debug("cdda: drive returns audio data Little Endian."); break; case 1: g_debug("cdda: drive returns audio data Big Endian."); break; default: g_set_error(error_r, cdio_quark(), 0, "Drive returns unknown data type %d", i->endian); input_cdio_close(&i->base); return NULL; } i->lsn_relofs = 0; if (i->trackno >= 0) { i->lsn_from = cdio_get_track_lsn(i->cdio, i->trackno); i->lsn_to = cdio_get_track_last_lsn(i->cdio, i->trackno); } else { i->lsn_from = 0; i->lsn_to = cdio_get_disc_last_lsn(i->cdio); } i->para = cdio_paranoia_init(i->drv); /* Set reading mode for full paranoia, but allow skipping sectors. */ paranoia_modeset(i->para, PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP); /* seek to beginning of the track */ cdio_paranoia_seek(i->para, i->lsn_from, SEEK_SET); i->base.ready = true; i->base.seekable = true; i->base.size = (i->lsn_to - i->lsn_from + 1) * CDIO_CD_FRAMESIZE_RAW; /* hack to make MPD select the "pcm" decoder plugin */ i->base.mime = g_strdup("audio/x-mpd-cdda-pcm"); return &i->base; }
//virtual Metadata *CdDecoder::getMetadata() { QString artist, album, compilation_artist, title, genre; int year = 0; unsigned long length = 0; track_t tracknum = 0; if (-1 == m_settracknum) tracknum = getFilename().toUInt(); else { tracknum = m_settracknum; setFilename(QString("%1" CDEXT).arg(tracknum)); } QMutexLocker lock(&getCdioMutex()); StCdioDevice cdio(m_devicename); if (!cdio) return NULL; const track_t lastTrack = cdio_get_last_track_num(cdio); if (CDIO_INVALID_TRACK == lastTrack) return NULL; if (TRACK_FORMAT_AUDIO != cdio_get_track_format(cdio, tracknum)) return NULL; // Assume disc changed if max LSN different bool isDiscChanged = false; static lsn_t s_totalSectors; lsn_t totalSectors = cdio_get_track_lsn(cdio, CDIO_CDROM_LEADOUT_TRACK); if (s_totalSectors != totalSectors) { s_totalSectors = totalSectors; isDiscChanged = true; } // NB cdio_get_track_last_lsn is unreliable for the last audio track // of discs with data tracks beyond lsn_t end = cdio_get_track_last_lsn(cdio, tracknum); if (isDiscChanged) { const track_t audioTracks = getNumCDAudioTracks(); s_lastAudioLsn = cdio_get_track_last_lsn(cdio, audioTracks); if (audioTracks < lastTrack) { cdrom_drive_t *dev = cdio_cddap_identify_cdio(cdio, 0, NULL); if (NULL != dev) { if (DRIVER_OP_SUCCESS == cdio_cddap_open(dev)) { // NB this can be S L O W but is reliable lsn_t end2 = cdio_cddap_track_lastsector(dev, getNumCDAudioTracks()); if (CDIO_INVALID_LSN != end2) s_lastAudioLsn = end2; } cdio_cddap_close_no_free_cdio(dev); } } } if (s_lastAudioLsn && s_lastAudioLsn < end) end = s_lastAudioLsn; const lsn_t start = cdio_get_track_lsn(cdio, tracknum); if (CDIO_INVALID_LSN != start && CDIO_INVALID_LSN != end) { length = ((end - start + 1) * 1000 + CDIO_CD_FRAMES_PER_SEC/2) / CDIO_CD_FRAMES_PER_SEC; } bool isCompilation = false; #define CDTEXT 0 // Disabled - cd-text access on discs without it is S L O W #if CDTEXT static int s_iCdtext; if (isDiscChanged) s_iCdtext = -1; if (s_iCdtext) { // cdio_get_cdtext can't take >5 seconds on some CD's without cdtext if (s_iCdtext < 0) LOG(VB_MEDIA, LOG_INFO, QString("Getting cdtext for track %1...").arg(tracknum)); cdtext_t * cdtext = cdio_get_cdtext(m_cdio, tracknum); if (NULL != cdtext) { genre = cdtext_get_const(CDTEXT_GENRE, cdtext); artist = cdtext_get_const(CDTEXT_PERFORMER, cdtext); title = cdtext_get_const(CDTEXT_TITLE, cdtext); const char* isrc = cdtext_get_const(CDTEXT_ISRC, cdtext); /* ISRC codes are 12 characters long, in the form CCXXXYYNNNNN * CC = country code * XXX = registrant e.g. BMG * CC = year withou century * NNNNN = unique ID */ if (isrc && strlen(isrc) >= 7) { year = (isrc[5] - '0') * 10 + (isrc[6] - '0'); year += (year <= 30) ? 2000 : 1900; } cdtext_destroy(cdtext); if (!title.isNull()) { if (s_iCdtext < 0) LOG(VB_MEDIA, LOG_INFO, "Found cdtext track title"); s_iCdtext = 1; // Get disc info cdtext = cdio_get_cdtext(cdio, 0); if (NULL != cdtext) { compilation_artist = cdtext_get_const( CDTEXT_PERFORMER, cdtext); if (!compilation_artist.isEmpty() && artist != compilation_artist) isCompilation = true; album = cdtext_get_const(CDTEXT_TITLE, cdtext); if (genre.isNull()) genre = cdtext_get_const(CDTEXT_GENRE, cdtext); cdtext_destroy(cdtext); } } else { if (s_iCdtext < 0) LOG(VB_MEDIA, LOG_INFO, "No cdtext title for track"); s_iCdtext = 0; } } else { if (s_iCdtext < 0) LOG(VB_MEDIA, LOG_INFO, "No cdtext"); s_iCdtext = 0; } } if (title.isEmpty() || artist.isEmpty() || album.isEmpty()) #endif // CDTEXT { // CDDB lookup Cddb::Toc toc; Cddb::Matches r; if (Cddb::Query(r, GetToc(cdio, toc))) { Cddb::Matches::match_t::const_iterator select = r.matches.begin(); if (r.matches.size() > 1) { // TODO prompt user to select one // In the meantime, select the first non-generic genre for (Cddb::Matches::match_t::const_iterator it = select; it != r.matches.end(); ++it) { QString g = it->genre.toLower(); if (g != "misc" && g != "data") { select = it; break; } } } Cddb::Album info; if (Cddb::Read(info, select->genre, select->discID)) { isCompilation = info.isCompilation; if (info.genre.toLower() != "misc") genre = info.genre; album = info.title; compilation_artist = info.artist; year = info.year; if (info.tracks.size() >= tracknum) { const Cddb::Track& track = info.tracks[tracknum - 1]; title = track.title; artist = track.artist; } // Create a temporary local alias for future lookups if (r.discID != info.discID) Cddb::Alias(info, r.discID); } } } if (compilation_artist.toLower().left(7) == "various") compilation_artist = QObject::tr("Various Artists"); if (artist.isEmpty()) { artist = compilation_artist; compilation_artist.clear(); } if (title.isEmpty()) title = QObject::tr("Track %1").arg(tracknum); Metadata *m = new Metadata(getFilename(), artist, compilation_artist, album, title, genre, year, tracknum, length); if (m) m->setCompilation(isCompilation); return m; }
// pure virtual bool CdDecoder::initialize() { if (m_inited) return true; m_inited = m_user_stop = m_finish = false; m_freq = m_bitrate = 0L; m_stat = DecoderEvent::Error; m_chan = 0; m_seekTime = -1.; if (output()) output()->PauseUntilBuffered(); QFile* file = dynamic_cast< QFile* >(input()); // From QIODevice* if (file) { setFilename(file->fileName()); m_tracknum = getFilename().section('.', 0, 0).toUInt(); } QMutexLocker lock(&getCdioMutex()); m_cdio = openCdio(m_devicename); if (!m_cdio) return false; m_start = cdio_get_track_lsn(m_cdio, m_tracknum); m_end = cdio_get_track_last_lsn(m_cdio, m_tracknum); if (CDIO_INVALID_LSN == m_start || CDIO_INVALID_LSN == m_end) { LOG(VB_MEDIA, LOG_INFO, "CdDecoder: No tracks on " + m_devicename); cdio_destroy(m_cdio), m_cdio = 0; return false; } LOG(VB_MEDIA, LOG_DEBUG, QString("CdDecoder track=%1 lsn start=%2 end=%3") .arg(m_tracknum).arg(m_start).arg(m_end)); m_curpos = m_start; m_device = cdio_cddap_identify_cdio(m_cdio, 0, NULL); if (NULL == m_device) { LOG(VB_GENERAL, LOG_ERR, QString("Error: CdDecoder: cdio_cddap_identify(%1) failed") .arg(m_devicename)); cdio_destroy(m_cdio), m_cdio = 0; return false; } cdio_cddap_verbose_set(m_device, VERBOSE_LEVEL_CHECK(VB_MEDIA, LOG_ANY) ? CDDA_MESSAGE_PRINTIT : CDDA_MESSAGE_FORGETIT, VERBOSE_LEVEL_CHECK(VB_MEDIA, LOG_DEBUG) ? CDDA_MESSAGE_PRINTIT : CDDA_MESSAGE_FORGETIT); if (DRIVER_OP_SUCCESS == cdio_cddap_open(m_device)) { // cdio_get_track_last_lsn is unreliable on discs with data at end lsn_t end2 = cdio_cddap_track_lastsector(m_device, m_tracknum); if (end2 < m_end) { LOG(VB_MEDIA, LOG_INFO, QString("CdDecoder: trim last lsn from %1 to %2") .arg(m_end).arg(end2)); m_end = end2; } m_paranoia = cdio_paranoia_init(m_device); if (NULL != m_paranoia) { cdio_paranoia_modeset(m_paranoia, PARANOIA_MODE_DISABLE); (void)cdio_paranoia_seek(m_paranoia, m_start, SEEK_SET); } else { LOG(VB_GENERAL, LOG_ERR, "Warn: CD reading with paranoia is disabled"); } } else { LOG(VB_GENERAL, LOG_ERR, QString("Warn: drive '%1' is not cdda capable"). arg(m_devicename)); } int chnls = cdio_get_track_channels(m_cdio, m_tracknum); m_chan = chnls > 0 ? chnls : 2; m_freq = kSamplesPerSec; if (output()) { const AudioSettings settings(FORMAT_S16, m_chan, CODEC_ID_PCM_S16LE, m_freq, false /* AC3/DTS passthru */); output()->Reconfigure(settings); output()->SetSourceBitrate(m_freq * m_chan * 16); } // 20ms worth m_bks = (m_freq * m_chan * 2) / 50; m_bksFrames = m_freq / 50; // decode 8 bks worth of samples each time we need more m_decodeBytes = m_bks << 3; m_output_buf = reinterpret_cast< char* >( ::av_malloc(m_decodeBytes + CDIO_CD_FRAMESIZE_RAW * 2)); m_output_at = 0; setCDSpeed(2); m_inited = true; return m_inited; }