libavcodec/libvpxenc.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2010, Google, Inc.
00003  *
00004  * This file is part of Libav.
00005  *
00006  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00020 
00026 #define VPX_DISABLE_CTRL_TYPECHECKS 1
00027 #define VPX_CODEC_DISABLE_COMPAT    1
00028 #include <vpx/vpx_encoder.h>
00029 #include <vpx/vp8cx.h>
00030 
00031 #include "avcodec.h"
00032 #include "internal.h"
00033 #include "libavutil/base64.h"
00034 #include "libavutil/mathematics.h"
00035 #include "libavutil/opt.h"
00036 
00041 struct FrameListData {
00042     void *buf;                       
00043     size_t sz;                       
00044     int64_t pts;                     
00046     unsigned long duration;          
00048     uint32_t flags;                  
00049     struct FrameListData *next;
00050 };
00051 
00052 typedef struct VP8EncoderContext {
00053     AVClass *class;
00054     struct vpx_codec_ctx encoder;
00055     struct vpx_image rawimg;
00056     struct vpx_fixed_buf twopass_stats;
00057     unsigned long deadline; //i.e., RT/GOOD/BEST
00058     struct FrameListData *coded_frame_list;
00059     int cpu_used;
00060     int auto_alt_ref;
00061     int arnr_max_frames;
00062     int arnr_strength;
00063     int arnr_type;
00064     int lag_in_frames;
00065     int error_resilient;
00066 } VP8Context;
00067 
00069 static const char *ctlidstr[] = {
00070     [VP8E_UPD_ENTROPY]           = "VP8E_UPD_ENTROPY",
00071     [VP8E_UPD_REFERENCE]         = "VP8E_UPD_REFERENCE",
00072     [VP8E_USE_REFERENCE]         = "VP8E_USE_REFERENCE",
00073     [VP8E_SET_ROI_MAP]           = "VP8E_SET_ROI_MAP",
00074     [VP8E_SET_ACTIVEMAP]         = "VP8E_SET_ACTIVEMAP",
00075     [VP8E_SET_SCALEMODE]         = "VP8E_SET_SCALEMODE",
00076     [VP8E_SET_CPUUSED]           = "VP8E_SET_CPUUSED",
00077     [VP8E_SET_ENABLEAUTOALTREF]  = "VP8E_SET_ENABLEAUTOALTREF",
00078     [VP8E_SET_NOISE_SENSITIVITY] = "VP8E_SET_NOISE_SENSITIVITY",
00079     [VP8E_SET_SHARPNESS]         = "VP8E_SET_SHARPNESS",
00080     [VP8E_SET_STATIC_THRESHOLD]  = "VP8E_SET_STATIC_THRESHOLD",
00081     [VP8E_SET_TOKEN_PARTITIONS]  = "VP8E_SET_TOKEN_PARTITIONS",
00082     [VP8E_GET_LAST_QUANTIZER]    = "VP8E_GET_LAST_QUANTIZER",
00083     [VP8E_SET_ARNR_MAXFRAMES]    = "VP8E_SET_ARNR_MAXFRAMES",
00084     [VP8E_SET_ARNR_STRENGTH]     = "VP8E_SET_ARNR_STRENGTH",
00085     [VP8E_SET_ARNR_TYPE]         = "VP8E_SET_ARNR_TYPE",
00086 };
00087 
00088 static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc)
00089 {
00090     VP8Context *ctx = avctx->priv_data;
00091     const char *error  = vpx_codec_error(&ctx->encoder);
00092     const char *detail = vpx_codec_error_detail(&ctx->encoder);
00093 
00094     av_log(avctx, AV_LOG_ERROR, "%s: %s\n", desc, error);
00095     if (detail)
00096         av_log(avctx, AV_LOG_ERROR, "  Additional information: %s\n", detail);
00097 }
00098 
00099 static av_cold void dump_enc_cfg(AVCodecContext *avctx,
00100                                  const struct vpx_codec_enc_cfg *cfg)
00101 {
00102     int width = -30;
00103     int level = AV_LOG_DEBUG;
00104 
00105     av_log(avctx, level, "vpx_codec_enc_cfg\n");
00106     av_log(avctx, level, "generic settings\n"
00107            "  %*s%u\n  %*s%u\n  %*s%u\n  %*s%u\n  %*s%u\n"
00108            "  %*s{%u/%u}\n  %*s%u\n  %*s%d\n  %*s%u\n",
00109            width, "g_usage:",           cfg->g_usage,
00110            width, "g_threads:",         cfg->g_threads,
00111            width, "g_profile:",         cfg->g_profile,
00112            width, "g_w:",               cfg->g_w,
00113            width, "g_h:",               cfg->g_h,
00114            width, "g_timebase:",        cfg->g_timebase.num, cfg->g_timebase.den,
00115            width, "g_error_resilient:", cfg->g_error_resilient,
00116            width, "g_pass:",            cfg->g_pass,
00117            width, "g_lag_in_frames:",   cfg->g_lag_in_frames);
00118     av_log(avctx, level, "rate control settings\n"
00119            "  %*s%u\n  %*s%u\n  %*s%u\n  %*s%u\n"
00120            "  %*s%d\n  %*s%p(%zu)\n  %*s%u\n",
00121            width, "rc_dropframe_thresh:",   cfg->rc_dropframe_thresh,
00122            width, "rc_resize_allowed:",     cfg->rc_resize_allowed,
00123            width, "rc_resize_up_thresh:",   cfg->rc_resize_up_thresh,
00124            width, "rc_resize_down_thresh:", cfg->rc_resize_down_thresh,
00125            width, "rc_end_usage:",          cfg->rc_end_usage,
00126            width, "rc_twopass_stats_in:",   cfg->rc_twopass_stats_in.buf, cfg->rc_twopass_stats_in.sz,
00127            width, "rc_target_bitrate:",     cfg->rc_target_bitrate);
00128     av_log(avctx, level, "quantizer settings\n"
00129            "  %*s%u\n  %*s%u\n",
00130            width, "rc_min_quantizer:", cfg->rc_min_quantizer,
00131            width, "rc_max_quantizer:", cfg->rc_max_quantizer);
00132     av_log(avctx, level, "bitrate tolerance\n"
00133            "  %*s%u\n  %*s%u\n",
00134            width, "rc_undershoot_pct:", cfg->rc_undershoot_pct,
00135            width, "rc_overshoot_pct:",  cfg->rc_overshoot_pct);
00136     av_log(avctx, level, "decoder buffer model\n"
00137             "  %*s%u\n  %*s%u\n  %*s%u\n",
00138             width, "rc_buf_sz:",         cfg->rc_buf_sz,
00139             width, "rc_buf_initial_sz:", cfg->rc_buf_initial_sz,
00140             width, "rc_buf_optimal_sz:", cfg->rc_buf_optimal_sz);
00141     av_log(avctx, level, "2 pass rate control settings\n"
00142            "  %*s%u\n  %*s%u\n  %*s%u\n",
00143            width, "rc_2pass_vbr_bias_pct:",       cfg->rc_2pass_vbr_bias_pct,
00144            width, "rc_2pass_vbr_minsection_pct:", cfg->rc_2pass_vbr_minsection_pct,
00145            width, "rc_2pass_vbr_maxsection_pct:", cfg->rc_2pass_vbr_maxsection_pct);
00146     av_log(avctx, level, "keyframing settings\n"
00147            "  %*s%d\n  %*s%u\n  %*s%u\n",
00148            width, "kf_mode:",     cfg->kf_mode,
00149            width, "kf_min_dist:", cfg->kf_min_dist,
00150            width, "kf_max_dist:", cfg->kf_max_dist);
00151     av_log(avctx, level, "\n");
00152 }
00153 
00154 static void coded_frame_add(void *list, struct FrameListData *cx_frame)
00155 {
00156     struct FrameListData **p = list;
00157 
00158     while (*p != NULL)
00159         p = &(*p)->next;
00160     *p = cx_frame;
00161     cx_frame->next = NULL;
00162 }
00163 
00164 static av_cold void free_coded_frame(struct FrameListData *cx_frame)
00165 {
00166     av_freep(&cx_frame->buf);
00167     av_freep(&cx_frame);
00168 }
00169 
00170 static av_cold void free_frame_list(struct FrameListData *list)
00171 {
00172     struct FrameListData *p = list;
00173 
00174     while (p) {
00175         list = list->next;
00176         free_coded_frame(p);
00177         p = list;
00178     }
00179 }
00180 
00181 static av_cold int codecctl_int(AVCodecContext *avctx,
00182                                 enum vp8e_enc_control_id id, int val)
00183 {
00184     VP8Context *ctx = avctx->priv_data;
00185     char buf[80];
00186     int width = -30;
00187     int res;
00188 
00189     snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]);
00190     av_log(avctx, AV_LOG_DEBUG, "  %*s%d\n", width, buf, val);
00191 
00192     res = vpx_codec_control(&ctx->encoder, id, val);
00193     if (res != VPX_CODEC_OK) {
00194         snprintf(buf, sizeof(buf), "Failed to set %s codec control",
00195                  ctlidstr[id]);
00196         log_encoder_error(avctx, buf);
00197     }
00198 
00199     return res == VPX_CODEC_OK ? 0 : AVERROR(EINVAL);
00200 }
00201 
00202 static av_cold int vp8_free(AVCodecContext *avctx)
00203 {
00204     VP8Context *ctx = avctx->priv_data;
00205 
00206     vpx_codec_destroy(&ctx->encoder);
00207     av_freep(&ctx->twopass_stats.buf);
00208     av_freep(&avctx->coded_frame);
00209     av_freep(&avctx->stats_out);
00210     free_frame_list(ctx->coded_frame_list);
00211     return 0;
00212 }
00213 
00214 static av_cold int vp8_init(AVCodecContext *avctx)
00215 {
00216     VP8Context *ctx = avctx->priv_data;
00217     const struct vpx_codec_iface *iface = &vpx_codec_vp8_cx_algo;
00218     struct vpx_codec_enc_cfg enccfg;
00219     int res;
00220 
00221     av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str());
00222     av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config());
00223 
00224     if ((res = vpx_codec_enc_config_default(iface, &enccfg, 0)) != VPX_CODEC_OK) {
00225         av_log(avctx, AV_LOG_ERROR, "Failed to get config: %s\n",
00226                vpx_codec_err_to_string(res));
00227         return AVERROR(EINVAL);
00228     }
00229     dump_enc_cfg(avctx, &enccfg);
00230 
00231     enccfg.g_w            = avctx->width;
00232     enccfg.g_h            = avctx->height;
00233     enccfg.g_timebase.num = avctx->time_base.num;
00234     enccfg.g_timebase.den = avctx->time_base.den;
00235     enccfg.g_threads      = avctx->thread_count;
00236 
00237     if (ctx->lag_in_frames >= 0)
00238         enccfg.g_lag_in_frames = ctx->lag_in_frames;
00239 
00240     if (avctx->flags & CODEC_FLAG_PASS1)
00241         enccfg.g_pass = VPX_RC_FIRST_PASS;
00242     else if (avctx->flags & CODEC_FLAG_PASS2)
00243         enccfg.g_pass = VPX_RC_LAST_PASS;
00244     else
00245         enccfg.g_pass = VPX_RC_ONE_PASS;
00246 
00247     if (avctx->rc_min_rate == avctx->rc_max_rate &&
00248         avctx->rc_min_rate == avctx->bit_rate)
00249         enccfg.rc_end_usage = VPX_CBR;
00250     enccfg.rc_target_bitrate = av_rescale_rnd(avctx->bit_rate, 1, 1000,
00251                                               AV_ROUND_NEAR_INF);
00252     if (avctx->qmin > 0)
00253         enccfg.rc_min_quantizer = avctx->qmin;
00254     if (avctx->qmax > 0)
00255         enccfg.rc_max_quantizer = avctx->qmax;
00256     enccfg.rc_dropframe_thresh = avctx->frame_skip_threshold;
00257 
00258     //0-100 (0 => CBR, 100 => VBR)
00259     enccfg.rc_2pass_vbr_bias_pct           = round(avctx->qcompress * 100);
00260     enccfg.rc_2pass_vbr_minsection_pct     =
00261         avctx->rc_min_rate * 100LL / avctx->bit_rate;
00262     if (avctx->rc_max_rate)
00263         enccfg.rc_2pass_vbr_maxsection_pct =
00264             avctx->rc_max_rate * 100LL / avctx->bit_rate;
00265 
00266     if (avctx->rc_buffer_size)
00267         enccfg.rc_buf_sz         =
00268             avctx->rc_buffer_size * 1000LL / avctx->bit_rate;
00269     if (avctx->rc_initial_buffer_occupancy)
00270         enccfg.rc_buf_initial_sz =
00271             avctx->rc_initial_buffer_occupancy * 1000LL / avctx->bit_rate;
00272     enccfg.rc_buf_optimal_sz     = enccfg.rc_buf_sz * 5 / 6;
00273 
00274     //_enc_init() will balk if kf_min_dist differs from max w/VPX_KF_AUTO
00275     if (avctx->keyint_min >= 0 && avctx->keyint_min == avctx->gop_size)
00276         enccfg.kf_min_dist = avctx->keyint_min;
00277     if (avctx->gop_size >= 0)
00278         enccfg.kf_max_dist = avctx->gop_size;
00279 
00280     if (enccfg.g_pass == VPX_RC_FIRST_PASS)
00281         enccfg.g_lag_in_frames = 0;
00282     else if (enccfg.g_pass == VPX_RC_LAST_PASS) {
00283         int decode_size;
00284 
00285         if (!avctx->stats_in) {
00286             av_log(avctx, AV_LOG_ERROR, "No stats file for second pass\n");
00287             return AVERROR_INVALIDDATA;
00288         }
00289 
00290         ctx->twopass_stats.sz  = strlen(avctx->stats_in) * 3 / 4;
00291         ctx->twopass_stats.buf = av_malloc(ctx->twopass_stats.sz);
00292         if (!ctx->twopass_stats.buf) {
00293             av_log(avctx, AV_LOG_ERROR,
00294                    "Stat buffer alloc (%zu bytes) failed\n",
00295                    ctx->twopass_stats.sz);
00296             return AVERROR(ENOMEM);
00297         }
00298         decode_size = av_base64_decode(ctx->twopass_stats.buf, avctx->stats_in,
00299                                        ctx->twopass_stats.sz);
00300         if (decode_size < 0) {
00301             av_log(avctx, AV_LOG_ERROR, "Stat buffer decode failed\n");
00302             return AVERROR_INVALIDDATA;
00303         }
00304 
00305         ctx->twopass_stats.sz      = decode_size;
00306         enccfg.rc_twopass_stats_in = ctx->twopass_stats;
00307     }
00308 
00309     /* 0-3: For non-zero values the encoder increasingly optimizes for reduced
00310        complexity playback on low powered devices at the expense of encode
00311        quality. */
00312    if (avctx->profile != FF_PROFILE_UNKNOWN)
00313        enccfg.g_profile = avctx->profile;
00314 
00315     enccfg.g_error_resilient = ctx->error_resilient;
00316 
00317     dump_enc_cfg(avctx, &enccfg);
00318     /* Construct Encoder Context */
00319     res = vpx_codec_enc_init(&ctx->encoder, iface, &enccfg, 0);
00320     if (res != VPX_CODEC_OK) {
00321         log_encoder_error(avctx, "Failed to initialize encoder");
00322         return AVERROR(EINVAL);
00323     }
00324 
00325     //codec control failures are currently treated only as warnings
00326     av_log(avctx, AV_LOG_DEBUG, "vpx_codec_control\n");
00327     if (ctx->cpu_used != INT_MIN)
00328         codecctl_int(avctx, VP8E_SET_CPUUSED,          ctx->cpu_used);
00329     if (ctx->auto_alt_ref >= 0)
00330         codecctl_int(avctx, VP8E_SET_ENABLEAUTOALTREF, ctx->auto_alt_ref);
00331     if (ctx->arnr_max_frames >= 0)
00332         codecctl_int(avctx, VP8E_SET_ARNR_MAXFRAMES,   ctx->arnr_max_frames);
00333     if (ctx->arnr_strength >= 0)
00334         codecctl_int(avctx, VP8E_SET_ARNR_STRENGTH,    ctx->arnr_strength);
00335     if (ctx->arnr_type >= 0)
00336         codecctl_int(avctx, VP8E_SET_ARNR_TYPE,        ctx->arnr_type);
00337     codecctl_int(avctx, VP8E_SET_NOISE_SENSITIVITY, avctx->noise_reduction);
00338     codecctl_int(avctx, VP8E_SET_TOKEN_PARTITIONS,  av_log2(avctx->slices));
00339     codecctl_int(avctx, VP8E_SET_STATIC_THRESHOLD,  avctx->mb_threshold);
00340 
00341     //provide dummy value to initialize wrapper, values will be updated each _encode()
00342     vpx_img_wrap(&ctx->rawimg, VPX_IMG_FMT_I420, avctx->width, avctx->height, 1,
00343                  (unsigned char*)1);
00344 
00345     avctx->coded_frame = avcodec_alloc_frame();
00346     if (!avctx->coded_frame) {
00347         av_log(avctx, AV_LOG_ERROR, "Error allocating coded frame\n");
00348         vp8_free(avctx);
00349         return AVERROR(ENOMEM);
00350     }
00351     return 0;
00352 }
00353 
00354 static inline void cx_pktcpy(struct FrameListData *dst,
00355                              const struct vpx_codec_cx_pkt *src)
00356 {
00357     dst->pts      = src->data.frame.pts;
00358     dst->duration = src->data.frame.duration;
00359     dst->flags    = src->data.frame.flags;
00360     dst->sz       = src->data.frame.sz;
00361     dst->buf      = src->data.frame.buf;
00362 }
00363 
00372 static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame,
00373                       uint8_t *buf, int buf_size, AVFrame *coded_frame)
00374 {
00375     if ((int) cx_frame->sz <= buf_size) {
00376         buf_size = cx_frame->sz;
00377         memcpy(buf, cx_frame->buf, buf_size);
00378         coded_frame->pts       = cx_frame->pts;
00379         coded_frame->key_frame = !!(cx_frame->flags & VPX_FRAME_IS_KEY);
00380 
00381         if (coded_frame->key_frame)
00382             coded_frame->pict_type = AV_PICTURE_TYPE_I;
00383         else
00384             coded_frame->pict_type = AV_PICTURE_TYPE_P;
00385     } else {
00386         av_log(avctx, AV_LOG_ERROR,
00387                "Compressed frame larger than storage provided! (%zu/%d)\n",
00388                cx_frame->sz, buf_size);
00389         return AVERROR(EINVAL);
00390     }
00391     return buf_size;
00392 }
00393 
00402 static int queue_frames(AVCodecContext *avctx, uint8_t *buf, int buf_size,
00403                         AVFrame *coded_frame)
00404 {
00405     VP8Context *ctx = avctx->priv_data;
00406     const struct vpx_codec_cx_pkt *pkt;
00407     const void *iter = NULL;
00408     int size = 0;
00409 
00410     if (ctx->coded_frame_list) {
00411         struct FrameListData *cx_frame = ctx->coded_frame_list;
00412         /* return the leading frame if we've already begun queueing */
00413         size = storeframe(avctx, cx_frame, buf, buf_size, coded_frame);
00414         if (size < 0)
00415             return AVERROR(EINVAL);
00416         ctx->coded_frame_list = cx_frame->next;
00417         free_coded_frame(cx_frame);
00418     }
00419 
00420     /* consume all available output from the encoder before returning. buffers
00421        are only good through the next vpx_codec call */
00422     while ((pkt = vpx_codec_get_cx_data(&ctx->encoder, &iter))) {
00423         switch (pkt->kind) {
00424         case VPX_CODEC_CX_FRAME_PKT:
00425             if (!size) {
00426                 struct FrameListData cx_frame;
00427 
00428                 /* avoid storing the frame when the list is empty and we haven't yet
00429                    provided a frame for output */
00430                 assert(!ctx->coded_frame_list);
00431                 cx_pktcpy(&cx_frame, pkt);
00432                 size = storeframe(avctx, &cx_frame, buf, buf_size, coded_frame);
00433                 if (size < 0)
00434                     return AVERROR(EINVAL);
00435             } else {
00436                 struct FrameListData *cx_frame =
00437                     av_malloc(sizeof(struct FrameListData));
00438 
00439                 if (!cx_frame) {
00440                     av_log(avctx, AV_LOG_ERROR,
00441                            "Frame queue element alloc failed\n");
00442                     return AVERROR(ENOMEM);
00443                 }
00444                 cx_pktcpy(cx_frame, pkt);
00445                 cx_frame->buf = av_malloc(cx_frame->sz);
00446 
00447                 if (!cx_frame->buf) {
00448                     av_log(avctx, AV_LOG_ERROR,
00449                            "Data buffer alloc (%zu bytes) failed\n",
00450                            cx_frame->sz);
00451                     return AVERROR(ENOMEM);
00452                 }
00453                 memcpy(cx_frame->buf, pkt->data.frame.buf, pkt->data.frame.sz);
00454                 coded_frame_add(&ctx->coded_frame_list, cx_frame);
00455             }
00456             break;
00457         case VPX_CODEC_STATS_PKT: {
00458             struct vpx_fixed_buf *stats = &ctx->twopass_stats;
00459             stats->buf = av_realloc(stats->buf,
00460                                     stats->sz + pkt->data.twopass_stats.sz);
00461             if (!stats->buf) {
00462                 av_log(avctx, AV_LOG_ERROR, "Stat buffer realloc failed\n");
00463                 return AVERROR(ENOMEM);
00464             }
00465             memcpy((uint8_t*)stats->buf + stats->sz,
00466                    pkt->data.twopass_stats.buf, pkt->data.twopass_stats.sz);
00467             stats->sz += pkt->data.twopass_stats.sz;
00468             break;
00469         }
00470         case VPX_CODEC_PSNR_PKT: //FIXME add support for CODEC_FLAG_PSNR
00471         case VPX_CODEC_CUSTOM_PKT:
00472             //ignore unsupported/unrecognized packet types
00473             break;
00474         }
00475     }
00476 
00477     return size;
00478 }
00479 
00480 static int vp8_encode(AVCodecContext *avctx, uint8_t *buf, int buf_size,
00481                       void *data)
00482 {
00483     VP8Context *ctx = avctx->priv_data;
00484     AVFrame *frame = data;
00485     struct vpx_image *rawimg = NULL;
00486     int64_t timestamp = 0;
00487     int res, coded_size;
00488 
00489     if (frame) {
00490         rawimg                      = &ctx->rawimg;
00491         rawimg->planes[VPX_PLANE_Y] = frame->data[0];
00492         rawimg->planes[VPX_PLANE_U] = frame->data[1];
00493         rawimg->planes[VPX_PLANE_V] = frame->data[2];
00494         rawimg->stride[VPX_PLANE_Y] = frame->linesize[0];
00495         rawimg->stride[VPX_PLANE_U] = frame->linesize[1];
00496         rawimg->stride[VPX_PLANE_V] = frame->linesize[2];
00497         timestamp                   = frame->pts;
00498     }
00499 
00500     res = vpx_codec_encode(&ctx->encoder, rawimg, timestamp,
00501                            avctx->ticks_per_frame, 0, ctx->deadline);
00502     if (res != VPX_CODEC_OK) {
00503         log_encoder_error(avctx, "Error encoding frame");
00504         return AVERROR_INVALIDDATA;
00505     }
00506     coded_size = queue_frames(avctx, buf, buf_size, avctx->coded_frame);
00507 
00508     if (!frame && avctx->flags & CODEC_FLAG_PASS1) {
00509         unsigned int b64_size = AV_BASE64_SIZE(ctx->twopass_stats.sz);
00510 
00511         avctx->stats_out = av_malloc(b64_size);
00512         if (!avctx->stats_out) {
00513             av_log(avctx, AV_LOG_ERROR, "Stat buffer alloc (%d bytes) failed\n",
00514                    b64_size);
00515             return AVERROR(ENOMEM);
00516         }
00517         av_base64_encode(avctx->stats_out, b64_size, ctx->twopass_stats.buf,
00518                          ctx->twopass_stats.sz);
00519     }
00520     return coded_size;
00521 }
00522 
00523 #define OFFSET(x) offsetof(VP8Context, x)
00524 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
00525 static const AVOption options[] = {
00526     { "cpu-used",        "Quality/Speed ratio modifier",           OFFSET(cpu_used),        AV_OPT_TYPE_INT, {INT_MIN}, INT_MIN, INT_MAX, VE},
00527     { "auto-alt-ref",    "Enable use of alternate reference "
00528                          "frames (2-pass only)",                   OFFSET(auto_alt_ref),    AV_OPT_TYPE_INT, {-1},      -1,      1,       VE},
00529     { "lag-in-frames",   "Number of frames to look ahead for "
00530                          "alternate reference frame selection",    OFFSET(lag_in_frames),   AV_OPT_TYPE_INT, {-1},      -1,      INT_MAX, VE},
00531     { "arnr-maxframes",  "altref noise reduction max frame count", OFFSET(arnr_max_frames), AV_OPT_TYPE_INT, {-1},      -1,      INT_MAX, VE},
00532     { "arnr-strength",   "altref noise reduction filter strength", OFFSET(arnr_strength),   AV_OPT_TYPE_INT, {-1},      -1,      INT_MAX, VE},
00533     { "arnr-type",       "altref noise reduction filter type",     OFFSET(arnr_type),       AV_OPT_TYPE_INT, {-1},      -1,      INT_MAX, VE, "arnr_type"},
00534     { "backward",        NULL, 0, AV_OPT_TYPE_CONST, {1}, 0, 0, VE, "arnr_type" },
00535     { "forward",         NULL, 0, AV_OPT_TYPE_CONST, {2}, 0, 0, VE, "arnr_type" },
00536     { "centered",        NULL, 0, AV_OPT_TYPE_CONST, {3}, 0, 0, VE, "arnr_type" },
00537     { "deadline",        "Time to spend encoding, in microseconds.", OFFSET(deadline),      AV_OPT_TYPE_INT, {VPX_DL_GOOD_QUALITY}, INT_MIN, INT_MAX, VE, "quality"},
00538     { "best",            NULL, 0, AV_OPT_TYPE_CONST, {VPX_DL_BEST_QUALITY}, 0, 0, VE, "quality"},
00539     { "good",            NULL, 0, AV_OPT_TYPE_CONST, {VPX_DL_GOOD_QUALITY}, 0, 0, VE, "quality"},
00540     { "realtime",        NULL, 0, AV_OPT_TYPE_CONST, {VPX_DL_REALTIME},     0, 0, VE, "quality"},
00541     { "error-resilient", "Error resilience configuration", OFFSET(error_resilient), AV_OPT_TYPE_FLAGS, {0}, INT_MIN, INT_MAX, VE, "er"},
00542 #ifdef VPX_ERROR_RESILIENT_DEFAULT
00543     { "default",         "Improve resiliency against losses of whole frames", 0, AV_OPT_TYPE_CONST, {VPX_ERROR_RESILIENT_DEFAULT}, 0, 0, VE, "er"},
00544     { "partitions",      "The frame partitions are independently decodable "
00545                          "by the bool decoder, meaning that partitions can be decoded even "
00546                          "though earlier partitions have been lost. Note that intra predicition"
00547                          " is still done over the partition boundary.",       0, AV_OPT_TYPE_CONST, {VPX_ERROR_RESILIENT_PARTITIONS}, 0, 0, VE, "er"},
00548 #endif
00549     { NULL }
00550 };
00551 
00552 static const AVClass class = {
00553     .class_name = "libvpx encoder",
00554     .item_name  = av_default_item_name,
00555     .option     = options,
00556     .version    = LIBAVUTIL_VERSION_INT,
00557 };
00558 
00559 static const AVCodecDefault defaults[] = {
00560     { "qmin",             "-1" },
00561     { "qmax",             "-1" },
00562     { "g",                "-1" },
00563     { "keyint_min",       "-1" },
00564     { NULL },
00565 };
00566 
00567 AVCodec ff_libvpx_encoder = {
00568     .name           = "libvpx",
00569     .type           = AVMEDIA_TYPE_VIDEO,
00570     .id             = CODEC_ID_VP8,
00571     .priv_data_size = sizeof(VP8Context),
00572     .init           = vp8_init,
00573     .encode         = vp8_encode,
00574     .close          = vp8_free,
00575     .capabilities   = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS,
00576     .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
00577     .long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"),
00578     .priv_class = &class,
00579     .defaults       = defaults,
00580 };