FFmpeg
flashsvenc.c
Go to the documentation of this file.
1 /*
2  * Flash Screen Video encoder
3  * Copyright (C) 2004 Alex Beregszaszi
4  * Copyright (C) 2006 Benjamin Larsson
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 /* Encoding development sponsored by http://fh-campuswien.ac.at */
24 
25 /**
26  * @file
27  * Flash Screen Video encoder
28  * @author Alex Beregszaszi
29  * @author Benjamin Larsson
30  *
31  * A description of the bitstream format for Flash Screen Video version 1/2
32  * is part of the SWF File Format Specification (version 10), which can be
33  * downloaded from http://www.adobe.com/devnet/swf.html.
34  */
35 
36 /*
37  * Encoding ideas: A basic encoder would just use a fixed block size.
38  * Block sizes can be multiples of 16, from 16 to 256. The blocks don't
39  * have to be quadratic. A brute force search with a set of different
40  * block sizes should give a better result than to just use a fixed size.
41  *
42  * TODO:
43  * Don't reencode the frame in brute force mode if the frame is a dupe.
44  * Speed up. Make the difference check faster.
45  */
46 
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <zlib.h>
50 
51 #include "avcodec.h"
52 #include "internal.h"
53 #include "put_bits.h"
54 #include "bytestream.h"
55 
56 
57 typedef struct FlashSVContext {
64  int block_size;
65  z_stream zstream;
68 
69 static int copy_region_enc(uint8_t *sptr, uint8_t *dptr, int dx, int dy,
70  int h, int w, int stride, uint8_t *pfptr)
71 {
72  int i, j;
73  uint8_t *nsptr;
74  uint8_t *npfptr;
75  int diff = 0;
76 
77  for (i = dx + h; i > dx; i--) {
78  nsptr = sptr + i * stride + dy * 3;
79  npfptr = pfptr + i * stride + dy * 3;
80  for (j = 0; j < w * 3; j++) {
81  diff |= npfptr[j] ^ nsptr[j];
82  dptr[j] = nsptr[j];
83  }
84  dptr += w * 3;
85  }
86  if (diff)
87  return 1;
88  return 0;
89 }
90 
92 {
93  FlashSVContext *s = avctx->priv_data;
94 
95  deflateEnd(&s->zstream);
96 
97  av_freep(&s->encbuffer);
99  av_freep(&s->tmpblock);
100 
101  return 0;
102 }
103 
105 {
106  FlashSVContext *s = avctx->priv_data;
107 
108  s->avctx = avctx;
109 
110  if (avctx->width > 4095 || avctx->height > 4095) {
111  av_log(avctx, AV_LOG_ERROR,
112  "Input dimensions too large, input must be max 4095x4095 !\n");
113  return AVERROR_INVALIDDATA;
114  }
115 
116  // Needed if zlib unused or init aborted before deflateInit
117  memset(&s->zstream, 0, sizeof(z_stream));
118 
119  s->last_key_frame = 0;
120 
121  s->image_width = avctx->width;
122  s->image_height = avctx->height;
123 
124  s->tmpblock = av_mallocz(3 * 256 * 256);
125  s->encbuffer = av_mallocz(s->image_width * s->image_height * 3);
126 
127  if (!s->tmpblock || !s->encbuffer) {
128  av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
129  return AVERROR(ENOMEM);
130  }
131 
132  return 0;
133 }
134 
135 
137  int buf_size, int block_width, int block_height,
138  uint8_t *previous_frame, int *I_frame)
139 {
140 
141  PutBitContext pb;
142  int h_blocks, v_blocks, h_part, v_part, i, j;
143  int buf_pos, res;
144  int pred_blocks = 0;
145 
146  init_put_bits(&pb, buf, buf_size);
147 
148  put_bits(&pb, 4, block_width / 16 - 1);
149  put_bits(&pb, 12, s->image_width);
150  put_bits(&pb, 4, block_height / 16 - 1);
151  put_bits(&pb, 12, s->image_height);
152  flush_put_bits(&pb);
153  buf_pos = 4;
154 
155  h_blocks = s->image_width / block_width;
156  h_part = s->image_width % block_width;
157  v_blocks = s->image_height / block_height;
158  v_part = s->image_height % block_height;
159 
160  /* loop over all block columns */
161  for (j = 0; j < v_blocks + (v_part ? 1 : 0); j++) {
162 
163  int y_pos = j * block_height; // vertical position in frame
164  int cur_blk_height = (j < v_blocks) ? block_height : v_part;
165 
166  /* loop over all block rows */
167  for (i = 0; i < h_blocks + (h_part ? 1 : 0); i++) {
168  int x_pos = i * block_width; // horizontal position in frame
169  int cur_blk_width = (i < h_blocks) ? block_width : h_part;
170  int ret = Z_OK;
171  uint8_t *ptr = buf + buf_pos;
172 
173  /* copy the block to the temp buffer before compression
174  * (if it differs from the previous frame's block) */
175  res = copy_region_enc(p->data[0], s->tmpblock,
176  s->image_height - (y_pos + cur_blk_height + 1),
177  x_pos, cur_blk_height, cur_blk_width,
178  p->linesize[0], previous_frame);
179 
180  if (res || *I_frame) {
181  unsigned long zsize = 3 * block_width * block_height;
182  ret = compress2(ptr + 2, &zsize, s->tmpblock,
183  3 * cur_blk_width * cur_blk_height, 9);
184 
185  //ret = deflateReset(&s->zstream);
186  if (ret != Z_OK)
188  "error while compressing block %dx%d\n", i, j);
189 
190  bytestream_put_be16(&ptr, zsize);
191  buf_pos += zsize + 2;
192  ff_dlog(s->avctx, "buf_pos = %d\n", buf_pos);
193  } else {
194  pred_blocks++;
195  bytestream_put_be16(&ptr, 0);
196  buf_pos += 2;
197  }
198  }
199  }
200 
201  if (pred_blocks)
202  *I_frame = 0;
203  else
204  *I_frame = 1;
205 
206  return buf_pos;
207 }
208 
209 
211  const AVFrame *pict, int *got_packet)
212 {
213  FlashSVContext * const s = avctx->priv_data;
214  const AVFrame * const p = pict;
215  uint8_t *pfptr;
216  int res;
217  int I_frame = 0;
218  int opt_w = 4, opt_h = 4;
219 
220  /* First frame needs to be a keyframe */
221  if (avctx->frame_number == 0) {
223  if (!s->previous_frame) {
224  av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
225  return AVERROR(ENOMEM);
226  }
227  I_frame = 1;
228  }
229 
230  if (p->linesize[0] < 0)
231  pfptr = s->previous_frame - (s->image_height - 1) * p->linesize[0];
232  else
233  pfptr = s->previous_frame;
234 
235  /* Check the placement of keyframes */
236  if (avctx->gop_size > 0 &&
237  avctx->frame_number >= s->last_key_frame + avctx->gop_size) {
238  I_frame = 1;
239  }
240 
241  if ((res = ff_alloc_packet2(avctx, pkt, s->image_width * s->image_height * 3, 0)) < 0)
242  return res;
243 
244  pkt->size = encode_bitstream(s, p, pkt->data, pkt->size, opt_w * 16, opt_h * 16,
245  pfptr, &I_frame);
246 
247  //save the current frame
248  if (p->linesize[0] > 0)
249  memcpy(s->previous_frame, p->data[0], s->image_height * p->linesize[0]);
250  else
251  memcpy(s->previous_frame,
252  p->data[0] + p->linesize[0] * (s->image_height - 1),
253  s->image_height * FFABS(p->linesize[0]));
254 
255  //mark the frame type so the muxer can mux it correctly
256  if (I_frame) {
257 #if FF_API_CODED_FRAME
260  avctx->coded_frame->key_frame = 1;
262 #endif
263  s->last_key_frame = avctx->frame_number;
264  ff_dlog(avctx, "Inserting keyframe at frame %d\n", avctx->frame_number);
265  } else {
266 #if FF_API_CODED_FRAME
269  avctx->coded_frame->key_frame = 0;
271 #endif
272  }
273 
274  if (I_frame)
275  pkt->flags |= AV_PKT_FLAG_KEY;
276  *got_packet = 1;
277 
278  return 0;
279 }
280 
282  .name = "flashsv",
283  .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video"),
284  .type = AVMEDIA_TYPE_VIDEO,
285  .id = AV_CODEC_ID_FLASHSV,
286  .priv_data_size = sizeof(FlashSVContext),
288  .encode2 = flashsv_encode_frame,
289  .close = flashsv_encode_end,
291 };
static int encode_bitstream(FlashSVContext *s, const AVFrame *p, uint8_t *buf, int buf_size, int block_width, int block_height, uint8_t *previous_frame, int *I_frame)
Definition: flashsvenc.c:136
#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:268
static void put_bits(Jpeg2000EncoderContext *s, int val, int n)
put n times val bit
Definition: j2kenc.c:208
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int size
Definition: avcodec.h:1478
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:236
static AVPacket pkt
AVCodec.
Definition: avcodec.h:3477
uint8_t * encbuffer
Definition: flashsvenc.c:63
AVCodecContext * avctx
Definition: flashsv.c:52
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:32
uint8_t
#define av_cold
Definition: attributes.h:82
uint8_t * data
Definition: avcodec.h:1477
#define ff_dlog(a,...)
int image_width
Definition: flashsv.c:54
static int copy_region_enc(uint8_t *sptr, uint8_t *dptr, int dx, int dy, int h, int w, int stride, uint8_t *pfptr)
Definition: flashsvenc.c:69
#define av_log(a,...)
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1509
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:260
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
static int flashsv_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet)
Definition: flashsvenc.c:210
int block_width
Definition: flashsv.c:55
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
const char * name
Name of the codec implementation.
Definition: avcodec.h:3484
AVCodec ff_flashsv_encoder
Definition: flashsvenc.c:281
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1483
int last_key_frame
Definition: flashsvenc.c:66
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:351
static av_cold int flashsv_encode_end(AVCodecContext *avctx)
Definition: flashsvenc.c:91
int width
picture width / height.
Definition: avcodec.h:1738
uint8_t w
Definition: llviddspenc.c:38
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:72
#define s(width, name)
Definition: cbs_vp9.c:257
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:69
if(ret)
int block_size
Definition: flashsv.c:57
Libavcodec external API header.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:299
main external API structure.
Definition: avcodec.h:1565
void * buf
Definition: avisynth_c.h:766
z_stream zstream
Definition: flashsv.c:58
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:275
uint8_t * previous_frame
Definition: flashsvenc.c:59
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:282
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
Definition: avcodec.h:1760
GLint GLenum GLboolean GLsizei stride
Definition: opengl_enc.c:104
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:84
common internal api header.
static void flush_put_bits(PutBitContext *s)
Pad the end of the output stream with zeros.
Definition: put_bits.h:101
attribute_deprecated AVFrame * coded_frame
the picture in the bitstream
Definition: avcodec.h:2811
static void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size)
Initialize the PutBitContext s.
Definition: put_bits.h:48
void * priv_data
Definition: avcodec.h:1592
uint8_t * tmpblock
Definition: flashsv.c:56
static av_cold int flashsv_encode_init(AVCodecContext *avctx)
Definition: flashsvenc.c:104
static av_always_inline int diff(const uint32_t a, const uint32_t b)
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition: internal.h:85
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:346
int frame_number
Frame counter, set by libavcodec.
Definition: avcodec.h:2252
#define av_freep(p)
int block_height
Definition: flashsv.c:55
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
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
This structure stores compressed data.
Definition: avcodec.h:1454
Predicted.
Definition: avutil.h:275
int image_height
Definition: flashsv.c:54
bitstream writer API