X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fdvdec.c;h=d768326661a9d1bec072a5837ea267389e0a060d;hb=a247ac640df3da573cd661065bf53f37863e2b46;hp=7b16787e2745cf34315d68207c844952ecfde413;hpb=185aa5e896e15ae96145609944bfc6bbb239bc64;p=ffmpeg diff --git a/libavcodec/dvdec.c b/libavcodec/dvdec.c index 7b16787e274..d768326661a 100644 --- a/libavcodec/dvdec.c +++ b/libavcodec/dvdec.c @@ -38,6 +38,7 @@ #include "libavutil/avassert.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #include "libavutil/pixdesc.h" #include "avcodec.h" @@ -45,10 +46,10 @@ #include "dv_profile_internal.h" #include "dvdata.h" #include "get_bits.h" -#include "idctdsp.h" #include "internal.h" #include "put_bits.h" #include "simple_idct.h" +#include "thread.h" typedef struct BlockInfo { const uint32_t *factor_table; @@ -176,24 +177,22 @@ static void dv_init_weight_tables(DVVideoContext *ctx, const AVDVProfile *d) static av_cold int dvvideo_decode_init(AVCodecContext *avctx) { DVVideoContext *s = avctx->priv_data; - IDCTDSPContext idsp; int i; - memset(&idsp,0, sizeof(idsp)); - ff_idctdsp_init(&idsp, avctx); + ff_idctdsp_init(&s->idsp, avctx); for (i = 0; i < 64; i++) - s->dv_zigzag[0][i] = idsp.idct_permutation[ff_zigzag_direct[i]]; + s->dv_zigzag[0][i] = s->idsp.idct_permutation[ff_zigzag_direct[i]]; if (avctx->lowres){ for (i = 0; i < 64; i++){ int j = ff_dv_zigzag248_direct[i]; - s->dv_zigzag[1][i] = idsp.idct_permutation[(j & 7) + (j & 8) * 4 + (j & 48) / 2]; + s->dv_zigzag[1][i] = s->idsp.idct_permutation[(j & 7) + (j & 8) * 4 + (j & 48) / 2]; } }else memcpy(s->dv_zigzag[1], ff_dv_zigzag248_direct, sizeof(s->dv_zigzag[1])); - s->idct_put[0] = idsp.idct_put; + s->idct_put[0] = s->idsp.idct_put; s->idct_put[1] = ff_simple_idct248_put; return ff_dvvideo_init(avctx); @@ -271,6 +270,48 @@ static inline void bit_copy(PutBitContext *pb, GetBitContext *gb) put_bits(pb, bits_left, get_bits(gb, bits_left)); } +static av_always_inline void put_block_8x4(int16_t *block, uint8_t *av_restrict p, int stride) +{ + int i, j; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 8; j++) + p[j] = av_clip_uint8(block[j]); + block += 8; + p += stride; + } +} + +static void dv100_idct_put_last_row_field_chroma(DVVideoContext *s, uint8_t *data, + int stride, int16_t *blocks) +{ + s->idsp.idct(blocks + 0*64); + s->idsp.idct(blocks + 1*64); + + put_block_8x4(blocks+0*64, data, stride<<1); + put_block_8x4(blocks+0*64 + 4*8, data + 8, stride<<1); + put_block_8x4(blocks+1*64, data + stride, stride<<1); + put_block_8x4(blocks+1*64 + 4*8, data + 8 + stride, stride<<1); +} + +static void dv100_idct_put_last_row_field_luma(DVVideoContext *s, uint8_t *data, + int stride, int16_t *blocks) +{ + s->idsp.idct(blocks + 0*64); + s->idsp.idct(blocks + 1*64); + s->idsp.idct(blocks + 2*64); + s->idsp.idct(blocks + 3*64); + + put_block_8x4(blocks+0*64, data, stride<<1); + put_block_8x4(blocks+0*64 + 4*8, data + 16, stride<<1); + put_block_8x4(blocks+1*64, data + 8, stride<<1); + put_block_8x4(blocks+1*64 + 4*8, data + 24, stride<<1); + put_block_8x4(blocks+2*64, data + stride, stride<<1); + put_block_8x4(blocks+2*64 + 4*8, data + 16 + stride, stride<<1); + put_block_8x4(blocks+3*64, data + 8 + stride, stride<<1); + put_block_8x4(blocks+3*64 + 4*8, data + 24 + stride, stride<<1); +} + /* mb_x and mb_y are in units of 8 pixels */ static int dv_decode_video_segment(AVCodecContext *avctx, void *arg) { @@ -442,14 +483,18 @@ retry: } y_ptr = s->frame->data[0] + ((mb_y * s->frame->linesize[0] + mb_x) << log2_blocksize); - linesize = s->frame->linesize[0] << is_field_mode[mb_index]; - mb[0].idct_put(y_ptr, linesize, block + 0 * 64); - if (s->sys->video_stype == 4) { /* SD 422 */ - mb[2].idct_put(y_ptr + (1 << log2_blocksize), linesize, block + 2 * 64); + if (mb_y == 134 && is_field_mode[mb_index]) { + dv100_idct_put_last_row_field_luma(s, y_ptr, s->frame->linesize[0], block); } else { - mb[1].idct_put(y_ptr + (1 << log2_blocksize), linesize, block + 1 * 64); - mb[2].idct_put(y_ptr + y_stride, linesize, block + 2 * 64); - mb[3].idct_put(y_ptr + (1 << log2_blocksize) + y_stride, linesize, block + 3 * 64); + linesize = s->frame->linesize[0] << is_field_mode[mb_index]; + mb[0].idct_put(y_ptr, linesize, block + 0 * 64); + if (s->sys->video_stype == 4) { /* SD 422 */ + mb[2].idct_put(y_ptr + (1 << log2_blocksize), linesize, block + 2 * 64); + } else { + mb[1].idct_put(y_ptr + (1 << log2_blocksize), linesize, block + 1 * 64); + mb[2].idct_put(y_ptr + y_stride, linesize, block + 2 * 64); + mb[3].idct_put(y_ptr + (1 << log2_blocksize) + y_stride, linesize, block + 3 * 64); + } } mb += 4; block += 4 * 64; @@ -477,13 +522,19 @@ retry: mb++; } else { y_stride = (mb_y == 134) ? (1 << log2_blocksize) : - s->frame->linesize[j] << ((!is_field_mode[mb_index]) * log2_blocksize); - linesize = s->frame->linesize[j] << is_field_mode[mb_index]; - (mb++)->idct_put(c_ptr, linesize, block); - block += 64; - if (s->sys->bpm == 8) { - (mb++)->idct_put(c_ptr + y_stride, linesize, block); + s->frame->linesize[j] << ((!is_field_mode[mb_index]) * log2_blocksize); + if (mb_y == 134 && is_field_mode[mb_index]) { + dv100_idct_put_last_row_field_chroma(s, c_ptr, s->frame->linesize[j], block); + mb += 2; + block += 2*64; + } else { + linesize = s->frame->linesize[j] << is_field_mode[mb_index]; + (mb++)->idct_put(c_ptr, linesize, block); block += 64; + if (s->sys->bpm == 8) { + (mb++)->idct_put(c_ptr + y_stride, linesize, block); + block += 64; + } } } } @@ -499,7 +550,7 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, void *data, uint8_t *buf = avpkt->data; int buf_size = avpkt->size; DVVideoContext *s = avctx->priv_data; - AVFrame *frame = data; + ThreadFrame frame = { .f = data }; const uint8_t *vsc_pack; int apt, is16_9, ret; const AVDVProfile *sys; @@ -520,9 +571,9 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, void *data, s->sys = sys; } - s->frame = frame; - frame->key_frame = 1; - frame->pict_type = AV_PICTURE_TYPE_I; + s->frame = frame.f; + frame.f->key_frame = 1; + frame.f->pict_type = AV_PICTURE_TYPE_I; avctx->pix_fmt = s->sys->pix_fmt; avctx->framerate = av_inv_q(s->sys->time_base); @@ -539,14 +590,21 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, void *data, ff_set_sar(avctx, s->sys->sar[is16_9]); } - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) return ret; - frame->interlaced_frame = 1; - frame->top_field_first = 0; /* Determine the codec's field order from the packet */ if ( *vsc_pack == dv_video_control ) { - frame->top_field_first = !(vsc_pack[3] & 0x40); + if (avctx->height == 720) { + frame.f->interlaced_frame = 0; + frame.f->top_field_first = 0; + } else if (avctx->height == 1080) { + frame.f->interlaced_frame = 1; + frame.f->top_field_first = (vsc_pack[3] & 0x40) == 0x40; + } else { + frame.f->interlaced_frame = (vsc_pack[3] & 0x10) == 0x10; + frame.f->top_field_first = !(vsc_pack[3] & 0x40); + } } s->buf = buf; @@ -561,7 +619,7 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, void *data, return s->sys->frame_size; } -AVCodec ff_dvvideo_decoder = { +const AVCodec ff_dvvideo_decoder = { .name = "dvvideo", .long_name = NULL_IF_CONFIG_SMALL("DV (Digital Video)"), .type = AVMEDIA_TYPE_VIDEO, @@ -569,6 +627,6 @@ AVCodec ff_dvvideo_decoder = { .priv_data_size = sizeof(DVVideoContext), .init = dvvideo_decode_init, .decode = dvvideo_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS, .max_lowres = 3, };