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) {
58  if (frame->width % TEXTURE_BLOCK_W || frame->height % TEXTURE_BLOCK_H) {
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  avctx->execute2(avctx, ff_texturedsp_compress_thread, &ctx->enc, NULL, ctx->enc.slice_count);
118  } else {
119  const uint8_t *flipped = frame->data[0] + frame->linesize[0] * (frame->height - 1);
120  av_image_copy_plane(pkt->data + VBN_HEADER_SIZE, linesize, flipped, -frame->linesize[0], linesize, frame->height);
121  }
122 
123  *got_packet = 1;
124  return 0;
125 }
126 
127 static av_cold int vbn_init(AVCodecContext *avctx)
128 {
129  VBNContext *ctx = avctx->priv_data;
130  ff_texturedspenc_init(&ctx->dxtc);
131  return 0;
132 }
133 
134 #define OFFSET(x) offsetof(VBNContext, x)
135 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
136 static const AVOption options[] = {
137  { "format", "Texture format", OFFSET(format), AV_OPT_TYPE_INT, { .i64 = VBN_FORMAT_DXT5 }, VBN_FORMAT_RAW, VBN_FORMAT_DXT5, FLAGS, "format" },
138  { "raw", "RAW texture", 0, AV_OPT_TYPE_CONST, { .i64 = VBN_FORMAT_RAW }, 0, 0, FLAGS, "format" },
139  { "dxt1", "DXT1 texture", 0, AV_OPT_TYPE_CONST, { .i64 = VBN_FORMAT_DXT1 }, 0, 0, FLAGS, "format" },
140  { "dxt5", "DXT5 texture", 0, AV_OPT_TYPE_CONST, { .i64 = VBN_FORMAT_DXT5 }, 0, 0, FLAGS, "format" },
141  { NULL },
142 };
143 
144 static const AVClass vbnenc_class = {
145  .class_name = "VBN encoder",
146  .item_name = av_default_item_name,
147  .option = options,
148  .version = LIBAVUTIL_VERSION_INT,
149 };
150 
152  .p.name = "vbn",
153  CODEC_LONG_NAME("Vizrt Binary Image"),
154  .p.type = AVMEDIA_TYPE_VIDEO,
155  .p.id = AV_CODEC_ID_VBN,
156  .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS |
158  .p.priv_class = &vbnenc_class,
159  .init = vbn_init,
161  .priv_data_size = sizeof(VBNContext),
162  .p.pix_fmts = (const enum AVPixelFormat[]) {
164  },
165  .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
166 };
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
av_clip
#define av_clip
Definition: common.h:95
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:45
VBN_MINOR
#define VBN_MINOR
Definition: vbn.h:31
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:330
AVPacket::data
uint8_t * data
Definition: packet.h:374
AVOption
AVOption.
Definition: opt.h:251
encode.h
FFCodec
Definition: codec_internal.h:127
TextureDSPContext
Definition: texturedsp.h:47
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
ff_texturedsp_compress_thread
int ff_texturedsp_compress_thread(AVCodecContext *avctx, void *arg, int slice, int thread_nb)
texturedsp.h
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:1502
OFFSET
#define OFFSET(x)
Definition: vbnenc.c:134
FF_CODEC_ENCODE_CB
#define FF_CODEC_ENCODE_CB(func)
Definition: codec_internal.h:315
VBN_HEADER_SIZE
#define VBN_HEADER_SIZE
Definition: vbn.h:33
VBNContext::dxtc
TextureDSPContext dxtc
Definition: vbnenc.c:39
TextureDSPThreadContext
Definition: texturedsp.h:65
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:156
ctx
AVFormatContext * ctx
Definition: movenc.c:48
ff_texturedspenc_init
void ff_texturedspenc_init(TextureDSPContext *c)
Definition: texturedspenc.c:666
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:93
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:68
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:151
codec_internal.h
VBNContext
Definition: vbndec.c:34
VBN_FORMAT_RAW
#define VBN_FORMAT_RAW
Definition: vbn.h:35
frame.h
AV_CODEC_CAP_SLICE_THREADS
#define AV_CODEC_CAP_SLICE_THREADS
Codec supports slice-based (or partition-based) multithreading.
Definition: codec.h:111
FLAGS
#define FLAGS
Definition: vbnenc.c:135
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:44
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:191
options
static const AVOption options[]
Definition: vbnenc.c:136
AVCodecContext::height
int height
Definition: avcodec.h:598
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:315
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
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
VBN_PIX_RGB
#define VBN_PIX_RGB
Definition: vbn.h:46
AVCodecContext
main external API structure.
Definition: avcodec.h:426
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:79
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
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:225
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
vbn_init
static av_cold int vbn_init(AVCodecContext *avctx)
Definition: vbnenc.c:127
vbn.h
VBN_FORMAT_DXT1
#define VBN_FORMAT_DXT1
Definition: vbn.h:37
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:453
AVPacket
This structure stores compressed data.
Definition: packet.h:351
bytestream.h
imgutils.h
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:234
AVCodecContext::execute2
int(* execute2)(struct AVCodecContext *c, int(*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count)
The codec may call this to execute several independent things.
Definition: avcodec.h:1551
VBN_PIX_RGBA
#define VBN_PIX_RGBA
Definition: vbn.h:47
vbnenc_class
static const AVClass vbnenc_class
Definition: vbnenc.c:144