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