FFmpeg
vbnenc.c
Go to the documentation of this file.
1 /*
2  * Vizrt Binary Image encoder
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /**
22  * @file
23  * Vizrt Binary Image encoder
24  */
25 
26 #include "avcodec.h"
27 #include "bytestream.h"
28 #include "codec_internal.h"
29 #include "encode.h"
30 #include "texturedsp.h"
31 #include "vbn.h"
32 
33 #include "libavutil/imgutils.h"
34 #include "libavutil/frame.h"
35 #include "libavutil/opt.h"
36 
37 typedef struct VBNContext {
38  AVClass *class;
40  int format;
42 } VBNContext;
43 
44 static int vbn_encode(AVCodecContext *avctx, AVPacket *pkt,
45  const AVFrame *frame, int *got_packet)
46 {
47  VBNContext *ctx = avctx->priv_data;
48  PutByteContext pb0, *const pb = &pb0;
49  int ret;
50  ptrdiff_t linesize;
51  int64_t pkt_size;
52 
53  ret = av_image_check_size2(frame->width, frame->height, INT_MAX, frame->format, 0, avctx);
54  if (ret < 0)
55  return ret;
56 
57  if (ctx->format == VBN_FORMAT_DXT1 || ctx->format == VBN_FORMAT_DXT5) {
59  av_log(avctx, AV_LOG_ERROR, "Video size %dx%d is not multiple of 4\n", frame->width, frame->height);
60  return AVERROR(EINVAL);
61  }
62  if (frame->format != AV_PIX_FMT_RGBA) {
63  av_log(avctx, AV_LOG_ERROR, "DXT formats only support RGBA pixel format\n");
64  return AVERROR(EINVAL);
65  }
66  ctx->enc.raw_ratio = 16;
67  ctx->enc.slice_count = av_clip(avctx->thread_count, 1, avctx->height / TEXTURE_BLOCK_H);
68  }
69 
70  switch (ctx->format) {
71  case VBN_FORMAT_DXT1:
72  linesize = frame->width / 2;
73  ctx->enc.tex_funct = ctx->dxtc.dxt1_block;
74  ctx->enc.tex_ratio = 8;
75  break;
76  case VBN_FORMAT_DXT5:
77  linesize = frame->width;
78  ctx->enc.tex_funct = ctx->dxtc.dxt5_block;
79  ctx->enc.tex_ratio = 16;
80  break;
81  case VBN_FORMAT_RAW:
82  linesize = av_image_get_linesize(frame->format, frame->width, 0);
83  if (linesize < 0)
84  return linesize;
85  break;
86  default:
87  av_log(avctx, AV_LOG_ERROR, "Invalid format %02X\n", ctx->format);
88  return AVERROR(EINVAL);
89  }
90 
91  pkt_size = VBN_HEADER_SIZE + linesize * frame->height;
92  if (pkt_size > INT_MAX)
93  return AVERROR(EINVAL);
94 
95  if ((ret = ff_get_encode_buffer(avctx, pkt, pkt_size, 0)) < 0)
96  return ret;
97 
98  memset(pkt->data, 0, VBN_HEADER_SIZE);
99  bytestream2_init_writer(pb, pkt->data, pkt_size);
100  bytestream2_put_le32u(pb, VBN_MAGIC);
101  bytestream2_put_le32u(pb, VBN_MAJOR);
102  bytestream2_put_le32u(pb, VBN_MINOR);
103  bytestream2_put_le32u(pb, frame->width);
104  bytestream2_put_le32u(pb, frame->height);
105  bytestream2_put_le32u(pb, frame->format == AV_PIX_FMT_RGBA ? 4 : 3);
106  bytestream2_put_le32u(pb, ctx->format);
107  bytestream2_put_le32u(pb, frame->format == AV_PIX_FMT_RGBA ? VBN_PIX_RGBA : VBN_PIX_RGB);
108  bytestream2_put_le32u(pb, 0); // mipmaps
109  bytestream2_put_le32u(pb, pkt_size - VBN_HEADER_SIZE);
110  bytestream2_seek_p(pb, 64, SEEK_SET);
111  bytestream2_put_le32u(pb, pkt_size - VBN_HEADER_SIZE);
112 
113  if (ctx->format == VBN_FORMAT_DXT1 || ctx->format == VBN_FORMAT_DXT5) {
114  ctx->enc.frame_data.in = (frame->height - 1) * frame->linesize[0] + frame->data[0];
115  ctx->enc.stride = -frame->linesize[0];
116  ctx->enc.tex_data.out = pkt->data + VBN_HEADER_SIZE;
117  ctx->enc.width = avctx->width;
118  ctx->enc.height = avctx->height;
120  } else {
121  const uint8_t *flipped = frame->data[0] + frame->linesize[0] * (frame->height - 1);
122  av_image_copy_plane(pkt->data + VBN_HEADER_SIZE, linesize, flipped, -frame->linesize[0], linesize, frame->height);
123  }
124 
125  *got_packet = 1;
126  return 0;
127 }
128 
129 static av_cold int vbn_init(AVCodecContext *avctx)
130 {
131  VBNContext *ctx = avctx->priv_data;
132  ff_texturedspenc_init(&ctx->dxtc);
133  return 0;
134 }
135 
136 #define OFFSET(x) offsetof(VBNContext, x)
137 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
138 static const AVOption options[] = {
139  { "format", "Texture format", OFFSET(format), AV_OPT_TYPE_INT, { .i64 = VBN_FORMAT_DXT5 }, VBN_FORMAT_RAW, VBN_FORMAT_DXT5, FLAGS, .unit = "format" },
140  { "raw", "RAW texture", 0, AV_OPT_TYPE_CONST, { .i64 = VBN_FORMAT_RAW }, 0, 0, FLAGS, .unit = "format" },
141  { "dxt1", "DXT1 texture", 0, AV_OPT_TYPE_CONST, { .i64 = VBN_FORMAT_DXT1 }, 0, 0, FLAGS, .unit = "format" },
142  { "dxt5", "DXT5 texture", 0, AV_OPT_TYPE_CONST, { .i64 = VBN_FORMAT_DXT5 }, 0, 0, FLAGS, .unit = "format" },
143  { NULL },
144 };
145 
146 static const AVClass vbnenc_class = {
147  .class_name = "VBN encoder",
148  .item_name = av_default_item_name,
149  .option = options,
150  .version = LIBAVUTIL_VERSION_INT,
151 };
152 
154  .p.name = "vbn",
155  CODEC_LONG_NAME("Vizrt Binary Image"),
156  .p.type = AVMEDIA_TYPE_VIDEO,
157  .p.id = AV_CODEC_ID_VBN,
158  .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS |
160  .p.priv_class = &vbnenc_class,
161  .init = vbn_init,
163  .priv_data_size = sizeof(VBNContext),
164  .p.pix_fmts = (const enum AVPixelFormat[]) {
166  },
167  .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
168 };
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
av_clip
#define av_clip
Definition: common.h:98
FF_CODEC_CAP_INIT_CLEANUP
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
Definition: codec_internal.h:42
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
TEXTURE_BLOCK_H
#define TEXTURE_BLOCK_H
Definition: texturedsp.h:43
VBN_MINOR
#define VBN_MINOR
Definition: vbn.h:31
int64_t
long long int64_t
Definition: coverity.c:34
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:344
AVFrame::width
int width
Definition: frame.h:416
AVPacket::data
uint8_t * data
Definition: packet.h:522
TextureDSPEncContext
Definition: texturedsp.h:63
AVOption
AVOption.
Definition: opt.h:346
encode.h
FFCodec
Definition: codec_internal.h:127
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:365
av_image_copy_plane
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
Definition: imgutils.c:374
texturedsp.h
ff_texturedspenc_init
void ff_texturedspenc_init(TextureDSPEncContext *c)
Definition: texturedspenc.c:650
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
AVCodecContext::thread_count
int thread_count
thread count is used to decide how many independent tasks should be passed to execute()
Definition: avcodec.h:1582
OFFSET
#define OFFSET(x)
Definition: vbnenc.c:136
FF_CODEC_ENCODE_CB
#define FF_CODEC_ENCODE_CB(func)
Definition: codec_internal.h:296
VBN_HEADER_SIZE
#define VBN_HEADER_SIZE
Definition: vbn.h:33
TextureDSPThreadContext
Definition: texturedsp.h:69
av_image_check_size2
int av_image_check_size2(unsigned int w, unsigned int h, int64_t max_pixels, enum AVPixelFormat pix_fmt, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of a plane of an image with...
Definition: imgutils.c:289
vbn_encode
static int vbn_encode(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet)
Definition: vbnenc.c:44
pkt
AVPacket * pkt
Definition: movenc.c:59
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
VBNContext::format
int format
Definition: vbnenc.c:40
bytestream2_init_writer
static av_always_inline void bytestream2_init_writer(PutByteContext *p, uint8_t *buf, int buf_size)
Definition: bytestream.h:147
format
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample format(the sample packing is implied by the sample format) and sample rate. The lists are not just lists
AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
This encoder can reorder user opaque values from input AVFrames and return them with corresponding ou...
Definition: codec.h:159
ctx
AVFormatContext * ctx
Definition: movenc.c:48
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:272
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:100
frame
static AVFrame * frame
Definition: demux_decode.c:54
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
NULL
#define NULL
Definition: coverity.c:32
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
VBN_MAJOR
#define VBN_MAJOR
Definition: vbn.h:30
VBN_MAGIC
#define VBN_MAGIC
Definition: vbn.h:29
PutByteContext
Definition: bytestream.h:37
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:75
AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
ff_vbn_encoder
const FFCodec ff_vbn_encoder
Definition: vbnenc.c:153
codec_internal.h
VBNContext
Definition: vbndec.c:34
ff_texturedsp_exec_compress_threads
int ff_texturedsp_exec_compress_threads(struct AVCodecContext *avctx, TextureDSPThreadContext *ctx)
VBN_FORMAT_RAW
#define VBN_FORMAT_RAW
Definition: vbn.h:35
AVFrame::format
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition: frame.h:431
frame.h
AV_CODEC_CAP_SLICE_THREADS
#define AV_CODEC_CAP_SLICE_THREADS
Codec supports slice-based (or partition-based) multithreading.
Definition: codec.h:114
FLAGS
#define FLAGS
Definition: vbnenc.c:137
av_image_get_linesize
int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane)
Compute the size of an image line with format pix_fmt and width width for the plane plane.
Definition: imgutils.c:76
VBN_FORMAT_DXT5
#define VBN_FORMAT_DXT5
Definition: vbn.h:38
TEXTURE_BLOCK_W
#define TEXTURE_BLOCK_W
Definition: texturedsp.h:42
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:194
options
static const AVOption options[]
Definition: vbnenc.c:138
AVCodecContext::height
int height
Definition: avcodec.h:618
VBNContext::enc
TextureDSPThreadContext enc
Definition: vbnenc.c:41
avcodec.h
ret
ret
Definition: filter_design.txt:187
AV_CODEC_ID_VBN
@ AV_CODEC_ID_VBN
Definition: codec_id.h:312
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:71
VBN_PIX_RGB
#define VBN_PIX_RGB
Definition: vbn.h:46
AVCodecContext
main external API structure.
Definition: avcodec.h:445
AVFrame::height
int height
Definition: frame.h:416
ff_get_encode_buffer
int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags)
Get a buffer for a packet.
Definition: encode.c:105
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
bytestream2_seek_p
static av_always_inline int bytestream2_seek_p(PutByteContext *p, int offset, int whence)
Definition: bytestream.h:236
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:235
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
vbn_init
static av_cold int vbn_init(AVCodecContext *avctx)
Definition: vbnenc.c:129
vbn.h
VBN_FORMAT_DXT1
#define VBN_FORMAT_DXT1
Definition: vbn.h:37
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:472
AVPacket
This structure stores compressed data.
Definition: packet.h:499
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:618
VBNContext::dxtc
TextureDSPEncContext dxtc
Definition: vbnenc.c:39
bytestream.h
imgutils.h
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:389
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:244
VBN_PIX_RGBA
#define VBN_PIX_RGBA
Definition: vbn.h:47
vbnenc_class
static const AVClass vbnenc_class
Definition: vbnenc.c:146