in h264_encoder_core/src/h264_encoder.cpp [130:243]
AwsError Initialize(const int src_width, const int src_height, const AVPixelFormat src_encoding,
const std::string & codec_name, const int dst_width, const int dst_height,
const int fps_num, const int fps_den, const int64_t bitrate)
{
if (src_width <= 0) {
AWS_LOGSTREAM_ERROR(__func__, "Invalid video source width " << src_width << "!");
return AWS_ERR_PARAM;
}
if (src_height <= 0) {
AWS_LOGSTREAM_ERROR(__func__, "Invalid video source height " << src_height << "!");
return AWS_ERR_PARAM;
}
if (dst_width <= 0) {
AWS_LOGSTREAM_ERROR(__func__, "Invalid output video width " << dst_width << "!");
return AWS_ERR_PARAM;
}
if (dst_height <= 0) {
AWS_LOGSTREAM_ERROR(__func__, "Invalid video source height " << dst_height << "!");
return AWS_ERR_PARAM;
}
if (fps_num <= 0) {
AWS_LOGSTREAM_ERROR(__func__, "Invalid FPS numerator " << fps_num << "!");
return AWS_ERR_PARAM;
}
if (fps_den <= 0) {
AWS_LOGSTREAM_ERROR(__func__, "Invalid FPS denominator " << fps_den << "!");
return AWS_ERR_PARAM;
}
if (bitrate <= 0) {
AWS_LOGSTREAM_ERROR(__func__, "Invalid bit rate " << bitrate << "!");
return AWS_ERR_PARAM;
}
src_width_ = src_width;
src_height_ = src_height;
src_encoding_ = src_encoding;
if (src_encoding_ == AV_PIX_FMT_RGB24) {
src_stride_ = 3 * src_width_; // 3 color channels (red, green, blue)
} else if (src_encoding_ == AV_PIX_FMT_BGR24) {
src_stride_ = 3 * src_width_; // 3 color channels (blue, green, red)
} else if (src_encoding_ == AV_PIX_FMT_RGBA) {
src_stride_ = 4 * src_width_; // 4 color channels (red, green, blue, alpha)
} else if (src_encoding_ == AV_PIX_FMT_BGRA) {
src_stride_ = 4 * src_width_; // 4 color channels (blue, green, red, alpha)
} else {
AWS_LOG_ERROR(__func__, "Trying to work with unsupported encoding!");
return AWS_ERR_PARAM;
}
dst_width_ = dst_width;
dst_height_ = dst_height;
fps_num_ = fps_num;
fps_den_ = fps_den;
bitrate_ = bitrate;
avcodec_register_all();
/* find the mpeg1 video encoder */
AVCodec * codec = nullptr;
AVDictionary * opts = nullptr;
if (codec_name.empty()) {
codec = avcodec_find_encoder_by_name(kDefaultHardwareCodec);
if (AWS_ERR_OK != open_codec(codec, opts)) {
codec = avcodec_find_encoder_by_name(kDefaultSoftwareCodec);
av_dict_set(&opts, "preset", "veryfast", 0);
av_dict_set(&opts, "tune", "zerolatency", 0);
if (AWS_ERR_OK != open_codec(codec, opts)) {
AWS_LOGSTREAM_ERROR(__func__, kDefaultHardwareCodec << " and " << kDefaultSoftwareCodec
<< " codecs were not available!");
return AWS_ERR_NOT_FOUND;
}
}
} else {
codec = avcodec_find_encoder_by_name(codec_name.c_str());
if (AWS_ERR_OK != open_codec(codec, opts)) {
AWS_LOGSTREAM_ERROR(__func__, codec_name << " codec not found!");
return AWS_ERR_NOT_FOUND;
}
}
AWS_LOGSTREAM_INFO(__func__, "Encoding using " << codec->name << " codec");
dst_width_ = param_->width;
dst_height_ = param_->height;
pic_in_ = av_frame_alloc();
if (nullptr == pic_in_) {
AWS_LOG_ERROR(__func__, "Could not allocate video frame");
return AWS_ERR_MEMORY;
}
pic_in_->format = param_->pix_fmt;
pic_in_->width = param_->width;
pic_in_->height = param_->height;
pic_in_->pts = 0;
/* the image can be allocated by any means and av_image_alloc() is
* just the most convenient way if av_malloc() is to be used */
int ret = av_image_alloc(pic_in_->data, pic_in_->linesize, param_->width, param_->height,
param_->pix_fmt, 32);
if (ret < 0) {
AWS_LOGSTREAM_ERROR(__func__,
"Could not allocate raw picture buffer"
" (av_image_alloc() returned: "
<< ret << ")");
return AWS_ERR_MEMORY;
}
convert_ctx_ = sws_getContext(src_width_, src_height_, src_encoding_, dst_width_, dst_height_,
AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
return AWS_ERR_OK;
}