FFmpeg
vbndec.c
Go to the documentation of this file.
1 /*
2  * Vizrt Binary Image decoder
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 decoder
24  */
25 
26 #include "avcodec.h"
27 #include "bytestream.h"
28 #include "codec_internal.h"
29 #include "decode.h"
30 #include "texturedsp.h"
31 #include "vbn.h"
32 #include "libavutil/imgutils.h"
33 
34 typedef struct VBNContext {
37 } VBNContext;
38 
39 static av_cold int vbn_init(AVCodecContext *avctx)
40 {
41  VBNContext *ctx = avctx->priv_data;
42  ff_texturedsp_init(&ctx->texdsp);
43  return 0;
44 }
45 
46 static int decompress(AVCodecContext *avctx, GetByteContext *gb,
47  int compression, uint8_t **outbuf)
48 {
49  if (compression == VBN_COMPRESSION_NONE) // outbuf is left NULL because gb->buf can be used directly
50  return bytestream2_get_bytes_left(gb);
51 
52  av_log(avctx, AV_LOG_ERROR, "Unsupported VBN compression: 0x%08x\n", compression);
53  return AVERROR_PATCHWELCOME;
54 }
55 
56 static int vbn_decode_frame(AVCodecContext *avctx,
57  AVFrame *frame, int *got_frame,
58  AVPacket *avpkt)
59 {
60  VBNContext *ctx = avctx->priv_data;
61  GetByteContext gb0, *const gb = &gb0;
62  uint8_t *image_buf = NULL;
63  int image_len;
64  int width, height, components, format, compression, pix_fmt, linesize, data_size;
65  int ret;
66 
67  bytestream2_init(gb, avpkt->data, avpkt->size);
68 
70  av_log(avctx, AV_LOG_ERROR, "VBN header truncated\n");
71  return AVERROR_INVALIDDATA;
72  }
73 
74  if (bytestream2_get_le32u(gb) != VBN_MAGIC ||
75  bytestream2_get_le32u(gb) != VBN_MAJOR ||
76  bytestream2_get_le32u(gb) != VBN_MINOR) {
77  av_log(avctx, AV_LOG_ERROR, "Invalid VBN header\n");
78  return AVERROR_INVALIDDATA;
79  }
80 
81  width = bytestream2_get_le32u(gb);
82  height = bytestream2_get_le32u(gb);
83  components = bytestream2_get_le32u(gb);
84  format = bytestream2_get_le32u(gb);
85  pix_fmt = bytestream2_get_le32u(gb);
86  bytestream2_get_le32u(gb); // mipmaps
87  data_size = bytestream2_get_le32u(gb);
88  bytestream2_seek(gb, VBN_HEADER_SIZE, SEEK_SET);
89 
90  compression = format & 0xffffff00;
91  format = format & 0xff;
92 
93  if (data_size != bytestream2_get_bytes_left(gb)) {
94  av_log(avctx, AV_LOG_ERROR, "Truncated packet\n");
95  return AVERROR_INVALIDDATA;
96  }
97 
98  if (pix_fmt != VBN_PIX_RGBA && pix_fmt != VBN_PIX_RGB) {
99  av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format: 0x%08x\n", pix_fmt);
100  return AVERROR_PATCHWELCOME;
101  }
102 
103  ret = ff_set_dimensions(avctx, width, height);
104  if (ret < 0)
105  return ret;
106 
107  if (format == VBN_FORMAT_RAW) {
108  if (pix_fmt == VBN_PIX_RGB && components == 3) {
109  avctx->pix_fmt = AV_PIX_FMT_RGB24;
110  linesize = avctx->width * 3;
111  } else if (pix_fmt == VBN_PIX_RGBA && components == 4) {
112  avctx->pix_fmt = AV_PIX_FMT_RGBA;
113  linesize = avctx->width * 4;
114  } else {
115  av_log(avctx, AV_LOG_ERROR, "Unsupported number of components: %d\n", components);
116  return AVERROR_PATCHWELCOME;
117  }
118  } else if (format == VBN_FORMAT_DXT1 || format == VBN_FORMAT_DXT5) {
119  if (avctx->width % TEXTURE_BLOCK_W || avctx->height % TEXTURE_BLOCK_H) {
120  av_log(avctx, AV_LOG_ERROR, "DXTx compression only supports 4 pixel aligned resolutions\n");
121  return AVERROR_INVALIDDATA;
122  }
123 
124  avctx->pix_fmt = AV_PIX_FMT_RGBA;
125  if (format == VBN_FORMAT_DXT1) {
126  ctx->dec.tex_funct = ctx->texdsp.dxt1_block;
127  ctx->dec.tex_ratio = 8;
128  linesize = avctx->coded_width / 2;
129  } else {
130  ctx->dec.tex_funct = ctx->texdsp.dxt5_block;
131  ctx->dec.tex_ratio = 16;
132  linesize = avctx->coded_width;
133  }
134  } else {
135  av_log(avctx, AV_LOG_ERROR, "Unsupported VBN format: 0x%02x\n", format);
136  return AVERROR_PATCHWELCOME;
137  }
138 
139  image_len = decompress(avctx, gb, compression, &image_buf);
140  if (image_len < 0)
141  return image_len;
142 
143  if (image_len < linesize * avctx->coded_height) {
144  av_log(avctx, AV_LOG_ERROR, "Insufficent data\n");
146  goto out;
147  }
148 
149  ret = ff_get_buffer(avctx, frame, 0);
150  if (ret < 0)
151  goto out;
152 
155 
156  if (format == VBN_FORMAT_RAW) {
157  uint8_t *flipped = frame->data[0] + frame->linesize[0] * (frame->height - 1);
158  av_image_copy_plane(flipped, -frame->linesize[0], image_buf ? image_buf : gb->buffer, linesize, linesize, frame->height);
159  } else {
160  ctx->dec.slice_count = av_clip(avctx->thread_count, 1, avctx->coded_height / TEXTURE_BLOCK_H);
161  ctx->dec.tex_data.in = image_buf ? image_buf : gb->buffer;
162  ctx->dec.raw_ratio = 16;
163  ctx->dec.frame_data.out = frame->data[0] + frame->linesize[0] * (frame->height - 1);
164  ctx->dec.stride = -frame->linesize[0];
165  ctx->dec.width = avctx->coded_width;
166  ctx->dec.height = avctx->coded_height;
168  }
169 
170  *got_frame = 1;
171  ret = avpkt->size;
172 
173 out:
174  av_freep(&image_buf);
175  return ret;
176 }
177 
179  .p.name = "vbn",
180  CODEC_LONG_NAME("Vizrt Binary Image"),
181  .p.type = AVMEDIA_TYPE_VIDEO,
182  .p.id = AV_CODEC_ID_VBN,
183  .init = vbn_init,
185  .priv_data_size = sizeof(VBNContext),
186  .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS,
187 };
av_clip
#define av_clip
Definition: common.h:98
TEXTURE_BLOCK_H
#define TEXTURE_BLOCK_H
Definition: texturedsp.h:43
out
FILE * out
Definition: movenc.c:54
GetByteContext
Definition: bytestream.h:33
VBN_MINOR
#define VBN_MINOR
Definition: vbn.h:31
decompress
static int decompress(AVCodecContext *avctx, GetByteContext *gb, int compression, uint8_t **outbuf)
Definition: vbndec.c:46
bytestream2_seek
static av_always_inline int bytestream2_seek(GetByteContext *g, int offset, int whence)
Definition: bytestream.h:212
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:344
AVPacket::data
uint8_t * data
Definition: packet.h:522
FFCodec
Definition: codec_internal.h:127
AVFrame::flags
int flags
Frame flags, a combination of AV_FRAME_FLAGS.
Definition: frame.h:616
TextureDSPContext
Definition: texturedsp.h:45
ff_set_dimensions
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Check that the provided frame dimensions are valid and set them on the codec context.
Definition: utils.c:94
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
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
AVCodecContext::coded_height
int coded_height
Definition: avcodec.h:633
VBN_HEADER_SIZE
#define VBN_HEADER_SIZE
Definition: vbn.h:33
TextureDSPThreadContext
Definition: texturedsp.h:69
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
VBN_COMPRESSION_NONE
#define VBN_COMPRESSION_NONE
Definition: vbn.h:40
AV_FRAME_FLAG_KEY
#define AV_FRAME_FLAG_KEY
A flag to mark frames that are keyframes.
Definition: frame.h:595
width
#define width
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:287
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
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demux_decode.c:41
GetByteContext::buffer
const uint8_t * buffer
Definition: bytestream.h:34
ctx
AVFormatContext * ctx
Definition: movenc.c:48
decode.h
ff_texturedsp_init
av_cold void ff_texturedsp_init(TextureDSPContext *c)
Definition: texturedsp.c:640
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
NULL
#define NULL
Definition: coverity.c:32
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:64
AV_PICTURE_TYPE_I
@ AV_PICTURE_TYPE_I
Intra.
Definition: avutil.h:279
VBN_MAJOR
#define VBN_MAJOR
Definition: vbn.h:30
VBNContext::texdsp
TextureDSPContext texdsp
Definition: vbndec.c:35
VBN_MAGIC
#define VBN_MAGIC
Definition: vbn.h:29
bytestream2_get_bytes_left
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:158
ff_texturedsp_exec_decompress_threads
int ff_texturedsp_exec_decompress_threads(struct AVCodecContext *avctx, TextureDSPThreadContext *ctx)
AVFrame::pict_type
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:446
ff_get_buffer
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1569
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
AVPacket::size
int size
Definition: packet.h:523
codec_internal.h
vbn_decode_frame
static int vbn_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt)
Definition: vbndec.c:56
VBNContext
Definition: vbndec.c:34
VBN_FORMAT_RAW
#define VBN_FORMAT_RAW
Definition: vbn.h:35
VBNContext::dec
TextureDSPThreadContext dec
Definition: vbndec.c:36
height
#define height
AV_CODEC_CAP_SLICE_THREADS
#define AV_CODEC_CAP_SLICE_THREADS
Codec supports slice-based (or partition-based) multithreading.
Definition: codec.h:114
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
AVCodecContext::height
int height
Definition: avcodec.h:618
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:657
avcodec.h
ff_vbn_decoder
const FFCodec ff_vbn_decoder
Definition: vbndec.c:178
ret
ret
Definition: filter_design.txt:187
AV_CODEC_ID_VBN
@ AV_CODEC_ID_VBN
Definition: codec_id.h:312
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
AVCodecContext::coded_width
int coded_width
Bitstream width / height, may be different from width/height e.g.
Definition: avcodec.h:633
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
vbn.h
VBN_FORMAT_DXT1
#define VBN_FORMAT_DXT1
Definition: vbn.h:37
AVPacket
This structure stores compressed data.
Definition: packet.h:499
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:472
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:618
bytestream.h
imgutils.h
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
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
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
VBN_PIX_RGBA
#define VBN_PIX_RGBA
Definition: vbn.h:47
vbn_init
static av_cold int vbn_init(AVCodecContext *avctx)
Definition: vbndec.c:39