diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-01-04 01:12:34 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-01-04 01:12:34 +0100 |
commit | ad1c8dd6734f0aa7a7a87b4669a166715c114b46 (patch) | |
tree | c03c08f30bf1a7e8d9859abc48de3391bb05c6a0 /libavcodec/utvideo.c | |
parent | d6da16dca5a64ed7ab2db54710a0c703f179d3ba (diff) | |
parent | fd16f567987524a769d5d4f1f69089f000386ac2 (diff) | |
download | ffmpeg-ad1c8dd6734f0aa7a7a87b4669a166715c114b46.tar.gz |
Merge remote-tracking branch 'qatar/master'
* qatar/master:
fate: add dxtory test
adx_parser: rewrite.
adxdec: Validate channel count to fix a division by zero.
adxdec: Do not require extradata.
cmdutils: K&R reformatting cosmetics
alacdec: implement the 2-pass prediction type.
alacenc: implement the 2-pass prediction type.
alacenc: do not generate invalid multi-channel ALAC files
alacdec: fill in missing or guessed info about the extradata format.
utvideo: proper median prediction for interlaced videos
lavu: bump lavu minor for av_popcount64
dca: K&R formatting cosmetics
dct: K&R formatting cosmetics
lavf: flush decoders in avformat_find_stream_info().
win32: detect number of CPUs using affinity
Add av_popcount64
snow: Restore three mistakenly removed casts.
Conflicts:
cmdutils.c
doc/APIchanges
libavcodec/adx_parser.c
libavcodec/adxdec.c
libavcodec/alacenc.c
libavutil/avutil.h
tests/fate/screen.mak
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/utvideo.c')
-rw-r--r-- | libavcodec/utvideo.c | 101 |
1 files changed, 94 insertions, 7 deletions
diff --git a/libavcodec/utvideo.c b/libavcodec/utvideo.c index 6fb384a4e4..906a61f9f8 100644 --- a/libavcodec/utvideo.c +++ b/libavcodec/utvideo.c @@ -282,6 +282,77 @@ static void restore_median(uint8_t *src, int step, int stride, } } +/* UtVideo interlaced mode treats every two lines as a single one, + * so restoring function should take care of possible padding between + * two parts of the same "line". + */ +static void restore_median_il(uint8_t *src, int step, int stride, + int width, int height, int slices, int rmode) +{ + int i, j, slice; + int A, B, C; + uint8_t *bsrc; + int slice_start, slice_height; + const int cmask = ~(rmode ? 3 : 1); + const int stride2 = stride << 1; + + for (slice = 0; slice < slices; slice++) { + slice_start = ((slice * height) / slices) & cmask; + slice_height = ((((slice + 1) * height) / slices) & cmask) - slice_start; + slice_height >>= 1; + + bsrc = src + slice_start * stride; + + // first line - left neighbour prediction + bsrc[0] += 0x80; + A = bsrc[0]; + for (i = step; i < width * step; i += step) { + bsrc[i] += A; + A = bsrc[i]; + } + for (i = 0; i < width * step; i += step) { + bsrc[stride + i] += A; + A = bsrc[stride + i]; + } + bsrc += stride2; + if (slice_height == 1) + continue; + // second line - first element has top predition, the rest uses median + C = bsrc[-stride2]; + bsrc[0] += C; + A = bsrc[0]; + for (i = step; i < width * step; i += step) { + B = bsrc[i - stride2]; + bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C)); + C = B; + A = bsrc[i]; + } + for (i = 0; i < width * step; i += step) { + B = bsrc[i - stride]; + bsrc[stride + i] += mid_pred(A, B, (uint8_t)(A + B - C)); + C = B; + A = bsrc[stride + i]; + } + bsrc += stride2; + // the rest of lines use continuous median prediction + for (j = 2; j < slice_height; j++) { + for (i = 0; i < width * step; i += step) { + B = bsrc[i - stride2]; + bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C)); + C = B; + A = bsrc[i]; + } + for (i = 0; i < width * step; i += step) { + B = bsrc[i - stride]; + bsrc[i + stride] += mid_pred(A, B, (uint8_t)(A + B - C)); + C = B; + A = bsrc[i + stride]; + } + bsrc += stride2; + } + } +} + static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; @@ -381,10 +452,18 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac c->frame_pred == PRED_LEFT); if (ret) return ret; - if (c->frame_pred == PRED_MEDIAN) - restore_median(c->pic.data[i], 1, c->pic.linesize[i], - avctx->width >> !!i, avctx->height >> !!i, - c->slices, !i); + if (c->frame_pred == PRED_MEDIAN) { + if (!c->interlaced) { + restore_median(c->pic.data[i], 1, c->pic.linesize[i], + avctx->width >> !!i, avctx->height >> !!i, + c->slices, !i); + } else { + restore_median_il(c->pic.data[i], 1, c->pic.linesize[i], + avctx->width >> !!i, + avctx->height >> !!i, + c->slices, !i); + } + } } break; case PIX_FMT_YUV422P: @@ -395,9 +474,17 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac c->frame_pred == PRED_LEFT); if (ret) return ret; - if (c->frame_pred == PRED_MEDIAN) - restore_median(c->pic.data[i], 1, c->pic.linesize[i], - avctx->width >> !!i, avctx->height, c->slices, 0); + if (c->frame_pred == PRED_MEDIAN) { + if (!c->interlaced) { + restore_median(c->pic.data[i], 1, c->pic.linesize[i], + avctx->width >> !!i, avctx->height, + c->slices, 0); + } else { + restore_median_il(c->pic.data[i], 1, c->pic.linesize[i], + avctx->width >> !!i, avctx->height, + c->slices, 0); + } + } } break; } |