Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FFmpeg/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2012-03-18 02:16:05 +0400
committerMichael Niedermayer <michaelni@gmx.at>2012-03-18 02:16:05 +0400
commit967bdb8572f27b9891fe7bd9b8489146a906633d (patch)
tree61b486be897a4503f71e2ecc7734f16930dc1a94 /libavcodec/h264.c
parent219a6fb61cb9e6f534f20dc3313442f89b0ffd42 (diff)
parent6ca3b248e21fc48418c4221fc92c2eecaf07cb9b (diff)
Merge remote-tracking branch 'qatar/master'
* qatar/master: resample: allocate a large enough output buffer fate: fix enc_dec_pcm tests with remote target wmaenc: remove bit-exact hack FATE: remove WMA acodec tests FATE: add WMAv1 and WMAv2 encode/decode tests with fuzzy comparison FATE: add AC-3 and E-AC-3 encode/decode tests with fuzzy comparison qtrle: Use bytestream2 functions to prevent buffer overreads. vqavideo: check malloc return values x11grab: fix a memory leak exposed by valgrind threads: fix old frames returned after avcodec_flush_buffers() MPV: always mark dummy frames as reference h264: fix deadlocks on incomplete reference frame decoding. mpeg4: report frame decoding completion at ff_MPV_frame_end(). mimic: don't use self as reference, and report completion at end of decode(). Conflicts: libavcodec/h264.c libavcodec/qtrle.c libavcodec/resample.c libavcodec/vqavideo.c libavdevice/x11grab.c tests/ref/seek/wmav1_asf tests/ref/seek/wmav2_asf Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/h264.c')
-rw-r--r--libavcodec/h264.c123
1 files changed, 109 insertions, 14 deletions
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index cfb6aa5345..5785278ede 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -2733,8 +2733,7 @@ static int field_end(H264Context *h, int in_setup)
s->mb_y = 0;
if (!in_setup && !s->dropable)
- ff_thread_report_progress(&s->current_picture_ptr->f,
- (16 * s->mb_height >> FIELD_PICTURE) - 1,
+ ff_thread_report_progress(&s->current_picture_ptr->f, INT_MAX,
s->picture_structure == PICT_BOTTOM_FIELD);
if (CONFIG_H264_VDPAU_DECODER &&
@@ -2857,9 +2856,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0)
int num_ref_idx_active_override_flag;
unsigned int slice_type, tmp, i, j;
int default_ref_list_done = 0;
- int last_pic_structure;
-
- s->dropable = h->nal_ref_idc == 0;
+ int last_pic_structure, last_pic_dropable;
/* FIXME: 2tap qpel isn't implemented for high bit depth. */
if ((s->avctx->flags2 & CODEC_FLAG2_FAST) &&
@@ -2879,8 +2876,14 @@ static int decode_slice_header(H264Context *h, H264Context *h0)
}
h0->current_slice = 0;
- if (!s0->first_field)
+ if (!s0->first_field) {
+ if (s->current_picture_ptr && !s->dropable &&
+ s->current_picture_ptr->owner2 == s) {
+ ff_thread_report_progress(&s->current_picture_ptr->f, INT_MAX,
+ s->picture_structure == PICT_BOTTOM_FIELD);
+ }
s->current_picture_ptr = NULL;
+ }
}
slice_type = get_ue_golomb_31(&s->gb);
@@ -3114,6 +3117,8 @@ static int decode_slice_header(H264Context *h, H264Context *h0)
h->mb_mbaff = 0;
h->mb_aff_frame = 0;
last_pic_structure = s0->picture_structure;
+ last_pic_dropable = s->dropable;
+ s->dropable = h->nal_ref_idc == 0;
if (h->sps.frame_mbs_only_flag) {
s->picture_structure = PICT_FRAME;
} else {
@@ -3130,7 +3135,17 @@ static int decode_slice_header(H264Context *h, H264Context *h0)
}
h->mb_field_decoding_flag = s->picture_structure != PICT_FRAME;
- if (h0->current_slice == 0) {
+ if (h0->current_slice != 0) {
+ if (last_pic_structure != s->picture_structure ||
+ last_pic_dropable != s->dropable) {
+ av_log(h->s.avctx, AV_LOG_ERROR,
+ "Changing field mode (%d -> %d) between slices is not allowed\n",
+ last_pic_structure, s->picture_structure);
+ s->picture_structure = last_pic_structure;
+ s->dropable = last_pic_dropable;
+ return AVERROR_INVALIDDATA;
+ }
+ } else {
/* Shorten frame num gaps so we don't have to allocate reference
* frames just to throw them away */
if (h->frame_num != h->prev_frame_num && h->prev_frame_num >= 0) {
@@ -3149,6 +3164,72 @@ static int decode_slice_header(H264Context *h, H264Context *h0)
}
}
+ /* See if we have a decoded first field looking for a pair...
+ * Here, we're using that to see if we should mark previously
+ * decode frames as "finished".
+ * We have to do that before the "dummy" in-between frame allocation,
+ * since that can modify s->current_picture_ptr. */
+ if (s0->first_field) {
+ assert(s0->current_picture_ptr);
+ assert(s0->current_picture_ptr->f.data[0]);
+ assert(s0->current_picture_ptr->f.reference != DELAYED_PIC_REF);
+
+ /* Mark old field/frame as completed */
+ if (!last_pic_dropable && s0->current_picture_ptr->owner2 == s0) {
+ ff_thread_report_progress(&s0->current_picture_ptr->f, INT_MAX,
+ last_pic_structure == PICT_BOTTOM_FIELD);
+ }
+
+ /* figure out if we have a complementary field pair */
+ if (!FIELD_PICTURE || s->picture_structure == last_pic_structure) {
+ /* Previous field is unmatched. Don't display it, but let it
+ * remain for reference if marked as such. */
+ if (!last_pic_dropable && last_pic_structure != PICT_FRAME) {
+ ff_thread_report_progress(&s0->current_picture_ptr->f, INT_MAX,
+ last_pic_structure == PICT_TOP_FIELD);
+ }
+ } else {
+ if (s0->current_picture_ptr->frame_num != h->frame_num) {
+ /* This and previous field were reference, but had
+ * different frame_nums. Consider this field first in
+ * pair. Throw away previous field except for reference
+ * purposes. */
+ if (!last_pic_dropable && last_pic_structure != PICT_FRAME) {
+ ff_thread_report_progress(&s0->current_picture_ptr->f, INT_MAX,
+ last_pic_structure == PICT_TOP_FIELD);
+ }
+ } else {
+ /* Second field in complementary pair */
+ if (!((last_pic_structure == PICT_TOP_FIELD &&
+ s->picture_structure == PICT_BOTTOM_FIELD) ||
+ (last_pic_structure == PICT_BOTTOM_FIELD &&
+ s->picture_structure == PICT_TOP_FIELD))) {
+ av_log(s->avctx, AV_LOG_ERROR,
+ "Invalid field mode combination %d/%d\n",
+ last_pic_structure, s->picture_structure);
+ s->picture_structure = last_pic_structure;
+ s->dropable = last_pic_dropable;
+ return AVERROR_INVALIDDATA;
+ } else if (last_pic_dropable != s->dropable) {
+ av_log(s->avctx, AV_LOG_ERROR,
+ "Cannot combine reference and non-reference fields in the same frame\n");
+ av_log_ask_for_sample(s->avctx, NULL);
+ s->picture_structure = last_pic_structure;
+ s->dropable = last_pic_dropable;
+ return AVERROR_INVALIDDATA;
+ }
+
+ /* Take ownership of this buffer. Note that if another thread owned
+ * the first field of this buffer, we're not operating on that pointer,
+ * so the original thread is still responsible for reporting progress
+ * on that first field (or if that was us, we just did that above).
+ * By taking ownership, we assign responsibility to ourselves to
+ * report progress on the second field. */
+ s0->current_picture_ptr->owner2 = s0;
+ }
+ }
+ }
+
while (h->frame_num != h->prev_frame_num && h->prev_frame_num >= 0 &&
h->frame_num != (h->prev_frame_num + 1) % (1 << h->sps.log2_max_frame_num)) {
Picture *prev = h->short_ref_count ? h->short_ref[0] : NULL;
@@ -3182,7 +3263,9 @@ static int decode_slice_header(H264Context *h, H264Context *h0)
}
}
- /* See if we have a decoded first field looking for a pair... */
+ /* See if we have a decoded first field looking for a pair...
+ * We're using that to see whether to continue decoding in that
+ * frame, or to allocate a new one. */
if (s0->first_field) {
assert(s0->current_picture_ptr);
assert(s0->current_picture_ptr->f.data[0]);
@@ -3198,9 +3281,9 @@ static int decode_slice_header(H264Context *h, H264Context *h0)
if (s0->current_picture_ptr->frame_num != h->frame_num) {
ff_thread_report_progress((AVFrame*)s0->current_picture_ptr, INT_MAX,
s0->picture_structure==PICT_BOTTOM_FIELD);
- /* This and the previous field had
- * different frame_nums. Consider this field first in pair.
- * Throw away previous one except for reference purposes. */
+ /* This and the previous field had different frame_nums.
+ * Consider this field first in pair. Throw away previous
+ * one except for reference purposes. */
s0->first_field = 1;
s0->current_picture_ptr = NULL;
} else {
@@ -4155,8 +4238,10 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
ptr = ff_h264_decode_nal(hx, buf + buf_index, &dst_length,
&consumed, next_avc - buf_index);
- if (ptr == NULL || dst_length < 0)
- return -1;
+ if (ptr == NULL || dst_length < 0) {
+ buf_index = -1;
+ goto end;
+ }
i = buf_index + consumed;
if ((s->workaround_bugs & FF_BUG_AUTODETECT) && i + 3 < next_avc &&
buf[i] == 0x00 && buf[i + 1] == 0x00 &&
@@ -4211,7 +4296,8 @@ again:
if (h->nal_unit_type != NAL_IDR_SLICE) {
av_log(h->s.avctx, AV_LOG_ERROR,
"Invalid mix of idr and non-idr slices\n");
- return -1;
+ buf_index = -1;
+ goto end;
}
idr(h); // FIXME ensure we don't lose some frames if there is reordering
case NAL_SLICE:
@@ -4369,6 +4455,15 @@ again:
}
if (context_count)
execute_decode_slices(h, context_count);
+
+end:
+ /* clean up */
+ if (s->current_picture_ptr && s->current_picture_ptr->owner2 == s &&
+ !s->dropable) {
+ ff_thread_report_progress(&s->current_picture_ptr->f, INT_MAX,
+ s->picture_structure == PICT_BOTTOM_FIELD);
+ }
+
return buf_index;
}