annotate ffmpeg/libavdevice/libcdio.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Copyright (c) 2011 Anton Khirnov <anton@khirnov.net>
yading@10 3 *
yading@10 4 * This file is part of Libav.
yading@10 5 *
yading@10 6 * Libav is free software; you can redistribute it and/or
yading@10 7 * modify it under the terms of the GNU Lesser General Public
yading@10 8 * License as published by the Free Software Foundation; either
yading@10 9 * version 2.1 of the License, or (at your option) any later version.
yading@10 10 *
yading@10 11 * Libav is distributed in the hope that it will be useful,
yading@10 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 14 * Lesser General Public License for more details.
yading@10 15 *
yading@10 16 * You should have received a copy of the GNU Lesser General Public
yading@10 17 * License along with Libav; if not, write to the Free Software
yading@10 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 19 */
yading@10 20
yading@10 21 /**
yading@10 22 * @file
yading@10 23 * libcdio CD grabbing
yading@10 24 */
yading@10 25
yading@10 26 #include "config.h"
yading@10 27
yading@10 28 #if HAVE_CDIO_PARANOIA_H
yading@10 29 #include <cdio/cdda.h>
yading@10 30 #include <cdio/paranoia.h>
yading@10 31 #elif HAVE_CDIO_PARANOIA_PARANOIA_H
yading@10 32 #include <cdio/paranoia/cdda.h>
yading@10 33 #include <cdio/paranoia/paranoia.h>
yading@10 34 #endif
yading@10 35
yading@10 36 #include "libavutil/log.h"
yading@10 37 #include "libavutil/mem.h"
yading@10 38 #include "libavutil/opt.h"
yading@10 39
yading@10 40 #include "libavformat/avformat.h"
yading@10 41 #include "libavformat/internal.h"
yading@10 42
yading@10 43 typedef struct CDIOContext {
yading@10 44 const AVClass *class;
yading@10 45 cdrom_drive_t *drive;
yading@10 46 cdrom_paranoia_t *paranoia;
yading@10 47 int32_t last_sector;
yading@10 48
yading@10 49 /* private options */
yading@10 50 int speed;
yading@10 51 int paranoia_mode;
yading@10 52 } CDIOContext;
yading@10 53
yading@10 54 static av_cold int read_header(AVFormatContext *ctx)
yading@10 55 {
yading@10 56 CDIOContext *s = ctx->priv_data;
yading@10 57 AVStream *st;
yading@10 58 int ret, i;
yading@10 59 char *err = NULL;
yading@10 60
yading@10 61 if (!(st = avformat_new_stream(ctx, NULL)))
yading@10 62 return AVERROR(ENOMEM);
yading@10 63 s->drive = cdio_cddap_identify(ctx->filename, CDDA_MESSAGE_LOGIT, &err);
yading@10 64 if (!s->drive) {
yading@10 65 av_log(ctx, AV_LOG_ERROR, "Could not open drive %s.\n", ctx->filename);
yading@10 66 return AVERROR(EINVAL);
yading@10 67 }
yading@10 68 if (err) {
yading@10 69 av_log(ctx, AV_LOG_VERBOSE, "%s\n", err);
yading@10 70 free(err);
yading@10 71 }
yading@10 72 if ((ret = cdio_cddap_open(s->drive)) < 0 || !s->drive->opened) {
yading@10 73 av_log(ctx, AV_LOG_ERROR, "Could not open disk in drive %s.\n", ctx->filename);
yading@10 74 return AVERROR(EINVAL);
yading@10 75 }
yading@10 76
yading@10 77 cdio_cddap_verbose_set(s->drive, CDDA_MESSAGE_LOGIT, CDDA_MESSAGE_LOGIT);
yading@10 78 if (s->speed)
yading@10 79 cdio_cddap_speed_set(s->drive, s->speed);
yading@10 80
yading@10 81 s->paranoia = cdio_paranoia_init(s->drive);
yading@10 82 if (!s->paranoia) {
yading@10 83 av_log(ctx, AV_LOG_ERROR, "Could not init paranoia.\n");
yading@10 84 return AVERROR(EINVAL);
yading@10 85 }
yading@10 86 cdio_paranoia_modeset(s->paranoia, s->paranoia_mode);
yading@10 87
yading@10 88 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
yading@10 89 if (s->drive->bigendianp)
yading@10 90 st->codec->codec_id = AV_CODEC_ID_PCM_S16BE;
yading@10 91 else
yading@10 92 st->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
yading@10 93 st->codec->sample_rate = 44100;
yading@10 94 st->codec->channels = 2;
yading@10 95 if (s->drive->audio_last_sector != CDIO_INVALID_LSN &&
yading@10 96 s->drive->audio_first_sector != CDIO_INVALID_LSN)
yading@10 97 st->duration = s->drive->audio_last_sector - s->drive->audio_first_sector;
yading@10 98 else if (s->drive->tracks)
yading@10 99 st->duration = s->drive->disc_toc[s->drive->tracks].dwStartSector;
yading@10 100 avpriv_set_pts_info(st, 64, CDIO_CD_FRAMESIZE_RAW, 2*st->codec->channels*st->codec->sample_rate);
yading@10 101
yading@10 102 for (i = 0; i < s->drive->tracks; i++) {
yading@10 103 char title[16];
yading@10 104 snprintf(title, sizeof(title), "track %02d", s->drive->disc_toc[i].bTrack);
yading@10 105 avpriv_new_chapter(ctx, i, st->time_base, s->drive->disc_toc[i].dwStartSector,
yading@10 106 s->drive->disc_toc[i+1].dwStartSector, title);
yading@10 107 }
yading@10 108
yading@10 109 s->last_sector = cdio_cddap_disc_lastsector(s->drive);
yading@10 110
yading@10 111 return 0;
yading@10 112 }
yading@10 113
yading@10 114 static int read_packet(AVFormatContext *ctx, AVPacket *pkt)
yading@10 115 {
yading@10 116 CDIOContext *s = ctx->priv_data;
yading@10 117 int ret;
yading@10 118 uint16_t *buf;
yading@10 119 char *err = NULL;
yading@10 120
yading@10 121 if (ctx->streams[0]->cur_dts > s->last_sector)
yading@10 122 return AVERROR_EOF;
yading@10 123
yading@10 124 buf = cdio_paranoia_read(s->paranoia, NULL);
yading@10 125 if (!buf)
yading@10 126 return AVERROR_EOF;
yading@10 127
yading@10 128 if (err = cdio_cddap_errors(s->drive)) {
yading@10 129 av_log(ctx, AV_LOG_ERROR, "%s\n", err);
yading@10 130 free(err);
yading@10 131 err = NULL;
yading@10 132 }
yading@10 133 if (err = cdio_cddap_messages(s->drive)) {
yading@10 134 av_log(ctx, AV_LOG_VERBOSE, "%s\n", err);
yading@10 135 free(err);
yading@10 136 err = NULL;
yading@10 137 }
yading@10 138
yading@10 139 if ((ret = av_new_packet(pkt, CDIO_CD_FRAMESIZE_RAW)) < 0)
yading@10 140 return ret;
yading@10 141 memcpy(pkt->data, buf, CDIO_CD_FRAMESIZE_RAW);
yading@10 142 return 0;
yading@10 143 }
yading@10 144
yading@10 145 static av_cold int read_close(AVFormatContext *ctx)
yading@10 146 {
yading@10 147 CDIOContext *s = ctx->priv_data;
yading@10 148 cdio_paranoia_free(s->paranoia);
yading@10 149 cdio_cddap_close(s->drive);
yading@10 150 return 0;
yading@10 151 }
yading@10 152
yading@10 153 static int read_seek(AVFormatContext *ctx, int stream_index, int64_t timestamp,
yading@10 154 int flags)
yading@10 155 {
yading@10 156 CDIOContext *s = ctx->priv_data;
yading@10 157 AVStream *st = ctx->streams[0];
yading@10 158
yading@10 159 cdio_paranoia_seek(s->paranoia, timestamp, SEEK_SET);
yading@10 160 st->cur_dts = timestamp;
yading@10 161 return 0;
yading@10 162 }
yading@10 163
yading@10 164 #define OFFSET(x) offsetof(CDIOContext, x)
yading@10 165 #define DEC AV_OPT_FLAG_DECODING_PARAM
yading@10 166 static const AVOption options[] = {
yading@10 167 { "speed", "Drive reading speed.", OFFSET(speed), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, DEC },
yading@10 168 { "paranoia_mode", "Error recovery mode.", OFFSET(paranoia_mode), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX, DEC, "paranoia_mode" },
yading@10 169 { "verify", "Verify data integrity in overlap area", 0, AV_OPT_TYPE_CONST, { .i64 = PARANOIA_MODE_VERIFY }, 0, 0, DEC, "paranoia_mode" },
yading@10 170 { "overlap", "Perform overlapped reads.", 0, AV_OPT_TYPE_CONST, { .i64 = PARANOIA_MODE_OVERLAP }, 0, 0, DEC, "paranoia_mode" },
yading@10 171 { "neverskip", "Do not skip failed reads.", 0, AV_OPT_TYPE_CONST, { .i64 = PARANOIA_MODE_NEVERSKIP }, 0, 0, DEC, "paranoia_mode" },
yading@10 172 { NULL },
yading@10 173 };
yading@10 174
yading@10 175 static const AVClass libcdio_class = {
yading@10 176 .class_name = "libcdio indev",
yading@10 177 .item_name = av_default_item_name,
yading@10 178 .option = options,
yading@10 179 .version = LIBAVUTIL_VERSION_INT,
yading@10 180 };
yading@10 181
yading@10 182 AVInputFormat ff_libcdio_demuxer = {
yading@10 183 .name = "libcdio",
yading@10 184 .read_header = read_header,
yading@10 185 .read_packet = read_packet,
yading@10 186 .read_close = read_close,
yading@10 187 .read_seek = read_seek,
yading@10 188 .priv_data_size = sizeof(CDIOContext),
yading@10 189 .flags = AVFMT_NOFILE,
yading@10 190 .priv_class = &libcdio_class,
yading@10 191 };