00001
00025 #include <stdlib.h>
00026 #include <theora/theora.h>
00027 #include "avcodec.h"
00028
00029 typedef struct TheoraContext {
00030 theora_info info;
00031 theora_state state;
00032 theora_comment comment;
00033 ogg_packet op;
00034 } TheoraContext;
00035
00036 static int
00037 Theora_decode_frame(AVCodecContext *ctx, void *outdata, int *outdata_size,
00038 uint8_t *buf, int buf_size)
00039 {
00040 TheoraContext *thc = ctx->priv_data;
00041 AVFrame *frame = outdata;
00042 yuv_buffer yuv;
00043
00044 thc->op.packet = buf;
00045 thc->op.bytes = buf_size;
00046
00047 if(theora_decode_packetin(&thc->state, &thc->op))
00048 return -1;
00049
00050 theora_decode_YUVout(&thc->state, &yuv);
00051
00052 frame->data[0] = yuv.y;
00053 frame->data[1] = yuv.u;
00054 frame->data[2] = yuv.v;
00055 frame->linesize[0] = yuv.y_stride;
00056 frame->linesize[1] = yuv.uv_stride;
00057 frame->linesize[2] = yuv.uv_stride;
00058
00059 *outdata_size = sizeof(*frame);
00060 return buf_size;
00061 }
00062
00063 static int
00064 Theora_decode_end(AVCodecContext *ctx)
00065 {
00066 TheoraContext *thc = ctx->priv_data;
00067 theora_info_clear(&thc->info);
00068 theora_comment_clear(&thc->comment);
00069 return 0;
00070 }
00071
00072 static int
00073 Theora_decode_init(AVCodecContext *ctx)
00074 {
00075 TheoraContext *thc = ctx->priv_data;
00076 int size, hs, i;
00077 ogg_packet op;
00078 uint8_t *cdp;
00079
00080 if(ctx->extradata_size < 6)
00081 return -1;
00082
00083 theora_info_init(&thc->info);
00084
00085 memset(&op, 0, sizeof(op));
00086 cdp = ctx->extradata;
00087 size = ctx->extradata_size;
00088
00089 for(i = 0; i < 3; i++){
00090 hs = *cdp++ << 8;
00091 hs += *cdp++;
00092 size -= 2;
00093
00094 if(hs > size){
00095 av_log(ctx, AV_LOG_ERROR, "extradata too small: %i > %i\n",
00096 hs, size);
00097 return -1;
00098 }
00099
00100 op.packet = cdp;
00101 op.bytes = hs;
00102 op.b_o_s = !i;
00103 if(theora_decode_header(&thc->info, &thc->comment, &op))
00104 return -1;
00105 op.packetno++;
00106
00107 cdp += hs;
00108 size -= hs;
00109 }
00110
00111 theora_decode_init(&thc->state, &thc->info);
00112
00113 ctx->width = thc->info.width;
00114 ctx->height = thc->info.height;
00115 ctx->time_base.num = thc->info.fps_denominator;
00116 ctx->time_base.den = thc->info.fps_numerator;
00117 ctx->pix_fmt = PIX_FMT_YUV420P;
00118
00119 return 0;
00120 }
00121
00122 AVCodec oggtheora_decoder = {
00123 "theora",
00124 CODEC_TYPE_VIDEO,
00125 CODEC_ID_THEORA,
00126 sizeof(TheoraContext),
00127 Theora_decode_init,
00128 NULL,
00129 Theora_decode_end,
00130 Theora_decode_frame,
00131 0,
00132 NULL
00133 };