aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2015-01-20 20:30:53 +0100
committerMichael Niedermayer <michaelni@gmx.at>2015-01-23 00:47:24 +0100
commitecd39520b83ecc2f10a884b6c2a5594247806601 (patch)
tree04f6a52a9651dd31996e24256d5d2559c36d68fa
parent4b46ce8e91bdcf0726f669525609f77fc1a88472 (diff)
downloadffmpeg-ecd39520b83ecc2f10a884b6c2a5594247806601.tar.gz
avcodec/h264: Partially decode and display single fields try #2
This like the previous attempt does not fully correctly decode this type of non standard H.264, but it now works fully automatic requiring no manual filters or flags to be used See Ticket2254 Reviewed-by: Kieran Kunhya <kierank@obe.tv> Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r--libavcodec/h264.c28
-rw-r--r--libavcodec/h264.h2
-rw-r--r--libavcodec/h264_slice.c2
3 files changed, 31 insertions, 1 deletions
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index ab9acde7cb..23f775414f 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -762,7 +762,10 @@ static void decode_postinit(H264Context *h, int setup_finished)
* yet, so we assume the worst for now. */
// if (setup_finished)
// ff_thread_finish_setup(h->avctx);
- return;
+ if (cur->field_poc[0] == INT_MAX && cur->field_poc[1] == INT_MAX)
+ return;
+ if (h->avctx->hwaccel || h->missing_fields <=1)
+ return;
}
cur->f.interlaced_frame = 0;
@@ -1912,6 +1915,29 @@ static int h264_decode_frame(AVCodecContext *avctx, void *data,
if (!h->next_output_pic->recovered)
h->next_output_pic->f.flags |= AV_FRAME_FLAG_CORRUPT;
+ if (!h->avctx->hwaccel &&
+ (h->next_output_pic->field_poc[0] == INT_MAX ||
+ h->next_output_pic->field_poc[1] == INT_MAX)
+ ) {
+ int p;
+ AVFrame *f = &h->next_output_pic->f;
+ int field = h->next_output_pic->field_poc[0] == INT_MAX;
+ uint8_t *dst_data[4];
+ int linesizes[4];
+ const uint8_t *src_data[4];
+
+ av_log(h->avctx, AV_LOG_DEBUG, "Duplicating field %d to fill missing\n", field);
+
+ for (p = 0; p<4; p++) {
+ dst_data[p] = f->data[p] + (field^1)*f->linesize[p];
+ src_data[p] = f->data[p] + field *f->linesize[p];
+ linesizes[p] = 2*f->linesize[p];
+ }
+
+ av_image_copy(dst_data, linesizes, src_data, linesizes,
+ f->format, f->width, f->height>>1);
+ }
+
ret = output_frame(h, pict, h->next_output_pic);
if (ret < 0)
return ret;
diff --git a/libavcodec/h264.h b/libavcodec/h264.h
index 2d8e1375a2..cf4998fe09 100644
--- a/libavcodec/h264.h
+++ b/libavcodec/h264.h
@@ -740,6 +740,8 @@ typedef struct H264Context {
int has_recovery_point;
+ int missing_fields;
+
int luma_weight_flag[2]; ///< 7.4.3.2 luma_weight_lX_flag
int chroma_weight_flag[2]; ///< 7.4.3.2 chroma_weight_lX_flag
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index 3874d07000..6d19c73bf0 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -1663,9 +1663,11 @@ int ff_h264_decode_slice_header(H264Context *h, H264Context *h0)
if (!FIELD_PICTURE(h) || h->picture_structure == last_pic_structure) {
/* Previous field is unmatched. Don't display it, but let it
* remain for reference if marked as such. */
+ h0->missing_fields ++;
h0->cur_pic_ptr = NULL;
h0->first_field = FIELD_PICTURE(h);
} else {
+ h0->missing_fields = 0;
if (h0->cur_pic_ptr->frame_num != h->frame_num) {
ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX,
h0->picture_structure==PICT_BOTTOM_FIELD);