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.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
00113 t_info.quick_p = 1;
00114 t_info.dropframes_p = 0;
00115 t_info.keyframe_auto_p = 1;
00116 t_info.keyframe_data_target_bitrate = t_info.target_bitrate * 1.5;
00117 t_info.keyframe_auto_threshold = 80;
00118 t_info.noise_sensitivity = 1;
00119 t_info.sharpness = 0;
00120
00121 if (avc_context->flags & CODEC_FLAG_QSCALE) {
00122
00123
00124
00125
00126
00127 t_info.quality = av_clip(avc_context->global_quality / (float)FF_QP2LAMBDA, 0, 10) * 6.3;
00128 t_info.target_bitrate = 0;
00129 } else {
00130 t_info.target_bitrate = avc_context->bit_rate;
00131 t_info.quality = 0;
00132 }
00133
00134
00135 if (theora_encode_init( &(h->t_state), &t_info ) != 0) {
00136 av_log(avc_context, AV_LOG_ERROR, "theora_encode_init failed\n");
00137 return -1;
00138 }
00139
00140
00141 theora_info_clear( &t_info );
00142
00143
00144
00145
00146
00147
00148
00149
00150 offset = 0;
00151
00152
00153 theora_encode_header( &(h->t_state), &o_packet );
00154 if (concatenate_packet( &offset, avc_context, &o_packet ) != 0) {
00155 return -1;
00156 }
00157
00158
00159 theora_comment_init( &t_comment );
00160 theora_encode_comment( &t_comment, &o_packet );
00161 if (concatenate_packet( &offset, avc_context, &o_packet ) != 0) {
00162 return -1;
00163 }
00164
00165
00166 theora_encode_tables( &(h->t_state), &o_packet );
00167 if (concatenate_packet( &offset, avc_context, &o_packet ) != 0) {
00168 return -1;
00169 }
00170
00171
00172 theora_comment_clear( &t_comment );
00173
00174
00175 avc_context->coded_frame= avcodec_alloc_frame();
00176
00177 return 0;
00178 }
00179
00180 static int encode_frame(
00181 AVCodecContext* avc_context,
00182 uint8_t *outbuf,
00183 int buf_size,
00184 void *data)
00185 {
00186 yuv_buffer t_yuv_buffer;
00187 TheoraContext *h = avc_context->priv_data;
00188 AVFrame *frame = data;
00189 ogg_packet o_packet;
00190 int result;
00191
00192 assert(avc_context->pix_fmt == PIX_FMT_YUV420P);
00193
00194
00195 if (frame->linesize[1] != frame->linesize[2]) {
00196 av_log(avc_context, AV_LOG_ERROR, "U and V stride differ\n");
00197 return -1;
00198 }
00199
00200 t_yuv_buffer.y_width = avc_context->width;
00201 t_yuv_buffer.y_height = avc_context->height;
00202 t_yuv_buffer.y_stride = frame->linesize[0];
00203 t_yuv_buffer.uv_width = t_yuv_buffer.y_width / 2;
00204 t_yuv_buffer.uv_height = t_yuv_buffer.y_height / 2;
00205 t_yuv_buffer.uv_stride = frame->linesize[1];
00206
00207 t_yuv_buffer.y = frame->data[0];
00208 t_yuv_buffer.u = frame->data[1];
00209 t_yuv_buffer.v = frame->data[2];
00210
00211
00212 result = theora_encode_YUVin( &(h->t_state), &t_yuv_buffer );
00213 if (result != 0) {
00214 const char* message;
00215 switch (result) {
00216 case -1:
00217 message = "differing frame sizes";
00218 break;
00219 case OC_EINVAL:
00220 message = "encoder is not ready or is finished";
00221 break;
00222 default:
00223 message = "unknown reason";
00224 break;
00225 }
00226 av_log(avc_context, AV_LOG_ERROR, "theora_encode_YUVin failed (%s) [%d]\n", message, result);
00227 return -1;
00228 }
00229
00230
00231 result = theora_encode_packetout( &(h->t_state), 0, &o_packet );
00232 switch (result) {
00233 case 0:
00234
00235 return 0;
00236 case 1:
00237
00238 break;
00239 default:
00240 av_log(avc_context, AV_LOG_ERROR, "theora_encode_packetout failed [%d]\n", result);
00241 return -1;
00242 }
00243
00244
00245 if (buf_size < o_packet.bytes) {
00246 av_log(avc_context, AV_LOG_ERROR, "encoded frame too large\n");
00247 return -1;
00248 }
00249 memcpy(outbuf, o_packet.packet, o_packet.bytes);
00250
00251 return o_packet.bytes;
00252 }
00253
00254 static av_cold int encode_close(AVCodecContext* avc_context)
00255 {
00256 ogg_packet o_packet;
00257 TheoraContext *h = avc_context->priv_data;
00258 int result;
00259 const char* message;
00260
00261 result = theora_encode_packetout( &(h->t_state), 1, &o_packet );
00262 theora_clear( &(h->t_state) );
00263 switch (result) {
00264 case 0:
00265 case -1:
00266 return 0;
00267 case 1:
00268
00269 message = "gave us a packet";
00270 break;
00271 default:
00272 message = "unknown reason";
00273 break;
00274 }
00275 av_log(avc_context, AV_LOG_ERROR, "theora_encode_packetout failed (%s) [%d]\n", message, result);
00276 return -1;
00277 }
00278
00279 static const enum PixelFormat supported_pixel_formats[] = { PIX_FMT_YUV420P, PIX_FMT_NONE };
00280
00282 AVCodec libtheora_encoder =
00283 {
00284 .name = "libtheora",
00285 .type = CODEC_TYPE_VIDEO,
00286 .id = CODEC_ID_THEORA,
00287 .priv_data_size = sizeof(TheoraContext),
00288 .init = encode_init,
00289 .close = encode_close,
00290 .encode = encode_frame,
00291 .pix_fmts = supported_pixel_formats,
00292 .long_name = NULL_IF_CONFIG_SMALL("libtheora Theora"),
00293 };