History

h264: fully support cropping.

Based on a patch by Vittorio Giovara <vittorio.giovara@gmail.com> Fixes Bug 378.

Anton Khirnov committed 13 years ago

Commit 5e83d9a1 parent a7f46587 files · +108 −39Browse files

Unified · Split

7 files
  1. doc/APIchanges +3 −0
  2. libavcodec/avcodec.h +5 −0
  3. libavcodec/h264.c +68 −19
  4. libavcodec/h264.h +3 −0
  5. libavcodec/h264_ps.c +27 −19
  6. libavcodec/options_table.h +1 −0
  7. libavcodec/version.h +1 −1
doc/APIchanges+3−0
@@ -13,6 +13,9 @@ libavutil: 2012-10-22 · 12 unmodified lines
13 13
14API changes, most recent first:14API changes, most recent first:
15 15
162013-03-xx - xxxxxxx - lavc 55.2.0 - avcodec.h
17 Add CODEC_FLAG_UNALIGNED to allow decoders to produce unaligned output.
18
162013-xx-xx - lavfi 3.8.0192013-xx-xx - lavfi 3.8.0
17 Move all content from avfiltergraph.h to avfilter.h. Deprecate20 Move all content from avfiltergraph.h to avfilter.h. Deprecate
18 avfilterhraph.h, user applications should include just avfilter.h21 avfilterhraph.h, user applications should include just avfilter.h
libavcodec/avcodec.h+5−0
@@ -609,6 +609,11 @@ typedef struct RcOverride{ · 608 unmodified lines
609 Note: Not everything is supported yet.609 Note: Not everything is supported yet.
610*/610*/
611 611
612/**
613 * Allow decoders to produce frames with data planes that are not aligned
614 * to CPU requirements (e.g. due to cropping).
615 */
616#define CODEC_FLAG_UNALIGNED 0x0001
612#define CODEC_FLAG_QSCALE 0x0002 ///< Use fixed qscale.617#define CODEC_FLAG_QSCALE 0x0002 ///< Use fixed qscale.
613#define CODEC_FLAG_4MV 0x0004 ///< 4 MV per MB allowed / advanced prediction for H.263.618#define CODEC_FLAG_4MV 0x0004 ///< 4 MV per MB allowed / advanced prediction for H.263.
614#define CODEC_FLAG_QPEL 0x0010 ///< Use qpel MC.619#define CODEC_FLAG_QPEL 0x0010 ///< Use qpel MC.
libavcodec/h264.c+68−19
@@ -1426,9 +1426,6 @@ av_cold int ff_h264_decode_init(AVCodecContext *avctx) · 1425 unmodified lines
1426 1426
1427 h->avctx = avctx;1427 h->avctx = avctx;
1428 1428
1429 h->width = h->avctx->width;
1430 h->height = h->avctx->height;
1431
1432 h->bit_depth_luma = 8;1429 h->bit_depth_luma = 8;
1433 h->chroma_format_idc = 1;1430 h->chroma_format_idc = 1;
1434 1431
@@ -2978,14 +2975,49 @@ static enum AVPixelFormat get_pixel_format(H264Context *h) · 1543 unmodified lines
2978 }2975 }
2979}2976}
2980 2977
2978/* export coded and cropped frame dimensions to AVCodecContext */
2979static int init_dimensions(H264Context *h)
2980{
2981 int width = h->width - (h->sps.crop_right + h->sps.crop_left);
2982 int height = h->height - (h->sps.crop_top + h->sps.crop_bottom);
2983
2984 /* handle container cropping */
2985 if (!h->sps.crop &&
2986 FFALIGN(h->avctx->width, 16) == h->width &&
2987 FFALIGN(h->avctx->height, 16) == h->height) {
2988 width = h->avctx->width;
2989 height = h->avctx->height;
2990 }
2991
2992 if (width <= 0 || height <= 0) {
2993 av_log(h->avctx, AV_LOG_ERROR, "Invalid cropped dimensions: %dx%d.\n",
2994 width, height);
2995 if (h->avctx->err_recognition & AV_EF_EXPLODE)
2996 return AVERROR_INVALIDDATA;
2997
2998 av_log(h->avctx, AV_LOG_WARNING, "Ignoring cropping information.\n");
2999 h->sps.crop_bottom = h->sps.crop_top = h->sps.crop_right = h->sps.crop_left = 0;
3000 h->sps.crop = 0;
3001
3002 width = h->width;
3003 height = h->height;
3004 }
3005
3006 h->avctx->coded_width = h->width;
3007 h->avctx->coded_height = h->height;
3008 h->avctx->width = width;
3009 h->avctx->height = height;
3010
3011 return 0;
3012}
3013
2981static int h264_slice_header_init(H264Context *h, int reinit)3014static int h264_slice_header_init(H264Context *h, int reinit)
2982{3015{
2983 int nb_slices = (HAVE_THREADS &&3016 int nb_slices = (HAVE_THREADS &&
2984 h->avctx->active_thread_type & FF_THREAD_SLICE) ?3017 h->avctx->active_thread_type & FF_THREAD_SLICE) ?
2985 h->avctx->thread_count : 1;3018 h->avctx->thread_count : 1;
2986 int i;3019 int i, ret;
2987 3020
2988 avcodec_set_dimensions(h->avctx, h->width, h->height);
2989 h->avctx->sample_aspect_ratio = h->sps.sar;3021 h->avctx->sample_aspect_ratio = h->sps.sar;
2990 av_assert0(h->avctx->sample_aspect_ratio.den);3022 av_assert0(h->avctx->sample_aspect_ratio.den);
2991 av_pix_fmt_get_chroma_sub_sample(h->avctx->pix_fmt,3023 av_pix_fmt_get_chroma_sub_sample(h->avctx->pix_fmt,
@@ -3196,17 +3228,12 @@ static int decode_slice_header(H264Context *h, H264Context *h0) · 204 unmodified lines
3196 3228
3197 h->chroma_y_shift = h->sps.chroma_format_idc <= 1; // 400 uses yuv420p3229 h->chroma_y_shift = h->sps.chroma_format_idc <= 1; // 400 uses yuv420p
3198 3230
3199 h->width = 16 * h->mb_width - (2 >> CHROMA444(h)) * FFMIN(h->sps.crop_right, (8 << CHROMA444(h)) - 1);3231 h->width = 16 * h->mb_width;
3200 if (h->sps.frame_mbs_only_flag)3232 h->height = 16 * h->mb_height;
3201 h->height = 16 * h->mb_height - (1 << h->chroma_y_shift) * FFMIN(h->sps.crop_bottom, (16 >> h->chroma_y_shift) - 1);
3202 else
3203 h->height = 16 * h->mb_height - (2 << h->chroma_y_shift) * FFMIN(h->sps.crop_bottom, (16 >> h->chroma_y_shift) - 1);
3204 3233
3205 if (FFALIGN(h->avctx->width, 16) == h->width &&3234 ret = init_dimensions(h);
3206 FFALIGN(h->avctx->height, 16) == h->height) {3235 if (ret < 0)
3207 h->width = h->avctx->width;3236 return ret;
3208 h->height = h->avctx->height;
3209 }
3210 3237
3211 if (h->sps.video_signal_type_present_flag) {3238 if (h->sps.video_signal_type_present_flag) {
3212 h->avctx->color_range = h->sps.full_range ? AVCOL_RANGE_JPEG3239 h->avctx->color_range = h->sps.full_range ? AVCOL_RANGE_JPEG
@@ -3221,8 +3248,8 @@ static int decode_slice_header(H264Context *h, H264Context *h0) · 8 unmodified lines
3221 }3248 }
3222 3249
3223 if (h->context_initialized &&3250 if (h->context_initialized &&
3224 (h->width != h->avctx->width ||3251 (h->width != h->avctx->coded_width ||
3225 h->height != h->avctx->height ||3252 h->height != h->avctx->coded_height ||
3226 needs_reinit)) {3253 needs_reinit)) {
3227 3254
3228 if (h != h0) {3255 if (h != h0) {
@@ -4611,6 +4638,26 @@ static int get_consumed_bytes(int pos, int buf_size) · 1382 unmodified lines
4611 return pos;4638 return pos;
4612}4639}
4613 4640
4641static int output_frame(H264Context *h, AVFrame *dst, AVFrame *src)
4642{
4643 int i;
4644 int ret = av_frame_ref(dst, src);
4645 if (ret < 0)
4646 return ret;
4647
4648 if (!h->sps.crop)
4649 return 0;
4650
4651 for (i = 0; i < 3; i++) {
4652 int hshift = (i > 0) ? h->chroma_x_shift : 0;
4653 int vshift = (i > 0) ? h->chroma_y_shift : 0;
4654 int off = ((h->sps.crop_left >> hshift) << h->pixel_shift) +
4655 (h->sps.crop_top >> vshift) * dst->linesize[i];
4656 dst->data[i] += off;
4657 }
4658 return 0;
4659}
4660
4614static int decode_frame(AVCodecContext *avctx, void *data,4661static int decode_frame(AVCodecContext *avctx, void *data,
4615 int *got_frame, AVPacket *avpkt)4662 int *got_frame, AVPacket *avpkt)
4616{4663{
@@ -4648,7 +4695,8 @@ out: · 31 unmodified lines
4648 h->delayed_pic[i] = h->delayed_pic[i + 1];4695 h->delayed_pic[i] = h->delayed_pic[i + 1];
4649 4696
4650 if (out) {4697 if (out) {
4651 if ((ret = av_frame_ref(pict, &out->f)) < 0)4698 ret = output_frame(h, pict, &out->f);
4699 if (ret < 0)
4652 return ret;4700 return ret;
4653 *got_frame = 1;4701 *got_frame = 1;
4654 }4702 }
@@ -4683,7 +4731,8 @@ out: · 28 unmodified lines
4683 /* Wait for second field. */4731 /* Wait for second field. */
4684 *got_frame = 0;4732 *got_frame = 0;
4685 } else {4733 } else {
4686 if ((ret = av_frame_ref(pict, &h->next_output_pic->f)) < 0)4734 ret = output_frame(h, pict, &h->next_output_pic->f);
4735 if (ret < 0)
4687 return ret;4736 return ret;
4688 *got_frame = 1;4737 *got_frame = 1;
4689 }4738 }
libavcodec/h264.h+3−0
@@ -164,6 +164,8 @@ typedef struct SPS { · 163 unmodified lines
164 int mb_aff; ///< mb_adaptive_frame_field_flag164 int mb_aff; ///< mb_adaptive_frame_field_flag
165 int direct_8x8_inference_flag;165 int direct_8x8_inference_flag;
166 int crop; ///< frame_cropping_flag166 int crop; ///< frame_cropping_flag
167
168 /* those 4 are already in luma samples */
167 unsigned int crop_left; ///< frame_cropping_rect_left_offset169 unsigned int crop_left; ///< frame_cropping_rect_left_offset
168 unsigned int crop_right; ///< frame_cropping_rect_right_offset170 unsigned int crop_right; ///< frame_cropping_rect_right_offset
169 unsigned int crop_top; ///< frame_cropping_rect_top_offset171 unsigned int crop_top; ///< frame_cropping_rect_top_offset
@@ -272,6 +274,7 @@ typedef struct H264Context { · 102 unmodified lines
272 274
273 int qp_thresh; ///< QP threshold to skip loopfilter275 int qp_thresh; ///< QP threshold to skip loopfilter
274 276
277 /* coded dimensions -- 16 * mb w/h */
275 int width, height;278 int width, height;
276 int linesize, uvlinesize;279 int linesize, uvlinesize;
277 int chroma_x_shift, chroma_y_shift;280 int chroma_x_shift, chroma_y_shift;
libavcodec/h264_ps.c+27−19
@@ -413,37 +413,45 @@ int ff_h264_decode_seq_parameter_set(H264Context *h){ · 412 unmodified lines
413#endif413#endif
414 sps->crop= get_bits1(&h->gb);414 sps->crop= get_bits1(&h->gb);
415 if(sps->crop){415 if(sps->crop){
416 int crop_vertical_limit = sps->chroma_format_idc & 2 ? 16 : 8;416 int crop_left = get_ue_golomb(&h->gb);
417 int crop_horizontal_limit = sps->chroma_format_idc == 3 ? 16 : 8;417 int crop_right = get_ue_golomb(&h->gb);
418 sps->crop_left = get_ue_golomb(&h->gb);418 int crop_top = get_ue_golomb(&h->gb);
419 sps->crop_right = get_ue_golomb(&h->gb);419 int crop_bottom = get_ue_golomb(&h->gb);
420 sps->crop_top = get_ue_golomb(&h->gb);420
421 sps->crop_bottom= get_ue_golomb(&h->gb);
422 if (h->avctx->flags2 & CODEC_FLAG2_IGNORE_CROP) {421 if (h->avctx->flags2 & CODEC_FLAG2_IGNORE_CROP) {
423 av_log(h->avctx, AV_LOG_DEBUG,422 av_log(h->avctx, AV_LOG_DEBUG, "discarding sps cropping, original "
424 "discarding sps cropping, "423 "values are l:%u r:%u t:%u b:%u\n", crop_left, crop_right,
425 "original values are l:%u r:%u t:%u b:%u\n",424 crop_top, crop_bottom);
426 sps->crop_left,
427 sps->crop_right,
428 sps->crop_top,
429 sps->crop_bottom);
430 425
431 sps->crop_left =426 sps->crop_left =
432 sps->crop_right =427 sps->crop_right =
433 sps->crop_top =428 sps->crop_top =
434 sps->crop_bottom = 0;429 sps->crop_bottom = 0;
435 }430 } else {
436 if(sps->crop_left || sps->crop_top){431 int vsub = (sps->chroma_format_idc == 1) ? 1 : 0;
437 av_log(h->avctx, AV_LOG_ERROR, "insane cropping not completely supported, this could look slightly wrong ...\n");432 int hsub = (sps->chroma_format_idc == 1 || sps->chroma_format_idc == 2) ? 1 : 0;
438 }433 int step_x = 1 << hsub;
439 if(sps->crop_right >= crop_horizontal_limit || sps->crop_bottom >= crop_vertical_limit){434 int step_y = (2 - sps->frame_mbs_only_flag) << vsub;
440 av_log(h->avctx, AV_LOG_ERROR, "brainfart cropping not supported, this could look slightly wrong ...\n");435
436 if (crop_left & (0x1F >> (sps->bit_depth_luma > 8)) &&
437 !(h->avctx->flags & CODEC_FLAG_UNALIGNED)) {
438 crop_left &= ~(0x1F >> (sps->bit_depth_luma > 8));
439 av_log(h->avctx, AV_LOG_WARNING, "Reducing left cropping to %d "
440 "chroma samples to preserve alignment.\n",
441 crop_left);
442 }
443
444 sps->crop_left = crop_left * step_x;
445 sps->crop_right = crop_right * step_x;
446 sps->crop_top = crop_top * step_y;
447 sps->crop_bottom = crop_bottom * step_y;
441 }448 }
442 }else{449 }else{
443 sps->crop_left =450 sps->crop_left =
444 sps->crop_right =451 sps->crop_right =
445 sps->crop_top =452 sps->crop_top =
446 sps->crop_bottom= 0;453 sps->crop_bottom= 0;
454 sps->crop = 0;
447 }455 }
448 456
449 sps->vui_parameters_present_flag= get_bits1(&h->gb);457 sps->vui_parameters_present_flag= get_bits1(&h->gb);
libavcodec/options_table.h+1−0
@@ -46,6 +46,7 @@ static const AVOption options[]={ · 45 unmodified lines
46 "to minimum/maximum bitrate. Lowering tolerance too much has an adverse effect on quality.",46 "to minimum/maximum bitrate. Lowering tolerance too much has an adverse effect on quality.",
47 OFFSET(bit_rate_tolerance), AV_OPT_TYPE_INT, {.i64 = AV_CODEC_DEFAULT_BITRATE*20 }, 1, INT_MAX, V|E},47 OFFSET(bit_rate_tolerance), AV_OPT_TYPE_INT, {.i64 = AV_CODEC_DEFAULT_BITRATE*20 }, 1, INT_MAX, V|E},
48{"flags", NULL, OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, UINT_MAX, V|A|E|D, "flags"},48{"flags", NULL, OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, UINT_MAX, V|A|E|D, "flags"},
49{"unaligned", "allow decoders to produce unaligned output", 0, AV_OPT_TYPE_CONST, { .i64 = CODEC_FLAG_UNALIGNED }, INT_MIN, INT_MAX, V | D, "flags" },
49{"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"},50{"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"},
50{"qpel", "use 1/4-pel motion compensation", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_QPEL }, INT_MIN, INT_MAX, V|E, "flags"},51{"qpel", "use 1/4-pel motion compensation", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_QPEL }, INT_MIN, INT_MAX, V|E, "flags"},
51{"loop", "use loop filter", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_LOOP_FILTER }, INT_MIN, INT_MAX, V|E, "flags"},52{"loop", "use loop filter", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_LOOP_FILTER }, INT_MIN, INT_MAX, V|E, "flags"},
libavcodec/version.h+1−1
@@ -27,7 +27,7 @@ · 26 unmodified lines
27 */27 */
28 28
29#define LIBAVCODEC_VERSION_MAJOR 5529#define LIBAVCODEC_VERSION_MAJOR 55
30#define LIBAVCODEC_VERSION_MINOR 130#define LIBAVCODEC_VERSION_MINOR 2
31#define LIBAVCODEC_VERSION_MICRO 031#define LIBAVCODEC_VERSION_MICRO 0
32 32
33#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \33#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t