[FFmpeg-devel] [PATCH 2/3] avcodec/h264: error out on ff_h264_pred_weight_table() only if strict spec compliance is requested

James Almer jamrial at gmail.com
Tue Apr 9 21:32:26 EEST 2019


Fixes ticket #7174.

Signed-off-by: James Almer <jamrial at gmail.com>
---
This makes what's essentially a non spec compliant stream decodable again with
no visual artifacts, and without reintroducing the risk of overflows.

Alternatively, we could clip the luma and chroma values to the -128..127
range instead of setting them to defaults.

 libavcodec/h264_parse.c | 15 +++++++++------
 libavcodec/h264_slice.c |  2 +-
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c
index 8bdd886000..1b162b7361 100644
--- a/libavcodec/h264_parse.c
+++ b/libavcodec/h264_parse.c
@@ -31,6 +31,7 @@ int ff_h264_pred_weight_table(GetBitContext *gb, const SPS *sps,
 {
     int list, i, j;
     int luma_def, chroma_def;
+    int ret = 0;
 
     pwt->use_weight             = 0;
     pwt->use_weight_chroma      = 0;
@@ -39,6 +40,7 @@ int ff_h264_pred_weight_table(GetBitContext *gb, const SPS *sps,
     if (pwt->luma_log2_weight_denom > 7U) {
         av_log(logctx, AV_LOG_ERROR, "luma_log2_weight_denom %d is out of range\n", pwt->luma_log2_weight_denom);
         pwt->luma_log2_weight_denom = 0;
+        ret = AVERROR_INVALIDDATA;
     }
     luma_def = 1 << pwt->luma_log2_weight_denom;
 
@@ -47,6 +49,7 @@ int ff_h264_pred_weight_table(GetBitContext *gb, const SPS *sps,
         if (pwt->chroma_log2_weight_denom > 7U) {
             av_log(logctx, AV_LOG_ERROR, "chroma_log2_weight_denom %d is out of range\n", pwt->chroma_log2_weight_denom);
             pwt->chroma_log2_weight_denom = 0;
+            ret = AVERROR_INVALIDDATA;
         }
         chroma_def = 1 << pwt->chroma_log2_weight_denom;
     }
@@ -63,9 +66,10 @@ int ff_h264_pred_weight_table(GetBitContext *gb, const SPS *sps,
                 pwt->luma_weight[i][list][1] = get_se_golomb(gb);
                 if ((int8_t)pwt->luma_weight[i][list][0] != pwt->luma_weight[i][list][0] ||
                     (int8_t)pwt->luma_weight[i][list][1] != pwt->luma_weight[i][list][1]) {
+                    av_log(logctx, AV_LOG_ERROR, "luma weight is out of range\n");
                     pwt->luma_weight[i][list][0] = luma_def;
                     pwt->luma_weight[i][list][1] = 0;
-                    goto out_range_weight;
+                    ret = AVERROR_INVALIDDATA;
                 }
                 if (pwt->luma_weight[i][list][0] != luma_def ||
                     pwt->luma_weight[i][list][1] != 0) {
@@ -86,9 +90,10 @@ int ff_h264_pred_weight_table(GetBitContext *gb, const SPS *sps,
                         pwt->chroma_weight[i][list][j][1] = get_se_golomb(gb);
                         if ((int8_t)pwt->chroma_weight[i][list][j][0] != pwt->chroma_weight[i][list][j][0] ||
                             (int8_t)pwt->chroma_weight[i][list][j][1] != pwt->chroma_weight[i][list][j][1]) {
+                            av_log(logctx, AV_LOG_ERROR, "chroma weight is out of range\n");
                             pwt->chroma_weight[i][list][j][0] = chroma_def;
                             pwt->chroma_weight[i][list][j][1] = 0;
-                            goto out_range_weight;
+                            ret = AVERROR_INVALIDDATA;
                         }
                         if (pwt->chroma_weight[i][list][j][0] != chroma_def ||
                             pwt->chroma_weight[i][list][j][1] != 0) {
@@ -121,10 +126,8 @@ int ff_h264_pred_weight_table(GetBitContext *gb, const SPS *sps,
             break;
     }
     pwt->use_weight = pwt->use_weight || pwt->use_weight_chroma;
-    return 0;
-out_range_weight:
-    avpriv_request_sample(logctx, "Out of range weight");
-    return AVERROR_INVALIDDATA;
+
+    return ret;
 }
 
 /**
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index 1c9a270fb6..d3432d7b1f 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -1867,7 +1867,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
         ret = ff_h264_pred_weight_table(&sl->gb, sps, sl->ref_count,
                                   sl->slice_type_nos, &sl->pwt,
                                   picture_structure, h->avctx);
-        if (ret < 0)
+        if (ret < 0 && (h->avctx->err_recognition & (AV_EF_BITSTREAM|AV_EF_COMPLIANT)))
             return ret;
     }
 
-- 
2.21.0



More information about the ffmpeg-devel mailing list