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