~ubuntu-branches/debian/sid/mplayer/sid

« back to all changes in this revision

Viewing changes to libavformat/oggparsevorbis.c

  • Committer: Bazaar Package Importer
  • Author(s): A Mennucc1
  • Date: 2009-03-23 10:05:45 UTC
  • mfrom: (4.1.4 sid)
  • Revision ID: james.westby@ubuntu.com-20090323100545-x8h79obawnnte7kk
Tags: 1.0~rc2+svn20090303-5
debian/control : move docbook-xml,docbook-xsl,xsltproc from 
Build-Depends-Indep to Build-Depends, since they are needed to run
configure

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
**/
24
24
 
25
25
#include <stdlib.h>
 
26
#include "libavutil/avstring.h"
 
27
#include "libavutil/bswap.h"
 
28
#include "libavcodec/bitstream.h"
 
29
#include "libavcodec/bytestream.h"
26
30
#include "avformat.h"
27
 
#include "bitstream.h"
28
 
#include "bswap.h"
29
 
#include "ogg2.h"
30
 
#include "avstring.h"
 
31
#include "oggdec.h"
31
32
 
32
 
extern int
 
33
int
33
34
vorbis_comment(AVFormatContext * as, uint8_t *buf, int size)
34
35
{
35
 
    char *p = buf;
36
 
    int s, n, j;
 
36
    const uint8_t *p = buf;
 
37
    const uint8_t *end = buf + size;
 
38
    unsigned s, n, j;
37
39
 
38
 
    if (size < 4)
 
40
    if (size < 8) /* must have vendor_length and user_comment_list_length */
39
41
        return -1;
40
42
 
41
 
    s = AV_RL32(p);
42
 
    p += 4;
43
 
    size -= 4;
 
43
    s = bytestream_get_le32(&p);
44
44
 
45
 
    if (size < s + 4)
 
45
    if (end - p < s)
46
46
        return -1;
47
47
 
48
48
    p += s;
49
 
    size -= s;
50
 
 
51
 
    n = AV_RL32(p);
52
 
    p += 4;
53
 
    size -= 4;
54
 
 
55
 
    while (size >= 4) {
56
 
        char *t, *v;
 
49
 
 
50
    n = bytestream_get_le32(&p);
 
51
 
 
52
    while (p < end && n > 0) {
 
53
        const char *t, *v;
57
54
        int tl, vl;
58
55
 
59
 
        s = AV_RL32(p);
60
 
        p += 4;
61
 
        size -= 4;
 
56
        s = bytestream_get_le32(&p);
62
57
 
63
 
        if (size < s)
 
58
        if (end - p < s)
64
59
            break;
65
60
 
66
61
        t = p;
67
62
        p += s;
68
 
        size -= s;
69
63
        n--;
70
64
 
71
65
        v = memchr(t, '=', s);
77
71
        v++;
78
72
 
79
73
        if (tl && vl) {
80
 
            char tt[tl + 1];
81
 
            char ct[vl + 1];
 
74
            char *tt, *ct;
 
75
 
 
76
            tt = av_malloc(tl + 1);
 
77
            ct = av_malloc(vl + 1);
 
78
            if (!tt || !ct) {
 
79
                av_freep(&tt);
 
80
                av_freep(&ct);
 
81
                av_log(as, AV_LOG_WARNING, "out-of-memory error. skipping VorbisComment tag.\n");
 
82
                continue;
 
83
            }
82
84
 
83
85
            for (j = 0; j < tl; j++)
84
86
                tt[j] = toupper(t[j]);
87
89
            memcpy(ct, v, vl);
88
90
            ct[vl] = 0;
89
91
 
90
 
            // took from Vorbis_I_spec
91
 
            if (!strcmp(tt, "AUTHOR") || !strcmp(tt, "ARTIST"))
92
 
                av_strlcpy(as->author, ct, sizeof(as->author));
93
 
            else if (!strcmp(tt, "TITLE"))
94
 
                av_strlcpy(as->title, ct, sizeof(as->title));
95
 
            else if (!strcmp(tt, "COPYRIGHT"))
96
 
                av_strlcpy(as->copyright, ct, sizeof(as->copyright));
97
 
            else if (!strcmp(tt, "DESCRIPTION"))
98
 
                av_strlcpy(as->comment, ct, sizeof(as->comment));
99
 
            else if (!strcmp(tt, "GENRE"))
100
 
                av_strlcpy(as->genre, ct, sizeof(as->genre));
101
 
            else if (!strcmp(tt, "TRACKNUMBER"))
102
 
                as->track = atoi(ct);
103
 
            else if (!strcmp(tt, "ALBUM"))
104
 
                av_strlcpy(as->album, ct, sizeof(as->album));
105
 
            else if (!strcmp(tt, "GENRE"))
106
 
                av_strlcpy(as->genre, ct, sizeof(as->genre));
107
 
            else if (!strcmp(tt, "DESCRIPTION"))
108
 
                av_strlcpy(as->comment, ct, sizeof(as->comment));
 
92
            av_metadata_set(&as->metadata, tt, ct);
 
93
 
 
94
            av_freep(&tt);
 
95
            av_freep(&ct);
109
96
        }
110
97
    }
111
98
 
112
 
    if (size > 0)
113
 
        av_log(as, AV_LOG_INFO, "%i bytes of comment header remain\n", size);
 
99
    if (p != end)
 
100
        av_log(as, AV_LOG_INFO, "%ti bytes of comment header remain\n", p-end);
114
101
    if (n > 0)
115
102
        av_log(as, AV_LOG_INFO,
116
103
               "truncated comment header, %i comments not found\n", n);
132
119
 * [framing_flag] = read one bit | Not Used
133
120
 *    */
134
121
 
135
 
typedef struct {
 
122
struct oggvorbis_private {
136
123
    unsigned int len[3];
137
124
    unsigned char *packet[3];
138
 
} oggvorbis_private_t;
 
125
};
139
126
 
140
127
 
141
128
static unsigned int
142
 
fixup_vorbis_headers(AVFormatContext * as, oggvorbis_private_t *priv,
 
129
fixup_vorbis_headers(AVFormatContext * as, struct oggvorbis_private *priv,
143
130
                     uint8_t **buf)
144
131
{
145
132
    int i,offset, len;
156
143
        memcpy(&ptr[offset], priv->packet[i], priv->len[i]);
157
144
        offset += priv->len[i];
158
145
    }
159
 
    *buf = av_realloc(*buf, offset);
 
146
    *buf = av_realloc(*buf, offset + FF_INPUT_BUFFER_PADDING_SIZE);
160
147
    return offset;
161
148
}
162
149
 
164
151
static int
165
152
vorbis_header (AVFormatContext * s, int idx)
166
153
{
167
 
    ogg_t *ogg = s->priv_data;
168
 
    ogg_stream_t *os = ogg->streams + idx;
 
154
    struct ogg *ogg = s->priv_data;
 
155
    struct ogg_stream *os = ogg->streams + idx;
169
156
    AVStream *st = s->streams[idx];
170
 
    oggvorbis_private_t *priv;
 
157
    struct oggvorbis_private *priv;
171
158
 
172
159
    if (os->seq > 2)
173
160
        return 0;
174
161
 
175
162
    if (os->seq == 0) {
176
 
        os->private = av_mallocz(sizeof(oggvorbis_private_t));
 
163
        os->private = av_mallocz(sizeof(struct oggvorbis_private));
177
164
        if (!os->private)
178
165
            return 0;
179
166
    }
180
167
 
 
168
    if (os->psize < 1)
 
169
        return -1;
 
170
 
181
171
    priv = os->private;
182
172
    priv->len[os->seq] = os->psize;
183
173
    priv->packet[os->seq] = av_mallocz(os->psize);
184
174
    memcpy(priv->packet[os->seq], os->buf + os->pstart, os->psize);
185
175
    if (os->buf[os->pstart] == 1) {
186
 
        uint8_t *p = os->buf + os->pstart + 11; //skip up to the audio channels
187
 
        st->codec->channels = *p++;
188
 
        st->codec->sample_rate = AV_RL32(p);
189
 
        p += 8; //skip maximum and and nominal bitrate
190
 
        st->codec->bit_rate = AV_RL32(p); //Minimum bitrate
 
176
        const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */
 
177
        unsigned blocksize, bs0, bs1;
 
178
 
 
179
        if (os->psize != 30)
 
180
            return -1;
 
181
 
 
182
        if (bytestream_get_le32(&p) != 0) /* vorbis_version */
 
183
            return -1;
 
184
 
 
185
        st->codec->channels = bytestream_get_byte(&p);
 
186
        st->codec->sample_rate = bytestream_get_le32(&p);
 
187
        p += 4; // skip maximum bitrate
 
188
        st->codec->bit_rate = bytestream_get_le32(&p); // nominal bitrate
 
189
        p += 4; // skip minimum bitrate
 
190
 
 
191
        blocksize = bytestream_get_byte(&p);
 
192
        bs0 = blocksize & 15;
 
193
        bs1 = blocksize >> 4;
 
194
 
 
195
        if (bs0 > bs1)
 
196
            return -1;
 
197
        if (bs0 < 6 || bs1 > 13)
 
198
            return -1;
 
199
 
 
200
        if (bytestream_get_byte(&p) != 1) /* framing_flag */
 
201
            return -1;
191
202
 
192
203
        st->codec->codec_type = CODEC_TYPE_AUDIO;
193
204
        st->codec->codec_id = CODEC_ID_VORBIS;
195
206
        st->time_base.num = 1;
196
207
        st->time_base.den = st->codec->sample_rate;
197
208
    } else if (os->buf[os->pstart] == 3) {
198
 
        vorbis_comment (s, os->buf + os->pstart + 7, os->psize - 8);
 
209
        if (os->psize > 8)
 
210
            vorbis_comment (s, os->buf + os->pstart + 7, os->psize - 8);
199
211
    } else {
200
212
        st->codec->extradata_size =
201
213
            fixup_vorbis_headers(s, priv, &st->codec->extradata);
204
216
    return os->seq < 3;
205
217
}
206
218
 
207
 
ogg_codec_t vorbis_codec = {
 
219
const struct ogg_codec ff_vorbis_codec = {
208
220
    .magic = "\001vorbis",
209
221
    .magicsize = 7,
210
222
    .header = vorbis_header