On 2013-12-20 13:00:19 +0100, Anton Khirnov wrote:
> This introduces some code duplication. However, much of it should go
> away once the decoders stop using MpegEncContext.
Might just look different but reference frame handling won't go from
either. that said I think the duplication is fine as it untangles the
mess.
> ---
> libavcodec/mpegvideo.c | 114
> ++++++++++++++++----------------------------
> libavcodec/mpegvideo_enc.c | 97 ++++++++++++++++++++++++++++++++++++-
> 2 files changed, 137 insertions(+), 74 deletions(-)
>
> diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
> index 5f51e5c..db5022e 100644
> --- a/libavcodec/mpegvideo.c
> +++ b/libavcodec/mpegvideo.c
> @@ -1309,30 +1309,9 @@ int ff_find_unused_picture(MpegEncContext *s, int
> shared)
> return ret;
> }
>
> -static void update_noise_reduction(MpegEncContext *s)
> -{
> - int intra, i;
> -
> - for (intra = 0; intra < 2; intra++) {
> - if (s->dct_count[intra] > (1 << 16)) {
> - for (i = 0; i < 64; i++) {
> - s->dct_error_sum[intra][i] >>= 1;
> - }
> - s->dct_count[intra] >>= 1;
> - }
> -
> - for (i = 0; i < 64; i++) {
> - s->dct_offset[intra][i] = (s->avctx->noise_reduction *
> - s->dct_count[intra] +
> - s->dct_error_sum[intra][i] / 2) /
> - (s->dct_error_sum[intra][i] + 1);
> - }
> - }
> -}
> -
> /**
> - * generic function for encode/decode called after coding/decoding
> - * the header and before a frame is coded/decoded.
> + * generic function called after decoding
> + * the header and before a frame is decoded.
> */
> int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
> {
> @@ -1349,62 +1328,58 @@ int ff_MPV_frame_start(MpegEncContext *s,
> AVCodecContext *avctx)
>
> /* release forgotten pictures */
> /* if (mpeg124/h263) */
> - if (!s->encoding) {
> - for (i = 0; i < MAX_PICTURE_COUNT; i++) {
> - if (&s->picture[i] != s->last_picture_ptr &&
> - &s->picture[i] != s->next_picture_ptr &&
> - s->picture[i].reference && !s->picture[i].needs_realloc) {
> - if (!(avctx->active_thread_type & FF_THREAD_FRAME))
> - av_log(avctx, AV_LOG_ERROR,
> - "releasing zombie picture\n");
> - ff_mpeg_unref_picture(s, &s->picture[i]);
> - }
> + for (i = 0; i < MAX_PICTURE_COUNT; i++) {
> + if (&s->picture[i] != s->last_picture_ptr &&
> + &s->picture[i] != s->next_picture_ptr &&
> + s->picture[i].reference && !s->picture[i].needs_realloc) {
> + if (!(avctx->active_thread_type & FF_THREAD_FRAME))
> + av_log(avctx, AV_LOG_ERROR,
> + "releasing zombie picture\n");
> + ff_mpeg_unref_picture(s, &s->picture[i]);
> }
> }
>
> ff_mpeg_unref_picture(s, &s->current_picture);
>
> - if (!s->encoding) {
> - release_unused_pictures(s);
> + release_unused_pictures(s);
>
> - if (s->current_picture_ptr &&
> - s->current_picture_ptr->f.buf[0] == NULL) {
> - // we already have a unused image
> - // (maybe it was set before reading the header)
> - pic = s->current_picture_ptr;
> - } else {
> - i = ff_find_unused_picture(s, 0);
> - if (i < 0) {
> - av_log(s->avctx, AV_LOG_ERROR, "no frame buffer
> available\n");
> - return i;
> - }
> - pic = &s->picture[i];
> + if (s->current_picture_ptr &&
> + s->current_picture_ptr->f.buf[0] == NULL) {
> + // we already have a unused image
> + // (maybe it was set before reading the header)
> + pic = s->current_picture_ptr;
> + } else {
> + i = ff_find_unused_picture(s, 0);
> + if (i < 0) {
> + av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n");
> + return i;
> }
> + pic = &s->picture[i];
> + }
>
> - pic->reference = 0;
> - if (!s->droppable) {
> - if (s->pict_type != AV_PICTURE_TYPE_B)
> - pic->reference = 3;
> - }
> + pic->reference = 0;
> + if (!s->droppable) {
> + if (s->pict_type != AV_PICTURE_TYPE_B)
> + pic->reference = 3;
> + }
>
> - pic->f.coded_picture_number = s->coded_picture_number++;
> + pic->f.coded_picture_number = s->coded_picture_number++;
>
> - if (ff_alloc_picture(s, pic, 0) < 0)
> - return -1;
> + if (ff_alloc_picture(s, pic, 0) < 0)
> + return -1;
>
> - s->current_picture_ptr = pic;
> - // FIXME use only the vars from current_pic
> - s->current_picture_ptr->f.top_field_first = s->top_field_first;
> - if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO ||
> - s->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
> - if (s->picture_structure != PICT_FRAME)
> - s->current_picture_ptr->f.top_field_first =
> - (s->picture_structure == PICT_TOP_FIELD) ==
> s->first_field;
> - }
> - s->current_picture_ptr->f.interlaced_frame = !s->progressive_frame &&
> -
> !s->progressive_sequence;
> - s->current_picture_ptr->field_picture = s->picture_structure
> != PICT_FRAME;
> + s->current_picture_ptr = pic;
> + // FIXME use only the vars from current_pic
> + s->current_picture_ptr->f.top_field_first = s->top_field_first;
> + if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO ||
> + s->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
> + if (s->picture_structure != PICT_FRAME)
> + s->current_picture_ptr->f.top_field_first =
> + (s->picture_structure == PICT_TOP_FIELD) == s->first_field;
> }
> + s->current_picture_ptr->f.interlaced_frame = !s->progressive_frame &&
> + !s->progressive_sequence;
> + s->current_picture_ptr->field_picture = s->picture_structure !=
> PICT_FRAME;
>
> s->current_picture_ptr->f.pict_type = s->pict_type;
> // if (s->flags && CODEC_FLAG_QSCALE)
> @@ -1534,11 +1509,6 @@ int ff_MPV_frame_start(MpegEncContext *s,
> AVCodecContext *avctx)
> s->dct_unquantize_inter = s->dct_unquantize_mpeg1_inter;
> }
>
> - if (s->dct_error_sum) {
> - assert(s->avctx->noise_reduction && s->encoding);
> - update_noise_reduction(s);
> - }
> -
> #if FF_API_XVMC
> FF_DISABLE_DEPRECATION_WARNINGS
> if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration)
> diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
> index 590e025..59d94b8 100644
> --- a/libavcodec/mpegvideo_enc.c
> +++ b/libavcodec/mpegvideo_enc.c
> @@ -1385,6 +1385,99 @@ static void frame_end(MpegEncContext *s)
>
> }
>
> +static void update_noise_reduction(MpegEncContext *s)
> +{
> + int intra, i;
> +
> + for (intra = 0; intra < 2; intra++) {
> + if (s->dct_count[intra] > (1 << 16)) {
> + for (i = 0; i < 64; i++) {
> + s->dct_error_sum[intra][i] >>= 1;
> + }
> + s->dct_count[intra] >>= 1;
> + }
> +
> + for (i = 0; i < 64; i++) {
> + s->dct_offset[intra][i] = (s->avctx->noise_reduction *
> + s->dct_count[intra] +
> + s->dct_error_sum[intra][i] / 2) /
> + (s->dct_error_sum[intra][i] + 1);
> + }
> + }
> +}
> +
> +static int frame_start(MpegEncContext *s)
> +{
> + int ret;
> +
> + /* mark & release old frames */
> + if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr &&
> + s->last_picture_ptr != s->next_picture_ptr &&
> + s->last_picture_ptr->f.buf[0]) {
> + ff_mpeg_unref_picture(s, s->last_picture_ptr);
> + }
> +
> + s->current_picture_ptr->f.pict_type = s->pict_type;
> + s->current_picture_ptr->f.key_frame = s->pict_type == AV_PICTURE_TYPE_I;
> +
> + ff_mpeg_unref_picture(s, &s->current_picture);
> + if ((ret = ff_mpeg_ref_picture(s, &s->current_picture,
> + s->current_picture_ptr)) < 0)
> + return ret;
> +
> + if (s->pict_type != AV_PICTURE_TYPE_B) {
> + s->last_picture_ptr = s->next_picture_ptr;
> + if (!s->droppable)
> + s->next_picture_ptr = s->current_picture_ptr;
> + }
> +
> + if (s->last_picture_ptr) {
> + ff_mpeg_unref_picture(s, &s->last_picture);
> + if (s->last_picture_ptr->f.buf[0] &&
> + (ret = ff_mpeg_ref_picture(s, &s->last_picture,
> + s->last_picture_ptr)) < 0)
> + return ret;
> + }
> + if (s->next_picture_ptr) {
> + ff_mpeg_unref_picture(s, &s->next_picture);
> + if (s->next_picture_ptr->f.buf[0] &&
> + (ret = ff_mpeg_ref_picture(s, &s->next_picture,
> + s->next_picture_ptr)) < 0)
> + return ret;
> + }
> +
> + if (s->picture_structure!= PICT_FRAME) {
> + int i;
> + for (i = 0; i < 4; i++) {
> + if (s->picture_structure == PICT_BOTTOM_FIELD) {
> + s->current_picture.f.data[i] +=
> + s->current_picture.f.linesize[i];
> + }
> + s->current_picture.f.linesize[i] *= 2;
> + s->last_picture.f.linesize[i] *= 2;
> + s->next_picture.f.linesize[i] *= 2;
> + }
> + }
> +
> + if (s->mpeg_quant || s->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
> + s->dct_unquantize_intra = s->dct_unquantize_mpeg2_intra;
> + s->dct_unquantize_inter = s->dct_unquantize_mpeg2_inter;
> + } else if (s->out_format == FMT_H263 || s->out_format == FMT_H261) {
> + s->dct_unquantize_intra = s->dct_unquantize_h263_intra;
> + s->dct_unquantize_inter = s->dct_unquantize_h263_inter;
> + } else {
> + s->dct_unquantize_intra = s->dct_unquantize_mpeg1_intra;
> + s->dct_unquantize_inter = s->dct_unquantize_mpeg1_inter;
> + }
> +
> + if (s->dct_error_sum) {
> + assert(s->avctx->noise_reduction && s->encoding);
> + update_noise_reduction(s);
> + }
> +
> + return 0;
> +}
> +
> int ff_MPV_encode_picture(AVCodecContext *avctx, AVPacket *pkt,
> const AVFrame *pic_arg, int *got_packet)
> {
> @@ -1425,7 +1518,7 @@ int ff_MPV_encode_picture(AVCodecContext *avctx,
> AVPacket *pkt,
>
> s->pict_type = s->new_picture.f.pict_type;
> //emms_c();
> - ff_MPV_frame_start(s, avctx);
> + frame_start(s);
kind of unrelated but please add check for error and pass the return
value along on error.
> vbv_retry:
> if (encode_picture(s, s->picture_number) < 0)
> return -1;
> @@ -1461,7 +1554,7 @@ vbv_retry:
> s->lambda_table[i] * (s->qscale + 1) /
> s->qscale);
> }
> - s->mb_skipped = 0; // done in MPV_frame_start()
> + s->mb_skipped = 0; // done in frame_start()
> // done in encode_picture() so we must undo it
> if (s->pict_type == AV_PICTURE_TYPE_P) {
> if (s->flipflop_rounding ||
otherwise ok
Janne
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel