FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
librsvgdec.c
Go to the documentation of this file.
1 /*
2  * Librsvg rasterization wrapper
3  * Copyright (c) 2017 Rostislav Pehlivanov <atomnuker@gmail.com>
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 "avcodec.h"
23 #include "internal.h"
24 #include "libavutil/opt.h"
25 #include "librsvg-2.0/librsvg/rsvg.h"
26 
27 typedef struct LibRSVGContext {
28  AVClass *class;
29 
30  int width;
31  int height;
32  int keep_ar;
34 
35 static int librsvg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *pkt)
36 {
37  int ret;
38  LibRSVGContext *s = avctx->priv_data;
39  AVFrame *frame = data;
40 
41  RsvgHandle *handle;
42  RsvgDimensionData unscaled_dimensions, dimensions;
43  cairo_surface_t *image;
44  cairo_t *crender = NULL;
45  GError *error = NULL;
46 
47  *got_frame = 0;
48 
49  handle = rsvg_handle_new_from_data(pkt->data, pkt->size, &error);
50  if (error) {
51  av_log(avctx, AV_LOG_ERROR, "Error parsing svg!\n");
52  g_error_free(error);
53  return AVERROR_INVALIDDATA;
54  }
55 
56  rsvg_handle_get_dimensions(handle, &dimensions);
57  rsvg_handle_get_dimensions(handle, &unscaled_dimensions);
58  dimensions.width = s->width ? s->width : dimensions.width;
59  dimensions.height = s->height ? s->height : dimensions.height;
60  if (s->keep_ar && (s->width || s->height)) {
61  double default_ar = unscaled_dimensions.width/(double)unscaled_dimensions.height;
62  if (!s->width)
63  dimensions.width = lrintf(dimensions.height * default_ar);
64  else
65  dimensions.height = lrintf(dimensions.width / default_ar);
66  }
67 
68  if ((ret = ff_set_dimensions(avctx, dimensions.width, dimensions.height)))
69  return ret;
70  avctx->pix_fmt = AV_PIX_FMT_RGB32;
71 
72  if ((ret = ff_get_buffer(avctx, frame, 0)))
73  return ret;
75  frame->key_frame = 1;
76 
77  image = cairo_image_surface_create_for_data(frame->data[0], CAIRO_FORMAT_ARGB32,
78  frame->width, frame->height,
79  frame->linesize[0]);
80  if (cairo_surface_status(image) != CAIRO_STATUS_SUCCESS)
81  return AVERROR_INVALIDDATA;
82 
83  crender = cairo_create(image);
84 
85  cairo_set_source_rgba(crender, 0.0, 0.0, 0.0, 1.0f);
86  cairo_paint_with_alpha(crender, 0.0f);
87 
88  cairo_scale(crender, dimensions.width / (double)unscaled_dimensions.width,
89  dimensions.height / (double)unscaled_dimensions.height);
90 
91  rsvg_handle_render_cairo(handle, crender);
92 
93  cairo_destroy(crender);
94  cairo_surface_destroy(image);
95  g_object_unref(handle);
96 
97  *got_frame = 1;
98 
99  return 0;
100 }
101 
102 #define OFFSET(x) offsetof(LibRSVGContext, x)
103 #define DEC (AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
104 static const AVOption options[] = {
105  { "width", "Width to render to (0 for default)", OFFSET(width), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, DEC },
106  { "height", "Height to render to (0 for default)", OFFSET(height), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, DEC },
107  { "keep_ar", "Keep aspect ratio with custom width/height", OFFSET(keep_ar), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, DEC },
108  { NULL },
109 };
110 
112  .class_name = "Librsvg",
113  .item_name = av_default_item_name,
114  .option = options,
115  .version = LIBAVUTIL_VERSION_INT,
116 };
117 
119  .name = "librsvg",
120  .long_name = NULL_IF_CONFIG_SMALL("Librsvg rasterizer"),
121  .priv_class = &librsvg_decoder_class,
122  .type = AVMEDIA_TYPE_VIDEO,
123  .id = AV_CODEC_ID_SVG,
124  .decode = librsvg_decode_frame,
125  .priv_data_size = sizeof(LibRSVGContext),
126  .capabilities = AV_CODEC_CAP_LOSSLESS | AV_CODEC_CAP_DR1,
127 };
#define NULL
Definition: coverity.c:32
const char * s
Definition: avisynth_c.h:768
#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:201
AVOption.
Definition: opt.h:246
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
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:196
int size
Definition: avcodec.h:1401
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:193
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1697
static AVPacket pkt
AVCodec.
Definition: avcodec.h:3351
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
AVOptions.
static AVFrame * frame
#define height
uint8_t * data
Definition: avcodec.h:1400
#define lrintf(x)
Definition: libm_mips.h:70
#define av_log(a,...)
int width
Definition: frame.h:259
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
uint16_t width
Definition: gdv.c:47
#define OFFSET(x)
Definition: librsvgdec.c:102
const char * name
Name of the codec implementation.
Definition: avcodec.h:3358
#define DEC
Definition: librsvgdec.c:103
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:284
int width
picture width / height.
Definition: avcodec.h:1660
static void error(const char *err)
Libavcodec external API header.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:232
main external API structure.
Definition: avcodec.h:1488
#define AV_PIX_FMT_RGB32
Definition: pixfmt.h:342
static const AVClass librsvg_decoder_class
Definition: librsvgdec.c:111
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1886
Describe the class of an AVClass context structure.
Definition: log.h:67
static const AVOption options[]
Definition: librsvgdec.c:104
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:215
common internal api header.
if(ret< 0)
Definition: vf_mcdeint.c:279
AVCodec ff_librsvg_decoder
Definition: librsvgdec.c:118
#define AV_CODEC_CAP_LOSSLESS
Codec is lossless.
Definition: avcodec.h:1046
static int librsvg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *pkt)
Definition: librsvgdec.c:35
void * priv_data
Definition: avcodec.h:1515
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:279
int height
Definition: frame.h:259
This structure stores compressed data.
Definition: avcodec.h:1377
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: avcodec.h:956