Libav 0.7.1
|
00001 /* 00002 * Raw FLAC demuxer 00003 * Copyright (c) 2001 Fabrice Bellard 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 #include "libavcodec/flac.h" 00023 #include "avformat.h" 00024 #include "rawdec.h" 00025 #include "oggdec.h" 00026 #include "vorbiscomment.h" 00027 00028 static int flac_read_header(AVFormatContext *s, 00029 AVFormatParameters *ap) 00030 { 00031 int ret, metadata_last=0, metadata_type, metadata_size, found_streaminfo=0; 00032 uint8_t header[4]; 00033 uint8_t *buffer=NULL; 00034 AVStream *st = av_new_stream(s, 0); 00035 if (!st) 00036 return AVERROR(ENOMEM); 00037 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; 00038 st->codec->codec_id = CODEC_ID_FLAC; 00039 st->need_parsing = AVSTREAM_PARSE_FULL; 00040 /* the parameters will be extracted from the compressed bitstream */ 00041 00042 /* if fLaC marker is not found, assume there is no header */ 00043 if (avio_rl32(s->pb) != MKTAG('f','L','a','C')) { 00044 avio_seek(s->pb, -4, SEEK_CUR); 00045 return 0; 00046 } 00047 00048 /* process metadata blocks */ 00049 while (!s->pb->eof_reached && !metadata_last) { 00050 avio_read(s->pb, header, 4); 00051 ff_flac_parse_block_header(header, &metadata_last, &metadata_type, 00052 &metadata_size); 00053 switch (metadata_type) { 00054 /* allocate and read metadata block for supported types */ 00055 case FLAC_METADATA_TYPE_STREAMINFO: 00056 case FLAC_METADATA_TYPE_VORBIS_COMMENT: 00057 buffer = av_mallocz(metadata_size + FF_INPUT_BUFFER_PADDING_SIZE); 00058 if (!buffer) { 00059 return AVERROR(ENOMEM); 00060 } 00061 if (avio_read(s->pb, buffer, metadata_size) != metadata_size) { 00062 av_freep(&buffer); 00063 return AVERROR(EIO); 00064 } 00065 break; 00066 /* skip metadata block for unsupported types */ 00067 default: 00068 ret = avio_skip(s->pb, metadata_size); 00069 if (ret < 0) 00070 return ret; 00071 } 00072 00073 if (metadata_type == FLAC_METADATA_TYPE_STREAMINFO) { 00074 FLACStreaminfo si; 00075 /* STREAMINFO can only occur once */ 00076 if (found_streaminfo) { 00077 av_freep(&buffer); 00078 return AVERROR_INVALIDDATA; 00079 } 00080 if (metadata_size != FLAC_STREAMINFO_SIZE) { 00081 av_freep(&buffer); 00082 return AVERROR_INVALIDDATA; 00083 } 00084 found_streaminfo = 1; 00085 st->codec->extradata = buffer; 00086 st->codec->extradata_size = metadata_size; 00087 buffer = NULL; 00088 00089 /* get codec params from STREAMINFO header */ 00090 ff_flac_parse_streaminfo(st->codec, &si, st->codec->extradata); 00091 00092 /* set time base and duration */ 00093 if (si.samplerate > 0) { 00094 av_set_pts_info(st, 64, 1, si.samplerate); 00095 if (si.samples > 0) 00096 st->duration = si.samples; 00097 } 00098 } else { 00099 /* STREAMINFO must be the first block */ 00100 if (!found_streaminfo) { 00101 av_freep(&buffer); 00102 return AVERROR_INVALIDDATA; 00103 } 00104 /* process supported blocks other than STREAMINFO */ 00105 if (metadata_type == FLAC_METADATA_TYPE_VORBIS_COMMENT) { 00106 if (ff_vorbis_comment(s, &s->metadata, buffer, metadata_size)) { 00107 av_log(s, AV_LOG_WARNING, "error parsing VorbisComment metadata\n"); 00108 } 00109 } 00110 av_freep(&buffer); 00111 } 00112 } 00113 00114 return 0; 00115 } 00116 00117 static int flac_probe(AVProbeData *p) 00118 { 00119 uint8_t *bufptr = p->buf; 00120 uint8_t *end = p->buf + p->buf_size; 00121 00122 if(bufptr > end-4 || memcmp(bufptr, "fLaC", 4)) return 0; 00123 else return AVPROBE_SCORE_MAX/2; 00124 } 00125 00126 AVInputFormat ff_flac_demuxer = { 00127 "flac", 00128 NULL_IF_CONFIG_SMALL("raw FLAC"), 00129 0, 00130 flac_probe, 00131 flac_read_header, 00132 ff_raw_read_partial_packet, 00133 .flags= AVFMT_GENERIC_INDEX, 00134 .extensions = "flac", 00135 .value = CODEC_ID_FLAC, 00136 };