annotate ffmpeg/libavformat/oggparsetheora.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /**
yading@11 2 Copyright (C) 2005 Matthieu CASTET, Alex Beregszaszi
yading@11 3
yading@11 4 Permission is hereby granted, free of charge, to any person
yading@11 5 obtaining a copy of this software and associated documentation
yading@11 6 files (the "Software"), to deal in the Software without
yading@11 7 restriction, including without limitation the rights to use, copy,
yading@11 8 modify, merge, publish, distribute, sublicense, and/or sell copies
yading@11 9 of the Software, and to permit persons to whom the Software is
yading@11 10 furnished to do so, subject to the following conditions:
yading@11 11
yading@11 12 The above copyright notice and this permission notice shall be
yading@11 13 included in all copies or substantial portions of the Software.
yading@11 14
yading@11 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
yading@11 16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
yading@11 17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
yading@11 18 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
yading@11 19 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
yading@11 20 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
yading@11 21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
yading@11 22 DEALINGS IN THE SOFTWARE.
yading@11 23 **/
yading@11 24
yading@11 25 #include <stdlib.h>
yading@11 26 #include "libavutil/bswap.h"
yading@11 27 #include "libavcodec/get_bits.h"
yading@11 28 #include "avformat.h"
yading@11 29 #include "internal.h"
yading@11 30 #include "oggdec.h"
yading@11 31
yading@11 32 struct theora_params {
yading@11 33 int gpshift;
yading@11 34 int gpmask;
yading@11 35 unsigned version;
yading@11 36 };
yading@11 37
yading@11 38 static int
yading@11 39 theora_header (AVFormatContext * s, int idx)
yading@11 40 {
yading@11 41 struct ogg *ogg = s->priv_data;
yading@11 42 struct ogg_stream *os = ogg->streams + idx;
yading@11 43 AVStream *st = s->streams[idx];
yading@11 44 struct theora_params *thp = os->private;
yading@11 45 int cds = st->codec->extradata_size + os->psize + 2;
yading@11 46 uint8_t *cdp;
yading@11 47
yading@11 48 if(!(os->buf[os->pstart] & 0x80))
yading@11 49 return 0;
yading@11 50
yading@11 51 if(!thp){
yading@11 52 thp = av_mallocz(sizeof(*thp));
yading@11 53 os->private = thp;
yading@11 54 }
yading@11 55
yading@11 56 switch (os->buf[os->pstart]) {
yading@11 57 case 0x80: {
yading@11 58 GetBitContext gb;
yading@11 59 int width, height;
yading@11 60 AVRational timebase;
yading@11 61
yading@11 62 init_get_bits(&gb, os->buf + os->pstart, os->psize*8);
yading@11 63
yading@11 64 skip_bits_long(&gb, 7*8); /* 0x80"theora" */
yading@11 65
yading@11 66 thp->version = get_bits_long(&gb, 24);
yading@11 67 if (thp->version < 0x030100)
yading@11 68 {
yading@11 69 av_log(s, AV_LOG_ERROR,
yading@11 70 "Too old or unsupported Theora (%x)\n", thp->version);
yading@11 71 return -1;
yading@11 72 }
yading@11 73
yading@11 74 width = get_bits(&gb, 16) << 4;
yading@11 75 height = get_bits(&gb, 16) << 4;
yading@11 76 avcodec_set_dimensions(st->codec, width, height);
yading@11 77
yading@11 78 if (thp->version >= 0x030400)
yading@11 79 skip_bits(&gb, 100);
yading@11 80
yading@11 81 if (thp->version >= 0x030200) {
yading@11 82 width = get_bits_long(&gb, 24);
yading@11 83 height = get_bits_long(&gb, 24);
yading@11 84 if ( width <= st->codec->width && width > st->codec->width-16
yading@11 85 && height <= st->codec->height && height > st->codec->height-16)
yading@11 86 avcodec_set_dimensions(st->codec, width, height);
yading@11 87
yading@11 88 skip_bits(&gb, 16);
yading@11 89 }
yading@11 90 timebase.den = get_bits_long(&gb, 32);
yading@11 91 timebase.num = get_bits_long(&gb, 32);
yading@11 92 if (!(timebase.num > 0 && timebase.den > 0)) {
yading@11 93 av_log(s, AV_LOG_WARNING, "Invalid time base in theora stream, assuming 25 FPS\n");
yading@11 94 timebase.num = 1;
yading@11 95 timebase.den = 25;
yading@11 96 }
yading@11 97 avpriv_set_pts_info(st, 64, timebase.num, timebase.den);
yading@11 98
yading@11 99 st->sample_aspect_ratio.num = get_bits_long(&gb, 24);
yading@11 100 st->sample_aspect_ratio.den = get_bits_long(&gb, 24);
yading@11 101
yading@11 102 if (thp->version >= 0x030200)
yading@11 103 skip_bits_long(&gb, 38);
yading@11 104 if (thp->version >= 0x304000)
yading@11 105 skip_bits(&gb, 2);
yading@11 106
yading@11 107 thp->gpshift = get_bits(&gb, 5);
yading@11 108 thp->gpmask = (1 << thp->gpshift) - 1;
yading@11 109
yading@11 110 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
yading@11 111 st->codec->codec_id = AV_CODEC_ID_THEORA;
yading@11 112 st->need_parsing = AVSTREAM_PARSE_HEADERS;
yading@11 113 }
yading@11 114 break;
yading@11 115 case 0x81:
yading@11 116 ff_vorbis_comment(s, &st->metadata, os->buf + os->pstart + 7, os->psize - 7);
yading@11 117 case 0x82:
yading@11 118 if (!thp->version)
yading@11 119 return -1;
yading@11 120 break;
yading@11 121 default:
yading@11 122 av_log(s, AV_LOG_ERROR, "Unknown header type %X\n", os->buf[os->pstart]);
yading@11 123 return -1;
yading@11 124 }
yading@11 125
yading@11 126 st->codec->extradata = av_realloc (st->codec->extradata,
yading@11 127 cds + FF_INPUT_BUFFER_PADDING_SIZE);
yading@11 128 cdp = st->codec->extradata + st->codec->extradata_size;
yading@11 129 *cdp++ = os->psize >> 8;
yading@11 130 *cdp++ = os->psize & 0xff;
yading@11 131 memcpy (cdp, os->buf + os->pstart, os->psize);
yading@11 132 st->codec->extradata_size = cds;
yading@11 133
yading@11 134 return 1;
yading@11 135 }
yading@11 136
yading@11 137 static uint64_t
yading@11 138 theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp, int64_t *dts)
yading@11 139 {
yading@11 140 struct ogg *ogg = ctx->priv_data;
yading@11 141 struct ogg_stream *os = ogg->streams + idx;
yading@11 142 struct theora_params *thp = os->private;
yading@11 143 uint64_t iframe, pframe;
yading@11 144
yading@11 145 if (!thp)
yading@11 146 return AV_NOPTS_VALUE;
yading@11 147
yading@11 148 iframe = gp >> thp->gpshift;
yading@11 149 pframe = gp & thp->gpmask;
yading@11 150
yading@11 151 if (thp->version < 0x030201)
yading@11 152 iframe++;
yading@11 153
yading@11 154 if(!pframe)
yading@11 155 os->pflags |= AV_PKT_FLAG_KEY;
yading@11 156
yading@11 157 if (dts)
yading@11 158 *dts = iframe + pframe;
yading@11 159
yading@11 160 return iframe + pframe;
yading@11 161 }
yading@11 162
yading@11 163 static int theora_packet(AVFormatContext *s, int idx)
yading@11 164 {
yading@11 165 struct ogg *ogg = s->priv_data;
yading@11 166 struct ogg_stream *os = ogg->streams + idx;
yading@11 167 int duration;
yading@11 168
yading@11 169 /* first packet handling
yading@11 170 here we parse the duration of each packet in the first page and compare
yading@11 171 the total duration to the page granule to find the encoder delay and
yading@11 172 set the first timestamp */
yading@11 173
yading@11 174 if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) {
yading@11 175 int seg;
yading@11 176
yading@11 177 duration = 1;
yading@11 178 for (seg = os->segp; seg < os->nsegs; seg++) {
yading@11 179 if (os->segments[seg] < 255)
yading@11 180 duration ++;
yading@11 181 }
yading@11 182
yading@11 183 os->lastpts = os->lastdts = theora_gptopts(s, idx, os->granule, NULL) - duration;
yading@11 184 if(s->streams[idx]->start_time == AV_NOPTS_VALUE) {
yading@11 185 s->streams[idx]->start_time = os->lastpts;
yading@11 186 if (s->streams[idx]->duration)
yading@11 187 s->streams[idx]->duration -= s->streams[idx]->start_time;
yading@11 188 }
yading@11 189 }
yading@11 190
yading@11 191 /* parse packet duration */
yading@11 192 if (os->psize > 0) {
yading@11 193 os->pduration = 1;
yading@11 194 }
yading@11 195
yading@11 196 return 0;
yading@11 197 }
yading@11 198
yading@11 199 const struct ogg_codec ff_theora_codec = {
yading@11 200 .magic = "\200theora",
yading@11 201 .magicsize = 7,
yading@11 202 .header = theora_header,
yading@11 203 .packet = theora_packet,
yading@11 204 .gptopts = theora_gptopts,
yading@11 205 .nb_header = 3,
yading@11 206 };