lavc: move some flac-specific options to its private context.
[ffmpeg.git] / libavformat / flacdec.c
1 /*
2  * Raw FLAC demuxer
3  * Copyright (c) 2001 Fabrice Bellard
4  *
5  * This file is part of Libav.
6  *
7  * Libav is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * Libav is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include "libavcodec/flac.h"
23 #include "avformat.h"
24 #include "rawdec.h"
25 #include "oggdec.h"
26 #include "vorbiscomment.h"
27
28 static int flac_read_header(AVFormatContext *s,
29                              AVFormatParameters *ap)
30 {
31     int ret, metadata_last=0, metadata_type, metadata_size, found_streaminfo=0;
32     uint8_t header[4];
33     uint8_t *buffer=NULL;
34     AVStream *st = av_new_stream(s, 0);
35     if (!st)
36         return AVERROR(ENOMEM);
37     st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
38     st->codec->codec_id = CODEC_ID_FLAC;
39     st->need_parsing = AVSTREAM_PARSE_FULL;
40     /* the parameters will be extracted from the compressed bitstream */
41
42     /* if fLaC marker is not found, assume there is no header */
43     if (avio_rl32(s->pb) != MKTAG('f','L','a','C')) {
44         avio_seek(s->pb, -4, SEEK_CUR);
45         return 0;
46     }
47
48     /* process metadata blocks */
49     while (!s->pb->eof_reached && !metadata_last) {
50         avio_read(s->pb, header, 4);
51         ff_flac_parse_block_header(header, &metadata_last, &metadata_type,
52                                    &metadata_size);
53         switch (metadata_type) {
54         /* allocate and read metadata block for supported types */
55         case FLAC_METADATA_TYPE_STREAMINFO:
56         case FLAC_METADATA_TYPE_VORBIS_COMMENT:
57             buffer = av_mallocz(metadata_size + FF_INPUT_BUFFER_PADDING_SIZE);
58             if (!buffer) {
59                 return AVERROR(ENOMEM);
60             }
61             if (avio_read(s->pb, buffer, metadata_size) != metadata_size) {
62                 av_freep(&buffer);
63                 return AVERROR(EIO);
64             }
65             break;
66         /* skip metadata block for unsupported types */
67         default:
68             ret = avio_skip(s->pb, metadata_size);
69             if (ret < 0)
70                 return ret;
71         }
72
73         if (metadata_type == FLAC_METADATA_TYPE_STREAMINFO) {
74             FLACStreaminfo si;
75             /* STREAMINFO can only occur once */
76             if (found_streaminfo) {
77                 av_freep(&buffer);
78                 return AVERROR_INVALIDDATA;
79             }
80             if (metadata_size != FLAC_STREAMINFO_SIZE) {
81                 av_freep(&buffer);
82                 return AVERROR_INVALIDDATA;
83             }
84             found_streaminfo = 1;
85             st->codec->extradata      = buffer;
86             st->codec->extradata_size = metadata_size;
87             buffer = NULL;
88
89             /* get codec params from STREAMINFO header */
90             ff_flac_parse_streaminfo(st->codec, &si, st->codec->extradata);
91
92             /* set time base and duration */
93             if (si.samplerate > 0) {
94                 av_set_pts_info(st, 64, 1, si.samplerate);
95                 if (si.samples > 0)
96                     st->duration = si.samples;
97             }
98         } else {
99             /* STREAMINFO must be the first block */
100             if (!found_streaminfo) {
101                 av_freep(&buffer);
102                 return AVERROR_INVALIDDATA;
103             }
104             /* process supported blocks other than STREAMINFO */
105             if (metadata_type == FLAC_METADATA_TYPE_VORBIS_COMMENT) {
106                 if (ff_vorbis_comment(s, &s->metadata, buffer, metadata_size)) {
107                     av_log(s, AV_LOG_WARNING, "error parsing VorbisComment metadata\n");
108                 }
109             }
110             av_freep(&buffer);
111         }
112     }
113
114     return 0;
115 }
116
117 static int flac_probe(AVProbeData *p)
118 {
119     uint8_t *bufptr = p->buf;
120     uint8_t *end    = p->buf + p->buf_size;
121
122     if(bufptr > end-4 || memcmp(bufptr, "fLaC", 4)) return 0;
123     else                                            return AVPROBE_SCORE_MAX/2;
124 }
125
126 AVInputFormat ff_flac_demuxer = {
127     "flac",
128     NULL_IF_CONFIG_SMALL("raw FLAC"),
129     0,
130     flac_probe,
131     flac_read_header,
132     ff_raw_read_partial_packet,
133     .flags= AVFMT_GENERIC_INDEX,
134     .extensions = "flac",
135     .value = CODEC_ID_FLAC,
136 };