Mercurial > audlegacy-plugins
diff src/ffmpeg/libavformat/oggparsevorbis.c @ 808:e8776388b02a trunk
[svn] - add ffmpeg
author | nenolod |
---|---|
date | Mon, 12 Mar 2007 11:18:54 -0700 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ffmpeg/libavformat/oggparsevorbis.c Mon Mar 12 11:18:54 2007 -0700 @@ -0,0 +1,205 @@ +/** + Copyright (C) 2005 Michael Ahlberg, Måns Rullgård + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +**/ + +#include <stdlib.h> +#include "avformat.h" +#include "bitstream.h" +#include "bswap.h" +#include "ogg2.h" + +extern int +vorbis_comment (AVFormatContext * as, uint8_t *buf, int size) +{ + char *p = buf; + int s, n, j; + + if (size < 4) + return -1; + + s = le2me_32 (unaligned32 (p)); + p += 4; + size -= 4; + + if (size < s + 4) + return -1; + + p += s; + size -= s; + + n = le2me_32 (unaligned32 (p)); + p += 4; + size -= 4; + + while (size >= 4){ + char *t, *v; + int tl, vl; + + s = le2me_32 (unaligned32 (p)); + p += 4; + size -= 4; + + if (size < s) + break; + + t = p; + p += s; + size -= s; + n--; + + v = memchr (t, '=', s); + if (!v) + continue; + + tl = v - t; + vl = s - tl - 1; + v++; + + if (tl && vl){ + char tt[tl + 1]; + char ct[vl + 1]; + + for (j = 0; j < tl; j++) + tt[j] = toupper (t[j]); + tt[tl] = 0; + + memcpy (ct, v, vl); + ct[vl] = 0; + + // took from Vorbis_I_spec + if (!strcmp (tt, "AUTHOR")) + strncpy (as->author, ct, FFMIN(sizeof (as->author), vl)); + else if (!strcmp (tt, "TITLE")) + strncpy (as->title, ct, FFMIN(sizeof (as->title), vl)); + else if (!strcmp (tt, "COPYRIGHT")) + strncpy (as->copyright, ct, FFMIN(sizeof (as->copyright), vl)); + else if (!strcmp (tt, "DESCRIPTION")) + strncpy (as->comment, ct, FFMIN(sizeof (as->comment), vl)); + else if (!strcmp (tt, "GENRE")) + strncpy (as->genre, ct, FFMIN(sizeof (as->genre), vl)); + else if (!strcmp (tt, "TRACKNUMBER")) + as->track = atoi (ct); + //Too bored to add others for today + } + } + + if (size > 0) + av_log (as, AV_LOG_INFO, "%i bytes of comment header remain\n", size); + if (n > 0) + av_log (as, AV_LOG_INFO, + "truncated comment header, %i comments not found\n", n); + + return 0; +} + + +/** Parse the vorbis header + * Vorbis Identification header from Vorbis_I_spec.html#vorbis-spec-codec + * [vorbis_version] = read 32 bits as unsigned integer | Not used + * [audio_channels] = read 8 bit integer as unsigned | Used + * [audio_sample_rate] = read 32 bits as unsigned integer | Used + * [bitrate_maximum] = read 32 bits as signed integer | Not used yet + * [bitrate_nominal] = read 32 bits as signed integer | Not used yet + * [bitrate_minimum] = read 32 bits as signed integer | Used as bitrate + * [blocksize_0] = read 4 bits as unsigned integer | Not Used + * [blocksize_1] = read 4 bits as unsigned integer | Not Used + * [framing_flag] = read one bit | Not Used + * */ + +typedef struct { + unsigned int len[3]; + unsigned char *packet[3]; +} oggvorbis_private_t; + + +static unsigned int +fixup_vorbis_headers(AVFormatContext * as, oggvorbis_private_t *priv, + void **buf) +{ + int i,offset, len; + unsigned char *ptr; + + len = priv->len[0] + priv->len[1] + priv->len[2]; + ptr = *buf = av_mallocz(len + len/255 + 64); + + ptr[0] = 2; + offset = 1; + offset += av_xiphlacing(&ptr[offset], priv->len[0]); + offset += av_xiphlacing(&ptr[offset], priv->len[1]); + for(i = 0; i < 3; i++) { + memcpy(&ptr[offset], priv->packet[i], priv->len[i]); + offset += priv->len[i]; + } + *buf = av_realloc(*buf, offset); + return offset; +} + + +static int +vorbis_header (AVFormatContext * s, int idx) +{ + ogg_t *ogg = s->priv_data; + ogg_stream_t *os = ogg->streams + idx; + AVStream *st = s->streams[idx]; + oggvorbis_private_t *priv; + + if (os->seq > 2) + return 0; + + if(os->seq == 0) { + os->private = av_mallocz(sizeof(oggvorbis_private_t)); + if(!os->private) + return 0; + } + + priv = os->private; + priv->len[os->seq] = os->psize; + priv->packet[os->seq] = av_mallocz(os->psize); + memcpy(priv->packet[os->seq], os->buf + os->pstart, os->psize); + if (os->buf[os->pstart] == 1) { + uint8_t *p = os->buf + os->pstart + 11; //skip up to the audio channels + st->codec->channels = *p++; + st->codec->sample_rate = le2me_32 (unaligned32 (p)); + p += 8; //skip maximum and and nominal bitrate + st->codec->bit_rate = le2me_32 (unaligned32 (p)); //Minimum bitrate + + st->codec->codec_type = CODEC_TYPE_AUDIO; + st->codec->codec_id = CODEC_ID_VORBIS; + + st->time_base.num = 1; + st->time_base.den = st->codec->sample_rate; + } else if (os->buf[os->pstart] == 3) { + vorbis_comment (s, os->buf + os->pstart + 7, os->psize - 8); + } else { + st->codec->extradata_size = + fixup_vorbis_headers(s, priv, &st->codec->extradata); + } + + return os->seq < 3; +} + +ogg_codec_t vorbis_codec = { + .magic = "\001vorbis", + .magicsize = 7, + .header = vorbis_header +};