Ejemplo n.º 1
0
static int xvid_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
                             const AVFrame *picture, int *got_packet)
{
    int xerr, i, ret, user_packet = !!pkt->data;
    char *tmp;
    struct xvid_context *x = avctx->priv_data;
    AVFrame *p = &x->encoded_picture;
    int mb_width   = (avctx->width  + 15) / 16;
    int mb_height  = (avctx->height + 15) / 16;

    xvid_enc_frame_t xvid_enc_frame = { 0 };
    xvid_enc_stats_t xvid_enc_stats = { 0 };

    if ((ret = ff_alloc_packet2(avctx, pkt, mb_width*mb_height*MAX_MB_BYTES + FF_MIN_BUFFER_SIZE)) < 0)
        return ret;

    /* Start setting up the frame */
    xvid_enc_frame.version = XVID_VERSION;
    xvid_enc_stats.version = XVID_VERSION;
    *p = *picture;

    /* Let Xvid know where to put the frame. */
    xvid_enc_frame.bitstream = pkt->data;
    xvid_enc_frame.length    = pkt->size;

    /* Initialize input image fields */
    if( avctx->pix_fmt != AV_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 =
        picture->pict_type == AV_PICTURE_TYPE_I ? XVID_TYPE_IVOP :
        picture->pict_type == AV_PICTURE_TYPE_P ? XVID_TYPE_PVOP :
        picture->pict_type == AV_PICTURE_TYPE_B ? XVID_TYPE_BVOP :
                                          XVID_TYPE_AUTO;

    /* Pixel aspect ratio setting */
    if (avctx->sample_aspect_ratio.num < 0 || avctx->sample_aspect_ratio.num > 255 ||
        avctx->sample_aspect_ratio.den < 0 || avctx->sample_aspect_ratio.den > 255) {
        av_log(avctx, AV_LOG_WARNING,
               "Invalid pixel aspect ratio %i/%i, limit is 255/255 reducing\n",
               avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den);
        av_reduce(&avctx->sample_aspect_ratio.num, &avctx->sample_aspect_ratio.den,
                   avctx->sample_aspect_ratio.num,  avctx->sample_aspect_ratio.den, 255);
    }
    xvid_enc_frame.par = XVID_PAR_EXT;
    xvid_enc_frame.par_width  = avctx->sample_aspect_ratio.num;
    xvid_enc_frame.par_height = avctx->sample_aspect_ratio.den;

    /* 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 (xerr > 0) {
        *got_packet = 1;

        p->quality = xvid_enc_stats.quant * FF_QP2LAMBDA;
        if( xvid_enc_stats.type == XVID_TYPE_PVOP )
            p->pict_type = AV_PICTURE_TYPE_P;
        else if( xvid_enc_stats.type == XVID_TYPE_BVOP )
            p->pict_type = AV_PICTURE_TYPE_B;
        else if( xvid_enc_stats.type == XVID_TYPE_SVOP )
            p->pict_type = AV_PICTURE_TYPE_S;
        else
            p->pict_type = AV_PICTURE_TYPE_I;
        if( xvid_enc_frame.out_flags & XVID_KEYFRAME ) {
            p->key_frame = 1;
            pkt->flags |= AV_PKT_FLAG_KEY;
            if( x->quicktime_format )
                return xvid_strip_vol_header(avctx, pkt,
                    xvid_enc_stats.hlength, xerr);
         } else
            p->key_frame = 0;

        pkt->size = xerr;

        return 0;
    } else {
        if (!user_packet)
            av_free_packet(pkt);
        if (!xerr)
            return 0;
        av_log(avctx, AV_LOG_ERROR, "Xvid: Encoding Error Occurred: %i\n", xerr);
        return -1;
    }
}
Ejemplo n.º 2
0
/**
 * Encode a single frame.
 *
 * @param avctx AVCodecContext pointer to context
 * @param frame Pointer to encoded frame buffer
 * @param buf_size Size of encoded frame buffer
 * @param data Pointer to AVFrame of unencoded frame
 * @return Returns 0 on success, -1 on failure
 */
static int xvid_encode_frame(AVCodecContext *avctx,
                         unsigned char *frame, int buf_size, void *data) {
    int xerr, i;
    char *tmp;
    struct xvid_context *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 =
        picture->pict_type == FF_I_TYPE ? XVID_TYPE_IVOP :
        picture->pict_type == FF_P_TYPE ? XVID_TYPE_PVOP :
        picture->pict_type == FF_B_TYPE ? XVID_TYPE_BVOP :
                                          XVID_TYPE_AUTO;

    /* Pixel aspect ratio setting */
    if (avctx->sample_aspect_ratio.num < 1 || avctx->sample_aspect_ratio.num > 255 ||
        avctx->sample_aspect_ratio.den < 1 || avctx->sample_aspect_ratio.den > 255) {
        av_log(avctx, AV_LOG_ERROR, "Invalid pixel aspect ratio %i/%i\n",
               avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den);
        return -1;
    }
    xvid_enc_frame.par = XVID_PAR_EXT;
    xvid_enc_frame.par_width  = avctx->sample_aspect_ratio.num;
    xvid_enc_frame.par_height = avctx->sample_aspect_ratio.den;

    /* 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;
    }
}