#include "flv.h"
#include "mpeg4video.h"
#include "internal.h"
+#include "bytestream.h"
#include <limits.h>
#include "sp5x.h"
static uint8_t default_mv_penalty[MAX_FCODE + 1][MAX_MV * 2 + 1];
static uint8_t default_fcode_tab[MAX_MV * 2 + 1];
+const AVOption ff_mpv_generic_options[] = {
+ FF_MPV_COMMON_OPTS
+ { NULL },
+};
+
void ff_convert_matrix(DSPContext *dsp, int (*qmat)[64],
uint16_t (*qmat16)[2][64],
const uint16_t *quant_matrix,
for (qscale = qmin; qscale <= qmax; qscale++) {
int i;
if (dsp->fdct == ff_jpeg_fdct_islow_8 ||
- dsp->fdct == ff_jpeg_fdct_islow_10
-#ifdef FAAN_POSTSCALE
- || dsp->fdct == ff_faandct
-#endif
- ) {
+ dsp->fdct == ff_jpeg_fdct_islow_10 ||
+ dsp->fdct == ff_faandct) {
for (i = 0; i < 64; i++) {
const int j = dsp->idct_permutation[i];
/* 16 <= qscale * quant_matrix[i] <= 7905
qmat[qscale][i] = (int)((UINT64_C(1) << QMAT_SHIFT) /
(qscale * quant_matrix[j]));
}
- } else if (dsp->fdct == ff_fdct_ifast
-#ifndef FAAN_POSTSCALE
- || dsp->fdct == ff_faandct
-#endif
- ) {
+ } else if (dsp->fdct == ff_fdct_ifast) {
for (i = 0; i < 64; i++) {
const int j = dsp->idct_permutation[i];
/* 16 <= qscale * quant_matrix[i] <= 7905
for (i = intra; i < 64; i++) {
int64_t max = 8191;
- if (dsp->fdct == ff_fdct_ifast
-#ifndef FAAN_POSTSCALE
- || dsp->fdct == ff_faandct
-#endif
- ) {
+ if (dsp->fdct == ff_fdct_ifast) {
max = (8191LL * ff_aanscales[i]) >> 14;
}
while (((max * qmat[qscale][i]) >> shift) > INT_MAX) {
s->flags2 = avctx->flags2;
s->max_b_frames = avctx->max_b_frames;
s->codec_id = avctx->codec->id;
- s->luma_elim_threshold = avctx->luma_elim_threshold;
- s->chroma_elim_threshold = avctx->chroma_elim_threshold;
+#if FF_API_MPV_GLOBAL_OPTS
+ if (avctx->luma_elim_threshold)
+ s->luma_elim_threshold = avctx->luma_elim_threshold;
+ if (avctx->chroma_elim_threshold)
+ s->chroma_elim_threshold = avctx->chroma_elim_threshold;
+#endif
s->strict_std_compliance = avctx->strict_std_compliance;
s->quarter_sample = (avctx->flags & CODEC_FLAG_QPEL) != 0;
s->mpeg_quant = avctx->mpeg_quant;
/* Fixed QSCALE */
s->fixed_qscale = !!(avctx->flags & CODEC_FLAG_QSCALE);
+#if FF_API_MPV_GLOBAL_OPTS
+ if (s->flags & CODEC_FLAG_QP_RD)
+ s->mpv_flags |= FF_MPV_FLAG_QP_RD;
+#endif
+
s->adaptive_quant = (s->avctx->lumi_masking ||
s->avctx->dark_masking ||
s->avctx->temporal_cplx_masking ||
s->avctx->spatial_cplx_masking ||
s->avctx->p_masking ||
s->avctx->border_masking ||
- (s->flags & CODEC_FLAG_QP_RD)) &&
+ (s->mpv_flags & FF_MPV_FLAG_QP_RD)) &&
!s->fixed_qscale;
s->loop_filter = !!(s->flags & CODEC_FLAG_LOOP_FILTER);
if ((!avctx->rc_max_rate) != (!avctx->rc_buffer_size)) {
av_log(avctx, AV_LOG_ERROR, "Either both buffer size and max rate or neither must be specified\n");
- return -1;
+ if (avctx->rc_max_rate && !avctx->rc_buffer_size)
+ return -1;
}
if (avctx->rc_min_rate && avctx->rc_max_rate != avctx->rc_min_rate) {
return -1;
}
- if ((s->flags & CODEC_FLAG_CBP_RD) && !avctx->trellis) {
+#if FF_API_MPV_GLOBAL_OPTS
+ if (s->flags & CODEC_FLAG_CBP_RD)
+ s->mpv_flags |= FF_MPV_FLAG_CBP_RD;
+#endif
+
+ if ((s->mpv_flags & FF_MPV_FLAG_CBP_RD) && !avctx->trellis) {
av_log(avctx, AV_LOG_ERROR, "CBP RD needs trellis quant\n");
return -1;
}
- if ((s->flags & CODEC_FLAG_QP_RD) &&
+ if ((s->mpv_flags & FF_MPV_FLAG_QP_RD) &&
s->avctx->mb_decision != FF_MB_DECISION_RD) {
av_log(avctx, AV_LOG_ERROR, "QP RD needs mbd=2\n");
return -1;
}
s->time_increment_bits = av_log2(s->avctx->time_base.den - 1) + 1;
+#if FF_API_MPV_GLOBAL_OPTS
+ if (avctx->flags2 & CODEC_FLAG2_SKIP_RD)
+ s->mpv_flags |= FF_MPV_FLAG_SKIP_RD;
+ if (avctx->flags2 & CODEC_FLAG2_STRICT_GOP)
+ s->mpv_flags |= FF_MPV_FLAG_STRICT_GOP;
+ if (avctx->quantizer_noise_shaping)
+ s->quantizer_noise_shaping = avctx->quantizer_noise_shaping;
+#endif
+
switch (avctx->codec->id) {
case CODEC_ID_MPEG1VIDEO:
s->out_format = FMT_MPEG1;
if (i < 0)
return i;
- pic = (AVFrame *) &s->picture[i];
+ pic = &s->picture[i].f;
pic->reference = 3;
for (i = 0; i < 4; i++) {
if (i < 0)
return i;
- pic = (AVFrame *) &s->picture[i];
+ pic = &s->picture[i].f;
pic->reference = 3;
if (ff_alloc_picture(s, (Picture *) pic, 0) < 0) {
s->input_picture[0]->f.type == FF_BUFFER_TYPE_INTERNAL);
s->avctx->release_buffer(s->avctx,
- (AVFrame *) s->input_picture[0]);
+ &s->input_picture[0]->f);
}
emms_c();
}
if (s->picture_in_gop_number + b_frames >= s->gop_size) {
- if ((s->flags2 & CODEC_FLAG2_STRICT_GOP) &&
+ if ((s->mpv_flags & FF_MPV_FLAG_STRICT_GOP) &&
s->gop_size > s->picture_in_gop_number) {
b_frames = s->gop_size - s->picture_in_gop_number - 1;
} else {
/* mark us unused / free shared pic */
if (s->reordered_input_picture[0]->f.type == FF_BUFFER_TYPE_INTERNAL)
s->avctx->release_buffer(s->avctx,
- (AVFrame *) s->reordered_input_picture[0]);
+ &s->reordered_input_picture[0]->f);
for (i = 0; i < 4; i++)
s->reordered_input_picture[0]->f.data[i] = NULL;
s->reordered_input_picture[0]->f.type = 0;
- copy_picture_attributes(s, (AVFrame *) pic,
- (AVFrame *) s->reordered_input_picture[0]);
+ copy_picture_attributes(s, &pic->f,
+ &s->reordered_input_picture[0]->f);
s->current_picture_ptr = pic;
} else {
}
int ff_MPV_encode_picture(AVCodecContext *avctx, AVPacket *pkt,
- const AVFrame *pic_arg, int *got_packet)
+ AVFrame *pic_arg, int *got_packet)
{
MpegEncContext *s = avctx->priv_data;
int i, stuffing_count, ret;
/* output? */
if (s->new_picture.f.data[0]) {
- if (!pkt->data &&
- (ret = ff_alloc_packet(pkt, s->mb_width*s->mb_height*(MAX_MB_BYTES+100)+10000)) < 0)
+ if ((ret = ff_alloc_packet2(avctx, pkt, s->mb_width*s->mb_height*(MAX_MB_BYTES+100)+10000)) < 0)
return ret;
+ if (s->mb_info) {
+ s->mb_info_ptr = av_packet_new_side_data(pkt,
+ AV_PKT_DATA_H263_MB_INFO,
+ s->mb_width*s->mb_height*12);
+ s->prev_mb_info = s->last_mb_info = s->mb_info_size = 0;
+ }
for (i = 0; i < context_count; i++) {
int start_y = s->thread_context[i]->start_mb_y;
avctx->frame_bits = s->frame_bits;
pkt->pts = s->current_picture.f.pts;
- if (!s->low_delay) {
+ if (!s->low_delay && s->pict_type != AV_PICTURE_TYPE_B) {
if (!s->current_picture.f.coded_picture_number)
pkt->dts = pkt->pts - s->dts_delta;
else
pkt->dts = s->reordered_pts;
- s->reordered_pts = s->input_picture[0]->f.pts;
+ s->reordered_pts = pkt->pts;
} else
pkt->dts = pkt->pts;
if (s->current_picture.f.key_frame)
pkt->flags |= AV_PKT_FLAG_KEY;
+ if (s->mb_info)
+ av_packet_shrink_side_data(pkt, AV_PKT_DATA_H263_MB_INFO, s->mb_info_size);
} else {
assert((put_bits_ptr(&s->pb) == s->pb.buf));
s->frame_bits = 0;
s->lambda = s->lambda_table[mb_xy];
update_qscale(s);
- if (!(s->flags & CODEC_FLAG_QP_RD)) {
+ if (!(s->mpv_flags & FF_MPV_FLAG_QP_RD)) {
s->qscale = s->current_picture_ptr->f.qscale_table[mb_xy];
s->dquant = s->qscale - last_qp;
}
}
ff_set_qscale(s, last_qp + s->dquant);
- } else if (s->flags & CODEC_FLAG_QP_RD)
+ } else if (s->mpv_flags & FF_MPV_FLAG_QP_RD)
ff_set_qscale(s, s->qscale + s->dquant);
wrap_y = s->linesize;
}
}
- if (s->avctx->quantizer_noise_shaping) {
+ if (s->quantizer_noise_shaping) {
if (!skip_dct[0])
get_visual_weight(weight[0], ptr_y , wrap_y);
if (!skip_dct[1])
} else
s->block_last_index[i] = -1;
}
- if (s->avctx->quantizer_noise_shaping) {
+ if (s->quantizer_noise_shaping) {
for (i = 0; i < mb_block_count; i++) {
if (!skip_dct[i]) {
s->block_last_index[i] =
for (i = 4; i < mb_block_count; i++)
dct_single_coeff_elimination(s, i, s->chroma_elim_threshold);
- if (s->flags & CODEC_FLAG_CBP_RD) {
+ if (s->mpv_flags & FF_MPV_FLAG_CBP_RD) {
for (i = 0; i < mb_block_count; i++) {
if (s->block_last_index[i] == -1)
s->coded_score[i] = INT_MAX / 256;
s->misc_bits+= get_bits_diff(s);
}
+static void write_mb_info(MpegEncContext *s)
+{
+ uint8_t *ptr = s->mb_info_ptr + s->mb_info_size - 12;
+ int offset = put_bits_count(&s->pb);
+ int mba = s->mb_x + s->mb_width * (s->mb_y % s->gob_index);
+ int gobn = s->mb_y / s->gob_index;
+ int pred_x, pred_y;
+ if (CONFIG_H263_ENCODER)
+ ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y);
+ bytestream_put_le32(&ptr, offset);
+ bytestream_put_byte(&ptr, s->qscale);
+ bytestream_put_byte(&ptr, gobn);
+ bytestream_put_le16(&ptr, mba);
+ bytestream_put_byte(&ptr, pred_x); /* hmv1 */
+ bytestream_put_byte(&ptr, pred_y); /* vmv1 */
+ /* 4MV not implemented */
+ bytestream_put_byte(&ptr, 0); /* hmv2 */
+ bytestream_put_byte(&ptr, 0); /* vmv2 */
+}
+
+static void update_mb_info(MpegEncContext *s, int startcode)
+{
+ if (!s->mb_info)
+ return;
+ if (put_bits_count(&s->pb) - s->prev_mb_info*8 >= s->mb_info*8) {
+ s->mb_info_size += 12;
+ s->prev_mb_info = s->last_mb_info;
+ }
+ if (startcode) {
+ s->prev_mb_info = put_bits_count(&s->pb)/8;
+ /* This might have incremented mb_info_size above, and we return without
+ * actually writing any info into that slot yet. But in that case,
+ * this will be called again at the start of the after writing the
+ * start code, actually writing the mb info. */
+ return;
+ }
+
+ s->last_mb_info = put_bits_count(&s->pb)/8;
+ if (!s->mb_info_size)
+ s->mb_info_size += 12;
+ write_mb_info(s);
+}
+
static int encode_thread(AVCodecContext *c, void *arg){
MpegEncContext *s= *(void**)arg;
int mb_x, mb_y, pdif = 0;
int number_mb = (mb_y - s->resync_mb_y)*s->mb_width + mb_x - s->resync_mb_x;
s->avctx->rtp_callback(s->avctx, s->ptr_lastgob, current_packet_size, number_mb);
}
+ update_mb_info(s, 1);
switch(s->codec_id){
case CODEC_ID_MPEG4:
s->mb_skipped=0;
s->dquant=0; //only for QP_RD
- if(mb_type & (mb_type-1) || (s->flags & CODEC_FLAG_QP_RD)){ // more than 1 MB type possible or CODEC_FLAG_QP_RD
+ update_mb_info(s, 0);
+
+ if (mb_type & (mb_type-1) || (s->mpv_flags & FF_MPV_FLAG_QP_RD)) { // more than 1 MB type possible or FF_MPV_FLAG_QP_RD
int next_block=0;
int pb_bits_count, pb2_bits_count, tex_pb_bits_count;
}
}
- if((s->flags & CODEC_FLAG_QP_RD) && dmin < INT_MAX){
+ if ((s->mpv_flags & FF_MPV_FLAG_QP_RD) && dmin < INT_MAX) {
if(best_s.mv_type==MV_TYPE_16X16){ //FIXME move 4mv after QPRD
const int last_qp= backup_s.qscale;
int qpi, qp, dc[6];
encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_DIRECT, pb, pb2, tex_pb,
&dmin, &next_block, 0, 0);
}
- if(!best_s.mb_intra && s->flags2&CODEC_FLAG2_SKIP_RD){
+ if (!best_s.mb_intra && s->mpv_flags & FF_MPV_FLAG_SKIP_RD) {
int coded=0;
for(i=0; i<6; i++)
coded |= s->block_last_index[i];
int dct_coeff= FFABS(block[ scantable[i] ]);
int best_score=256*256*256*120;
- if ( s->dsp.fdct == ff_fdct_ifast
-#ifndef FAAN_POSTSCALE
- || s->dsp.fdct == ff_faandct
-#endif
- )
+ if (s->dsp.fdct == ff_fdct_ifast)
dct_coeff= (dct_coeff*ff_inv_aanscales[ scantable[i] ]) >> 12;
zero_distortion= dct_coeff*dct_coeff;
#ifdef REFINE_STATS
{START_TIMER
#endif
- analyze_gradient = last_non_zero > 2 || s->avctx->quantizer_noise_shaping >= 3;
+ analyze_gradient = last_non_zero > 2 || s->quantizer_noise_shaping >= 3;
if(analyze_gradient){
#ifdef REFINE_STATS
const int level= block[j];
int change, old_coeff;
- if(s->avctx->quantizer_noise_shaping < 3 && i > last_non_zero + 1)
+ if(s->quantizer_noise_shaping < 3 && i > last_non_zero + 1)
break;
if(level){
int score, new_coeff, unquant_change;
score=0;
- if(s->avctx->quantizer_noise_shaping < 2 && FFABS(new_level) > FFABS(level))
+ if(s->quantizer_noise_shaping < 2 && FFABS(new_level) > FFABS(level))
continue;
if(new_level){
static const AVOption h263_options[] = {
{ "obmc", "use overlapped block motion compensation.", OFFSET(obmc), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE },
{ "structured_slices","Write slice start position at every GOB header instead of just GOB number.", OFFSET(h263_slice_structured), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE},
+ { "mb_info", "emit macroblock info for RFC 2190 packetization, the parameter value is the maximum payload size", OFFSET(mb_info), AV_OPT_TYPE_INT, { 0 }, 0, INT_MAX, VE },
+ FF_MPV_COMMON_OPTS
{ NULL },
};
{ "aiv", "Use alternative inter VLC.", OFFSET(alt_inter_vlc), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE },
{ "obmc", "use overlapped block motion compensation.", OFFSET(obmc), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE },
{ "structured_slices", "Write slice start position at every GOB header instead of just GOB number.", OFFSET(h263_slice_structured), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE},
+ FF_MPV_COMMON_OPTS
{ NULL },
};
static const AVClass h263p_class = {
.init = ff_MPV_encode_init,
.encode2 = ff_MPV_encode_picture,
.close = ff_MPV_encode_end,
- .capabilities = CODEC_CAP_SLICE_THREADS,
- .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
- .long_name= NULL_IF_CONFIG_SMALL("H.263+ / H.263-1998 / H.263 version 2"),
+ .capabilities = CODEC_CAP_SLICE_THREADS,
+ .pix_fmts = (const enum PixelFormat[]){ PIX_FMT_YUV420P, PIX_FMT_NONE },
+ .long_name = NULL_IF_CONFIG_SMALL("H.263+ / H.263-1998 / H.263 version 2"),
.priv_class = &h263p_class,
};
+FF_MPV_GENERIC_CLASS(msmpeg4v2)
+
AVCodec ff_msmpeg4v2_encoder = {
.name = "msmpeg4v2",
.type = AVMEDIA_TYPE_VIDEO,
.init = ff_MPV_encode_init,
.encode2 = ff_MPV_encode_picture,
.close = ff_MPV_encode_end,
- .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
- .long_name= NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 2"),
+ .pix_fmts = (const enum PixelFormat[]){ PIX_FMT_YUV420P, PIX_FMT_NONE },
+ .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 2"),
+ .priv_class = &msmpeg4v2_class,
};
+FF_MPV_GENERIC_CLASS(msmpeg4v3)
+
AVCodec ff_msmpeg4v3_encoder = {
.name = "msmpeg4",
.type = AVMEDIA_TYPE_VIDEO,
.init = ff_MPV_encode_init,
.encode2 = ff_MPV_encode_picture,
.close = ff_MPV_encode_end,
- .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
- .long_name= NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 3"),
+ .pix_fmts = (const enum PixelFormat[]){ PIX_FMT_YUV420P, PIX_FMT_NONE },
+ .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 3"),
+ .priv_class = &msmpeg4v3_class,
};
+FF_MPV_GENERIC_CLASS(wmv1)
+
AVCodec ff_wmv1_encoder = {
.name = "wmv1",
.type = AVMEDIA_TYPE_VIDEO,
.init = ff_MPV_encode_init,
.encode2 = ff_MPV_encode_picture,
.close = ff_MPV_encode_end,
- .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
- .long_name= NULL_IF_CONFIG_SMALL("Windows Media Video 7"),
+ .pix_fmts = (const enum PixelFormat[]){ PIX_FMT_YUV420P, PIX_FMT_NONE },
+ .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 7"),
+ .priv_class = &wmv1_class,
};