]> git.sesse.net Git - ffmpeg/blob - libavformat/flacdec.c
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libavformat / flacdec.c
1 /*
2  * Raw FLAC demuxer
3  * Copyright (c) 2001 Fabrice Bellard
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg 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  * FFmpeg 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 FFmpeg; 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 "internal.h"
25 #include "rawdec.h"
26 #include "oggdec.h"
27 #include "vorbiscomment.h"
28 #include "libavcodec/bytestream.h"
29
30 static int flac_read_header(AVFormatContext *s)
31 {
32     int ret, metadata_last=0, metadata_type, metadata_size, found_streaminfo=0;
33     uint8_t header[4];
34     uint8_t *buffer=NULL;
35     AVStream *st = avformat_new_stream(s, NULL);
36     if (!st)
37         return AVERROR(ENOMEM);
38     st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
39     st->codec->codec_id = CODEC_ID_FLAC;
40     st->need_parsing = AVSTREAM_PARSE_FULL;
41     /* the parameters will be extracted from the compressed bitstream */
42
43     /* if fLaC marker is not found, assume there is no header */
44     if (avio_rl32(s->pb) != MKTAG('f','L','a','C')) {
45         avio_seek(s->pb, -4, SEEK_CUR);
46         return 0;
47     }
48
49     /* process metadata blocks */
50     while (!url_feof(s->pb) && !metadata_last) {
51         avio_read(s->pb, header, 4);
52         avpriv_flac_parse_block_header(header, &metadata_last, &metadata_type,
53                                    &metadata_size);
54         switch (metadata_type) {
55         /* allocate and read metadata block for supported types */
56         case FLAC_METADATA_TYPE_STREAMINFO:
57         case FLAC_METADATA_TYPE_CUESHEET:
58         case FLAC_METADATA_TYPE_VORBIS_COMMENT:
59             buffer = av_mallocz(metadata_size + FF_INPUT_BUFFER_PADDING_SIZE);
60             if (!buffer) {
61                 return AVERROR(ENOMEM);
62             }
63             if (avio_read(s->pb, buffer, metadata_size) != metadata_size) {
64                 av_freep(&buffer);
65                 return AVERROR(EIO);
66             }
67             break;
68         /* skip metadata block for unsupported types */
69         default:
70             ret = avio_skip(s->pb, metadata_size);
71             if (ret < 0)
72                 return ret;
73         }
74
75         if (metadata_type == FLAC_METADATA_TYPE_STREAMINFO) {
76             FLACStreaminfo si;
77             /* STREAMINFO can only occur once */
78             if (found_streaminfo) {
79                 av_freep(&buffer);
80                 return AVERROR_INVALIDDATA;
81             }
82             if (metadata_size != FLAC_STREAMINFO_SIZE) {
83                 av_freep(&buffer);
84                 return AVERROR_INVALIDDATA;
85             }
86             found_streaminfo = 1;
87             st->codec->extradata      = buffer;
88             st->codec->extradata_size = metadata_size;
89             buffer = NULL;
90
91             /* get codec params from STREAMINFO header */
92             avpriv_flac_parse_streaminfo(st->codec, &si, st->codec->extradata);
93
94             /* set time base and duration */
95             if (si.samplerate > 0) {
96                 avpriv_set_pts_info(st, 64, 1, si.samplerate);
97                 if (si.samples > 0)
98                     st->duration = si.samples;
99             }
100         } else if (metadata_type == FLAC_METADATA_TYPE_CUESHEET) {
101             uint8_t isrc[13];
102             uint64_t start;
103             const uint8_t *offset;
104             int i, chapters, track, ti;
105             if (metadata_size < 431)
106                 return AVERROR_INVALIDDATA;
107             offset = buffer + 395;
108             chapters = bytestream_get_byte(&offset) - 1;
109             if (chapters <= 0)
110                 return AVERROR_INVALIDDATA;
111             for (i = 0; i < chapters; i++) {
112                 if (offset + 36 - buffer > metadata_size)
113                     return AVERROR_INVALIDDATA;
114                 start = bytestream_get_be64(&offset);
115                 track = bytestream_get_byte(&offset);
116                 bytestream_get_buffer(&offset, isrc, 12);
117                 isrc[12] = 0;
118                 offset += 14;
119                 ti = bytestream_get_byte(&offset);
120                 if (ti <= 0) return AVERROR_INVALIDDATA;
121                 offset += ti * 12;
122                 avpriv_new_chapter(s, track, st->time_base, start, AV_NOPTS_VALUE, isrc);
123             }
124         } else {
125             /* STREAMINFO must be the first block */
126             if (!found_streaminfo) {
127                 av_freep(&buffer);
128                 return AVERROR_INVALIDDATA;
129             }
130             /* process supported blocks other than STREAMINFO */
131             if (metadata_type == FLAC_METADATA_TYPE_VORBIS_COMMENT) {
132                 if (ff_vorbis_comment(s, &s->metadata, buffer, metadata_size)) {
133                     av_log(s, AV_LOG_WARNING, "error parsing VorbisComment metadata\n");
134                 }
135             }
136             av_freep(&buffer);
137         }
138     }
139
140     return 0;
141 }
142
143 static int flac_probe(AVProbeData *p)
144 {
145     uint8_t *bufptr = p->buf;
146     uint8_t *end    = p->buf + p->buf_size;
147
148     if(bufptr > end-4 || memcmp(bufptr, "fLaC", 4)) return 0;
149     else                                            return AVPROBE_SCORE_MAX/2;
150 }
151
152 AVInputFormat ff_flac_demuxer = {
153     .name           = "flac",
154     .long_name      = NULL_IF_CONFIG_SMALL("raw FLAC"),
155     .read_probe     = flac_probe,
156     .read_header    = flac_read_header,
157     .read_packet    = ff_raw_read_partial_packet,
158     .flags= AVFMT_GENERIC_INDEX,
159     .extensions = "flac",
160     .value = CODEC_ID_FLAC,
161 };