libavcodec/nuv.c
Go to the documentation of this file.
1 /*
2  * NuppelVideo decoder
3  * Copyright (c) 2006 Reimar Doeffinger
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <limits.h>
25 
26 #include "libavutil/bswap.h"
27 #include "libavutil/common.h"
28 #include "libavutil/lzo.h"
29 #include "libavutil/imgutils.h"
30 #include "avcodec.h"
31 #include "internal.h"
32 #include "rtjpeg.h"
33 
34 typedef struct {
37  int quality;
38  int width, height;
39  unsigned int decomp_size;
40  unsigned char *decomp_buf;
41  uint32_t lq[64], cq[64];
44 } NuvContext;
45 
46 static const uint8_t fallback_lquant[] = {
47  16, 11, 10, 16, 24, 40, 51, 61,
48  12, 12, 14, 19, 26, 58, 60, 55,
49  14, 13, 16, 24, 40, 57, 69, 56,
50  14, 17, 22, 29, 51, 87, 80, 62,
51  18, 22, 37, 56, 68, 109, 103, 77,
52  24, 35, 55, 64, 81, 104, 113, 92,
53  49, 64, 78, 87, 103, 121, 120, 101,
54  72, 92, 95, 98, 112, 100, 103, 99
55 };
56 
57 static const uint8_t fallback_cquant[] = {
58  17, 18, 24, 47, 99, 99, 99, 99,
59  18, 21, 26, 66, 99, 99, 99, 99,
60  24, 26, 56, 99, 99, 99, 99, 99,
61  47, 66, 99, 99, 99, 99, 99, 99,
62  99, 99, 99, 99, 99, 99, 99, 99,
63  99, 99, 99, 99, 99, 99, 99, 99,
64  99, 99, 99, 99, 99, 99, 99, 99,
65  99, 99, 99, 99, 99, 99, 99, 99
66 };
67 
68 /**
69  * @brief copy frame data from buffer to AVFrame, handling stride.
70  * @param f destination AVFrame
71  * @param src source buffer, does not use any line-stride
72  * @param width width of the video frame
73  * @param height height of the video frame
74  */
75 static void copy_frame(AVFrame *f, const uint8_t *src, int width, int height)
76 {
77  AVPicture pic;
78  avpicture_fill(&pic, src, AV_PIX_FMT_YUV420P, width, height);
79  av_picture_copy((AVPicture *)f, &pic, AV_PIX_FMT_YUV420P, width, height);
80 }
81 
82 /**
83  * @brief extract quantization tables from codec data into our context
84  */
85 static int get_quant(AVCodecContext *avctx, NuvContext *c, const uint8_t *buf,
86  int size)
87 {
88  int i;
89  if (size < 2 * 64 * 4) {
90  av_log(avctx, AV_LOG_ERROR, "insufficient rtjpeg quant data\n");
91  return AVERROR_INVALIDDATA;
92  }
93  for (i = 0; i < 64; i++, buf += 4)
94  c->lq[i] = AV_RL32(buf);
95  for (i = 0; i < 64; i++, buf += 4)
96  c->cq[i] = AV_RL32(buf);
97  return 0;
98 }
99 
100 /**
101  * @brief set quantization tables from a quality value
102  */
104 {
105  int i;
106  quality = FFMAX(quality, 1);
107  for (i = 0; i < 64; i++) {
108  c->lq[i] = (fallback_lquant[i] << 7) / quality;
109  c->cq[i] = (fallback_cquant[i] << 7) / quality;
110  }
111 }
112 
113 static int codec_reinit(AVCodecContext *avctx, int width, int height,
114  int quality)
115 {
116  NuvContext *c = avctx->priv_data;
117  int ret;
118 
119  width = FFALIGN(width, 2);
120  height = FFALIGN(height, 2);
121  if (quality >= 0)
122  get_quant_quality(c, quality);
123  if (width != c->width || height != c->height) {
124  // also reserve space for a possible additional header
125  int buf_size = 24 + height * width * 3 / 2 + AV_LZO_OUTPUT_PADDING;
126  if (buf_size > INT_MAX/8)
127  return -1;
128  if ((ret = av_image_check_size(height, width, 0, avctx)) < 0)
129  return ret;
130  avctx->width = c->width = width;
131  avctx->height = c->height = height;
133  buf_size);
134  if (!c->decomp_buf) {
135  av_log(avctx, AV_LOG_ERROR,
136  "Can't allocate decompression buffer.\n");
137  return AVERROR(ENOMEM);
138  }
139  ff_rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height,
140  c->lq, c->cq);
141  return 1;
142  } else if (quality != c->quality)
143  ff_rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height,
144  c->lq, c->cq);
145 
146  return 0;
147 }
148 
149 static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
150  AVPacket *avpkt)
151 {
152  const uint8_t *buf = avpkt->data;
153  int buf_size = avpkt->size;
154  NuvContext *c = avctx->priv_data;
155  AVFrame *picture = data;
156  int orig_size = buf_size;
157  int keyframe;
158  int size_change = 0;
159  int result, init_frame = !avctx->frame_number;
160  enum {
161  NUV_UNCOMPRESSED = '0',
162  NUV_RTJPEG = '1',
163  NUV_RTJPEG_IN_LZO = '2',
164  NUV_LZO = '3',
165  NUV_BLACK = 'N',
166  NUV_COPY_LAST = 'L'
167  } comptype;
168 
169  if (buf_size < 12) {
170  av_log(avctx, AV_LOG_ERROR, "coded frame too small\n");
171  return AVERROR_INVALIDDATA;
172  }
173 
174  // codec data (rtjpeg quant tables)
175  if (buf[0] == 'D' && buf[1] == 'R') {
176  int ret;
177  // skip rest of the frameheader.
178  buf = &buf[12];
179  buf_size -= 12;
180  ret = get_quant(avctx, c, buf, buf_size);
181  if (ret < 0)
182  return ret;
183  ff_rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, c->lq,
184  c->cq);
185  return orig_size;
186  }
187 
188  if (buf_size < 12 || buf[0] != 'V') {
189  av_log(avctx, AV_LOG_ERROR, "not a nuv video frame\n");
190  return AVERROR_INVALIDDATA;
191  }
192  comptype = buf[1];
193  switch (comptype) {
194  case NUV_RTJPEG_IN_LZO:
195  case NUV_RTJPEG:
196  keyframe = !buf[2];
197  break;
198  case NUV_COPY_LAST:
199  keyframe = 0;
200  break;
201  default:
202  keyframe = 1;
203  break;
204  }
205 retry:
206  // skip rest of the frameheader.
207  buf = &buf[12];
208  buf_size -= 12;
209  if (comptype == NUV_RTJPEG_IN_LZO || comptype == NUV_LZO) {
210  int outlen = c->decomp_size - AV_LZO_OUTPUT_PADDING, inlen = buf_size;
211  if (av_lzo1x_decode(c->decomp_buf, &outlen, buf, &inlen))
212  av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n");
213  buf = c->decomp_buf;
214  buf_size = c->decomp_size - AV_LZO_OUTPUT_PADDING - outlen;
215  }
216  if (c->codec_frameheader) {
217  int w, h, q;
218  if (buf_size < RTJPEG_HEADER_SIZE) {
219  av_log(avctx, AV_LOG_ERROR, "Too small NUV video frame\n");
220  return AVERROR_INVALIDDATA;
221  }
222  // There seem to exist two variants of this header: one starts with 'V'
223  // and 5 bytes unknown, the other matches current MythTV and is 4 bytes size,
224  // 1 byte header size (== 12), 1 byte version (== 0)
225  if (buf[0] != 'V' && AV_RL16(&buf[4]) != 0x000c) {
226  av_log(avctx, AV_LOG_ERROR, "Unknown secondary frame header (wrong codec_tag?)\n");
227  return AVERROR_INVALIDDATA;
228  }
229  w = AV_RL16(&buf[6]);
230  h = AV_RL16(&buf[8]);
231  q = buf[10];
232  if ((result = codec_reinit(avctx, w, h, q)) < 0)
233  return result;
234  if (result) {
235  buf = avpkt->data;
236  buf_size = avpkt->size;
237  size_change = 1;
238  goto retry;
239  }
240  buf = &buf[RTJPEG_HEADER_SIZE];
241  buf_size -= RTJPEG_HEADER_SIZE;
242  }
243 
244  if (size_change || keyframe) {
245  av_frame_unref(&c->pic);
246  init_frame = 1;
247  }
248 
249  if ((result = ff_reget_buffer(avctx, &c->pic)) < 0)
250  return result;
251  if (init_frame) {
252  memset(c->pic.data[0], 0, avctx->height * c->pic.linesize[0]);
253  memset(c->pic.data[1], 0x80, avctx->height * c->pic.linesize[1] / 2);
254  memset(c->pic.data[2], 0x80, avctx->height * c->pic.linesize[2] / 2);
255  }
256 
258  c->pic.key_frame = keyframe;
259  // decompress/copy/whatever data
260  switch (comptype) {
261  case NUV_LZO:
262  case NUV_UNCOMPRESSED: {
263  int height = c->height;
264  if (buf_size < c->width * height * 3 / 2) {
265  av_log(avctx, AV_LOG_ERROR, "uncompressed frame too short\n");
266  height = buf_size / c->width / 3 * 2;
267  }
268  if(height > 0)
269  copy_frame(&c->pic, buf, c->width, height);
270  break;
271  }
272  case NUV_RTJPEG_IN_LZO:
273  case NUV_RTJPEG:
274  ff_rtjpeg_decode_frame_yuv420(&c->rtj, &c->pic, buf, buf_size);
275  break;
276  case NUV_BLACK:
277  memset(c->pic.data[0], 0, c->width * c->height);
278  memset(c->pic.data[1], 128, c->width * c->height / 4);
279  memset(c->pic.data[2], 128, c->width * c->height / 4);
280  break;
281  case NUV_COPY_LAST:
282  /* nothing more to do here */
283  break;
284  default:
285  av_log(avctx, AV_LOG_ERROR, "unknown compression\n");
286  return AVERROR_INVALIDDATA;
287  }
288 
289  if ((result = av_frame_ref(picture, &c->pic)) < 0)
290  return result;
291 
292  *got_frame = 1;
293  return orig_size;
294 }
295 
297 {
298  NuvContext *c = avctx->priv_data;
299  int ret;
300 
301  avctx->pix_fmt = AV_PIX_FMT_YUV420P;
302  c->pic.data[0] = NULL;
303  c->decomp_buf = NULL;
304  c->quality = -1;
305  c->width = 0;
306  c->height = 0;
307 
308  c->codec_frameheader = avctx->codec_tag == MKTAG('R', 'J', 'P', 'G');
309 
310  if (avctx->extradata_size)
311  get_quant(avctx, c, avctx->extradata, avctx->extradata_size);
312 
313  ff_dsputil_init(&c->dsp, avctx);
314 
315  if ((ret = codec_reinit(avctx, avctx->width, avctx->height, -1)) < 0)
316  return ret;
317 
318  return 0;
319 }
320 
322 {
323  NuvContext *c = avctx->priv_data;
324 
325  av_freep(&c->decomp_buf);
326  av_frame_unref(&c->pic);
327 
328  return 0;
329 }
330 
332  .name = "nuv",
333  .type = AVMEDIA_TYPE_VIDEO,
334  .id = AV_CODEC_ID_NUV,
335  .priv_data_size = sizeof(NuvContext),
336  .init = decode_init,
337  .close = decode_end,
338  .decode = decode_frame,
339  .capabilities = CODEC_CAP_DR1,
340  .long_name = NULL_IF_CONFIG_SMALL("NuppelVideo/RTJPEG"),
341 };
av_cold void ff_dsputil_init(DSPContext *c, AVCodecContext *avctx)
Definition: dsputil.c:2675
static av_cold int decode_end(AVCodecContext *avctx)
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
misc image utilities
AVFrame pic
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
Sinusoidal phase f
static int get_quant(AVCodecContext *avctx, NuvContext *c, const uint8_t *buf, int size)
extract quantization tables from codec data into our context
DSPContext dsp
int codec_frameheader
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
#define AV_RL16
static void get_quant_quality(NuvContext *c, int quality)
set quantization tables from a quality value
static const uint8_t fallback_lquant[]
four components are given, that&#39;s all.
int avpicture_fill(AVPicture *picture, const uint8_t *ptr, enum AVPixelFormat pix_fmt, int width, int height)
Fill in the AVPicture fields, always assume a linesize alignment of 1.
Definition: avpicture.c:34
output residual component w
#define FFALIGN(x, a)
Definition: common.h:63
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
void av_picture_copy(AVPicture *dst, const AVPicture *src, enum AVPixelFormat pix_fmt, int width, int height)
Copy image src to dst.
Definition: avpicture.c:72
void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
Allocate a buffer, reusing the given one if large enough.
uint8_t
#define av_cold
Definition: attributes.h:78
int ff_rtjpeg_decode_frame_yuv420(RTJpegContext *c, AVFrame *f, const uint8_t *buf, int buf_size)
decode one rtjpeg YUV420 frame
Definition: rtjpeg.c:106
#define AV_LZO_OUTPUT_PADDING
Definition: lzo.h:47
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
#define CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
void ff_rtjpeg_decode_init(RTJpegContext *c, DSPContext *dsp, int width, int height, const uint32_t *lquant, const uint32_t *cquant)
initialize an RTJpegContext, may be called multiple times
Definition: rtjpeg.c:156
uint8_t * data
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Spectrum Plot time data
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
const char * name
Name of the codec implementation.
#define FFMAX(a, b)
Definition: common.h:56
external API header
int size
static av_cold int decode_init(AVCodecContext *avctx)
AVCodec ff_nuv_decoder
unsigned char * decomp_buf
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
Definition: imgutils.c:231
int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame)
Identical in function to av_frame_make_writable(), except it uses ff_get_buffer() to allocate the buf...
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:144
ret
Definition: avfilter.c:821
int width
picture width / height.
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about quality
int av_lzo1x_decode(void *out, int *outlen, const void *in, int *inlen)
Decodes LZO 1x compressed data.
Definition: lzo.c:126
#define AV_RL32
NULL
Definition: eval.c:55
static int width
Definition: tests/utils.c:158
AVS_Value src
Definition: avisynth_c.h:523
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:101
main external API structure.
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:375
static void copy_frame(AVFrame *f, const uint8_t *src, int width, int height)
copy frame data from buffer to AVFrame, handling stride.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
unsigned int codec_tag
fourcc (LSB first, so "ABCD" -> (&#39;D&#39;<<24) + (&#39;C&#39;<<16) + (&#39;B&#39;<<8) + &#39;A&#39;).
void * buf
Definition: avisynth_c.h:594
BYTE int const BYTE int int int height
Definition: avisynth_c.h:713
synthesis window for stochastic i
byte swapping routines
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:330
unsigned int decomp_size
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer 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.Buffer references ownership and permissions
int av_frame_ref(AVFrame *dst, AVFrame *src)
Setup a new reference to the data described by an given frame.
Definition: frame.c:228
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
static const uint8_t fallback_cquant[]
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:68
common internal api header.
common internal and external API header
static double c[64]
static int codec_reinit(AVCodecContext *avctx, int width, int height, int quality)
uint32_t lq[64]
#define RTJPEG_HEADER_SIZE
Definition: rtjpeg.h:30
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:139
int frame_number
Frame counter, set by libavcodec.
static void init_frame(FlacEncodeContext *s, int nb_samples)
static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
RTJpegContext rtj
static int decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: crystalhd.c:868
#define MKTAG(a, b, c, d)
Definition: common.h:282
This structure stores compressed data.
uint32_t cq[64]
Predicted.
Definition: avutil.h:217
DSPContext.
Definition: dsputil.h:127