ffmpeg / libavformat / flacdec.c @ 45a8a02a
History | View | Annotate | Download (4.58 KB)
1 | 81f052cb | Justin Ruggles | /*
|
---|---|---|---|
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 | f48b9304 | Justin Ruggles | #include "libavcodec/flac.h" |
23 | 81f052cb | Justin Ruggles | #include "avformat.h" |
24 | 4ca31edc | Aurelien Jacobs | #include "rawdec.h" |
25 | f48b9304 | Justin Ruggles | #include "oggdec.h" |
26 | 66061a12 | James Darnley | #include "vorbiscomment.h" |
27 | 81f052cb | Justin Ruggles | |
28 | static int flac_read_header(AVFormatContext *s, |
||
29 | AVFormatParameters *ap) |
||
30 | { |
||
31 | f48b9304 | Justin Ruggles | int ret, metadata_last=0, metadata_type, metadata_size, found_streaminfo=0; |
32 | uint8_t header[4];
|
||
33 | uint8_t *buffer=NULL;
|
||
34 | 81f052cb | Justin Ruggles | AVStream *st = av_new_stream(s, 0);
|
35 | if (!st)
|
||
36 | return AVERROR(ENOMEM);
|
||
37 | 72415b2a | Stefano Sabatini | st->codec->codec_type = AVMEDIA_TYPE_AUDIO; |
38 | 81f052cb | Justin Ruggles | 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 | f48b9304 | Justin Ruggles | /* if fLaC marker is not found, assume there is no header */
|
43 | b7effd4e | Anton Khirnov | if (avio_rl32(s->pb) != MKTAG('f','L','a','C')) { |
44 | 6b4aa5da | Anton Khirnov | avio_seek(s->pb, -4, SEEK_CUR);
|
45 | f48b9304 | Justin Ruggles | return 0; |
46 | 29b0d168 | Justin Ruggles | } |
47 | f48b9304 | Justin Ruggles | |
48 | /* process metadata blocks */
|
||
49 | 66e5b1df | Anton Khirnov | while (!s->pb->eof_reached && !metadata_last) {
|
50 | b7effd4e | Anton Khirnov | avio_read(s->pb, header, 4);
|
51 | f48b9304 | Justin Ruggles | 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 | 2874c81c | Stefano Sabatini | return AVERROR(ENOMEM);
|
60 | f48b9304 | Justin Ruggles | } |
61 | b7effd4e | Anton Khirnov | if (avio_read(s->pb, buffer, metadata_size) != metadata_size) {
|
62 | f48b9304 | Justin Ruggles | av_freep(&buffer); |
63 | 5ae092ee | Stefano Sabatini | return AVERROR(EIO);
|
64 | f48b9304 | Justin Ruggles | } |
65 | break;
|
||
66 | /* skip metadata block for unsupported types */
|
||
67 | default:
|
||
68 | 45a8a02a | Anton Khirnov | ret = avio_skip(s->pb, metadata_size); |
69 | f48b9304 | Justin Ruggles | 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 | b53cde48 | David Conrad | if (ff_vorbis_comment(s, &s->metadata, buffer, metadata_size)) {
|
107 | f48b9304 | Justin Ruggles | av_log(s, AV_LOG_WARNING, "error parsing VorbisComment metadata\n");
|
108 | } |
||
109 | } |
||
110 | av_freep(&buffer); |
||
111 | } |
||
112 | } |
||
113 | |||
114 | 81f052cb | Justin Ruggles | 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 | c6610a21 | Diego Elio Pettenò | AVInputFormat ff_flac_demuxer = { |
127 | 81f052cb | Justin Ruggles | "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 | }; |