diff options
Diffstat (limited to 'libavcodec/mpegvideo.c')
-rw-r--r-- | libavcodec/mpegvideo.c | 803 |
1 files changed, 587 insertions, 216 deletions
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index ce366102d1..a21054b5ff 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -5,20 +5,20 @@ * * 4MV & hq & B-frame encoding stuff by Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -58,9 +58,6 @@ static void dct_unquantize_h263_inter_c(MpegEncContext *s, DCTELEM *block, int n, int qscale); -/* enable all paranoid tests for rounding, overflows, etc... */ -//#define PARANOID - //#define DEBUG @@ -139,9 +136,9 @@ const enum AVPixelFormat ff_hwaccel_pixfmt_list_420[] = { AV_PIX_FMT_NONE }; -const uint8_t *avpriv_mpv_find_start_code(const uint8_t *restrict p, +const uint8_t *avpriv_mpv_find_start_code(const uint8_t *av_restrict p, const uint8_t *end, - uint32_t * restrict state) + uint32_t *av_restrict state) { int i; @@ -226,6 +223,7 @@ void ff_copy_picture(Picture *dst, Picture *src) */ static void free_frame_buffer(MpegEncContext *s, Picture *pic) { + pic->period_since_free = 0; /* WM Image / Screen codecs allocate internal buffers with different * dimensions / colorspaces; ignore user-defined callbacks for these. */ if (s->codec_id != AV_CODEC_ID_WMV3IMAGE && @@ -239,17 +237,17 @@ static void free_frame_buffer(MpegEncContext *s, Picture *pic) int ff_mpv_frame_size_alloc(MpegEncContext *s, int linesize) { - int alloc_size = FFALIGN(FFABS(linesize) + 32, 32); + int alloc_size = FFALIGN(FFABS(linesize) + 64, 32); // edge emu needs blocksize + filter length - 1 // (= 17x17 for halfpel / 21x21 for h264) // VC1 computes luma and chroma simultaneously and needs 19X19 + 9x9 // at uvlinesize. It supports only YUV420 so 24x24 is enough // linesize * interlaced * MBsize - FF_ALLOCZ_OR_GOTO(s->avctx, s->edge_emu_buffer, alloc_size * 2 * 24, + FF_ALLOCZ_OR_GOTO(s->avctx, s->edge_emu_buffer, alloc_size * 4 * 24, fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->me.scratchpad, alloc_size * 2 * 16 * 2, + FF_ALLOCZ_OR_GOTO(s->avctx, s->me.scratchpad, alloc_size * 4 * 16 * 2, fail) s->me.temp = s->me.scratchpad; s->rd_scratchpad = s->me.scratchpad; @@ -566,27 +564,35 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst, const AVCodecContext *src) { int i; + int err; MpegEncContext *s = dst->priv_data, *s1 = src->priv_data; - if (dst == src || !s1->context_initialized) + if (dst == src) return 0; + av_assert0(s != s1); + // FIXME can parameters change on I-frames? // in that case dst may need a reinit if (!s->context_initialized) { memcpy(s, s1, sizeof(MpegEncContext)); s->avctx = dst; - s->picture_range_start += MAX_PICTURE_COUNT; - s->picture_range_end += MAX_PICTURE_COUNT; s->bitstream_buffer = NULL; s->bitstream_buffer_size = s->allocated_bitstream_buffer_size = 0; - ff_MPV_common_init(s); + if (s1->context_initialized){ + s->picture_range_start += MAX_PICTURE_COUNT; + s->picture_range_end += MAX_PICTURE_COUNT; + if((err = ff_MPV_common_init(s)) < 0){ + memset(s, 0, sizeof(MpegEncContext)); + s->avctx = dst; + return err; + } + } } if (s->height != s1->height || s->width != s1->width || s->context_reinit) { - int err; s->context_reinit = 0; s->height = s1->height; s->width = s1->width; @@ -603,13 +609,16 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst, s->picture_number = s1->picture_number; s->input_picture_number = s1->input_picture_number; + av_assert0(!s->picture || s->picture != s1->picture); memcpy(s->picture, s1->picture, s1->picture_count * sizeof(Picture)); memcpy(&s->last_picture, &s1->last_picture, (char *) &s1->last_picture_ptr - (char *) &s1->last_picture); // reset s->picture[].f.extended_data to s->picture[].f.data - for (i = 0; i < s->picture_count; i++) + for (i = 0; i < s->picture_count; i++) { s->picture[i].f.extended_data = s->picture[i].f.data; + s->picture[i].period_since_free ++; + } s->last_picture_ptr = REBASE_PICTURE(s1->last_picture_ptr, s, s1); s->current_picture_ptr = REBASE_PICTURE(s1->current_picture_ptr, s, s1); @@ -618,6 +627,7 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst, // Error/bug resilience s->next_p_frame_damaged = s1->next_p_frame_damaged; s->workaround_bugs = s1->workaround_bugs; + s->padding_bug_score = s1->padding_bug_score; // MPEG4 timing info memcpy(&s->time_increment_bits, &s1->time_increment_bits, @@ -655,7 +665,6 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst, } else { av_log(s->avctx, AV_LOG_ERROR, "Context scratch buffers could not " "be allocated due to unknown size.\n"); - return AVERROR_BUG; } // MPEG2/interlacing info @@ -747,44 +756,32 @@ static int init_context_frame(MpegEncContext *s) c_size = s->mb_stride * (s->mb_height + 1); yc_size = y_size + 2 * c_size; - FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_index2xy, (s->mb_num + 1) * sizeof(int), - fail); // error ressilience code looks cleaner with this + FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_index2xy, (s->mb_num + 1) * sizeof(int), fail); // error ressilience code looks cleaner with this for (y = 0; y < s->mb_height; y++) for (x = 0; x < s->mb_width; x++) s->mb_index2xy[x + y * s->mb_width] = x + y * s->mb_stride; - s->mb_index2xy[s->mb_height * s->mb_width] = - (s->mb_height - 1) * s->mb_stride + s->mb_width; // FIXME really needed? + s->mb_index2xy[s->mb_height * s->mb_width] = (s->mb_height - 1) * s->mb_stride + s->mb_width; // FIXME really needed? if (s->encoding) { /* Allocate MV tables */ - FF_ALLOCZ_OR_GOTO(s->avctx, s->p_mv_table_base, - mv_table_size * 2 * sizeof(int16_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->b_forw_mv_table_base, - mv_table_size * 2 * sizeof(int16_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->b_back_mv_table_base, - mv_table_size * 2 * sizeof(int16_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_forw_mv_table_base, - mv_table_size * 2 * sizeof(int16_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_back_mv_table_base, - mv_table_size * 2 * sizeof(int16_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->b_direct_mv_table_base, - mv_table_size * 2 * sizeof(int16_t), fail); + FF_ALLOCZ_OR_GOTO(s->avctx, s->p_mv_table_base, mv_table_size * 2 * sizeof(int16_t), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->b_forw_mv_table_base, mv_table_size * 2 * sizeof(int16_t), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->b_back_mv_table_base, mv_table_size * 2 * sizeof(int16_t), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_forw_mv_table_base, mv_table_size * 2 * sizeof(int16_t), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_back_mv_table_base, mv_table_size * 2 * sizeof(int16_t), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->b_direct_mv_table_base, mv_table_size * 2 * sizeof(int16_t), fail) s->p_mv_table = s->p_mv_table_base + s->mb_stride + 1; s->b_forw_mv_table = s->b_forw_mv_table_base + s->mb_stride + 1; s->b_back_mv_table = s->b_back_mv_table_base + s->mb_stride + 1; - s->b_bidir_forw_mv_table = s->b_bidir_forw_mv_table_base + - s->mb_stride + 1; - s->b_bidir_back_mv_table = s->b_bidir_back_mv_table_base + - s->mb_stride + 1; + s->b_bidir_forw_mv_table = s->b_bidir_forw_mv_table_base + s->mb_stride + 1; + s->b_bidir_back_mv_table = s->b_bidir_back_mv_table_base + s->mb_stride + 1; s->b_direct_mv_table = s->b_direct_mv_table_base + s->mb_stride + 1; /* Allocate MB type table */ - FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_type, mb_array_size * - sizeof(uint16_t), fail); // needed for encoding + FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_type, mb_array_size * sizeof(uint16_t), fail) // needed for encoding - FF_ALLOCZ_OR_GOTO(s->avctx, s->lambda_table, mb_array_size * - sizeof(int), fail); + FF_ALLOCZ_OR_GOTO(s->avctx, s->lambda_table, mb_array_size * sizeof(int), fail) FF_ALLOC_OR_GOTO(s->avctx, s->cplx_tab, mb_array_size * sizeof(float), fail); @@ -798,8 +795,7 @@ static int init_context_frame(MpegEncContext *s) FF_ALLOCZ_OR_GOTO(s->avctx, s->error_status_table, mb_array_size * sizeof(uint8_t), fail); - if (s->codec_id == AV_CODEC_ID_MPEG4 || - (s->flags & CODEC_FLAG_INTERLACED_ME)) { + if (s->codec_id == AV_CODEC_ID_MPEG4 || (s->flags & CODEC_FLAG_INTERLACED_ME)) { /* interlaced direct mode decoding tables */ for (i = 0; i < 2; i++) { int j, k; @@ -812,15 +808,11 @@ static int init_context_frame(MpegEncContext *s) s->b_field_mv_table[i][j][k] = s->b_field_mv_table_base[i][j][k] + s->mb_stride + 1; } - FF_ALLOCZ_OR_GOTO(s->avctx, s->b_field_select_table [i][j], - mb_array_size * 2 * sizeof(uint8_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_mv_table_base[i][j], - mv_table_size * 2 * sizeof(int16_t), fail); - s->p_field_mv_table[i][j] = s->p_field_mv_table_base[i][j] - + s->mb_stride + 1; + FF_ALLOCZ_OR_GOTO(s->avctx, s->b_field_select_table [i][j], mb_array_size * 2 * sizeof(uint8_t), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_mv_table_base[i][j], mv_table_size * 2 * sizeof(int16_t), fail) + s->p_field_mv_table[i][j] = s->p_field_mv_table_base[i][j] + s->mb_stride + 1; } - FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_select_table[i], - mb_array_size * 2 * sizeof(uint8_t), fail); + FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_select_table[i], mb_array_size * 2 * sizeof(uint8_t), fail) } } if (s->out_format == FMT_H263) { @@ -829,17 +821,14 @@ static int init_context_frame(MpegEncContext *s) s->coded_block = s->coded_block_base + s->b8_stride + 1; /* cbp, ac_pred, pred_dir */ - FF_ALLOCZ_OR_GOTO(s->avctx, s->cbp_table, - mb_array_size * sizeof(uint8_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->pred_dir_table, - mb_array_size * sizeof(uint8_t), fail); + FF_ALLOCZ_OR_GOTO(s->avctx, s->cbp_table , mb_array_size * sizeof(uint8_t), fail); + FF_ALLOCZ_OR_GOTO(s->avctx, s->pred_dir_table, mb_array_size * sizeof(uint8_t), fail); } if (s->h263_pred || s->h263_plus || !s->encoding) { /* dc values */ // MN: we need these for error resilience of intra-frames - FF_ALLOCZ_OR_GOTO(s->avctx, s->dc_val_base, - yc_size * sizeof(int16_t), fail); + FF_ALLOCZ_OR_GOTO(s->avctx, s->dc_val_base, yc_size * sizeof(int16_t), fail); s->dc_val[0] = s->dc_val_base + s->b8_stride + 1; s->dc_val[1] = s->dc_val_base + y_size + s->mb_stride + 1; s->dc_val[2] = s->dc_val[1] + c_size; @@ -855,16 +844,6 @@ static int init_context_frame(MpegEncContext *s) FF_ALLOCZ_OR_GOTO(s->avctx, s->mbskip_table, mb_array_size + 2, fail); // Note the + 1 is for a quicker mpeg4 slice_end detection - if ((s->avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) || - s->avctx->debug_mv) { - s->visualization_buffer[0] = av_malloc((s->mb_width * 16 + - 2 * EDGE_WIDTH) * s->mb_height * 16 + 2 * EDGE_WIDTH); - s->visualization_buffer[1] = av_malloc((s->mb_width * 16 + - 2 * EDGE_WIDTH) * s->mb_height * 16 + 2 * EDGE_WIDTH); - s->visualization_buffer[2] = av_malloc((s->mb_width * 16 + - 2 * EDGE_WIDTH) * s->mb_height * 16 + 2 * EDGE_WIDTH); - } - return 0; fail: return AVERROR(ENOMEM); @@ -915,44 +894,34 @@ av_cold int ff_MPV_common_init(MpegEncContext *s) s->flags = s->avctx->flags; s->flags2 = s->avctx->flags2; - if (s->width && s->height) { - /* set chroma shifts */ - av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, - &s->chroma_x_shift, - &s->chroma_y_shift); + /* set chroma shifts */ + avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &s->chroma_x_shift, &s->chroma_y_shift); - /* convert fourcc to upper case */ - s->codec_tag = avpriv_toupper4(s->avctx->codec_tag); + /* convert fourcc to upper case */ + s->codec_tag = avpriv_toupper4(s->avctx->codec_tag); + s->stream_codec_tag = avpriv_toupper4(s->avctx->stream_codec_tag); - s->stream_codec_tag = avpriv_toupper4(s->avctx->stream_codec_tag); + s->avctx->coded_frame = &s->current_picture.f; - s->avctx->coded_frame = &s->current_picture.f; + if (s->encoding) { + if (s->msmpeg4_version) { + FF_ALLOCZ_OR_GOTO(s->avctx, s->ac_stats, + 2 * 2 * (MAX_LEVEL + 1) * + (MAX_RUN + 1) * 2 * sizeof(int), fail); + } + FF_ALLOCZ_OR_GOTO(s->avctx, s->avctx->stats_out, 256, fail); - if (s->encoding) { - if (s->msmpeg4_version) { - FF_ALLOCZ_OR_GOTO(s->avctx, s->ac_stats, - 2 * 2 * (MAX_LEVEL + 1) * - (MAX_RUN + 1) * 2 * sizeof(int), fail); - } - FF_ALLOCZ_OR_GOTO(s->avctx, s->avctx->stats_out, 256, fail); - - FF_ALLOCZ_OR_GOTO(s->avctx, s->q_intra_matrix, - 64 * 32 * sizeof(int), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->q_inter_matrix, - 64 * 32 * sizeof(int), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->q_intra_matrix16, - 64 * 32 * 2 * sizeof(uint16_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->q_inter_matrix16, - 64 * 32 * 2 * sizeof(uint16_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->input_picture, - MAX_PICTURE_COUNT * sizeof(Picture *), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->reordered_input_picture, - MAX_PICTURE_COUNT * sizeof(Picture *), fail); - - if (s->avctx->noise_reduction) { - FF_ALLOCZ_OR_GOTO(s->avctx, s->dct_offset, - 2 * 64 * sizeof(uint16_t), fail); - } + FF_ALLOCZ_OR_GOTO(s->avctx, s->q_intra_matrix, 64 * 32 * sizeof(int), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->q_chroma_intra_matrix, 64 * 32 * sizeof(int), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->q_inter_matrix, 64 * 32 * sizeof(int), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->q_intra_matrix16, 64 * 32 * 2 * sizeof(uint16_t), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->q_chroma_intra_matrix16, 64 * 32 * 2 * sizeof(uint16_t), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->q_inter_matrix16, 64 * 32 * 2 * sizeof(uint16_t), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->input_picture, MAX_PICTURE_COUNT * sizeof(Picture *), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->reordered_input_picture, MAX_PICTURE_COUNT * sizeof(Picture *), fail) + + if (s->avctx->noise_reduction) { + FF_ALLOCZ_OR_GOTO(s->avctx, s->dct_offset, 2 * 64 * sizeof(uint16_t), fail); } } @@ -963,17 +932,15 @@ av_cold int ff_MPV_common_init(MpegEncContext *s) avcodec_get_frame_defaults(&s->picture[i].f); } - if (s->width && s->height) { if (init_context_frame(s)) goto fail; s->parse_context.state = -1; - } - s->context_initialized = 1; - s->thread_context[0] = s; + s->context_initialized = 1; + s->thread_context[0] = s; - if (s->width && s->height) { +// if (s->width && s->height) { if (nb_slices > 1) { for (i = 1; i < nb_slices; i++) { s->thread_context[i] = av_malloc(sizeof(MpegEncContext)); @@ -995,7 +962,7 @@ av_cold int ff_MPV_common_init(MpegEncContext *s) s->end_mb_y = s->mb_height; } s->slice_context_count = nb_slices; - } +// } return 0; fail: @@ -1050,6 +1017,7 @@ static int free_context_frame(MpegEncContext *s) av_freep(&s->er_temp_buffer); av_freep(&s->mb_index2xy); av_freep(&s->lambda_table); + av_freep(&s->cplx_tab); av_freep(&s->bits_tab); @@ -1156,6 +1124,10 @@ void ff_MPV_common_end(MpegEncContext *s) av_freep(&s->avctx->stats_out); av_freep(&s->ac_stats); + if(s->q_chroma_intra_matrix != s->q_intra_matrix ) av_freep(&s->q_chroma_intra_matrix); + if(s->q_chroma_intra_matrix16 != s->q_intra_matrix16) av_freep(&s->q_chroma_intra_matrix16); + s->q_chroma_intra_matrix= NULL; + s->q_chroma_intra_matrix16= NULL; av_freep(&s->q_intra_matrix); av_freep(&s->q_inter_matrix); av_freep(&s->q_intra_matrix16); @@ -1292,6 +1264,10 @@ void ff_release_unused_pictures(MpegEncContext*s, int remove_current) static inline int pic_is_unused(MpegEncContext *s, Picture *pic) { + if ( (s->avctx->active_thread_type & FF_THREAD_FRAME) + && pic->f.qscale_table //check if the frame has anything allocated + && pic->period_since_free < s->avctx->thread_count) + return 0; if (pic->f.data[0] == NULL) return 1; if (pic->needs_realloc && !(pic->f.reference & DELAYED_PIC_REF)) @@ -1320,7 +1296,21 @@ static int find_unused_picture(MpegEncContext *s, int shared) } } - return AVERROR_INVALIDDATA; + av_log(s->avctx, AV_LOG_FATAL, + "Internal error, picture buffer overflow\n"); + /* We could return -1, but the codec would crash trying to draw into a + * non-existing frame anyway. This is safer than waiting for a random crash. + * Also the return of this is never useful, an encoder must only allocate + * as much as allowed in the specification. This has no relationship to how + * much libavcodec could allocate (and MAX_PICTURE_COUNT is always large + * enough for such valid streams). + * Plus, a decoder has to check stream validity and remove frames if too + * many reference frames are around. Waiting for "OOM" is not correct at + * all. Similarly, missing reference frames have to be replaced by + * interpolated/MC frames, anything else is a bug in the codec ... + */ + abort(); + return -1; } int ff_find_unused_picture(MpegEncContext *s, int shared) @@ -1368,6 +1358,11 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) Picture *pic; s->mb_skipped = 0; + if (!ff_thread_can_start_frame(avctx)) { + av_log(avctx, AV_LOG_ERROR, "Attempt to start a frame outside SETUP state\n"); + return -1; + } + /* mark & release old frames */ if (s->out_format != FMT_H264 || s->codec_id == AV_CODEC_ID_SVQ3) { if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr && @@ -1476,10 +1471,17 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) return i; } s->last_picture_ptr = &s->picture[i]; + s->last_picture_ptr->f.key_frame = 0; if (ff_alloc_picture(s, s->last_picture_ptr, 0) < 0) { s->last_picture_ptr = NULL; return -1; } + + if(s->codec_id == AV_CODEC_ID_FLV1 || s->codec_id == AV_CODEC_ID_H263){ + for(i=0; i<avctx->height; i++) + memset(s->last_picture_ptr->f.data[0] + s->last_picture_ptr->f.linesize[0]*i, 16, avctx->width); + } + ff_thread_report_progress(&s->last_picture_ptr->f, INT_MAX, 0); ff_thread_report_progress(&s->last_picture_ptr->f, INT_MAX, 1); s->last_picture_ptr->f.reference = 3; @@ -1494,6 +1496,7 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) return i; } s->next_picture_ptr = &s->picture[i]; + s->next_picture_ptr->f.key_frame = 0; if (ff_alloc_picture(s, s->next_picture_ptr, 0) < 0) { s->next_picture_ptr = NULL; return -1; @@ -1504,6 +1507,8 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) } } + memset(s->last_picture.f.data, 0, sizeof(s->last_picture.f.data)); + memset(s->next_picture.f.data, 0, sizeof(s->next_picture.f.data)); if (s->last_picture_ptr) ff_copy_picture(&s->last_picture, s->last_picture_ptr); if (s->next_picture_ptr) @@ -1568,28 +1573,30 @@ void ff_MPV_frame_end(MpegEncContext *s) // just to make sure that all data is rendered. if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) { ff_xvmc_field_end(s); - } else if ((s->error_count || s->encoding) && + } else if((s->error_count || s->encoding || !(s->avctx->codec->capabilities&CODEC_CAP_DRAW_HORIZ_BAND)) && !s->avctx->hwaccel && !(s->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) && s->unrestricted_mv && s->current_picture.f.reference && !s->intra_only && - !(s->flags & CODEC_FLAG_EMU_EDGE)) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->avctx->pix_fmt); - int hshift = desc->log2_chroma_w; - int vshift = desc->log2_chroma_h; - s->dsp.draw_edges(s->current_picture.f.data[0], s->linesize, - s->h_edge_pos, s->v_edge_pos, - EDGE_WIDTH, EDGE_WIDTH, - EDGE_TOP | EDGE_BOTTOM); - s->dsp.draw_edges(s->current_picture.f.data[1], s->uvlinesize, - s->h_edge_pos >> hshift, s->v_edge_pos >> vshift, - EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, - EDGE_TOP | EDGE_BOTTOM); - s->dsp.draw_edges(s->current_picture.f.data[2], s->uvlinesize, - s->h_edge_pos >> hshift, s->v_edge_pos >> vshift, - EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, - EDGE_TOP | EDGE_BOTTOM); + !(s->flags & CODEC_FLAG_EMU_EDGE) && + !s->avctx->lowres + ) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->avctx->pix_fmt); + int hshift = desc->log2_chroma_w; + int vshift = desc->log2_chroma_h; + s->dsp.draw_edges(s->current_picture.f.data[0], s->current_picture.f.linesize[0], + s->h_edge_pos, s->v_edge_pos, + EDGE_WIDTH, EDGE_WIDTH, + EDGE_TOP | EDGE_BOTTOM); + s->dsp.draw_edges(s->current_picture.f.data[1], s->current_picture.f.linesize[1], + s->h_edge_pos >> hshift, s->v_edge_pos >> vshift, + EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, + EDGE_TOP | EDGE_BOTTOM); + s->dsp.draw_edges(s->current_picture.f.data[2], s->current_picture.f.linesize[2], + s->h_edge_pos >> hshift, s->v_edge_pos >> vshift, + EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, + EDGE_TOP | EDGE_BOTTOM); } emms_c(); @@ -1663,7 +1670,7 @@ static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey, y = (x * f) >> 16; fr = (x * f) & 0xFFFF; buf[y * stride + x] += (color * (0x10000 - fr)) >> 16; - buf[(y + 1) * stride + x] += (color * fr ) >> 16; + if(fr) buf[(y + 1) * stride + x] += (color * fr ) >> 16; } } else { if (sy > ey) { @@ -1673,14 +1680,14 @@ static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey, buf += sx + sy * stride; ey -= sy; if (ey) - f = ((ex - sx) << 16) / ey; + f = ((ex - sx) << 16) / ey; else f = 0; - for (y = 0; y = ey; y++) { - x = (y * f) >> 16; - fr = (y * f) & 0xFFFF; + for(y= 0; y <= ey; y++){ + x = (y*f) >> 16; + fr = (y*f) & 0xFFFF; buf[y * stride + x] += (color * (0x10000 - fr)) >> 16; - buf[y * stride + x + 1] += (color * fr ) >> 16; + if(fr) buf[y * stride + x + 1] += (color * fr ) >> 16; } } } @@ -1725,33 +1732,16 @@ static void draw_arrow(uint8_t *buf, int sx, int sy, int ex, */ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict) { - if (s->avctx->hwaccel || !pict || !pict->mb_type) + if ( s->avctx->hwaccel || !pict || !pict->mb_type + || (s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)) return; + if (s->avctx->debug & (FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE)) { int x,y; - av_log(s->avctx,AV_LOG_DEBUG,"New frame, type: "); - switch (pict->pict_type) { - case AV_PICTURE_TYPE_I: - av_log(s->avctx,AV_LOG_DEBUG,"I\n"); - break; - case AV_PICTURE_TYPE_P: - av_log(s->avctx,AV_LOG_DEBUG,"P\n"); - break; - case AV_PICTURE_TYPE_B: - av_log(s->avctx,AV_LOG_DEBUG,"B\n"); - break; - case AV_PICTURE_TYPE_S: - av_log(s->avctx,AV_LOG_DEBUG,"S\n"); - break; - case AV_PICTURE_TYPE_SI: - av_log(s->avctx,AV_LOG_DEBUG,"SI\n"); - break; - case AV_PICTURE_TYPE_SP: - av_log(s->avctx,AV_LOG_DEBUG,"SP\n"); - break; - } + av_log(s->avctx, AV_LOG_DEBUG, "New frame, type: %c\n", + av_get_picture_type_char(pict->pict_type)); for (y = 0; y < s->mb_height; y++) { for (x = 0; x < s->mb_width; x++) { if (s->avctx->debug & FF_DEBUG_SKIP) { @@ -1790,7 +1780,7 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict) else if (!USES_LIST(mb_type, 0)) av_log(s->avctx, AV_LOG_DEBUG, "<"); else { - assert(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1)); + av_assert2(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1)); av_log(s->avctx, AV_LOG_DEBUG, "X"); } @@ -1831,15 +1821,17 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict) (s->codec_id == AV_CODEC_ID_H264 ? 0 : 1); s->low_delay = 0; // needed to see the vectors without trashing the buffers - av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, - &h_chroma_shift, &v_chroma_shift); + avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &h_chroma_shift, &v_chroma_shift); + for (i = 0; i < 3; i++) { - memcpy(s->visualization_buffer[i], pict->data[i], - (i == 0) ? pict->linesize[i] * height: - pict->linesize[i] * height >> v_chroma_shift); + size_t size= (i == 0) ? pict->linesize[i] * FFALIGN(height, 16): + pict->linesize[i] * FFALIGN(height, 16) >> v_chroma_shift; + s->visualization_buffer[i]= av_realloc(s->visualization_buffer[i], size); + memcpy(s->visualization_buffer[i], pict->data[i], size); pict->data[i] = s->visualization_buffer[i]; } pict->type = FF_BUFFER_TYPE_COPY; + pict->opaque= NULL; ptr = pict->data[0]; block_height = 16 >> v_chroma_shift; @@ -1847,7 +1839,7 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict) int mb_x; for (mb_x = 0; mb_x < s->mb_width; mb_x++) { const int mb_index = mb_x + mb_y * s->mb_stride; - if ((s->avctx->debug_mv) && pict->motion_val) { + if ((s->avctx->debug_mv) && pict->motion_val[0]) { int type; for (type = 0; type < 3; type++) { int direction = 0; @@ -1917,16 +1909,16 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict) height, s->linesize, 100); } } else { - int sx = mb_x * 16 + 8; - int sy = mb_y * 16 + 8; - int xy = (mb_x + mb_y * mv_stride) << mv_sample_log2; - int mx = pict->motion_val[direction][xy][0] >> shift + sx; - int my = pict->motion_val[direction][xy][1] >> shift + sy; + int sx= mb_x * 16 + 8; + int sy= mb_y * 16 + 8; + int xy= (mb_x + mb_y * mv_stride) << mv_sample_log2; + int mx= (pict->motion_val[direction][xy][0]>>shift) + sx; + int my= (pict->motion_val[direction][xy][1]>>shift) + sy; draw_arrow(ptr, sx, sy, mx, my, width, height, s->linesize, 100); } } } - if ((s->avctx->debug & FF_DEBUG_VIS_QP) && pict->motion_val) { + if ((s->avctx->debug & FF_DEBUG_VIS_QP)) { uint64_t c = (pict->qscale_table[mb_index] * 128 / 31) * 0x0101010101010101ULL; int y; @@ -1940,7 +1932,7 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict) } } if ((s->avctx->debug & FF_DEBUG_VIS_MB_TYPE) && - pict->motion_val) { + pict->motion_val[0]) { int mb_type = pict->mb_type[mb_index]; uint64_t u,v; int y; @@ -1972,7 +1964,7 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict) } else if (!USES_LIST(mb_type, 0)) { COLOR(0, 48) } else { - assert(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1)); + av_assert2(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1)); COLOR(300,48) } @@ -2027,6 +2019,381 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict) } } +static inline int hpel_motion_lowres(MpegEncContext *s, + uint8_t *dest, uint8_t *src, + int field_based, int field_select, + int src_x, int src_y, + int width, int height, int stride, + int h_edge_pos, int v_edge_pos, + int w, int h, h264_chroma_mc_func *pix_op, + int motion_x, int motion_y) +{ + const int lowres = s->avctx->lowres; + const int op_index = FFMIN(lowres, 2); + const int s_mask = (2 << lowres) - 1; + int emu = 0; + int sx, sy; + + if (s->quarter_sample) { + motion_x /= 2; + motion_y /= 2; + } + + sx = motion_x & s_mask; + sy = motion_y & s_mask; + src_x += motion_x >> lowres + 1; + src_y += motion_y >> lowres + 1; + + src += src_y * stride + src_x; + + if ((unsigned)src_x > FFMAX( h_edge_pos - (!!sx) - w, 0) || + (unsigned)src_y > FFMAX((v_edge_pos >> field_based) - (!!sy) - h, 0)) { + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, src, s->linesize, w + 1, + (h + 1) << field_based, src_x, + src_y << field_based, + h_edge_pos, + v_edge_pos); + src = s->edge_emu_buffer; + emu = 1; + } + + sx = (sx << 2) >> lowres; + sy = (sy << 2) >> lowres; + if (field_select) + src += s->linesize; + pix_op[op_index](dest, src, stride, h, sx, sy); + return emu; +} + +/* apply one mpeg motion vector to the three components */ +static av_always_inline void mpeg_motion_lowres(MpegEncContext *s, + uint8_t *dest_y, + uint8_t *dest_cb, + uint8_t *dest_cr, + int field_based, + int bottom_field, + int field_select, + uint8_t **ref_picture, + h264_chroma_mc_func *pix_op, + int motion_x, int motion_y, + int h, int mb_y) +{ + uint8_t *ptr_y, *ptr_cb, *ptr_cr; + int mx, my, src_x, src_y, uvsrc_x, uvsrc_y, uvlinesize, linesize, sx, sy, + uvsx, uvsy; + const int lowres = s->avctx->lowres; + const int op_index = FFMIN(lowres-1+s->chroma_x_shift, 2); + const int block_s = 8>>lowres; + const int s_mask = (2 << lowres) - 1; + const int h_edge_pos = s->h_edge_pos >> lowres; + const int v_edge_pos = s->v_edge_pos >> lowres; + linesize = s->current_picture.f.linesize[0] << field_based; + uvlinesize = s->current_picture.f.linesize[1] << field_based; + + // FIXME obviously not perfect but qpel will not work in lowres anyway + if (s->quarter_sample) { + motion_x /= 2; + motion_y /= 2; + } + + if(field_based){ + motion_y += (bottom_field - field_select)*((1 << lowres)-1); + } + + sx = motion_x & s_mask; + sy = motion_y & s_mask; + src_x = s->mb_x * 2 * block_s + (motion_x >> lowres + 1); + src_y = (mb_y * 2 * block_s >> field_based) + (motion_y >> lowres + 1); + + if (s->out_format == FMT_H263) { + uvsx = ((motion_x >> 1) & s_mask) | (sx & 1); + uvsy = ((motion_y >> 1) & s_mask) | (sy & 1); + uvsrc_x = src_x >> 1; + uvsrc_y = src_y >> 1; + } else if (s->out_format == FMT_H261) { + // even chroma mv's are full pel in H261 + mx = motion_x / 4; + my = motion_y / 4; + uvsx = (2 * mx) & s_mask; + uvsy = (2 * my) & s_mask; + uvsrc_x = s->mb_x * block_s + (mx >> lowres); + uvsrc_y = mb_y * block_s + (my >> lowres); + } else { + if(s->chroma_y_shift){ + mx = motion_x / 2; + my = motion_y / 2; + uvsx = mx & s_mask; + uvsy = my & s_mask; + uvsrc_x = s->mb_x * block_s + (mx >> lowres + 1); + uvsrc_y = (mb_y * block_s >> field_based) + (my >> lowres + 1); + } else { + if(s->chroma_x_shift){ + //Chroma422 + mx = motion_x / 2; + uvsx = mx & s_mask; + uvsy = motion_y & s_mask; + uvsrc_y = src_y; + uvsrc_x = s->mb_x*block_s + (mx >> (lowres+1)); + } else { + //Chroma444 + uvsx = motion_x & s_mask; + uvsy = motion_y & s_mask; + uvsrc_x = src_x; + uvsrc_y = src_y; + } + } + } + + ptr_y = ref_picture[0] + src_y * linesize + src_x; + ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x; + ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x; + + if ((unsigned) src_x > FFMAX( h_edge_pos - (!!sx) - 2 * block_s, 0) || + (unsigned) src_y > FFMAX((v_edge_pos >> field_based) - (!!sy) - h, 0)) { + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y, + linesize >> field_based, 17, 17 + field_based, + src_x, src_y << field_based, h_edge_pos, + v_edge_pos); + ptr_y = s->edge_emu_buffer; + if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) { + uint8_t *uvbuf = s->edge_emu_buffer + 18 * s->linesize; + s->vdsp.emulated_edge_mc(uvbuf , ptr_cb, uvlinesize >> field_based, 9, + 9 + field_based, + uvsrc_x, uvsrc_y << field_based, + h_edge_pos >> 1, v_edge_pos >> 1); + s->vdsp.emulated_edge_mc(uvbuf + 16, ptr_cr, uvlinesize >> field_based, 9, + 9 + field_based, + uvsrc_x, uvsrc_y << field_based, + h_edge_pos >> 1, v_edge_pos >> 1); + ptr_cb = uvbuf; + ptr_cr = uvbuf + 16; + } + } + + // FIXME use this for field pix too instead of the obnoxious hack which changes picture.f.data + if (bottom_field) { + dest_y += s->linesize; + dest_cb += s->uvlinesize; + dest_cr += s->uvlinesize; + } + + if (field_select) { + ptr_y += s->linesize; + ptr_cb += s->uvlinesize; + ptr_cr += s->uvlinesize; + } + + sx = (sx << 2) >> lowres; + sy = (sy << 2) >> lowres; + pix_op[lowres - 1](dest_y, ptr_y, linesize, h, sx, sy); + + if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) { + uvsx = (uvsx << 2) >> lowres; + uvsy = (uvsy << 2) >> lowres; + if (h >> s->chroma_y_shift) { + pix_op[op_index](dest_cb, ptr_cb, uvlinesize, h >> s->chroma_y_shift, uvsx, uvsy); + pix_op[op_index](dest_cr, ptr_cr, uvlinesize, h >> s->chroma_y_shift, uvsx, uvsy); + } + } + // FIXME h261 lowres loop filter +} + +static inline void chroma_4mv_motion_lowres(MpegEncContext *s, + uint8_t *dest_cb, uint8_t *dest_cr, + uint8_t **ref_picture, + h264_chroma_mc_func * pix_op, + int mx, int my) +{ + const int lowres = s->avctx->lowres; + const int op_index = FFMIN(lowres, 2); + const int block_s = 8 >> lowres; + const int s_mask = (2 << lowres) - 1; + const int h_edge_pos = s->h_edge_pos >> lowres + 1; + const int v_edge_pos = s->v_edge_pos >> lowres + 1; + int emu = 0, src_x, src_y, offset, sx, sy; + uint8_t *ptr; + + if (s->quarter_sample) { + mx /= 2; + my /= 2; + } + + /* In case of 8X8, we construct a single chroma motion vector + with a special rounding */ + mx = ff_h263_round_chroma(mx); + my = ff_h263_round_chroma(my); + + sx = mx & s_mask; + sy = my & s_mask; + src_x = s->mb_x * block_s + (mx >> lowres + 1); + src_y = s->mb_y * block_s + (my >> lowres + 1); + + offset = src_y * s->uvlinesize + src_x; + ptr = ref_picture[1] + offset; + if (s->flags & CODEC_FLAG_EMU_EDGE) { + if ((unsigned) src_x > FFMAX(h_edge_pos - (!!sx) - block_s, 0) || + (unsigned) src_y > FFMAX(v_edge_pos - (!!sy) - block_s, 0)) { + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, + 9, 9, src_x, src_y, h_edge_pos, v_edge_pos); + ptr = s->edge_emu_buffer; + emu = 1; + } + } + sx = (sx << 2) >> lowres; + sy = (sy << 2) >> lowres; + pix_op[op_index](dest_cb, ptr, s->uvlinesize, block_s, sx, sy); + + ptr = ref_picture[2] + offset; + if (emu) { + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9, + src_x, src_y, h_edge_pos, v_edge_pos); + ptr = s->edge_emu_buffer; + } + pix_op[op_index](dest_cr, ptr, s->uvlinesize, block_s, sx, sy); +} + +/** + * motion compensation of a single macroblock + * @param s context + * @param dest_y luma destination pointer + * @param dest_cb chroma cb/u destination pointer + * @param dest_cr chroma cr/v destination pointer + * @param dir direction (0->forward, 1->backward) + * @param ref_picture array[3] of pointers to the 3 planes of the reference picture + * @param pix_op halfpel motion compensation function (average or put normally) + * the motion vectors are taken from s->mv and the MV type from s->mv_type + */ +static inline void MPV_motion_lowres(MpegEncContext *s, + uint8_t *dest_y, uint8_t *dest_cb, + uint8_t *dest_cr, + int dir, uint8_t **ref_picture, + h264_chroma_mc_func *pix_op) +{ + int mx, my; + int mb_x, mb_y, i; + const int lowres = s->avctx->lowres; + const int block_s = 8 >>lowres; + + mb_x = s->mb_x; + mb_y = s->mb_y; + + switch (s->mv_type) { + case MV_TYPE_16X16: + mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, + 0, 0, 0, + ref_picture, pix_op, + s->mv[dir][0][0], s->mv[dir][0][1], + 2 * block_s, mb_y); + break; + case MV_TYPE_8X8: + mx = 0; + my = 0; + for (i = 0; i < 4; i++) { + hpel_motion_lowres(s, dest_y + ((i & 1) + (i >> 1) * + s->linesize) * block_s, + ref_picture[0], 0, 0, + (2 * mb_x + (i & 1)) * block_s, + (2 * mb_y + (i >> 1)) * block_s, + s->width, s->height, s->linesize, + s->h_edge_pos >> lowres, s->v_edge_pos >> lowres, + block_s, block_s, pix_op, + s->mv[dir][i][0], s->mv[dir][i][1]); + + mx += s->mv[dir][i][0]; + my += s->mv[dir][i][1]; + } + + if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) + chroma_4mv_motion_lowres(s, dest_cb, dest_cr, ref_picture, + pix_op, mx, my); + break; + case MV_TYPE_FIELD: + if (s->picture_structure == PICT_FRAME) { + /* top field */ + mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, + 1, 0, s->field_select[dir][0], + ref_picture, pix_op, + s->mv[dir][0][0], s->mv[dir][0][1], + block_s, mb_y); + /* bottom field */ + mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, + 1, 1, s->field_select[dir][1], + ref_picture, pix_op, + s->mv[dir][1][0], s->mv[dir][1][1], + block_s, mb_y); + } else { + if (s->picture_structure != s->field_select[dir][0] + 1 && + s->pict_type != AV_PICTURE_TYPE_B && !s->first_field) { + ref_picture = s->current_picture_ptr->f.data; + + } + mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, + 0, 0, s->field_select[dir][0], + ref_picture, pix_op, + s->mv[dir][0][0], + s->mv[dir][0][1], 2 * block_s, mb_y >> 1); + } + break; + case MV_TYPE_16X8: + for (i = 0; i < 2; i++) { + uint8_t **ref2picture; + + if (s->picture_structure == s->field_select[dir][i] + 1 || + s->pict_type == AV_PICTURE_TYPE_B || s->first_field) { + ref2picture = ref_picture; + } else { + ref2picture = s->current_picture_ptr->f.data; + } + + mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, + 0, 0, s->field_select[dir][i], + ref2picture, pix_op, + s->mv[dir][i][0], s->mv[dir][i][1] + + 2 * block_s * i, block_s, mb_y >> 1); + + dest_y += 2 * block_s * s->linesize; + dest_cb += (2 * block_s >> s->chroma_y_shift) * s->uvlinesize; + dest_cr += (2 * block_s >> s->chroma_y_shift) * s->uvlinesize; + } + break; + case MV_TYPE_DMV: + if (s->picture_structure == PICT_FRAME) { + for (i = 0; i < 2; i++) { + int j; + for (j = 0; j < 2; j++) { + mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, + 1, j, j ^ i, + ref_picture, pix_op, + s->mv[dir][2 * i + j][0], + s->mv[dir][2 * i + j][1], + block_s, mb_y); + } + pix_op = s->dsp.avg_h264_chroma_pixels_tab; + } + } else { + for (i = 0; i < 2; i++) { + mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, + 0, 0, s->picture_structure != i + 1, + ref_picture, pix_op, + s->mv[dir][2 * i][0],s->mv[dir][2 * i][1], + 2 * block_s, mb_y >> 1); + + // after put we make avg of the same block + pix_op = s->dsp.avg_h264_chroma_pixels_tab; + + // opposite parity is always in the same + // frame if this is second field + if (!s->first_field) { + ref_picture = s->current_picture_ptr->f.data; + } + } + } + break; + default: + av_assert2(0); + } +} + /** * find the lowest MB row referenced in the MVs */ @@ -2137,7 +2504,7 @@ void ff_clean_intra_table_entries(MpegEncContext *s) */ static av_always_inline void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64], - int is_mpeg12) + int lowres_flag, int is_mpeg12) { const int mb_xy = s->mb_y * s->mb_stride + s->mb_x; if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration){ @@ -2182,8 +2549,8 @@ void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64], qpel_mc_func (*op_qpix)[16]; const int linesize = s->current_picture.f.linesize[0]; //not s->linesize as this would be wrong for field pics const int uvlinesize = s->current_picture.f.linesize[1]; - const int readable= s->pict_type != AV_PICTURE_TYPE_B || s->encoding || s->avctx->draw_horiz_band; - const int block_size = 8; + const int readable= s->pict_type != AV_PICTURE_TYPE_B || s->encoding || s->avctx->draw_horiz_band || lowres_flag; + const int block_size= lowres_flag ? 8>>s->avctx->lowres : 8; /* avoid copy if macroblock skipped in last frame too */ /* skip only during decoding as we might trash the buffers during encoding a bit */ @@ -2192,7 +2559,7 @@ void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64], if (s->mb_skipped) { s->mb_skipped= 0; - assert(s->pict_type!=AV_PICTURE_TYPE_I); + av_assert2(s->pict_type!=AV_PICTURE_TYPE_I); *mbskip_ptr = 1; } else if(!s->current_picture.f.reference) { *mbskip_ptr = 1; @@ -2232,19 +2599,31 @@ void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64], } } - op_qpix= s->me.qpel_put; - if ((!s->no_rounding) || s->pict_type==AV_PICTURE_TYPE_B){ - op_pix = s->dsp.put_pixels_tab; + if(lowres_flag){ + h264_chroma_mc_func *op_pix = s->dsp.put_h264_chroma_pixels_tab; + + if (s->mv_dir & MV_DIR_FORWARD) { + MPV_motion_lowres(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.f.data, op_pix); + op_pix = s->dsp.avg_h264_chroma_pixels_tab; + } + if (s->mv_dir & MV_DIR_BACKWARD) { + MPV_motion_lowres(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.f.data, op_pix); + } }else{ - op_pix = s->dsp.put_no_rnd_pixels_tab; - } - if (s->mv_dir & MV_DIR_FORWARD) { - ff_MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.f.data, op_pix, op_qpix); - op_pix = s->dsp.avg_pixels_tab; - op_qpix= s->me.qpel_avg; - } - if (s->mv_dir & MV_DIR_BACKWARD) { - ff_MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.f.data, op_pix, op_qpix); + op_qpix= s->me.qpel_put; + if ((!s->no_rounding) || s->pict_type==AV_PICTURE_TYPE_B){ + op_pix = s->dsp.put_pixels_tab; + }else{ + op_pix = s->dsp.put_no_rnd_pixels_tab; + } + if (s->mv_dir & MV_DIR_FORWARD) { + ff_MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.f.data, op_pix, op_qpix); + op_pix = s->dsp.avg_pixels_tab; + op_qpix= s->me.qpel_avg; + } + if (s->mv_dir & MV_DIR_BACKWARD) { + ff_MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.f.data, op_pix, op_qpix); + } } } @@ -2290,17 +2669,17 @@ void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64], }else{ //chroma422 dct_linesize = uvlinesize << s->interlaced_dct; - dct_offset = s->interlaced_dct ? uvlinesize : uvlinesize * 8; + dct_offset = s->interlaced_dct ? uvlinesize : uvlinesize*block_size; add_dct(s, block[4], 4, dest_cb, dct_linesize); add_dct(s, block[5], 5, dest_cr, dct_linesize); add_dct(s, block[6], 6, dest_cb+dct_offset, dct_linesize); add_dct(s, block[7], 7, dest_cr+dct_offset, dct_linesize); if(!s->chroma_x_shift){//Chroma444 - add_dct(s, block[8], 8, dest_cb+8, dct_linesize); - add_dct(s, block[9], 9, dest_cr+8, dct_linesize); - add_dct(s, block[10], 10, dest_cb+8+dct_offset, dct_linesize); - add_dct(s, block[11], 11, dest_cr+8+dct_offset, dct_linesize); + add_dct(s, block[8], 8, dest_cb+block_size, dct_linesize); + add_dct(s, block[9], 9, dest_cr+block_size, dct_linesize); + add_dct(s, block[10], 10, dest_cb+block_size+dct_offset, dct_linesize); + add_dct(s, block[11], 11, dest_cr+block_size+dct_offset, dct_linesize); } } }//fi gray @@ -2342,17 +2721,17 @@ void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64], }else{ dct_linesize = uvlinesize << s->interlaced_dct; - dct_offset = s->interlaced_dct ? uvlinesize : uvlinesize * 8; + dct_offset = s->interlaced_dct? uvlinesize : uvlinesize*block_size; s->dsp.idct_put(dest_cb, dct_linesize, block[4]); s->dsp.idct_put(dest_cr, dct_linesize, block[5]); s->dsp.idct_put(dest_cb + dct_offset, dct_linesize, block[6]); s->dsp.idct_put(dest_cr + dct_offset, dct_linesize, block[7]); if(!s->chroma_x_shift){//Chroma444 - s->dsp.idct_put(dest_cb + 8, dct_linesize, block[8]); - s->dsp.idct_put(dest_cr + 8, dct_linesize, block[9]); - s->dsp.idct_put(dest_cb + 8 + dct_offset, dct_linesize, block[10]); - s->dsp.idct_put(dest_cr + 8 + dct_offset, dct_linesize, block[11]); + s->dsp.idct_put(dest_cb + block_size, dct_linesize, block[8]); + s->dsp.idct_put(dest_cr + block_size, dct_linesize, block[9]); + s->dsp.idct_put(dest_cb + block_size + dct_offset, dct_linesize, block[10]); + s->dsp.idct_put(dest_cr + block_size + dct_offset, dct_linesize, block[11]); } } }//gray @@ -2370,10 +2749,12 @@ skip_idct: void ff_MPV_decode_mb(MpegEncContext *s, DCTELEM block[12][64]){ #if !CONFIG_SMALL if(s->out_format == FMT_MPEG1) { - MPV_decode_mb_internal(s, block, 1); + if(s->avctx->lowres) MPV_decode_mb_internal(s, block, 1, 1); + else MPV_decode_mb_internal(s, block, 0, 1); } else #endif - MPV_decode_mb_internal(s, block, 0); + if(s->avctx->lowres) MPV_decode_mb_internal(s, block, 1, 0); + else MPV_decode_mb_internal(s, block, 0, 0); } /** @@ -2449,7 +2830,7 @@ void ff_draw_horiz_band(MpegEncContext *s, int y, int h){ void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename const int linesize = s->current_picture.f.linesize[0]; //not s->linesize as this would be wrong for field pics const int uvlinesize = s->current_picture.f.linesize[1]; - const int mb_size= 4; + const int mb_size= 4 - s->avctx->lowres; s->block_index[0]= s->b8_stride*(s->mb_y*2 ) - 2 + s->mb_x*2; s->block_index[1]= s->b8_stride*(s->mb_y*2 ) - 1 + s->mb_x*2; @@ -2473,7 +2854,7 @@ void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename s->dest[0] += (s->mb_y>>1) * linesize << mb_size; s->dest[1] += (s->mb_y>>1) * uvlinesize << (mb_size - s->chroma_y_shift); s->dest[2] += (s->mb_y>>1) * uvlinesize << (mb_size - s->chroma_y_shift); - assert((s->mb_y&1) == (s->picture_structure == PICT_BOTTOM_FIELD)); + av_assert1((s->mb_y&1) == (s->picture_structure == PICT_BOTTOM_FIELD)); } } } @@ -2494,6 +2875,7 @@ void ff_mpeg_flush(AVCodecContext *avctx){ s->current_picture_ptr = s->last_picture_ptr = s->next_picture_ptr = NULL; s->mb_x= s->mb_y= 0; + s->closed_gop= 0; s->parse_context.state= -1; s->parse_context.frame_start_found= 0; @@ -2513,10 +2895,7 @@ static void dct_unquantize_mpeg1_intra_c(MpegEncContext *s, nCoeffs= s->block_last_index[n]; - if (n < 4) - block[0] = block[0] * s->y_dc_scale; - else - block[0] = block[0] * s->c_dc_scale; + block[0] *= n < 4 ? s->y_dc_scale : s->c_dc_scale; /* XXX: only mpeg1 */ quant_matrix = s->intra_matrix; for(i=1;i<=nCoeffs;i++) { @@ -2575,10 +2954,7 @@ static void dct_unquantize_mpeg2_intra_c(MpegEncContext *s, if(s->alternate_scan) nCoeffs= 63; else nCoeffs= s->block_last_index[n]; - if (n < 4) - block[0] = block[0] * s->y_dc_scale; - else - block[0] = block[0] * s->c_dc_scale; + block[0] *= n < 4 ? s->y_dc_scale : s->c_dc_scale; quant_matrix = s->intra_matrix; for(i=1;i<=nCoeffs;i++) { int j= s->intra_scantable.permutated[i]; @@ -2606,10 +2982,8 @@ static void dct_unquantize_mpeg2_intra_bitexact(MpegEncContext *s, if(s->alternate_scan) nCoeffs= 63; else nCoeffs= s->block_last_index[n]; - if (n < 4) - block[0] = block[0] * s->y_dc_scale; - else - block[0] = block[0] * s->c_dc_scale; + block[0] *= n < 4 ? s->y_dc_scale : s->c_dc_scale; + sum += block[0]; quant_matrix = s->intra_matrix; for(i=1;i<=nCoeffs;i++) { int j= s->intra_scantable.permutated[i]; @@ -2671,10 +3045,7 @@ static void dct_unquantize_h263_intra_c(MpegEncContext *s, qmul = qscale << 1; if (!s->h263_aic) { - if (n < 4) - block[0] = block[0] * s->y_dc_scale; - else - block[0] = block[0] * s->c_dc_scale; + block[0] *= n < 4 ? s->y_dc_scale : s->c_dc_scale; qadd = (qscale - 1) | 1; }else{ qadd = 0; |