2
* Copyright (C) 2013 Savoir-Faire Linux Inc.
3
* Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com>
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 3 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20
* Additional permission under GNU GPL version 3 section 7:
22
* If you modify this program, or any covered work, by linking or
23
* combining it with the OpenSSL project's OpenSSL library (or a
24
* modified version of that library), containing parts covered by the
25
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
26
* grants you additional permission to convey the resulting work.
27
* Corresponding Source for a non-source form of such a combination
28
* shall include the source code for the parts of OpenSSL used as well
29
* as that of the covered work.
32
#include "libav_deps.h"
33
#include "video_encoder.h"
44
VideoEncoder::VideoEncoder() :
47
, outputCtx_(avformat_alloc_context())
51
, scaledFrameBuffer_(0)
52
, scaledFrameBufferSize_(0)
56
#if (LIBAVCODEC_VERSION_MAJOR < 54)
58
, encoderBufferSize_(0)
62
VideoEncoder::~VideoEncoder()
64
if (outputCtx_ and outputCtx_->priv_data)
65
av_write_trailer(outputCtx_);
68
avcodec_close(encoderCtx_);
70
av_free(scaledFrameBuffer_);
72
#if (LIBAVCODEC_VERSION_MAJOR < 54)
73
av_free(encoderBuffer_);
77
int VideoEncoder::openOutput(const char *enc_name, const char *short_name,
78
const char *filename, const char *mime_type)
80
AVOutputFormat *oformat = av_guess_format(short_name, filename,
84
ERROR("Unable to find a suitable output format for %s", filename);
88
outputCtx_->oformat = oformat;
89
strncpy(outputCtx_->filename, filename, sizeof(outputCtx_->filename));
90
// guarantee that buffer is NULL terminated
91
outputCtx_->filename[sizeof(outputCtx_->filename) - 1] = '\0';
93
/* find the video encoder */
94
outputEncoder_ = avcodec_find_encoder_by_name(enc_name);
95
if (!outputEncoder_) {
96
ERROR("Encoder \"%s\" not found!", enc_name);
100
prepareEncoderContext();
102
/* let x264 preset override our encoder settings */
103
if (!strcmp(enc_name, "libx264")) {
104
AVDictionaryEntry *entry = av_dict_get(options_, "parameters",
106
// FIXME: this should be parsed from the fmtp:profile-level-id
107
// attribute of our peer, it will determine what profile and
108
// level we are sending (i.e. that they can accept).
109
extractProfileLevelID(entry?entry->value:"", encoderCtx_);
111
} else if (!strcmp(enc_name, "libvpx")) {
112
av_opt_set(encoderCtx_->priv_data, "quality", "realtime", 0);
116
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53, 6, 0)
117
ret = avcodec_open(encoderCtx_, outputEncoder_);
119
ret = avcodec_open2(encoderCtx_, outputEncoder_, NULL);
122
ERROR("Could not open encoder");
126
// add video stream to outputformat context
127
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 8, 0)
128
stream_ = av_new_stream(outputCtx_, 0);
130
stream_ = avformat_new_stream(outputCtx_, 0);
133
ERROR("Could not allocate stream");
136
stream_->codec = encoderCtx_;
138
// allocate buffers for both scaled (pre-encoder) and encoded frames
139
scaledFrame_.setGeometry(encoderCtx_->width, encoderCtx_->height,
140
libav_utils::sfl_pixel_format((int)encoderCtx_->pix_fmt));
141
scaledFrameBufferSize_ = scaledFrame_.getSize();
143
if (scaledFrameBufferSize_ <= FF_MIN_BUFFER_SIZE) {
144
ERROR(" buffer too small");
148
#if (LIBAVCODEC_VERSION_MAJOR < 54)
149
encoderBufferSize_ = scaledFrameBufferSize_; // seems to be ok
150
encoderBuffer_ = (uint8_t*) av_malloc(encoderBufferSize_);
151
if (!encoderBuffer_) {
152
ERROR("encoderBuffer = av_malloc() failed");
157
scaledFrameBuffer_ = (uint8_t*) av_malloc(scaledFrameBufferSize_);
158
if (!scaledFrameBuffer_) {
159
ERROR("scaledFrameBuffer = av_malloc() failed");
163
scaledFrame_.setDestination(scaledFrameBuffer_);
168
void VideoEncoder::setInterruptCallback(int (*cb)(void*), void *opaque)
171
outputCtx_->interrupt_callback.callback = cb;
172
outputCtx_->interrupt_callback.opaque = opaque;
174
outputCtx_->interrupt_callback.callback = 0;
178
void VideoEncoder::setIOContext(const std::unique_ptr<VideoIOHandle> &ioctx)
180
outputCtx_->pb = ioctx->getContext();
181
outputCtx_->packet_size = outputCtx_->pb->buffer_size;
184
int VideoEncoder::startIO()
186
int ret = avformat_write_header(outputCtx_,
187
options_ ? &options_ : NULL);
189
ERROR("Could not write header for output file..."
190
"check codec parameters");
194
av_dump_format(outputCtx_, 0, outputCtx_->filename, 1);
199
int VideoEncoder::encode(VideoFrame &input, bool is_keyframe, int frame_number)
202
AVFrame *frame = scaledFrame_.get();
204
scaler_.scale(input, scaledFrame_);
205
frame->pts = frame_number;
208
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(53, 20, 0)
209
frame->pict_type = AV_PICTURE_TYPE_I;
211
frame->pict_type = FF_I_TYPE;
214
/* FIXME: Should be AV_PICTURE_TYPE_NONE for newer libavutil */
215
frame->pict_type = (AVPictureType) 0;
219
av_init_packet(&pkt);
221
#if (LIBAVCODEC_VERSION_MAJOR >= 54)
223
ret = avcodec_encode_video2(encoderCtx_, &pkt, frame, &got_packet);
225
ERROR("avcodec_encode_video2 failed");
226
av_free_packet(&pkt);
230
if (pkt.size and got_packet) {
231
if (pkt.pts != AV_NOPTS_VALUE)
232
pkt.pts = av_rescale_q(pkt.pts, encoderCtx_->time_base, stream_->time_base);
233
if (pkt.dts != AV_NOPTS_VALUE)
234
pkt.dts = av_rescale_q(pkt.dts, encoderCtx_->time_base, stream_->time_base);
236
pkt.stream_index = stream_->index;
238
// write the compressed frame
239
ret = av_interleaved_write_frame(outputCtx_, &pkt);
241
ERROR("interleaved_write_frame failed");
245
ret = avcodec_encode_video(encoderCtx_, encoderBuffer_,
246
encoderBufferSize_, frame);
248
ERROR("avcodec_encode_video failed");
249
av_free_packet(&pkt);
253
pkt.data = encoderBuffer_;
256
// rescale pts from encoded video framerate to rtp clock rate
257
if (encoderCtx_->coded_frame->pts != static_cast<int64_t>(AV_NOPTS_VALUE)) {
258
pkt.pts = av_rescale_q(encoderCtx_->coded_frame->pts,
259
encoderCtx_->time_base, stream_->time_base);
264
// is it a key frame?
265
if (encoderCtx_->coded_frame->key_frame)
266
pkt.flags |= AV_PKT_FLAG_KEY;
267
pkt.stream_index = stream_->index;
269
// write the compressed frame
270
if ((ret = av_interleaved_write_frame(outputCtx_, &pkt)) < 0)
271
ERROR("interleaved_write_frame failed");
274
av_free_packet(&pkt);
279
int VideoEncoder::flush()
282
av_init_packet(&pkt);
285
#if (LIBAVCODEC_VERSION_MAJOR >= 54)
289
ret = avcodec_encode_video2(encoderCtx_, &pkt, NULL, &got_packet);
291
ERROR("avcodec_encode_video failed");
292
av_free_packet(&pkt);
296
if (pkt.size and got_packet) {
297
// write the compressed frame
298
ret = av_interleaved_write_frame(outputCtx_, &pkt);
300
ERROR("interleaved_write_frame failed");
303
ret = avcodec_encode_video(encoderCtx_, encoderBuffer_,
304
encoderBufferSize_, NULL);
306
ERROR("avcodec_encode_video failed");
307
av_free_packet(&pkt);
311
pkt.data = encoderBuffer_;
314
// write the compressed frame
315
ret = av_interleaved_write_frame(outputCtx_, &pkt);
317
ERROR("interleaved_write_frame failed");
319
av_free_packet(&pkt);
324
void VideoEncoder::print_sdp(std::string &sdp_)
326
/* theora sdp can be huge */
327
const size_t sdp_size = outputCtx_->streams[0]->codec->extradata_size \
329
std::string sdp(sdp_size, 0);
330
av_sdp_create(&outputCtx_, 1, &(*sdp.begin()), sdp_size);
331
std::istringstream iss(sdp);
334
while (std::getline(iss, line)) {
335
/* strip windows line ending */
336
line = line.substr(0, line.length() - 1);
339
DEBUG("Sending SDP: \n%s", sdp_.c_str());
342
void VideoEncoder::prepareEncoderContext()
344
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53, 12, 0)
345
encoderCtx_ = avcodec_alloc_context();
346
avcodec_get_context_defaults(encoderCtx_);
347
(void) outputEncoder_;
349
encoderCtx_ = avcodec_alloc_context3(outputEncoder_);
352
// set some encoder settings here
353
encoderCtx_->bit_rate = 1000 * atoi(av_dict_get(options_, "bitrate",
355
DEBUG("Using bitrate %d", encoderCtx_->bit_rate);
357
// resolution must be a multiple of two
358
char *width = av_dict_get(options_, "width", NULL, 0)->value;
359
dstWidth_ = encoderCtx_->width = width ? atoi(width) : 0;
360
char *height = av_dict_get(options_, "height", NULL, 0)->value;
361
dstHeight_ = encoderCtx_->height = height ? atoi(height) : 0;
363
const char *framerate = av_dict_get(options_, "framerate",
365
const int DEFAULT_FPS = 30;
366
const int fps = framerate ? atoi(framerate) : DEFAULT_FPS;
367
encoderCtx_->time_base = (AVRational) {1, fps};
368
// emit one intra frame every gop_size frames
369
encoderCtx_->max_b_frames = 0;
370
encoderCtx_->pix_fmt = PIXEL_FORMAT(YUV420P); // TODO: option me !
372
// Fri Jul 22 11:37:59 EDT 2011:tmatth:XXX: DON'T set this, we want our
373
// pps and sps to be sent in-band for RTP
374
// This is to place global headers in extradata instead of every
376
// encoderCtx_->flags |= CODEC_FLAG_GLOBAL_HEADER;
379
void VideoEncoder::forcePresetX264()
381
const char *speedPreset = "ultrafast";
382
if (av_opt_set(encoderCtx_->priv_data, "preset", speedPreset, 0))
383
WARN("Failed to set x264 preset '%s'", speedPreset);
384
const char *tune = "zerolatency";
385
if (av_opt_set(encoderCtx_->priv_data, "tune", tune, 0))
386
WARN("Failed to set x264 tune '%s'", tune);
389
void VideoEncoder::extractProfileLevelID(const std::string ¶meters,
393
// If no profile-level-id is present, the Baseline Profile without
394
// additional constraints at Level 1 MUST be implied.
395
ctx->profile = FF_PROFILE_H264_BASELINE;
397
// ctx->level = 0x0d; // => 13 aka 1.3
398
if (parameters.empty())
401
const std::string target("profile-level-id=");
402
size_t needle = parameters.find(target);
403
if (needle == std::string::npos)
406
needle += target.length();
407
const size_t id_length = 6; /* digits */
408
const std::string profileLevelID(parameters.substr(needle, id_length));
409
if (profileLevelID.length() != id_length)
413
std::stringstream ss;
414
ss << profileLevelID;
415
ss >> std::hex >> result;
416
// profile-level id consists of three bytes
417
const unsigned char profile_idc = result >> 16; // 42xxxx -> 42
418
const unsigned char profile_iop = ((result >> 8) & 0xff); // xx80xx -> 80
419
ctx->level = result & 0xff; // xxxx0d -> 0d
420
switch (profile_idc) {
421
case FF_PROFILE_H264_BASELINE:
422
// check constraint_set_1_flag
423
if ((profile_iop & 0x40) >> 6)
424
ctx->profile |= FF_PROFILE_H264_CONSTRAINED;
426
case FF_PROFILE_H264_HIGH_10:
427
case FF_PROFILE_H264_HIGH_422:
428
case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
429
// check constraint_set_3_flag
430
if ((profile_iop & 0x10) >> 4)
431
ctx->profile |= FF_PROFILE_H264_INTRA;
434
DEBUG("Using profile %x and level %d", ctx->profile, ctx->level);