Libav 0.7.1
|
00001 00025 #include <stdlib.h> 00026 #include "libavutil/bswap.h" 00027 #include "libavcodec/get_bits.h" 00028 #include "avformat.h" 00029 #include "oggdec.h" 00030 00031 struct theora_params { 00032 int gpshift; 00033 int gpmask; 00034 unsigned version; 00035 }; 00036 00037 static int 00038 theora_header (AVFormatContext * s, int idx) 00039 { 00040 struct ogg *ogg = s->priv_data; 00041 struct ogg_stream *os = ogg->streams + idx; 00042 AVStream *st = s->streams[idx]; 00043 struct theora_params *thp = os->private; 00044 int cds = st->codec->extradata_size + os->psize + 2; 00045 uint8_t *cdp; 00046 00047 if(!(os->buf[os->pstart] & 0x80)) 00048 return 0; 00049 00050 if(!thp){ 00051 thp = av_mallocz(sizeof(*thp)); 00052 os->private = thp; 00053 } 00054 00055 if (os->buf[os->pstart] == 0x80) { 00056 GetBitContext gb; 00057 int width, height; 00058 00059 init_get_bits(&gb, os->buf + os->pstart, os->psize*8); 00060 00061 skip_bits_long(&gb, 7*8); /* 0x80"theora" */ 00062 00063 thp->version = get_bits_long(&gb, 24); 00064 if (thp->version < 0x030100) 00065 { 00066 av_log(s, AV_LOG_ERROR, 00067 "Too old or unsupported Theora (%x)\n", thp->version); 00068 return -1; 00069 } 00070 00071 width = get_bits(&gb, 16) << 4; 00072 height = get_bits(&gb, 16) << 4; 00073 avcodec_set_dimensions(st->codec, width, height); 00074 00075 if (thp->version >= 0x030400) 00076 skip_bits(&gb, 100); 00077 00078 if (thp->version >= 0x030200) { 00079 width = get_bits_long(&gb, 24); 00080 height = get_bits_long(&gb, 24); 00081 if ( width <= st->codec->width && width > st->codec->width-16 00082 && height <= st->codec->height && height > st->codec->height-16) 00083 avcodec_set_dimensions(st->codec, width, height); 00084 00085 skip_bits(&gb, 16); 00086 } 00087 st->codec->time_base.den = get_bits_long(&gb, 32); 00088 st->codec->time_base.num = get_bits_long(&gb, 32); 00089 if (!(st->codec->time_base.num > 0 && st->codec->time_base.den > 0)) { 00090 av_log(s, AV_LOG_WARNING, "Invalid time base in theora stream, assuming 25 FPS\n"); 00091 st->codec->time_base.num = 1; 00092 st->codec->time_base.den = 25; 00093 } 00094 av_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den); 00095 00096 st->sample_aspect_ratio.num = get_bits_long(&gb, 24); 00097 st->sample_aspect_ratio.den = get_bits_long(&gb, 24); 00098 00099 if (thp->version >= 0x030200) 00100 skip_bits_long(&gb, 38); 00101 if (thp->version >= 0x304000) 00102 skip_bits(&gb, 2); 00103 00104 thp->gpshift = get_bits(&gb, 5); 00105 thp->gpmask = (1 << thp->gpshift) - 1; 00106 00107 st->codec->codec_type = AVMEDIA_TYPE_VIDEO; 00108 st->codec->codec_id = CODEC_ID_THEORA; 00109 st->need_parsing = AVSTREAM_PARSE_HEADERS; 00110 00111 } else if (os->buf[os->pstart] == 0x83) { 00112 ff_vorbis_comment (s, &st->metadata, os->buf + os->pstart + 7, os->psize - 8); 00113 } 00114 00115 st->codec->extradata = av_realloc (st->codec->extradata, 00116 cds + FF_INPUT_BUFFER_PADDING_SIZE); 00117 cdp = st->codec->extradata + st->codec->extradata_size; 00118 *cdp++ = os->psize >> 8; 00119 *cdp++ = os->psize & 0xff; 00120 memcpy (cdp, os->buf + os->pstart, os->psize); 00121 st->codec->extradata_size = cds; 00122 00123 return 1; 00124 } 00125 00126 static uint64_t 00127 theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp, int64_t *dts) 00128 { 00129 struct ogg *ogg = ctx->priv_data; 00130 struct ogg_stream *os = ogg->streams + idx; 00131 struct theora_params *thp = os->private; 00132 uint64_t iframe = gp >> thp->gpshift; 00133 uint64_t pframe = gp & thp->gpmask; 00134 00135 if (thp->version < 0x030201) 00136 iframe++; 00137 00138 if(!pframe) 00139 os->pflags |= AV_PKT_FLAG_KEY; 00140 00141 if (dts) 00142 *dts = iframe + pframe; 00143 00144 return iframe + pframe; 00145 } 00146 00147 const struct ogg_codec ff_theora_codec = { 00148 .magic = "\200theora", 00149 .magicsize = 7, 00150 .header = theora_header, 00151 .gptopts = theora_gptopts 00152 };