FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
libopenh264enc.c
Go to the documentation of this file.
1 /*
2  * OpenH264 video encoder
3  * Copyright (C) 2014 Martin Storsjo
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 <wels/codec_api.h>
23 #include <wels/codec_ver.h>
24 
25 #include "libavutil/attributes.h"
26 #include "libavutil/common.h"
27 #include "libavutil/opt.h"
28 #include "libavutil/internal.h"
29 #include "libavutil/intreadwrite.h"
30 #include "libavutil/mathematics.h"
31 
32 #include "avcodec.h"
33 #include "internal.h"
34 
35 typedef struct SVCContext {
36  const AVClass *av_class;
37  ISVCEncoder *encoder;
40  char *profile;
43  int skipped;
44  int cabac;
45 } SVCContext;
46 
47 #define OPENH264_VER_AT_LEAST(maj, min) \
48  ((OPENH264_MAJOR > (maj)) || \
49  (OPENH264_MAJOR == (maj) && OPENH264_MINOR >= (min)))
50 
51 #define OFFSET(x) offsetof(SVCContext, x)
52 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
53 static const AVOption options[] = {
54  { "slice_mode", "set slice mode", OFFSET(slice_mode), AV_OPT_TYPE_INT, { .i64 = SM_AUTO_SLICE }, SM_SINGLE_SLICE, SM_RESERVED, VE, "slice_mode" },
55  { "fixed", "a fixed number of slices", 0, AV_OPT_TYPE_CONST, { .i64 = SM_FIXEDSLCNUM_SLICE }, 0, 0, VE, "slice_mode" },
56  { "rowmb", "one slice per row of macroblocks", 0, AV_OPT_TYPE_CONST, { .i64 = SM_ROWMB_SLICE }, 0, 0, VE, "slice_mode" },
57  { "auto", "automatic number of slices according to number of threads", 0, AV_OPT_TYPE_CONST, { .i64 = SM_AUTO_SLICE }, 0, 0, VE, "slice_mode" },
58  { "dyn", "Dynamic slicing", 0, AV_OPT_TYPE_CONST, { .i64 = SM_DYN_SLICE }, 0, 0, VE, "slice_mode" },
59  { "loopfilter", "enable loop filter", OFFSET(loopfilter), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE },
60  { "profile", "set profile restrictions", OFFSET(profile), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VE },
61  { "max_nal_size", "set maximum NAL size in bytes", OFFSET(max_nal_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
62  { "allow_skip_frames", "allow skipping frames to hit the target bitrate", OFFSET(skip_frames), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
63  { "cabac", "Enable cabac", OFFSET(cabac), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE },
64  { NULL }
65 };
66 
67 static const AVClass class = {
69 };
70 
71 // Convert libopenh264 log level to equivalent ffmpeg log level.
72 static int libopenh264_to_ffmpeg_log_level(int libopenh264_log_level)
73 {
74  if (libopenh264_log_level >= WELS_LOG_DETAIL) return AV_LOG_TRACE;
75  else if (libopenh264_log_level >= WELS_LOG_DEBUG) return AV_LOG_DEBUG;
76  else if (libopenh264_log_level >= WELS_LOG_INFO) return AV_LOG_VERBOSE;
77  else if (libopenh264_log_level >= WELS_LOG_WARNING) return AV_LOG_WARNING;
78  else if (libopenh264_log_level >= WELS_LOG_ERROR) return AV_LOG_ERROR;
79  else return AV_LOG_QUIET;
80 }
81 
82 // This function will be provided to the libopenh264 library. The function will be called
83 // when libopenh264 wants to log a message (error, warning, info, etc.). The signature for
84 // this function (defined in .../codec/api/svc/codec_api.h) is:
85 //
86 // typedef void (*WelsTraceCallback) (void* ctx, int level, const char* string);
87 
88 static void libopenh264_trace_callback(void *ctx, int level, char const *msg)
89 {
90  // The message will be logged only if the requested EQUIVALENT ffmpeg log level is
91  // less than or equal to the current ffmpeg log level.
92  int equiv_ffmpeg_log_level = libopenh264_to_ffmpeg_log_level(level);
93  av_log(ctx, equiv_ffmpeg_log_level, "%s\n", msg);
94 }
95 
97 {
98  SVCContext *s = avctx->priv_data;
99 
100  if (s->encoder)
101  WelsDestroySVCEncoder(s->encoder);
102  if (s->skipped > 0)
103  av_log(avctx, AV_LOG_WARNING, "%d frames skipped\n", s->skipped);
104  return 0;
105 }
106 
108 {
109  SVCContext *s = avctx->priv_data;
110  SEncParamExt param = { 0 };
111  int err = AVERROR_UNKNOWN;
112  int log_level;
113  WelsTraceCallback callback_function;
114  AVCPBProperties *props;
115 
116  // Mingw GCC < 4.7 on x86_32 uses an incorrect/buggy ABI for the WelsGetCodecVersion
117  // function (for functions returning larger structs), thus skip the check in those
118  // configurations.
119 #if !defined(_WIN32) || !defined(__GNUC__) || !ARCH_X86_32 || AV_GCC_VERSION_AT_LEAST(4, 7)
120  OpenH264Version libver = WelsGetCodecVersion();
121  if (memcmp(&libver, &g_stCodecVersion, sizeof(libver))) {
122  av_log(avctx, AV_LOG_ERROR, "Incorrect library version loaded\n");
123  return AVERROR(EINVAL);
124  }
125 #endif
126 
127  if (WelsCreateSVCEncoder(&s->encoder)) {
128  av_log(avctx, AV_LOG_ERROR, "Unable to create encoder\n");
129  return AVERROR_UNKNOWN;
130  }
131 
132  // Pass all libopenh264 messages to our callback, to allow ourselves to filter them.
133  log_level = WELS_LOG_DETAIL;
134  (*s->encoder)->SetOption(s->encoder, ENCODER_OPTION_TRACE_LEVEL, &log_level);
135 
136  // Set the logging callback function to one that uses av_log() (see implementation above).
137  callback_function = (WelsTraceCallback) libopenh264_trace_callback;
138  (*s->encoder)->SetOption(s->encoder, ENCODER_OPTION_TRACE_CALLBACK, (void *)&callback_function);
139 
140  // Set the AVCodecContext as the libopenh264 callback context so that it can be passed to av_log().
141  (*s->encoder)->SetOption(s->encoder, ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, (void *)&avctx);
142 
143  (*s->encoder)->GetDefaultParams(s->encoder, &param);
144 
145 #if FF_API_CODER_TYPE
147  if (!s->cabac)
148  s->cabac = avctx->coder_type == FF_CODER_TYPE_AC;
150 #endif
151 
152  param.fMaxFrameRate = 1/av_q2d(avctx->time_base);
153  param.iPicWidth = avctx->width;
154  param.iPicHeight = avctx->height;
155  param.iTargetBitrate = avctx->bit_rate;
156  param.iMaxBitrate = FFMAX(avctx->rc_max_rate, avctx->bit_rate);
157  param.iRCMode = RC_QUALITY_MODE;
158  param.iTemporalLayerNum = 1;
159  param.iSpatialLayerNum = 1;
160  param.bEnableDenoise = 0;
161  param.bEnableBackgroundDetection = 1;
162  param.bEnableAdaptiveQuant = 1;
163  param.bEnableFrameSkip = s->skip_frames;
164  param.bEnableLongTermReference = 0;
165  param.iLtrMarkPeriod = 30;
166  param.uiIntraPeriod = avctx->gop_size;
167 #if OPENH264_VER_AT_LEAST(1, 4)
168  param.eSpsPpsIdStrategy = CONSTANT_ID;
169 #else
170  param.bEnableSpsPpsIdAddition = 0;
171 #endif
172  param.bPrefixNalAddingCtrl = 0;
173  param.iLoopFilterDisableIdc = !s->loopfilter;
174  param.iEntropyCodingModeFlag = 0;
175  param.iMultipleThreadIdc = avctx->thread_count;
176  if (s->profile && !strcmp(s->profile, "main"))
177  param.iEntropyCodingModeFlag = 1;
178  else if (!s->profile && s->cabac)
179  param.iEntropyCodingModeFlag = 1;
180 
181  param.sSpatialLayers[0].iVideoWidth = param.iPicWidth;
182  param.sSpatialLayers[0].iVideoHeight = param.iPicHeight;
183  param.sSpatialLayers[0].fFrameRate = param.fMaxFrameRate;
184  param.sSpatialLayers[0].iSpatialBitrate = param.iTargetBitrate;
185  param.sSpatialLayers[0].iMaxSpatialBitrate = param.iMaxBitrate;
186 
187  if ((avctx->slices > 1) && (s->max_nal_size)){
188  av_log(avctx,AV_LOG_ERROR,"Invalid combination -slices %d and -max_nal_size %d.\n",avctx->slices,s->max_nal_size);
189  goto fail;
190  }
191 
192  if (avctx->slices > 1)
193  s->slice_mode = SM_FIXEDSLCNUM_SLICE;
194 
195  if (s->max_nal_size)
196  s->slice_mode = SM_DYN_SLICE;
197 
198  param.sSpatialLayers[0].sSliceCfg.uiSliceMode = s->slice_mode;
199  param.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceNum = avctx->slices;
200 
201  if (s->slice_mode == SM_DYN_SLICE) {
202  if (s->max_nal_size){
203  param.uiMaxNalSize = s->max_nal_size;
204  param.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = s->max_nal_size;
205  } else {
206  av_log(avctx, AV_LOG_ERROR, "Invalid -max_nal_size, "
207  "specify a valid max_nal_size to use -slice_mode dyn\n");
208  goto fail;
209  }
210  }
211 
212  if ((*s->encoder)->InitializeExt(s->encoder, &param) != cmResultSuccess) {
213  av_log(avctx, AV_LOG_ERROR, "Initialize failed\n");
214  goto fail;
215  }
216 
217  if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
218  SFrameBSInfo fbi = { 0 };
219  int i, size = 0;
220  (*s->encoder)->EncodeParameterSets(s->encoder, &fbi);
221  for (i = 0; i < fbi.sLayerInfo[0].iNalCount; i++)
222  size += fbi.sLayerInfo[0].pNalLengthInByte[i];
224  if (!avctx->extradata) {
225  err = AVERROR(ENOMEM);
226  goto fail;
227  }
228  avctx->extradata_size = size;
229  memcpy(avctx->extradata, fbi.sLayerInfo[0].pBsBuf, size);
230  }
231 
232  props = ff_add_cpb_side_data(avctx);
233  if (!props) {
234  err = AVERROR(ENOMEM);
235  goto fail;
236  }
237  props->max_bitrate = param.iMaxBitrate;
238  props->avg_bitrate = param.iTargetBitrate;
239 
240  return 0;
241 
242 fail:
243  svc_encode_close(avctx);
244  return err;
245 }
246 
247 static int svc_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
248  const AVFrame *frame, int *got_packet)
249 {
250  SVCContext *s = avctx->priv_data;
251  SFrameBSInfo fbi = { 0 };
252  int i, ret;
253  int encoded;
254  SSourcePicture sp = { 0 };
255  int size = 0, layer, first_layer = 0;
256  int layer_size[MAX_LAYER_NUM_OF_FRAME] = { 0 };
257 
258  sp.iColorFormat = videoFormatI420;
259  for (i = 0; i < 3; i++) {
260  sp.iStride[i] = frame->linesize[i];
261  sp.pData[i] = frame->data[i];
262  }
263  sp.iPicWidth = avctx->width;
264  sp.iPicHeight = avctx->height;
265 
266  encoded = (*s->encoder)->EncodeFrame(s->encoder, &sp, &fbi);
267  if (encoded != cmResultSuccess) {
268  av_log(avctx, AV_LOG_ERROR, "EncodeFrame failed\n");
269  return AVERROR_UNKNOWN;
270  }
271  if (fbi.eFrameType == videoFrameTypeSkip) {
272  s->skipped++;
273  av_log(avctx, AV_LOG_DEBUG, "frame skipped\n");
274  return 0;
275  }
276  first_layer = 0;
277  // Normal frames are returned with one single layer, while IDR
278  // frames have two layers, where the first layer contains the SPS/PPS.
279  // If using global headers, don't include the SPS/PPS in the returned
280  // packet - thus, only return one layer.
281  if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)
282  first_layer = fbi.iLayerNum - 1;
283 
284  for (layer = first_layer; layer < fbi.iLayerNum; layer++) {
285  for (i = 0; i < fbi.sLayerInfo[layer].iNalCount; i++)
286  layer_size[layer] += fbi.sLayerInfo[layer].pNalLengthInByte[i];
287  size += layer_size[layer];
288  }
289  av_log(avctx, AV_LOG_DEBUG, "%d slices\n", fbi.sLayerInfo[fbi.iLayerNum - 1].iNalCount);
290 
291  if ((ret = ff_alloc_packet2(avctx, avpkt, size, size))) {
292  av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
293  return ret;
294  }
295  size = 0;
296  for (layer = first_layer; layer < fbi.iLayerNum; layer++) {
297  memcpy(avpkt->data + size, fbi.sLayerInfo[layer].pBsBuf, layer_size[layer]);
298  size += layer_size[layer];
299  }
300  avpkt->pts = frame->pts;
301  if (fbi.eFrameType == videoFrameTypeIDR)
302  avpkt->flags |= AV_PKT_FLAG_KEY;
303  *got_packet = 1;
304  return 0;
305 }
306 
308  .name = "libopenh264",
309  .long_name = NULL_IF_CONFIG_SMALL("OpenH264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),
310  .type = AVMEDIA_TYPE_VIDEO,
311  .id = AV_CODEC_ID_H264,
312  .priv_data_size = sizeof(SVCContext),
314  .encode2 = svc_encode_frame,
315  .close = svc_encode_close,
316  .capabilities = AV_CODEC_CAP_AUTO_THREADS,
317  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P,
318  AV_PIX_FMT_NONE },
319  .priv_class = &class,
320 };
#define NULL
Definition: coverity.c:32
const char * s
Definition: avisynth_c.h:631
This structure describes decoded (raw) audio or video data.
Definition: frame.h:181
AVOption.
Definition: opt.h:245
AVFormatContext * ctx
Definition: movenc-test.c:48
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
int64_t bit_rate
the average bitrate
Definition: avcodec.h:1597
#define LIBAVUTIL_VERSION_INT
Definition: version.h:70
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int max_bitrate
Maximum bitrate of the stream, in bits per second.
Definition: avcodec.h:1203
#define AV_CODEC_CAP_AUTO_THREADS
Codec supports avctx->thread_count == 0 (auto).
Definition: avcodec.h:931
AVCodec.
Definition: avcodec.h:3392
Macro definitions for various function/variable attributes.
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avcodec.h:1661
#define AV_LOG_QUIET
Print no output.
Definition: log.h:158
#define av_cold
Definition: attributes.h:82
AVOptions.
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:202
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:262
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:1647
static AVFrame * frame
static double av_q2d(AVRational a)
Convert rational to double.
Definition: rational.h:80
uint8_t * data
Definition: avcodec.h:1467
#define OFFSET(x)
#define sp
Definition: regdef.h:63
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
ptrdiff_t size
Definition: opengl_enc.c:101
ISVCEncoder * encoder
#define av_log(a,...)
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1499
static void libopenh264_trace_callback(void *ctx, int level, char const *msg)
static const AVOption options[]
#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:176
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
const AVClass * av_class
int flags
AV_CODEC_FLAG_*.
Definition: avcodec.h:1627
const char * name
Name of the codec implementation.
Definition: avcodec.h:3399
static av_cold int svc_encode_close(AVCodecContext *avctx)
#define FFMAX(a, b)
Definition: common.h:94
#define fail()
Definition: checkasm.h:80
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1473
static av_cold int svc_encode_init(AVCodecContext *avctx)
common internal API header
#define VE
int width
picture width / height.
Definition: avcodec.h:1711
static int libopenh264_to_ffmpeg_log_level(int libopenh264_log_level)
attribute_deprecated int coder_type
Definition: avcodec.h:2576
int thread_count
thread count is used to decide how many independent tasks should be passed to execute() ...
Definition: avcodec.h:2954
This structure describes the bitrate properties of an encoded bitstream.
Definition: avcodec.h:1198
Libavcodec external API header.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:209
main external API structure.
Definition: avcodec.h:1532
#define FF_CODER_TYPE_AC
Definition: avcodec.h:2566
char * profile
int extradata_size
Definition: avcodec.h:1648
Describe the class of an AVClass context structure.
Definition: log.h:67
static int svc_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet)
int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int64_t min_size)
Check AVPacket size and/or allocate data.
Definition: utils.c:1621
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:262
mfxU16 profile
Definition: qsvenc.c:42
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:192
uint8_t level
Definition: svq3.c:150
#define AV_CODEC_FLAG_GLOBAL_HEADER
Place global headers in extradata instead of every keyframe.
Definition: avcodec.h:783
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
Definition: avcodec.h:1737
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:63
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:80
common internal api header.
common internal and external API header
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
AVCPBProperties * ff_add_cpb_side_data(AVCodecContext *avctx)
Add a CPB properties side data to an encoding context.
Definition: utils.c:3533
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
Definition: avcodec.h:635
int slices
Number of slices.
Definition: avcodec.h:2278
void * priv_data
Definition: avcodec.h:1574
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition: internal.h:81
int avg_bitrate
Average bitrate of the stream, in bits per second.
Definition: avcodec.h:1213
AVCodec ff_libopenh264_encoder
AVPixelFormat
Pixel format.
Definition: pixfmt.h:61
This structure stores compressed data.
Definition: avcodec.h:1444
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:252
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1460
int64_t rc_max_rate
maximum bitrate
Definition: avcodec.h:2523