예제 #1
0
/*!

 */
long ParanoiaReaderImpl::read(uint8_t* buffer, uint32_t begin_sector, uint32_t sectors)
{
   if (not _audio_cd->is_open()) 
   {
      THROW_EXCEPTION(CddaException, "AudioCd is closed");
   }

   cdio_paranoia_modeset(_cdrom_paranoia, PARANOIA_MODE_FULL ^ PARANOIA_MODE_NEVERSKIP);

   cdio_paranoia_seek(_cdrom_paranoia, begin_sector, SEEK_SET);

   int16_t* read_buffer = cdio_paranoia_read_limited(_cdrom_paranoia, NULL, _max_retries);

   //! \todo Use another system to free returned messages
   char* err = cdio_cddap_errors(_audio_cd->cdrom());
   //char* mes = cdio_cddap_messages(_audio_cd->cdrom());

   if (err) 
   {
      std::string tmp = err;
      delete [] err;
      THROW_EXCEPTION(CddaException, tmp);
   }

   buffer = reinterpret_cast<uint8_t*>(read_buffer);

   return sectors;
}
예제 #2
0
int CdParanoia::seek(long sector, int mode)
{
    #ifdef CDIOPARANOIA_FOUND
    return paranoia ? cdio_paranoia_seek(paranoia, sector, mode) : -1;
    #else
    return paranoia ? paranoia_seek(paranoia, sector, mode) : -1;
    #endif
}
예제 #3
0
static int read_seek(AVFormatContext *ctx, int stream_index, int64_t timestamp,
                     int flags)
{
    CDIOContext *s = ctx->priv_data;
    AVStream *st = ctx->streams[0];

    cdio_paranoia_seek(s->paranoia, timestamp, SEEK_SET);
    st->cur_dts = timestamp;
    return 0;
}
static unsigned
CDDAReader_seek_device(cdio_CDDAReader *self, unsigned sector)
{
    const unsigned desired_sector = MIN(sector, self->_.drive.final_sector - 1u);
    /*not sure what this returns, but it isn't the sector seeked to*/
    cdio_paranoia_seek(self->_.drive.paranoia,
                       (int32_t)desired_sector,
                       (int)SEEK_SET);
    self->_.drive.current_sector = desired_sector;
    return self->_.drive.current_sector;
}
예제 #5
0
static PyObject*
CDDA_seek(cdio_CDDAObject* self, PyObject *args)
{
    off_t location;
    lsn_t new_location;

    if (!PyArg_ParseTuple(args, "l", &location))
        return NULL;

    new_location = cdio_paranoia_seek(self->paranoia,
                                      (int32_t)location,
                                      (int)SEEK_SET);

    return Py_BuildValue("i", new_location);
}
static bool
input_cdio_seek(struct input_stream *is,
		goffset offset, int whence, GError **error_r)
{
	struct input_cdio_paranoia *cis = (struct input_cdio_paranoia *)is;

	/* calculate absolute offset */
	switch (whence) {
	case SEEK_SET:
		break;
	case SEEK_CUR:
		offset += cis->base.offset;
		break;
	case SEEK_END:
		offset += cis->base.size;
		break;
	}

	if (offset < 0 || offset > cis->base.size) {
		g_set_error(error_r, cdio_quark(), 0,
			    "Invalid offset to seek %ld (%ld)",
			    (long int)offset, (long int)cis->base.size);
		return false;
	}

	/* simple case */
	if (offset == cis->base.offset)
		return true;

	/* calculate current LSN */
	cis->lsn_relofs = offset / CDIO_CD_FRAMESIZE_RAW;
	cis->base.offset = offset;

	cdio_paranoia_seek(cis->para, cis->lsn_from + cis->lsn_relofs, SEEK_SET);

	return true;
}
예제 #7
0
static int32_t seek_track(cdpa_t *cdpa, int idx, uint32_t blk)
{
    lsn_t lsn;

    mrp_debug("seeking to track #%d, block %u", idx, blk);

    if (idx < 0 || idx >= cdpa->ntrack)
        goto invalid;

    if (cdpa->tracks[idx].fblk + blk > cdpa->tracks[idx].lblk)
        goto invalid;

    blk += cdpa->tracks[idx].fblk;
    lsn  = (int32_t)cdio_paranoia_seek(cdpa->cdpa, blk, SEEK_SET);

    if (lsn < 0)
      goto invalid;

    return (int32_t)(lsn * CDIO_CD_FRAMESIZE_RAW);

 invalid:
    errno = EINVAL;
    return -1;
}
예제 #8
0
파일: rip.c 프로젝트: RomanHargrave/cued
void cued_rip_to_file(rip_context_t *rip)
{
    SF_INFO sfinfo;
    PIT(SNDFILE, sfObj);
    PIT(int16_t, pbuf);
    lsn_t currSector, offsetSectors;
    int wordsToWrite, wordsWritten, i;

    int offsetWords = rip->offsetWords;
    track_t track = rip->currentTrack;

    memset(&sfinfo, 0x00, sizeof(sfinfo));
    sfinfo.samplerate = 44100;
    sfinfo.channels = rip->channels;
    sfinfo.format = SF_FORMAT_PCM_16 | rip->soundFileFormat;

    offsetSectors = offsetWords / CD_FRAMEWORDS;
    rip->firstSector += offsetSectors;
    rip->lastSector  += offsetSectors;
    offsetWords %= CD_FRAMEWORDS;

    if (offsetWords < 0) {
        rip->firstSector -= 1;
    } else if (offsetWords > 0) {
        rip->lastSector  += 1;
    }
    // else offsetWords is zero b/c the offset fell on a sector boundary

    currSector = rip->firstSector;

#ifdef CUED_HAVE_PARANOIA

    if (ripUseParanoia) {
        lsn_t seekSector, prc;

        if (currSector < 0 && !ripReadPregap) {
            seekSector = 0;
        } else {
            seekSector = currSector;
        }

        // TODO:  paranoia has a problem with reading leadout
        if (seekSector < rip->endOfDiscSector) {
            prc = cdio_paranoia_seek(rip->paranoiaRipObj, seekSector, SEEK_SET);
            cdio2_paranoia_msg(rip->paranoiaCtlObj, "paranoia seek");
            if (-1 == prc) {
                cdio_error("paranoia returned \"%d\" during seek to \"%d\"; skipping track %02d", prc, seekSector, track);

                return;
            }
        }
    }

#endif // CUED_HAVE_PARANOIA

    if (ripExtract) {

        // does not return on error
        (void) format_get_file_path(rip->cdObj, rip->cddbObj,
            rip->fileNamePattern, cued_fmt_to_ext(rip->soundFileFormat), track,
            rip->fileNameBuffer, rip->bufferSize
            );

        sfObj = sf_open(rip->fileNameBuffer, SFM_WRITE, &sfinfo);
        if (!sfObj) {
            cdio_error("sf_open(\"%s\") returned \"%s\"; skipping extraction of track %02d", rip->fileNameBuffer, sf_strerror(sfObj), track);

            return;
        }
    }

    for (;  currSector <= rip->lastSector;  ++currSector) {

        if ((currSector < 0 && !ripReadPregap) || (currSector >= rip->endOfDiscSector && !ripReadLeadout)) {

            // N.B.  assume that if mmcBuf is not NULL, it is >= sizeof(audio_buffer_t)
            if (!rip->mmcBuf) {

                // use twice the audio_buffer_t size for reading 1 sector;
                // this should accomodate any extra headers/sub-channel data
                // requested later in the normal read path
                //
                rip->mmcBuf = (uint8_t *) malloc(2 * sizeof(audio_buffer_t));
                if (rip->mmcBuf) {
                    rip->allocatedSectors = 1;
                } else {
                    cdio2_abort("out of memory allocating overread sector");
                }
            }

            memset(rip->mmcBuf, 0x00, sizeof(audio_buffer_t));
            pbuf = (int16_t *) rip->mmcBuf;

        } else {

            // TODO:  need to update track indices on skip of sector (continue)

            if (ripUseParanoia) {

#ifdef CUED_HAVE_PARANOIA

                pbuf = cdio_paranoia_read_limited(rip->paranoiaRipObj, cdio2_paranoia_callback, rip->retries);
                cdio2_paranoia_msg(rip->paranoiaCtlObj, "read of audio sector");
                if (!pbuf) {
                    cdio_error("paranoia did not return data; skipping extraction of audio sector %d in track %02d", currSector, track);
                    continue;
                }

#endif // CUED_HAVE_PARANOIA

            } else {
                if (DRIVER_OP_SUCCESS == cued_read_audio(rip, currSector, 1, NULL, rip->retries)) {
                    pbuf = (int16_t *) rip->mmcBuf;
                } else {
                    continue;
                }
            }
        }

        wordsToWrite = CD_FRAMEWORDS;

        // N.B. firstSector == lastSector is not possible if offsetWords is non-zero
        //
        if (rip->firstSector == currSector) {
            if (offsetWords < 0) {
                pbuf += CD_FRAMEWORDS + offsetWords;
                wordsToWrite  = -offsetWords;
            } else if (offsetWords > 0) {
                pbuf += offsetWords;
                wordsToWrite -= offsetWords;
            }
        } else if (rip->lastSector == currSector) {
            if (offsetWords < 0) {
                wordsToWrite += offsetWords;
            } else if (offsetWords > 0) {
                wordsToWrite  = offsetWords;    
            }
        }

        if (ripExtract) {
            wordsWritten = sf_write_short(sfObj, pbuf, wordsToWrite);
            if (wordsWritten != wordsToWrite) {

                // probably out of disk space, which is bad, because most things rely on it
                cdio2_abort("failed to write to file \"%s\" due to \"%s\"", rip->fileNameBuffer, sf_strerror(sfObj));
            }
        }

        if (!track && !ripNoisyPregap) {
            for (i = 0;  i < wordsToWrite;  ++i) {
                if (pbuf[i]) {
                    SETF(RIP_F_NOISY_PREGAP, rip->flags);
                    break;
                }
            }
        }
    }

    if (!track && !ripNoisyPregap) {
        SETF(RIP_F_SILENT_PREGAP, rip->flags);
    }

    if (ripExtract) {
        sf_close(sfObj);
    }
}
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;
}
예제 #10
0
// private virtual
void CdDecoder::run()
{
    RunProlog();

    if (!m_inited)
    {
        RunEpilog();
        return;
    }

    m_stat = DecoderEvent::Decoding;
    // NB block scope required to prevent re-entrancy
    {
        DecoderEvent e(m_stat);
        dispatch(e);
    }

    // account for possible frame expansion in aobase (upmix, float conv)
    const std::size_t thresh = m_bks * 6;

    while (!m_finish && !m_user_stop)
    {
        if (m_seekTime >= +0.)
        {
            m_curpos = m_start + static_cast< lsn_t >(
                (m_seekTime * kSamplesPerSec) / CD_FRAMESAMPLES);
            if (m_paranoia)
            {
                QMutexLocker lock(&getCdioMutex());
                cdio_paranoia_seek(m_paranoia, m_curpos, SEEK_SET);
            }

            m_output_at = 0;
            m_seekTime = -1.;
        }

        if (m_output_at < m_bks)
        {
            while (m_output_at < m_decodeBytes &&
                   !m_finish && !m_user_stop && m_seekTime <= +0.)
            {
                if (m_curpos < m_end)
                {
                    QMutexLocker lock(&getCdioMutex());
                    if (m_paranoia)
                    {
                        int16_t *cdbuffer = cdio_paranoia_read_limited(
                                                m_paranoia, 0, 10);
                        if (cdbuffer)
                            memcpy(&m_output_buf[m_output_at],
                                cdbuffer, CDIO_CD_FRAMESIZE_RAW);
                    }
                    else
                    {
                        driver_return_code_t c = cdio_read_audio_sector(
                            m_cdio, &m_output_buf[m_output_at],
                            m_curpos);
                        if (DRIVER_OP_SUCCESS != c)
                        {
                            LOG(VB_MEDIA, LOG_DEBUG,
                                QString("cdio_read_audio_sector(%1) error %2").
                                arg(m_curpos).arg(c));
                            memset( &m_output_buf[m_output_at],
                                0, CDIO_CD_FRAMESIZE_RAW);
                        }
                    }

                    m_output_at += CDIO_CD_FRAMESIZE_RAW;
                    ++(m_curpos);
                }
                else
                {
                    m_finish = true;
                }
            }
        }

        if (!output())
            continue;

        // Wait until we need to decode or supply more samples
        uint fill = 0, total = 0;
        while (!m_finish && !m_user_stop && m_seekTime <= +0.)
        {
            output()->GetBufferStatus(fill, total);
            // Make sure we have decoded samples ready and that the
            // audiobuffer is reasonably populated
            if (fill < (thresh << 6))
                break;
            else
            {
                // Wait for half of the buffer to drain
                ::usleep(output()->GetAudioBufferedTime()<<9);
            }
        }

        // write a block if there's sufficient space for it
        if (!m_user_stop &&
            m_output_at >= m_bks &&
            fill <= total - thresh)
        {
            writeBlock();
        }
    }

    if (m_user_stop)
        m_inited = false;
    else if (output())
    {
        // Drain our buffer
        while (m_output_at >= m_bks)
            writeBlock();

        // Drain ao buffer
        output()->Drain();
    }

    if (m_finish)
        m_stat = DecoderEvent::Finished;
    else if (m_user_stop)
        m_stat = DecoderEvent::Stopped;
    else
        m_stat = DecoderEvent::Error;

    // NB block scope required to step onto next track
    {
        DecoderEvent e(m_stat);
        dispatch(e);
    }

    deinit();

    RunEpilog();
}
예제 #11
0
// 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;
}
예제 #12
0
파일: ripncode.c 프로젝트: klihub/ripncode
static void get_track_info(ripncode_t *r)
{
    rip_track_t *t;
    int          i, base;
    char         file[1024], *msg;
    int16_t     *samples;
    int          fd, n, l, total;

    base      = cdio_get_first_track_num(r->cdio);
    r->ntrack = cdio_get_num_tracks(r->cdio);
    r->tracks = mrp_allocz_array(rip_track_t, r->ntrack);

    if (r->tracks == NULL && r->ntrack > 0)
        ripncode_fatal(r, "failed to allocate track info");

    cdio_paranoia_modeset(r->cdpa, PARANOIA_MODE_FULL);

    for (i = 0, t = r->tracks; i < r->ntrack; i++, t++) {
        if (i >= r->last)
            break;
        t->id      = base + i;
        t->format  = cdio_get_track_format(r->cdio, base + i);
        t->lsn_beg = cdio_get_track_lsn(r->cdio, base + i);
        t->lsn_end = cdio_get_track_last_lsn(r->cdio, base + i);
        t->lba     = cdio_get_track_lba(r->cdio, base + i);

        printf("track #%d (id %d): lsn: %u - %u (lba %u), format: %s\n",
               i, base + i, t->lsn_beg, t->lsn_end, t->lba,
               track_format_name(t->format));

        if (r->dryrun)
            continue;

        snprintf(file, sizeof(file), "track-%d.raw", i);
        if ((fd = open(file, O_WRONLY|O_CREAT, 0644)) < 0)
            ripncode_fatal(r, "failed to open '%s' (%d: %s)", file,
                           errno, strerror(errno));

        cdio_paranoia_seek(r->cdpa, t->lsn_beg * CDIO_CD_FRAMESIZE_RAW,
                           SEEK_SET);

        total = t->lsn_end - t->lsn_beg + 1;
        for (l = 0; l <= total; l++) {
            printf("\rreading track sector %d/%d (#%d)...", l, total,
                   t->lsn_beg + l);
            fflush(stdout);

            samples = cdio_paranoia_read(r->cdpa, read_status);

            if (samples == NULL) {
                msg = cdio_cddap_errors(r->cdda);
                ripncode_fatal(r, "failed to seek to LSN %d (%s)", t->lsn_beg,
                               msg ? msg : "unknown error");
            }

            n = write(fd, samples, CDIO_CD_FRAMESIZE_RAW);

            if (n < 0)
                ripncode_fatal(r, "failed to write sector data (%d: %s)",
                               errno, strerror(errno));
        }

        close(fd);
    }
}