• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavcodec/libxavs.c

Go to the documentation of this file.
00001 /*
00002  * AVS encoding using the xavs library
00003  * Copyright (C) 2010 Amanda, Y.N. Wu <amanda11192003@gmail.com>
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 #include <math.h>
00026 #include <stdint.h>
00027 #include <xavs.h>
00028 #include "avcodec.h"
00029 
00030 #define END_OF_STREAM 0x001
00031 
00032 #define XAVS_PART_I8X8 0x002 /* Analyze i8x8 (requires 8x8 transform) */
00033 #define XAVS_PART_P8X8 0x010 /* Analyze p16x8, p8x16 and p8x8 */
00034 #define XAVS_PART_B8X8 0x100 /* Analyze b16x8, b*/
00035 
00036 typedef struct XavsContext {
00037     xavs_param_t    params;
00038     xavs_t         *enc;
00039     xavs_picture_t  pic;
00040     uint8_t        *sei;
00041     int             sei_size;
00042     AVFrame         out_pic;
00043     int             end_of_stream;
00044 } XavsContext;
00045 
00046 static void XAVS_log(void *p, int level, const char *fmt, va_list args)
00047 {
00048     static const int level_map[] = {
00049         [XAVS_LOG_ERROR]   = AV_LOG_ERROR,
00050         [XAVS_LOG_WARNING] = AV_LOG_WARNING,
00051         [XAVS_LOG_INFO]    = AV_LOG_INFO,
00052         [XAVS_LOG_DEBUG]   = AV_LOG_DEBUG
00053     };
00054 
00055     if (level < 0 || level > XAVS_LOG_DEBUG)
00056         return;
00057 
00058     av_vlog(p, level_map[level], fmt, args);
00059 }
00060 
00061 static int encode_nals(AVCodecContext *ctx, uint8_t *buf,
00062                        int size, xavs_nal_t *nals,
00063                        int nnal, int skip_sei)
00064 {
00065     XavsContext *x4 = ctx->priv_data;
00066     uint8_t *p = buf;
00067     int i, s;
00068 
00069     /* Write the SEI as part of the first frame. */
00070     if (x4->sei_size > 0 && nnal > 0) {
00071         memcpy(p, x4->sei, x4->sei_size);
00072         p += x4->sei_size;
00073         x4->sei_size = 0;
00074     }
00075 
00076     for (i = 0; i < nnal; i++) {
00077         /* Don't put the SEI in extradata. */
00078         if (skip_sei && nals[i].i_type == NAL_SEI) {
00079             x4->sei = av_malloc( 5 + nals[i].i_payload * 4 / 3 );
00080             if (xavs_nal_encode(x4->sei, &x4->sei_size, 1, nals + i) < 0)
00081                 return -1;
00082 
00083             continue;
00084         }
00085         s = xavs_nal_encode(p, &size, 1, nals + i);
00086         if (s < 0)
00087             return -1;
00088         p += s;
00089     }
00090 
00091     return p - buf;
00092 }
00093 
00094 static int XAVS_frame(AVCodecContext *ctx, uint8_t *buf,
00095                       int bufsize, void *data)
00096 {
00097     XavsContext *x4 = ctx->priv_data;
00098     AVFrame *frame = data;
00099     xavs_nal_t *nal;
00100     int nnal, i;
00101     xavs_picture_t pic_out;
00102 
00103     x4->pic.img.i_csp   = XAVS_CSP_I420;
00104     x4->pic.img.i_plane = 3;
00105 
00106     if (frame) {
00107        for (i = 0; i < 3; i++) {
00108             x4->pic.img.plane[i] = frame->data[i];
00109             x4->pic.img.i_stride[i] = frame->linesize[i];
00110        }
00111 
00112         x4->pic.i_pts  = frame->pts;
00113         x4->pic.i_type = XAVS_TYPE_AUTO;
00114     }
00115 
00116     if (xavs_encoder_encode(x4->enc, &nal, &nnal,
00117                             frame? &x4->pic: NULL, &pic_out) < 0)
00118     return -1;
00119 
00120     bufsize = encode_nals(ctx, buf, bufsize, nal, nnal, 0);
00121 
00122     if (bufsize < 0)
00123         return -1;
00124 
00125     if (!bufsize && !frame && !(x4->end_of_stream)){
00126         buf[bufsize]   = 0x0;
00127         buf[bufsize+1] = 0x0;
00128         buf[bufsize+2] = 0x01;
00129         buf[bufsize+3] = 0xb1;
00130         bufsize += 4;
00131         x4->end_of_stream = END_OF_STREAM;
00132         return bufsize;
00133     }
00134     /* FIXME: libxavs now provides DTS */
00135     /* but AVFrame doesn't have a field for it. */
00136     x4->out_pic.pts = pic_out.i_pts;
00137 
00138     switch (pic_out.i_type) {
00139     case XAVS_TYPE_IDR:
00140     case XAVS_TYPE_I:
00141         x4->out_pic.pict_type = AV_PICTURE_TYPE_I;
00142         break;
00143     case XAVS_TYPE_P:
00144         x4->out_pic.pict_type = AV_PICTURE_TYPE_P;
00145         break;
00146     case XAVS_TYPE_B:
00147     case XAVS_TYPE_BREF:
00148         x4->out_pic.pict_type = AV_PICTURE_TYPE_B;
00149         break;
00150     }
00151 
00152     /* There is no IDR frame in AVS JiZhun */
00153     /* Sequence header is used as a flag */
00154     x4->out_pic.key_frame = pic_out.i_type == XAVS_TYPE_I;
00155 
00156     x4->out_pic.quality   = (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA;
00157 
00158     return bufsize;
00159 }
00160 
00161 static av_cold int XAVS_close(AVCodecContext *avctx)
00162 {
00163     XavsContext *x4 = avctx->priv_data;
00164 
00165     av_freep(&avctx->extradata);
00166     av_free(x4->sei);
00167 
00168     if (x4->enc)
00169         xavs_encoder_close(x4->enc);
00170 
00171     return 0;
00172 }
00173 
00174 static av_cold int XAVS_init(AVCodecContext *avctx)
00175 {
00176     XavsContext *x4 = avctx->priv_data;
00177 
00178     x4->sei_size = 0;
00179     xavs_param_default(&x4->params);
00180 
00181     x4->params.pf_log               = XAVS_log;
00182     x4->params.p_log_private        = avctx;
00183     x4->params.i_keyint_max         = avctx->gop_size;
00184     x4->params.rc.i_bitrate         = avctx->bit_rate       / 1000;
00185     x4->params.rc.i_vbv_buffer_size = avctx->rc_buffer_size / 1000;
00186     x4->params.rc.i_vbv_max_bitrate = avctx->rc_max_rate    / 1000;
00187     x4->params.rc.b_stat_write      = avctx->flags & CODEC_FLAG_PASS1;
00188     if (avctx->flags & CODEC_FLAG_PASS2) {
00189         x4->params.rc.b_stat_read = 1;
00190     } else {
00191         if (avctx->crf) {
00192             x4->params.rc.i_rc_method   = XAVS_RC_CRF;
00193             x4->params.rc.f_rf_constant = avctx->crf;
00194         } else if (avctx->cqp > -1) {
00195             x4->params.rc.i_rc_method   = XAVS_RC_CQP;
00196             x4->params.rc.i_qp_constant = avctx->cqp;
00197         }
00198     }
00199 
00200     /* if neither crf nor cqp modes are selected we have to enable the RC */
00201     /* we do it this way because we cannot check if the bitrate has been set */
00202     if (!(avctx->crf || (avctx->cqp > -1)))
00203         x4->params.rc.i_rc_method = XAVS_RC_ABR;
00204 
00205     x4->params.i_bframe          = avctx->max_b_frames;
00206     /* cabac is not included in AVS JiZhun Profile */
00207     x4->params.b_cabac           = 0;
00208 
00209     x4->params.i_bframe_adaptive = avctx->b_frame_strategy;
00210     x4->params.i_bframe_bias     = avctx->bframebias;
00211 
00212     avctx->has_b_frames          = !!avctx->max_b_frames;
00213 
00214     /* AVS doesn't allow B picture as reference */
00215     /* The max allowed reference frame number of B is 2 */
00216     x4->params.i_keyint_min      = avctx->keyint_min;
00217     if (x4->params.i_keyint_min > x4->params.i_keyint_max)
00218         x4->params.i_keyint_min = x4->params.i_keyint_max;
00219 
00220     x4->params.i_scenecut_threshold        = avctx->scenechange_threshold;
00221 
00222    // x4->params.b_deblocking_filter       = avctx->flags & CODEC_FLAG_LOOP_FILTER;
00223     x4->params.i_deblocking_filter_alphac0 = avctx->deblockalpha;
00224     x4->params.i_deblocking_filter_beta    = avctx->deblockbeta;
00225 
00226     x4->params.rc.i_qp_min                 = avctx->qmin;
00227     x4->params.rc.i_qp_max                 = avctx->qmax;
00228     x4->params.rc.i_qp_step                = avctx->max_qdiff;
00229 
00230     x4->params.rc.f_qcompress       = avctx->qcompress; /* 0.0 => cbr, 1.0 => constant qp */
00231     x4->params.rc.f_qblur           = avctx->qblur;     /* temporally blur quants */
00232     x4->params.rc.f_complexity_blur = avctx->complexityblur;
00233 
00234     x4->params.i_frame_reference    = avctx->refs;
00235 
00236     x4->params.i_width              = avctx->width;
00237     x4->params.i_height             = avctx->height;
00238     x4->params.vui.i_sar_width      = avctx->sample_aspect_ratio.num;
00239     x4->params.vui.i_sar_height     = avctx->sample_aspect_ratio.den;
00240     /* This is only used for counting the fps */
00241     x4->params.i_fps_num            = avctx->time_base.den;
00242     x4->params.i_fps_den            = avctx->time_base.num;
00243     x4->params.analyse.inter        = XAVS_ANALYSE_I8x8 |XAVS_ANALYSE_PSUB16x16| XAVS_ANALYSE_BSUB16x16;
00244     if (avctx->partitions) {
00245         if (avctx->partitions & XAVS_PART_I8X8)
00246             x4->params.analyse.inter |= XAVS_ANALYSE_I8x8;
00247 
00248         if (avctx->partitions & XAVS_PART_P8X8)
00249             x4->params.analyse.inter |= XAVS_ANALYSE_PSUB16x16;
00250 
00251         if (avctx->partitions & XAVS_PART_B8X8)
00252             x4->params.analyse.inter |= XAVS_ANALYSE_BSUB16x16;
00253     }
00254 
00255     x4->params.analyse.i_direct_mv_pred  = avctx->directpred;
00256 
00257     x4->params.analyse.b_weighted_bipred = avctx->flags2 & CODEC_FLAG2_WPRED;
00258 
00259     switch (avctx->me_method) {
00260          case  ME_EPZS:
00261                x4->params.analyse.i_me_method = XAVS_ME_DIA;
00262                break;
00263          case  ME_HEX:
00264                x4->params.analyse.i_me_method = XAVS_ME_HEX;
00265                break;
00266          case  ME_UMH:
00267                x4->params.analyse.i_me_method = XAVS_ME_UMH;
00268                break;
00269          case  ME_FULL:
00270                x4->params.analyse.i_me_method = XAVS_ME_ESA;
00271                break;
00272          case  ME_TESA:
00273                x4->params.analyse.i_me_method = XAVS_ME_TESA;
00274                break;
00275          default:
00276                x4->params.analyse.i_me_method = XAVS_ME_HEX;
00277     }
00278 
00279     x4->params.analyse.i_me_range = avctx->me_range;
00280     x4->params.analyse.i_subpel_refine    = avctx->me_subpel_quality;
00281 
00282     x4->params.analyse.b_mixed_references = avctx->flags2 & CODEC_FLAG2_MIXED_REFS;
00283     x4->params.analyse.b_chroma_me        = avctx->me_cmp & FF_CMP_CHROMA;
00284     /* AVS P2 only enables 8x8 transform */
00285     x4->params.analyse.b_transform_8x8    = 1; //avctx->flags2 & CODEC_FLAG2_8X8DCT;
00286     x4->params.analyse.b_fast_pskip       = avctx->flags2 & CODEC_FLAG2_FASTPSKIP;
00287 
00288     x4->params.analyse.i_trellis          = avctx->trellis;
00289     x4->params.analyse.i_noise_reduction  = avctx->noise_reduction;
00290 
00291     if (avctx->level > 0)
00292         x4->params.i_level_idc = avctx->level;
00293 
00294     x4->params.rc.f_rate_tolerance =
00295         (float)avctx->bit_rate_tolerance/avctx->bit_rate;
00296 
00297     if ((avctx->rc_buffer_size) &&
00298         (avctx->rc_initial_buffer_occupancy <= avctx->rc_buffer_size)) {
00299         x4->params.rc.f_vbv_buffer_init =
00300             (float)avctx->rc_initial_buffer_occupancy / avctx->rc_buffer_size;
00301     } else
00302         x4->params.rc.f_vbv_buffer_init = 0.9;
00303 
00304     /* TAG:do we have MB tree RC method */
00305     /* what is the RC method we are now using? Default NO */
00306     x4->params.rc.b_mb_tree               = !!(avctx->flags2 & CODEC_FLAG2_MBTREE);
00307     x4->params.rc.f_ip_factor             = 1 / fabs(avctx->i_quant_factor);
00308     x4->params.rc.f_pb_factor             = avctx->b_quant_factor;
00309     x4->params.analyse.i_chroma_qp_offset = avctx->chromaoffset;
00310 
00311     x4->params.analyse.b_psnr = avctx->flags & CODEC_FLAG_PSNR;
00312     x4->params.i_log_level    = XAVS_LOG_DEBUG;
00313     x4->params.b_aud          = avctx->flags2 & CODEC_FLAG2_AUD;
00314     x4->params.i_threads      = avctx->thread_count;
00315     x4->params.b_interlaced   = avctx->flags & CODEC_FLAG_INTERLACED_DCT;
00316 
00317     if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER)
00318         x4->params.b_repeat_headers = 0;
00319 
00320     x4->enc = xavs_encoder_open(&x4->params);
00321     if (!x4->enc)
00322         return -1;
00323 
00324     avctx->coded_frame = &x4->out_pic;
00325     /* TAG: Do we have GLOBAL HEADER in AVS */
00326     /* We Have PPS and SPS in AVS */
00327     if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) {
00328         xavs_nal_t *nal;
00329         int nnal, s;
00330 
00331         s = xavs_encoder_headers(x4->enc, &nal, &nnal);
00332 
00333         avctx->extradata      = av_malloc(s);
00334         avctx->extradata_size = encode_nals(avctx, avctx->extradata, s, nal, nnal, 1);
00335     }
00336     return 0;
00337 }
00338 
00339 AVCodec ff_libxavs_encoder = {
00340     .name           = "libxavs",
00341     .type           = AVMEDIA_TYPE_VIDEO,
00342     .id             = CODEC_ID_CAVS,
00343     .priv_data_size = sizeof(XavsContext),
00344     .init           = XAVS_init,
00345     .encode         = XAVS_frame,
00346     .close          = XAVS_close,
00347     .capabilities   = CODEC_CAP_DELAY,
00348     .pix_fmts       = (const enum PixelFormat[]) { PIX_FMT_YUV420P, PIX_FMT_NONE },
00349     .long_name      = NULL_IF_CONFIG_SMALL("libxavs - the Chinese Audio Video Standard Encoder"),
00350 };
00351 

Generated on Wed Apr 11 2012 07:31:33 for FFmpeg by  doxygen 1.7.1