00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00033
00034 #include "libavutil/intreadwrite.h"
00035 #include "libavutil/log.h"
00036 #include "avcodec.h"
00037
00038
00039 #include <theora/theora.h>
00040
00041 typedef struct TheoraContext{
00042 theora_state t_state;
00043 } TheoraContext;
00044
00048 static int concatenate_packet(unsigned int* offset, AVCodecContext* avc_context, const ogg_packet* packet)
00049 {
00050 char* message = NULL;
00051 uint8_t* newdata = NULL;
00052 int newsize = avc_context->extradata_size + 2 + packet->bytes;
00053
00054 if (packet->bytes < 0) {
00055 message = "ogg_packet has negative size";
00056 } else if (packet->bytes > 0xffff) {
00057 message = "ogg_packet is larger than 65535 bytes";
00058 } else if (newsize < avc_context->extradata_size) {
00059 message = "extradata_size would overflow";
00060 } else {
00061 newdata = av_realloc(avc_context->extradata, newsize);
00062 if (newdata == NULL) {
00063 message = "av_realloc failed";
00064 }
00065 }
00066 if (message != NULL) {
00067 av_log(avc_context, AV_LOG_ERROR, "concatenate_packet failed: %s\n", message);
00068 return -1;
00069 }
00070
00071 avc_context->extradata = newdata;
00072 avc_context->extradata_size = newsize;
00073 AV_WB16(avc_context->extradata + (*offset), packet->bytes);
00074 *offset += 2;
00075 memcpy( avc_context->extradata + (*offset), packet->packet, packet->bytes );
00076 (*offset) += packet->bytes;
00077 return 0;
00078 }
00079
00080 static av_cold int encode_init(AVCodecContext* avc_context)
00081 {
00082 theora_info t_info;
00083 theora_comment t_comment;
00084 ogg_packet o_packet;
00085 unsigned int offset;
00086 TheoraContext *h = avc_context->priv_data;
00087
00088
00089 theora_info_init( &t_info );
00090 t_info.width = avc_context->width;
00091 t_info.height = avc_context->height;
00092 t_info.frame_width = avc_context->width;
00093 t_info.frame_height = avc_context->height;
00094 t_info.offset_x = 0;
00095 t_info.offset_y = 0;
00096
00097
00098 t_info.fps_numerator = avc_context->time_base.den;
00099 t_info.fps_denominator = avc_context->time_base.num;
00100 if (avc_context->sample_aspect_ratio.num != 0) {
00101 t_info.aspect_numerator = avc_context->sample_aspect_ratio.num;
00102 t_info.aspect_denominator = avc_context->sample_aspect_ratio.den;
00103 } else {
00104 t_info.aspect_numerator = 1;
00105 t_info.aspect_denominator = 1;
00106 }
00107 t_info.colorspace = OC_CS_UNSPECIFIED;
00108 t_info.pixelformat = OC_PF_420;
00109 t_info.target_bitrate = avc_context->bit_rate;
00110 t_info.keyframe_frequency = avc_context->gop_size;
00111 t_info.keyframe_frequency_force = avc_context->gop_size;
00112 t_info.keyframe_mindistance = avc_context->keyint_min;
00113 t_info.quality = 0;
00114
00115 t_info.quick_p = 1;
00116 t_info.dropframes_p = 0;
00117 t_info.keyframe_auto_p = 1;
00118 t_info.keyframe_data_target_bitrate = t_info.target_bitrate * 1.5;
00119 t_info.keyframe_auto_threshold = 80;
00120 t_info.noise_sensitivity = 1;
00121 t_info.sharpness = 0;
00122
00123
00124 if (theora_encode_init( &(h->t_state), &t_info ) != 0) {
00125 av_log(avc_context, AV_LOG_ERROR, "theora_encode_init failed\n");
00126 return -1;
00127 }
00128
00129
00130 theora_info_clear( &t_info );
00131
00132
00133
00134
00135
00136
00137
00138
00139 offset = 0;
00140
00141
00142 theora_encode_header( &(h->t_state), &o_packet );
00143 if (concatenate_packet( &offset, avc_context, &o_packet ) != 0) {
00144 return -1;
00145 }
00146
00147
00148 theora_comment_init( &t_comment );
00149 theora_encode_comment( &t_comment, &o_packet );
00150 if (concatenate_packet( &offset, avc_context, &o_packet ) != 0) {
00151 return -1;
00152 }
00153
00154
00155 theora_encode_tables( &(h->t_state), &o_packet );
00156 if (concatenate_packet( &offset, avc_context, &o_packet ) != 0) {
00157 return -1;
00158 }
00159
00160
00161 theora_comment_clear( &t_comment );
00162
00163
00164 avc_context->coded_frame= avcodec_alloc_frame();
00165
00166 return 0;
00167 }
00168
00169 static int encode_frame(
00170 AVCodecContext* avc_context,
00171 uint8_t *outbuf,
00172 int buf_size,
00173 void *data)
00174 {
00175 yuv_buffer t_yuv_buffer;
00176 TheoraContext *h = avc_context->priv_data;
00177 AVFrame *frame = data;
00178 ogg_packet o_packet;
00179 int result;
00180
00181 assert(avc_context->pix_fmt == PIX_FMT_YUV420P);
00182
00183
00184 if (frame->linesize[1] != frame->linesize[2]) {
00185 av_log(avc_context, AV_LOG_ERROR, "U and V stride differ\n");
00186 return -1;
00187 }
00188
00189 t_yuv_buffer.y_width = avc_context->width;
00190 t_yuv_buffer.y_height = avc_context->height;
00191 t_yuv_buffer.y_stride = frame->linesize[0];
00192 t_yuv_buffer.uv_width = t_yuv_buffer.y_width / 2;
00193 t_yuv_buffer.uv_height = t_yuv_buffer.y_height / 2;
00194 t_yuv_buffer.uv_stride = frame->linesize[1];
00195
00196 t_yuv_buffer.y = frame->data[0];
00197 t_yuv_buffer.u = frame->data[1];
00198 t_yuv_buffer.v = frame->data[2];
00199
00200
00201 result = theora_encode_YUVin( &(h->t_state), &t_yuv_buffer );
00202 if (result != 0) {
00203 const char* message;
00204 switch (result) {
00205 case -1:
00206 message = "differing frame sizes";
00207 break;
00208 case OC_EINVAL:
00209 message = "encoder is not ready or is finished";
00210 break;
00211 default:
00212 message = "unknown reason";
00213 break;
00214 }
00215 av_log(avc_context, AV_LOG_ERROR, "theora_encode_YUVin failed (%s) [%d]\n", message, result);
00216 return -1;
00217 }
00218
00219
00220 result = theora_encode_packetout( &(h->t_state), 0, &o_packet );
00221 switch (result) {
00222 case 0:
00223
00224 return 0;
00225 case 1:
00226
00227 break;
00228 default:
00229 av_log(avc_context, AV_LOG_ERROR, "theora_encode_packetout failed [%d]\n", result);
00230 return -1;
00231 }
00232
00233
00234 if (buf_size < o_packet.bytes) {
00235 av_log(avc_context, AV_LOG_ERROR, "encoded frame too large\n");
00236 return -1;
00237 }
00238 memcpy(outbuf, o_packet.packet, o_packet.bytes);
00239
00240 return o_packet.bytes;
00241 }
00242
00243 static av_cold int encode_close(AVCodecContext* avc_context)
00244 {
00245 ogg_packet o_packet;
00246 TheoraContext *h = avc_context->priv_data;
00247 int result;
00248 const char* message;
00249
00250 result = theora_encode_packetout( &(h->t_state), 1, &o_packet );
00251 theora_clear( &(h->t_state) );
00252 switch (result) {
00253 case 0:
00254 case -1:
00255 return 0;
00256 case 1:
00257
00258 message = "gave us a packet";
00259 break;
00260 default:
00261 message = "unknown reason";
00262 break;
00263 }
00264 av_log(avc_context, AV_LOG_ERROR, "theora_encode_packetout failed (%s) [%d]\n", message, result);
00265 return -1;
00266 }
00267
00268 static const enum PixelFormat supported_pixel_formats[] = { PIX_FMT_YUV420P, PIX_FMT_NONE };
00269
00271 AVCodec libtheora_encoder =
00272 {
00273 .name = "libtheora",
00274 .type = CODEC_TYPE_VIDEO,
00275 .id = CODEC_ID_THEORA,
00276 .priv_data_size = sizeof(TheoraContext),
00277 .init = encode_init,
00278 .close = encode_close,
00279 .encode = encode_frame,
00280 .pix_fmts = supported_pixel_formats,
00281 .long_name = NULL_IF_CONFIG_SMALL("libtheora Theora"),
00282 };