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