FFmpeg
qtrleenc.c
Go to the documentation of this file.
1 /*
2  * Quicktime Animation (RLE) Video Encoder
3  * Copyright (C) 2007 Clemens Fruhwirth
4  * Copyright (C) 2007 Alexis Ballier
5  *
6  * This file is based on flashsvenc.c.
7  *
8  * This file is part of FFmpeg.
9  *
10  * FFmpeg is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * FFmpeg is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with FFmpeg; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  */
24 
25 #include "libavutil/imgutils.h"
26 #include "avcodec.h"
27 #include "bytestream.h"
28 #include "internal.h"
29 
30 /** Maximum RLE code for bulk copy */
31 #define MAX_RLE_BULK 127
32 /** Maximum RLE code for repeat */
33 #define MAX_RLE_REPEAT 128
34 /** Maximum RLE code for skip */
35 #define MAX_RLE_SKIP 254
36 
37 typedef struct QtrleEncContext {
41  unsigned int max_buf_size;
43  /**
44  * This array will contain at ith position the value of the best RLE code
45  * if the line started at pixel i
46  * There can be 3 values :
47  * skip (0) : skip as much as possible pixels because they are equal to the
48  * previous frame ones
49  * repeat (<-1) : repeat that pixel -rle_code times, still as much as
50  * possible
51  * copy (>0) : copy the raw next rle_code pixels */
52  signed char *rlecode_table;
53  /**
54  * This array will contain the length of the best rle encoding of the line
55  * starting at ith pixel */
57  /**
58  * Will contain at ith position the number of consecutive pixels equal to the previous
59  * frame starting from pixel i */
60  uint8_t* skip_table;
61 
62  /** Encoded frame is a key frame */
63  int key_frame;
65 
67 {
68  QtrleEncContext *s = avctx->priv_data;
69 
70  av_frame_free(&s->previous_frame);
71  av_free(s->rlecode_table);
72  av_free(s->length_table);
73  av_free(s->skip_table);
74  return 0;
75 }
76 
78 {
79  QtrleEncContext *s = avctx->priv_data;
80 
81  if (av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0) {
82  return AVERROR(EINVAL);
83  }
84  s->avctx=avctx;
85  s->logical_width=avctx->width;
86 
87  switch (avctx->pix_fmt) {
88  case AV_PIX_FMT_GRAY8:
89  if (avctx->width % 4) {
90  av_log(avctx, AV_LOG_ERROR, "Width not being a multiple of 4 is not supported\n");
91  return AVERROR(EINVAL);
92  }
93  s->logical_width = avctx->width / 4;
94  s->pixel_size = 4;
95  break;
97  s->pixel_size = 2;
98  break;
99  case AV_PIX_FMT_RGB24:
100  s->pixel_size = 3;
101  break;
102  case AV_PIX_FMT_ARGB:
103  s->pixel_size = 4;
104  break;
105  default:
106  av_log(avctx, AV_LOG_ERROR, "Unsupported colorspace.\n");
107  break;
108  }
109  avctx->bits_per_coded_sample = avctx->pix_fmt == AV_PIX_FMT_GRAY8 ? 40 : s->pixel_size*8;
110 
111  s->rlecode_table = av_mallocz(s->logical_width);
112  s->skip_table = av_mallocz(s->logical_width);
113  s->length_table = av_mallocz_array(s->logical_width + 1, sizeof(int));
114  if (!s->skip_table || !s->length_table || !s->rlecode_table) {
115  av_log(avctx, AV_LOG_ERROR, "Error allocating memory.\n");
116  return AVERROR(ENOMEM);
117  }
118  s->previous_frame = av_frame_alloc();
119  if (!s->previous_frame) {
120  av_log(avctx, AV_LOG_ERROR, "Error allocating picture\n");
121  return AVERROR(ENOMEM);
122  }
123 
124  s->max_buf_size = s->logical_width*s->avctx->height*s->pixel_size*2 /* image base material */
125  + 15 /* header + footer */
126  + s->avctx->height*2 /* skip code+rle end */
127  + s->logical_width/MAX_RLE_BULK + 1 /* rle codes */;
128 
129  return 0;
130 }
131 
132 /**
133  * Compute the best RLE sequence for a line
134  */
135 static void qtrle_encode_line(QtrleEncContext *s, const AVFrame *p, int line, uint8_t **buf)
136 {
137  int width=s->logical_width;
138  int i;
139  signed char rlecode;
140 
141  /* This will be the number of pixels equal to the previous frame one's
142  * starting from the ith pixel */
143  unsigned int skipcount;
144  /* This will be the number of consecutive equal pixels in the current
145  * frame, starting from the ith one also */
146  unsigned int av_uninit(repeatcount);
147 
148  /* The cost of the three different possibilities */
149  int total_skip_cost;
150  int total_repeat_cost;
151 
152  int base_bulk_cost;
153  int lowest_bulk_cost;
154  int lowest_bulk_cost_index;
155  int sec_lowest_bulk_cost;
156  int sec_lowest_bulk_cost_index;
157 
158  const uint8_t *this_line = p->data[0] + line * p->linesize[0] + width * s->pixel_size;
159  /* There might be no earlier frame if the current frame is a keyframe.
160  * So just use a pointer to the current frame to avoid a check
161  * to avoid NULL - s->pixel_size (which is undefined behaviour). */
162  const uint8_t *prev_line = s->key_frame ? this_line
163  : s->previous_frame->data[0]
164  + line * s->previous_frame->linesize[0]
165  + width * s->pixel_size;
166 
167  s->length_table[width] = 0;
168  skipcount = 0;
169 
170  /* Initial values */
171  lowest_bulk_cost = INT_MAX / 2;
172  lowest_bulk_cost_index = width;
173  sec_lowest_bulk_cost = INT_MAX / 2;
174  sec_lowest_bulk_cost_index = width;
175 
176  base_bulk_cost = 1 + s->pixel_size;
177 
178  for (i = width - 1; i >= 0; i--) {
179 
180  int prev_bulk_cost;
181 
182  this_line -= s->pixel_size;
183  prev_line -= s->pixel_size;
184 
185  /* If our lowest bulk cost index is too far away, replace it
186  * with the next lowest bulk cost */
187  if (FFMIN(width, i + MAX_RLE_BULK) < lowest_bulk_cost_index) {
188  lowest_bulk_cost = sec_lowest_bulk_cost;
189  lowest_bulk_cost_index = sec_lowest_bulk_cost_index;
190 
191  sec_lowest_bulk_cost = INT_MAX / 2;
192  sec_lowest_bulk_cost_index = width;
193  }
194 
195  /* Deal with the first pixel's bulk cost */
196  if (!i) {
197  base_bulk_cost++;
198  lowest_bulk_cost++;
199  sec_lowest_bulk_cost++;
200  }
201 
202  /* Look at the bulk cost of the previous loop and see if it is
203  * a new lower bulk cost */
204  prev_bulk_cost = s->length_table[i + 1] + base_bulk_cost;
205  if (prev_bulk_cost <= sec_lowest_bulk_cost) {
206  /* If it's lower than the 2nd lowest, then it may be lower
207  * than the lowest */
208  if (prev_bulk_cost <= lowest_bulk_cost) {
209 
210  /* If we have found a new lowest bulk cost,
211  * then the 2nd lowest bulk cost is now farther than the
212  * lowest bulk cost, and will never be used */
213  sec_lowest_bulk_cost = INT_MAX / 2;
214 
215  lowest_bulk_cost = prev_bulk_cost;
216  lowest_bulk_cost_index = i + 1;
217  } else {
218  /* Then it must be the 2nd lowest bulk cost */
219  sec_lowest_bulk_cost = prev_bulk_cost;
220  sec_lowest_bulk_cost_index = i + 1;
221  }
222  }
223 
224  if (!s->key_frame && !memcmp(this_line, prev_line, s->pixel_size))
225  skipcount = FFMIN(skipcount + 1, MAX_RLE_SKIP);
226  else
227  skipcount = 0;
228 
229  total_skip_cost = s->length_table[i + skipcount] + 2;
230  s->skip_table[i] = skipcount;
231 
232 
233  if (i < width - 1 && !memcmp(this_line, this_line + s->pixel_size, s->pixel_size))
234  repeatcount = FFMIN(repeatcount + 1, MAX_RLE_REPEAT);
235  else
236  repeatcount = 1;
237 
238  total_repeat_cost = s->length_table[i + repeatcount] + 1 + s->pixel_size;
239 
240  /* skip code is free for the first pixel, it costs one byte for repeat and bulk copy
241  * so let's make it aware */
242  if (i == 0) {
243  total_skip_cost--;
244  total_repeat_cost++;
245  }
246 
247  if (repeatcount > 1 && (skipcount == 0 || total_repeat_cost < total_skip_cost)) {
248  /* repeat is the best */
249  s->length_table[i] = total_repeat_cost;
250  s->rlecode_table[i] = -repeatcount;
251  }
252  else if (skipcount > 0) {
253  /* skip is the best choice here */
254  s->length_table[i] = total_skip_cost;
255  s->rlecode_table[i] = 0;
256  }
257  else {
258  /* We cannot do neither skip nor repeat
259  * thus we use the best bulk copy */
260 
261  s->length_table[i] = lowest_bulk_cost;
262  s->rlecode_table[i] = lowest_bulk_cost_index - i;
263 
264  }
265 
266  /* These bulk costs increase every iteration */
267  lowest_bulk_cost += s->pixel_size;
268  sec_lowest_bulk_cost += s->pixel_size;
269  }
270 
271  /* Good! Now we have the best sequence for this line, let's output it. */
272 
273  /* We do a special case for the first pixel so that we avoid testing it in
274  * the whole loop */
275 
276  i=0;
277  this_line = p-> data[0] + line*p->linesize[0];
278 
279  if (s->rlecode_table[0] == 0) {
280  bytestream_put_byte(buf, s->skip_table[0] + 1);
281  i += s->skip_table[0];
282  }
283  else bytestream_put_byte(buf, 1);
284 
285 
286  while (i < width) {
287  rlecode = s->rlecode_table[i];
288  bytestream_put_byte(buf, rlecode);
289  if (rlecode == 0) {
290  /* Write a skip sequence */
291  bytestream_put_byte(buf, s->skip_table[i] + 1);
292  i += s->skip_table[i];
293  }
294  else if (rlecode > 0) {
295  /* bulk copy */
296  if (s->avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
297  int j;
298  // QT grayscale colorspace has 0=white and 255=black, we will
299  // ignore the palette that is included in the AVFrame because
300  // AV_PIX_FMT_GRAY8 has defined color mapping
301  for (j = 0; j < rlecode*s->pixel_size; ++j)
302  bytestream_put_byte(buf, *(this_line + i*s->pixel_size + j) ^ 0xff);
303  } else {
304  bytestream_put_buffer(buf, this_line + i*s->pixel_size, rlecode*s->pixel_size);
305  }
306  i += rlecode;
307  }
308  else {
309  /* repeat the bits */
310  if (s->avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
311  int j;
312  // QT grayscale colorspace has 0=white and 255=black, ...
313  for (j = 0; j < s->pixel_size; ++j)
314  bytestream_put_byte(buf, *(this_line + i*s->pixel_size + j) ^ 0xff);
315  } else {
316  bytestream_put_buffer(buf, this_line + i*s->pixel_size, s->pixel_size);
317  }
318  i -= rlecode;
319  }
320  }
321  bytestream_put_byte(buf, -1); // end RLE line
322 }
323 
324 /** Encode frame including header */
325 static int encode_frame(QtrleEncContext *s, const AVFrame *p, uint8_t *buf)
326 {
327  int i;
328  int start_line = 0;
329  int end_line = s->avctx->height;
330  uint8_t *orig_buf = buf;
331 
332  if (!s->key_frame) {
333  unsigned line_size = s->logical_width * s->pixel_size;
334  for (start_line = 0; start_line < s->avctx->height; start_line++)
335  if (memcmp(p->data[0] + start_line*p->linesize[0],
336  s->previous_frame->data[0] + start_line * s->previous_frame->linesize[0],
337  line_size))
338  break;
339 
340  for (end_line=s->avctx->height; end_line > start_line; end_line--)
341  if (memcmp(p->data[0] + (end_line - 1)*p->linesize[0],
342  s->previous_frame->data[0] + (end_line - 1) * s->previous_frame->linesize[0],
343  line_size))
344  break;
345  }
346 
347  bytestream_put_be32(&buf, 0); // CHUNK SIZE, patched later
348 
349  if ((start_line == 0 && end_line == s->avctx->height) || start_line == s->avctx->height)
350  bytestream_put_be16(&buf, 0); // header
351  else {
352  bytestream_put_be16(&buf, 8); // header
353  bytestream_put_be16(&buf, start_line); // starting line
354  bytestream_put_be16(&buf, 0); // unknown
355  bytestream_put_be16(&buf, end_line - start_line); // lines to update
356  bytestream_put_be16(&buf, 0); // unknown
357  }
358  for (i = start_line; i < end_line; i++)
359  qtrle_encode_line(s, p, i, &buf);
360 
361  bytestream_put_byte(&buf, 0); // zero skip code = frame finished
362  AV_WB32(orig_buf, buf - orig_buf); // patch the chunk size
363  return buf - orig_buf;
364 }
365 
367  const AVFrame *pict, int *got_packet)
368 {
369  QtrleEncContext * const s = avctx->priv_data;
370  int ret;
371 
372  if ((ret = ff_alloc_packet2(avctx, pkt, s->max_buf_size, 0)) < 0)
373  return ret;
374 
375  if (avctx->gop_size == 0 || !s->previous_frame->data[0] ||
376  (s->avctx->frame_number % avctx->gop_size) == 0) {
377  /* I-Frame */
378  s->key_frame = 1;
379  } else {
380  /* P-Frame */
381  s->key_frame = 0;
382  }
383 
384  pkt->size = encode_frame(s, pict, pkt->data);
385 
386  /* save the current frame */
387  av_frame_unref(s->previous_frame);
388  ret = av_frame_ref(s->previous_frame, pict);
389  if (ret < 0) {
390  av_log(avctx, AV_LOG_ERROR, "cannot add reference\n");
391  return ret;
392  }
393 
394  if (s->key_frame)
396  *got_packet = 1;
397 
398  return 0;
399 }
400 
402  .name = "qtrle",
403  .long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"),
404  .type = AVMEDIA_TYPE_VIDEO,
405  .id = AV_CODEC_ID_QTRLE,
406  .priv_data_size = sizeof(QtrleEncContext),
408  .encode2 = qtrle_encode_frame,
409  .close = qtrle_encode_end,
410  .pix_fmts = (const enum AVPixelFormat[]){
412  },
414 };
AVCodec
AVCodec.
Definition: codec.h:197
FF_CODEC_CAP_INIT_THREADSAFE
#define FF_CODEC_CAP_INIT_THREADSAFE
The codec does not modify any global variables in the init function, allowing to call the init functi...
Definition: internal.h:41
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
init
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:31
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
MAX_RLE_BULK
#define MAX_RLE_BULK
Maximum RLE code for bulk copy.
Definition: qtrleenc.c:31
QtrleEncContext::avctx
AVCodecContext * avctx
Definition: qtrleenc.c:38
QtrleEncContext::length_table
int * length_table
This array will contain the length of the best rle encoding of the line starting at ith pixel.
Definition: qtrleenc.c:56
QtrleEncContext::pixel_size
int pixel_size
Definition: qtrleenc.c:39
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:111
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:303
internal.h
AVPacket::data
uint8_t * data
Definition: packet.h:365
data
const char data[16]
Definition: mxf.c:142
qtrle_encode_end
static av_cold int qtrle_encode_end(AVCodecContext *avctx)
Definition: qtrleenc.c:66
av_mallocz_array
void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.c:196
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:396
AV_PIX_FMT_RGB555BE
@ AV_PIX_FMT_RGB555BE
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined
Definition: pixfmt.h:107
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:317
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:98
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:181
av_cold
#define av_cold
Definition: attributes.h:90
width
#define width
s
#define s(width, name)
Definition: cbs_vp9.c:257
qtrle_encode_line
static void qtrle_encode_line(QtrleEncContext *s, const AVFrame *p, int line, uint8_t **buf)
Compute the best RLE sequence for a line.
Definition: qtrleenc.c:135
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:289
QtrleEncContext::logical_width
int logical_width
Definition: qtrleenc.c:42
MAX_RLE_SKIP
#define MAX_RLE_SKIP
Maximum RLE code for skip.
Definition: qtrleenc.c:35
QtrleEncContext::key_frame
int key_frame
Encoded frame is a key frame.
Definition: qtrleenc.c:63
QtrleEncContext::skip_table
uint8_t * skip_table
Will contain at ith position the number of consecutive pixels equal to the previous frame starting fr...
Definition: qtrleenc.c:60
ff_qtrle_encoder
const AVCodec ff_qtrle_encoder
Definition: qtrleenc.c:401
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:74
AV_WB32
#define AV_WB32(p, v)
Definition: intreadwrite.h:419
MAX_RLE_REPEAT
#define MAX_RLE_REPEAT
Maximum RLE code for repeat.
Definition: qtrleenc.c:33
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
AVPacket::size
int size
Definition: packet.h:366
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
AVCodecContext::gop_size
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
Definition: avcodec.h:696
av_frame_ref
int av_frame_ref(AVFrame *dst, const AVFrame *src)
Set up a new reference to the data described by the source frame.
Definition: frame.c:326
encode_frame
static int encode_frame(QtrleEncContext *s, const AVFrame *p, uint8_t *buf)
Encode frame including header.
Definition: qtrleenc.c:325
QtrleEncContext::rlecode_table
signed char * rlecode_table
This array will contain at ith position the value of the best RLE code if the line started at pixel i...
Definition: qtrleenc.c:52
FFMIN
#define FFMIN(a, b)
Definition: common.h:105
line
Definition: graph2dot.c:48
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:371
QtrleEncContext::max_buf_size
unsigned int max_buf_size
Definition: qtrleenc.c:41
AV_PIX_FMT_ARGB
@ AV_PIX_FMT_ARGB
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
Definition: pixfmt.h:92
AVCodecContext::bits_per_coded_sample
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
Definition: avcodec.h:1524
bytestream_put_buffer
static av_always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
Definition: bytestream.h:372
i
int i
Definition: input.c:407
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: internal.h:49
QtrleEncContext::previous_frame
AVFrame * previous_frame
Definition: qtrleenc.c:40
av_frame_unref
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:436
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:243
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:204
AVCodecContext::height
int height
Definition: avcodec.h:674
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:711
avcodec.h
av_uninit
#define av_uninit(x)
Definition: attributes.h:154
ret
ret
Definition: filter_design.txt:187
AVCodecContext
main external API structure.
Definition: avcodec.h:501
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
qtrle_encode_frame
static int qtrle_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet)
Definition: qtrleenc.c:366
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
AV_CODEC_ID_QTRLE
@ AV_CODEC_ID_QTRLE
Definition: codec_id.h:104
qtrle_encode_init
static av_cold int qtrle_encode_init(AVCodecContext *avctx)
Definition: qtrleenc.c:77
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
AVPacket
This structure stores compressed data.
Definition: packet.h:342
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:528
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:674
bytestream.h
imgutils.h
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:334
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
av_image_check_size
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:315
QtrleEncContext
Definition: qtrleenc.c:37
ff_alloc_packet2
int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int64_t min_size)
Check AVPacket size and/or allocate data.
Definition: encode.c:33