FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
libkvazaar.c
Go to the documentation of this file.
1 /*
2  * libkvazaar encoder
3  *
4  * Copyright (c) 2015 Tampere University of Technology
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 #include <kvazaar.h>
24 #include <string.h>
25 
26 #include "libavutil/avassert.h"
27 #include "libavutil/dict.h"
28 #include "libavutil/opt.h"
29 #include "avcodec.h"
30 #include "internal.h"
31 
32 typedef struct LibkvazaarContext {
33  const AVClass *class;
34 
35  const kvz_api *api;
36  kvz_encoder *encoder;
37  kvz_config *config;
38 
39  char *kvz_params;
41 
43 {
44  int retval = 0;
45  kvz_config *cfg = NULL;
46  kvz_encoder *enc = NULL;
47  const kvz_api *const api = kvz_api_get(8);
48 
49  LibkvazaarContext *const ctx = avctx->priv_data;
50 
51  // Kvazaar requires width and height to be multiples of eight.
52  if (avctx->width % 8 || avctx->height % 8) {
53  av_log(avctx, AV_LOG_ERROR, "Video dimensions are not a multiple of 8.\n");
54  retval = AVERROR_INVALIDDATA;
55  goto done;
56  }
57 
58  cfg = api->config_alloc();
59  if (!cfg) {
60  av_log(avctx, AV_LOG_ERROR, "Could not allocate kvazaar config structure.\n");
61  retval = AVERROR(ENOMEM);
62  goto done;
63  }
64 
65  if (!api->config_init(cfg)) {
66  av_log(avctx, AV_LOG_ERROR, "Could not initialize kvazaar config structure.\n");
67  retval = AVERROR_EXTERNAL;
68  goto done;
69  }
70 
71  cfg->width = avctx->width;
72  cfg->height = avctx->height;
73  cfg->framerate =
74  (double)(avctx->time_base.num * avctx->ticks_per_frame) / avctx->time_base.den;
75  cfg->threads = avctx->thread_count;
76  cfg->target_bitrate = avctx->bit_rate;
77  cfg->vui.sar_width = avctx->sample_aspect_ratio.num;
78  cfg->vui.sar_height = avctx->sample_aspect_ratio.den;
79 
80  if (ctx->kvz_params) {
81  AVDictionary *dict = NULL;
82  if (!av_dict_parse_string(&dict, ctx->kvz_params, "=", ",", 0)) {
83  AVDictionaryEntry *entry = NULL;
84  while ((entry = av_dict_get(dict, "", entry, AV_DICT_IGNORE_SUFFIX))) {
85  if (!api->config_parse(cfg, entry->key, entry->value)) {
86  av_log(avctx, AV_LOG_WARNING,
87  "Invalid option: %s=%s.\n",
88  entry->key, entry->value);
89  }
90  }
91  av_dict_free(&dict);
92  }
93  }
94 
95  enc = api->encoder_open(cfg);
96  if (!enc) {
97  av_log(avctx, AV_LOG_ERROR, "Could not open kvazaar encoder.\n");
98  retval = AVERROR_EXTERNAL;
99  goto done;
100  }
101 
102  ctx->api = api;
103  ctx->encoder = enc;
104  ctx->config = cfg;
105  enc = NULL;
106  cfg = NULL;
107 
108 done:
109  if (cfg) api->config_destroy(cfg);
110  if (enc) api->encoder_close(enc);
111 
112  return retval;
113 }
114 
116 {
117  LibkvazaarContext *ctx = avctx->priv_data;
118  if (!ctx->api) return 0;
119 
120  if (ctx->encoder) {
121  ctx->api->encoder_close(ctx->encoder);
122  ctx->encoder = NULL;
123  }
124 
125  if (ctx->config) {
126  ctx->api->config_destroy(ctx->config);
127  ctx->config = NULL;
128  }
129 
130  return 0;
131 }
132 
134  AVPacket *avpkt,
135  const AVFrame *frame,
136  int *got_packet_ptr)
137 {
138  int retval = 0;
139  kvz_picture *img_in = NULL;
140  kvz_data_chunk *data_out = NULL;
141  uint32_t len_out = 0;
142  LibkvazaarContext *ctx = avctx->priv_data;
143 
144  *got_packet_ptr = 0;
145 
146  if (frame) {
147  int i = 0;
148 
149  av_assert0(frame->width == ctx->config->width);
150  av_assert0(frame->height == ctx->config->height);
151  av_assert0(frame->format == avctx->pix_fmt);
152 
153  // Allocate input picture for kvazaar.
154  img_in = ctx->api->picture_alloc(frame->width, frame->height);
155  if (!img_in) {
156  av_log(avctx, AV_LOG_ERROR, "Failed to allocate picture.\n");
157  retval = AVERROR(ENOMEM);
158  goto done;
159  }
160 
161  // Copy pixels from frame to img_in.
162  for (i = 0; i < 3; ++i) {
163  uint8_t *dst = img_in->data[i];
164  uint8_t *src = frame->data[i];
165  int width = (i == 0) ? frame->width : (frame->width / 2);
166  int height = (i == 0) ? frame->height : (frame->height / 2);
167  int y = 0;
168  for (y = 0; y < height; ++y) {
169  memcpy(dst, src, width);
170  src += frame->linesize[i];
171  dst += width;
172  }
173  }
174  }
175 
176  if (!ctx->api->encoder_encode(ctx->encoder, img_in, &data_out, &len_out, NULL)) {
177  av_log(avctx, AV_LOG_ERROR, "Failed to encode frame.\n");
178  retval = AVERROR_EXTERNAL;
179  goto done;
180  }
181 
182  if (data_out) {
183  kvz_data_chunk *chunk = NULL;
184  uint64_t written = 0;
185 
186  retval = ff_alloc_packet(avpkt, len_out);
187  if (retval < 0) {
188  av_log(avctx, AV_LOG_ERROR, "Failed to allocate output packet.\n");
189  goto done;
190  }
191 
192  for (chunk = data_out; chunk != NULL; chunk = chunk->next) {
193  av_assert0(written + chunk->len <= len_out);
194  memcpy(avpkt->data + written, chunk->data, chunk->len);
195  written += chunk->len;
196  }
197  *got_packet_ptr = 1;
198 
199  ctx->api->chunk_free(data_out);
200  data_out = NULL;
201  }
202 
203 done:
204  if (img_in) ctx->api->picture_free(img_in);
205  if (data_out) ctx->api->chunk_free(data_out);
206  return retval;
207 }
208 
209 static const enum AVPixelFormat pix_fmts[] = {
212 };
213 
214 static const AVOption options[] = {
215  { "kvazaar-params", "Set kvazaar parameters as a comma-separated list of name=value pairs.",
216  offsetof(LibkvazaarContext, kvz_params), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0,
218  { NULL },
219 };
220 
221 static const AVClass class = {
222  .class_name = "libkvazaar",
223  .item_name = av_default_item_name,
224  .option = options,
226 };
227 
228 static const AVCodecDefault defaults[] = {
229  { "b", "0" },
230  { NULL },
231 };
232 
234  .name = "libkvazaar",
235  .long_name = NULL_IF_CONFIG_SMALL("libkvazaar H.265 / HEVC"),
236  .type = AVMEDIA_TYPE_VIDEO,
237  .id = AV_CODEC_ID_HEVC,
238  .capabilities = AV_CODEC_CAP_DELAY,
239  .pix_fmts = pix_fmts,
240 
241  .priv_class = &class,
242  .priv_data_size = sizeof(LibkvazaarContext),
243  .defaults = defaults,
244 
246  .encode2 = libkvazaar_encode,
247  .close = libkvazaar_close,
248 };
#define NULL
Definition: coverity.c:32
#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:171
AVOption.
Definition: opt.h:255
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
#define LIBAVUTIL_VERSION_INT
Definition: version.h:62
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int num
numerator
Definition: rational.h:44
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown) That is the width of a pixel divided by the height of the pixel...
Definition: avcodec.h:1902
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1722
static av_cold int libkvazaar_close(AVCodecContext *avctx)
Definition: libkvazaar.c:115
AVCodec ff_libkvazaar_encoder
Definition: libkvazaar.c:233
AVCodec.
Definition: avcodec.h:3472
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avcodec.h:1631
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
#define AV_CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
Definition: avcodec.h:882
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
Public dictionary API.
uint8_t
#define av_cold
Definition: attributes.h:74
AVOptions.
static AVFrame * frame
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:39
uint8_t * data
Definition: avcodec.h:1423
kvz_encoder * encoder
Definition: libkvazaar.c:36
kvz_config * config
Definition: libkvazaar.c:37
#define av_log(a,...)
const kvz_api * api
Definition: libkvazaar.c:35
#define AV_OPT_FLAG_ENCODING_PARAM
a generic parameter which can be set by the user for muxing or encoding
Definition: opt.h:285
int width
width and height of the video frame
Definition: frame.h:220
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
av_default_item_name
#define AVERROR(e)
Definition: error.h:43
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:175
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:199
simple assert() macros that are a bit more flexible than ISO C assert().
const char * name
Name of the codec implementation.
Definition: avcodec.h:3479
Libavcodec external API header.
static const AVOption options[]
Definition: libkvazaar.c:214
int bit_rate
the average bitrate
Definition: avcodec.h:1567
float y
int width
picture width / height.
Definition: avcodec.h:1681
int ticks_per_frame
For some codecs, the time base is closer to the field rate than the frame rate.
Definition: avcodec.h:1640
static const AVCodecDefault defaults[]
Definition: libkvazaar.c:228
int thread_count
thread count is used to decide how many independent tasks should be passed to execute() ...
Definition: avcodec.h:3033
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:232
int av_dict_parse_string(AVDictionary **pm, const char *str, const char *key_val_sep, const char *pairs_sep, int flags)
Parse the key/value pairs list and add the parsed entries to a dictionary.
Definition: dict.c:176
AVS_Value src
Definition: avisynth_c.h:482
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:199
#define AV_OPT_FLAG_VIDEO_PARAM
Definition: opt.h:291
main external API structure.
Definition: avcodec.h:1502
BYTE int const BYTE int int int height
Definition: avisynth_c.h:676
Describe the class of an AVClass context structure.
Definition: log.h:67
static int libkvazaar_encode(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr)
Definition: libkvazaar.c:133
static av_cold int libkvazaar_init(AVCodecContext *avctx)
Definition: libkvazaar.c:42
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:209
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:182
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:63
common internal api header.
char * key
Definition: dict.h:87
int den
denominator
Definition: rational.h:45
void * priv_data
Definition: avcodec.h:1544
char * value
Definition: dict.h:88
attribute_deprecated int ff_alloc_packet(AVPacket *avpkt, int size)
Definition: utils.c:1838
int height
Definition: frame.h:220
#define AV_DICT_IGNORE_SUFFIX
Return first entry in a dictionary whose first part corresponds to the search key, ignoring the suffix of the found key string.
Definition: dict.h:72
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:57
AVPixelFormat
Pixel format.
Definition: pixfmt.h:61
This structure stores compressed data.
Definition: avcodec.h:1400
static int width