00001
00025 #include <stdlib.h>
00026 #include "libavutil/avstring.h"
00027 #include "libavutil/bswap.h"
00028 #include "libavutil/dict.h"
00029 #include "libavcodec/get_bits.h"
00030 #include "libavcodec/bytestream.h"
00031 #include "avformat.h"
00032 #include "internal.h"
00033 #include "oggdec.h"
00034 #include "vorbiscomment.h"
00035
00036 static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val)
00037 {
00038 int i, cnum, h, m, s, ms, keylen = strlen(key);
00039 AVChapter *chapter = NULL;
00040
00041 if (keylen < 9 || sscanf(key, "CHAPTER%02d", &cnum) != 1)
00042 return 0;
00043
00044 if (keylen == 9) {
00045 if (sscanf(val, "%02d:%02d:%02d.%03d", &h, &m, &s, &ms) < 4)
00046 return 0;
00047
00048 avpriv_new_chapter(as, cnum, (AVRational){1,1000},
00049 ms + 1000*(s + 60*(m + 60*h)),
00050 AV_NOPTS_VALUE, NULL);
00051 av_free(val);
00052 } else if (!strcmp(key+9, "NAME")) {
00053 for(i = 0; i < as->nb_chapters; i++)
00054 if (as->chapters[i]->id == cnum) {
00055 chapter = as->chapters[i];
00056 break;
00057 }
00058 if (!chapter)
00059 return 0;
00060
00061 av_dict_set(&chapter->metadata, "title", val,
00062 AV_DICT_DONT_STRDUP_VAL);
00063 } else
00064 return 0;
00065
00066 av_free(key);
00067 return 1;
00068 }
00069
00070 int
00071 ff_vorbis_comment(AVFormatContext * as, AVDictionary **m, const uint8_t *buf, int size)
00072 {
00073 const uint8_t *p = buf;
00074 const uint8_t *end = buf + size;
00075 unsigned n, j;
00076 int s;
00077
00078 if (size < 8)
00079 return -1;
00080
00081 s = bytestream_get_le32(&p);
00082
00083 if (end - p - 4 < s || s < 0)
00084 return -1;
00085
00086 p += s;
00087
00088 n = bytestream_get_le32(&p);
00089
00090 while (end - p >= 4 && n > 0) {
00091 const char *t, *v;
00092 int tl, vl;
00093
00094 s = bytestream_get_le32(&p);
00095
00096 if (end - p < s || s < 0)
00097 break;
00098
00099 t = p;
00100 p += s;
00101 n--;
00102
00103 v = memchr(t, '=', s);
00104 if (!v)
00105 continue;
00106
00107 tl = v - t;
00108 vl = s - tl - 1;
00109 v++;
00110
00111 if (tl && vl) {
00112 char *tt, *ct;
00113
00114 tt = av_malloc(tl + 1);
00115 ct = av_malloc(vl + 1);
00116 if (!tt || !ct) {
00117 av_freep(&tt);
00118 av_freep(&ct);
00119 av_log(as, AV_LOG_WARNING, "out-of-memory error. skipping VorbisComment tag.\n");
00120 continue;
00121 }
00122
00123 for (j = 0; j < tl; j++)
00124 tt[j] = toupper(t[j]);
00125 tt[tl] = 0;
00126
00127 memcpy(ct, v, vl);
00128 ct[vl] = 0;
00129
00130 if (!ogm_chapter(as, tt, ct))
00131 av_dict_set(m, tt, ct,
00132 AV_DICT_DONT_STRDUP_KEY |
00133 AV_DICT_DONT_STRDUP_VAL);
00134 }
00135 }
00136
00137 if (p != end)
00138 av_log(as, AV_LOG_INFO, "%ti bytes of comment header remain\n", end-p);
00139 if (n > 0)
00140 av_log(as, AV_LOG_INFO,
00141 "truncated comment header, %i comments not found\n", n);
00142
00143 ff_metadata_conv(m, NULL, ff_vorbiscomment_metadata_conv);
00144
00145 return 0;
00146 }
00147
00148
00162 struct oggvorbis_private {
00163 unsigned int len[3];
00164 unsigned char *packet[3];
00165 };
00166
00167
00168 static unsigned int
00169 fixup_vorbis_headers(AVFormatContext * as, struct oggvorbis_private *priv,
00170 uint8_t **buf)
00171 {
00172 int i,offset, len;
00173 unsigned char *ptr;
00174
00175 len = priv->len[0] + priv->len[1] + priv->len[2];
00176 ptr = *buf = av_mallocz(len + len/255 + 64);
00177
00178 ptr[0] = 2;
00179 offset = 1;
00180 offset += av_xiphlacing(&ptr[offset], priv->len[0]);
00181 offset += av_xiphlacing(&ptr[offset], priv->len[1]);
00182 for (i = 0; i < 3; i++) {
00183 memcpy(&ptr[offset], priv->packet[i], priv->len[i]);
00184 offset += priv->len[i];
00185 av_freep(&priv->packet[i]);
00186 }
00187 *buf = av_realloc(*buf, offset + FF_INPUT_BUFFER_PADDING_SIZE);
00188 return offset;
00189 }
00190
00191 static int vorbis_cleanup(AVFormatContext *s, int idx)
00192 {
00193 struct ogg *ogg = s->priv_data;
00194 struct ogg_stream *os = ogg->streams + idx;
00195 struct oggvorbis_private *priv = os->private;
00196 int i;
00197 if (os->private)
00198 for (i = 0; i < 3; i++)
00199 av_freep(&priv->packet[i]);
00200 }
00201
00202 static int
00203 vorbis_header (AVFormatContext * s, int idx)
00204 {
00205 struct ogg *ogg = s->priv_data;
00206 struct ogg_stream *os = ogg->streams + idx;
00207 AVStream *st = s->streams[idx];
00208 struct oggvorbis_private *priv;
00209 int pkt_type = os->buf[os->pstart];
00210
00211 if (!(pkt_type & 1))
00212 return 0;
00213
00214 if (!os->private) {
00215 os->private = av_mallocz(sizeof(struct oggvorbis_private));
00216 if (!os->private)
00217 return 0;
00218 }
00219
00220 if (os->psize < 1 || pkt_type > 5)
00221 return -1;
00222
00223 priv = os->private;
00224
00225 if (priv->packet[pkt_type>>1])
00226 return -1;
00227 if (pkt_type > 1 && !priv->packet[0] || pkt_type > 3 && !priv->packet[1])
00228 return -1;
00229
00230 priv->len[pkt_type >> 1] = os->psize;
00231 priv->packet[pkt_type >> 1] = av_mallocz(os->psize);
00232 memcpy(priv->packet[pkt_type >> 1], os->buf + os->pstart, os->psize);
00233 if (os->buf[os->pstart] == 1) {
00234 const uint8_t *p = os->buf + os->pstart + 7;
00235 unsigned blocksize, bs0, bs1;
00236 int srate;
00237
00238 if (os->psize != 30)
00239 return -1;
00240
00241 if (bytestream_get_le32(&p) != 0)
00242 return -1;
00243
00244 st->codec->channels = bytestream_get_byte(&p);
00245 srate = bytestream_get_le32(&p);
00246 p += 4;
00247 st->codec->bit_rate = bytestream_get_le32(&p);
00248 p += 4;
00249
00250 blocksize = bytestream_get_byte(&p);
00251 bs0 = blocksize & 15;
00252 bs1 = blocksize >> 4;
00253
00254 if (bs0 > bs1)
00255 return -1;
00256 if (bs0 < 6 || bs1 > 13)
00257 return -1;
00258
00259 if (bytestream_get_byte(&p) != 1)
00260 return -1;
00261
00262 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00263 st->codec->codec_id = CODEC_ID_VORBIS;
00264
00265 if (srate > 0) {
00266 st->codec->sample_rate = srate;
00267 avpriv_set_pts_info(st, 64, 1, srate);
00268 }
00269 } else if (os->buf[os->pstart] == 3) {
00270 if (os->psize > 8 &&
00271 ff_vorbis_comment(s, &st->metadata, os->buf + os->pstart + 7, os->psize - 8) >= 0) {
00272
00273 unsigned new_len = 7 + 4 + AV_RL32(priv->packet[1] + 7) + 4 + 1;
00274 if (new_len >= 16 && new_len < os->psize) {
00275 AV_WL32(priv->packet[1] + new_len - 5, 0);
00276 priv->packet[1][new_len - 1] = 1;
00277 priv->len[1] = new_len;
00278 }
00279 }
00280 } else {
00281 st->codec->extradata_size =
00282 fixup_vorbis_headers(s, priv, &st->codec->extradata);
00283 }
00284
00285 return 1;
00286 }
00287
00288 const struct ogg_codec ff_vorbis_codec = {
00289 .magic = "\001vorbis",
00290 .magicsize = 7,
00291 .header = vorbis_header,
00292 .cleanup= vorbis_cleanup,
00293 .nb_header = 3,
00294 };