diff options
author | Derek Buitenhuis <derek.buitenhuis@gmail.com> | 2016-04-27 16:34:40 +0100 |
---|---|---|
committer | Derek Buitenhuis <derek.buitenhuis@gmail.com> | 2016-04-27 16:34:40 +0100 |
commit | a2922b5d614ca6db025364f47bc4a1e4812859aa (patch) | |
tree | ce37baec9ca2a82cd1a91c83ad4959fbfc76c421 /libavcodec/h264_parse.c | |
parent | c18535399d2597afd8855ccaa4416b0999d0d7f9 (diff) | |
parent | ecc31f6b086453ab9811dce2ae5ceb6a7c19e4ad (diff) | |
download | ffmpeg-a2922b5d614ca6db025364f47bc4a1e4812859aa.tar.gz |
Merge commit 'ecc31f6b086453ab9811dce2ae5ceb6a7c19e4ad'
* commit 'ecc31f6b086453ab9811dce2ae5ceb6a7c19e4ad':
h264: move ff_h264_check_intra[4x4]_pred_mode() to h264_parse
Merged-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
Diffstat (limited to 'libavcodec/h264_parse.c')
-rw-r--r-- | libavcodec/h264_parse.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c index ebd87b0e5b..e6cc28e42e 100644 --- a/libavcodec/h264_parse.c +++ b/libavcodec/h264_parse.c @@ -94,3 +94,95 @@ int ff_h264_pred_weight_table(GetBitContext *gb, const SPS *sps, pwt->use_weight = pwt->use_weight || pwt->use_weight_chroma; return 0; } + +/** + * Check if the top & left blocks are available if needed and + * change the dc mode so it only uses the available blocks. + */ +int ff_h264_check_intra4x4_pred_mode(int8_t *pred_mode_cache, void *logctx, + int top_samples_available, int left_samples_available) +{ + static const int8_t top[12] = { + -1, 0, LEFT_DC_PRED, -1, -1, -1, -1, -1, 0 + }; + static const int8_t left[12] = { + 0, -1, TOP_DC_PRED, 0, -1, -1, -1, 0, -1, DC_128_PRED + }; + int i; + + if (!(top_samples_available & 0x8000)) { + for (i = 0; i < 4; i++) { + int status = top[pred_mode_cache[scan8[0] + i]]; + if (status < 0) { + av_log(logctx, AV_LOG_ERROR, + "top block unavailable for requested intra mode %d\n", + status); + return AVERROR_INVALIDDATA; + } else if (status) { + pred_mode_cache[scan8[0] + i] = status; + } + } + } + + if ((left_samples_available & 0x8888) != 0x8888) { + static const int mask[4] = { 0x8000, 0x2000, 0x80, 0x20 }; + for (i = 0; i < 4; i++) + if (!(left_samples_available & mask[i])) { + int status = left[pred_mode_cache[scan8[0] + 8 * i]]; + if (status < 0) { + av_log(logctx, AV_LOG_ERROR, + "left block unavailable for requested intra4x4 mode %d\n", + status); + return AVERROR_INVALIDDATA; + } else if (status) { + pred_mode_cache[scan8[0] + 8 * i] = status; + } + } + } + + return 0; +} + +/** + * Check if the top & left blocks are available if needed and + * change the dc mode so it only uses the available blocks. + */ +int ff_h264_check_intra_pred_mode(void *logctx, int top_samples_available, + int left_samples_available, + int mode, int is_chroma) +{ + static const int8_t top[4] = { LEFT_DC_PRED8x8, 1, -1, -1 }; + static const int8_t left[5] = { TOP_DC_PRED8x8, -1, 2, -1, DC_128_PRED8x8 }; + + if (mode > 3U) { + av_log(logctx, AV_LOG_ERROR, + "out of range intra chroma pred mode\n"); + return AVERROR_INVALIDDATA; + } + + if (!(top_samples_available & 0x8000)) { + mode = top[mode]; + if (mode < 0) { + av_log(logctx, AV_LOG_ERROR, + "top block unavailable for requested intra mode\n"); + return AVERROR_INVALIDDATA; + } + } + + if ((left_samples_available & 0x8080) != 0x8080) { + mode = left[mode]; + if (mode < 0) { + av_log(logctx, AV_LOG_ERROR, + "left block unavailable for requested intra mode\n"); + return AVERROR_INVALIDDATA; + } + if (is_chroma && (left_samples_available & 0x8080)) { + // mad cow disease mode, aka MBAFF + constrained_intra_pred + mode = ALZHEIMER_DC_L0T_PRED8x8 + + (!(left_samples_available & 0x8000)) + + 2 * (mode == DC_128_PRED8x8); + } + } + + return mode; +} |