LCOV - code coverage report
Current view: top level - libavcodec - v210enc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 108 120 90.0 %
Date: 2017-12-13 10:57:33 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :  * V210 encoder
       3             :  *
       4             :  * Copyright (C) 2009 Michael Niedermayer <michaelni@gmx.at>
       5             :  * Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
       6             :  *
       7             :  * This file is part of FFmpeg.
       8             :  *
       9             :  * FFmpeg is free software; you can redistribute it and/or
      10             :  * modify it under the terms of the GNU Lesser General Public
      11             :  * License as published by the Free Software Foundation; either
      12             :  * version 2.1 of the License, or (at your option) any later version.
      13             :  *
      14             :  * FFmpeg is distributed in the hope that it will be useful,
      15             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :  * Lesser General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU Lesser General Public
      20             :  * License along with FFmpeg; if not, write to the Free Software
      21             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      22             :  */
      23             : 
      24             : #include "avcodec.h"
      25             : #include "bytestream.h"
      26             : #include "internal.h"
      27             : #include "v210enc.h"
      28             : 
      29             : #define CLIP(v) av_clip(v, 4, 1019)
      30             : #define CLIP8(v) av_clip(v, 1, 254)
      31             : 
      32             : #define WRITE_PIXELS(a, b, c)           \
      33             :     do {                                \
      34             :         val  =  CLIP(*a++);             \
      35             :         val |= (CLIP(*b++) << 10) |     \
      36             :                (CLIP(*c++) << 20);      \
      37             :         AV_WL32(dst, val);              \
      38             :         dst += 4;                       \
      39             :     } while (0)
      40             : 
      41             : #define WRITE_PIXELS8(a, b, c)          \
      42             :     do {                                \
      43             :         val  = (CLIP8(*a++) << 2);      \
      44             :         val |= (CLIP8(*b++) << 12) |    \
      45             :                (CLIP8(*c++) << 22);     \
      46             :         AV_WL32(dst, val);              \
      47             :         dst += 4;                       \
      48             :     } while (0)
      49             : 
      50       45023 : static void v210_planar_pack_8_c(const uint8_t *y, const uint8_t *u,
      51             :                                  const uint8_t *v, uint8_t *dst,
      52             :                                  ptrdiff_t width)
      53             : {
      54             :     uint32_t val;
      55             :     int i;
      56             : 
      57             :     /* unroll this to match the assembly */
      58     1303806 :     for (i = 0; i < width - 11; i += 12) {
      59     1258783 :         WRITE_PIXELS8(u, y, v);
      60     1258783 :         WRITE_PIXELS8(y, u, y);
      61     1258783 :         WRITE_PIXELS8(v, y, u);
      62     1258783 :         WRITE_PIXELS8(y, v, y);
      63     1258783 :         WRITE_PIXELS8(u, y, v);
      64     1258783 :         WRITE_PIXELS8(y, u, y);
      65     1258783 :         WRITE_PIXELS8(v, y, u);
      66     1258783 :         WRITE_PIXELS8(y, v, y);
      67             :     }
      68       45023 : }
      69             : 
      70       45146 : static void v210_planar_pack_10_c(const uint16_t *y, const uint16_t *u,
      71             :                                   const uint16_t *v, uint8_t *dst,
      72             :                                   ptrdiff_t width)
      73             : {
      74             :     uint32_t val;
      75             :     int i;
      76             : 
      77     2569455 :     for (i = 0; i < width - 5; i += 6) {
      78     2524309 :         WRITE_PIXELS(u, y, v);
      79     2524309 :         WRITE_PIXELS(y, u, y);
      80     2524309 :         WRITE_PIXELS(v, y, u);
      81     2524309 :         WRITE_PIXELS(y, v, y);
      82             :     }
      83       45146 : }
      84             : 
      85          21 : av_cold void ff_v210enc_init(V210EncContext *s)
      86             : {
      87          21 :     s->pack_line_8  = v210_planar_pack_8_c;
      88          21 :     s->pack_line_10 = v210_planar_pack_10_c;
      89          21 :     s->sample_factor_8  = 1;
      90          21 :     s->sample_factor_10 = 1;
      91             : 
      92             :     if (ARCH_X86)
      93          21 :         ff_v210enc_init_x86(s);
      94          21 : }
      95             : 
      96           8 : static av_cold int encode_init(AVCodecContext *avctx)
      97             : {
      98           8 :     V210EncContext *s = avctx->priv_data;
      99             : 
     100           8 :     if (avctx->width & 1) {
     101           0 :         av_log(avctx, AV_LOG_ERROR, "v210 needs even width\n");
     102           0 :         return AVERROR(EINVAL);
     103             :     }
     104             : 
     105             : #if FF_API_CODED_FRAME
     106             : FF_DISABLE_DEPRECATION_WARNINGS
     107           8 :     avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
     108             : FF_ENABLE_DEPRECATION_WARNINGS
     109             : #endif
     110             : 
     111           8 :     ff_v210enc_init(s);
     112             : 
     113           8 :     avctx->bits_per_coded_sample = 20;
     114           8 :     avctx->bit_rate = ff_guess_coded_bitrate(avctx) * 16 / 15;
     115             : 
     116           8 :     return 0;
     117             : }
     118             : 
     119         400 : static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     120             :                         const AVFrame *pic, int *got_packet)
     121             : {
     122         400 :     V210EncContext *s = avctx->priv_data;
     123         400 :     int aligned_width = ((avctx->width + 47) / 48) * 48;
     124         400 :     int stride = aligned_width * 8 / 3;
     125         400 :     int line_padding = stride - ((avctx->width * 8 + 11) / 12) * 4;
     126             :     int h, w, ret;
     127             :     uint8_t *dst;
     128             : 
     129         400 :     ret = ff_alloc_packet2(avctx, pkt, avctx->height * stride, avctx->height * stride);
     130         400 :     if (ret < 0) {
     131           0 :         av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n");
     132           0 :         return ret;
     133             :     }
     134         400 :     dst = pkt->data;
     135             : 
     136         400 :     if (pic->format == AV_PIX_FMT_YUV422P10) {
     137         200 :         const uint16_t *y = (const uint16_t *)pic->data[0];
     138         200 :         const uint16_t *u = (const uint16_t *)pic->data[1];
     139         200 :         const uint16_t *v = (const uint16_t *)pic->data[2];
     140             : 
     141         200 :         const int sample_size = 6 * s->sample_factor_10;
     142         200 :         const int sample_w    = avctx->width / sample_size;
     143             : 
     144       45100 :         for (h = 0; h < avctx->height; h++) {
     145             :             uint32_t val;
     146       44900 :             w = sample_w * sample_size;
     147       44900 :             s->pack_line_10(y, u, v, dst, w);
     148             : 
     149       44900 :             y += w;
     150       44900 :             u += w >> 1;
     151       44900 :             v += w >> 1;
     152       44900 :             dst += sample_w * 16 * s->sample_factor_10;
     153             : 
     154       44900 :             for (; w < avctx->width - 5; w += 6) {
     155           0 :                 WRITE_PIXELS(u, y, v);
     156           0 :                 WRITE_PIXELS(y, u, y);
     157           0 :                 WRITE_PIXELS(v, y, u);
     158           0 :                 WRITE_PIXELS(y, v, y);
     159             :             }
     160       44900 :             if (w < avctx->width - 1) {
     161       44900 :                 WRITE_PIXELS(u, y, v);
     162             : 
     163       44900 :                 val = CLIP(*y++);
     164       44900 :                 if (w == avctx->width - 2) {
     165           0 :                     AV_WL32(dst, val);
     166           0 :                     dst += 4;
     167             :                 }
     168             :             }
     169       44900 :             if (w < avctx->width - 3) {
     170       44900 :                 val |= (CLIP(*u++) << 10) | (CLIP(*y++) << 20);
     171       44900 :                 AV_WL32(dst, val);
     172       44900 :                 dst += 4;
     173             : 
     174       44900 :                 val = CLIP(*v++) | (CLIP(*y++) << 10);
     175       44900 :                 AV_WL32(dst, val);
     176       44900 :                 dst += 4;
     177             :             }
     178             : 
     179       44900 :             memset(dst, 0, line_padding);
     180       44900 :             dst += line_padding;
     181       44900 :             y += pic->linesize[0] / 2 - avctx->width;
     182       44900 :             u += pic->linesize[1] / 2 - avctx->width / 2;
     183       44900 :             v += pic->linesize[2] / 2 - avctx->width / 2;
     184             :         }
     185         200 :     } else if(pic->format == AV_PIX_FMT_YUV422P) {
     186         200 :         const uint8_t *y = pic->data[0];
     187         200 :         const uint8_t *u = pic->data[1];
     188         200 :         const uint8_t *v = pic->data[2];
     189             : 
     190         200 :         const int sample_size = 12 * s->sample_factor_8;
     191         200 :         const int sample_w    = avctx->width / sample_size;
     192             : 
     193       45100 :         for (h = 0; h < avctx->height; h++) {
     194             :             uint32_t val;
     195       44900 :             w = sample_w * sample_size;
     196       44900 :             s->pack_line_8(y, u, v, dst, w);
     197             : 
     198       44900 :             y += w;
     199       44900 :             u += w >> 1;
     200       44900 :             v += w >> 1;
     201       44900 :             dst += sample_w * 32 * s->sample_factor_8;
     202             : 
     203       46600 :             for (; w < avctx->width - 5; w += 6) {
     204        1700 :                 WRITE_PIXELS8(u, y, v);
     205        1700 :                 WRITE_PIXELS8(y, u, y);
     206        1700 :                 WRITE_PIXELS8(v, y, u);
     207        1700 :                 WRITE_PIXELS8(y, v, y);
     208             :             }
     209       44900 :             if (w < avctx->width - 1) {
     210       44900 :                 WRITE_PIXELS8(u, y, v);
     211             : 
     212       44900 :                 val = CLIP8(*y++) << 2;
     213       44900 :                 if (w == avctx->width - 2) {
     214           0 :                     AV_WL32(dst, val);
     215           0 :                     dst += 4;
     216             :                 }
     217             :             }
     218       44900 :             if (w < avctx->width - 3) {
     219       44900 :                 val |= (CLIP8(*u++) << 12) | (CLIP8(*y++) << 22);
     220       44900 :                 AV_WL32(dst, val);
     221       44900 :                 dst += 4;
     222             : 
     223       44900 :                 val = (CLIP8(*v++) << 2) | (CLIP8(*y++) << 12);
     224       44900 :                 AV_WL32(dst, val);
     225       44900 :                 dst += 4;
     226             :             }
     227       44900 :             memset(dst, 0, line_padding);
     228       44900 :             dst += line_padding;
     229             : 
     230       44900 :             y += pic->linesize[0] - avctx->width;
     231       44900 :             u += pic->linesize[1] - avctx->width / 2;
     232       44900 :             v += pic->linesize[2] - avctx->width / 2;
     233             :         }
     234             :     }
     235             : 
     236         400 :     pkt->flags |= AV_PKT_FLAG_KEY;
     237         400 :     *got_packet = 1;
     238         400 :     return 0;
     239             : }
     240             : 
     241             : AVCodec ff_v210_encoder = {
     242             :     .name           = "v210",
     243             :     .long_name      = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"),
     244             :     .type           = AVMEDIA_TYPE_VIDEO,
     245             :     .id             = AV_CODEC_ID_V210,
     246             :     .priv_data_size = sizeof(V210EncContext),
     247             :     .init           = encode_init,
     248             :     .encode2        = encode_frame,
     249             :     .pix_fmts       = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE },
     250             : };

Generated by: LCOV version 1.13