FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/bitpacked_enc.c
Date: 2021-11-29 18:02:40
Exec Total Coverage
Lines: 0 38 0.0%
Branches: 0 12 0.0%

Line Branch Exec Source
1 /*
2 * bitpacked encoder
3 *
4 * Copyright (c) 2021 Limin Wang
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include "avcodec.h"
24 #include "encode.h"
25 #include "internal.h"
26 #include "put_bits.h"
27 #include "libavutil/pixdesc.h"
28
29 struct BitpackedContext {
30 int (*encode)(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame);
31 };
32
33 static int encode_yuv422p10(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame)
34 {
35 const int buf_size = avctx->height * avctx->width * avctx->bits_per_coded_sample / 8;
36 int ret;
37 uint8_t *dst;
38 const uint16_t *y;
39 const uint16_t *u;
40 const uint16_t *v;
41 PutBitContext pb;
42
43 ret = ff_get_encode_buffer(avctx, pkt, buf_size, 0);
44 if (ret < 0) {
45 av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n");
46 return ret;
47 }
48 dst = pkt->data;
49
50 init_put_bits(&pb, dst, buf_size);
51
52 for (int i = 0; i < avctx->height; i++) {
53 y = (uint16_t*)(frame->data[0] + i * frame->linesize[0]);
54 u = (uint16_t*)(frame->data[1] + i * frame->linesize[1]);
55 v = (uint16_t*)(frame->data[2] + i * frame->linesize[2]);
56
57 for (int j = 0; j < avctx->width; j += 2) {
58 /* u, y0, v, y1 */
59 put_bits(&pb, 10, av_clip_uintp2(*u++, 10));
60 put_bits(&pb, 10, av_clip_uintp2(*y++, 10));
61 put_bits(&pb, 10, av_clip_uintp2(*v++, 10));
62 put_bits(&pb, 10, av_clip_uintp2(*y++, 10));
63 }
64 }
65 flush_put_bits(&pb);
66
67 return 0;
68 }
69
70
71 static av_cold int encode_init(AVCodecContext *avctx)
72 {
73 struct BitpackedContext *s = avctx->priv_data;
74 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
75
76 if (avctx->width & 1) {
77 av_log(avctx, AV_LOG_ERROR, "bitpacked needs even width\n");
78 return AVERROR(EINVAL);
79 }
80
81 avctx->bits_per_coded_sample = av_get_bits_per_pixel(desc);
82 avctx->bit_rate = ff_guess_coded_bitrate(avctx);
83
84 if (avctx->pix_fmt == AV_PIX_FMT_YUV422P10)
85 s->encode = encode_yuv422p10;
86 else
87 return AVERROR(EINVAL);
88
89 return 0;
90 }
91
92 static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
93 const AVFrame *frame, int *got_packet)
94 {
95 struct BitpackedContext *s = avctx->priv_data;
96 int ret;
97
98 ret = s->encode(avctx, pkt, frame);
99 if (ret)
100 return ret;
101
102 *got_packet = 1;
103 return 0;
104 }
105
106 const AVCodec ff_bitpacked_encoder = {
107 .name = "bitpacked",
108 .long_name = NULL_IF_CONFIG_SMALL("Bitpacked"),
109 .type = AVMEDIA_TYPE_VIDEO,
110 .id = AV_CODEC_ID_BITPACKED,
111 .priv_data_size = sizeof(struct BitpackedContext),
112 .capabilities = AV_CODEC_CAP_DR1,
113 .init = encode_init,
114 .encode2 = encode_frame,
115 .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P10,
116 AV_PIX_FMT_NONE },
117 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
118 };
119