]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/dvdec.c
avcodec: Constify AVCodecs
[ffmpeg] / libavcodec / dvdec.c
index 7b16787e2745cf34315d68207c844952ecfde413..d768326661a9d1bec072a5837ea267389e0a060d 100644 (file)
@@ -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"
 #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,
 };