#include "libavutil/avassert.h"
#include "libavutil/imgutils.h"
#include "libavutil/internal.h"
+#include "libavutil/mem_internal.h"
#include "libavutil/pixdesc.h"
#include "avcodec.h"
#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"
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);
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)
{
}
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;
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;
+ }
}
}
}
if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
return ret;
- frame.f->interlaced_frame = 1;
- frame.f->top_field_first = 0;
/* Determine the codec's field order from the packet */
if ( *vsc_pack == dv_video_control ) {
- frame.f->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;
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,