4 * Copyright (c) 2021 Limin Wang
6 * This file is part of FFmpeg.
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.
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.
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
24 #include "codec_internal.h"
28 #include "libavutil/pixdesc.h"
30 struct BitpackedContext
{
31 int (*encode
)(AVCodecContext
*avctx
, AVPacket
*pkt
, const AVFrame
*frame
);
34 static int encode_yuv422p10(AVCodecContext
*avctx
, AVPacket
*pkt
, const AVFrame
*frame
)
36 const int buf_size
= avctx
->height
* avctx
->width
* avctx
->bits_per_coded_sample
/ 8;
44 ret
= ff_get_encode_buffer(avctx
, pkt
, buf_size
, 0);
46 av_log(avctx
, AV_LOG_ERROR
, "Error getting output packet.\n");
51 init_put_bits(&pb
, dst
, buf_size
);
53 for (int i
= 0; i
< avctx
->height
; i
++) {
54 y
= (uint16_t*)(frame
->data
[0] + i
* frame
->linesize
[0]);
55 u
= (uint16_t*)(frame
->data
[1] + i
* frame
->linesize
[1]);
56 v
= (uint16_t*)(frame
->data
[2] + i
* frame
->linesize
[2]);
58 for (int j
= 0; j
< avctx
->width
; j
+= 2) {
60 put_bits(&pb
, 10, av_clip_uintp2(*u
++, 10));
61 put_bits(&pb
, 10, av_clip_uintp2(*y
++, 10));
62 put_bits(&pb
, 10, av_clip_uintp2(*v
++, 10));
63 put_bits(&pb
, 10, av_clip_uintp2(*y
++, 10));
72 static av_cold
int encode_init(AVCodecContext
*avctx
)
74 struct BitpackedContext
*s
= avctx
->priv_data
;
75 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(avctx
->pix_fmt
);
77 if (avctx
->width
& 1) {
78 av_log(avctx
, AV_LOG_ERROR
, "bitpacked needs even width\n");
79 return AVERROR(EINVAL
);
82 avctx
->bits_per_coded_sample
= av_get_bits_per_pixel(desc
);
83 avctx
->bit_rate
= ff_guess_coded_bitrate(avctx
);
85 if (avctx
->pix_fmt
== AV_PIX_FMT_YUV422P10
)
86 s
->encode
= encode_yuv422p10
;
88 return AVERROR(EINVAL
);
93 static int encode_frame(AVCodecContext
*avctx
, AVPacket
*pkt
,
94 const AVFrame
*frame
, int *got_packet
)
96 struct BitpackedContext
*s
= avctx
->priv_data
;
99 ret
= s
->encode(avctx
, pkt
, frame
);
107 const FFCodec ff_bitpacked_encoder
= {
108 .p
.name
= "bitpacked",
109 .p
.long_name
= NULL_IF_CONFIG_SMALL("Bitpacked"),
110 .p
.type
= AVMEDIA_TYPE_VIDEO
,
111 .p
.id
= AV_CODEC_ID_BITPACKED
,
112 .priv_data_size
= sizeof(struct BitpackedContext
),
113 .p
.capabilities
= AV_CODEC_CAP_DR1
| AV_CODEC_CAP_FRAME_THREADS
,
115 FF_CODEC_ENCODE_CB(encode_frame
),
116 .p
.pix_fmts
= (const enum AVPixelFormat
[]){ AV_PIX_FMT_YUV422P10
,
118 .caps_internal
= FF_CODEC_CAP_INIT_THREADSAFE
,