⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xvidff.c

📁 tcpmp播放器的flv插件
💻 C
📖 第 1 页 / 共 2 页
字号:
int ff_xvid_encode_frame(AVCodecContext *avctx,                         unsigned char *frame, int buf_size, void *data) {    int xerr, i;    char *tmp;    xvid_context_t *x = avctx->priv_data;    AVFrame *picture = data;    AVFrame *p = &(x->encoded_picture);        xvid_enc_frame_t xvid_enc_frame;    xvid_enc_stats_t xvid_enc_stats;        /* Start setting up the frame */    memset(&xvid_enc_frame, 0, sizeof(xvid_enc_frame));    xvid_enc_frame.version = XVID_VERSION;    memset(&xvid_enc_stats, 0, sizeof(xvid_enc_stats));    xvid_enc_stats.version = XVID_VERSION;    *p = *picture;        /* Let XviD know where to put the frame. */    xvid_enc_frame.bitstream = frame;    xvid_enc_frame.length = buf_size;        /* Initialize input image fields */    if( avctx->pix_fmt != PIX_FMT_YUV420P ) {        av_log(avctx, AV_LOG_ERROR, "XviD: Color spaces other than 420p not supported\n");        return -1;    }        xvid_enc_frame.input.csp = XVID_CSP_PLANAR; /* YUV420P */    for( i = 0; i < 4; i++ ) {        xvid_enc_frame.input.plane[i] = picture->data[i];        xvid_enc_frame.input.stride[i] = picture->linesize[i];    }    /* Encoder Flags */    xvid_enc_frame.vop_flags = x->vop_flags;    xvid_enc_frame.vol_flags = x->vol_flags;    xvid_enc_frame.motion = x->me_flags;    xvid_enc_frame.type = XVID_TYPE_AUTO;        /* Quant Setting */    if( x->qscale ) xvid_enc_frame.quant = picture->quality / FF_QP2LAMBDA;    else xvid_enc_frame.quant = 0;        /* Matrices */    xvid_enc_frame.quant_intra_matrix = x->intra_matrix;    xvid_enc_frame.quant_inter_matrix = x->inter_matrix;    /* Encode */    xerr = xvid_encore(x->encoder_handle, XVID_ENC_ENCODE,         &xvid_enc_frame, &xvid_enc_stats);    /* Two-pass log buffer swapping */    avctx->stats_out = NULL;    if( x->twopassbuffer ) {        tmp = x->old_twopassbuffer;        x->old_twopassbuffer = x->twopassbuffer;        x->twopassbuffer = tmp;        x->twopassbuffer[0] = 0;        if( x->old_twopassbuffer[0] != 0 ) {            avctx->stats_out = x->old_twopassbuffer;        }    }                              if( 0 <= xerr ) {        p->quality = xvid_enc_stats.quant * FF_QP2LAMBDA;        if( xvid_enc_stats.type == XVID_TYPE_PVOP )            p->pict_type = FF_P_TYPE;        else if( xvid_enc_stats.type == XVID_TYPE_BVOP )            p->pict_type = FF_B_TYPE;        else if( xvid_enc_stats.type == XVID_TYPE_SVOP )            p->pict_type = FF_S_TYPE;        else            p->pict_type = FF_I_TYPE;        if( xvid_enc_frame.out_flags & XVID_KEYFRAME ) {            p->key_frame = 1;            if( x->quicktime_format )                return xvid_strip_vol_header(avctx, frame,                     xvid_enc_stats.hlength, xerr);         } else             p->key_frame = 0;        return xerr;    } else {        av_log(avctx, AV_LOG_ERROR, "XviD: Encoding Error Occurred: %i\n", xerr);        return -1;    }}/**  * Destroys the private context for the encoder. * All buffers are freed, and the XviD encoder context is destroyed. * * @param avctx AVCodecContext pointer to context * @return Returns 0, success guaranteed */int ff_xvid_encode_close(AVCodecContext *avctx) {    xvid_context_t *x = avctx->priv_data;        xvid_encore(x->encoder_handle, XVID_ENC_DESTROY, NULL, NULL);    if( avctx->extradata != NULL )        av_free(avctx->extradata);    if( x->twopassbuffer != NULL ) {        av_free(x->twopassbuffer);        av_free(x->old_twopassbuffer);    }    if( x->twopassfile != NULL )        av_free(x->twopassfile);    if( x->intra_matrix != NULL )        av_free(x->intra_matrix);    if( x->inter_matrix != NULL )        av_free(x->inter_matrix);    return 0;}/**  * Routine to create a global VO/VOL header for MP4 container. * What we do here is extract the header from the XviD bitstream * as it is encoded. We also strip the repeated headers from the * bitstream when a global header is requested for MPEG-4 ISO * compliance. * * @param avctx AVCodecContext pointer to context * @param frame Pointer to encoded frame data * @param header_len Length of header to search * @param frame_len Length of encoded frame data * @return Returns new length of frame data */int xvid_strip_vol_header(AVCodecContext *avctx,                   unsigned char *frame,                   unsigned int header_len,                  unsigned int frame_len) {    int vo_len = 0, i;    for( i = 0; i < header_len - 3; i++ ) {        if( frame[i] == 0x00 &&             frame[i+1] == 0x00 &&            frame[i+2] == 0x01 &&            frame[i+3] == 0xB6 ) {            vo_len = i;            break;        }     }        if( vo_len > 0 ) {        /* We need to store the header, so extract it */        if( avctx->extradata == NULL ) {            avctx->extradata = av_malloc(vo_len);            memcpy(avctx->extradata, frame, vo_len);            avctx->extradata_size = vo_len;        }        /* Less dangerous now, memmove properly copies the two           chunks of overlapping data */        memmove(frame, &(frame[vo_len]), frame_len - vo_len);        return frame_len - vo_len;    } else        return frame_len;}/** * Routine to correct a possibly erroneous framerate being fed to us. * XviD currently chokes on framerates where the ticks per frame is  * extremely large. This function works to correct problems in this area * by estimating a new framerate and taking the simpler fraction of  * the two presented. * * @param avctx Context that contains the framerate to correct. */void xvid_correct_framerate(AVCodecContext *avctx) {    int frate, fbase;    int est_frate, est_fbase;    int gcd;    float est_fps, fps;        frate = avctx->time_base.den;    fbase = avctx->time_base.num;        gcd = ff_gcd(frate, fbase);    if( gcd > 1 ) {        frate /= gcd;        fbase /= gcd;    }        if( frate <= 65000 && fbase <= 65000 ) {        avctx->time_base.den = frate;        avctx->time_base.num = fbase;        return;    }        fps = (float)frate / (float)fbase;    est_fps = roundf(fps * 1000.0) / 1000.0;    est_frate = (int)est_fps;    if( est_fps > (int)est_fps ) {        est_frate = (est_frate + 1) * 1000;        est_fbase = (int)roundf((float)est_frate / est_fps);            } else        est_fbase = 1;    gcd = ff_gcd(est_frate, est_fbase);    if( gcd > 1 ) {        est_frate /= gcd;        est_fbase /= gcd;    }            if( fbase > est_fbase ) {        avctx->time_base.den = est_frate;        avctx->time_base.num = est_fbase;        av_log(avctx, AV_LOG_DEBUG,             "XviD: framerate re-estimated: %.2f, %.3f%% correction\n",            est_fps, (((est_fps - fps)/fps) * 100.0));    } else {        avctx->time_base.den = frate;        avctx->time_base.num = fbase;    }}/* * XviD 2-Pass Kludge Section * * XviD's default 2-pass doesn't allow us to create data as we need to, so * this section spends time replacing the first pass plugin so we can write * statistic information as libavcodec requests in. We have another kludge * that allows us to pass data to the second pass in XviD without a custom * rate-control plugin. *//** * Initializes the two-pass plugin and context. * * @param param Input construction parameter structure * @param handle Private context handle * @return Returns XVID_ERR_xxxx on failure, or 0 on success. */static int xvid_ff_2pass_create(xvid_plg_create_t * param,                                void ** handle) {    xvid_ff_pass1_t *x = (xvid_ff_pass1_t *)param->param;    char *log = x->context->twopassbuffer;        /* Do a quick bounds check */    if( log == NULL )        return XVID_ERR_FAIL;        /* We use snprintf() */    /* This is because we can safely prevent a buffer overflow */    log[0] = 0;    snprintf(log, BUFFER_REMAINING(log),        "# ffmpeg 2-pass log file, using xvid codec\n");    snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log),        "# Do not modify. libxvidcore version: %d.%d.%d\n\n",        XVID_VERSION_MAJOR(XVID_VERSION),        XVID_VERSION_MINOR(XVID_VERSION),        XVID_VERSION_PATCH(XVID_VERSION));        *handle = x->context;    return 0;                                }/** * Destroys the two-pass plugin context. * * @param ref Context pointer for the plugin * @param param Destrooy context * @return Returns 0, success guaranteed */static int xvid_ff_2pass_destroy(xvid_context_t *ref,                                 xvid_plg_destroy_t *param) {    /* Currently cannot think of anything to do on destruction */    /* Still, the framework should be here for reference/use */    if( ref->twopassbuffer != NULL )        ref->twopassbuffer[0] = 0;    return 0;}/** * Enables fast encode mode during the first pass. * * @param ref Context pointer for the plugin * @param param Frame data * @return Returns 0, success guaranteed */static int xvid_ff_2pass_before(xvid_context_t *ref,                                xvid_plg_data_t *param) {    int motion_remove;    int motion_replacements;                                int vop_remove;                     /* Nothing to do here, result is changed too much */      if( param->zone && param->zone->mode == XVID_ZONE_QUANT )        return 0;                     /* We can implement a 'turbo' first pass mode here */          param->quant = 2;              /* Init values */    motion_remove = ~XVID_ME_CHROMA_PVOP &                    ~XVID_ME_CHROMA_BVOP &                    ~XVID_ME_EXTSEARCH16 &                    ~XVID_ME_ADVANCEDDIAMOND16;    motion_replacements = XVID_ME_FAST_MODEINTERPOLATE |                          XVID_ME_SKIP_DELTASEARCH |                          XVID_ME_FASTREFINE16 |                          XVID_ME_BFRAME_EARLYSTOP;    vop_remove = ~XVID_VOP_MODEDECISION_RD &                 ~XVID_VOP_FAST_MODEDECISION_RD &                 ~XVID_VOP_TRELLISQUANT &                 ~XVID_VOP_INTER4V &                 ~XVID_VOP_HQACPRED;                     param->vol_flags &= ~XVID_VOL_GMC;    param->vop_flags &= vop_remove;    param->motion_flags &= motion_remove;    param->motion_flags |= motion_replacements;                              return 0;                                }/** * Captures statistic data and writes it during first pass. * * @param ref Context pointer for the plugin * @param param Statistic data * @return Returns XVID_ERR_xxxx on failure, or 0 on success */static int xvid_ff_2pass_after(xvid_context_t *ref,                                xvid_plg_data_t *param) {    char *log = ref->twopassbuffer;    char *frame_types = " ipbs";    char frame_type;        /* Quick bounds check */    if( log == NULL )        return XVID_ERR_FAIL;        /* Convert the type given to us into a character */    if( param->type < 5 && param->type > 0 ) {        frame_type = frame_types[param->type];    } else {        return XVID_ERR_FAIL;    }        snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log),        "%c %d %d %d %d %d %d\n",        frame_type, param->stats.quant, param->stats.kblks, param->stats.mblks,         param->stats.ublks, param->stats.length, param->stats.hlength);        return 0;}/** * Dispatch function for our custom plugin. * This handles the dispatch for the XviD plugin. It passes data * on to other functions for actual processing. * * @param ref Context pointer for the plugin * @param cmd The task given for us to complete * @param p1 First parameter (varies) * @param p2 Second parameter (varies) * @return Returns XVID_ERR_xxxx on failure, or 0 on success */int xvid_ff_2pass(void *ref, int cmd, void *p1, void *p2) {    switch( cmd ) {        case XVID_PLG_INFO:        case XVID_PLG_FRAME:            return 0;        case XVID_PLG_BEFORE:            return xvid_ff_2pass_before(ref, p1);                    case XVID_PLG_CREATE:            return xvid_ff_2pass_create(p1, p2);                case XVID_PLG_AFTER:            return xvid_ff_2pass_after(ref, p1);                    case XVID_PLG_DESTROY:            return xvid_ff_2pass_destroy(ref, p1);                            default:            return XVID_ERR_FAIL;    }}/** * XviD codec definition for libavcodec. */AVCodec xvid_encoder = {    "xvid",    CODEC_TYPE_VIDEO,    CODEC_ID_XVID,    sizeof(xvid_context_t),    ff_xvid_encode_init,    ff_xvid_encode_frame,    ff_xvid_encode_close};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -