[FFmpeg-cvslog] avcodec/h264: Partially decode and display single fields try #2
Michael Niedermayer
git at videolan.org
Fri Jan 23 01:06:05 CET 2015
ffmpeg | branch: master | Michael Niedermayer <michaelni at gmx.at> | Tue Jan 20 20:30:53 2015 +0100| [ecd39520b83ecc2f10a884b6c2a5594247806601] | committer: Michael Niedermayer
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 at obe.tv>
Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=ecd39520b83ecc2f10a884b6c2a5594247806601
---
libavcodec/h264.c | 28 +++++++++++++++++++++++++++-
libavcodec/h264.h | 2 ++
libavcodec/h264_slice.c | 2 ++
3 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index ab9acde..23f7754 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 2d8e137..cf4998f 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 3874d07..6d19c73 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);
More information about the ffmpeg-cvslog
mailing list