summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Cadhalpun <Andreas.Cadhalpun@googlemail.com>2015-06-09 23:38:26 +0200
committerAndreas Cadhalpun <Andreas.Cadhalpun@googlemail.com>2015-06-12 21:22:00 +0200
commit1189af429211ac650aac730368a6cf5b23756605 (patch)
tree6e91ea70c031cb700402c5f6b82905eb36cf930c
parentb5c71fba594353b0676fa41c1f279d42adb6e716 (diff)
h264: update avctx width/height/pix_fmt when returning frame
Inconsistencies between the dimensions/pixel format of avctx and the frame can confuse API users. For example this can crash the demuxing_decoding example. Back up the previous values and restore them, when decoding the next frame. This is necessary, because these can be different between the returned frame and the last decoded frame. Reviewed-by: Michael Niedermayer <michaelni@gmx.at> Signed-off-by: Andreas Cadhalpun <Andreas.Cadhalpun@googlemail.com>
-rw-r--r--libavcodec/h264.c24
-rw-r--r--libavcodec/h264.h8
-rw-r--r--libavcodec/h264_slice.c3
3 files changed, 35 insertions, 0 deletions
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index 9a002142cc..9be317c55f 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -591,6 +591,9 @@ static int h264_init_context(AVCodecContext *avctx, H264Context *h)
int i;
h->avctx = avctx;
+ h->backup_width = -1;
+ h->backup_height = -1;
+ h->backup_pix_fmt = AV_PIX_FMT_NONE;
h->dequant_coeff_pps = -1;
h->current_sps_id = -1;
h->cur_chroma_format_idc = -1;
@@ -1675,6 +1678,14 @@ static int output_frame(H264Context *h, AVFrame *dst, H264Picture *srcp)
av_dict_set(&dst->metadata, "stereo_mode", ff_h264_sei_stereo_mode(h), 0);
+ h->backup_width = h->avctx->width;
+ h->backup_height = h->avctx->height;
+ h->backup_pix_fmt = h->avctx->pix_fmt;
+
+ h->avctx->width = dst->width;
+ h->avctx->height = dst->height;
+ h->avctx->pix_fmt = dst->format;
+
if (srcp->sei_recovery_frame_cnt == 0)
dst->key_frame = 1;
if (!srcp->crop)
@@ -1726,6 +1737,19 @@ static int h264_decode_frame(AVCodecContext *avctx, void *data,
h->flags = avctx->flags;
+ if (h->backup_width != -1) {
+ avctx->width = h->backup_width;
+ h->backup_width = -1;
+ }
+ if (h->backup_height != -1) {
+ avctx->height = h->backup_height;
+ h->backup_height = -1;
+ }
+ if (h->backup_pix_fmt != AV_PIX_FMT_NONE) {
+ avctx->pix_fmt = h->backup_pix_fmt;
+ h->backup_pix_fmt = AV_PIX_FMT_NONE;
+ }
+
ff_h264_unref_picture(h, &h->last_pic_for_ec);
/* end of stream, output what is still in the buffers */
diff --git a/libavcodec/h264.h b/libavcodec/h264.h
index 95db912465..548510d793 100644
--- a/libavcodec/h264.h
+++ b/libavcodec/h264.h
@@ -519,6 +519,14 @@ typedef struct H264Context {
int width, height;
int chroma_x_shift, chroma_y_shift;
+ /**
+ * Backup frame properties: needed, because they can be different
+ * between returned frame and last decoded frame.
+ **/
+ int backup_width;
+ int backup_height;
+ enum AVPixelFormat backup_pix_fmt;
+
int droppable;
int coded_picture_number;
int low_delay;
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index 9c4d613195..0c0812f472 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -497,6 +497,9 @@ int ff_h264_update_thread_context(AVCodecContext *dst,
h->picture_structure = h1->picture_structure;
h->droppable = h1->droppable;
h->low_delay = h1->low_delay;
+ h->backup_width = h1->backup_width;
+ h->backup_height = h1->backup_height;
+ h->backup_pix_fmt = h1->backup_pix_fmt;
for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) {
ff_h264_unref_picture(h, &h->DPB[i]);