1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00

Merge commit '5e83d9aced2fc2b2e1360452794c58aba55d497c'

* 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>
This commit is contained in:
Michael Niedermayer 2013-04-19 22:24:33 +02:00
commit f4b05cd841
7 changed files with 109 additions and 50 deletions

View File

@ -167,6 +167,9 @@ API changes, most recent first:
2012-03-26 - a67d9cf - lavfi 2.66.100 2012-03-26 - a67d9cf - lavfi 2.66.100
Add avfilter_fill_frame_from_{audio_,}buffer_ref() functions. 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 2013-xx-xx - lavfi 3.8.0
Move all content from avfiltergraph.h to avfilter.h. Deprecate Move all content from avfiltergraph.h to avfilter.h. Deprecate
avfilterhraph.h, user applications should include just avfilter.h avfilterhraph.h, user applications should include just avfilter.h

View File

@ -685,6 +685,11 @@ typedef struct RcOverride{
Note: Not everything is supported yet. 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_QSCALE 0x0002 ///< Use fixed qscale.
#define CODEC_FLAG_4MV 0x0004 ///< 4 MV per MB allowed / advanced prediction for H.263. #define CODEC_FLAG_4MV 0x0004 ///< 4 MV per MB allowed / advanced prediction for H.263.
#define CODEC_FLAG_QPEL 0x0010 ///< Use qpel MC. #define CODEC_FLAG_QPEL 0x0010 ///< Use qpel MC.

View File

@ -1459,9 +1459,6 @@ av_cold int ff_h264_decode_init(AVCodecContext *avctx)
h->avctx = avctx; h->avctx = avctx;
h->width = h->avctx->width;
h->height = h->avctx->height;
h->bit_depth_luma = 8; h->bit_depth_luma = 8;
h->chroma_format_idc = 1; 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) static int h264_slice_header_init(H264Context *h, int reinit)
{ {
int nb_slices = (HAVE_THREADS && int nb_slices = (HAVE_THREADS &&
h->avctx->active_thread_type & FF_THREAD_SLICE) ? h->avctx->active_thread_type & FF_THREAD_SLICE) ?
h->avctx->thread_count : 1; h->avctx->thread_count : 1;
int i; int i, ret;
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);
}
h->avctx->sample_aspect_ratio = h->sps.sar; h->avctx->sample_aspect_ratio = h->sps.sar;
av_assert0(h->avctx->sample_aspect_ratio.den); 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->width = 16 * h->mb_width;
h->height = 16 * h->mb_height; h->height = 16 * h->mb_height;
ret = init_dimensions(h);
if (ret < 0)
return ret;
if (h->sps.video_signal_type_present_flag) { if (h->sps.video_signal_type_present_flag) {
h->avctx->color_range = h->sps.full_range>0 ? AVCOL_RANGE_JPEG h->avctx->color_range = h->sps.full_range>0 ? AVCOL_RANGE_JPEG
: AVCOL_RANGE_MPEG; : AVCOL_RANGE_MPEG;
@ -3311,9 +3334,10 @@ static int decode_slice_header(H264Context *h, H264Context *h0)
} }
if (h->context_initialized && if (h->context_initialized &&
( (h->width != h->avctx->coded_width ||
needs_reinit || h->height != h->avctx->coded_height ||
must_reinit)) { must_reinit ||
needs_reinit)) {
if (h != h0) { if (h != h0) {
av_log(h->avctx, AV_LOG_ERROR, "changing width/height on " 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; 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, static int decode_frame(AVCodecContext *avctx, void *data,
int *got_frame, AVPacket *avpkt) int *got_frame, AVPacket *avpkt)
{ {
@ -4856,7 +4900,8 @@ static int decode_frame(AVCodecContext *avctx, void *data,
if (out) { if (out) {
out->reference &= ~DELAYED_PIC_REF; 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; return ret;
*got_frame = 1; *got_frame = 1;
} }
@ -4913,7 +4958,8 @@ not_extra:
/* Wait for second field. */ /* Wait for second field. */
*got_frame = 0; *got_frame = 0;
if (h->next_output_pic && (h->next_output_pic->sync || h->sync>1)) { 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; return ret;
*got_frame = 1; *got_frame = 1;
if (CONFIG_MPEGVIDEO) { if (CONFIG_MPEGVIDEO) {

View File

@ -168,6 +168,8 @@ typedef struct SPS {
int mb_aff; ///< mb_adaptive_frame_field_flag int mb_aff; ///< mb_adaptive_frame_field_flag
int direct_8x8_inference_flag; int direct_8x8_inference_flag;
int crop; ///< frame_cropping_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_left; ///< frame_cropping_rect_left_offset
unsigned int crop_right; ///< frame_cropping_rect_right_offset unsigned int crop_right; ///< frame_cropping_rect_right_offset
unsigned int crop_top; ///< frame_cropping_rect_top_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 int qp_thresh; ///< QP threshold to skip loopfilter
/* coded dimensions -- 16 * mb w/h */
int width, height; int width, height;
int linesize, uvlinesize; int linesize, uvlinesize;
int chroma_x_shift, chroma_y_shift; int chroma_x_shift, chroma_y_shift;

View File

@ -459,44 +459,45 @@ int ff_h264_decode_seq_parameter_set(H264Context *h){
#endif #endif
sps->crop= get_bits1(&h->gb); sps->crop= get_bits1(&h->gb);
if(sps->crop){ if(sps->crop){
int crop_vertical_limit = sps->chroma_format_idc & 2 ? 16 : 8; int crop_left = get_ue_golomb(&h->gb);
int crop_horizontal_limit = sps->chroma_format_idc == 3 ? 16 : 8; int crop_right = get_ue_golomb(&h->gb);
sps->crop_left = get_ue_golomb(&h->gb); int crop_top = get_ue_golomb(&h->gb);
sps->crop_right = get_ue_golomb(&h->gb); int crop_bottom = get_ue_golomb(&h->gb);
sps->crop_top = get_ue_golomb(&h->gb);
sps->crop_bottom= get_ue_golomb(&h->gb);
if (h->avctx->flags2 & CODEC_FLAG2_IGNORE_CROP) { if (h->avctx->flags2 & CODEC_FLAG2_IGNORE_CROP) {
av_log(h->avctx, AV_LOG_DEBUG, av_log(h->avctx, AV_LOG_DEBUG, "discarding sps cropping, original "
"discarding sps cropping, " "values are l:%u r:%u t:%u b:%u\n", crop_left, crop_right,
"original values are l:%u r:%u t:%u b:%u\n", crop_top, crop_bottom);
sps->crop_left,
sps->crop_right,
sps->crop_top,
sps->crop_bottom);
sps->crop_left = sps->crop_left =
sps->crop_right = sps->crop_right =
sps->crop_top = sps->crop_top =
sps->crop_bottom = 0; sps->crop_bottom = 0;
} } else {
if(sps->crop_left || sps->crop_top){ int vsub = (sps->chroma_format_idc == 1) ? 1 : 0;
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); int hsub = (sps->chroma_format_idc == 1 || sps->chroma_format_idc == 2) ? 1 : 0;
} int step_x = 1 << hsub;
if(sps->crop_right >= crop_horizontal_limit || sps->crop_bottom >= crop_vertical_limit){ int step_y = (2 - sps->frame_mbs_only_flag) << vsub;
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. if (crop_left & (0x1F >> (sps->bit_depth_luma > 8)) &&
* Not cropping at all fixes for example playback of Sisvel 3D streams !(h->avctx->flags & CODEC_FLAG_UNALIGNED)) {
* in applications supporting Sisvel 3D. */ crop_left &= ~(0x1F >> (sps->bit_depth_luma > 8));
sps->crop_left = av_log(h->avctx, AV_LOG_WARNING, "Reducing left cropping to %d "
sps->crop_right = "chroma samples to preserve alignment.\n",
sps->crop_top = crop_left);
sps->crop_bottom= 0; }
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{ }else{
sps->crop_left = sps->crop_left =
sps->crop_right = sps->crop_right =
sps->crop_top = sps->crop_top =
sps->crop_bottom= 0; sps->crop_bottom= 0;
sps->crop = 0;
} }
sps->vui_parameters_present_flag= get_bits1(&h->gb); sps->vui_parameters_present_flag= get_bits1(&h->gb);

View File

@ -49,6 +49,7 @@ static const AVOption options[]={
"to minimum/maximum bitrate. Lowering tolerance too much has an adverse effect on quality.", "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}, 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"}, {"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"}, {"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"}, {"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"}, {"loop", "use loop filter", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_LOOP_FILTER }, INT_MIN, INT_MAX, V|E, "flags"},

View File

@ -29,7 +29,7 @@
#include "libavutil/avutil.h" #include "libavutil/avutil.h"
#define LIBAVCODEC_VERSION_MAJOR 55 #define LIBAVCODEC_VERSION_MAJOR 55
#define LIBAVCODEC_VERSION_MINOR 4 #define LIBAVCODEC_VERSION_MINOR 5
#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \