* commit '5e83d9aced2fc2b2e1360452794c58aba55d497c': h264: fully support cropping. Conflicts: doc/APIchanges libavcodec/h264.c libavcodec/h264_ps.c libavcodec/options_table.h libavcodec/version.h Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n2.0
| @@ -167,6 +167,9 @@ API changes, most recent first: | |||
| 2012-03-26 - a67d9cf - lavfi 2.66.100 | |||
| Add avfilter_fill_frame_from_{audio_,}buffer_ref() functions. | |||
| 2013-03-xx - xxxxxxx - lavc 55.2.0 - avcodec.h | |||
| Add CODEC_FLAG_UNALIGNED to allow decoders to produce unaligned output. | |||
| 2013-xx-xx - lavfi 3.8.0 | |||
| Move all content from avfiltergraph.h to avfilter.h. Deprecate | |||
| avfilterhraph.h, user applications should include just avfilter.h | |||
| @@ -685,6 +685,11 @@ typedef struct RcOverride{ | |||
| Note: Not everything is supported yet. | |||
| */ | |||
| /** | |||
| * Allow decoders to produce frames with data planes that are not aligned | |||
| * to CPU requirements (e.g. due to cropping). | |||
| */ | |||
| #define CODEC_FLAG_UNALIGNED 0x0001 | |||
| #define CODEC_FLAG_QSCALE 0x0002 ///< Use fixed qscale. | |||
| #define CODEC_FLAG_4MV 0x0004 ///< 4 MV per MB allowed / advanced prediction for H.263. | |||
| #define CODEC_FLAG_QPEL 0x0010 ///< Use qpel MC. | |||
| @@ -1459,9 +1459,6 @@ av_cold int ff_h264_decode_init(AVCodecContext *avctx) | |||
| h->avctx = avctx; | |||
| h->width = h->avctx->width; | |||
| h->height = h->avctx->height; | |||
| h->bit_depth_luma = 8; | |||
| h->chroma_format_idc = 1; | |||
| @@ -3053,26 +3050,48 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) | |||
| } | |||
| } | |||
| /* export coded and cropped frame dimensions to AVCodecContext */ | |||
| static int init_dimensions(H264Context *h) | |||
| { | |||
| int width = h->width - (h->sps.crop_right + h->sps.crop_left); | |||
| int height = h->height - (h->sps.crop_top + h->sps.crop_bottom); | |||
| /* handle container cropping */ | |||
| if (!h->sps.crop && | |||
| FFALIGN(h->avctx->width, 16) == h->width && | |||
| FFALIGN(h->avctx->height, 16) == h->height) { | |||
| width = h->avctx->width; | |||
| height = h->avctx->height; | |||
| } | |||
| if (width <= 0 || height <= 0) { | |||
| av_log(h->avctx, AV_LOG_ERROR, "Invalid cropped dimensions: %dx%d.\n", | |||
| width, height); | |||
| if (h->avctx->err_recognition & AV_EF_EXPLODE) | |||
| return AVERROR_INVALIDDATA; | |||
| av_log(h->avctx, AV_LOG_WARNING, "Ignoring cropping information.\n"); | |||
| h->sps.crop_bottom = h->sps.crop_top = h->sps.crop_right = h->sps.crop_left = 0; | |||
| h->sps.crop = 0; | |||
| width = h->width; | |||
| height = h->height; | |||
| } | |||
| h->avctx->coded_width = h->width; | |||
| h->avctx->coded_height = h->height; | |||
| h->avctx->width = width; | |||
| h->avctx->height = height; | |||
| return 0; | |||
| } | |||
| static int h264_slice_header_init(H264Context *h, int reinit) | |||
| { | |||
| int nb_slices = (HAVE_THREADS && | |||
| h->avctx->active_thread_type & FF_THREAD_SLICE) ? | |||
| h->avctx->thread_count : 1; | |||
| int i; | |||
| if( FFALIGN(h->avctx->width , 16 ) == h->width | |||
| && FFALIGN(h->avctx->height, 16*(2 - h->sps.frame_mbs_only_flag)) == h->height | |||
| && !h->sps.crop_right && !h->sps.crop_bottom | |||
| && (h->avctx->width != h->width || h->avctx->height && h->height) | |||
| ) { | |||
| av_log(h->avctx, AV_LOG_DEBUG, "Using externally provided dimensions\n"); | |||
| h->avctx->coded_width = h->width; | |||
| h->avctx->coded_height = h->height; | |||
| } else{ | |||
| avcodec_set_dimensions(h->avctx, h->width, h->height); | |||
| h->avctx->width -= (2>>CHROMA444(h))*FFMIN(h->sps.crop_right, (8<<CHROMA444(h))-1); | |||
| h->avctx->height -= (1<<h->chroma_y_shift)*FFMIN(h->sps.crop_bottom, (16>>h->chroma_y_shift)-1) * (2 - h->sps.frame_mbs_only_flag); | |||
| } | |||
| int i, ret; | |||
| h->avctx->sample_aspect_ratio = h->sps.sar; | |||
| av_assert0(h->avctx->sample_aspect_ratio.den); | |||
| @@ -3298,6 +3317,10 @@ static int decode_slice_header(H264Context *h, H264Context *h0) | |||
| h->width = 16 * h->mb_width; | |||
| h->height = 16 * h->mb_height; | |||
| ret = init_dimensions(h); | |||
| if (ret < 0) | |||
| return ret; | |||
| if (h->sps.video_signal_type_present_flag) { | |||
| h->avctx->color_range = h->sps.full_range>0 ? AVCOL_RANGE_JPEG | |||
| : AVCOL_RANGE_MPEG; | |||
| @@ -3311,9 +3334,10 @@ static int decode_slice_header(H264Context *h, H264Context *h0) | |||
| } | |||
| if (h->context_initialized && | |||
| ( | |||
| needs_reinit || | |||
| must_reinit)) { | |||
| (h->width != h->avctx->coded_width || | |||
| h->height != h->avctx->coded_height || | |||
| must_reinit || | |||
| needs_reinit)) { | |||
| if (h != h0) { | |||
| av_log(h->avctx, AV_LOG_ERROR, "changing width/height on " | |||
| @@ -4817,6 +4841,26 @@ static int get_consumed_bytes(int pos, int buf_size) | |||
| return pos; | |||
| } | |||
| static int output_frame(H264Context *h, AVFrame *dst, AVFrame *src) | |||
| { | |||
| int i; | |||
| int ret = av_frame_ref(dst, src); | |||
| if (ret < 0) | |||
| return ret; | |||
| if (!h->sps.crop) | |||
| return 0; | |||
| for (i = 0; i < 3; i++) { | |||
| int hshift = (i > 0) ? h->chroma_x_shift : 0; | |||
| int vshift = (i > 0) ? h->chroma_y_shift : 0; | |||
| int off = ((h->sps.crop_left >> hshift) << h->pixel_shift) + | |||
| (h->sps.crop_top >> vshift) * dst->linesize[i]; | |||
| dst->data[i] += off; | |||
| } | |||
| return 0; | |||
| } | |||
| static int decode_frame(AVCodecContext *avctx, void *data, | |||
| int *got_frame, AVPacket *avpkt) | |||
| { | |||
| @@ -4856,7 +4900,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, | |||
| if (out) { | |||
| out->reference &= ~DELAYED_PIC_REF; | |||
| if ((ret = av_frame_ref(pict, &out->f)) < 0) | |||
| ret = output_frame(h, pict, &out->f); | |||
| if (ret < 0) | |||
| return ret; | |||
| *got_frame = 1; | |||
| } | |||
| @@ -4913,7 +4958,8 @@ not_extra: | |||
| /* Wait for second field. */ | |||
| *got_frame = 0; | |||
| if (h->next_output_pic && (h->next_output_pic->sync || h->sync>1)) { | |||
| if ((ret = av_frame_ref(pict, &h->next_output_pic->f)) < 0) | |||
| ret = output_frame(h, pict, &h->next_output_pic->f); | |||
| if (ret < 0) | |||
| return ret; | |||
| *got_frame = 1; | |||
| if (CONFIG_MPEGVIDEO) { | |||
| @@ -168,6 +168,8 @@ typedef struct SPS { | |||
| int mb_aff; ///< mb_adaptive_frame_field_flag | |||
| int direct_8x8_inference_flag; | |||
| int crop; ///< frame_cropping_flag | |||
| /* those 4 are already in luma samples */ | |||
| unsigned int crop_left; ///< frame_cropping_rect_left_offset | |||
| unsigned int crop_right; ///< frame_cropping_rect_right_offset | |||
| unsigned int crop_top; ///< frame_cropping_rect_top_offset | |||
| @@ -276,6 +278,7 @@ typedef struct H264Context { | |||
| int qp_thresh; ///< QP threshold to skip loopfilter | |||
| /* coded dimensions -- 16 * mb w/h */ | |||
| int width, height; | |||
| int linesize, uvlinesize; | |||
| int chroma_x_shift, chroma_y_shift; | |||
| @@ -459,44 +459,45 @@ int ff_h264_decode_seq_parameter_set(H264Context *h){ | |||
| #endif | |||
| sps->crop= get_bits1(&h->gb); | |||
| if(sps->crop){ | |||
| int crop_vertical_limit = sps->chroma_format_idc & 2 ? 16 : 8; | |||
| int crop_horizontal_limit = sps->chroma_format_idc == 3 ? 16 : 8; | |||
| sps->crop_left = get_ue_golomb(&h->gb); | |||
| sps->crop_right = get_ue_golomb(&h->gb); | |||
| sps->crop_top = get_ue_golomb(&h->gb); | |||
| sps->crop_bottom= get_ue_golomb(&h->gb); | |||
| int crop_left = get_ue_golomb(&h->gb); | |||
| int crop_right = get_ue_golomb(&h->gb); | |||
| int crop_top = get_ue_golomb(&h->gb); | |||
| int crop_bottom = get_ue_golomb(&h->gb); | |||
| if (h->avctx->flags2 & CODEC_FLAG2_IGNORE_CROP) { | |||
| av_log(h->avctx, AV_LOG_DEBUG, | |||
| "discarding sps cropping, " | |||
| "original values are l:%u r:%u t:%u b:%u\n", | |||
| sps->crop_left, | |||
| sps->crop_right, | |||
| sps->crop_top, | |||
| sps->crop_bottom); | |||
| av_log(h->avctx, AV_LOG_DEBUG, "discarding sps cropping, original " | |||
| "values are l:%u r:%u t:%u b:%u\n", crop_left, crop_right, | |||
| crop_top, crop_bottom); | |||
| sps->crop_left = | |||
| sps->crop_right = | |||
| sps->crop_top = | |||
| sps->crop_bottom = 0; | |||
| } | |||
| if(sps->crop_left || sps->crop_top){ | |||
| av_log(h->avctx, AV_LOG_ERROR, "insane cropping not completely supported, this could look slightly wrong ... (left: %d, top: %d)\n", sps->crop_left, sps->crop_top); | |||
| } | |||
| if(sps->crop_right >= crop_horizontal_limit || sps->crop_bottom >= crop_vertical_limit){ | |||
| av_log(h->avctx, AV_LOG_ERROR, "brainfart cropping not supported, cropping disabled (right: %d, bottom: %d)\n", sps->crop_right, sps->crop_bottom); | |||
| /* It is very unlikely that partial cropping will make anybody happy. | |||
| * Not cropping at all fixes for example playback of Sisvel 3D streams | |||
| * in applications supporting Sisvel 3D. */ | |||
| sps->crop_left = | |||
| sps->crop_right = | |||
| sps->crop_top = | |||
| sps->crop_bottom= 0; | |||
| } else { | |||
| int vsub = (sps->chroma_format_idc == 1) ? 1 : 0; | |||
| int hsub = (sps->chroma_format_idc == 1 || sps->chroma_format_idc == 2) ? 1 : 0; | |||
| int step_x = 1 << hsub; | |||
| int step_y = (2 - sps->frame_mbs_only_flag) << vsub; | |||
| if (crop_left & (0x1F >> (sps->bit_depth_luma > 8)) && | |||
| !(h->avctx->flags & CODEC_FLAG_UNALIGNED)) { | |||
| crop_left &= ~(0x1F >> (sps->bit_depth_luma > 8)); | |||
| av_log(h->avctx, AV_LOG_WARNING, "Reducing left cropping to %d " | |||
| "chroma samples to preserve alignment.\n", | |||
| crop_left); | |||
| } | |||
| sps->crop_left = crop_left * step_x; | |||
| sps->crop_right = crop_right * step_x; | |||
| sps->crop_top = crop_top * step_y; | |||
| sps->crop_bottom = crop_bottom * step_y; | |||
| } | |||
| }else{ | |||
| sps->crop_left = | |||
| sps->crop_right = | |||
| sps->crop_top = | |||
| sps->crop_bottom= 0; | |||
| sps->crop = 0; | |||
| } | |||
| sps->vui_parameters_present_flag= get_bits1(&h->gb); | |||
| @@ -49,6 +49,7 @@ static const AVOption options[]={ | |||
| "to minimum/maximum bitrate. Lowering tolerance too much has an adverse effect on quality.", | |||
| OFFSET(bit_rate_tolerance), AV_OPT_TYPE_INT, {.i64 = AV_CODEC_DEFAULT_BITRATE*20 }, 1, INT_MAX, V|E}, | |||
| {"flags", NULL, OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, UINT_MAX, V|A|S|E|D, "flags"}, | |||
| {"unaligned", "allow decoders to produce unaligned output", 0, AV_OPT_TYPE_CONST, { .i64 = CODEC_FLAG_UNALIGNED }, INT_MIN, INT_MAX, V | D, "flags" }, | |||
| {"mv4", "use four motion vectors per macroblock (MPEG-4)", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_4MV }, INT_MIN, INT_MAX, V|E, "flags"}, | |||
| {"qpel", "use 1/4-pel motion compensation", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_QPEL }, INT_MIN, INT_MAX, V|E, "flags"}, | |||
| {"loop", "use loop filter", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_LOOP_FILTER }, INT_MIN, INT_MAX, V|E, "flags"}, | |||
| @@ -29,7 +29,7 @@ | |||
| #include "libavutil/avutil.h" | |||
| #define LIBAVCODEC_VERSION_MAJOR 55 | |||
| #define LIBAVCODEC_VERSION_MINOR 4 | |||
| #define LIBAVCODEC_VERSION_MINOR 5 | |||
| #define LIBAVCODEC_VERSION_MICRO 100 | |||
| #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | |||