Libav
|
00001 /* 00002 * Copyright (c) 2006 Paul Richards <paul.richards@gmail.com> 00003 * 00004 * This file is part of FFmpeg. 00005 * 00006 * FFmpeg is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * FFmpeg is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with FFmpeg; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00033 /* FFmpeg includes */ 00034 #include "libavutil/intreadwrite.h" 00035 #include "libavutil/log.h" 00036 #include "libavutil/base64.h" 00037 #include "avcodec.h" 00038 00039 /* libtheora includes */ 00040 #include <theora/theoraenc.h> 00041 00042 typedef struct TheoraContext { 00043 th_enc_ctx *t_state; 00044 uint8_t *stats; 00045 int stats_size; 00046 int stats_offset; 00047 int uv_hshift; 00048 int uv_vshift; 00049 int keyframe_mask; 00050 } TheoraContext; 00051 00053 static int concatenate_packet(unsigned int* offset, 00054 AVCodecContext* avc_context, 00055 const ogg_packet* packet) 00056 { 00057 const char* message = NULL; 00058 uint8_t* newdata = NULL; 00059 int newsize = avc_context->extradata_size + 2 + packet->bytes; 00060 00061 if (packet->bytes < 0) { 00062 message = "ogg_packet has negative size"; 00063 } else if (packet->bytes > 0xffff) { 00064 message = "ogg_packet is larger than 65535 bytes"; 00065 } else if (newsize < avc_context->extradata_size) { 00066 message = "extradata_size would overflow"; 00067 } else { 00068 newdata = av_realloc(avc_context->extradata, newsize); 00069 if (!newdata) 00070 message = "av_realloc failed"; 00071 } 00072 if (message) { 00073 av_log(avc_context, AV_LOG_ERROR, "concatenate_packet failed: %s\n", message); 00074 return -1; 00075 } 00076 00077 avc_context->extradata = newdata; 00078 avc_context->extradata_size = newsize; 00079 AV_WB16(avc_context->extradata + (*offset), packet->bytes); 00080 *offset += 2; 00081 memcpy(avc_context->extradata + (*offset), packet->packet, packet->bytes); 00082 (*offset) += packet->bytes; 00083 return 0; 00084 } 00085 00086 static int get_stats(AVCodecContext *avctx, int eos) 00087 { 00088 #ifdef TH_ENCCTL_2PASS_OUT 00089 TheoraContext *h = avctx->priv_data; 00090 uint8_t *buf; 00091 int bytes; 00092 00093 bytes = th_encode_ctl(h->t_state, TH_ENCCTL_2PASS_OUT, &buf, sizeof(buf)); 00094 if (bytes < 0) { 00095 av_log(avctx, AV_LOG_ERROR, "Error getting first pass stats\n"); 00096 return -1; 00097 } 00098 if (!eos) { 00099 h->stats = av_fast_realloc(h->stats, &h->stats_size, 00100 h->stats_offset + bytes); 00101 memcpy(h->stats + h->stats_offset, buf, bytes); 00102 h->stats_offset += bytes; 00103 } else { 00104 int b64_size = ((h->stats_offset + 2) / 3) * 4 + 1; 00105 // libtheora generates a summary header at the end 00106 memcpy(h->stats, buf, bytes); 00107 avctx->stats_out = av_malloc(b64_size); 00108 av_base64_encode(avctx->stats_out, b64_size, h->stats, h->stats_offset); 00109 } 00110 return 0; 00111 #else 00112 av_log(avctx, AV_LOG_ERROR, "libtheora too old to support 2pass\n"); 00113 return -1; 00114 #endif 00115 } 00116 00117 // libtheora won't read the entire buffer we give it at once, so we have to 00118 // repeatedly submit it... 00119 static int submit_stats(AVCodecContext *avctx) 00120 { 00121 #ifdef TH_ENCCTL_2PASS_IN 00122 TheoraContext *h = avctx->priv_data; 00123 int bytes; 00124 if (!h->stats) { 00125 if (!avctx->stats_in) { 00126 av_log(avctx, AV_LOG_ERROR, "No statsfile for second pass\n"); 00127 return -1; 00128 } 00129 h->stats_size = strlen(avctx->stats_in) * 3/4; 00130 h->stats = av_malloc(h->stats_size); 00131 h->stats_size = av_base64_decode(h->stats, avctx->stats_in, h->stats_size); 00132 } 00133 while (h->stats_size - h->stats_offset > 0) { 00134 bytes = th_encode_ctl(h->t_state, TH_ENCCTL_2PASS_IN, 00135 h->stats + h->stats_offset, 00136 h->stats_size - h->stats_offset); 00137 if (bytes < 0) { 00138 av_log(avctx, AV_LOG_ERROR, "Error submitting stats\n"); 00139 return -1; 00140 } 00141 if (!bytes) 00142 return 0; 00143 h->stats_offset += bytes; 00144 } 00145 return 0; 00146 #else 00147 av_log(avctx, AV_LOG_ERROR, "libtheora too old to support 2pass\n"); 00148 return -1; 00149 #endif 00150 } 00151 00152 static av_cold int encode_init(AVCodecContext* avc_context) 00153 { 00154 th_info t_info; 00155 th_comment t_comment; 00156 ogg_packet o_packet; 00157 unsigned int offset; 00158 TheoraContext *h = avc_context->priv_data; 00159 uint32_t gop_size = avc_context->gop_size; 00160 00161 /* Set up the theora_info struct */ 00162 th_info_init(&t_info); 00163 t_info.frame_width = FFALIGN(avc_context->width, 16); 00164 t_info.frame_height = FFALIGN(avc_context->height, 16); 00165 t_info.pic_width = avc_context->width; 00166 t_info.pic_height = avc_context->height; 00167 t_info.pic_x = 0; 00168 t_info.pic_y = 0; 00169 /* Swap numerator and denominator as time_base in AVCodecContext gives the 00170 * time period between frames, but theora_info needs the framerate. */ 00171 t_info.fps_numerator = avc_context->time_base.den; 00172 t_info.fps_denominator = avc_context->time_base.num; 00173 if (avc_context->sample_aspect_ratio.num) { 00174 t_info.aspect_numerator = avc_context->sample_aspect_ratio.num; 00175 t_info.aspect_denominator = avc_context->sample_aspect_ratio.den; 00176 } else { 00177 t_info.aspect_numerator = 1; 00178 t_info.aspect_denominator = 1; 00179 } 00180 00181 if (avc_context->color_primaries == AVCOL_PRI_BT470M) 00182 t_info.colorspace = TH_CS_ITU_REC_470M; 00183 else if (avc_context->color_primaries == AVCOL_PRI_BT470BG) 00184 t_info.colorspace = TH_CS_ITU_REC_470BG; 00185 else 00186 t_info.colorspace = TH_CS_UNSPECIFIED; 00187 00188 if (avc_context->pix_fmt == PIX_FMT_YUV420P) 00189 t_info.pixel_fmt = TH_PF_420; 00190 else if (avc_context->pix_fmt == PIX_FMT_YUV422P) 00191 t_info.pixel_fmt = TH_PF_422; 00192 else if (avc_context->pix_fmt == PIX_FMT_YUV444P) 00193 t_info.pixel_fmt = TH_PF_444; 00194 else { 00195 av_log(avc_context, AV_LOG_ERROR, "Unsupported pix_fmt\n"); 00196 return -1; 00197 } 00198 avcodec_get_chroma_sub_sample(avc_context->pix_fmt, &h->uv_hshift, &h->uv_vshift); 00199 00200 if (avc_context->flags & CODEC_FLAG_QSCALE) { 00201 /* to be constant with the libvorbis implementation, clip global_quality to 0 - 10 00202 Theora accepts a quality parameter p, which is: 00203 * 0 <= p <=63 00204 * an int value 00205 */ 00206 t_info.quality = av_clip(avc_context->global_quality / (float)FF_QP2LAMBDA, 0, 10) * 6.3; 00207 t_info.target_bitrate = 0; 00208 } else { 00209 t_info.target_bitrate = avc_context->bit_rate; 00210 t_info.quality = 0; 00211 } 00212 00213 /* Now initialise libtheora */ 00214 h->t_state = th_encode_alloc(&t_info); 00215 if (!h->t_state) { 00216 av_log(avc_context, AV_LOG_ERROR, "theora_encode_init failed\n"); 00217 return -1; 00218 } 00219 00220 h->keyframe_mask = (1 << t_info.keyframe_granule_shift) - 1; 00221 /* Clear up theora_info struct */ 00222 th_info_clear(&t_info); 00223 00224 if (th_encode_ctl(h->t_state, TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE, 00225 &gop_size, sizeof(gop_size))) { 00226 av_log(avc_context, AV_LOG_ERROR, "Error setting GOP size\n"); 00227 return -1; 00228 } 00229 00230 // need to enable 2 pass (via TH_ENCCTL_2PASS_) before encoding headers 00231 if (avc_context->flags & CODEC_FLAG_PASS1) { 00232 if (get_stats(avc_context, 0)) 00233 return -1; 00234 } else if (avc_context->flags & CODEC_FLAG_PASS2) { 00235 if (submit_stats(avc_context)) 00236 return -1; 00237 } 00238 00239 /* 00240 Output first header packet consisting of theora 00241 header, comment, and tables. 00242 00243 Each one is prefixed with a 16bit size, then they 00244 are concatenated together into ffmpeg's extradata. 00245 */ 00246 offset = 0; 00247 00248 /* Headers */ 00249 th_comment_init(&t_comment); 00250 00251 while (th_encode_flushheader(h->t_state, &t_comment, &o_packet)) 00252 if (concatenate_packet(&offset, avc_context, &o_packet)) 00253 return -1; 00254 00255 th_comment_clear(&t_comment); 00256 00257 /* Set up the output AVFrame */ 00258 avc_context->coded_frame= avcodec_alloc_frame(); 00259 00260 return 0; 00261 } 00262 00263 static int encode_frame(AVCodecContext* avc_context, uint8_t *outbuf, 00264 int buf_size, void *data) 00265 { 00266 th_ycbcr_buffer t_yuv_buffer; 00267 TheoraContext *h = avc_context->priv_data; 00268 AVFrame *frame = data; 00269 ogg_packet o_packet; 00270 int result, i; 00271 00272 // EOS, finish and get 1st pass stats if applicable 00273 if (!frame) { 00274 th_encode_packetout(h->t_state, 1, &o_packet); 00275 if (avc_context->flags & CODEC_FLAG_PASS1) 00276 if (get_stats(avc_context, 1)) 00277 return -1; 00278 return 0; 00279 } 00280 00281 /* Copy planes to the theora yuv_buffer */ 00282 for (i = 0; i < 3; i++) { 00283 t_yuv_buffer[i].width = FFALIGN(avc_context->width, 16) >> (i && h->uv_hshift); 00284 t_yuv_buffer[i].height = FFALIGN(avc_context->height, 16) >> (i && h->uv_vshift); 00285 t_yuv_buffer[i].stride = frame->linesize[i]; 00286 t_yuv_buffer[i].data = frame->data[i]; 00287 } 00288 00289 if (avc_context->flags & CODEC_FLAG_PASS2) 00290 if (submit_stats(avc_context)) 00291 return -1; 00292 00293 /* Now call into theora_encode_YUVin */ 00294 result = th_encode_ycbcr_in(h->t_state, t_yuv_buffer); 00295 if (result) { 00296 const char* message; 00297 switch (result) { 00298 case -1: 00299 message = "differing frame sizes"; 00300 break; 00301 case TH_EINVAL: 00302 message = "encoder is not ready or is finished"; 00303 break; 00304 default: 00305 message = "unknown reason"; 00306 break; 00307 } 00308 av_log(avc_context, AV_LOG_ERROR, "theora_encode_YUVin failed (%s) [%d]\n", message, result); 00309 return -1; 00310 } 00311 00312 if (avc_context->flags & CODEC_FLAG_PASS1) 00313 if (get_stats(avc_context, 0)) 00314 return -1; 00315 00316 /* Pick up returned ogg_packet */ 00317 result = th_encode_packetout(h->t_state, 0, &o_packet); 00318 switch (result) { 00319 case 0: 00320 /* No packet is ready */ 00321 return 0; 00322 case 1: 00323 /* Success, we have a packet */ 00324 break; 00325 default: 00326 av_log(avc_context, AV_LOG_ERROR, "theora_encode_packetout failed [%d]\n", result); 00327 return -1; 00328 } 00329 00330 /* Copy ogg_packet content out to buffer */ 00331 if (buf_size < o_packet.bytes) { 00332 av_log(avc_context, AV_LOG_ERROR, "encoded frame too large\n"); 00333 return -1; 00334 } 00335 memcpy(outbuf, o_packet.packet, o_packet.bytes); 00336 00337 // HACK: assumes no encoder delay, this is true until libtheora becomes 00338 // multithreaded (which will be disabled unless explictly requested) 00339 avc_context->coded_frame->pts = frame->pts; 00340 avc_context->coded_frame->key_frame = !(o_packet.granulepos & h->keyframe_mask); 00341 00342 return o_packet.bytes; 00343 } 00344 00345 static av_cold int encode_close(AVCodecContext* avc_context) 00346 { 00347 TheoraContext *h = avc_context->priv_data; 00348 00349 th_encode_free(h->t_state); 00350 av_freep(&h->stats); 00351 av_freep(&avc_context->coded_frame); 00352 av_freep(&avc_context->stats_out); 00353 av_freep(&avc_context->extradata); 00354 avc_context->extradata_size = 0; 00355 00356 return 0; 00357 } 00358 00360 AVCodec libtheora_encoder = { 00361 .name = "libtheora", 00362 .type = AVMEDIA_TYPE_VIDEO, 00363 .id = CODEC_ID_THEORA, 00364 .priv_data_size = sizeof(TheoraContext), 00365 .init = encode_init, 00366 .close = encode_close, 00367 .encode = encode_frame, 00368 .capabilities = CODEC_CAP_DELAY, // needed to get the statsfile summary 00369 .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_NONE}, 00370 .long_name = NULL_IF_CONFIG_SMALL("libtheora Theora"), 00371 };