00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavcodec/flac.h"
00023 #include "avformat.h"
00024 #include "id3v2.h"
00025 #include "internal.h"
00026 #include "rawdec.h"
00027 #include "oggdec.h"
00028 #include "vorbiscomment.h"
00029 #include "libavcodec/bytestream.h"
00030
00031 #define RETURN_ERROR(code) do { ret = (code); goto fail; } while (0)
00032
00033 static int parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size)
00034 {
00035 const CodecMime *mime = ff_id3v2_mime_tags;
00036 enum AVCodecID id = AV_CODEC_ID_NONE;
00037 uint8_t mimetype[64], *desc = NULL, *data = NULL;
00038 AVIOContext *pb = NULL;
00039 AVStream *st;
00040 int type, width, height;
00041 int len, ret = 0;
00042
00043 pb = avio_alloc_context(buf, buf_size, 0, NULL, NULL, NULL, NULL);
00044 if (!pb)
00045 return AVERROR(ENOMEM);
00046
00047
00048 type = avio_rb32(pb);
00049 if (type >= FF_ARRAY_ELEMS(ff_id3v2_picture_types) || type < 0) {
00050 av_log(s, AV_LOG_ERROR, "Invalid picture type: %d.\n", type);
00051 if (s->error_recognition & AV_EF_EXPLODE) {
00052 RETURN_ERROR(AVERROR_INVALIDDATA);
00053 }
00054 type = 0;
00055 }
00056
00057
00058 len = avio_rb32(pb);
00059 if (len <= 0 ||
00060 avio_read(pb, mimetype, FFMIN(len, sizeof(mimetype) - 1)) != len) {
00061 av_log(s, AV_LOG_ERROR, "Could not read mimetype from an attached "
00062 "picture.\n");
00063 if (s->error_recognition & AV_EF_EXPLODE)
00064 ret = AVERROR_INVALIDDATA;
00065 goto fail;
00066 }
00067 mimetype[len] = 0;
00068
00069 while (mime->id != AV_CODEC_ID_NONE) {
00070 if (!strncmp(mime->str, mimetype, sizeof(mimetype))) {
00071 id = mime->id;
00072 break;
00073 }
00074 mime++;
00075 }
00076 if (id == AV_CODEC_ID_NONE) {
00077 av_log(s, AV_LOG_ERROR, "Unknown attached picture mimetype: %s.\n",
00078 mimetype);
00079 if (s->error_recognition & AV_EF_EXPLODE)
00080 ret = AVERROR_INVALIDDATA;
00081 goto fail;
00082 }
00083
00084
00085 len = avio_rb32(pb);
00086 if (len > 0) {
00087 if (!(desc = av_malloc(len + 1))) {
00088 RETURN_ERROR(AVERROR(ENOMEM));
00089 }
00090
00091 if (avio_read(pb, desc, len) != len) {
00092 av_log(s, AV_LOG_ERROR, "Error reading attached picture description.\n");
00093 if (s->error_recognition & AV_EF_EXPLODE)
00094 ret = AVERROR(EIO);
00095 goto fail;
00096 }
00097 desc[len] = 0;
00098 }
00099
00100
00101 width = avio_rb32(pb);
00102 height = avio_rb32(pb);
00103 avio_skip(pb, 8);
00104
00105
00106 len = avio_rb32(pb);
00107 if (len <= 0) {
00108 av_log(s, AV_LOG_ERROR, "Invalid attached picture size: %d.\n", len);
00109 if (s->error_recognition & AV_EF_EXPLODE)
00110 ret = AVERROR_INVALIDDATA;
00111 goto fail;
00112 }
00113 if (!(data = av_malloc(len))) {
00114 RETURN_ERROR(AVERROR(ENOMEM));
00115 }
00116 if (avio_read(pb, data, len) != len) {
00117 av_log(s, AV_LOG_ERROR, "Error reading attached picture data.\n");
00118 if (s->error_recognition & AV_EF_EXPLODE)
00119 ret = AVERROR(EIO);
00120 goto fail;
00121 }
00122
00123 st = avformat_new_stream(s, NULL);
00124 if (!st) {
00125 RETURN_ERROR(AVERROR(ENOMEM));
00126 }
00127
00128 av_init_packet(&st->attached_pic);
00129 st->attached_pic.data = data;
00130 st->attached_pic.size = len;
00131 st->attached_pic.destruct = av_destruct_packet;
00132 st->attached_pic.stream_index = st->index;
00133 st->attached_pic.flags |= AV_PKT_FLAG_KEY;
00134
00135 st->disposition |= AV_DISPOSITION_ATTACHED_PIC;
00136 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00137 st->codec->codec_id = id;
00138 st->codec->width = width;
00139 st->codec->height = height;
00140 av_dict_set(&st->metadata, "comment", ff_id3v2_picture_types[type], 0);
00141 if (desc)
00142 av_dict_set(&st->metadata, "title", desc, AV_DICT_DONT_STRDUP_VAL);
00143
00144 av_freep(&pb);
00145
00146 return 0;
00147
00148 fail:
00149 av_freep(&desc);
00150 av_freep(&data);
00151 av_freep(&pb);
00152 return ret;
00153
00154 }
00155
00156 static int flac_read_header(AVFormatContext *s)
00157 {
00158 int ret, metadata_last=0, metadata_type, metadata_size, found_streaminfo=0;
00159 uint8_t header[4];
00160 uint8_t *buffer=NULL;
00161 AVStream *st = avformat_new_stream(s, NULL);
00162 if (!st)
00163 return AVERROR(ENOMEM);
00164 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00165 st->codec->codec_id = AV_CODEC_ID_FLAC;
00166 st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
00167
00168
00169
00170 if (avio_rl32(s->pb) != MKTAG('f','L','a','C')) {
00171 avio_seek(s->pb, -4, SEEK_CUR);
00172 return 0;
00173 }
00174
00175
00176 while (!url_feof(s->pb) && !metadata_last) {
00177 avio_read(s->pb, header, 4);
00178 avpriv_flac_parse_block_header(header, &metadata_last, &metadata_type,
00179 &metadata_size);
00180 switch (metadata_type) {
00181
00182 case FLAC_METADATA_TYPE_STREAMINFO:
00183 case FLAC_METADATA_TYPE_CUESHEET:
00184 case FLAC_METADATA_TYPE_PICTURE:
00185 case FLAC_METADATA_TYPE_VORBIS_COMMENT:
00186 buffer = av_mallocz(metadata_size + FF_INPUT_BUFFER_PADDING_SIZE);
00187 if (!buffer) {
00188 return AVERROR(ENOMEM);
00189 }
00190 if (avio_read(s->pb, buffer, metadata_size) != metadata_size) {
00191 RETURN_ERROR(AVERROR(EIO));
00192 }
00193 break;
00194
00195 default:
00196 ret = avio_skip(s->pb, metadata_size);
00197 if (ret < 0)
00198 return ret;
00199 }
00200
00201 if (metadata_type == FLAC_METADATA_TYPE_STREAMINFO) {
00202 FLACStreaminfo si;
00203
00204 if (found_streaminfo) {
00205 RETURN_ERROR(AVERROR_INVALIDDATA);
00206 }
00207 if (metadata_size != FLAC_STREAMINFO_SIZE) {
00208 RETURN_ERROR(AVERROR_INVALIDDATA);
00209 }
00210 found_streaminfo = 1;
00211 st->codec->extradata = buffer;
00212 st->codec->extradata_size = metadata_size;
00213 buffer = NULL;
00214
00215
00216 avpriv_flac_parse_streaminfo(st->codec, &si, st->codec->extradata);
00217
00218
00219 if (si.samplerate > 0) {
00220 avpriv_set_pts_info(st, 64, 1, si.samplerate);
00221 if (si.samples > 0)
00222 st->duration = si.samples;
00223 }
00224 } else if (metadata_type == FLAC_METADATA_TYPE_CUESHEET) {
00225 uint8_t isrc[13];
00226 uint64_t start;
00227 const uint8_t *offset;
00228 int i, chapters, track, ti;
00229 if (metadata_size < 431)
00230 RETURN_ERROR(AVERROR_INVALIDDATA);
00231 offset = buffer + 395;
00232 chapters = bytestream_get_byte(&offset) - 1;
00233 if (chapters <= 0)
00234 RETURN_ERROR(AVERROR_INVALIDDATA);
00235 for (i = 0; i < chapters; i++) {
00236 if (offset + 36 - buffer > metadata_size)
00237 RETURN_ERROR(AVERROR_INVALIDDATA);
00238 start = bytestream_get_be64(&offset);
00239 track = bytestream_get_byte(&offset);
00240 bytestream_get_buffer(&offset, isrc, 12);
00241 isrc[12] = 0;
00242 offset += 14;
00243 ti = bytestream_get_byte(&offset);
00244 if (ti <= 0) RETURN_ERROR(AVERROR_INVALIDDATA);
00245 offset += ti * 12;
00246 avpriv_new_chapter(s, track, st->time_base, start, AV_NOPTS_VALUE, isrc);
00247 }
00248 av_freep(&buffer);
00249 } else if (metadata_type == FLAC_METADATA_TYPE_PICTURE) {
00250 ret = parse_picture(s, buffer, metadata_size);
00251 av_freep(&buffer);
00252 if (ret < 0) {
00253 av_log(s, AV_LOG_ERROR, "Error parsing attached picture.\n");
00254 return ret;
00255 }
00256 } else {
00257
00258 if (!found_streaminfo) {
00259 RETURN_ERROR(AVERROR_INVALIDDATA);
00260 }
00261
00262 if (metadata_type == FLAC_METADATA_TYPE_VORBIS_COMMENT) {
00263 if (ff_vorbis_comment(s, &s->metadata, buffer, metadata_size)) {
00264 av_log(s, AV_LOG_WARNING, "error parsing VorbisComment metadata\n");
00265 }
00266 }
00267 av_freep(&buffer);
00268 }
00269 }
00270
00271 return 0;
00272
00273 fail:
00274 av_free(buffer);
00275 return ret;
00276 }
00277
00278 static int flac_probe(AVProbeData *p)
00279 {
00280 uint8_t *bufptr = p->buf;
00281 uint8_t *end = p->buf + p->buf_size;
00282
00283 if(bufptr > end-4 || memcmp(bufptr, "fLaC", 4)) return 0;
00284 else return AVPROBE_SCORE_MAX/2;
00285 }
00286
00287 AVInputFormat ff_flac_demuxer = {
00288 .name = "flac",
00289 .long_name = NULL_IF_CONFIG_SMALL("raw FLAC"),
00290 .read_probe = flac_probe,
00291 .read_header = flac_read_header,
00292 .read_packet = ff_raw_read_partial_packet,
00293 .flags = AVFMT_GENERIC_INDEX,
00294 .extensions = "flac",
00295 .raw_codec_id = AV_CODEC_ID_FLAC,
00296 };