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 {
60  AVFrame frame;
65  int block_size;
66  z_stream zstream;
69 
70 static int copy_region_enc(uint8_t *sptr, uint8_t *dptr, int dx, int dy,
71  int h, int w, int stride, uint8_t *pfptr)
72 {
73  int i, j;
74  uint8_t *nsptr;
75  uint8_t *npfptr;
76  int diff = 0;
77 
78  for (i = dx + h; i > dx; i--) {
79  nsptr = sptr + i * stride + dy * 3;
80  npfptr = pfptr + i * stride + dy * 3;
81  for (j = 0; j < w * 3; j++) {
82  diff |= npfptr[j] ^ nsptr[j];
83  dptr[j] = nsptr[j];
84  }
85  dptr += w * 3;
86  }
87  if (diff)
88  return 1;
89  return 0;
90 }
91 
93 {
94  FlashSVContext *s = avctx->priv_data;
95 
96  s->avctx = avctx;
97 
98  if (avctx->width > 4095 || avctx->height > 4095) {
99  av_log(avctx, AV_LOG_ERROR,
100  "Input dimensions too large, input must be max 4096x4096 !\n");
101  return AVERROR_INVALIDDATA;
102  }
103 
104  // Needed if zlib unused or init aborted before deflateInit
105  memset(&s->zstream, 0, sizeof(z_stream));
106 
107  s->last_key_frame = 0;
108 
109  s->image_width = avctx->width;
110  s->image_height = avctx->height;
111 
112  s->tmpblock = av_mallocz(3 * 256 * 256);
113  s->encbuffer = av_mallocz(s->image_width * s->image_height * 3);
114 
115  if (!s->tmpblock || !s->encbuffer) {
116  av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
117  return AVERROR(ENOMEM);
118  }
119 
120  return 0;
121 }
122 
123 
125  int buf_size, int block_width, int block_height,
126  uint8_t *previous_frame, int *I_frame)
127 {
128 
129  PutBitContext pb;
130  int h_blocks, v_blocks, h_part, v_part, i, j;
131  int buf_pos, res;
132  int pred_blocks = 0;
133 
134  init_put_bits(&pb, buf, buf_size * 8);
135 
136  put_bits(&pb, 4, block_width / 16 - 1);
137  put_bits(&pb, 12, s->image_width);
138  put_bits(&pb, 4, block_height / 16 - 1);
139  put_bits(&pb, 12, s->image_height);
140  flush_put_bits(&pb);
141  buf_pos = 4;
142 
143  h_blocks = s->image_width / block_width;
144  h_part = s->image_width % block_width;
145  v_blocks = s->image_height / block_height;
146  v_part = s->image_height % block_height;
147 
148  /* loop over all block columns */
149  for (j = 0; j < v_blocks + (v_part ? 1 : 0); j++) {
150 
151  int y_pos = j * block_height; // vertical position in frame
152  int cur_blk_height = (j < v_blocks) ? block_height : v_part;
153 
154  /* loop over all block rows */
155  for (i = 0; i < h_blocks + (h_part ? 1 : 0); i++) {
156  int x_pos = i * block_width; // horizontal position in frame
157  int cur_blk_width = (i < h_blocks) ? block_width : h_part;
158  int ret = Z_OK;
159  uint8_t *ptr = buf + buf_pos;
160 
161  /* copy the block to the temp buffer before compression
162  * (if it differs from the previous frame's block) */
163  res = copy_region_enc(p->data[0], s->tmpblock,
164  s->image_height - (y_pos + cur_blk_height + 1),
165  x_pos, cur_blk_height, cur_blk_width,
166  p->linesize[0], previous_frame);
167 
168  if (res || *I_frame) {
169  unsigned long zsize = 3 * block_width * block_height;
170  ret = compress2(ptr + 2, &zsize, s->tmpblock,
171  3 * cur_blk_width * cur_blk_height, 9);
172 
173  //ret = deflateReset(&s->zstream);
174  if (ret != Z_OK)
176  "error while compressing block %dx%d\n", i, j);
177 
178  bytestream_put_be16(&ptr, zsize);
179  buf_pos += zsize + 2;
180  av_dlog(s->avctx, "buf_pos = %d\n", buf_pos);
181  } else {
182  pred_blocks++;
183  bytestream_put_be16(&ptr, 0);
184  buf_pos += 2;
185  }
186  }
187  }
188 
189  if (pred_blocks)
190  *I_frame = 0;
191  else
192  *I_frame = 1;
193 
194  return buf_pos;
195 }
196 
197 
199  const AVFrame *pict, int *got_packet)
200 {
201  FlashSVContext * const s = avctx->priv_data;
202  AVFrame * const p = &s->frame;
203  uint8_t *pfptr;
204  int res;
205  int I_frame = 0;
206  int opt_w = 4, opt_h = 4;
207 
208  *p = *pict;
209 
210  /* First frame needs to be a keyframe */
211  if (avctx->frame_number == 0) {
213  if (!s->previous_frame) {
214  av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
215  return AVERROR(ENOMEM);
216  }
217  I_frame = 1;
218  }
219 
220  if (p->linesize[0] < 0)
221  pfptr = s->previous_frame - (s->image_height - 1) * p->linesize[0];
222  else
223  pfptr = s->previous_frame;
224 
225  /* Check the placement of keyframes */
226  if (avctx->gop_size > 0 &&
227  avctx->frame_number >= s->last_key_frame + avctx->gop_size) {
228  I_frame = 1;
229  }
230 
231  if ((res = ff_alloc_packet2(avctx, pkt, s->image_width * s->image_height * 3)) < 0)
232  return res;
233 
234  pkt->size = encode_bitstream(s, p, pkt->data, pkt->size, opt_w * 16, opt_h * 16,
235  pfptr, &I_frame);
236 
237  //save the current frame
238  if (p->linesize[0] > 0)
239  memcpy(s->previous_frame, p->data[0], s->image_height * p->linesize[0]);
240  else
241  memcpy(s->previous_frame,
242  p->data[0] + p->linesize[0] * (s->image_height - 1),
243  s->image_height * FFABS(p->linesize[0]));
244 
245  //mark the frame type so the muxer can mux it correctly
246  if (I_frame) {
248  p->key_frame = 1;
249  s->last_key_frame = avctx->frame_number;
250  av_dlog(avctx, "Inserting keyframe at frame %d\n", avctx->frame_number);
251  } else {
253  p->key_frame = 0;
254  }
255 
256  avctx->coded_frame = p;
257 
258  if (p->key_frame)
259  pkt->flags |= AV_PKT_FLAG_KEY;
260  *got_packet = 1;
261 
262  return 0;
263 }
264 
266 {
267  FlashSVContext *s = avctx->priv_data;
268 
269  deflateEnd(&s->zstream);
270 
271  av_free(s->encbuffer);
273  av_free(s->tmpblock);
274 
275  return 0;
276 }
277 
279  .name = "flashsv",
280  .type = AVMEDIA_TYPE_VIDEO,
281  .id = AV_CODEC_ID_FLASHSV,
282  .priv_data_size = sizeof(FlashSVContext),
284  .encode2 = flashsv_encode_frame,
286  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE },
287  .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video"),
288 };
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:205
const char * s
Definition: avisynth_c.h:668
#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
AVFrame * coded_frame
the picture in the bitstream
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
av_dlog(ac->avr,"%d samples - audio_convert: %s to %s (%s)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt), use_generic?ac->func_descr_generic:ac->func_descr)
int stride
Definition: mace.c:144
output residual component w
uint8_t * encbuffer
Definition: flashsvenc.c:64
initialize output if(nPeaks >3)%at least 3 peaks in spectrum for trying to find f0 nf0peaks
AVCodecContext * avctx
Definition: flashsv.c:52
uint8_t
#define av_cold
Definition: attributes.h:78
static AVPacket pkt
Definition: demuxing.c:56
uint8_t * data
static int encode_bitstream(FlashSVContext *s, AVFrame *p, uint8_t *buf, int buf_size, int block_width, int block_height, uint8_t *previous_frame, int *I_frame)
Definition: flashsvenc.c:124
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:70
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
struct FlashSVContext FlashSVContext
static int flashsv_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet)
Definition: flashsvenc.c:198
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. ...
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
const char * name
Name of the codec implementation.
static void put_bits(J2kEncoderContext *s, int val, int n)
put n times val bit
Definition: j2kenc.c:160
AVCodec ff_flashsv_encoder
Definition: flashsvenc.c:278
external API header
int flags
A combination of AV_PKT_FLAG values.
int last_key_frame
Definition: flashsvenc.c:67
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:144
static av_cold int flashsv_encode_end(AVCodecContext *avctx)
Definition: flashsvenc.c:265
ret
Definition: avfilter.c:821
int width
picture width / height.
#define FFABS(a)
Definition: common.h:53
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:71
#define diff(a, as, b, bs)
Definition: vf_phase.c:80
int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int size)
Check AVPacket size and/or allocate data.
AVFrame frame
Definition: flashsv.c:53
int block_size
Definition: flashsv.c:57
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
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
void * buf
Definition: avisynth_c.h:594
synthesis window for stochastic i
z_stream zstream
Definition: flashsv.c:58
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
uint8_t * previous_frame
Definition: flashsvenc.c:59
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
common internal api header.
static void flush_put_bits(PutBitContext *s)
Pad the end of the output stream with zeros.
Definition: put_bits.h:81
static void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size)
Initialize the PutBitContext s.
Definition: put_bits.h:54
uint8_t * tmpblock
Definition: flashsv.c:56
static av_cold int flashsv_encode_init(AVCodecContext *avctx)
Definition: flashsvenc.c:92
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:139
int frame_number
Frame counter, set by libavcodec.
int block_height
Definition: flashsv.c:55
AVPixelFormat
Pixel format.
Definition: pixfmt.h:66
This structure stores compressed data.
Predicted.
Definition: avutil.h:217
int image_height
Definition: flashsv.c:54
bitstream writer API